env-injectorを階層化パラメータに対応させた
引き続きコレの件。
最初に
前のエントリの追記で、 ENV_INJECTOR_MODE
に対応とか書いてたけど、どうも git push
を忘れていた模様。orz…
今回の修正で大体ユースケースカバーできそうなので、もうこのままなかったことにします(ぉ
階層化パラメータ
DescribeParametersでは対象のパラメータをIAMでリソース制限できないのがちょっとアレかなぁと思って 今までのenv-injectorは、inject対象リスト作成のためにあえて事前に空の環境変数を用意するようにしてました。
でもアップデートで対応された階層化されたパラメータに対してGetParametersByPathを使えば必要なパラメータだけに絞ったアクセス許可をIAMで設定できます。
というわけでenv-injectorでも対応してみました。
必要なIAMのポリシーはこんな感じで
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParametersByPath" ], "Resource": [ "arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/wap" ] } ] }
こんなカンジでパラメータが設定されているときに
$ aws ssm get-parameters-by-path --with-decryption --path /prod/wap { "Parameters": [ { "Type": "String", "Name": "/prod/wap/DB_USER", "Value": "scott" }, { "Type": "SecureString", "Name": "/prod/wap/DB_PASSWORD", "Value": "tiger" } ] }
ENV_INJECTOR_PATH
を指定して実行するだけ。
$ ENV_INJECTOR_PATH=/prod/wap env-injector printenv | grep DB_ DB_USER=scott DB_PASSWORD=tiger
DescribeParametersのような制限の効かないパーミションも不要ですし、AWS的にも階層化されたパラメータ推しっぽいので今後はこっちを使うとイイトオモイマス。
意図しないパラメータがinjectされるかも、、、という懸念は残りますが、、、ま、いっか、ということで。(;・∀・)
そんなわけで今後もenv-injectorをよろしくお願いします。
AWS環境下で動かすDockerのイメージのENTRYPOINTに仕込んでおくと本当に便利なので、是非使ってみてください
env-injector作るときに考えてたこと
env-injectorが「問題がある」って言われてもうた。ツライ……
というわけで言い訳エントリです。見苦しいですね。
env-injectorの作成時、空の環境変数を作らずに「DescribeParameterでパラメータ一覧ぶっこ抜いてprefixにマッチするものをinjectする」っていうのも考えたんですけど、以下のような理由からやめました。
1. DescribeParameterはIAMのポリシーで必要となる一部のパラメータだけに制限することができない。
開発環境から本番環境のパラメータ一覧が見えたり、別アプリケーションのパラメータ一覧が見えたからって「だから何?」ってハナシもありますが、 なんとなく嬉しくないかなぁ……と。
2. 意図しない環境変数をinjectしないか?
ssm側のパラメータ一覧を全部読み込むことになるので、ちょっとした確認での実行時に意図しない環境変数まで読み込んでしまうコトを懸念しました。
自分で空の環境変数用意するんなら、必要なものだけinjectするだろうし、意図せずinjectするコトはないだろうと思ってみたり。
3. dockerのentrypoint用を最初から想定
パラメータの一覧の「正」とするモノはアプリケーション側にあった方がいい(パラメータストアを見ないと一覧がワカラナイとかツライ)し、 空の環境変数用意するのは、DockerfileのENVで指定すればそんなに手間じゃない、と考えました。
また環境変数のキーが隠蔽できない件も、DockerfileのENVで記述するような時点で隠蔽するものではないだろうと。
最終的には「id:kakku22兄さんからの宿題で、数ヶ月放置したあげくの回答用のPoCだから何でもいっか」っていう雑な決断ですけどね。。。
ざっくり見たカンジ、スクリプトに組み込むんならexecするenv-injectorより、ssm2envの方が便利だと思います。
そんなこんなでパラメータストア周りのツールでイロイロ選択肢が増えればいいんじゃないかなぁ、と個人的には思います。
(追記: 2017-08-04)
なんか元記事の中の方に気を使わせてしまったみたいでスミマセン。
もともとがやっつけで作ったもなので対応できないユースケースがあるのは当然なので、「イケてない」と思われても仕方ないんですけどね。(;・∀・)
んで、実はこっそりDescribeParametersでパラメータぶっこ抜いて環境変数を設定するモードも用意してみました。
# 以下の値がパラメータストアに保存されてるという前提で # - prod.wap.DB_USER=admin # - prod.wap.DB_PASSWORD=password # - prod.wap.DB_PARAM=param # こんな環境変数を設定しておく $ export ENV_INJECTOR_PREFIX=prod.wap $ export DB_USER=user $ export DB_PASSWORD= # mode=empty_only: 空の環境変数(DB_PASSWORD)だけ上書き。デフォルト $ ENV_INJECTOR_MODE=empty_only env-injector printenv | grep DB_ DB_USER=user DB_PASSWORD=password # 当然無指定でも同じ挙動 $ env-injector printenv | grep DB_ DB_USER=user DB_PASSWORD=password # mode=aggressive: パラメータストアの変数を全部設定するけど、もともと設定されている環境変数(DB_USER)はそのまま $ ENV_INJECTOR_MODE=aggressive env-injector printenv | grep DB_ DB_USER=user DB_PASSWORD=password DB_PARAM=param # mode=all: パラメータストアの変数を全部設定する。もともと設定されている環境変数があっても上書き $ ENV_INJECTOR_MODE=all env-injector printenv | grep DB_ DB_USER=admin DB_PASSWORD=password DB_PARAM=param
aggressive
とall
はGetParametersに加えてDescribeParametersのパーミッションも必要になります。
逆にデフォルトのままだと特に追加のパーミッションもいらない、ということで。
……こ、これで、どや?
AWS上で動かすアプリケーションとクレデンシャル情報
AWSで動かすアプリケーションのクレデンシャル情報ってどう管理してますか?
chefやansibleでプロビジョニングしたりするにしても、平文でgit管理するのもアレだし、暗号化してコミットするのも結局扱いにくいし……と悩ましいですよね?
そんな中、こちらのクラスメソッドさんのエントリを拝見したところ dev.classmethod.jp
「AWS上で動かすアプリのクレデンシャル情報をパラメータストアから環境変数にぶっこんでくれるツールがあればイケてるんじゃね?」と思いついてしまったので、勢いでPoC的に作ってみました。
使い方は、空の環境変数用意しておいてから
$ export DB_USER= $ export DB_PASSWORD=
プレフィックスを指定して、env-injector経由で任意のコマンドを実行します。
$ ENV_INJECTOR_PREFIX=prod.wap env-injector printenv | grep DB_ DB_USER=scott DB_PASSWORD=tiger
するとパラメータストア(この例ではprod.wap.DB_USERとprod.wap.DB_PASSWORD)の値が環境変数に入った状態でそのコマンドが実行されます。
dockerの場合ですと、以下のDockerfileのようにENTRYPOINTで指定するといいんじゃないかなぁ……と。
FROM golang AS build-env RUN CGO_ENABLED=0 go get github.com/okzk/env-injector FROM alpine RUN apk add --no-cache ca-certificates COPY --from=build-env /go/bin/env-injector /usr/local/bin/ ENTRYPOINT ["env-injector"] ENV DB_USER= DB_PASSWORD= CMD ["printenv"]
プレフィックスを指定しなければなんの影響もありませんし、
# docker build -t test . # docker run --rm test | grep DB_ DB_USER= DB_PASSWORD=
環境を切り替えるのもラクチン。
# docker run --rm -e ENV_INJECTOR_PREFIX=prod.wap test | grep DB_ DB_USER=scott DB_PASSWORD=tiger # docker run --rm -e ENV_INJECTOR_PREFIX=stg.wap test | grep DB_ DB_USER=admin DB_PASSWORD=password
アプリケーション本体は普通に環境変数で設定を受け取るように作るだけでOKですので、アプリケーションとパラメータストアが密結合になることもありません。
ECSで動かすアプリケーションも適切にtask roleと組み合わせればクレデンシャル管理もバッチリになる、ということで。
nohupなncでのtarなファイル転送
TB級のデータ転送のように、scpがかったるくてやってられない場合にncでファイル転送をしようというケースありますよね?
そんなケースでは当然相当時間がかかるんで、途中で死なないようにnohupをつけたい、と思うわけで。
んで、そのままnohupつけると動かなくなるんですが、よくワークアラウンドを忘れるのでメモを残しておきます。
# ホストやポート番号等は適当に読み替えてください
ファイル受信側
nohup nc -d -l 12345 2> nohup.out | tar xvf - &
ポイントは2点
ファイル送信側
nohup tar cf - files | nc 192.168.10.10 12345 &
こっちのポイントは
- ファイル名のような余計な出力をしないよう、tarのzオプションなんかはつけない
以上ですー
MackerelとECSのダイナミックポートマッピング
当方、現在の担当業務的にMackerelを両手で数えられるくらいのサーバにしか導入しておらず、しかも初期に設定をしたあとは絶賛放置中という超ライトユーザなのですが、先日なんの因果か他部署の方から「ECRのダイナミックポートマッピングしているときのコンテナのメトリクス取るのどうすればええん?」という相談をうけてしまいました。
完全無欠のMackerel情弱としては、極々テキトーなやり取りをせざるを得なかったのですが、なんだかそれなりにイイ感じまとまったみたいです。
kakakakakku.hatenablog.com kakakakakku.hatenablog.com
結論、id:kakku22 さんカッケー。
まあそれだけだとアレなわけで、事情があって歯牙にもかけてもらえなかった別の方法をこのエントリでは書いてみようと思います。
ざっくり提案したのは以下のようなやり方。なお当方テキトーなので自分で試してないです(ぉ
ECSのtask-definitionで以下のように複数コンテナが動くようなタスク設定をする
- メトリクスを取りたい対象のコンテナ
→ 適当なポートでサービスが動いていて、そのポートでメトリクスをとれる
→ hostとのポートマッピングは動的で、host側からアクセスではポート固定できない- mackerel-agentを動かすコンテナ
→ dockerのlink機能で上記のコンテナのポート(こっちは固定指定可)にアクセスしてメトリクス収集
要するに1タスクを1ホストとみなして、そこの中でメトリクス収集を完結させちまおう、というやり方ですね。
そーすることでMackerelの管理画面でもroleでのグラフもいい感じにまとまって見れるんじゃね?的な?的な?
やろうと思えば設定もカンタンで管理画面上も管理しやすい、という案なのですが、既に書いたように採用は見送られました。
理由は単純で、Mackerelの課金がホスト単位なので、1タスク1ホストとかでポンポン設定入れちゃうとアホみたいにオカネがかかるから、という。。。
そんなわけでMackerel様としては「ホストあたりの基本料金を極々安くして、その代わりメトリクス数で従量課金する」みたいな設定も可能にしていただけるとイイなぁと思う次第であります。
# じゃねーとみんなdatadogに逃げちゃうよ?
Symantecの証明書問題私的まとめ
Symantecの証明書でアレコレざわついているので、自分用にまとめます。
経緯等
以下にまとまっていまるので省略。
何がおこるか?
https://github.com/sleevi/explainer/blob/master/README.md
ざっくりまとめると以下の2点
- 該当の証明書の有効期限を短いモノとして取り扱う(最終的には最大279日とみなす)
- 該当の証明書はDomain Validatedとして扱う(EV証明書がEV証明書として扱われなくなる)
「該当の証明書」って?
https://chromium.googlesource.com/chromium/src/+/master/net/data/ssl/symantec/README.md
- 証明書チェーンのルートCAの証明書が ここになければセーフ
- subCAで発行した証明書の場合、それが"Excluded Sub-CAs"に記載されていればセーフ
- それ以外はアウト
もっと具体的には?
個人的観測範囲で使われていて、該当するCAは以下
3/27くらいからChromeでEV証明書がEV証明書として扱われなくなったんだけど?
WindowsのChrome 57では現象を確認できたが、MacのChrome 57では確認できず。
経緯は以下
- https://knowledge.symantec.com/jp/support/ssl-certificates-support/index?vproductcat=V_C_S&vdomain=VERISIGN.JP&page=content&id=INFO4287&actp=RSS&viewlocale=ja_JP&locale=ja_JP&redirected=true
- https://bugs.chromium.org/p/chromium/issues/detail?id=705285
斜め読みしたカンジでは、"Symantecに激おこ事案"とは無関係の単なるバグか?
# タイミング悪すぎやろ。。。
どうすればいいの?
今後どう転ぶかわからないし、巻き込まれたくないならSymantecやVeriSignのEV証明書をつかってるトコは、他社に乗り換えればいいと思う。
EV証明書じゃないなら、有効期限が短くなるだけといえば、それだけなので運用回避もアリかと。
私見
Symantecはギルティでも、Symantec発行の証明書を使ってるトコまで巻き込まれるのはツライ。
ただひたすらツライ。
5/2追記
まだちゃんと読んでないけど、リンクだけ
docker swarmのオーバーレイネットワークの安定性について
半年くらい前にこんな記事を書いたのですが、まあうまく行きませんでした。
頂いたブコメも試してみたんですけど、結果は芳しくなく。。。
Re: Dockerに載せたサービスをホットデプロイする - okzkメモb.hatena.ne.jp--stop-grace-periodの設定とDockerfileのHEARTBEATとSTOPSIGNALの設定をすれば出来るはず
2016/08/17 06:19
そんな中、元記事のヒトも試してみたようですけど、同じ結果に。。。
そんな中、CVE-2016-9962も出ちゃったし、docker 1.13もリリースされたコトだし、ということでdocker 1.13でswarmモードをもう一回試してみました。
インストール後、swarm初期化
# docker swarm init # docker service create --update-delay 5s -p 80:80 --name test --replicas 2 nginx
別ウインドウでログ等を確認しつつ
# watch -n 0.3 'curl -sI http://localhost; docker ps -q | xargs -i sh -c "echo ----------- {};docker logs --tail 5 {}"'
パタパタイメージが切り替わるようにやる気なくワンライナー
# set -e # while : ; do docker service update --image nginx:stable test ; sleep 15 ; docker service update --image nginx test; sleep 15 ; done
数十分放置してみましたが、特に問題ありませんでした。
というわけで元記事に対する半年遅れの回答になりますけどdocker 1.13のswarmモード使えば良いんじゃないでしょうか?