CIWindows

インフラCI実践ガイドを試してみる③【環境構築の自動化】

CI

引き続きインフラCI実践ガイドの第5章に取り組んでみます。

4章まででテスト環境の構築は完了しているので、第5章からは実際にCIを行うために必要となる考え方についての解説が主になってきています。

5.1 仕様書と手順書

座学として必要となる概念についての説明です。

  • 仕様書や手順書をヒューマンが読めるようにした場合(ヒューマンリーダブル)には認識のズレがでる可能性がある
  • 逆にjsonなどでマシンが読めるようにした場合(マシンリーダブル)はズレはなくなるが人間からは読みにくくてそれを書くための学習コストが必要となる
  • インフラCIにおける仕様書と手順書は「ヒューマンリーダブルでありマシンリーダブルである」必要がある。いわゆる良いとこ取り
    • 具体的には「人が読んで解釈でき、そのままマシンが実行できるので人のズレが持ち込まれる余地がなく、バージョン管理も容易」なもの
  • Ansibleにとっての仕様書と手順書は、playbookのこと

5.2 パイプラインのなかでの自動構築作業

5.2.1 自動実行される構築作業の内容

例としてketchup-vagrant-ansibleのPlaybookの内容について確認します。

site.ymlからはフロントエンドとバックエンド構築の2つのplaybookを呼んでます。

[root@infraci ketchup-vagrant-ansible]# cat site.yml
---
- import_playbook: ketchup.yml
  tags:
    - ketchup
- import_playbook: ketchup_nginx.yml
  tags:
    - ketchup_nginx

さらに子にあたるplaybookからはroleという単位でさらに子となるものを呼んでいます。role内ではtaskといわれる単位で処理が呼ばれるようになってます。

[root@infraci ketchup-vagrant-ansible]# cat ketchup.yml
---
- name: Install Ketchup
  hosts: "ketchup"
  gather_facts: True

  roles:
    - role: repos_el

    - role: packages_el
      packages_el_nginx_packages: False

    - role: ketchup

どんなタスクが呼ばれているかを確認するためのコマンド(ansible-playbook –list-tasks site.yml)を実行してます。

ansibleのPlaybookで正しくnameを記載することで人間でも読みやすい(ヒューマンリーダブル)手順書ということができるようになります。

[root@infraci ketchup-vagrant-ansible]# ansible-playbook --list-tasks site.yml

playbook: site.yml

  play #1 (ketchup): Install Ketchup    TAGS: [ketchup]
    tasks:
      repos_el : include task specific variables        TAGS: [ketchup]
      repos_el : Install yum repositories       TAGS: [ketchup]
      repos_el : Enable epel repository TAGS: [ketchup]
      packages_el : include task specific variables     TAGS: [ketchup]
      packages_el : Install common packages     TAGS: [ketchup]
      packages_el : Install nginx packages      TAGS: [ketchup]
      ketchup : include task specific variables TAGS: [ketchup]
      ketchup : Create ketchup home directory   TAGS: [ketchup]
      ketchup : Download ketchup app and contents from github   TAGS: [ketchup]
      ketchup : Extract ketchup app     TAGS: [ketchup]
      ketchup : Install ketchup configuration file      TAGS: [ketchup]
      ketchup : Install bootstrap for systemd   TAGS: [ketchup]

  play #2 (ketchup_nginx): Install Nginx frontend for Ketchup   TAGS: [ketchup_nginx]
    tasks:
      repos_el : include task specific variables        TAGS: [ketchup_nginx]
      repos_el : Install yum repositories       TAGS: [ketchup_nginx]
      repos_el : Enable epel repository TAGS: [ketchup_nginx]
      packages_el : include task specific variables     TAGS: [ketchup_nginx]
      packages_el : Install common packages     TAGS: [ketchup_nginx]
      packages_el : Install nginx packages      TAGS: [ketchup_nginx]
      nginx : include task specific variables   TAGS: [ketchup_nginx]
      nginx : Ensure that selinux is enabled    TAGS: [ketchup_nginx]
      nginx : Grant selinux permission for Nginx        TAGS: [ketchup_nginx]
      nginx : Install nginx.conf for Nginx      TAGS: [ketchup_nginx]
      nginx : Install ketchup.conf for Nginx    TAGS: [ketchup_nginx]

5.2.2 構成定義ファイルを使った構築の自動化

実際にAnsibleからPlaybookを使って環境構築を行います。

Inventryファイルを本番環境とテスト環境でそれぞれ指定することで、同じ環境を構築することができます。Inventoryファイルは対象のホストもしくはホストグループを定義しています。

ここではまず初めに本番環境の構築をします。hosts/ketchup/inventoryで本番のInventoryファイルを指定しています。


[root@infraci ketchup-vagrant-ansible]# ansible-playbook -i hosts/ketchup/inventory site.yml

