前の記事と同様の構成で fleet で Datadog Agent コンテナも管理する。
参考
まずは...
unit ファイル
[Unit] Description=kappa-dd-agent After=docker.service Requires=docker.service [Service] ExecStartPre=-/usr/bin/docker kill dd-agent ExecStartPre=-/usr/bin/docker rm dd-agent ExecStart=/usr/bin/bash -c \ "/usr/bin/docker run --privileged --name dd-agent -h `hostname` \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /proc/mounts:/host/proc/mounts:ro \ -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \ -e API_KEY=`etcdctl get /dd-api-key` \ datadog/docker-dd-agent" ExecStop=/usr/bin/docker stop dd-agent [Install] WantedBy=multi-user.target [X-Fleet] Global=true
今回の [X-Fleet]
は Global=true
となっているが、これは
Schedule this unit on all agents in the cluster. A unit is considered invalid if options other than MachineMetadata are provided alongside Global=true.
とあるのでクラスタ内の全てのエージェント(ノード)でユニット(サービス)を起動することになる。
API キー
以下のように etcd に登録してサービス起動時(コンテナ起動時)に etcd から取得する。
core@core-01 ~ $ curl -X PUT -L http://127.0.0.1:4001/v2/keys/dd-api-key -d value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
念のために API キーを etcd から取得する。
core@core-01 ~ $ etcdctl get /dd-api-key
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
起動
core@core-01 ~ $ fleetctl submit kappa-dd-agent.service core@core-01 ~ $ fleetctl load kappa-dd-agent.service core@core-01 ~ $ fleetctl start kappa-dd-agent.service
監視開始でめでたしめでたし
ところが...
API キーは etcd に平文で
暗号化等されずに平文で入っているので改めて...
core@core-01 ~ $ etcdctl get /dd-api-key
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
これではいかんざき。
xordataexchange/crypt で暗号化
上記の記事を参考にさせて頂いて etcd に登録する API キーを暗号化してみるのでまずは gpg2 を利用して公開鍵と秘密鍵を生成する必要があるので以下のようなバッチファイルを作成して生成する。
core@core-01 ~ $ cat app.batch %echo Generating a configuration OpenPGP key Key-Type: default Subkey-Type: default Name-Real: dd-api-key Name-Comment: Datadog API key Name-Email: app@example.com Expire-Date: 0 %pubring .pubring.gpg %secring .secring.gpg %commit %echo done
次に gpg2 で公開鍵と秘密鍵を生成。
# gpg2 --batch --armor --gen-key app.batch を実行して生成 core@core-01 ~ $ gpg2 --batch --armor --gen-key app.batch gpg: Generating a configuration OpenPGP key (暫く時間が掛かる...) gpg: done # 公開鍵 .pubring.gpg と 秘密鍵 .secring.gpg が生成されている core@core-01 ~ $ ls -l .*.gpg -rw-r--r-- 1 core core 1722 Aug 10 22:36 .pubring.gpg -rw------- 1 core core 3488 Aug 10 22:36 .secring.gpg
続けて xordataexchange/crypt は Go で書かれておりバイナリも配布されているのでバイナリをダウンロードする。
core@core-01 ~ $ wget https://github.com/xordataexchange/crypt/releases/download/v0.0.1/crypt-0.0.1-linux-amd64 core@core-01 ~ $ mv crypt-0.0.1-linux-amd64 crypt core@core-01 ~ $ chmod +x crypt core@core-01 ~ $ ./crypt -h usage: ./crypt COMMAND [arg...] commands: get retrieve the value of a key set set the value of a key
暗号化して登録したい情報をファイルで用意する。
core@core-01 ~ $ cat dd-api-key
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
用意した JSON ファイルを利用して etcd に情報を登録する。
# help を確認 core@core-01 ~ $ ./crypt set -h usage: ./crypt set [args...] key file -backend="etcd": backend provider -endpoint="": backend url -keyring=".pubring.gpg": path to armored public keyring # 登録する core@core-01 ~ $ ./crypt set -backend=etcd -keyring=/home/core/.pubring.gpg /dd-api-key dd-api-key
念のために etcdctl コマンドで確認する。
# 暗号化されている core@core-01 ~ $ etcdctl get /dd-api-key wcBMA7haxrMkuVotAQgAjhI52MGY+xM/WY7cliXLse0i5g5in8j2eo51rWGq7c6zsWmxiVD+nwBGubLiqWWz3xeR3wVgXy4nE4qX2gpW3VoK8sDZZ9kDEJ5OtgU/LdLXbEgG8GYHx8M3ODeuJQRr9+y4fiJcDOBXAVh2m5Uj2NfdyHkGv+7HchFfyNDLt6pXLFF6aRIgED10cC65Qkujtd/C1ouGrHZq9tjWYSw7MqPg94+vsXZNx9BCs9ZW4uzMDIwrKhxXvNXq0m/6bW9ky7ZrfbZGAlBbXYplMY9qQV5Rhn0G0w9xkEugvWkjX1y/mO+NoZKbxSyP9JgsnvtA5hXY9WzNzO5913uiHsbbx9LgAeR18eKNNiJ16JGhLf+pge474aeb4JbgPOHm0uDy4tG4R1vgn+NKerfJJZFBjuCt4QTE4FTiTYtrv+Cn4Ssk4J7icd3BuOAC4z8Whhmt7ECf4KfkvtnNb76/VjGO22dKAxBr9eKCT0Ps4UzIAA==
crypt を利用して復号化して確認する。
# help を確認 core@core-01 ~ $ ./crypt get -h usage: ./crypt get [args...] key -backend="etcd": backend provider -endpoint="": backend url -secret-keyring=".secring.gpg": path to armored secret keyring # 確認 core@core-01 ~ $ ./crypt get -backend=etcd -secret-keyring=/home/core/.secring.gpg /dd-api-key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
暗号化された API キーを利用して Datadog Agent のコンテナを起動してみる。
core@core-01 ~ $ docker run -d \ --name dd-agent \ -h `hostname` \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /proc/mounts:/host/proc/mounts:ro \ -v /cgroup/:/host/sys/fs/cgroup:ro \ -e API_KEY=`/home/core/crypt get -backend=etcd -secret-keyring=/home/core/.secring.gpg /dd-api-key` \ datadog/docker-dd-agent
-e
オプションを利用してコンテナに環境変数 API_KEY を渡す際に crypt get
で復号化してコンテナを起動している。
めでたし...と言いたいところだけど、気になった点を幾つか。
- etcd に登録された暗号化データを利用するノード全てに crypt を導入して利用できるようにしておく必要がある(これはやるしかない)
- せっかく etcd で暗号化していても起動したコンテナに対して
docker inspect
すると Environment の値が見れてしまうのに気付いた...(これは Environment で API キー等を渡すアプリケーションコンテナでは共通の悩みだとオモフ)
おわり
etcd や Consul の KVS に
環境変数や今回のような API キー等を登録して利用するのは色々と捗りそうだが、登録する内容によっては暗号化はしておきたいので crypt は良さそう。
CoreOS + etcd + fleet + Docker
従来のサーバー管理と比較すると異次元だが全てのアプリケーションを Docker で運用するというのは、上記のような認証情報管理等の課題も多いと思われるが、面白いなあと今更ながらに思った。