Slide 1

Slide 1 text

泣きながら! AWS CodeBuidと Packer/Ansible provisionerで つくるWindows AMI _・)つかまん(塚本 正隆) 日本ヒューレット・パッカード株式会社 Pointnext HybridIT Practice http://bit.ly/JTF2019-B20

Slide 2

Slide 2 text

誰? • 名前:_・) つかまん (@tsukaman) • 仕事:HPE / Pointnext Hybrid IT Practice • 役割:Cloud Solution Architect、打楽器 • 書籍:Ansible実践ガイド 第3版、Raspberry Pi〔実用〕入門 • 好き:せがれいじり、ガジェットIYH、眼鏡、楽しいこと • 参加:Cloud Native Days Tokyo、 RancherJP、Tokyo HackerSpace 他 • 最近:合気道で白帯脱出しました(まだ茶帯) 2

Slide 3

Slide 3 text

なにしたの︖ ま ず は 出 来 上 が っ た も の を 紹 介 3

Slide 4

Slide 4 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image 4

Slide 5

Slide 5 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image 流れ コードを書いてPRすると⼀旦CodeBuild上でPacker のValidationが⾛ります。結果が問題なさそうだっ たらPRをMergeします。そうするとCodeBuild上で PackerによりAMI作成までの⾃動処理が流れます。 処理が終わるまで珈琲を飲みます。 5

Slide 6

Slide 6 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image Github コードリポジトリとして、CodeBuild や Packer が 使う各種ファイルの管理を⾏う。 Ansible や PowerShell など、Packer が使う各 Provisioner の コードも併せて管理する。Pull Request や Merge を契機に WebHook にて CodeBuild へ通知する。 6

Slide 7

Slide 7 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image AWS CodeBuild 予め定義した内容に従い、⾃動処理を⾏う。今回 はGitHubからのWebHookを契機に、カスタマイズ Dockerイメージからコンテナを起動し、その中で Packerの処理を実⾏する。AWSを利⽤する場合は、 安価で柔軟性も⾼く、使いやすい⾃動化ツール。 7

Slide 8

Slide 8 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image Docker(カスタムイメージ) CodeBuildの⾃動処理では、実⾏環境としてDocker コンテナを利⽤する。処理の内容に合わせて、利 ⽤するDockerイメージを指定するが、今回は Windowsに対して⾏う処理内容に併せて、必要な ツール群を配置したカスタムイメージを⽤意。 8

Slide 9

Slide 9 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image Packer HachiCorp社が中⼼に開発をしているOSS。各IaaS 基盤や仮想化環境に合わせたマシンイメージを コードから⾃動⽣成することができる。イメージ のカスタマイズにはProvisionerと呼ばれる様々な コンポーネントを組み合わせることが可能。 9

Slide 10

Slide 10 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image Provisioner Packerでカスタムイメージを作成する際に、ベー スとなるインスタンスに対して様々な処理をする ためのコンポーネント。処理の内容やお好みの定 義⽅法に合わせてツールを選択できる。今回は Ansible、PowerShell、Windows Shell、Fileを利⽤。 10

Slide 11

Slide 11 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image AWS EC2 / EBS 泣く⼦も黙るPublic Cloud界の重鎮であるAWS様に よる仮想サーバおよび仮想ボリュームを提供する サービス。EC2ではサーバインスタンスの起動に、 ベースとなるAMIを利⽤するが、今回はカスタマ イズしたWindows AMIをPackerで作るよ︕って話。 11

Slide 12

Slide 12 text

これをしました。 PowerShell AMI Instance Snapshot EBS EC2 AWS CodeBuild Provisioner PR/Merge Web Hook Run Custom Image 社畜(私) 泣く⼦。この仕組みを作るため、夜なべを繰り返 しながら⾃動処理が流れては死んでいくのを⽣暖 かく⾒守るというお仕事をする。⾃分でPRして⾃ 分でMergeするという作業を200回くらいやってた。 仕組みが出来た後は、他者に引き継いで去る⼈。 12

Slide 13

Slide 13 text

動かす こ い つ ・ ・ ・ 動 く ぞ ︕ ( た ぶ ん ) 13