PLAY [Install Ketchup] ***********************************************************************************************************************************************************************************************************************************************************
(省略)
RUNNING HANDLER [nginx : restart nginx] ******************************************************************************************************************************************************************************************************************************************
changed: [192.168.33.13]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************
192.168.33.12              : ok=13   changed=9    unreachable=0    failed=0
192.168.33.13              : ok=13   changed=8    unreachable=0    failed=0

で本番サイトにアクセスできることを確認します。

次にテスト環境の構築です。本番用ではなくテスト用のインベントリファイルを指定(hosts/ketchup/test_inventory)して同じく実行しているだけです。

[root@infraci ketchup-vagrant-ansible]# ansible-playbook -i hosts/ketchup/test_inventory site.yml

PLAY [Install Ketchup] ***********************************************************************************************************************************************************************************************************************************************************
(省略)
RUNNING HANDLER [nginx : restart nginx] ******************************************************************************************************************************************************************************************************************************************
changed: [192.168.33.15]

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************************************************
192.168.33.14              : ok=13   changed=8    unreachable=0    failed=0
192.168.33.15              : ok=13   changed=6    unreachable=0    failed=0

テスト環境にアクセスできることを確認します。

このようにInventoryファイルを変更するだけで本番とテストで同じ環境が構築できるのがAnsibleです。

5.3 構成定義ファイルを用いた構築自動化の基本

5.3.2 Ansibleの基本ルール作成の重要性

Ansible Playbookの構造とルールについての解説です。

私もAnsibleを使って自動化などを行ってますが、ルールなどは自分だけのルールで他人から見たらわかりにくい部分があるかと思います。

ここではプロジェクトメンバーが守るべき共通ルールをわかりやすく明確に定めることが重要とされており、チーム開発にとって必須となるルールです。

サンプルで記載されているルールの例が非常にわかりやすくて明確に定めれらていてすごいです。

①自動化全体を動かすときはsite.ymlだけを呼び出す

②実行対象のInventoryはhosts/<HOST_GROUP_NAME>以下に配置する
 HOST_GROUP_NAMEは共通の変数を参照する単位
 Inventoryファイルは本番やテスト環境という単位で分ける

<TASK_GROUP_NAME>.ymlは作業として意味を持つ単位rolesを順に呼び出す。合わせてrolesに実行時に必要な条件を与える

④OSの基本設定やアプリケーションのインストールなど、小さな作業単位に分けてroles/<ROLE_NAME>/以下に配置する。
 各ロール配下のディレクトリ構造はベストプラクティスを採用する
 ロール単位で必ずユニットテストを記述する

⑤Playbookで上書きされる可能性のある値は各ロールの<ROLE_NAME>/defaults/main.ymlに記載して、デフォルト値を設定しておく。それ以外の値は上書きしてなならない

⑥ロール間で共通に参照される変数や3の作業単位時間で共通に参照される変数はInventoryファイルで定義する。
 Taskの実行結果により設定値を変更したい変数は各Roleのvarsへと配置する

5.4 自動化(Playbook)の実装

5.4.1 手順(Tasks)の記述

はじめに手順(task)をAnsibleを使って自動化プロセスを開発する開発者は、「ツールがなくてもゼロから設定が行える」スキルを持っているエンジニアでないとtaskが作れません。当然です。

以下は私の感想
 →ということは、誰かが作ったPlaybookを利用するだけの人はスキルは不要
 →ということは、エンジニアでなくても使える
 →ということは、Playbookを自ら作れるスキルがあるインフラエンジニアだけが生き残り、中途半端なできる風エンジニアは不要ということになる。と感じました。

でも、現時点でも実際の現場はそんな感じになってきてますね。今後のインフラエンジニアとして勝ち残るためには、幅広くスキルを習得していることが必要です。

サンプルシステムの仕様

  • 2台のサーバで構成、1台はフロントエンド、1台はバックエンド
  • バックエンドにはCMSのketchupが起動してサービスを提供
  • フロントエンドにはNginxが起動してリバースプロキシとして動作

必要となる作業項目

必要な作業単位でRoleを作成していきます。この「作業単位」を設定するのは意外と難しいんですよね。幅広い視野を持ってないと主観が入ってルールが混在してしまいます。

①EPELリポジトリの追加
②パッケージのインストール
③アプリケーションのインストール
④リバースプロキシのインストール

Roleを作成

Roleのrepos_elを適用するPlaybookを作成して実行します。以下のplaybookを作って実行します。

 - hosts: ketchup
   roles:
   - repos_el

Playbookを実行してrepos_elのRoleがエラーなく実行されるのを確認します。

次にnginx側にも同じPlaybookを実行するためhostsを変更して実行します。

 - hosts: ketchup_nginx
   roles:
   - repos_el

こちらも問題なく実行されました。一つのRoleを作成すれば複数のホストに対しても簡単に実行することができるようになりました。

作業の単位について考える

書籍のこの部分に書かれている「作業単位」は本当に実際の現場では難しいことだと思います。

「意味のある作業で区切る」と「同じ系統の作業で区切る」は結局のところ人が判断する部分だからです。プロジェクトリーダーなりが正しい基準をもっていないと実施する人でバラバラになってします可能性があり危険です。

