Wakame

2014年12月06日

このエントリーをはてなブックマークに追加

Wakame-vdc / OpenVNet Advent Calendar 2014 12/06担当 (1回目)

enter image description here

開発の話は、開発担当者にお任せし、自分はCI環境周りのお話。
書けるネタは多々ある事が悩ましい。今回は、このネタを。

開発環境におけるアカウント管理に悩まされて・・・

背景

アカウント管理が煩雑になっていた。

  • 各自が思い思いのタイミングで作成
  • SSHの認証方式が、パスワード認証だったり、公開鍵認証だったり
  • 各サーバによって、個人のユーザー名が異なる場合も

課題整理してみると・・

  • UNIXユーザー名
    • 作成時に悩みたくない
    • 開発機においては統一したい
  • SSHの認証方式
    • パスワード認証は不可
    • 公開鍵認証のみ

全員がGitHubにアカウントを持ってるので、GitHubベースで揃えられないものか・・・?

github


アカウント管理整理へ
  • 開発機のユーザー名?
    • 全員がGitHubにアカウントを持っている
    • GitHubにおけるユーザー名を使う
  • 公開鍵管理?
    • GitHubにはSSH公開鍵用APIの口があり、ユーザーの毎公開鍵を取得可能
    • 各自から公開鍵を貰う必要が無い
    • 公開鍵入れ替えは、ローカルの公開鍵ファイルを上書き
  • sudoers権限?
    • パスワード設定しないので、NOPASSWDを付与

必要なのは、GitHubのユーザー名だけである事が分かった。
手順整理も出来たので、あとはスクリプト化するだけ。

アカウント管理スクリプト作成

期待するスクリプトは、ユーザー名が唯一の引数。

$ sudo ./add-github-user.sh <github user>

仮に hansode を追加する場合は、

$ sudo ./add-github-user.sh hansode

そして作ったのが、下記プロジェクト。

インストール
$ curl -fsSkL https://raw.githubusercontent.com/hansode/add-github-user.sh/master/add-github-user.sh -o add-github-user.sh
$ chmod +x add-github-user.sh
実行例
$ sudo ./add-github-user.sh hansode
+ [[ -z hansode ]]
++ tr A-Z a-z
+ declare devel_user=hansode
+ declare devel_group=hansode
+ declare devel_home=/home/hansode
+ getent group hansode
+ groupadd hansode
+ getent passwd hansode
+ useradd -g hansode -d /home/hansode -s /bin/bash -m hansode
+ [[ -f /etc/sudoers ]]
+ egrep '^hansode' /etc/sudoers -q
+ echo 'hansode ALL=(ALL) NOPASSWD: ALL'
+ su - hansode -c '/bin/bash -ex'
+ egrep -w '^umask 022' -q /home/hansode/.bashrc
+ echo 'umask 022'
+ su - hansode -c '/bin/bash -ex'
+ mkdir -p -m 700 /home/hansode/.ssh
+ curl -fsSkL https://github.com/hansode.keys -o /home/hansode/.ssh/authorized_keys

あとはこのスクリプトを使い、開発機ごとに必要なアカウントを作成するのみ。

導入後

  • 誰のモノか分からないアカウントが無くなった
  • 構築後は対象サーバのIPアドレスを教えるだけ
  • 環境構築スクリプトからアカウント作成までワンストップ

あとがき

開発者全員がGitHubアカウントを持っているからこそ可能な事。




編集
@hansode at 11:30|PermalinkComments(0)TrackBack(0)

2013年12月20日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/20担当 (6回目の登場)

Wakame2-logo-mini

「使ってみました/インストールしてみました」は他の方にお任せし、現場の風景をお届けします。

Wakame-vdcを読み解く

背景

困った時がドキュメントの書き時。今回は下記状況に陥って困った。

環境構成:

  • カナリア環境(しばらく稼働させてる環境)
  • ナイトリービルドによりスモークテスト実施

遭遇した状態:

  • どうやら断続的に node.state が !online状態(onlineではない状態の意味)のhvaが登場
    • 何故、断続的だと判断できるのは、一定時間経過したジョブを処理していたから
  • 何故 !online になっていたのか・・・を調査したいが、今の実装では state 変更をロギングする仕組みがないくて、ログだけでは調査出来ない
  • 今できる事は、state変更ロジックを確認しておく事

未理解な内部実装を理解する為、目出度く?!コードリーディングを開始したのであった。

