CIGitWindows

インフラCI実践ガイドを試してみる⑥【CIのパイプライン(前半)】

CI

購入した書籍「インフラCI実践ガイド」を試した際のメモの続きです。

第7章のCIのパイプラインとなります。CIを行うためのパイプラインについての解説になります。第7章もボリュームがあるので前半と後半に分けます。今回は前半です。

7.1 パイプラインとは

パイプラインとは関連するジョブ(タスク)を連結して一連のフローとして流すための機能です

7.1.1 パイプラインの役割

パイプラインとジョブネットやジョブワークフローとの違いについてです。

インフラCIは、人間が作業を行うことで環境に蓄積されてしますズレを抑制し、システムの品質や効率を上げるための手法です。

インフラCIを行うためにはプロジェクトメンバーにルール、ツールなどを遵守してもらう必要があります。

このプラクティスをメンバーに対して強制する方法がパイプラインの役割です。

7.1.2 インプットとアウトプット

インフラCIにおいて、入出力のインターフェースになるのがVCSやレビューシステムです。

7.1.3 パイプラインの注意点

インフラCIをデザインする担当者は、パイプラインを利用するメンバーの利便性を考える必要があります。パイプラインを作る際の注意点について解説してます。

メンバーが意義を感じられる

適用範囲を限定する

ブランチを用いた開発では変更部分のみに適用され、それ以外ではすべてのファイルに適用されるように作ってます。

軽微な問題を先に検知する

パイプラインでは必要なジョブを漏れなく実施することが重要ですが、それと同じくらいに「軽さ」が重視されます。

パイプラインが重くなってくるとメンバーは小さな変更ではなく大きな変更をまとめて流そうとします。これではせっかくIaCのベストプラクティスを実践しようしても効果が薄れてしまいます。

こうした事態を避けるには、パイプラインは簡単で素早く実行できるタスクを先に行い、時間がかかるタスクは後半へ回すことが良いとされています。

7.2 パイプラインを使った変更要求への対応

演習を通じて構成定義ファイルの変更とパイプラインを実行しています。

課題としてCMSのコンテンツのバックアップをする設定を行う要求があったというパターンで見ていきます。

7.2.1 バックアップの有効化

Ketchupには標準でバックアップ機能が準備されています。

設定ファイルでbackup enableをtrueに設定すると。ketchupが起動したタイミングでバックアップが作成されるようになります。

Ansibleのロールの中に設定ファイルを配置するテンプレートがあるので修正します。

変更作業の実施

テンプレートのファイル内のketchup bacupをtrueに変更したらpushします。

[root@infraci infraci]# cd ~/ketchup-vagrant-ansible/
[root@infraci ketchup-vagrant-ansible]# vim roles/ketchup/templates/config.json.j2
[root@infraci ketchup-vagrant-ansible]# git commit -a -m "enabled backup that was requested from app team"
[master 2a3cc15] enabled backup that was requested from app team
 1 file changed, 1 insertion(+), 1 deletion(-)
[root@infraci ketchup-vagrant-ansible]# git push
Username for 'http://192.168.33.10': root
Password for 'http://root@192.168.33.10':
Counting objects: 11, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 524 bytes | 0 bytes/s, done.
Total 6 (delta 4), reused 0 (delta 0)
To http://192.168.33.10/root/ketchup-vagrant-ansible.git
   dc91521..2a3cc15  master -> master

パイプラインが走っていることが確認できます

パイプラインが12分くらいかかって遅かったの書籍にあるgitlabとgitlab-runnerのメモリを上げてみました(デフォルトではどちらも2GB)

  config.vm.define "gitlab" do |machine|
    machine.vm.hostname = "gitlab"
    machine.vm.network "private_network", ip: "192.168.33.10"
    machine.vm.network "forwarded_port", guest: 80, host: 8080

    machine.vm.provider "virtualbox" do |vbox|
      vbox.cpus = 2
      vbox.memory = 6144
    end
  end
  config.vm.define "gitlab-runner" do |machine|
    machine.vm.hostname = "gitlab-runner"
    machine.vm.network "private_network", ip: "192.168.33.11"
    machine.vm.network "forwarded_port", guest: 80, host: 8081

    machine.vm.provider "virtualbox" do |vbox|
      vbox.cpus = 2
      vbox.memory = 8192
    end
  end

バックアップの確認