Slide 14

Slide 14 text

動かす こ い つ ・ ・ ・ 動 く ぞ ︕ ( た ぶ ん ) 14 デモ

Slide 15

Slide 15 text

内容の紹介 使 っ た コ ー ド や 設 定 と か 15

Slide 16

Slide 16 text

カスタム Dockerイメージ • CodeBuildの⾃動処理で利⽤するDockerイメージ – CodeBuildが提供するマネージドのイメージもある • この場合、必要なツールは処理の都度インストールすることになる – 必要な処理に併せたイメージを事前に⽤意することもできる • 処理時間を短縮したい場合は⽤意した⽅が無難 • イメージはアクセス出来る場所ならどこで保管しても良い – DockerHubやAmazon ECRなど、任意のDockerレジストリを利⽤可 – レジストリの認証情報を設定することも可能 • 今回利⽤しているDockerイメージはDockerHubで公開中 – https://hub.docker.com/repository/docker/tsukaman/jtf2019-packer- ansible-docker-image 16

Slide 17

Slide 17 text

Dockerfile https://github.com /tsukaman /jtf2019-packer-ansible-docker-image FROM ansible/ansible-runner:1.3.4 ENV PACKER_VERSION 1.4.5 WORKDIR /usr/local/bin RUN set -x && ¥ yum install -y https://centos7.iuscommunity.org/ius-release.rpm && ¥ yum update -y --exclude='ansible*' && ¥ yum install -y jq python2-pip tree unzip wget && ¥ rm -rf /var/cache/yum/* && yum clean all && ¥ wget -q https://releases.hashicorp.com/packer/${PACKER_VERSION}/ packer_${PACKER_VERSION}_linux_amd64.zip && ¥ unzip ./packer_${PACKER_VERSION}_linux_amd64.zip && ¥ rm ./packer_${PACKER_VERSION}_linux_amd64.zip && ¥ pip install --upgrade pip && ¥ pip install awscli boto pywinrm 17 1⾏で⼊⼒

Slide 18

Slide 18 text

AWS CodeBuildの Build Project • CodeBuildでは⾃動処理単位として「Build Project」を作成する • AWSコンソールのほか、AWS CLIやTerraformでも設定が可能 • Build Projectの設定前にやっておく準備の例 – ⾃動処理で利⽤するDockerコンテナイメージ – GithubのRepositoryの作成 – SystemsManagerのパラメータストアへ機密情報の登録 • パラメータストアでは機密情報を暗号化して保管が可能 – CodeBuildからはこの値を安全に実⾏環境コンテナへ引き渡せる • GitHubでコード化したくない情報を登録すると良い – Ansible vaultのパスワードとか 18

Slide 19

Slide 19 text

AWS Systems Managerの パラメータストア 19

Slide 20

Slide 20 text

AWS Systems Managerの パラメータストア 20 ここで⼊⼒する名前 は、CodeBuildの変数 定義で⼊⼒するので、 覚えておく。

Slide 21

Slide 21 text

AWS Systems Managerの パラメータストア 21 暗号化させたい場合 は「安全な⽂字列」 を選択し、値を⼊⼒ する。保管時はKMS キーによって暗号化 される。

Slide 22

Slide 22 text

AWS CodeBuildの ビルドプロジェクト 22 続いて、CodeBuildで のBuild Project新規作 成。まずは名前、説 明、タグ情報などを ⼊⼒する。

Slide 23

Slide 23 text

AWS CodeBuildの ビルドプロジェクト 23 送信元では、今回は OAuth連携した Githubのリポジトリ を指定。クローンの 深さをFullとし、ビ ルドステータスレ ポートも有効化。

Slide 24

Slide 24 text

AWS CodeBuildの ビルドプロジェクト 24 Web Hookから移動 実⾏する内容を指定。 柔軟な設定が可能。 今回はPRの作成/更 新/リオープンおよ びmasterへのプッ シュを契機に実⾏さ せる。

Slide 25

Slide 25 text

AWS CodeBuildの ビルドプロジェクト 25 処理の実⾏環境とな るコンテナ情報を指 定。今回は前述した DockerHub上のコン テナイメージを指定 している。

