やりたいこと・目的
- st2-docker使うとサクッと環境を構築出来る
- でも
st2
コマンドやst2ctl
を叩くのにいちいちdocker[-compose] exec
してコンテナに入るのめんどくさい-
packs.dev
ディレクトリを使って開発してる時にst2 run
とかst2 run packs.load
とかしょっちゅう叩く必要がある
-
- ホスト側に
st2
コマンド だけ 入れてリモート(ここではコンテナ)のStackStormを操作出来るようにすれば解決-
st2
コマンドはst2auth/st2api/st2streamに対してhttpでAPIの操作をしているだけなのでリモートのStackStormも実は操作出来るように実装されている-
--debug
オプションを付けて実行すると実際にどのエンドポイントを叩いてるのか見れる
-
- 今回は公式Dockerイメージ(st2-docker)のStackStormを操作する対象とするが、基本的にコンテナでない環境でも同じように動かせる、はず
-
- ホストにログインする全ユーザーが、特に何か手動で追加の設定をしたり、意識をしたりする必要なく
st2
コマンドを叩いてDockerコンテナ内のStackStormを操作出来るようにすることをゴールとする
セットアップ手順
環境
- ホストOS: CentOS 7
- StackStorm: ホストのDocker上に起動したコンテナ。公式の
docker-compose.yml
使用。バージョンは2.5.0
DockerはCEの最新版、ホストで使うpython/virtualenv/pipはCentOS 7標準のレポジトリから yum install
で入るものを使っている。
ホストへのst2clientのインストール
StackStorm公式のパッケージ(yum/deb)を使ってインストールしようとすると st2
パッケージをインストールすることになるのだが、こいつにはStackStormの全コンポーネントが入っているのでデカすぎる。代わりにpipで st2client
をインストールする。
ここでは環境を分けるためにvirtualenvを作ることにする。ユーザーは、ホストにログインした後にこのvirtualenvをactivateすることで st2
コマンドが使えるようになる。
virtualenv /usr/local/opt/virtualenvs/st2client
source /usr/local/opt/virtualenvs/st2client/bin/activate
pip install st2client
# CentOS 7のpipでは上記コマンドでは途中依存パッケージのインストールでコケる。
# 解決するためにpipを自体をアップグレードする必要がある。
pip install --upgrade pip
これで st2
コマンドが使える…と思いきや、実は依存関係のパッケージが足りなくてコケる。エラーメッセージが出なくなるまで pip install
を繰り返す。自分がやったときは最終的に以下のパッケージを追加でインストールする必要があった。
pip install argcomplete
pip install pytz
pip install jsonschema
pip install prompt-toolkit
pip install python-editor
pip install sseclient
この件はIssueもあがっている → st2client missing python dependencies
続いて、接続先を指定するための設定を行う。 st2
コマンドはデフォルトでは127.0.0.1のポート9100(auth),9101(api),9102(strem)に接続しにいくが、以下の3つの方法で接続先=操作する対象のStackStormを指定することが出来る(ドキュメント参照)。
- コマンドラインオプションで渡す
- configファイルに書く
- 環境変数で渡す
コマンドラインオプションを毎回指定するのは面倒くさい、となるとconfigファイルを書くか環境変数で渡すことになるが、複数人がこのホストに接続して st2
コマンドを使うことを想定する場合は環境変数を使うのがベスト。
それは何故かと言うと、configファイルは通常は ~/.st2
配下にあるものを読み込むのだが、このホストにログインする全員が特に何か設定をすることなく特定のリモートにあるStackStormに接続に行くようにする、というのを実現するために共通のconfigファイルを用意して環境変数 ST2_CONFIG_FILE
でそいつを読み込むようにしてしまうと st2 auth login
がうまく使えなくなってしまう。というのも st2 auth login
はconfigファイルのある場所を起点にトークンを書き込むため、全員が同じ場所にあるconfigを参照すると全員のトークンも同じ場所に出来てしまう、とか、じゃあそれを何とかするためにその辺のディレクトリのパーミッションをちゃんと全員が書き込めるようにしてやる必要がある、とかで考えることが多く面倒くさくなる。
接続先を指定するためには環境変数には以下の値を指定する。ここでは全ユーザー共通に設定するため /etc/environment
に書くことにする。
ST2_AUTH_URL=https://st2.example.com:8443/auth
ST2_API_URL=https://st2.example.com:8443/api
ST2_STREAM_URL=https://st2.example.com:8443/stream
ST2_CACERT=/etc/ssl/st2/st2.crt
URLはそれぞれ適切に書き換える。ST2_CACERT
については後述。この段階で、SSL証明書のエラーが出るが、とりあえず st2
コマンドは叩けるようになる。
SSL証明書の設定
StackStormを普通にインストールした場合、リモートからauth/api/streamの各サービスに接続する場合はnginxのリバースプロキシ経由で接続することになる。これはst2-dockerを使った場合も同じ。そしてデフォルトではnginxでSSLが有効化されているのでhttpsでの接続になるが、サーバー側の証明書を適切に設定し、さらにクライアント側でも ST2_CACERT
を正しく設定しないとSSL関連のwarningが出たりエラーが出たりして鬱陶しい。証明書もSubject Alt Nameが適切に設定されていないとpythonのライブラリがwarningを吐きまくるので、適当に設定してあげる。
証明書に関しては環境によって要件が違う(開発or検証環境だから自己署名証明書でよい、production用だからCAで署名された証明書を使う、等)のでセットアップ先に合わせて設定する必要があるが、ポイントは以下。
- アクセスする時に使うURLをSAN(Subject Alt Name)に含んだ証明書を使ってあげる
-
ST2_CACERT
はトラストアンカーにあるCAで署名されている証明書を使う場合でも 必ず明示的に設定する
とりあえずst2-dockerを使っていて自己署名証明書を使っている場合は、まず以下の手順でSAN付きの証明書と秘密鍵を作成し、
openssl req -x509 -new -newkey rsa:2048 -nodes -keyout /etc/ssl/st2/st2.crt \
-days 3650 -subj "/CN=localhost" -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=DNS:localhost,DNS:st2.example.com")) \
-out /etc/ssl/st2/st2.key
docker-compose.yml
を編集して上記で作成した証明書・秘密鍵それぞれ /etc/ssl/st2/{st2.crt, st2.key}
にbind mountしてあげる。そしてホスト側のst2clientの設定では、環境変数 ST2_CACERT
に証明書のCA、この場合は自己証明書なので /etc/ssl/st2/st2.crt
を指定してあげれば、SSLエラーが出なくなる。
もしうまく設定できていない場合、以下のようなエラーが出で動かない。
ERROR: ("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",)
また ST2_CACERT
を指定しなかった場合、証明書の検証が無効になるが、以下のwarningが毎回出る。
/usr/local/opt/virtualenvs/st2/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
ちゃんとトラストアンカーに追加されたCAにサインされた証明書を使う場合でも ST2_CACERT
の指定は必須なので要注意。 ST2_CACERT
を指定しなかった場合は、OS標準のトラストアンカーを使って証明書の検証をするのではなく 完全に証明書検証を無効化してwarningを出す という動作になる。
この件もIssueがあがっている → RFE: st2client should verify ssl certs by default
ちなみに上記Issueにも書いてある通り、warningsはconfigで ssl_silence_warnings = true
を指定すれば出なくすることも出来る(ドキュメント未記載)。しかし、このパラメータは環境変数で設定することは出来ない。ので、要件(全員が何のファイルも変更する必要がない)を満たすためにはSSL証明書をちゃんと設定する必要があった。
Caveat
殆ど問題無く使えるのだが、今のところ stream
に接続する場合にちょっとうまく動かない。例えば st2 execution tail
等。ちゃんと実行出来るのだが、ストリームの終了をクライアント側で検知出来ず?にいるようで Ctrl+C
で強制的に止める必要がある。恐らくだがnginx経由で接続していることに起因しているんじゃないか…と思われる。
st2 pack install/remove
コマンドもstreamに接続しているようで、最後になってコマンドがずっと終わらない状況に陥る。ただコマンド自体は正常に実行出来ている。気持ち悪いので st2 pack
ではなく代わりに st2 run packs.install
等で直接アクションを呼び出すようにしている。