パッケージバージョン
  • isono 0.2.19
  • wakame-vdc 13.08.0
家族構成

wakame-vdcは、複数agentによってクラスタが構成されていて、各agentはAMQPネットワークに参加している。この辺の詳細は、また後日、追い詰められた時に、書くのだと思う。触れる必要が中たっ為、今回は省略。

dcmgr-agent-cluster

今回の第一調査対象はhva。

役者: hva

hvaを覗いてみる。

wakame-vdc/dcmgr/bin/hva#L35

途中をざっくりと端折りつつ、読み解いて分かった事は、

  • NodeHeartbeatによって各agentがpingしているようだ
  • NodeHeartbeatの結果を集計しているのはNodeCollector
  • NodeCollectorモジュールを刺してるagentが誰か…
役者: collector

NodeCollectorモジュールを刺してるのは、collector。

wakame-vdc/dcmgr/bin/collector#L24

この先は、wakame-vdcではなく、Isono家の謎に迫る必要がある。さよなら、Wakameちゃん。

Isono家の謎 『状態遷移の条件』

状態遷移する条件を探していくと、

isono/node_modules/node_heartbeat.rb#L12-L19

      initialize_hook do
        @timer = EventMachine::PeriodicTimer.new(config_section.heartbeat_offset_time.to_f) {
          rpc = RpcChannel.new(node)
          rpc.request('node-collector', 'notify', manifest.node_id, node.boot_token) do |req|
            req.oneshot = true
          end
        }
      end

heartbeat_offset_time毎に、NodeCollector宛てにnotifyしてる事が分かる。

heartbeat_offset_timeは、何秒?

isono/node_modules/node_heartbeat.rb#L7-L10

      config_section do |c|
        desc "second(s) to wait until send the next heartbeat signal"
        heartbeat_offset_time 10
      end

明示設定が無い場合、 heartbeat_offset_time は 10 秒。

stateが !:online になる条件は?

少なくとも online ではない事までは分かっている。そうなると、!:onelineになる条件と、!:onlineとは、具体的に何かを探っていくと、node_stateモデルに辿り着く。

isono/models/node_state.rb#L23-L45

      def after_initialize
        self[:state] ||= :init
      end

      def process_event(ev, *args)
        case [ev, self.state.to_sym]
        when [:on_ping, :online], [:on_ping, :init], [:on_ping, :timeout]
          self.state = :online
          self.last_ping_at = Time.now
        when [:on_unmonitor, :online]
          self.state = :offline
        when [:on_unmonitor, :timeout]
          self.state = :offline
        when [:on_unmonitor, :init]
          self.state = :offline
        when [:on_timeout, :online], [:on_timeout, :timeout]
          self.state = :timeout
        when [:on_timeout, :init]
          # Do nothing
        else
          raise "Unknown state transition: #{ev}, #{self.state}"
        end
      end

onelineを含め、どんな状態になりえるのかが分かる。

  • init
  • oneline
  • timeout
  • offline

どの条件で、どうなるか・・・わけWakame(やっと使えた!)なので、直感的に分かりやすくしたくて図にしてみると、

isono-fsm

これで状態遷移を俯瞰しやすい。少なくとも普段コードを書かない自分にとっては最高に読みやすい。今回に限らず、今後の調査材料として役立つ。

前述の通りで、!onelineからonlineへ遷移してるのだから、その経路は絞られる。

!onlineからonlineへ遷移してるのだから・・・

online ⇒ timeout ⇒ online だった事が分かって来る。

isono/node_modules/node_collector.rb#L32-L49

            Models::NodeState.dataset.all.each { |row|
              next if row.state == :offline

              diff_time = Time.now - row[:last_ping_at]
              if row.state != :timeout && diff_time > config_section.timeout_sec
                row.process_event(:on_timeout)
                row.save_changes
                event.publish('node_collector/timedout', :args=>[row.values])
              end

              if diff_time > config_section.kill_sec
                row.process_event(:on_unmonitor)

                event.publish('node_collector/killed', :args=>[row.values])
                row.destroy
              end
            }
          }
  • 最終pingから何秒経過しているか
  • とある閾値を越えている場合、timeoutとして判定

と言う事が分かる。

閾値 config_section.timeout_sec は?

isono/node_modules/node_collector.rb#L8-L15

      config_section do
        desc "time in second to recognize if the agent is timed out"
        timeout_sec (10*2).to_f
        desc "the agent to be killed from the datasource after the time of second"
        kill_sec (10*2*2).to_f
        desc ""
        gc_period 20.0
      end
  • 明示指定が無い場合、 timeout_sec は (10*2).to_f => 20.0
