Managed Service Column <システム運用コラム>

Kubernetes で WordPress サイトを公開してみる (運用編)

Category: 実践編

2020.05.18

はじめに

前回のブログでは、無事に WordPress サイトの公開までたどり着けました。
しかし、実際のサービスでは、構築したら終わりではなく、その後の運用のほうが大事です。そして、Kubernetes はむしろ、運用のほうで本領を発揮します。

今回は、運用のなかでも特に以下にポイントを絞って、Kubernetes の機能をみてみます。

  • アプリケーションのアップデート
  • Pod に障害が発生した際の自動復旧
  • スケールイン、スケールアウト

アプリケーションのアップデート

本番環境で新しいアプリケーションをリリースすることは非常に大変な作業です。
システムやアプリケーションによっては、ダウンタイムが発生するために、メンテナンス時間を設けなくてはいけないこともあります。
Kubernetes では、ダウンタイムなく、安全にアプリケーションのアップデートを行うことができます。

一例として、公式のイメージに少しだけ修正を加えたものをリリースしてみます。
前回の記事では wp-content 以下を Azure Files による共有領域としました。
実は、WordPress の Docker イメージは毎回、起動時にドキュメントルート以下にファイルを展開するため、
共有領域内のファイルを上書きしてしまいます。
(デフォルトファイルに修正を加えていない限り、影響はありませんが。)

これを解消するために、公式の Docker イメージをカスタマイズしてみましょう。

Azure Container Registory の準備

カスタマイズしたイメージを保管するためのレジストリを用意しましょう。
今回は、Azure にて用意されている Azure Container Registory (以下、ACR) を利用します。

ACR の画面を開きます。

レジストリ名やリージョンを選択します。

できました。

最後に、AKS から ACR にアクセスできるようにします。
これにより、マニュフェストにてレジストリ内のイメージを指定するだけで、AKS 上にデプロイすることができます。

rworks@Azure:~/build$ az aks update -n wordpress-cluster -g wordpress --attach-acr rworks

イメージのカスタマイズ

Docker ライブラリから、Dockerfile と docker-entrypoint.sh をダウンロードします。
https://github.com/docker-library/wordpress/tree/bf85cc7bf33afbbfadd86ba79b3d8ad325289057/php7.3/apache

rworks@Azure:~/docker/wordpress$ ls
docker-entrypoint.sh  Dockerfile

docker-entrypoint.sh は、Docker の起動時に実行されるスクリプトです。
このなかに、WordPress の初期設定を行うコマンドが羅列してあります。
ここに、「展開する前のファイル群から wp-content ディレクトリを削除する」行を追記します。

                if [ "$user" != '0' ]; then
                        # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted"
                        targetTarArgs+=( --no-overwrite-dir )
                fi
+               rm -rf /usr/src/wordpress/wp-content
                tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}"

編集した docker-entrypoint.sh を反映させたイメージを、ビルドして、ACR にプッシュします。
“az acr build” コマンドを利用すれば、Azure 側でビルドが行われ、そのまま ACR にプッシュしてくれます。
ローカルにビルドするための環境を用意する必要はありません。

rworks@Azure:~/build$ az acr build --image wordpress:v1 --registry rworks --file DockerFile .
Packing source code into tar to upload...
Uploading archived source code from '/tmp/build_archive_922bf1d4cc1a431f9250e90182156ebf.tar.gz'...
Sending context (349.000 Bytes) to registry: rworks...
Queued a build with ID: ce1
Waiting for an agent...
2020/04/13 14:53:56 Downloading source code...

- image:
    registry: rworks.azurecr.io
    repository: wordpress
    tag: v1
    digest: sha256:d9b24db8c01cf917cc17aeb48118a32293eb6fbf597a0b5154e9a51fd12c4257
  runtime-dependency:
    registry: registry.hub.docker.com
    repository: library/wordpress
    tag: latest
    digest: sha256:191d5caf4ef5b8c57721ade777820f3267654325f7902b2ccd377ceeba1c3fe2
  git: {}

Run ID: ce1 was successful after 1m4s

“rworks.azurecr.io/wordpress:v1” を指定して pull できるようになりました。

カスタマイズしたイメージのデプロイ

deployment.yaml を書き換えて、新しいイメージをデプロイしてみましょう。

deployment.yaml の image を ACR 上のイメージに書き換えます。

    spec:
      containers:
      #- image: wordpress
      - image: rworks.azurecr.io/wordpress:v1

