u-ryo's blog

various information for coding...

Category: Ansible

Ansible for Docker

| Comments

ansibleのlocalでの開発環境といえばvagrant+virtualboxですが、dockerでいいんじゃねぇの?と思って色々試行錯誤してみました。何度も挫けて、もう駄目かと思いましたけど、幾つもの山を越え、ついに出来ましたですよ!

docker.ini
1
2
3
4
5
[docker_host]
localhost

[container]
eiger-local
playbooks/docker.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    ansible_python_interpreter: /Users/ryo-umetsu/.anyenv/envs/pyenv/shims/python
    # ansible_python_interpreter: /usr/bin/python3
  tasks:
    - name: deploy amazonlinux docker
      docker_container:
        image: amazonlinux
        name: eiger-local
        volumes:
          - /sys/fs/cgroup:/sys/fs/cgroup:ro
        ports: 57017:27017
        expose: 57017
        tty: yes
        detach: yes
        privileged: yes
        # capabilities:
        #   - SYS_ADMIN
        # sysctl:
        #   vm.swappiness: 1
        command: sh -c 'yum -y install procps systemd-sysv file && exec /sbin/init && systemctl restart'
    - name: adding host
      add_host: name="eiger-local"
    - name: wait
      wait_for:
        delay: 10
        timeout: 10

- hosts: eiger-local
  connection: docker
  vars:
    setup_mongodb_password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
          39356533306331333763353433363335343961653335373762623630653361623034646232633837
          6164306666656436653636643333363261646662356666640a636462346635323164633365376637
          39303832396638336664653439326536386235323262303733653563653766353263623032386538
          3135623166613363630a343734666666323830663838653962663032386337626635396563383230
          6266
    # setup_mongodb_password: "test"
    ansible_python_interpreter: /usr/bin/python
  roles:
    - role: "../roles/create_data_directory"
    - role: "../roles/setup_mongodb"
    - role: "../roles/configure_logrotate"
    - role: "../roles/configure_swap"

凄いknow-how詰まってます。

  • connection: localとするとssh経由じゃなく直接command叩いてくれる
  • connection: dockerとするとdocker execで叩いてくれる(のでtargetにauthorized_keysとかsshdとか不要)
  • localhostではgather_facts: noとする(これをしないとansible_swaptotal_mbとかansible_memtotal_mbといったシステムから検出される変数: Fact (ファクト)が埋められない)
  • ansible_python_interpreter: /usr/bin/python3python binaryを探す順序があって、/usr/bin/pythonを先に見つけてしまい、version 2を使ってしまうのを防ぐため。Macだと/usr/bin/pythonがpython2で、python3は/usr/bin/python3なので。ここのversionが合わないと、The error was: No module named 'requests'"と言われて何が悪いのかさっぱりだった。基本的にはpip3 install dockerが足りなかったのだが、その他に、このようにansibleが自分で見つけて使っているpythonのversionと自分がcommand lineで使っていてpip installしたpythonのversionがずれていると、このように言われる、ことがわかった。その他にもinventoryで指定することもcommand line optionで指定することも出来る。command line optionで-e ansible_python_interpreter=/usr/bin/python3とするのが最も柔軟だが、これはplaybooks中の値を全て上書きするので、やはり注意が必要だった。pythonってversionややこしくて...
  • setup_mongodb_password: !vault |Single Encrypted Variableecho -n test|ansible-vault encrypt_string --vault-password-file vault_password.txt --encrypt-vault-id default --stdin setup_mongodb_passwordのように使う(ansible-vaultで暗号化しよう。)
  • docker_container:はmodule名で、古い文献だとdocker:になっていて今は効かないので注意。中で指定できるものはcommunity.docker.docker_container – manage docker containersに挙がっている。privileged: yesは、container内でsysctl vm.swappiness=1(defaultは60)をされるので。sysctl:というoptionもあるのだけれど、そこで指定できる(whitelistにある)のはnet.*とかkernel.*の一部だけだそう(サポート中の sysctl)。
  • command: sh -c 'yum -y install procps systemd-sysv file && exec /sbin/init'は、playbook中でsystemctlを設定するものがあるから。Restart=alwaysにしたいんですよね要するに。でも、そうするとdockerにsystemd(initd)が動いていねばならず、そういえばdockerって普通はそんなのなかったな、どうやるんだ? 調べると、
  • systemd-sysvをinstallする必要
  • /sys/fs/cgroup:/sys/fs/cgroup:roのdevice mountが必要
    • macにはそんなdirectoryはないのに大丈夫なのが不思議
  • 最後は/sbin/init
  • ↑これではcontainerが数秒で倒れるので更に調べるとexec /sbin/init(これどこで見たんだっけなぁ感動したなぁStackOverflowだった気が。他では全然書いて無くて、よく見つけたもんだ)
  • wait_for:がないと、docker内にまだyum installとか終わりきってないのにどんどん次に進んでしまい、service.name:mongod,service.enabled:trueの時に「mongodというserviceはない」といって落ちてしまうので。ホントはちゃんと何かを待ちたかったんだけど、何を待ったらいいのか不明でした。processかなと思ったんですが、processのwaitってpid fileの存在有無を確認するみたいな。いゃー、systemdというかinitってpid fileなんてないんですけど。network port待つ例は数多あれど。仕方ないのでただ10秒待つように。timeout:10は不要かと思いきや、ないとずっと待ってました。
  • これをansible-playbook -vvv -i docker.ini playbooks/docker.ymlと実行するんですが、dockerでやる場合はansible/ansible-runner使って、docker run --rm --name=ansible -v $PWD:/work -w /work -v /var/run/docker.sock:/var/run/docker.sock ansible/ansible-runner sh -c 'pip3 install docker&yum install -y yum-utils;yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo;yum install -y docker-ce docker-ce-cli containerd.io;ansible-playbook -i docker.ini playbooks/docker.yml'と、CentOS8 baseのansible-runnerにdockerを入れねばならず、またunix socketを共有しないとなりませんでした。CentOS8にyum install dockerするとpodmanが入りやがるんですよね。podmanってMacじゃ動かねぇっつーの! podmanだとhosts:eiger-localgather_factsでDocker version checkに失敗して落ちるんですよね。Podman broken on Silverblue? Podman complains kernel not supporting overlay fs (backing file system is unsupported for this graph driver)見てsed -i "s/#mount_program/mount_program/" /etc/containers/storage.conf加えても、Error: mount /var/lib/containers/storage/overlay:/var/lib/containers/storage/overlay, flags: 0x1000: operation not permitted。うーん。逆に、docker containerにansibleを入れる方がsimpleでした。即ち、docker run --rm --name=ansible -v $PWD:/work -w /work -v /var/run/docker.sock:/var/run/docker.sock docker sh -c 'apk add ansible py3-pip;pip3 install docker;ansible-playbook -i docker.ini playbooks/docker.yml'ですね。

参考サイト