Isono家の安否確認まとめ
  • 各agentは、一定時刻(10秒)毎に生存してる事を通知
  • NodeCollectorは、前回の確認時刻から一定時刻(20秒)以内に通知して来たかどうかを確認
    • 時間以内通知の場合は、online
      • 一定時間が経過してる場合は、timeout

Isono家は、20秒以内に返事しないagentを、timeout扱いする。

Isono家の安否確認を踏まえて、当時の状況を考察すると
  • 20秒以内に返事して無いhvaが居た

と言う事までが判明。しかし、何故返事してなかったのかは、謎のまま。Isono家とは違う次元の何かが起きていたようだ。調査は続くのであった。

あとがき

追い詰められた時の学習意欲。

参考文献



編集
@hansode at 10:00|PermalinkComments(0)TrackBack(0)

2013年12月19日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/19担当 (5回目の登場)

Wakame2-logo-mini

「使ってみました/インストールしてみました」は他の方にお任せし、現場の声をお届けします。

もうすぐRHEL7がリリースされる

先日、RHEL7betaがリリースされた。今後やるであろうRHEL7対応作業へ向けて、ここ数日で気になった3項目に関して頭の中を整理してみた。

  1. epel6 -> epel7
  2. msyql -> mariadb
  3. systemd対応
1. epel6 -> epel7
  • epel-release-7-x.rpmへ変更する程度で済むはず
  • それと、rpmbuildツールが少し頑張れば良い領域
2. mysql -> mariadb
  • DB初期化時に使用している管理コマンドmysqladmin等を切り替え
  • Rubyの依存パッケージの検証が必要。仮にMySQLのままだとしても、ある程度のバージョン差異が生じるため、検証が必要。
3. systemd対応

現在upstartを採用している理由はいくつあって、その1つは、以前、ubuntuがメインディストリビューションだった事。upstart system confであれば、ubuntuでもrhel互換でも、どちらでも使える。そう言った理由で採用した経緯がある。しかし、最近ではubuntu環境へのインストール要件は皆無に近い。

  • rhel7には、upstartのrpmパッケージが存在してないので、SysV initかsystemdへ変更する必要がある。
  • rhel7の標準initはsystemd
  • これらを踏まえると、systemd対応は必至
あとがき

12/08担当 @debilityさんのエントリ:

2年ほど前にWakame-vdcと大いにまみれさせていただいた

2年前はRHEL6.0対応し始めてから間もない頃で、RPM化するよりも半年以上も前の事。ご迷惑をおかけしつつも、苦しみを分かち合いながら一緒にお仕事した日々は、今では良き思い出。あれから2年、あっと言う間。

福岡出張へのお誘い、まだ来てません。そろそろですね?




編集
@hansode at 10:00|PermalinkComments(0)TrackBack(0)

2013年12月18日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/18担当 (4回目の登場)

Wakame2-logo-mini

今回に限り「使ってみました/インストールしてみました」をしてみます。

Dockerと連携させる

Wakame Users Group Advent Calendar 2013 12/02担当がOpenVNetインストールネタ。

手順が正しいのかどうかをDockerで確認してみた。(あれ?Wakame-vdcじゃないの?)

検証環境
  • CentOS 6.5 (OpenVNet推奨はCentOS 6.4らしいけども気にしない)
  • kernel-2.6.32-431.el6.x86_64
  • docker-io-0.7.0-14.el6.x86_64
  • lxc-0.9.0-2.el6.x86_64
  • wakame-vnet.noarch 20131108190022git48a1361.fpm0-1
何度も再現させるのはDockerの得意とする所

手戻りと作業切りわけを兼ねて、3つのイメージを作成する戦略にした。

  1. repoファイルセットアップまで実施
  2. RPMインストールまで実施
  3. DB初期化まで実施
1: openvnet.repo
openvnet.repo/Dockerfileを配置
FROM hansode/centos-6-x86_64

RUN curl -fsSkL -o /etc/yum.repos.d/openvnet.repo             https://raw.github.com/axsh/openvnet/master/openvnet.repo
RUN curl -fsSkL -o /etc/yum.repos.d/openvnet-third-party.repo https://raw.github.com/axsh/openvnet/master/openvnet-third-party.repo
RUN rpm -Uvh http://dlc.wakame.axsh.jp.s3-website-us-east-1.amazonaws.com/epel-release
イメージをビルド
$ sudo docker build -t openvnet.repo .
Uploading context 10240 bytes
Step 1 : FROM hansode/centos-6-x86_64
 ---> cff199166afa