deployment を更新します。

rworks@Azure:~$ kubectl apply -f deployment.yaml
deployment.apps/wordpress configured

古い Pod が削除されるのと同時に、新しい Pod が作成されます。
既定では、このようにローリングアップデートが行われます。

# 一時的に、Pod が2倍になります
rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS              RESTARTS   AGE
wordpress-5f59c6698b-cdjkq   0/1     ContainerCreating   0          0s      # ← 新しい Pod
wordpress-5f59c6698b-jh2r4   1/1     Running             0          5s      # ← 新しい Pod
wordpress-7b95946f7c-gdm8b   1/1     Running             0          88s     # ← 古い Pod
wordpress-7b95946f7c-vgnt4   1/1     Terminating         0          88s     # ← 古い Pod
rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS        RESTARTS   AGE
wordpress-5f59c6698b-cdjkq   1/1     Running       0          14s           # ← 新しい Pod
wordpress-5f59c6698b-jh2r4   1/1     Running       0          19s           # ← 新しい Pod
wordpress-7b95946f7c-gdm8b   1/1     Terminating   0          102s          # ← 古い Pod
wordpress-7b95946f7c-vgnt4   1/1     Terminating   0          102s          # ← 古い Pod
rworks@Azure:~$ kubectl get pod

# 最終的に、Pod が入れ替わります
rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
wordpress-5f59c6698b-cdjkq   1/1     Running   0          42s               # ← 新しい Pod
wordpress-5f59c6698b-jh2r4   1/1     Running   0          47s               # ← 新しい Pod

# レプリカセットは古いものも残ります。
rworks@Azure:~$ kubectl get rs
NAME                   DESIRED   CURRENT   READY   AGE
wordpress-5f59c6698b   2         2         2       51s     # ← image が wordpress:v1 のレプリカセット
wordpress-7b95946f7c   0         0         0       2m14s   # ← image が wordpress のレプリカセット

万が一、アプリケーションに問題が生じた場合は、簡単にロールバックができます。
マニュフェスト deployment.yaml を編集前のものに戻して、再度、kubectl apply を実行します。

    spec:
      containers:
      - image: wordpress
      # - image: rworks.azurecr.io/wordpress:v1

deployment を更新します。

rworks@Azure:~$ kubectl apply -f deployment.yaml
deployment.apps/wordpress configured

Pod は新しいものに置き換わっていますが、レプリカセットは一番初めのものに戻っていることが分かります。

# Pod は新しいものに入れ替わります
rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
wordpress-7b95946f7c-d826x   1/1     Running   0          23s
wordpress-7b95946f7c-q7b2l   1/1     Running   0          29s

# レプリカセットがロールバックされています。
rworks@Azure:~$ kubectl get rs
NAME                   DESIRED   CURRENT   READY   AGE
wordpress-5f59c6698b   0         0         0       11m    # ← image が wordpress:v1 のレプリカセット
wordpress-7b95946f7c   2         2         2       12m    # ← image が wordpress のレプリカセット

このように、ダウンタイムのないアプリケーションのアップデートを簡単に行うことができます。
(削除される Pod と作成される Pod のタイミングによってはダウンタイムが発生することもあるので、パラメータは調整する必要があります。)
CI ツールと連携することで、アプリケーションのアップデートを完全自動化することも可能です。

Pod に障害が発生した際の自動復旧

Pod には Probe (ヘルスチェック) を設定することができ、Probe に失敗した際には自動で復旧させることができます。
Probe の方法には、”livenessProbe” と “readinessProbe” の2つのタイプがあります。
Probe 失敗後のアクションに違いがあり、前者は Pod の再作成が行われ、後者はサービスからのトラフィックが停止します。
デフォルトでは、livenessProbe が有効になっています。

今回は、livenessProbe を利用することにします。”httpGet” を指定することで、パス / の HTTP ステータスコードをチェックすることにします。
deployment.yaml の “template” 内に、以下の行を追加します。

  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      #- image: wordpress
      - image: rworks.azurecr.io/wordpress:v1
        name: wordpress
        envFrom:                      # ← 接続情報と認証情報を key, value を全て読み込み
        - configMapRef:
            name: wp-configmap
        - secretRef:
            name: db-secret
        ports:
        - containerPort: 80
          name: wordpress
