PHPシステムをコンテナで動かすための取組みのすべて

D9b4364dacae526c391909272bbb91ed?s=47 kikumoto
February 11, 2020

 PHPシステムをコンテナで動かすための取組みのすべて

D9b4364dacae526c391909272bbb91ed?s=128

kikumoto

February 11, 2020
Tweet

Transcript

  1. PHPシステムを コンテナで 動かすための 取り組みのすべて PHPerKaigi 2020 2020/02/11 きくもと (@takakiku)

  2. 自己紹介 ★ きくもと ★ Twitter: @takakiku ★ 所属: Hamee(ハミィ)株式会社 ◦

    小田原にあります! ◦ ランチセッションにGo! ★ お仕事: SRE、マネージャー ★ その他 ◦ PHPerKaigi 2020 当日スタッフ 2
  3. 話すこと、話さないこと ★ PHPコンテナを動かす際に実際に 取り組んだことを話します。 ◦ 基本泥臭い話しばかりです。 ◦ 「正しい」とは限らない。 ★ PHP成分はほんの僅かです。

    ★ Dockerそのものや、各種ツールの 細かい説明はしません。 3
  4. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 4 Agenda
  5. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 5 Agenda
  6. こんなシステムがありまして 6 ロードバランサ リバプロ RDBMS Appサーバ Apache mod_php モノリスなPHPコード (コードベースは1つ)

    Webリクエスト処理 プロセス メール受信処理 プロセス バッチ処理 プロセス
  7. AWSへ移行したい 7 ELB ECS Webリクエスト処理 Apache mod_php AWS Batch Lambda

    SNS SQS SES CloudWatch Events メール受信処理 バッチ処理
  8. その前に、、、 ★ コンテナ化しないと ★ 既存環境でコンテナ化された状態で 動作させて、実績を作っておきたい ★ AWSでの移行イメージを持ちやすい 状態にしたい 8

  9. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 9 Agenda
  10. 話すシステムのイメージ 10 10 ロードバランサ リバプロ RDBMS Appサーバ Webリクエスト処理 コンテナ メール受信処理

    コンテナ バッチ処理 コンテナ Apache mod_php 共通 Docker Image
  11. ログ収集 - コンテナ出力 ★ ログドライバにfluentdを指定 ★ dockerホスト上でfluent-agent-hydra を動かしている ◦ https:/

    /github.com/fujiwara/fluent-agent-hydra ◦ Kayac @fujiwara さん作成 ◦ Go 実装(docker ホストにruby不要) 11 docker run \ --log-driver=fluentd \ --log-opt fluentd-address=localhost:24224 \ <略>
  12. ログ収集 - その他ログ ★ 各コンテナはdockerホスト上のディレク トリをマウント ◦ ログはホスト上に出力される ★ docker

    ホスト上で fluent-agent-chimeraを動かしている ◦ 拙作 -https://kikumoto.hatenablog.com/entry/2018/02/02/095629 ◦ fluent-agent-hydraをベース ◦ 動的に生成されるログを取り込み fluent-agent-hydraに転送 12
  13. システム起動まわり ★ systemdな環境 ★ システム起動時にコンテナ(Webリク エスト処理)を起動したい。 ★ コンテナ起動前に、fluentdがPORTを LISTENしている必要。 13

  14. ★ Unit ファイル システム起動まわり 14 [Unit] After=fluent-agent-hydra.service docker.service Wants=fluent-agent-hydra.service docker.service

    [Service] Type=oneshot RemainAfterExit=yes ExecStart=<24224ポートがLISTENされるまで待つスクリプト> ExecStart=<docker run するスクリプト> ExecStop=<Apacheをgraceful shutdownするスクリプト>
  15. 兄弟コンテナ ★ crondコンテナも存在 ◦ 開発環境再現の容易にするため ◦ コンテナ内からdocker runする必要 ▪ docker

    コマンドをイメージに仕込済 ▪ /var/run/docker.sock をマウント 15 docker run \ --mount \ type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \ <略>
  16. メール送信 ★ コンテナ内からメール送信 ◦ ssmtp を利用 ▪ sendmail_path = /usr/sbin/ssmtp

    -t ▪ ssmtp.conf 16 mailhub=172.30.1.1:25 FromLineOverride=yes コンテナネットワーク上で のdocker ホストのIPと MTAのポート
  17. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 17 Agenda
  18. Dockerfile ★ 3つのDockerfile ◦ つまり、3つの Docker Image 18 OSおよび言語ランタイムを インストールしたイメージ

    アプリケーションが依存する外部 ツールやライブラリ アプリケーションコードや 設定 変更の頻度を意識し た構成 通常時は最上位の イメージをビルドす るだけ。
  19. Dockerfile 19 # syntax = docker/dockerfile:experimental FROM hamee/hoge_appenv:1.0.1 MAINTAINER Takahiro.Kikumoto

    WORKDIR /root RUN --mount=type=bind,target=. \ mitamae local ./docker/itamae/recipe.rb && \ rm -rf /var/cache/yum/* && \ yum clean all EXPOSE 80 ENTRYPOINT [\ "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf", \ "--", \ "/usr/local/bin/start.sh" \ ]
  20. Dockerfile 20 # syntax = docker/dockerfile:experimental FROM hamee/hoge_appenv:1.0.1 MAINTAINER Takahiro.Kikumoto

    WORKDIR /root RUN --mount=type=bind,target=. \ mitamae local ./docker/itamae/recipe.rb && \ rm -rf /var/cache/yum/* && \ yum clean all EXPOSE 80 ENTRYPOINT [\ "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf", \ "--", \ "/usr/local/bin/start.sh" \ ] mitamae local ./docker/itamae/recipe.rb
  21. mitamae ★ itamaeのmruby実装 ◦ ワンバイナリ(rubyランタイム不要!) ◦ itamae ▪ 構成管理ツール ▪

    Chefの簡易版みたいな感じ ◦ 採用理由 ▪ もともとChefの資産があった ▪ Dockerfileが長大になるのを避けたかった • 逆に、itamaeを知る必要あるのだけど。 21
  22. Dockerfile 22 # syntax = docker/dockerfile:experimental FROM hamee/hoge_appenv:1.0.1 MAINTAINER Takahiro.Kikumoto

    WORKDIR /root RUN --mount=type=bind,target=. \ mitamae local ./docker/itamae/recipe.rb && \ rm -rf /var/cache/yum/* && \ yum clean all EXPOSE 80 ENTRYPOINT [\ "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf", \ "--", \ "/usr/local/bin/start.sh" \ ] # syntax = docker/dockerfile:experimental RUN --mount=type=bind,target=.
  23. BuildKit ★ BuildKitを利用 ◦ export DOCKER_BUILDKIT=1 ◦ Dockerfile frontend experimental

    syntaxes ▪ RUN --mount=type=bind ▪ Itamaeのレシピをイメージにコピーすることなくコ ンテナにマウントして利用できる。 • 不要なDockerレイヤー削除 • COPY不要によるビルド時間短縮 23
  24. Dockerfile 24 # syntax = docker/dockerfile:experimental FROM hamee/hoge_appenv:1.0.1 MAINTAINER Takahiro.Kikumoto

    WORKDIR /root RUN --mount=type=bind,target=. \ mitamae local ./docker/itamae/recipe.rb && \ rm -rf /var/cache/yum/* && \ yum clean all EXPOSE 80 ENTRYPOINT [\ "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf", \ "--", \ "/usr/local/bin/start.sh" \ ] "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf",
  25. entrykit ★ entrykitを利用 ◦ https:/ /github.com/progrium/entrykit ◦ 起動時にテンプレートおよび環境変数 からファイル生成したり、事前コマンド の実行とか、引数に応じて実行プロセ

    スを変えるとか。 ◦ 今回は、テンプレートからのファイル生 成用途 25
  26. entrykit 26 mailhub={{ var "SMTP_ADDR" | default "localhost" }}:{{ var

    "SMTP_PORT" | default "25" }} /etc/ssmtp/ssmtp.conf.tmpl Docker run \ --env-file=env.txt SMTP_ADDR=172.30.1.1 SMTP_PORT=25 env.txt mailhub=172.30.1.1:25 /etc/ssmtp/ssmtp.conf
  27. Dockerfile 27 # syntax = docker/dockerfile:experimental FROM hamee/hoge_appenv:1.0.1 MAINTAINER Takahiro.Kikumoto

    WORKDIR /root RUN --mount=type=bind,target=. \ mitamae local ./docker/itamae/recipe.rb && \ rm -rf /var/cache/yum/* && \ yum clean all EXPOSE 80 ENTRYPOINT [\ "render", \ "/path/to/hogeapp/config.ini", \ "/etc/ssmtp/ssmtp.conf", \ "--", \ "/usr/local/bin/start.sh" \ ] /usr/local/bin/start.sh
  28. コンテナの動作変更 ★ docker run の引数で動作モードを 制御 ◦ entrykit の switch

    では、引数を渡すこ とができなかった。 28 #!/bin/sh mode=$1 shift case $mode in "php") exec /usr/bin/php "$@" ;; "webapp") exec /usr/sbin/httpd -D FOREGROUND ;; *) exec /bin/bash "$@" ;; esac
  29. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 29 Agenda
  30. ピタゴラスイッチ 30 Dockerビルド AWS Systems Manager Run Command deploy script

    Appサーバ push hook push pull api exec 新コンテナ
  31. CircleCIでのポイント ★ BuildKit利用、mountも。 ◦ docker executor ▪ dockerのバージョンは新しい • BuildKitはサポートしているバージョン

    ▪ mountができない。 ◦ machine executor ▪ デフォルトイメージでは、dockerのバージョン が古い ▪ ubuntu-1604:201903-01 を使用 • https://circleci.com/docs/ja/2.0/configuration-reference/#machine 31
  32. AWS Systems Manager ★ オンプレマシンもAWSの仕組みで 管理できる(雑) ◦ agentを動かして、登録。 32

  33. AWS Systems Manager ★ Run Command ◦ 管理サーバ上でスクリプトを実行可能。 ◦ 対象をタグで一括指定。

    ◦ CircleCIから以下を実行している。 33 aws ssm send-command \ --document-name "Our-Deploy" \ --parameters "{\"tag\":[\"$VERSION\"]}" \ --timeout-seconds 600 \ --max-concurrency "50" \ --targets Key=tag:Deployable,Values=Yes \ Key=tag:Environment,Values=Staging \ ...
  34. Blue-Green Deploy ★ 無停止デプロイへの課題 ◦ コンテナを入れ替える必要 ◦ コンテナポートをEXPORTする場合は、リバ プロ側の設定を変更する必要。 ▪

    リバプロ側のリロード処理も必要。 実行タイミング調整悩ましい。 ◦ Docker Swarmとか、k8sとか大掛かりな物 を導入したくなかった。 ▪ どのみちECSを目指しているし。 34
  35. Blue-Green Deploy ★ LVSを採用 ◦ Linux Virtual Server ◦ L4

    Load Balancer ◦ LVSが外向けにPORT (80) をLISTEN ◦ パケットの転送先にコンテナを指定 ◦ 新コンテナ起動後、health checkしてOKな ら、LVSに組み込む。 ◦ 古いコンテナはLVSから外して、graceful shutdown。 35 Ask The Speaer でのご指摘。 同時に新旧混在があるので、これは Rolling Updateですね。正しくは。 資料はそのままにしておきます。
  36. Blue-Green Deploy 36 リバプロ Appサーバ 旧イメージベースの コンテナ LVS upstream backend

    { server 192.168.3.14; server 192.168.3.15; ... } 192.168.3.14 PORT 80 PORT 80
  37. Blue-Green Deploy 37 リバプロ Appサーバ 旧イメージベースの コンテナ LVS 192.168.3.14 PORT

    80 PORT 80 新イメージベースの コンテナ PORT 80 起動確認
  38. Blue-Green Deploy 38 リバプロ Appサーバ 旧イメージベースの コンテナ LVS 192.168.3.14 PORT

    80 PORT 80 新イメージベースの コンテナ PORT 80
  39. Blue-Green Deploy 39 リバプロ Appサーバ 旧イメージベースの コンテナ LVS 192.168.3.14 PORT

    80 PORT 80 新イメージベースの コンテナ PORT 80
  40. Blue-Green Deploy 40 リバプロ Appサーバ 旧イメージベースの コンテナ LVS 192.168.3.14 PORT

    80 PORT 80 新イメージベースの コンテナ PORT 80 graceful shutdown (SIGWINCH)
  41. ❖ 背景 ❖ システムの動作まわり ❖ Docker Image ❖ CI/CD ❖

    開発環境 41 Agenda
  42. 開発環境(ローカルマシン) ★ 同じコンテナイメージを利用 ◦ ここはまだ悩んでいる ★ docker-compose を利用 ◦ 本番構成と同じ構成になるだけ近づける

    ために、リバプロコンテナ、fluentdコンテナ など、開発環境だけのコンテナイメージも 作成 ◦ PHPソースは、ローカルディレクトリをマウ ントしてそれが動作するようにしている。 42
  43. 開発環境(ローカルマシン) ★ メールは、mailcatcherを利用して、実 際には送信されないように ◦ これもコンテナなので、実際にノーマルな MTAがインストールされたコンテナに差し 替えることで、実際に送信できるようにもし ている。 43

  44. まとめ 44

  45. ★ PHPコンテナを動かす際に実際に取 り組んだことを話しました。 ◦ ひたすら泥臭く実装した感じです。 ◦ AWS環境移行時のイメージが具体化さ せるということはできた。 ★ 何か参考にでもなれば幸いです。

    45
  46. ご清聴ありがとうご ざいました。 46