LoginSignup
8
5

More than 3 years have passed since last update.

Packerを使ってAnsibleをDockerイメージにする

Last updated at Posted at 2018-11-27

概要

Packerとは、簡単に言うと、マシンイメージを作成するオーケストレーションツールです。
Dockerイメージや、AWSのAMIを作成することもできます。
Vagrantなどを作っている、hashicorpのツールです。

今回は、このPackerを使って、AnsibleのPlaybookからDockerイメージを作成します。

仕組み

仕組みを簡単に説明すると、Packerでビルド環境を定義し、Packerが立ち上げたDockerコンテナでlocalモードでAnsibleを実行し、出来上がったコンテナをイメージ化するという仕組みになります。

環境

  • CentOS 7.5
  • packer 1.3.2

packerのインストール

以下から環境にあったバイナリをダウンロードします。
https://www.packer.io/downloads.html

Linux環境なので、以下を使います。

$ curl -O https://releases.hashicorp.com/packer/1.3.2/packer_1.3.2_linux_amd64.zip
$ unzip packer_1.3.2_linux_amd64.zip
$ sudo cp packer /usr/local/bin

ディレクトリ構成

後述のpacker.jsonの内容と合わせてご確認いただければと思いますが、こういうディレクトリ構成でpackerの環境を作ります。

.
├── packer.json
├── playbooks/
│   ├── group_vars/
│   ├── roles/
│   ├── site.yml
│   └── inventories
│       ├── group_vars/
│       └── hosts.sample
└── vault-password-file

ビルド環境と内容を定義

ビルド環境と内容をjsonで定義します。
jsonファイルの名前は何でも構いませんが、ここではpackage.jsonとします。

package.json
{
    "builders":[{
        "type": "docker",
        "image": "centos:7",
        "export_path": "controller.tar",
        "privileged": "true",
        "run_command": ["-d", "-i", "-t", "{{.Image}}", "/sbin/init"]
    }],

    "provisioners":[{
        "type": "shell",
        "inline": [
            "yum clean all",
            "yum -y install epel-release",
            "yum -y install PyYAML",
            "yum -y install python-jinja2",
            "yum -y install python-httplib2",
            "yum -y install python-paramiko",
            "yum -y install python-setuptools",
            "yum -y install ansible",
            "mkdir -p /tmp/ansible-local"
        ]
    }, {
        "type": "file",
        "source": "playbooks/",
        "destination": "/tmp/ansible-local"
    }, {
        "type": "file",
        "source": "vault-password-file",
        "destination": "/tmp/ansible-local/vault-password-file.txt"
    }, {
        "type": "ansible-local",
        "playbook_file": "playbooks/site.yml",
        "staging_directory": "/tmp/ansible-local",
        "extra_arguments": [
            "-i /tmp/ansible-local/inventories/hosts.sample",
            "--vault-password-file=/tmp/ansible-local/vault-password-file.txt"
        ],
        "clean_staging_directory": true
    }],

    "post-processors": [{
        "type": "docker-import",
        "repository": "myname/image_name",
        "tag": "0.1"
    }]
}

内容を簡単に説明します。