+        livenessProbe:
+          httpGet:
+            path: /
+            port: 80
+            scheme: HTTP
+          initialDelaySeconds: 30  # ← 初回の Probe は30秒待つ
+          periodSeconds: 10        # ← 10秒間隔で Probe を行う
+          timeoutSeconds: 5        # ← タイムアウトを5秒に

Pod と MySQL の間に何らかの問題が発生し、一時的に接続できなかった場合を想定します。
wp-config のデータベース接続情報を書き換え、擬似的にこの状況を再現してみます。

rworks@Azure:~$ kubectl exec -it wordpress-69b76dc56f-q4tgz /bin/bash
root@wordpress-69b76dc56f-q4tgz:/var/www/html# sed -i 's/wordpress-db-rworks.mysql.database.azure.com/hoge/' wp-config.php
root@wordpress-69b76dc56f-q4tgz:/var/www/html# grep HOST wp-config.php
define( 'DB_HOST', 'hoge');

上記の変更後、すぐに自動的に Pod が再作成されました。
EVents を見てみると、HTTP ステータスコード 500 が返ってきたことにより、Probe が失敗したあと、コンテナの再作成が行われていることがわかります。
Pod はマニュフェストから再作成されますので、当然、wp-config.php も元の正しい設定になっています。

rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
wordpress-69b76dc56f-5srbh   1/1     Running   0          5m28s
wordpress-69b76dc56f-q4tgz   1/1     Running   1          5m33s   # ← RESTART がカウントアップしています


rworks@Azure:~$ kubectl describe pod wordpress-69b76dc56f-q4tgz
[省略]
 
Events:
  Type     Reason     Age                 From                                        Message
  ----     ------     ----                ----                                        -------
  Normal   Scheduled  2m10s               default-scheduler                           Successfully assigned default/wordpress-69b76dc56f-q4tgz to aks-agentpool-23520908-vmss000000
  Warning  Unhealthy  20s (x3 over 40s)   kubelet, aks-agentpool-23520908-vmss000000  Liveness probe failed: HTTP probe failed with statuscode: 500
  Normal   Killing    20s                 kubelet, aks-agentpool-23520908-vmss000000  Container wordpress failed liveness probe, will be restarted
  Normal   Pulling    18s (x2 over 2m8s)  kubelet, aks-agentpool-23520908-vmss000000  Pulling image "rworks.azurecr.io/wordpress:v1"
  Normal   Pulled     18s (x2 over 2m6s)  kubelet, aks-agentpool-23520908-vmss000000  Successfully pulled image "rworks.azurecr.io/wordpress:v1"
  Normal   Created    17s (x2 over 2m6s)  kubelet, aks-agentpool-23520908-vmss000000  Created container wordpress
  Normal   Started    17s (x2 over 2m5s)  kubelet, aks-agentpool-23520908-vmss000000  Started container wordpress

このように、Kubernetes は障害発生時に自動で復旧することが分かりました。
これにより、常にマニュフェストで定義したとおりの状態が保たれます。

スケールイン、スケールアウト

Pod のスケールイン、スケールアウトは簡単です。
deployment.yaml の replicass の値を変更するだけです。

spec:
  #replicas: 2
  replicas: 4

deployment を更新します。

rworks@Azure:~$ kubectl apply -f deployment.yaml
deployment.apps/wordpress configured

Pod が倍になりました。

rworks@Azure:~$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
wordpress-f6997b7bc-4fdzt   1/1     Running   0          7s
wordpress-f6997b7bc-6ttrn   1/1     Running   0          7s
wordpress-f6997b7bc-7tqnv   1/1     Running   0          15m
wordpress-f6997b7bc-q4jth   1/1     Running   1          15m

今回は手動で Pod の数を調整しましたが、オートスケール設定を行うことも可能です。

まとめ

コンテナの運用する際にポイントとなる、3つの機能について見てみました。
このように、Kubernetes はコンテナの運用を行う上での強力なツールとなることが分かっていただけたのではないでしょうか。
実際に本番環境にて運用する際には、さらに細かい調整が必要になりますが、一連のブログで「Kubernetes とは何なのか」「Kubernetes では何が出来るのか」をいただき、Kubernetes 利用の手助けになれば幸いです。

Tag: コンテナ Kubernetes

Contactお問い合わせ

お見積もり・ご相談など、お気軽にお問い合わせください。

single.php