signal を http で受ける process wrapper 書いた
結局使わなかったので供養のためにブログ化しておく.
docker を始めとするコンテナ環境では,設定を適用するため signal を送ることで graceful reload をする仕組みは相性が悪いことがある.ホスト環境から動作中のコンテナに対してなんらかの働きかけが必要だからだ.なので,例えば systemd 環境下で動作しているアプリケーションをそのままコンテナ化することが難しかったりする. 特に,複数のアプリケーションが強調して動作する仕組みが必要である場合,side car コンテナなどでアプリケーションを分割すると途端に困難さが増す*1. アーキテクチャの刷新をするのが最も健全な手段であるが,そうもいかない場合に対処するため,signal のインターフェースを http に露出させるプロセスの wrapper を書いた.
mvp
signal を露出させたいプロセスの例として signal_echo.rb
を用意
# signal_echo.rb running = true Signal.trap('INT') do |signo| puts 'Traped SIGINT' running = false end loop do break unless running end
signal_echo.rb
を http-signal-proxy から立ち上げる Dockerfile を用意
# Dockerfile FROM ruby:2.5 RUN wget -q https://github.com/s4ichi/http-signal-proxy/releases/download/v0.1.0/http-signal-proxy_v0.1.0_linux_amd64.tar.gz && \ tar -zxvf http-signal-proxy_v0.1.0_linux_amd64.tar.gz && \ mv http-signal-proxy_v0.1.0_linux_amd64/http-signal-proxy /usr/local/bin/http-signal-proxy && \ chmod +x /usr/local/bin/http-signal-proxy COPY ./signal_echo.rb /signal_echo.rb CMD ["http-signal-proxy", "--port=8080", "--command=ruby signal_echo.rb"]
実行
$ docker run -d --rm -p 8080:8080 -t http-signal-proxy-test:latest 81f3d8507baa9c2a945c20d920824b6ca18f3be4ef04c7b853ac9b33c0480356 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 81f3d8507baa http-signal-proxy-test:latest "http-signal-proxy -…" 4 seconds ago Up 3 seconds 0.0.0.0:8080->8080/tcp jolly_spence $ curl http://localhost:8080/http-signal/sigint Successed to proxy sigint to destination command% $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
実装は entrykit とか supervisord を参考にした.entrykit はなかなか厳しそうなコードがそこそこあることがわかった.
push or pull
コンテナ外部から reload したいとき(push 型)はこういう手段がいいのかなぁと思って書いた.結局使わなかったというのは,コンテナ内部で reload が必要かどうかを polling すれば(pull 型)十分であることがわかったからだ.push 型はいつか必要になるのかな….