package.json
{
    # Ansibleを実行するDocker環境を定義します。docker-composeと大体同じです。
    "builders":[{
        "type": "docker",
        "image": "centos:7",
        "export_path": "controller.tar",
        "privileged": "true",
        "run_command": ["-d", "-i", "-t", "{{.Image}}", "/sbin/init"]
    }],
    # Ansibleを実行する環境を構築します。Dockerfileに当たる部分です。
    # Ansibleをインストールします。
    # また、作業ディレクトリとして/tmp/ansible-localを作成します。
    "provisioners":[{
        "type": "shell",
        "inline": [
            "yum clean all",
            "yum -y install epel-release",
            "yum -y install PyYAML",
            "yum -y install python-jinja2",
            "yum -y install python-httplib2",
            "yum -y install python-paramiko",
            "yum -y install python-setuptools",
            "yum -y install ansible",
            "mkdir -p /tmp/ansible-local"
        ]
    }, {
        # こちらは、ホストOSのファイルをコンテナ内にコピーする定義です。
        # Ansibleのファイルをすべてコピーします。
        "type": "file",
        # playbooks/{site.yml,roles,inventories,group_vars...}という構成だとします。
        "source": "playbooks/",
        # コンテナ内のコピー先ディレクトリです。
        "destination": "/tmp/ansible-local"
    }, {
        # vaultファイルを複合するパスワードが書かれたファイルです。
        "type": "file",
        # ホストOSで、複合パスワードを平文で書いたものを用意してください。
        "source": "vault-password-file.txt",
        "destination": "/tmp/ansible-local/vault-password-file.txt"
    }, {
        # Ansible実行時の引数などの定義です。
        # localモードで実行する場合は、ansible-local、sshの場合はansibleになります。
        "type": "ansible-local",
        # playbookのパスを指定します。
        "playbook_file": "playbooks/site.yml",
        # 以下にplaybookが設置されます。
        "staging_directory": "/tmp/ansible-local",
        "extra_arguments": [
            # localモードの場合、ansibleが勝手に-iオプションを付与しますが、それだけでは、inventories以下にあるgroup_varsが読み込まれません。
            # そのため、-iオプションが2つ付くことになりますが、以下でも定義します、。
            # また、inventory fileのパスを、「inventory_file」ディレクティブとして定義できますが、そうするとstaging_directory直下にコピーされ、意図した挙動になりません。
            "-i /tmp/ansible-local/inventories/hosts.sample",
            # vaultの複合パスワードが書かれたファイルを指定します。
            "--vault-password-file=/tmp/ansible-local/vault-password-file.txt"
        ],
        # ビルド完了後に、staging_directoryを削除するかどうかのフラグです。defaultはfalseです。
        "clean_staging_directory": true
    }],
    # 作成するDockerイメージの定義です。
    "post-processors": [{
        # Dockerイメージを作成し、ローカルに保存する。
        "type": "docker-import",
        # イメージ名
        "repository": "myname/image_name",
        # tag
        "tag": "0.1"
    }]
}

Ansible実行時の引数について

Dockerコンテナ内でroot権限でAnsibleを実行するので、sudoパスワードは不要です。
また、ansible-vaultの複合パスワードは、今回は--vault-password-fileでファイルで渡すようにします。(というか、interactiveなやり方がわかりません。)

ビルド実行

以下のコマンドを実行します。

$ sudo packer build -on-error=abort packer.json

そうすると、実際には以下のコマンドが実行されます。

$ cd /tmp/ansible-local && ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 \
    ansible-playbook /tmp/ansible-local/site.yml \
    --extra-vars "packer_build_name=docker packer_builder_type=docker packer_http_addr=" \
    -i /tmp/ansible-local/inventories/hosts.sample \
    --vault-password-file=/tmp/ansible-local/vault-password-file.txt \
    -c local -i /tmp/ansible-local/packer-provisioner-ansible-local714008969

特にエラーがでなければ成功です。

Dockerイメージが作成されたか確認

ホストOS上にDockerイメージが作成されたことを確認します。

$ sudo docker images
REPOSITORY            TAG         IMAGE ID            CREATED            SIZE
myname/image_name     0.1         xxxxxxxxxxxx        1 minutes ago      846MB

connection: docker

ansibleのplaybookにconnection: dockerという行を追加すると、docker containerへの接続となる。
https://hiyoko-infratech.hateblo.jp/entry/2017/12/31/191043
https://dev.classmethod.jp/server-side/os/ansible-docker-connection-plugin/

- hosts: test_servers
  connection: docker
  tasks:
    - name: create directory
      file:
        path: /home/test/
        state: directory
        mode: 0755

    - name: create file
      file:
        path: /home/test/test.txt
        state: touch
        mode: 0644

コマンドにoptionを付ける場合

$ ansible-playbook -i "ansible-sync-test," reproduce.yml -c docker

参考

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5