本当にバックアップが行われているか確認してみます。

[root@infraci ketchup-vagrant-ansible]# cd ~/vagrant/infraci/
[root@infraci infraci]# vagrant ssh test-ketchup
Last login: Sun Jun 28 12:29:15 2020 from 192.168.33.1
[vagrant@test-ketchup ~]$
[vagrant@test-ketchup ~]$
[vagrant@test-ketchup ~]$ sudo -i
[root@test-ketchup ~]# cat /opt/ketchup/config.json
{
  "bindext": true,
  "port": 80,
  "data_dir": "app-contents/contents/data",
  "bolt": {
    "path": ""
  },
  "backup": {
    "enabled": true
  },
  "themes": {
    "path": "themes",
    "registry_url": "http://themes.ketchuphq.com/registry.json"
  }
}
[root@test-ketchup ~]# ls -al /opt/ketchup/app-contents/contents/data/backups/
total 4
drwx------. 2 root root   33 Jun 28 12:29 .
drwxr-xr-x. 6 root root  106 Jun 28 12:29 ..
-rwx------. 1 root root 3946 Jun 28 12:29 20200628-122916.bak

7.2.2 確かめられたこと、確かめられていないこと

今回のパイプラインで確認できたこと
→バックアップの設定をしても「バックアップ設定を実施する前のテスト」はパスできたという点

確認できなかったこと
→投入したバックアップの設定がただしく動作しているかどうかという点

7.2.3 テストを追加する

パイプラインにテストを追加する前に、現在どのように構成されているかを理解します。

Gitlabではプロジェクトのルートディレクトリに「.gitlab-ci.yml」というファイルを配置するとこれが読み込まれてパイプラインが起動します。

ステージと変更対象の確認

「.gitlab-ci.yml」の内容を確認してみます。

[root@infraci ketchup-vagrant-ansible]# head -n 10 ./.gitlab-ci.yml
---
stages:
  - lint
  - unit_prepare
  - unit_test
  - int_deploy
  - int_test

variables:
  CONTAINER_IMAGE: c7-systemd

stagesの部分についてです。パイプラインではステージという名前でジョブの実行順序を定義します。

演習では5つのステージが準備されています。

実行順序ステージ実行ジョブ実行される内容
1lintLint_Check_Master
Lint_Check_Branches
Masterに対する全ファイルの規約準拠チェック
Branchに対する全ファイルの規約準拠チェック
2unit_prepareUnit_Packageユニットテスト用のコンテナイメージ作成
3unit_testKetchup_Unit_Test
Ketchup_Nginx_Unit_Test
Ketchup設定に関するユニットテスト
Nginx設定に関するユニットテスト
4int_deployKetchup_Int_Deployテスト環境にシステム一式をデプロイ
5int_testKetchup_Nginx_Int_Testテスト環境にデプロイされた環境へインテグレーションテストを実行

ユニットテストの動作

演習環境のユニットテストの動きについて確認します。

etchup_Unit_Test:
  stage: unit_test
  variables:
    TARGET_APP: ketchup
  services:
    - name: ${CONTAINER_IMAGE_PATH}
      alias: ${TARGET_APP}
      entrypoint: ["/sbin/init"]
  script:
    - export CONTAINER_NAME="`hostname`-`echo ${CONTAINER_IMAGE_PATH}|sed -e 's/\//__/g' -e 's/\:[1-9a-z]\+//g'`-0"
    - docker exec ${CONTAINER_NAME} /bin/bash -c "ansible-playbook -i ./tests/inventory -l ${TARGET_APP} ./${TARGET_APP}.yml"
    - docker exec ${CONTAINER_NAME} /bin/bash -c "cd ./tests; ansible-playbook -i ./inventory ./${TARGET_APP}_test.yml -vv"
  tags:
    - docker

unit_prepareでユニットテスト用のイメージが作成。変更がされた構成定義ファイルをすべてイメージ内にコピーし、これらの実行のために必要な各種パッケージをインストールしています。

unit_testではこのイメージから起動したコンテナ内でテストを実行します。

テストにコンテナを利用している部分がポイントとなります。

テストコードの追加

ketchupの起動時に作成されるバックアップファイルの有無をチェックして、存在する→OK、存在しない→NG、というテストを追加します。

具体的には以下のような条件をテストします。

