ときどきAnsible日記

主にITインフラ基盤の自動化に関する事を書いているブログです

CIとCDについて

お疲れ様です。伊藤です。春を迎えたはずなのになんだかちょっぴり寒い。皆様風邪など引かぬように体調にはお気をつけください。

今日はCI(継続的インテグレーション)とCD(継続的デリバリー)について書きます。
で、まあ自動化といえばCI/CDはよく出ますね。しかし!結局なんなのそれ?よくわかんないんだけど?という方も多いかと思います(ってか私がそうでした)
そんなの常識だろう、という方はそっとブラウザを閉じていただけると助かります。

というわけでここからはインフラの知識ゼロでもわかるCI/CDを目指して書いていきたいと思います!(決意)

CIから行きましょう。まず継続的インテグレーションという言葉が難しい。インテグレーションが継続的ぃ?はぁ?って感じです。直訳にもほどがあるんじゃないのって感じですね。
英語で書くとcontinuous integration....うん、ちょっと忘れましょう。
おそらく当初は大層な意味があったんでしょうが、今は結局「CVSとかgitとかのライブラリ管理ソフトに作ったプログラムを登録したら自動的にテストまで行う」事に尽きると思っています。
もうそれだけかと。それを実行するのがJenkinsをはじめとしたCIツールと呼ばれるものです。要はこいつがライブラリを監視していて、登録されたら事前に予約しておいたシェルを動かす、それだけです。
つまりは

  • 修正ソースを開発ライブラリにコミット
  • ソースをビルド
  • 実行ファイルを開発環境に配置
  • 開発環境のアプリ停止
  • 開発環境へデプロイ
  • 開発環境のアプリ再開
  • テスト用のシェル実行

この流れを自動にするって感じですね。そうすると修正してすぐテストできるから効率上がるぜ!アジャイル開発にもってこい!見たいな感じになるわけですね。


~ある日の開発ルーム~
開発チームのA君:やっとプログラムが動くことまで行ったからテストしようかなぁ。。。でもデプロイは運用チーム担当だから今日の帰り際にお願いして明日テストしーよおっと。
運用チームのBさん:いやデプロイするならちゃんと申請してください。あと業務後なので明日の夜リリースです。
A君:えー。めんどくさいなあ。それぐらいちゃちゃっとやってよ。申請書書くのめんどくさいから明日やろっと。
~そして明日~
申請書は遅れたものの何とか無理を言ってデプロイしてもらう。
A君:あ~また止まった!ちょっと直すからまたデプロイしてもらおう!
~以下無限に続く~
ということもなくなりますね(いいすぎ)
その辺が一体化されることがまさにDev(開発)Ops(運用)の考え方だと思います。


では続いてCD(継続的デリバリー)ですね。こちらはリリースの自動化です。先ほどとほとんど一緒ですが下記の流れを自動化します。

  • テスト完了ソースを本番ライブラリにコミット
  • ソースをビルド
  • 実行ファイルを本番環境に配置
  • 本番環境のアプリ停止
  • 本番環境へデプロイ
  • 本番環境のアプリ再開

の自動化です。こう考えると非常に簡単。ですが、実際には開発対象のアプリケーションの種類によって色々とデプロイ方法も違ったり、再起動対象も代わったりと簡単にはいきません。が、使い込んでいくうちにリリースの人為的なミスは無くなり、リリースまで瞬時に完了するため開発のスピード感が劇的にあがります(たぶん)


まあそんなわけで、CI/CDっていうのは世の中に浸透していると思います。あと今回はすごーく狭義にCI/CDのことを書きましたが、もちろん開発環境でもCDするし本番でCIということもあるかもしれません。私もこの手の環境作ったことが無いのでエアプ感が漂いますが、機会があれば是非構築してみたいと思います。
お疲れ様でした。

whenで処理を分岐させる

お疲れ様です。伊藤です。

4月も2週目を回り、新生活もいよいよ本格化してきましたが、皆様いかがお過ごしでしょうか。社会人1年目の方も20年目の方も色々ありますががんばっていきましょう。

さてPlaybookで処理をしてると往々にして処理の分岐がしたくなる時があります。たとえばひとつ前の処理の結果によって実行させたりさせたくなかったり。まあプログラムで言うとif的な感じになると思うのですが、Ansibleでこれにあたるのがwhenです。ちょっとif文とはニュアンスが違うのですが、処理の実行条件をつけられる、といったものになります。
たとえば下記のようなplaybookを作成して実行してみましょう。

---
- hosts: localhost

  tasks:
    - name: test ping
      ping:
      register: ret

    - name: ping is ping
      debug: var=ret
      when: ret.ping == "ping"

    - name: ping is pong
      debug: var=ret
      when: ret.ping == "pong"

pingモジュールはコントロールサーバに対してpingを打ち、正常終了した場合にpongを返します。ピンポンですね。

pingの結果はregisterを使いretに入れています。
で、retの中のpingの項目にpongが入っているのでwhenの中でそれを判定しています。

実行すると以下のような結果になります。

[root@test ansible]# ansible-playbook playbook.yml

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [test ping] ***************************************************************
ok: [localhost]

TASK [ping is ping] ************************************************************
skipping: [localhost]

TASK [ping is pong] ************************************************************
ok: [localhost] => {
    "ret": {
        "changed": false,
        "failed": false,
        "ping": "pong"
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

ping is ping ではpingの戻り値がpingだった場合のみ実行されますが、こんなの帰ってくるわけ無いのでスルーします。結果上はskippingとなってますね。
で結果がpongだった場合はdebugでretの中身を表示させています。中を見るとやっぱりpingにpongが入っていると。

見た感じシェルとかプログラムに慣れている人には下のほうにwhenがあるので違和感があるかと思います(私はありました)が、こういうものなので直に慣れます(笑
whenが書かれた上の処理が分岐の対象になります。イメージとしては-nameの配下にいるものはひとつの塊としてみてもらって、その中での実行部と制御部に分かれている感じです。


ごくごく簡単に使うとこんな感じになります。非常に使う機会が多い...ってかこれ知らないと多分Playbook書けません。あと何故かはわからないのですが、本来変数を使用する場合(ここではretが変数)は{{ ret }}見たいな表現をしないといけないのですが、whenの中では無しで表現できています。ってか逆に{{}}つけるとエラーになります。(そーユー意味ではdebugも{{}}無しだ....この辺の切り分けは機能の設計者によって違うんでしょうねぇ...)

という感じで今回は終了です。お疲れ様でした。