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

D9b4364dacae526c391909272bbb91ed?s=47 kikumoto
February 11, 2020

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

D9b4364dacae526c391909272bbb91ed?s=128

kikumoto

February 11, 2020
Tweet

Transcript

  1. 2.

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

    小田原にあります! ◦ ランチセッションにGo! ★ お仕事: SRE、マネージャー ★ その他 ◦ PHPerKaigi 2020 当日スタッフ 2
  2. 7.

    AWSへ移行したい 7 ELB ECS Webリクエスト処理 Apache mod_php AWS Batch Lambda

    SNS SQS SES CloudWatch Events メール受信処理 バッチ処理
  3. 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 \ <略>
  4. 12.

    ログ収集 - その他ログ ★ 各コンテナはdockerホスト上のディレク トリをマウント ◦ ログはホスト上に出力される ★ docker

    ホスト上で fluent-agent-chimeraを動かしている ◦ 拙作 -https://kikumoto.hatenablog.com/entry/2018/02/02/095629 ◦ fluent-agent-hydraをベース ◦ 動的に生成されるログを取り込み fluent-agent-hydraに転送 12
  5. 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するスクリプト>
  6. 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 \ <略>
  7. 16.

    メール送信 ★ コンテナ内からメール送信 ◦ ssmtp を利用 ▪ sendmail_path = /usr/sbin/ssmtp

    -t ▪ ssmtp.conf 16 mailhub=172.30.1.1:25 FromLineOverride=yes コンテナネットワーク上で のdocker ホストのIPと MTAのポート
  8. 18.

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

    アプリケーションが依存する外部 ツールやライブラリ アプリケーションコードや 設定 変更の頻度を意識し た構成 通常時は最上位の イメージをビルドす るだけ。
  9. 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" \ ]
  10. 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
  11. 21.

    mitamae ★ itamaeのmruby実装 ◦ ワンバイナリ(rubyランタイム不要!) ◦ itamae ▪ 構成管理ツール ▪

    Chefの簡易版みたいな感じ ◦ 採用理由 ▪ もともとChefの資産があった ▪ Dockerfileが長大になるのを避けたかった • 逆に、itamaeを知る必要あるのだけど。 21
  12. 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=.
  13. 23.

    BuildKit ★ BuildKitを利用 ◦ export DOCKER_BUILDKIT=1 ◦ Dockerfile frontend experimental

    syntaxes ▪ RUN --mount=type=bind ▪ Itamaeのレシピをイメージにコピーすることなくコ ンテナにマウントして利用できる。 • 不要なDockerレイヤー削除 • COPY不要によるビルド時間短縮 23
  14. 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",
  15. 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
  16. 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
  17. 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
  18. 30.

    ピタゴラスイッチ 30 Dockerビルド AWS Systems Manager Run Command deploy script

    Appサーバ push hook push pull api exec 新コンテナ
  19. 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
  20. 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 \ ...
  21. 34.

    Blue-Green Deploy ★ 無停止デプロイへの課題 ◦ コンテナを入れ替える必要 ◦ コンテナポートをEXPORTする場合は、リバ プロ側の設定を変更する必要。 ▪

    リバプロ側のリロード処理も必要。 実行タイミング調整悩ましい。 ◦ Docker Swarmとか、k8sとか大掛かりな物 を導入したくなかった。 ▪ どのみちECSを目指しているし。 34
  22. 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ですね。正しくは。 資料はそのままにしておきます。
  23. 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
  24. 37.

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

    80 PORT 80 新イメージベースの コンテナ PORT 80 起動確認
  25. 40.

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

    80 PORT 80 新イメージベースの コンテナ PORT 80 graceful shutdown (SIGWINCH)
  26. 42.

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

    ために、リバプロコンテナ、fluentdコンテナ など、開発環境だけのコンテナイメージも 作成 ◦ PHPソースは、ローカルディレクトリをマウ ントしてそれが動作するようにしている。 42