【AWX】GitHubとAWSと連携して、ハンズオン環境をCI/CDする
本記事はエーピーコミュニケーションズ Advent Calendar 2020の12日目の記事です。
はじめに
AWS上のハンズオン環境(使い捨て)をCI/CDする仕組みをAWXとGitHubを連携させて実現してみました。
本記事では、その仕組みの構築方法・運用方法を紹介します。
ハンズオンの内容は、Amazon EC2上で行うAnsible研修を想定しています。
研修内容は他のテーマでも応用可能だと思います。
導入前の課題
本記事で紹介する仕組みは以下のような課題の解決を試みています。
- 以下の手動作業に時間がかかっている
- 研修で使用するハンズオン環境の準備・片付け
- 受講者からの要望を反映した研修内容の実機検証
- 作業ミスによって、同じ環境が再現されないことがある
構成
全体構成は以下のようになります。
※役割について補足
- メンテナンス担当:研修内容・ハンズオン環境のアップデート担当
- オペレーター:研修で使用するハンズオン環境の準備・片付け担当
環境構築
仕組みの構築方法を説明します。
環境情報
2020/11/23に検証しています。
- AWXサーバー
項目 | バージョン |
---|---|
Instance Type | t2.medium |
OS | Amazon Linux2 |
Ansible | 2.9.15 |
AWX | 15.0.1 |
事前準備
以下のAWSリソースは事前に作成してある想定です。
Playbook作成
以下の用途のroleとそれをキックするPlaybookを作成し、GitHubリポジトリに登録します。
検証で使用したPlaybookを以下のリポジトリに格納してます。
コントロールノードのみの省エネサンプルですが、ご容赦ください。
また、以下の点は検証時に実際に使った時の状態から修正しています。
- ハンズオンのサンプルPlaybook
- 実際は自社研修で使ってるもので検証しましたが、簡易化しています。
- AWSのリソースID
- <XXXのid>みたいな書き方に直してます。
各Playbookの概要を簡単に説明します。
Playbook名 | 処理内容 | 呼び出すロール |
---|---|---|
create_env.yml | CloudformationでEC2インスタンスのスタックを作成 | create_ec2instance |
setup_env.yml | ハンズオンで使用する教材(サンプルPlaybook)を配置 | setup_master |
test_scenario.yml | ハンズオンのシナリオを実行する | handson_scenario |
delete_env.yml | CloudformationでEC2インスタンスのスタックを削除 | delete_ec2instance |
構文チェックをGitHub Actionに設定
developブランチへのPushをトリガーにSyntax CheckとAnsible-Lintを実行するGitHub Action定義を仕込みます。
以下のワークフロー定義ファイルを.github/workflow/ansible-lint.ymlに登録します。
# This is a basic workflow to help you get started with Actions name: CI # Controls when the action will run. on: push: branches: [ develop ] # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: test: runs-on: ubuntu-latest steps: - name: Check out uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 - name: Install dependencies run: | python -m pip install --upgrade pip pip install ansible==2.9.15 ansible-lint==4.3 - name: Ansible-Lint run: | ansible-playbook create_env.yml --syntax-check ansible-playbook setup_env.yml --syntax-check ansible-playbook test_scenario.yml --syntax-check ansible-playbook delete_env.yml --syntax-check ansible-lint -x 301 -x 305 --force-color
NGだと以下のように表示されます。
ansible-lint -x 301 -x 305 --force-color
のところを
ansible-lint --force-color
(除外ルールなし)で実行してみたら、この結果になりました。
上記、shellモジュール回りで怒られていますが、
shellモジュールの使用は今回のPlaybookはやむを得ないので、
ルールを除外させるようにしてます。
AWX構築
自動テストはAWXから実行させるので、AWXを構築します。
以下のコマンドを順次実行して、AWXをインストールしました。
$ sudo yum update -y $ sudo yum install -y git $ sudo yum install -y docker $ sudo systemctl start docker $ sudo systemctl enable docker $ sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm $ sudo yum --enablerepo=epel install -y ansible $ sudo yum install -y python3 $ sudo pip3 install docker $ sudo pip3 install docker-compose $ git clone https://github.com/ansible/awx $ cd awx/installer/ $ sudo ansible-playbook -i inventory install.yml
http://AWX構築ホストのPublicIP/
にアクセスすると、AWXログイン画面が表示されます。
以下の情報ででログインします。
ユーザー名 | パスワード |
---|---|
admin | password |
また、AnsibleのCloudformationモジュールを使用するために必要なPythonモジュールをインストールします。
$ sudo yum install -y python-pip $ sudo pip install boto3 $ sudo pip install botocore
AWX設定
1.認証情報登録
メニューの認証情報
を選択し、+
ボタンをクリックして、以下の情報を登録します。
GitHub認証情報
項目 値 名前 github-auth 説明 GitHubリポジトリにアクセスするための認証情報 組織 Default 認証情報タイプ ソースコントロール ユーザ名 (GitHubのユーザ名) パスワード (GitHubのパスワード) AWS認証情報
項目 値 名前 aws-auth 説明 AWS上のインベントリ情報を取得するためのAWS認証情報 組織 Default 認証情報タイプ Amazon Web Service アクセスキー (IAMユーザのアクセスキー) シークレットキー (IAMユーザのシークレットキー) EC2インスタンス認証情報
項目 値 名前 ec2-auth 説明 EC2インスタンスへ接続するための認証情報 組織 Default 認証情報タイプ マシン ユーザー名 ec2-user SSH秘密鍵 (秘密鍵をドラッグアンドドロップ)
2.プロジェクト作成
メニューのプロジェクト
を選択し、+
ボタンをクリックして、以下の情報を登録します。
項目 | 値 |
---|---|
名前 | Hanson-Env |
説明 | ハンズオン環境構築コード |
組織 | Default |
SCMタイプ | Git |
SCM URL | (環境構築コードを登録しているGitHubリポジトリ) |
SCM認証情報 | github-auth |
3. インベントリ登録
メニューのインベントリー
を選択し、+
ボタンをクリックして、以下の情報を登録します。
ローカルホスト(Cloudformationモジュール実行対象)
項目 値 名前 localhost ホスト
項目 値 ホスト名 localhost 変数 ansible_connection: local
ansible_python_interpreter: '{{ ansible_playbook_python }}'
-
項目 値 名前 EC2Instances ソース
項目 値 名前 EC2Instances ソース Amazon EC2 認証情報 aws-auth 有効な変数 tags.Name 有効な値 Ansible-Master 上書き ☑ 起動時の更新 ☑
4.ジョブテンプレート登録
メニューのテンプレート
を選択し、+
ボタン・ジョブテンプレート
をクリックして、以下の情報を登録します。
EC2インスタンス作成
項目 値 名前 Create_EC2Instances ジョブタイプ 実行 インベントリー localhost プロジェクト Handson-Env Playbook create_env.yml 認証情報 aws-auth ハンズオン環境セットアップ
項目 値 名前 Setup-Handson ジョブタイプ 実行 インベントリー EC2Instances プロジェクト Handson-Env Playbook setup_env.yml 認証情報 ec2-auth ハンズオンシナリオテスト
項目 値 名前 Test-HandsonScenario ジョブタイプ 実行 インベントリー EC2Instances プロジェクト Handson-Env Playbook test_scenario.yml 認証情報 ec2-auth EC2インスタンス削除
項目 値 名前 Delete_EC2Instances ジョブタイプ 実行 インベントリー localhost プロジェクト Handson-Env Playbook delete_env.yml 認証情報 aws-auth
5.ワークフローテンプレート登録
メニューのテンプレート
を選択し、+
ボタン・ワークフローテンプレート
をクリックして、以下の情報を登録します。
自動テスト
項目 値 名前 自動テスト SCMブランチ develop - テスト実行後に確実にEC2インスタンスが削除されるように、以下の分岐条件を仕込みます。
- Setup-Handsonが失敗した場合は、Delete_EC2Instancesに進む
- Test-HandsonScenario実行後は常時(=ジョブテンプレートの成功・失敗に関わらず)Delete_EC2Instancesに進む
- テスト実行後に確実にEC2インスタンスが削除されるように、以下の分岐条件を仕込みます。
ハンズオン環境作成
項目 値 名前 ハンズオン環境作成 SCMブランチ main SURVEYの追加
項目 値 プロンプト Number of handson environment 説明 構築するハンズオン環境の台数 回答の変数名 howmany 回答タイプ 整数 最小 1 最大 (受講者の最大数) デフォルトの応答 必須 ☑ SURVEYを設定することによって、ワークフローテンプレート起動時に、
以下のように構築する環境の数を設定できます。
ハンズオン環境削除
項目 値 名前 ハンズオン環境削除 SCMブランチ main SURVEYの追加
項目 値 プロンプト Number of handson environment 説明 削除するハンズオン環境の台数 回答の変数名 howmany 回答タイプ 整数 最小 1 最大 (受講者の最大数) デフォルトの応答 必須 ☑
権限設定
オペレーター用のユーザーoperation
を作ります。
メニューのユーザー
を選択し、+
ボタンをクリックして、以下の情報を登録します。
項目 | 値 |
---|---|
ユーザー名 | operation |
メール | (メールアドレス) |
ユーザータイプ | 標準ユーザー |
以下のワークフローテンプレートの実行権限のみを持つように設定します。
メニューのテンプレート
を選択し、ワークフローテンプレート名をクリックします。
- ハンズオン環境作成
- ハンズオン環境削除
パーミッション
タブを選択し、+
ボタンをクリックして、以下の情報を登録します。
項目 | 値 |
---|---|
ユーザ名 | operation |
ロール | 実行 |
operationユーザでログインすると、テンプレート一覧は以下のように表示されます。
運用方法
以下のような手順で運用される想定です。
更新内容はあくまでも一例です。
トリガー
- 以下の要求が発生
- サンプルPlaybookの改善要望
- 最新バージョンのAnsibleでハンズオンを実施したい
Plan
- 以下の方針で更新することに決定
- サンプルPlaybookを更新する
- Ansibleバージョンを最新化する
Do
- メンテナンス担当はHandson-Envリポジトリのdevelopブランチで以下を対応
- サンプルPlaybookの更新
- Ansibleバージョン定義部分を更新
Check
- 構文チェック
- 自動テスト
- メンテナンス担当はワークフローテンプレート
自動テスト
を実行- developブランチの定義ファイルに基づいて以下の処理を自動実行
- ハンズオン環境を自動構築
- 構築したハンズオン環境に、ハンズオンシナリオを実行
- ハンズオン環境を削除
- developブランチの定義ファイルに基づいて以下の処理を自動実行
- メンテナンス担当はワークフローテンプレート
Action
- 自動テストの結果を確認し、問題なければmainブランチにマージ・正式版としてタグ付け
Delivery
- オペレーターはワークフローテンプレート
ハンズオン環境作成
を実行- mainブランチの定義ファイルに基づいて、ハンズオン環境を構築
- 研修実施後、オペレーターはワークフローテンプレート
ハンズオン環境削除
を実行- mainブランチの定義ファイルに基づいて、ハンズオン環境を削除
仕組み導入後の課題の解決状況
研修で使用するハンズオン環境の準備・片付け
- オペレーターはワンクリックで最新化されたハンズオン環境を受講者の台数分構築できる
- オペレーターはワンクリックで受講者のハンズオン環境を削除できる
受講者からの要望を反映した研修内容の実機検証
- メンテナンス担当は、ワンクリックで以下の項目を確認できる
- 更新した定義ファイルでハンズオン環境が構築できるか
- ハンズオン環境で更新したシナリオが実行できるか
- メンテナンス担当は、ワンクリックで以下の項目を確認できる
- 手動作業による構築のため、作業ミスによって、同じ環境が再現されないことがある
- 定義ファイルはGitで管理するので、検証済みの環境が確実に構築できる
今回の検証でできなかったこと
自動テストの実行トリガーをWebhookにする
もう一つブランチがある想定ですが、
特定のブランチへのマージをトリガーに自動テスト
が実行されるとか仕込んでみたかったんですが、
時間切れで挫折しました。次の機会に挑戦します。生成されるEC2インスタンスのNameタグを連番にする
今回完成したものは、生成されるEC2インスタンスのNameタグはすべて
Ansible-Master
になっています。
これをAnsible-Master01
のように連番にしようと、以下のように試していました。- CloudformationのEC2定義ファイルに生成されるEC2インスタンス共通のタグ
Handson: master
を定義 - インスタンスの
EC2Instances
のソースの有効な変数
にtags.Handson
、有効な値
にmaster
を定義
しかし、この設定だと、対象のEC2インスタンスが絞れず、
AWXサーバーもEC2Instances
に含まれてしまいました。
Nameタグだと絞れるのですが、それ以外のタグだと絞れないようです。
回避方法は時間切れで挫折、妥協案でNameタグを統一することにしました。
2021/02/27追記
上記打消し線の事象はAWX17.0.1では解消されていました。
Nameタグ以外のタグでも絞れるようになってます。
バグだったのかな。。- CloudformationのEC2定義ファイルに生成されるEC2インスタンス共通のタグ
おわりに
少々課題が残りましたが、
Git連携・AWS連携・SURVEY・ユーザー権限の設定など、
AWXの機能を活かした検証ができたので、楽しかったです。
参考
Playbook作成
構文チェック関連
AWX
考え方など