Step 2 : RUN curl -fsSkL -o /etc/yum.repos.d/openvnet.repo             https://raw.github.com/axsh/openvnet/master/openvnet.repo
 ---> Running in 5907fffae0ed
 ---> 79cea9051987
Step 3 : RUN curl -fsSkL -o /etc/yum.repos.d/openvnet-third-party.repo https://raw.github.com/axsh/openvnet/master/openvnet-third-party.repo
 ---> Running in 0ec98e92ddac
 ---> 103fb501492e
Step 4 : RUN rpm -Uvh http://dlc.wakame.axsh.jp.s3-website-us-east-1.amazonaws.com/epel-release
 ---> Running in 57110506cb9b
warning: /var/tmp/rpm-tmp.epxeye: Header V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
Retrieving http://dlc.wakame.axsh.jp.s3-website-us-east-1.amazonaws.com/epel-release
Preparing...                ##################################################
epel-release                ##################################################
 ---> ceb9cf50ef7e
Successfully built ceb9cf50ef7e
ビルドされたイメージの内容を確認
$ sudo docker images openvnet.repo
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
openvnet.repo       latest              ceb9cf50ef7e        25 seconds ago      14.42 MB (virtual 586.8 MB)

ここまでに586.8 MB使用。

2: openvnet.common
openvnet.common/Dockerfileを配置
FROM openvnet.repo

RUN yum install --disablerepo=updates -y wakame-vnet
イメージをビルド
$ sudo docker build -t openvnet.common .
Uploading context 10240 bytes
Step 1 : FROM openvnet.repo
 ---> ceb9cf50ef7e
Step 2 : RUN yum install --disablerepo=updates -y wakame-vnet
 ---> Running in 8ab3ffbfd54f
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: ftp.iij.ad.jp
 * epel: ftp.iij.ad.jp
 * extras: ftp.iij.ad.jp
Setting up Install Process
Resolving Dependencies
--> Running transaction check
...
Installed:
  wakame-vnet.noarch 0:20131108190022git48a1361.fpm0-1

Dependency Installed:
  dash.x86_64 0:0.5.5.1-4.el6
  dracut.noarch 0:004-335.el6
  dracut-kernel.noarch 0:004-335.el6
  file.x86_64 0:5.04-15.el6
  grubby.x86_64 0:7.0.15-5.el6
  kernel.x86_64 0:2.6.32-431.el6
  kmod-openvswitch.x86_64 0:1.10.0-1.el6
  libdrm.x86_64 0:2.4.45-2.el6
  libpcap.x86_64 14:1.4.0-1.20130826git2dbcaa1.el6
  libpcap-devel.x86_64 14:1.4.0-1.20130826git2dbcaa1.el6
  libpciaccess.x86_64 0:0.13.1-2.el6
  libxslt.x86_64 0:1.1.26-2.el6_3.1
  libyaml.x86_64 0:0.1.3-1.el6
  mysql.x86_64 0:5.1.71-1.el6
  mysql-server.x86_64 0:5.1.71-1.el6
  openpgm.x86_64 0:5.1.118-3.el6
  openvswitch.x86_64 0:1.10.0-1
  perl.x86_64 4:5.10.1-136.el6
  perl-DBD-MySQL.x86_64 0:4.013-3.el6
  perl-DBI.x86_64 0:1.609-4.el6
  perl-Module-Pluggable.x86_64 1:3.90-136.el6
  perl-Pod-Escapes.x86_64 1:1.04-136.el6
  perl-Pod-Simple.x86_64 1:3.13-136.el6
  perl-libs.x86_64 4:5.10.1-136.el6
  perl-version.x86_64 3:0.77-136.el6
  plymouth.x86_64 0:0.8.3-27.el6.centos
  plymouth-core-libs.x86_64 0:0.8.3-27.el6.centos
  plymouth-scripts.x86_64 0:0.8.3-27.el6.centos
  redis.x86_64 0:2.4.10-1.el6
  tar.x86_64 2:1.23-11.el6
  wakame-vnet-common.noarch 0:20131108190022git48a1361.fpm0-1
  wakame-vnet-ruby.x86_64 0:2.0.0.247.axsh0-1
  wakame-vnet-vna.noarch 0:20131108190022git48a1361.fpm0-1
  wakame-vnet-vnmgr.noarch 0:20131108190022git48a1361.fpm0-1
  wakame-vnet-webapi.noarch 0:20131108190022git48a1361.fpm0-1
  which.x86_64 0:2.19-6.el6
  zeromq.x86_64 0:2.2.0-4.el6
  zeromq-devel.x86_64 0:2.2.0-4.el6

