WordPress と MySQL での永続ディスクの使用

このチュートリアルでは、クラスタに単一レプリカ WordPress デプロイと、単一レプリカ MySQL データベースを設定する方法を説明します。これらのアプリケーションはいずれも、永続ディスクをストレージに使用します。永続ディスクは、アプリケーションのインスタンスが再起動されたとき、またはアプリケーションのコンテナがコンテナ クラスタの別のノードで再スケジュールされたときに、データを保持します。

背景

WordPress はブログツールです。ブログ記事を保存するためのデータベースとして MySQL を使用し、ブログ投稿内の画像などのアセットや拡張機能の保存にはローカル ファイルシステムを使用しています。このチュートリアルでは、Docker Hub で公開されている公式の MySQLWordPress のコンテナ イメージを使用します。

一般に、コンテナのルート ファイルシステムは永続データを格納するのに適していません。通常、Kubernetes Engine で実行するコンテナは廃棄可能なエンティティであり、ノードの障害やその他の原因によって使用できなくなったコンテナは、クラスタ マネージャによって削除、強制排除、再スケジュールされる可能性があります。このような場合、コンテナのルート ファイルシステムに保存されたすべてのデータは失われます。

永続ディスクを使用すると、WordPress や MySQL のアプリケーションのデータをコンテナの外部に保存することができます。この方法を使用すると、たとえコンテナが削除されても、そのデータは保持されます。

このチュートリアルでは、MySQL 用と WordPress 用の 2 つの Deployment を作成します。どちらの Deployment も、各ポッドのレプリカを 1 つだけ実行します。

次に、2 つの Service を作成します。1 つは WordPress コンテナが MySQL コンテナと通信するためのものです。もう 1 つはロードバランサを使用して WordPress の Deployment を外部 IP アドレスでインターネットに公開するためのものです。

始める前に

次の手順に従って Google Kubernetes Engine API を有効にします。
  1. Google Cloud Platform Console で Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。これには数分かかることがあります。
  4. プロジェクトの課金を有効にします。

    課金の有効化

このチュートリアルで使用されている以下のコマンドライン ツールをインストールします。

  • Kubernetes Engine クラスタを作成および削除するには、gcloud を使用します。gcloudGoogle Cloud SDK に含まれています。
  • kubectl は、Kubernetes Engine で使用されるクラスタ オーケストレーション システムである Kubernetes を管理するために使用されます。gcloud を使用して kubectl をインストールできます。
    gcloud components install kubectl

gcloud コマンドライン ツールのデフォルトを設定する

次のコマンドを実行してデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト IDCompute Engine ゾーンの各オプションを入力する時間を節約できます。
gcloud config set project [PROJECT_ID]
gcloud config set compute/zone us-central1-b

アプリケーション マニフェストのダウンロード

このチュートリアルでは、YAML 形式のマニフェスト ファイルを使用して必要な Kubernetes オブジェクトを作成します。

このアプローチは、宣言的オブジェクト管理と呼ばれます。これらのファイルを使用して、端末で次のコマンドを実行し、GitHub レポジトリからマニフェスト ファイルをダウンロードしてください。

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/wordpress-persistent-disks

git がシステムにインストールされていない場合は、以下のリンクからダウンロードできます)。

ステップ 1: Kubernetes Engine クラスタを作成する

最初のステップは、WordPress と MySQL のアプリケーション コンテナをホストする Kubernetes Engine クラスタを作成することです。次のコマンドは、3 つのノードを持つ persistent-disk-tutorial という名前のクラスタを作成します。

gcloud container clusters create persistent-disk-tutorial --num-nodes=3

ステップ 2: 永続ディスクを作成する

このチュートリアルでは永続ディスクを利用します。これにより、ポッドが再起動されるとき、またはアプリケーションのクラッシュやノードの再起動などの理由でポッドが他のノードで再スケジューリングされるときに、アプリケーションが自分のストレージを保持できます。

この例では 2 つのディスクが必要です。1 つは MySQL データベースがデータを格納するためのもので、もう 1 つは WordPress がアセットをファイルシステムに格納するためのものです。これらの永続ディスクを作成するには、次のコマンドを実行します。

gcloud compute disks create --size 200GB mysql-disk
gcloud compute disks create --size 200GB wordpress-disk

ステップ 3: MySQL をセットアップする

MySQL をデプロイする

MySQL をデプロイする最初のステップは、データベースのパスワードを格納する Kubernetes シークレットを作成することです。mysql という名前の Secret を作成するには、次のコマンドを実行します(YOUR_PASSWORD は適当なパスフレーズで置き換えてください)。

