$30 off During Our Annual Pro Sale. View Details »

泣きながらPacker/Ansible provisionerでつくるWindows AMI

泣きながらPacker/Ansible provisionerでつくるWindows AMI

July Tech Festa 2019で発表した「[B10] 泣きながらAWS CodeBuidとPacker/Ansible provisionerでつくるWindows AMI」のセッションスライドです。

https://2019.techfesta.jp/speakers#B20

Masataka Tsukamoto

December 08, 2019
Tweet

More Decks by Masataka Tsukamoto

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  5. これをしました。
    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

    View Slide

  6. これをしました。
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. これをしました。
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. 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⾏で⼊⼒

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  31. 紹介するファイル⼀覧
    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にて
    配布している。

    View Slide

  32. 紹介するファイル⼀覧
    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

    View Slide

  33. 紹介するファイル⼀覧
    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

    View Slide

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

    View Slide

  35. 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 を呼び出している。

    View Slide

  36. 紹介するファイル⼀覧
    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

    View Slide

  37. 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

    View Slide

  38. 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 をつけ
    て実⾏している。

    View Slide

  39. 紹介するファイル⼀覧
    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

    View Slide

  40. 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を流す際などは時間が余計にかかるので
    必要に応じて設定すると吉。

    View Slide

  41. 紹介するファイル⼀覧
    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

    View Slide

  42. 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

    View Slide

  43. 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」を指定している。

    View Slide

  44. 紹介するファイル⼀覧
    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

    View Slide

  45. 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/

    View Slide

  46. 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イメージで、上記の条件にマッチするものの
    うち、最新のものを選択するようにフィルタリングしている。

    View Slide

  47. 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を元に作成さ
    れたかなどを情報として埋め込んでいる。

    View Slide

  48. 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は後ほど
    定義するユーザ変数を参照させている。

    View Slide

  49. 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上でコマンドを
    実⾏させている。
    こちらの内容詳細は後述する。

    View Slide

  50. 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のプレイブックを実⾏させて
    いる。この部分の詳細は後述する。

    View Slide

  51. 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⽇に延⻑している。

    View Slide

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

    View Slide

  53. 紹介するファイル⼀覧
    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

    View Slide

  54. 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

    View Slide

  55. 紹介するファイル⼀覧
    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

    View Slide

  56. 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: '⾼パフォーマンス'

    View Slide

  57. 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

    View Slide

  58. 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サービスの起動設定は機能インストール後、
    ⼀度再起動を経てからじゃないと設定できないので、
    別のプレイブックにタスクを記述し、再起動後に実
    ⾏する

    View Slide

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

    View Slide

  60. 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

    View Slide

  61. 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⾏で⼊⼒

    View Slide

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

    View Slide

  63. 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イ
    ンスタンスに割り当てる。

    View Slide

  64. 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を選択し、権限ポ
    リシーとしてこの内容を指定する。

    View Slide

  65. 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インスタン
    ス内に保存させる。

    View Slide

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

    View Slide

  67. 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のプレイブックを実⾏させて
    いる。

    View Slide

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

    View Slide

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

    View Slide

  70. ほかにも
    こんな
    素敵♡な
    地獄が
    たくさん。
    • そもそも情報が少ない。
    – ⽇本語だけじゃなく英語も。
    • 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...

    View Slide

  71. View Slide

  72. View Slide

  73. View Slide

  74. View Slide

  75. あれ?
    もういらない…?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  80. ಛʹͳ͠ʂ
    80

    View Slide

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

    View Slide

  82. ஥͕ؒ
    ཉ͍͠ʂ
    82

    View Slide

  83. ஥͕ؒ
    ཉ͍͠ʂ
    83
    あと

    View Slide

  84. ങͬͯ
    Ͷʂ
    84

    View Slide

  85. ങͬͯ
    Ͷʂ
    85
    つまり

    View Slide

  86. 86

    View Slide

  87. 87
    さいごに

    View Slide

  88. ϝΨω͸
    ͍͍ͧʂ
    88

    View Slide

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

    View Slide

  90. またな︕

    View Slide