何かを入れたタイミングでいろいろな開発環境の依存関係が壊れてしまいansibleが逝ってしまった。これを機にandible専用のDockerを構築したのでメモ。
DockerをAnsibleで構築するのではなく、Ansibleを実行するDocker環境の構築である。Ansible2.4環境に固定して実行したい、とか、Ansible2.7系に固定して実行したいとか、そもそもAnsibleを実行するためのDockerが欲しいとかいろいろな要望を持っている人は参考にできる。かもしれない。少なくとも自分はこういったdocker環境が欲しかったので作った。
ホスト側のssh-agent情報をdocker側にForwardingすることに大変苦労した(というか情報に行きつくまでに苦労した)ので、メモ。
環境
- OSX Catalina 10.15.4
- Docker desktop 2.3.0.3
目指すところ
Ansilbe 2.4系〜2.7系の各環境の構築(汎用的に利用できるdocker環境の構築)
結論から先に。
今の時点でまだ汎用的なDocker環境は作れていない。ただ自分で利用するには問題ない範囲まで来た。理想としては、どんな環境でも利用できるところに持っていきたいところだが、うまい解決策が思いついていない。たぶん何か見落としをしている。
ポイント
- OSX 特有の問題として、ssh-addの環境をDocker側に引き継ぐことができておらず、GithubのIssueにあがっているオプションを利用している
- Ansibleのバージョンなのかknown_hostsを無視するオプションが全然動かないため、known_hostsをssh-keyscanを利用して強引にDockerfileの中に記載している
- ssh config,ssh-addについてホスト側の情報を利用するために、Docker側のマウントポイントを少しいじっている。
コード
説明
Dockerfile について
FROM alpine:3.9 ENV HOMEDIR {ホスト側のユーザディレクトリ e.g. /Users/hoge }
alpineのlatestを利用した場合とansibleの2.7系統をapt-getで入れた場合、インストールに失敗するため、latestではなく、3.9系統を利用する。
3.9であるのは適当。それ以外(3.12とか)でも動くかもしれないが、とりあえずalpine:3.9なら確実にinstall可能だった。
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.9/main/ ansible~=2.7.17 #RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.7/main/ ansible~=2.4.6.0
ここは各自の環境に合わせて、ansibleの2.7系なのか、2.4系なのかを入れると良い。
今回調べて初めて知ったが、dockerで特定のモジュールの特定のバージョンを入れる方法はいくつかあるらしい。が、そのうちの大半の方法がうまくいかなかった。
確認した限り、よくみるワークアラウンドとして ansible<2.5 とすると 2.5以下の最新が入る、といったものもネットではみられたものの、自分の環境では動作しなかった。
いろいろとググって試した結果、上記のように、 apk add に対して repository オプションを付与して、aplinelinuxのページから、どのリポジトリであればどのansibleが入手できるのかを確認して指定することで狙ったヴァージョン以下のAnsibleをいれることができた。
RUN apk --update add --no-cache py3-pip openssh openssh-client RUN pip3 install --upgrade pip botocore boto3
ここらへんは不要だったかもしれない。とりあえず必要になりそうなので入れておいた。
RUN mkdir -p ${HOMEDIR}/.ssh RUN chmod 700 ${HOMEDIR}/.ssh RUN mkdir -m 700 ${HOME}/.ssh RUN ssh-keyscan -t rsa {AnsibleでSSHしたいサーバ} >> $HOME/.ssh/known_hosts
dockerには、/root/.ssh のディレクトリがないため、パーミッション700で作成。docker-composeでマウントする。
ただ、ホストとなるssh-addの情報を引き継ぐため、(手元で確認している限り)ホスト側が、 /Users/Hoge/.ssh/id.rsa といった形で認証鍵を保持していた時、docker側でも /Users/Hoge/.ssh/id.rsa という形となってしまった。
Dockerのデフォルトユーザは/root/なので、/root/.ssh/id.rsaのパスでマウントされる(たぶん)
ssh-agent情報を引き継ごうとしてもパスが変わってしまうので、引き継げないみたいであった。
そのため、ENVでホスト側のOSXのユーザディレクトリを明示的に設定しておき、これをマウントすることにした。
ただし、ssh時にknown_hostsに書込みに行こうとするため(そして「ansibleのバージョンなのかknown_hostsを無視するオプションがうまく適用されない」)苦し紛れに /root/.ssh のパスを作成した上でssh-keyscanでホスト側の認証情報をdocker側に書き込むことにした。
ansible側でここの情報あるいは、known_hostsを無視するオプションが有効に効いてくれれば、ここらへんの対応は不要となるはず
docker-compose
services: ansible: build: . volumes: - ./:/home - ~/.ssh/:${YOUR_HOME_DIRECTORY}/.ssh/ - ${SSH_AUTH_SOCK}:/ssh-agent environment: - SSH_AUTH_SOCK=/ssh-agent ansible-playbook: build: . entrypoint: - ansible-playbook volumes: - ./:/home - ~/.ssh/:${YOUR_HOME_DIRECTORY}/.ssh/ - ${SSH_AUTH_SOCK}:/ssh-agent environment: - SSH_AUTH_SOCK=/ssh-agent
ぶっちゃけこれらのvolumes,とenviromentの設定が全く動いていない。少なくともMac OSX Marvericksの自分の環境では。
色々と調べているとCloseになっているIssuesというかワークアラウンドがあった。
つまり、
docker-compose run --rm -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock \ -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" \ --entrypoint="ssh -T git@github.com" ansible
と実行せよ、というわけだ。「まさかぁ」とおもっていたのだがこれで動いてしまった。
※今回調べていて初めて知ったのだが、entrypointオプションを指定すると、Dockerfileでentrypointを指定した場合に上書きできるオプション。単純にコマンドを書いたりしたりビルドし直さなくても確認できるので覚えておくと良い(知らなかった。)
というわけで今回のansible専用のdockerを利用する時は、
docker-compose run --rm -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock \ -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" \ ansible-playbook {Playbook}.yml
という少々めんどくさいコマンドを利用しないと実行できなくなってしまった。
- OSX 特有の問題(?)として、ssh-addの環境をDocker側に引き継ぐことができておらず、GithubのIssueにあがっているおまじない的なオプションを利用しなければならない
- known_hostsを無視するオプションが全然動かないため、ssh-keycsanを利用してknown_hostsをDockerfileの中に記載している
- ssh config,ssh-addについてホスト側の情報を利用するために、Docker側のマウントポイントを少しいじっている。
の3つのポイントがあと少しきれいになるとより使いやすい環境ができるのではないかと思う。