tjinjin's blog

インフラ要素多めの個人メモ

docker上のコンテナをansibleで構成管理する

いまだに手動で環境構築する会社が嫌になってきたので、Web界隈の
技術を試してみたくて触ってみました。自分用メモです。
chef等と違い、エージェントのインストールなどがいらないため、会社でも
もしかしたら使えるかもしれないですね。

前提

ホストOS(windows)上にvagrantを使ってCentOS(管理サーバとする)を構築。
dockerを使ってnodeをn台作成し、ansibleで構成管理してみる。

管理サーバの構築

Vagrantは既にインストールされているとします。

boxfileの追加

今回はCentOS6.5を使います。

vagrant add centos6.5 https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box

vagrant init

Vagrantfileを修正

  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "centos6.5"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network :private_network, ip: "192.168.40.10"
  vagrant up

うまく起動しました。

管理サーバに公開鍵を作成しておきます。

[root@centos ansible]# ssh-keygen
[root@centos ansible]# cp ~/.ssh/rsa_id.pub authorized_keys

packageのインストール

[root@centos ansible]# yum install docker-io -y
[root@centos ansible]# docker -v
Docker version 0.11.1, build fb99f99/0.11.1
[root@centos ansible]# yum install ansible -y
[root@centos ansible]# ansible --version
ansible 1.6.2

dockerコンテナの構築

Dockerfileの修正

いろいろサイトを参考にし下記のようにしてみました。最低限SSH
が利用できます。

# Dockerfile
FROM centos

MAINTAINER test

RUN yum update

# install package
RUN yum -y install vim git
RUN yum -y install passwd openssh openssh-server openssh-clients sudo

# Create user
RUN useradd docker
RUN passwd -f -u docker

# Set up SSH
RUN mkdir -p /home/docker/.ssh; chown docker /home/docker/.ssh; chmod 700 /home/docker/.ssh
ADD authorized_keys /home/docker/.ssh/authorized_keys

RUN chown docker /home/docker/.ssh/authorized_keys
RUN chmod 600 /home/docker/.ssh/authorized_keys

# setup sudoers
RUN echo "docker ALL=(ALL) ALL" >> /etc/sudoers.d/docker

# Set up SSHD config

RUN sed -ri 's/#PermitRootLogin yes/PermitRootLogin yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config
RUN sed -ri 's/#UsePAM no/UsePAM no/g' /etc/ssh/sshd_config


# Init SSHD
RUN /etc/init.d/sshd start
RUN /etc/init.d/sshd stop

#
EXPOSE 22

CMD ["/usr/sbin/sshd","-D"]
[root@centos ansible]# docker build -t docker/ansible .
[root@centos ansible]# docker run -d --name test01 docker/ansible
[root@centos ansible]# docker run -d --name test02 docker/ansible
[root@centos ansible]# docker run -d --name test03 docker/ansible 

これで環境構築完了です。
sshでログインできるか試してみる。

[root@centos ansible]# docker inspect --format ' {{ .NetworkSettings.IPAddress }} ' test01
172.17.0.2
[root@centos ansible]# ssh docker@172.17.0.2
[docker@ba8935ee38fa ~]$

ansibleを使ってみる

とりあえず動かす

[root@centos ansible]# cat hosts
[test]
172.17.0.2
172.17.0.3
172.17.0.4

ansibleを利用するにはhostsというファイルに対象ノードを記載する必要があります。
[test]というのはグループのようなもので、[ap-server][db-server]などと分けることで
それぞれにあった処理を実行することができるようです。

[root@centos ansible]# ansible -i hosts -u docker 172.17.0.2 -m ping
172.17.0.2 | success >> {
    "changed": false,
    "ping": "pong"
}
  • uオプションで実行ユーザを指定できます。今回はdockerユーザでログインするようにします。-mではmoduleを指定でき、pingを実行します。

※moduleの種類については公式ドキュメント(http://www.ansibleworks.com/docs/modules.html
やansible-docコマンドで確認が可能です。

playbookを作って動かす

[root@centos ansible]# cat site.yml
# base_playbook
- hosts: all
  sudo: yes
  user: docker
  tasks:
  - name: create directory
    file: path=/work/test state=directory owner=docker group=docker mode=0755
[root@centos ansible]# ansible-playbook -i hosts aaa.yml --syntax-check
playbook: aaa.yml
[root@centos ansible]# ansible-playbook -i hosts aaa.yml
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [172.17.0.4]
ok: [172.17.0.3]
ok: [172.17.0.2]

TASK: [create directory] ******************************************************
changed: [172.17.0.2]
changed: [172.17.0.3]
changed: [172.17.0.4]

PLAY RECAP ********************************************************************
172.17.0.2                 : ok=2    changed=1    unreachable=0    failed=0
172.17.0.3                 : ok=2    changed=1    unreachable=0    failed=0
172.17.0.4                 : ok=2    changed=1    unreachable=0    failed=0

playbookの構成を工夫する

1つのplaybookに設定してもいいのですが、大規模になるとファイルがわかりにくくなります。
そこでベストプラクティスが公開されています。今回は簡単に作ってみます。*1

ansible/
├─ aaa.yml
│   hosts
├─ roles
│   └─common
│       ├─ files
│       ├─ handlers
│       ├─ meta
│       ├─ tasks
│       │   └─ main.yml
│       ├─ templates
│       └─ vars
├─ site.yml               :メイン
└─webservers.yml     :webserverに特化した設定
[root@centos ansible]# cat site.yml
# base_playbook
- hosts: all
  sudo: yes
  roles:
    - common

  tasks:
    - include: webservers.yml
[root@centos ansible]# cat webservers.yml
- name: directory create
  file: path={{ item.path }} state=directory owner={{ item.owner }} group={{  item.group }} mode={{ item.mode }}
  with_items:
      - { path: '/work', owner: 'docker', group: 'docker', mode: '0755' }
      - { path: '/work/aaa', owner: 'docker', group: 'docker', mode: '0755' }
      - { path: '/work/bbb', owner: 'docker', group: 'docker', mode: '0755' }

[root@centos ansible]# cat /ansible/roles/common/tasks/main.yml
- name: common directory create
  file: path={{ item.path }} state=directory owner={{ item.owner }} group={{  item.group }} mode={{ item.mode }}
  with_items:
      - { path: '/work/common/', owner: 'docker', group: 'docker', mode: '0755' }
      - { path: '/work/common/aaa', owner: 'docker', group: 'docker', mode: '0755' }
      - { path: '/work/common/bbb', owner: 'docker', group: 'docker', mode: '0755' }

site.ymlが起動時に呼ぶものでその中でrolesとtasksを定義しています。
rolesを指定するとroles/xxx/yyy/main.ymlを自動で読込実行してくれるようです。
tasksでwebservers.ymlをincludeしていますがrolesに当てはまらないものをincludeすることも可能です。
こういったことができるよという意味合いでとらえてもらうとよいかと思います。最終的にはrolesに落としこむのがいいんでしょうか。

webservers.ymlでwith_itemsというものを使っていますが、これは変数の繰り返し定義です。varでも
できるそうですが、違いはまだ調べてません。
with_itemsではkeyとvalueを宣言できるので、大量にディレクトリを作りたい場合など
変数でまとめると見やすいかも。

感想

yamlとか使ったことなかったですが、なんとかなりそうです。ansibleのdirectory構造の部分は少しわかりにくいですが、慣れの問題かと。会社でも使えたらいいのに。。。もっと調べて使いこなせるようになりたいものです。