3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

StackStormAdvent Calendar 2017

Day 16

st2clientを使ってリモート(st2-docker)のst2を操作する

Last updated at Posted at 2017-12-26

やりたいこと・目的

  • 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 に書くことにする。

/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 等で直接アクションを呼び出すようにしている。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?