Complete!
 ---> f4585f3b20de
Successfully built f4585f3b20de
ビルドされたイメージの内容を確認
$ sudo docker images openvnet.common
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
openvnet.common     latest              f4585f3b20de        About a minute ago   632.1 MB (virtual 1.219 GB)

ここまでに1.219 GB使用。

3: openvnet.smallci
openvnet.smallci/Dockerfileを配置
FROM openvnet.common

ADD ./initdb.sh /initdb.sh
CMD /initdb.sh
openvnet.smallci/init.shを配置
#!/bin/bash
#
# requires:
#  bash
#
set -e
set -x

[ -f /etc/sysconfig/network ] || : > /etc/sysconfig/network
/etc/init.d/mysqld start

until mysqladmin -uroot ping; do
  sleep 1
done
mysqladmin -uroot create vnet

cd /opt/axsh/wakame-vnet/vnet
PATH=/opt/axsh/wakame-vnet/ruby/bin:$PATH /opt/axsh/wakame-vnet/ruby/bin/bundle exec rake db:init

実行権限を付与。

$ chmod +x init.sh
イメージをビルド
$ sudo docker build -t openvnet.smallci .
Uploading context 10240 bytes
Step 1 : FROM openvnet.common
 ---> f4585f3b20de
Step 2 : CMD : > /etc/sysconfig/network
 ---> Running in 885a743efd17
 ---> ce5389ddeb69
Step 3 : CMD /etc/init.d/mysqld start
 ---> Running in e6049c2aeaeb
 ---> 6957beeae0cd
Step 4 : CMD export PATH=/opt/axsh/wakame-vnet/ruby/bin:$PATH
 ---> Running in 7743b6dd88f1
 ---> c78f8c15a74d
Step 5 : CMD printenv PATH
 ---> Running in e76ba9bc75bb
 ---> f412fdc6fa00
Step 6 : CMD mysqladmin -uroot create vnet
 ---> Running in 6a5fea2907ca
 ---> eeb6f5b51fac
Step 7 : CMD cd /opt/axsh/wakame-vnet/vnet && /opt/axsh/wakame-vnet/ruby/bin/bundle exec rake db:init
 ---> Running in c7415047c846
 ---> 7a7db5249aa5
Successfully built 7a7db5249aa5
ビルドされたイメージの内容を確認
$ sudo docker images openvnet.smallci
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
openvnet.smallci    latest              6f6e46b2dbb9        25 minutes ago      1.192 GB (virtual 2.411 GB)

ここまでに2.411 GB使用。パッケージインストールするだけで、ディスクサイズが2.5GB弱必要である事が分かった。インストールしましたエントリでは触れられてない事の1つ。

コンテナを起動
$ sudo docker run -t openvnet.smallci
+ '[' -f /etc/sysconfig/network ']'
+ :
+ /etc/init.d/mysqld start
Initializing MySQL database:  Installing MySQL system tables...
OK
Filling help tables...
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h 02b537893292 password 'new-password'

Alternatively you can run:
/usr/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd /usr/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/bin/mysqlbug script!

[  OK  ]
Starting mysqld:  [  OK  ]
+ mysqladmin -uroot ping
mysqld is alive
+ mysqladmin -uroot create vnet
+ cd /opt/axsh/wakame-vnet/vnet
+ PATH=/opt/axsh/wakame-vnet/ruby/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ /opt/axsh/wakame-vnet/ruby/bin/bundle exec rake db:init

$ echo $?
0

DB初期化する所までは動作を確認できた。しかも、CentOS-6.5で!

まとめ
  • パッケージインストール程度ならばDockerで検証可能
  • OpenVNetはCentOS 6.5で動作しそう
  • DB初期化するまでとは言え、ディスクサイズは2.5GB弱使用する
あとがき

その先のOpen vSwitchやOpenFlowを使う構成になると、Dockerで検証できるかどうかは未知の世界。検証した結果、Dockerでは検証出来なかった。そんな結果になるかも知れない。そう言う時こそ、Wakame-vdcの出番。見事に繋がった?

参考文献