Slide 26

Slide 26 text

AWS CodeBuildの ビルドプロジェクト 26 実⾏コンテナに付与す るサービスロールを選 択する。今回はデフォ ルトのまま、ロールを 新規作成させて、あと から必要な権限をIAMで 追加する。 その他の項⽬はデフォ ルトで良い。

Slide 27

Slide 27 text

AWS CodeBuildの ビルドプロジェクト 27 コンテナ内の環境変数を定義する。 ここではパラメータストアで作成 した値を参照させている。その他 のものはデフォルトで良い。

Slide 28

Slide 28 text

AWS CodeBuildの ビルドプロジェクト 28 キャッシュは指定し なくても動作上は問 題ないが、指定する と⼀部の動作が⾼速 化する。

Slide 29

Slide 29 text

AWS CodeBuildの ビルドプロジェクト 29 ログの出⼒先として Cloud Watch Logsを指 定し、グループ名/ス トリーム名を指定す る。実⾏結果を確認 する為にも、設定す ると良い。

Slide 30

Slide 30 text

AWS IAM ロールの 権限ポリシー追加 30 ⾃動作成されたサービスロー ルへ権限ポリシーを追加する。 今回は 「AmazonEC2FullAccess」と 「IAMFullAccess」を追加する。

Slide 31

Slide 31 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 31 “packer.py” はPackerがWindowsインスタンスに対してAnsibleで処理を⾏う 為に必要なプラグインスクリプト。PackrのGithubにて配布している。 “ConfigureRemotingForAnsible.ps1” はWindowsがAnsibleの接続を受け付け る為に必要な設定を⾏う為のPowerShellスクリプト。AnsibleのGithubにて 配布している。

Slide 32

Slide 32 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 32 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 33

Slide 33 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 33 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 34

Slide 34 text

AWS CodeBuildの buildspec.yml • CodeBuildではどのような処理を⾏うかの内容を buildspec.yml で 定義することができる – ソースコードリポジトリのルートディレクトリに配置する • 配置場所やファイル名は違うものを指定することも可能 – このファイルの代わりに直接ビルドコマンドを定義することもで きる • YAML形式で様々な設定を柔軟に⾏える – 変数定義やフェーズ毎の細かい処理内容などを定義できる – https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec- ref.html 34

Slide 35

Slide 35 text

buildspec.yml version: 0.2 phases: install: commands: - ansible –version - packer --version - aws --version build: commands: - echo "$VAULT_PASS" > vault_password_file - /bin/sh scripts/run.sh 35 やっていることは⾮常にシンプル。 事前処理で各ソフトウェアのバージョンを出⼒。 実処理ではAnsibleVault⽤のパスワードファイルを 環境変数(パラメータストアの値から定義したア レ)から作成し、その後 run.sh を呼び出している。

Slide 36

Slide 36 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 36 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 37

Slide 37 text

run.sh #!/bin/sh -xe if echo ${CODEBUILD_SOURCE_VERSION} | grep -q 'pr/ʼ ; then /bin/sh scripts/validate.sh else /bin/sh scripts/build.sh fi 37 run.sh では、CodeBuildが⾃動的に設定する環境変数 「CODEBUILD_SOURCE_VERSION」に「pr/」が含まれるかどうかで実⾏する シェルスクリプトを切り替え。Pull-Reqの場合のみ、pr/が含まれる。 この処理はmixiのSREであるIsao Shimizu⽒の記事を参考に実装。 参考︓Terraform どこで実⾏していますか︖|Medium https://medium.com/mixi-developers/terraform-on-aws-codebuild-44dda951fead

Slide 38

Slide 38 text

build.sh #!/bin/sh -xe packer validate packer.json 38 #!/bin/sh -xe mkdir /etc/ansible cp -f ${CODEBUILD_SRC_DIR}/files/ansible.cfg /etc/ansible/ansible.cfg packer build -color=false packer.json validate.sh PRかPush/Mergeかで、packerのサブコマ ンドが変わる。 なおbuildにおいては、CodeBuildのログ コンソールがカラーコードを上⼿く処 理/表⽰できないため -color=false をつけ て実⾏している。