kubectl create secret generic mysql --from-literal=password=YOUR_PASSWORD

次に、mysql.yaml マニフェスト ファイルを使用して、ポート 3306 で動作する単一インスタンスの MySQL アプリケーションをデプロイします。mysql.yaml ファイルは次のようになります。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql
                  key: password
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          gcePersistentDisk:
            pdName: mysql-disk
            fsType: ext4

このマニフェストには単一インスタンスの MySQL ポッドの Deployment が記述されています。ポッドには、作成したシークレットから値が設定される MYSQL_ROOT_PASSWORD 環境変数が含まれています。MySQL コンテナは、/var/lib/mysql にマウントされた永続ディスクを使用します。

このマニフェスト ファイルをデプロイするには、次のコマンドを実行します。

kubectl create -f mysql.yaml

ポッドが実行されているかどうかを確認します。永続ディスクをコンピューティング ノードにアタッチするのにしばらく時間がかかるため、ポッドが Running ステータスに移行するまでに数分かかる場合があります。

$ kubectl get pod -l app=mysql
NAME                 READY     STATUS    RESTARTS   AGE
mysql-259040-flmqh   1/1       Running   0          3m

MySQL サービスを作成する

次に、MySQL コンテナを公開する Service を作成し、後で作成する wordpress コンテナからアクセスできるようにします。

mysql-service.yaml で定義された次のような Service マニフェストを使用します。

apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
  selector:
    app: mysql

このマニフェストに記述されている Service は、ラベル app: mysql と一致するポッド用のクラスタ IP をポート 3306 上に作成します。前のステップでデプロイした mysql コンテナにこのラベルが付けられます。この例では、Service に type:ClusterIP を使用します。これにより、この Service はクラスタ内からのみ到達できるようになります。

作成されたクラスタ IP は、クラスタ内のすべてのコンピューティング ノードからのトラフィックを MySQL コンテナにルーティングし、クラスタ外のクライアントからはアクセスできません。Service が作成されると、wordpress コンテナは、同じコンピューティング ノードに存在しない場合でも、mysql コンテナの DNS 名を使用して通信することができます。

このマニフェスト ファイルをデプロイするには、次のコマンドを実行します。

kubectl create -f mysql-service.yaml

サービスが作成されているかどうかを確認します。

$ kubectl get service mysql
NAME      CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
mysql     10.51.240.175   <none>        3306/TCP   4m

以上で、新しい WordPress ブログ用のデータベースの設定が完了しました。

ステップ 4: WordPress をセットアップする

WordPress をデプロイする

次に、WordPress コンテナをコンテナ クラスタにデプロイします。wordpress.yaml マニフェスト ファイルを使用して、単一インスタンスの WordPress コンテナをデプロイします。

wordpress.yaml は次のようになります。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - image: wordpress
          name: wordpress
          env:
          - name: WORDPRESS_DB_HOST
            value: mysql:3306
          - name: WORDPRESS_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql
                key: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
      volumes:
        - name: wordpress-persistent-storage
          gcePersistentDisk:
            pdName: wordpress-disk
            fsType: ext4

このマニフェストには、単一インスタンスの WordPress ポッドのデプロイが記述されています。このコンテナは WORDPRESS_DB_PASSWORD 環境変数の値を、前に作成したデータベース パスワード Secret から読み取ります。

また、このマニフェストは、ホストアドレス mysql:3306 で MySQL と通信するように WordPress コンテナを設定します。この値は、WORDPRESS_DB_HOST 環境変数で設定されています。Kubernetes DNS により、ポッドは名前を使って Service と通信できるため、mysql という名前でデータベースを参照できます。

このマニフェスト ファイルをデプロイするには、次のコマンドを実行します。

kubectl create -f wordpress.yaml

ポッドが実行されているかどうかを確認します。永続ディスクをコンピューティング ノードにアタッチするのにしばらく時間がかかるため、ポッドが Running ステータスに移行するまでに数分かかる場合があります。

$ kubectl get pod -l app=wordpress
NAME                     READY     STATUS    RESTARTS   AGE
wordpress-387015-02xxb   1/1       Running   0          9h

WordPress サービスを公開する

前のステップでデプロイした WordPress コンテナは、外部 IP アドレスを持たないため、現在はクラスタ外からアクセスできません。