編集
@hansode at 10:00|PermalinkComments(0)TrackBack(0)

2013年12月08日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/08担当 (3回目の登場)

Wakame2-logo-mini

「使ってみました/インストールしてみました」は他の方にお任せし、現場の悲鳴をお届けします。

全体が見えない

ここ1年は特に、自分がRubyコードをコミットするタイミングは、バグ修正がメイン。バグであるかどうかを確認する過程でモデルの関連を把握したくなる時がある。実装コードを読めば分かる訳だが、全体を俯瞰したい事が多い。実装者は狭い所を見ていれば良いみたいで、実装時のER図の需要は極めて低い。無くても実装されている事が、それを裏付けていると言えるのだろうか。

とある一部機能の実装を把握したくて実装コードを読み進めて行くと、途中で理解した内容を忘れてしまうほど、複雑怪奇(恐らく設計検討不足)になっていて・・・、俯瞰図が無いままでは効率が悪い。そこで、俯瞰図を書き始めた。

lib/dcmgr/models俯瞰図

俯瞰図作成後、調査効率は期待通りに向上した。

困った人が書く!

『ドキュメントがあれば・・・何故、書かないのか?』と思ってる時期はあったが、最近は、困った人が書けば良いと言う考え方へ切り替えた。と言うのは、誰向けに書かれてるのか分からないドキュメントを書く為の時間を割くよりは、実装に注力してもらった方が良い。そう思える事が多いからだ。

困った時が、ドキュメントの書き時

少なくともドキュメント対象は一人存在し、その人が欲するドキュメントが出来上がる。

コードを書かずに実装把握し、プロジェクトに貢献する事は十分可能。副産物として、実装を読み解くスキルは向上し、実装の理解度は高まる。この辺のドキュメント作成に興味のある方がいらっしゃいましたら、ご一報下さい。




編集
@hansode at 15:00|PermalinkComments(0)TrackBack(0)

2013年12月06日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/06担当 (2回目の登場)

Wakame2-logo-mini

「使ってみました/インストールしてみました」は他の方にお任せし、現場の悲鳴をお届けします。

2012/06末 こんにちは、『結合苦』さん

前エントリの継続RPMビルドする仕組み作りの裏では『結合苦』との戦いを繰り広げていた。

ファイル配置程度のインストール作業は、パッケージングによって軽減されていたが、コミッターは結合作業の事は気にせず、思い思いのタイミングで新機能をコミットして来る状況だった。当時の結合作業の大半は自分ひとりで行っていたので(そして今も)、システム結合に悩まされるのは自分ひとり。極度の結合苦に悩まされていた日々。

  • 「何故こうなったのか・・・」
  • 「何故こうなるのか・・・」
  • 「いっそのこと、開発を一時中断できないものか・・・」

苦い経験を踏まえ、後に実感した事は、

  • 「新たなRPMがビルドされてから結合するまでの時間が長ければ長い程、結合苦に陥る」

今となっては当たり前な着地点だが、当時は、それを身体で感じられなかった頃。結合苦を乗り越えたくて、早め早めに結合する作業へ挑み始めたのが、2012/06末。

2012/07 「インスタンス起動/破棄」連続成功への道

Wakame-VDCにおける結合成否の指標の1つ、それは、WebUIからインスタンス起動してインスタンスにログイン出来る事。もしもログイン出来なければ、容赦なく結合失敗と判断されてしまう。たかがログインの舞台裏には、幾つも前提条件が存在している。

  • インスタンスが起動している事
  • インスタンス管理エージェントが起動している事
  • APIサーバが起動してる事
  • WebUIが起動してる事
  • DBサーバが起動してる事
  • ○○・・・が起動している事

更に各コンポーネントが協調して動作する必要がある。

  • 起動順序通りに起動してる事
  • 各configが正しく設定されている事
  • 初期データが投入されている事
  • etc.

これ等は氷山の一角で、前提条件は他にも多々ある。何か1つでも条件が不足していると、ログイン可能状態にならないのは言うまでもない。動かない原因を1つ1つ分析し、動かすための組み合せを探って行く。とある組み合わせで動いていても、新たにビルドされて来た新機能入りRPMパッケージで入れ替えてみると、あっさり動かなくない。ふり出しへと戻される・・・。

2012/08 結合失敗回数と結合成功回数が、逆転する