Slide 39

Slide 39 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 39 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 40

Slide 40 text

ansible.cfg [defaults] gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/facts_cache # two hours timeout fact_caching_timeout = 7200 40 また、packer buildの実⾏の前処理として、/etc/ansible にコピーしていた ansible.cfg はfactキャッシュさせる為のカスタマイズ。 なくても良いが、複数のPlaybookを流す際などは時間が余計にかかるので 必要に応じて設定すると吉。

Slide 41

Slide 41 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 41 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 42

Slide 42 text

Packerテンプレート ( JSON形式 ) • Packerでどのようなマシンイメージを作成するかを 定義したJSON形式のファイル – ファイル名は任意につけることができる(今回は packer.json ) – builders、description、min_packer_version、post-processors、 provisioners、variables のセクションで細かく定義が可能 • 必須セクションは builders のみで残りはオプション • 今回、特に重要なのが builders と provisioners – https://www.packer.io/docs/templates/index.html 42

Slide 43

Slide 43 text

packer.json (1) { "builders": [ { "ami_description": "Windows 2016 AMI image created by Packer", "ami_name": "packer-win2016-{{timestamp | clean_resource_name}}", "iam_instance_profile": "packer-ec2-role", "instance_type": "t3.medium", "vpc_id": "vpc-XXXXXXXXXXXXXXX”, "subnet_id": "subnet-XXXXXXXXXX", "region": "ap-northeast-1", "type": "amazon-ebs", "user_data_file": "win-userdata.txt", "communicator": "winrm", "winrm_username": "Administrator", 43 buildersセクションでは、作成す るAMIに関する設定や、AMIの元 となるEC2インスタンスに関係す るパラメータを指定する。 また、今回はWindowsを利⽤する ので、コミュニケーターに 「WinRM」を指定している。

Slide 44

Slide 44 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 44 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 45

Slide 45 text

win-userdata.txt winrm quickconfig -q winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}' winrm set winrm/config '@{MaxTimeoutms="1800000"}' winrm set winrm/config/service '@{AllowUnencrypted="true"}' winrm set winrm/config/service/auth '@{Basic="true"}' netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow net stop winrm sc config winrm start=auto net start winrm Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine 45 1⾏ずつで⼊⼒ インスタンス起動時の実⾏スクリプト(PowerShell)で、 WinRM通信が出来るように設定している。 参考︓PackerでWindows Server 2016のAMIを作成してみた https://dev.classmethod.jp/cloud/aws/packer-winsrv2016-createami/

Slide 46

Slide 46 text

packer.json (2) "source_ami_filter": { "filters": { "virtualization-type": "hvm", "name": "*Windows_Server-2016-Japanese-Full-Base-*", "root-device-type": "ebs" }, "owners": "amazon", "most_recent": true }, 46 カスタムAMIの元となるEC2インスタンスを、どのAMIから起動させるかの 設定。今回は、Windows2016イメージで、上記の条件にマッチするものの うち、最新のものを選択するようにフィルタリングしている。

Slide 47

Slide 47 text

packer.json (3) "tags": { "Base_AMI_Name": "{{ .SourceAMIName }}", "Extra": "{{ .SourceAMITags.TagName }}", "Packer": "true", "Release": "Latest" }, "run_tags": { "Packer": "true" }, "run_volume_tags": { "Packer": "true" }, } ], 47 作成されるAMIや、作成中のEC2インスタンス およびEBSボリュームに設定されるTAG情報を 指定している。 カスタマイズAMIは元々どのAMIを元に作成さ れたかなどを情報として埋め込んでいる。

Slide 48

Slide 48 text