ロードバランサ(課金対象)を使用して WordPress アプリケーションをインターネットからのトラフィックに公開するには、type:LoadBalancer を設定した Service が必要です。

wordpress-service.yaml ファイルには、この Service のマニフェストが含まれており、内容は次のようになります。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress
  name: wordpress
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    app: wordpress

このマニフェスト ファイルをデプロイするには、次のコマンドを実行します。

kubectl create -f wordpress-service.yaml

このマニフェストをデプロイすると、ロードバランサが作成されます。作成には数分かかることがあります。次のコマンドを実行して、ブログの外部 IP アドレスを調べます。

$ kubectl get svc -l app=wordpress
NAME        CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
wordpress   10.51.243.233   203.0.113.3    80:32418/TCP   1m

上記の出力で、EXTERNAL-IP 列にはブログ用に作成されたパブリック IP アドレスが表示されます。次のステップのために、この IP アドレスを控えておきます。

これで、WordPress ブログのデプロイと公開が完了しました。

ステップ 5: 新しい WordPress ブログにアクセスする

ブログの IP アドレスを確認した後、ブラウザでその IP アドレスを指定すると、WordPress のインストール画面が次のように表示されます。

Wordpress インストール画面のスクリーンショット

WordPress の設定が完了したら、ブラウザで再度 WordPress アプリの IP アドレスを指定して、ブログにアクセスします。すべてが期待どおりに機能しています。

ステップ 6:(オプション)障害発生時のデータの永続性をテストする

永続ディスクの場合、データはアプリケーション コンテナの外部に存在します。コンテナが使用不能になり、Kubernetes によって別のコンピューティング インスタンス上でコンテナが再スケジュールされると、Kubernetes Engine は新しくポッドが起動されたインスタンスで永続ディスクを使用できるようにします。

$ kubectl get pods -o=wide
NAME                   ...  IP          NODE
mysql-259040-flmqh     ...  10.48.2.8   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4
wordpress-387483-02xxb ...  10.48.2.7   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4

ここで、次のコマンドを実行して mysql ポッドを削除します。

kubectl delete pod -l app=mysql

mysql ポッドが削除されると、デプロイ コントローラはポッドがないことを認識して、ポッドを再作成します。新しい mysql ポッドは、以前実行されていたノードとは異なるノードで起動する可能性があります。

次のコマンドを再び実行し、mysql ポッドが以前とは異なるコンピューティング インスタンスでスケジュールされていることを確認します(そうなっていない場合は、別の場所で実行されるようになるまでポッドを再び削除してください)。

$ kubectl get pods -o=wide
NAME                   ...  IP          NODE
mysql-259040-flmqh     ...  10.48.2.8   gke-persistent-disk-tutorial-default-pool-fe4fe9af-vg56
wordpress-387483-02xxb ...  10.48.2.7   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4

既存のポッドを削除して新しいポッドがクラスタ内の別のインスタンスでスケジュールされた後でもウェブサイトが正常に機能していてデータが保持されていることを確認するため、もう一度ブログにアクセスしてください。

ステップ 7: アプリケーション イメージを更新する

デプロイしたソフトウェアは最新の状態に保つことが重要です。たとえば、WordPress で更新が必要な脆弱性が報告される可能性があります。WordPress のコンテナ イメージを更新するには、Docker Hub で最新バージョン(wordpress.yaml ファイルの値)のイメージを探し更新します。更新を適用するには、次のコマンドを実行します。

kubectl apply -f wordpress.yaml

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

このチュートリアルを完了したら、アカウントで不要な請求が発生しないように、以下の手順でリソースを削除します。

  1. Service を削除する: wordpress Service 用に作成された Cloud Load Balancer の割り当てを解除します。

    kubectl delete service wordpress
    
  2. wordpress Service 用にプロビジョニングされたロードバランサが削除されるのを待つ: kubectl delete を実行すると、ロードバランサがバックグラウンドで非同期に削除されます。次のコマンドの出力を監視して、ロードバランサが削除されるまで待ちます。

    gcloud compute forwarding-rules list
    
  3. コンテナ クラスタを削除する: コンテナ クラスタを構成するリソース(コンピューティング インスタンス、ディスク、ネットワーク リソースなど)を削除します。

    gcloud container clusters delete persistent-disk-tutorial
    
  4. 永続ディスクを削除する: WordPress および MySQL アプリケーション用に作成されたディスクを削除します。

    gcloud compute disks delete mysql-disk wordpress-disk
    

次のステップ

フィードバックを送信...

Kubernetes Engine のドキュメント