原因を調査・分析、新たな動く組み合せを作っては、新たな変更によって壊れて行く。この泥臭い修復作業を、ただただ、繰り返す。何度か調査回数を重ねて行くと、似た調査パターン・コマンドセットに分類されて行く。例えばインスタンス作成失敗時エラーログに対するgrepコマンドの組み合わせ。そんな時はコマンドヒストリを駆使し、以前使ったコマンドを分析。少しずつ改良を重ね、手順を少しずつ確立させ、継続的に改善して行く。

  1. 調査手順を確立
  2. 調査手順を分析
  3. 手順を簡略化・単純化
  4. 内容によってはスクリプト化

結果、出来上がるのは、アプリケーション監視相当の仕組み。外堀が埋まって行った。

また、その当時、調査作業と並行してデプロイ作業改善も同時に進めていた。2012/07末にはパッケージ自動ビルドする仕組みを作り上げていたので、残り作業は、

  1. パッケージリポジトリを常時監視
  2. リポジトリが更新されていれば、新パッケージを関連ノードにインストール
  3. インストール後、プロセス再起動

この一連の流れを行うデプロイパイプラインの成長につれシステム全体が安定したのは、2012/08末の頃。 ただ、これは、特定環境におけるパイプラインであり、ポータブルなパイプラインを手に入れるまでには、まだ時間が必要だった。その辺の話は、別エントリに持ち越し。




編集
@hansode at 10:00|PermalinkComments(0)TrackBack(0)

2013年12月04日

このエントリーをはてなブックマークに追加

Wakame Users Group Advent Calendar 2013 12/04担当

Wakame2-logo-mini

「使ってみました/インストールしてみました」は他の方にお任せし、現場から見た風景をお届けします。

お粗末な対応からパッケージング生活へ

「Wakame-VDC RPM化」の話が舞い込んで来たのは2012年03月。RPM化以前のパッケージデプロイ手順は、下記の通りで、大分お粗末なものだった。

  1. ビルドサーバでbundle update等を半手動実行
  2. ビルドサーバからアプリケーションサーバへrsyncによる半手動デプロイ
  3. 依存関係に従い、プロセス再起動

少なくとも半年以上は同様のお粗末な対応でその場をやり過ごし続けていた。やがて、RHEL系の構築需要が高まり、政治的圧力も手伝い、RPM化が本格始動したのが2012年03月。ここからパッケージング生活へとシフトして行く。

RPM化へ向けて生きた参考材料収集

参考にしたのは、openstack-rhel。

当時は既にGitHubのおかげでrpmspecファイルを探す事も簡単になっていた頃。それまでは、SRPMをダウンロードしてインストールする等の作業を必要としたが、GitHub登場により状況は一変した。プログラミングのソースコードだけでなく、パッケージングの領域までオープンになりつつあった。

2012/04/17 rpmspec初コミット

最初の wakame-vdc.repoをコミットしたのは、2012/04/17。この日付には意味があり、Wakame-VDCがリリースされたのは、更に2年前の2010/04/17。2歳のお祝いと、成長の証として、この日にコミット。

2012/07/20 継続的RPMビルド開始 (cron方式)

初コミットからしばらくの間は手動実行で間に合う回数だったが、コミット頻度に比例してビルド需要が高まる。とある時期から手動運用では間に合わなくなり始め、リポジトリの先頭コミットハッシュを監視し続ける簡単な仕組みを導入し、自動ビルドさせる仕組みを導入したのが2012/07/20。小さな変化だったが、手持ち作業に注力出来るようになり、自動化による恩恵を、ジワジワと身体で感じ始めた頃。

2012/08/24 RPMビルド結果メール通知

継続的RPMビルドが安定稼働し始めると、『ビルド結果がどうだったのか』それを知りたい!と言う需要が高まり、ビルド成否をメール通知を開始。この頃から『少なくとも帰る前にコミットするルール』が開発メンバー内で自然に定着し始める。RPM化着手してから半年弱の出来事。

自動化体質へシフトし始めた半年間

パッケージングをきっかけに得た事は、数知れず。

  • 継続的ビルドがどう言うものか
  • 何を気を付けるべきか、何を気を付けるべきだったか
  • 開発プロセスの改善とは

自動化による恩恵を身体で感し始めた半年間。その後の品質向上について検討可能な時期へとシフトして行く話は、別エントリに持ち越し。




編集
@hansode at 10:00|PermalinkComments(0)TrackBack(0)

2013年06月28日

このエントリーをはてなブックマークに追加

継続的改善と自動化が品質を作り上げる