packer.json (4) "provisioners": [ { "type": "ansible", "playbook_file": "./ansible/site.yml", "extra_arguments": [ "--connection", "packer", "-v", "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None", "--vault-password-file={{user `vault_path`}}" ] }, 48 1⾏で⼊⼒ ここからProvisionerセクション。作成したEC2インスタンスへのカ スタマイズとして、site.ymlのプレイブックを実⾏している。ansible 実⾏時の引数なども柔軟に指定出来る。vault-password-fileは後ほど 定義するユーザ変数を参照させている。

Slide 49

Slide 49 text

packer.json (5) { "type": "powershell", "inline": [ "mkdir C:¥¥tmp" ] }, { "type": "powershell", "inline": [ "Import-Module -name AWSPowerShell", "Copy-S3Object -BucketName バケット名 -Key ファイル名 - LocalFile C:¥¥tmp¥¥保存ファイル名" ] }, 49 1⾏で⼊⼒ powershell provisionerにより、EC2上でコマンドを 実⾏させている。 こちらの内容詳細は後述する。

Slide 50

Slide 50 text

packer.json (6) { "type": "windows-restart", "restart_check_command": "powershell -command ¥"& {Write- Output 'restarted.'}¥"" }, { "type": "ansible", "playbook_file": "./ansible/after_reboot.yml", "extra_arguments": [ "--connection", "packer", "-v", "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None", "--vault-password-file={{user `vault_path`}}" ] }, 50 1⾏で⼊⼒ 1⾏で⼊⼒ windows-restart provisionerによりEC2インスタンスを再起動させてい る。また、再起動後にafter_reboot.ymlのプレイブックを実⾏させて いる。この部分の詳細は後述する。

Slide 51

Slide 51 text

packer.json (7) { "type": "file", "source": "powershell/ConfigureRemotingForAnsible.ps1", "destination": "C:¥¥tmp¥¥ConfigureRemotingForAnsible.ps1" }, { "type": "powershell", "inline": [ "C:¥¥tmp¥¥ConfigureRemotingForAnsible.ps1 -SkipNetworkProfileChec -CertValidityDays 3650", "rm C:¥¥tmp -Recurse" ] }, 51 1⾏で⼊⼒ HTTPS経由でAnsibleを実⾏させる為のセットアップスクリプトを配 置して実⾏させている。また、このスクリプトが⾃動作成する⾃⼰ 署名証明書の有効期限を3650⽇に延⻑している。

Slide 52

Slide 52 text

packer.json (8) { "type": "powershell", "scripts": [ "powershell/sysprep.ps1" ] } ], "variables": { "vault_path": "vault_password_file" } } 52 処理の最後にsysprepを実⾏させる PowerShellスクリプトをpowershell provisionerで実⾏している。 この部分では、前述のユーザ変 数”vault-path”を定義している。

Slide 53

Slide 53 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 53 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 54

Slide 54 text

sysprep.ps1 C:¥ProgramData¥Amazon¥EC2- Windows¥Launch¥Scripts¥InitializeInstance.ps1 –Schedule C:¥ProgramData¥Amazon¥EC2- Windows¥Launch¥Scripts¥SysprepInstance.ps1 54 1⾏で⼊⼒ 1⾏で⼊⼒ AWSで提供されるWindows2016 AMI内で⽤意されている、初 期化スクリプトを実⾏している。 参考︓Amazon EC2 Windows インスタンス⽤ユーザーガイド | Sysprep と EC2Launch の使⽤ https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ ec2launch.html#ec2launch-sysprep

Slide 55

Slide 55 text

紹介するファイル⼀覧 https://github.com/tsukaman /jtf2019-packer-ansible-aws ├ README.md ├ ansible │ ├ after_reboot.yml │ ├ connection_plugins │ │ └ packer.py │ └ site.yml ├ buildspec.yml ├ files │ └ ansible.cfg [ 右へ続く ] [ 左からの続き ] ├ packer.json ├ powershell │ ├ ConfigureRemotingForAnsible.ps1 │ └ sysprep.ps1 ├ scripts │ ├ build.sh │ ├ run.sh │ └ validate.sh └ win-userdata.txt 55 • ConfigureRemotingForAnsible.ps1 の⼊⼿先 https://github.com/ansible/ansible/blob/devel/examples/ scripts/ConfigureRemotingForAnsible.ps1 • packer.py の⼊⼿先 https://github.com/hashicorp/packer/blob/master/examples/ ansible/connection-plugin/2.6.x/packer.py

Slide 56

Slide 56 text