5.4.2 パラメータ(Vars)の記述

パラメーターについての説明に移ります。パラーメーターは変動する可能性のある値です。この部分をあらかじめ柔軟に構成できるように設計することが重要です。

書籍では結果として後で出てきますが、変数を複数定義した際の優先度は以下の通りです。

  1. roles/ketchup/vars/main.yml /opt/app/tmp/ketchup
  2. group_vars/ketchup.yml /opt/app/web/ketchup
  3. hosts/ketchup/inventory_tmp /opt/app/ketchup
  4. roles/ketchup/defaults/main.yml /opt/ketchup

書籍内のルールでは2と3だけを編集することとしています。設定箇所を絞ることでデバックしやすくなります。

まず初めに3のInventoryファイル(test_inventory_tmp)に対し、ketchup_homeのパラメータを定義してからPleybookを実行します。

その結果としてketchupにアクセスできることと、homeディレクトリが/opt/app/ketchup/に変更されることを確認します。

[root@infraci ketchup-vagrant-ansible]# cp hosts/ketchup/test_inventory hosts/ketchup/test_inventory_tmp
[root@infraci ketchup-vagrant-ansible]#  vim hosts/ketchup/test_inventory_tmp
(略)
ketchup_repos="https://github.com/infra-ci-book/app-contents.git"
ketchup_app_path="app-contents/applications/ketchup_Linux_x86_64.tar.gz"
ketchup_data_dir="app-contents/contents/data"
ketchup_home="/opt/app/ketchup" <-ここを変更
(略)
[root@infraci ketchup-vagrant-ansible]# ansible-playbook -i hosts/ketchup/test_inventory cleanup.yml


[root@infraci ketchup-vagrant-ansible]# ansible-playbook -i hosts/ketchup/test_inventory_tmp site.yml
(略)
[root@infraci ketchup-vagrant-ansible]# cd ~/vagrant/infraci/
[root@infraci infraci]# vagrant ssh test-ketchup
Last login: Wed Jun 24 03:26:47 2020 from 192.168.33.1
[vagrant@test-ketchup ~]$ ls /opt/app/ketchup/ <-新しいディレクトリ
LICENSE  app-contents  config.json  ketchup
[vagrant@test-ketchup ~]$ systemctl status ketchup
● ketchup.service - Start Ketchup
   Loaded: loaded (/etc/systemd/system/ketchup.service; static; vendor preset: disabled)
   Active: active (running) since Wed 2020-06-24 03:26:48 UTC; 5min ago
 Main PID: 4917 (ketchup)
   CGroup: /system.slice/ketchup.service
           mq4917 /opt/app/ketchup/ketchup start

続けて、優先度2にあたるgroup_vars/ketchup.ymlファイルを編集するとともに、優先度1ではあるがルール上は使用禁止のroles/ketchup/vars/main.ymlを編集します。


[root@infraci ketchup-vagrant-ansible]# mkdir group_vars
[root@infraci ketchup-vagrant-ansible]# vim group_vars/ketchup.yml
ketchup_home: /opt/app/web/ketchup

[root@infraci ketchup-vagrant-ansible]# vim roles/ketchup/vars/main.yml
ketchup_home: /opt/app/tmp/ketchup

[root@infraci ketchup-vagrant-ansible]# ansible-playbook -i hosts/ketchup/test_inventory_tmp site.yml

結果として優先度1のroles/ketchup/vars/main.ymlが反映されます。

変数のファイルがばらけすぎると複雑になってしますおで、優先順位を把握するよりはルールでつかう変数の場所をルールで絞るほうがよさそうです。

環境のクリア

[root@infraci ketchup-vagrant-ansible]# cd ~/
[root@infraci ~]# rm -rf ketchup-vagrant-ansible/
[root@infraci ~]# git clone http://192.168.33.10/root/ketchup-vagrant-ansible.git

[root@infraci ~]# cd ~/ketchup-vagrant-ansible/
[root@infraci ketchup-vagrant-ansible]#
[root@infraci ketchup-vagrant-ansible]# git config --local user.name "root"
[root@infraci ketchup-vagrant-ansible]# git config --local user.email "root@example.com"
[root@infraci ketchup-vagrant-ansible]# git config --local push.default simple


[root@infraci ketchup-vagrant-ansible]# cd ~/vagrant/infraci/
[root@infraci infraci]# vagrant destroy -f ketchup ketchup-nginx test-ketchup test-ketchup-nginx
[root@infraci infraci]# vagrant up  ketchup ketchup-nginx test-ketchup test-ketchup-nginx

5.5 変化するシステムへの対応

5.5.1 構築の自動化とダイナミックインフラストラクチャ

あとは動的な変数の対応についても説明されてます。

座学のレベルです。実際の現場で利用する場面は多そうです。

次回はユニットテストについて解説されてます。いよいよCIに近づいてきている感じがします。

今回は以上となります。

コメント