①「/opt/ketchup/app-contents/contents/data/backups/」に「英数字8桁-英数字6桁.bak」というファイルが生成される

②このファイルが1つだけ存在をOK(過去のバックアップなどの2つ以上のファイルが残っていたらNG)

③テスト実行時の10分前までに作成されたファイルでなければNG

実際にユニットテストのファイルに上記のテストを記載してGitにpushしてパイプラインが動いて、結果が成功することを確認します。

[root@infraci ~]# cd ~/ketchup-vagrant-ansible/
[root@infraci ketchup-vagrant-ansible]# vim roles/ketchup/tasks/unit_test.yml

  - name: Count the number of backup files
    shell: find {{ ketchup_home }}/{{ ketchup_data_dir }}/backups -type f -mmin -10 | grep -e '[0-9]\{8\}-[0-9]\{6\}.bak' | wc -l
    register: test_backup_file_num

  - name: Check th number of backup file is 1
    assert:
      that:
        - ( test_backup_file_num.stdout | int ) == 1
      msg: "Ketchup backup file is not exist or remaining old file"

[root@infraci ketchup-vagrant-ansible]# git commit -a -m "add unit test for backup config"
[root@infraci ketchup-vagrant-ansible]# git push
Username for 'http://192.168.33.10': root
Password for 'http://root@192.168.33.10':

テストコードの記載にミスがあって3回目でようやくクリアできました。

追加したテストコードの効果

他のチームメンバーが勘違いしてバックアップを無効にした場合を想定しています。もう一度バックアップを無効にします。

[root@infraci ~]# cd ~/ketchup-vagrant-ansible/
[root@infraci ketchup-vagrant-ansible]# vim roles/ketchup/templates/config.json.j2
(略)
  "backup": {
    "enabled": false
  },

[root@infraci ketchup-vagrant-ansible]# git commit -a -m "Undo the backup config"
[root@infraci ketchup-vagrant-ansible]# git push

バックアップを無効のまま、パイプラインを実行すると、正しくバックアップファイルのユニットテストの部分でエラーになっていました。

今回のケースは実際の現場では結構あって、誰かがわからないまま変更している、というのを防ぐことができます。

誰がファイルを更新したかもgit使っているので簡単です。

[root@infraci ketchup-vagrant-ansible]# git blame aafd21fb2cd783e2c8350bb694310277cb5d4613 roles/ketchup/tasks/unit_test.yml
(略)
df80aabe (spchildren       2018-02-26 03:02:41 +0900  86)     wait_for:
df80aabe (spchildren       2018-02-26 03:02:41 +0900  87)       port: "{{ ketchup_port }}"
df80aabe (spchildren       2018-02-26 03:02:41 +0900  88)       msg: "ketchup is not active."
df80aabe (spchildren       2018-02-26 03:02:41 +0900  89)
5b9815e8 (root             2020-06-25 06:42:50 +0900  90)   - name: Count the number of backup files
45acf213 (root             2020-06-25 06:56:30 +0900  91)     shell: find {{ ketchup_home }}/{{ ketchup_data_dir }}/backups -type f -mmin -10 | grep -e '[0-9]\{8\}-[0-9]
5b9815e8 (root             2020-06-25 06:42:50 +0900  92)     register: test_backup_file_num
5b9815e8 (root             2020-06-25 06:42:50 +0900  93)
5b9815e8 (root             2020-06-25 06:42:50 +0900  94)   - name: Check th number of backup file is 1
5b9815e8 (root             2020-06-25 06:42:50 +0900  95)     assert:
5b9815e8 (root             2020-06-25 06:42:50 +0900  96)       that:
aafd21fb (root             2020-06-25 07:17:52 +0900  97)         - ( test_backup_file_num.stdout | int ) == 1
5b9815e8 (root             2020-06-25 06:42:50 +0900  98)       msg: "Ketchup backup file is not exist or remaining old file"
5b9815e8 (root             2020-06-25 06:42:50 +0900  99)
df80aabe (spchildren       2018-02-26 03:02:41 +0900 100)   become: True

上の変更履歴を見ると誰が、いつ、どこを修正したかも一目瞭然ですね。

記載ミスで「grep -e ‘[0-9]{8}-[0-9]」と「test_backup_file_num.stdout | int ) == 1」の部分を修正しています。

今回は結構長くなりましたが、次回も引き続きCIの部分の後半です。

今回は以上となります。

コメント