site.yml (1) --- - hosts: all tasks: - name: Ensure local user for ansible is present win_user: name: ansible fullname: ansible description: 'Ansible⽤ユーザ' password: '@nsible01' password_never_expires: yes state: present groups: - Administrators - name: Disable password expirartion win_security_policy: section: System Access key: MaximumPasswordAge value: -1 56 - name: Disable password complexity req win_security_policy: section: System Access key: PasswordComplexity value: 0 - name: Set Allowed user for shutdown win_user_right: name: SeShutdownPrivilege users: - Administrators action: set - name: Change power plan to high performance win_power_plan: name: '⾼パフォーマンス'

Slide 57

Slide 57 text

site.yml (2) - name: Disable Windows Firewall win_firewall: state: disabled profiles: - Domain - Private - Public - name: Install SNMP service win_feature: name: SNMP-Service include_management_tools: yes include_sub_features: yes state: present 57

Slide 58

Slide 58 text

after_reboot.yml - hosts: all tasks: - name: Set startup mode to auto and ensure it is started win_service: name: SNMP start_mode: auto state: started 58 SNMPサービスの起動設定は機能インストール後、 ⼀度再起動を経てからじゃないと設定できないので、 別のプレイブックにタスクを記述し、再起動後に実 ⾏する

Slide 59

Slide 59 text

おもひで 何 が 私 を 泣 か せ た の か 59

Slide 60

Slide 60 text

Ansibleのバージョンが 新しすぎる場合に死ぬ • Packer/Ansible Provisionerを使ってWindows2016のAMIを 作成する場合、Ansible2.8を使うと謎のエラーで死ぬ – Windows2016以外でもダメかも知れない(未検証) – そのうち直ると思うけど、12⽉2⽇現在でIssueはOpenのまま – 2.7.10なら動くという報告がIssueのDiscussionスレッドにある • 私は何をしたか︖ – Dockerイメージのベースであるansible-runnerのTAG指定 • ansible-runner:1.3.4ではAnsibleは2.7.10 • yum updateをウッカリかけると最新バージョンになるので注意 – yum update -y --exclude=ʻansible*ʻ みたいにしよう 60

Slide 61

Slide 61 text

Dockerfile https://github.com /tsukaman /jtf2019-packer-ansible-docker-image FROM ansible/ansible-runner:1.3.4 ENV PACKER_VERSION 1.4.5 WORKDIR /usr/local/bin RUN set -x && ¥ yum install -y https://centos7.iuscommunity.org/ius-release.rpm && ¥ yum update -y --exclude='ansible*' && ¥ yum install -y jq python2-pip tree unzip wget && ¥ rm -rf /var/cache/yum/* && yum clean all && ¥ wget -q https://releases.hashicorp.com/packer/${PACKER_VERSION}/ packer_${PACKER_VERSION}_linux_amd64.zip && ¥ unzip ./packer_${PACKER_VERSION}_linux_amd64.zip && ¥ rm ./packer_${PACKER_VERSION}_linux_amd64.zip && ¥ pip install --upgrade pip && ¥ pip install awscli boto pywinrm 61 1⾏で⼊⼒

Slide 62

Slide 62 text

ファイル転送が 死ぬほど遅いので死ぬ • WinRMを利⽤している場合、そもそもファイル転送速度が遅い – ⾮常に転送速度が遅いので⼤きなファイルの転送は避ける – Ansibleのwin_copyモジュールのドキュメントにも⾔及あり • 「Webサーバでホストし、ターゲットにダウンロードさせろ」 – openSSHを使った通信も試験的に導⼊されたが私は未検証 • 私は何をしたか︖ – ⾃動処理の中でWebサーバを建てるという⾏為が微妙だった – AWS環境なのでS3 Bucketに巨⼤ファイルを置くことにした – ターゲットからはPowerShell for AWSでダウンロードさせる • S3にアクセスできるようにEC2 Roleの仕組みを使う 62

Slide 63

Slide 63 text