GW代休として、丸一週間お休みを頂いた。
今回の休暇は、いつもとは、一味も二味も違うものであった。

その要因は、自動化。

自動化による脱属人化

下記は、苦しみながら、この1年間で積み上げたWakame-VDCに関する自動化の一部で、今はJenkins(CIサーバ)さんが行っている。

  1. (誰かがSCMにコードをプッシュすると)変更を検知
  2. アプリケーションパッケージを生成
  3. パッケージリポジトリを再構築
  4. パッケージリポジトリから新規VMイメージをビルド
  5. ビルドされたVMイメージを起動
  6. VMに対し、スモークテストを実行
  7. テスト結果をチャットへ通知

ビルドが失敗した時は、ビルドを失敗させたコミッターが、失敗レポートを閲覧して対応する。
休暇中、一度だけビルドが失敗していたが、直ぐに修正され、自分に連絡が来る事は無かった。

これらの工程・処理に関しては、脱属人化に成功した。
自動化により、自分自身が一番助かっている。

身体で感じる重要性

CI環境は、作ってみない限り、その良さと意味が分からない事は、多々ある。
情報整理を兼ね、これまでの取り組み、支える技術等を書き綴ってみる事にする。

継続的インテグレーション入門 開発プロセスを自動化する47の作法
ポール・M・デュバル スティーブ・M・マティアス アンドリュー・グローバー
日経BP社
売り上げランキング: 132,948



編集
@hansode at 00:20|PermalinkComments(0)TrackBack(0)

2011年03月31日

このエントリーをはてなブックマークに追加

開発し辛さを少しでも解消したくて

OpenStackコンピュートのnovaには、nova.shと言うスクリプトがある。これは、novaを手軽に起動停止する目的のスクリプト。novaの起動停止だけでなく、データを初期化もしてくれる。各コンポーネントがscreenのwindowで起動し、ログが出力されている。是非、これをWakame-vdcに入れたくなった。

そして作ったのが、vdc.sh

▼検証環境

  • Ubuntu 10.04.2 Server LTS
  • Wakame-vdc 10.11

▼使い方

wakame-vdcをcloneし、プロジェクトの最上位ディレクトリで実行する事が前提。

$ git clone git@github.com:axsh/wakame-vdc.git
$ git clone git://gist.github.com/895965.git gist-895965
$ mv -i gist-895965/vdc.sh wakame-vdc/.
$ cd wakame-vdc
$ chmod +x ./vdc.sh
$ ./vdc.sh

vdc.shを実行すると、screenが起動し、コンポーネントの数だけwindowが作成され、それぞれのwindowではコンポーネントが実行される仕掛け。

開発時はinitctlでコンポーネントを起動停止するのが面倒で仕方が無い。コンポーネントを起動しては、tailでログを常時表示、そして停止。これを何度も繰り返す。一方、foregroundで実行すればログが表示され、停止するだけで済む。どちらにしても、コンポーネント毎にscreen windowを作成している訳だ。だったらscreenを起動し、コンポーネント分のscreen windowを作成して、コンポーネントを実行してしまえば良い。明らかに作業効率は向上する。vdc.shは、この単純作業を一撃で済ませてくれる。また、事前にデータを初期化するので、開発時は特に重宝する。

あと書き

良いものがあれば、どんどん取り込んで行かない理由がない。




編集
@hansode at 21:15|PermalinkComments(0)TrackBack(0)

2010年08月12日

このエントリーをはてなブックマークに追加

wakame-fuel環境構築スクリプト用のリポジトリを作ったをAMI化

wakame-fuel環境構築スクリプトを実行した状態になっている。

▼AWS情報

  • us-east-1
  • ami-b2bc56db
  • wakame-fuel-ami-us/wakame-fuel-0.5.1_ubuntu-10.04_20100811.01.manifest.xml

▼wakame-fuel情報

  • wakame-0.5.1インストール済み
  • wakameユーザー追加済み
  • プロジェクトディレクトリ /home/wakame/wakame.proj/ 作成済み

管理対象が無い

やはり、これもまたwakame-fuelが入っているだけで意味が無いに等しい。
ApacheやNginx、MySQLなどは未インストールなのだから。

普段からwakame-fuel環境構築慣れしている自分には意味がある。
wakame-fuelだけ入った環境をすぐに調達出来て嬉しい場合、それが大半であるのだから。

さあ、この課題をどう解決する?続きは次回へ。




編集
@hansode at 10:50|PermalinkComments(0)TrackBack(0)