GitHubActionsでPacker+Ansibleを使ってイメージを自動ビルドするアクションを作った
はじめに
マシンイメージの自動作成を行うPacker。便利なツールですよね。Packerを使えばコマンド1発でイメージのビルドを行えるのですが、その1発のコマンドでも自動化できたらだいぶ楽になるかなと思いGitHub ActionsでAnsibleのprovisionerに使ったPackerビルドを行う方法を書いていこうと思います。
アプローチ
GitHub Actionsでやっていくにはまずは公式の用意したワークフローを使うのが一般的だと思います。
もちろんPackerにも公式のワークフローが存在しています。
しかし、公式のワークフローだとProvisionarにAnsibleが使えないようです
このissueに書いてある通りansible-playbook
が実行できない感じです。
Packerのワークフローはランナー上のDockerコンテナ上で実行されるので、その中にAnsibleがインストールされてないような感じですね。
ということで、公式のワークフローではAnsibleが使えないようなので、自分でdockerのイメージとアクションを用意していく必要がありそうなので制作していきましょう!
ちなみに、自作のActionについては詳しく知りたい場合は以下の公式ドキュメントを参考にしてください。
今回はDockerコンテナのアクションでPacker+Ansibleのアクションを作成していきます
やり方
まずはディレクトリ構成は以下のような感じです
├── .github
│ └── workflows
│ └── packer.yml
├── Dockerfile
├── action.yml
├── entrypoint.sh
└── packer
├── packer.json
└── roles
Dockerイメージの用意
まずはDockerfileを書いていきます。
やってることはdebianのベースイメージを使って、PackerとAnsiblenのインストールをしています。
インストールについてはこちらの公式ドキュメントを参考にしています。
FROM debian:buster-slim
RUN apt update
RUN apt -y upgrade
RUN apt -y install gnupg
RUN apt -y install curl
RUN apt -y install software-properties-common
# Install Packer
RUN curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
RUN apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
RUN apt update && apt -y install packer
# Install Ansible
RUN echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
RUN apt update && apt -y install ansible
COPY "entrypoint.sh" "/entrypoint.sh"
ENTRYPOINT ["/entrypoint.sh"]
action.ymlの用意
GitHub Actionsでは自身が定義したアクションを実行したい際には、action.ymlを作成する必要があります。
やっていることとしては、inputでcommandとworking_directoryの2つの入力を受け取って、先ほど用意したDockerアクションを実行するためにrunsでDockerfileを設定しています。
action.ymlについての詳細は公式ドキュメントに詳しく書いてあります。
# action.yml
name: 'Packer Build'
description: 'Automatic build with Packer'
inputs:
command:
description: 'input command'
required: true
working_directory:
description: working directory for command (defaults to root)
required: false
runs:
using: 'docker'
image: 'Dockerfile'
entrypoint.shの用意
entrypoint.shは以下のようになってます。
やってることとしては、先程のaction.ymlのinputで定義したcommandとworking_directoryで得られた入力によってINPUT_COMMAND
とINPUT_WORKING_DIRECTORY
という環境変数が生成されるため、
必須の入力項目であるcommandがなければエラーを吐いて終了。ある場合はworking_directoryで指定されたディレクトリへCDして、コマンドの実行しています。
#!/usr/bin/env bash
set -e
# fail if INPUT_COMMAND is not set
if [ -z "${INPUT_COMMAND}" ]; then
echo "Required variable \`command\` is missing"
exit 1
fi
if [ -n "${INPUT_WORKING_DIRECTORY}" ]; then
cd "${INPUT_WORKING_DIRECTORY}"
fi
${INPUT_COMMAND}
workflows/packer.yml
いよいよワークフローファイルについてです
以下のような感じになっています。
uses:./
にすることで先ほど作成したaction.ymlを実行するようになっています。
あとは、commandとworking_directoryで実行したいコマンドとディレクトリを指定します。
コマンドをそのまま渡す形式にしているためvalidateコマンドなどで構文チェックなども可能です。
with:
command: packer build packer.json
working_directory: ./packer
このワークフローだとon
がworkflow_dispatch
になっているため手動で実行されるようになっています。
この部分はPRがマージされた時などいろいろ設定できるので好きなように変更するといいと思います。
name: Packer Build
on:
workflow_dispatch:
jobs:
packer:
runs-on: ubuntu-latest
name: packer
steps:
- uses: actions/checkout@v2
- name: Packer Validate
uses: ./
with:
command: packer validate -syntax-only packer.json
working_directory: ./packer
- name: Packer Build
uses: ./
with:
command: packer build packer.json
working_directory: ./packer
実行してみる
workflow_dispatch
であればGitHubのリポジトリのタブからActionsを選択して
Select Workflow
から先ほど作成したPacker Build
を選択
Run workflow
で実行が可能です。
実行してこんな感じでstepの横にチェックマークがついてたら成功です。
まとめ
これでGitHub Actions上でAnsibleを使ったPackerビルドができるようになると思います。
今後は、公式のワークフローでもできるようになればいいなぁと思ってます!
あと、今回作ったコンテナ上でコマンドを実行するみたいなアクションは汎用性が高いと思うので、このコマンドをGitHub Actionsで使ってみたいけど公式でアクション作ってないなぁみたいな時は、自作も簡単にできるようになるのではと思います。
Discussion