packer.json (1) { "builders": [ { "ami_description": "Windows 2016 AMI image created by Packer", "ami_name": "packer-win2016-{{timestamp | clean_resource_name}}", "iam_instance_profile": "packer-ec2-role", "instance_type": "t3.medium", "vpc_id": "vpc-XXXXXXXXXXXXXXX” "subnet_id": "subnet-XXXXXXXXXX", "region": "ap-northeast-1", "type": "amazon-ebs", "user_data_file": "win-userdata.txt", "communicator": "winrm", "winrm_username": "Administrator", 63 S3 バケットからファイルのダウ ンロードをさせる為に、特定のS3 Bucket内のファイルを読み取るこ とができるRoleを作成し、EC2イ ンスタンスに割り当てる。

Slide 64

Slide 64 text

Roleに割り当てる ポリシー(例) { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "s3:List*", "s3:Get*" ], "Resource": [ "arn:aws:s3:::バケット名/*", "arn:aws:s3:::バケット名" ] }, 64 { "Sid": "", "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*" } ] } Role作成時は、信頼するエンティ ティとしてEC2を選択し、権限ポ リシーとしてこの内容を指定する。

Slide 65

Slide 65 text

packer.json (5) { "type": "powershell", "inline": [ "mkdir C:¥¥tmp" ] }, { "type": "powershell", "inline": [ "Import-Module -name AWSPowerShell", “Copy-S3Object -BucketName バケット名 -Key ファイル名 - LocalFile C:¥¥tmp¥¥保存ファイル名" ] }, 65 1⾏で⼊⼒ ポリシーで許可したS3バケット内にダウンロード させたいファイルを置き、それをEC2インスタン ス内に保存させる。

Slide 66

Slide 66 text

win_rebootを使うと packerの処理が死ぬ • カスタマイズ内容によっては再起動が必要なケースがある – サービスやアプリケーションのインストール、レジストリの変更 など、再起動しないと反映されない項⽬がある – 新規サービスの起動設定をする場合、再起動が必要になった – Ansibleには再起動を⾏うModuleがあるが、安直に使うべからず • 再起動後にセッションが復帰せず、Packer処理がTimeoutする • 私は何をしたか︖ – そもそもPackerに、インスタンスを再起動する為の仕組み (windows-restart provisioner)が⽤意されている – Ansibleにこだわりすぎないで、他の⼿段にも⽬を向ける • 特にPowerShellはWindowsではほぼ最強・・・。 66

Slide 67

Slide 67 text

packer.json (6) { "type": "windows-restart", "restart_check_command": "powershell -command ¥"& {Write- Output 'restarted.'}¥"" }, { "type": "ansible", "playbook_file": "./ansible/after_reboot.yml", "extra_arguments": [ "--connection", "packer", "-v", "--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None", "--vault-password-file={{user `vault_path`}}" ] }, 67 1⾏で⼊⼒ 1⾏で⼊⼒ windows-restart provisionerによりEC2インスタンスを再起動させてい る。また、再起動後にafter_reboot.ymlのプレイブックを実⾏させて いる。

Slide 68

Slide 68 text

sysprepで初期化される 項⽬がでて死ぬ • 作成するのはGolden ImageなのでSIDなどの初期化が必要 – AWSのWindows AMIはsysprepを実⾏する仕組みが⽤意される – ただし、Sysprep実⾏により初期化される設定がある • ライセンス情報、Administratorユーザ情報、Networkアダプタ情報、 Windows Firewall設定など – 尚、この件、調査してくれたのは同僚で私ではない・・・(ありがたや • 私は何をしたか︖ – 巻き戻るものは仕⽅がないので、EC2インスタンス作成時または 作成後にこれらの設定がされるようにした • user-dataでの設定と、ansible-playbook実⾏を併⽤ • PackerでAnsibleを使うため、Ansibleの為の設定がほぼ出来ている という点はメリットと⾔える 68

Slide 69

Slide 69 text

ほかにも こんな 素敵♡な 地獄が たくさん。 • そもそも情報が少ない。 – ⽇本語だけじゃなく英語も。 • Windows Moduleが少ない。 – 2.8で対応になったものもあるが・・・。 • 結局PowerShell頼みになるケースも。 – Ansibleを使う意味を⾒失いそうに。 • レジストリ編集しか⽅法がないことも。 – Ansibleを使う意m(ry • カスタマイズ指⽰がGUIベース。 – 「チェックボックスを外す」「お、おう」 • デバッグがつろい。原因 is どこ。 – Packer?Ansible?CodeBuild?いいえケf(ry • ケチってインスタンスを低スペックで起動し死ぬ。 – 特にメモリがしょぼいとすぐAnsibleがエラーに。 • 私のWindows⼒、PowerShell⼒が低い。 – Apple信者ゆえ・・・。ゆるして・・・。 • ノリノリでJTFのCFPだしたけど仕事が⼤炎上 – これは⾃業⾃得(なのかな・・・) 69

Slide 70

Slide 70 text

ほかにも こんな 素敵♡な 地獄が たくさん。 • そもそも情報が少ない。 – ⽇本語だけじゃなく英語も。 • Windows Moduleが少ない。 – 2.8で対応になったものもあるが・・・。 • 結局PowerShell頼みになるケースも。 – Ansibleを使う意味を⾒失いそうに。 • レジストリ編集しか⽅法がないことも。 – Ansibleを使う意m(ry • カスタマイズ指⽰がGUIベース。 – 「チェックボックスを外す」「お、おう」 • デバッグがつろい。原因isどこ。 – Packer?Ansible?CodeBuild?いいえケf(ry • 私のWindows⼒、PowerShell⼒が低い。 – Apple信者ゆえ・・・。ゆるして・・・。 • やってることが変態(ドM)すぎて仲間が居ない。 – PR/Mergeを1⼈でやる意味(時間かかるんじゃ) 70 One More Thing...

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

あれ? もういらない…?

Slide 76

Slide 76 text

待て︕ まだ慌てる時間じゃない︕ • Packerのいいところ – AWS以外のイメージも作れるよ︕ – ちまたに情報が結構あるよ(ただし悪魔合体させなければ) – Ansibleが使える = 学習コストが低い・・・かも︕ – 使えるベースイメージも幅広く柔軟性が⾼い︕ • EC2 Image Builderのいいところ – AWS公式ツールの安⼼感 – マネージドサービスですぐ使える&基本無料 – AWSサービスとの連携が充実(S3とかIAMとか) – 更新やテストなどの痒いところに⼿が届く機能も実装 76

Slide 77

Slide 77 text

待て︕ まだ慌てる時間じゃない︕ • Packerのいいところ – AWS以外のイメージも作れるよ︕ – ちまたに情報が結構あるよ(ただし悪魔合体させなければ) – Ansibleが使える = 学習コストが低い・・・かも︕ – 使えるベースイメージも幅広く柔軟性が⾼い︕ • EC2 Image Builderのいいところ – AWS公式ツールの安⼼感 – マネージドサービスですぐ使える&基本無料 – AWSサービスとの連携が充実(S3とかIAMとか) – 更新やテストなどの痒いところに⼿が届く機能も実装 77 選択肢を増やし 状況に応じて 使い分ける!

Slide 78

Slide 78 text

SH A RE! MY ENGINEERING CU LT U RE 78 ま と め

Slide 79

Slide 79 text

中 年 の 主張 そ れ で は お 聴 き く だ さ い 79

Slide 80

Slide 80 text

ಛʹͳ͠ʂ 80

Slide 81

Slide 81 text

ಛʹͳ͠ʂ 81 強いて 言えば

Slide 82

Slide 82 text

஥͕ؒ ཉ͍͠ʂ 82

Slide 83

Slide 83 text

஥͕ؒ ཉ͍͠ʂ 83 あと

Slide 84

Slide 84 text

ങͬͯ Ͷʂ 84

Slide 85

Slide 85 text

ങͬͯ Ͷʂ 85 つまり

Slide 86

Slide 86 text

86

Slide 87

Slide 87 text

87 さいごに

Slide 88

Slide 88 text

ϝΨω͸ ͍͍ͧʂ 88

Slide 89

Slide 89 text

マジレスすると・・・ • ⼤切にしたいと想っていること –しなやかさ • 変化をおそれず、柔軟に、しかし芯を持つ。 –⾃分らしさ • 死ぬまで考え続けるべき永遠のテーマ。 –おもしろさ • 迷ったときは⾯⽩そうな⽅へ。 89

Slide 90

Slide 90 text

またな︕