Redis と PHP を使用したゲストブックの作成

このチュートリアルでは、Container Engine を使用して簡単な多層ウェブ アプリケーションを構築する方法を説明します。チュートリアル アプリケーションとしてゲストブックを使用します。訪問者はログにテキストを入力し、最新のログエントリを何件か見ることができます。

このチュートリアルでは、ロードバランサを使用して外部 IP にゲストブック ウェブサービスを設定する方法、および単一のマスターと複数のワーカーを使用して Redis クラスタを実行する方法を説明します。

この例では Container Engine の重要な概念をいくつか取り上げます。

  • 宣言型の構成: 構成には YAML マニフェスト ファイルを使用します
  • デプロイ: Kubernetes の概念で、これによりレプリカポッドのセットを維持します
  • サービス: 一連のポッド用の内部および外部ロードバランサを作成します

始める前に

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

    課金の有効化

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

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

設定ファイルのダウンロード

Kubernetes GitHub レポジトリにアクセスし、このチュートリアルで使用する設定ファイルをダウンロードします。

Container Engine クラスタの作成

最初に Container Engine クラスタを作成します。ゲストブック アプリケーションと Redis サービスはこの上で実行します。

3 ノードの guestbook という名前のコンテナ クラスタを作成します。

gcloud container clusters create guestbook --num-nodes=3

次のコマンドを使用すると、プロジェクト内のクラスタを一覧表示したり、単一のクラスタの詳細を取得したりできます。

gcloud container clusters list
gcloud container clusters describe guestbook

クラスタでのゲストブック アプリの実行

Container Engine でのゲストブック アプリケーションのデプロイと実行は、次の手順で行う必要があります。

  1. Redis マスターを設定します
  2. Redis ワーカーを設定します
  3. ゲストブック ウェブ フロントエンドを設定します
  4. ゲストブックのウェブサイトにアクセスします
  5. ゲストブック ウェブ フロントエンドをスケールアップします

ステップ 1: Redis マスターを設定する

ゲストブック アプリケーションは Redis を使用してデータを保存します。Redis マスター インスタンスにデータを書き込み、複数の Redis ワーカー(スレーブ)インスタンスからデータを読み取ります。最初のステップは、Redis マスターをデプロイすることです。

Redis マスターをデプロイするには、redis-master-deployment という名前のマニフェスト ファイルを使用します。このマニフェスト ファイルでは、単一のレプリカ Redis マスターポッドを実行するデプロイ コントローラを指定します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis-master
  # these labels can be applied automatically
  # from the labels in the pod template if not set
  # labels:
  #   app: redis
  #   role: master
  #   tier: backend
spec:
  # this replicas value is default
  # modify it according to your case
  replicas: 1
  # selector can be applied automatically
  # from the labels in the pod template if not set
  # selector:
  #   matchLabels:
  #     app: guestbook
  #     role: master
  #     tier: backend
  template:
    metadata:
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      containers:
      - name: master
        image: gcr.io/google_containers/redis:e2e  # or just image: redis
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379

次のコマンドを実行して、Redis マスターをデプロイします。

kubectl create -f redis-master-deployment.yaml

kubectl get pods を実行して、Redis マスターポッドが実行されていることを確認します。

kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
redis-master-343230949-qfvrq   1/1       Running   0          43s

前のコマンドの出力からポッド名をコピーし、次のコマンドを実行して、Redis マスターポッドのログを確認します。

kubectl logs -f POD-NAME

redis-master サービスの作成

ゲストブック アプリケーションは、データを書き込むために Redis マスターと通信する必要があります。Redis マスターポッドにトラフィックをプロキシするサービスを作成する必要があります。

Kubernetes において、サービスとはポッドの論理セットとポッドへのアクセスに使われるポリシーの定義を抽象化したものです。実際上は、トラフィックを 1 つまたは複数のポッドにプロキシする名前付きロードバランサです。サービスを設定するときには、プロキシ先のポッドをポッドのラベルで指定します。

Redis マスターのサービス リソースが記述されている redis-master-service.yaml マニフェスト ファイルを次に示します。

apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    app: redis
    role: master
    tier: backend
spec:
  ports:
    # the port that this service should serve on
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
    role: master
    tier: backend

このマニフェスト ファイルは、ラベルセレクタのセットを使用して redis-master という名前のサービスを作成します。これらのラベルは、前のステップでデプロイしたラベルのセットと一致します。したがって、このサービスは、ステップ 1 で作成した Redis マスターポッドにネットワーク トラフィックをルーティングします。

マニフェストの ports セクションでは、1 つのポート マッピングが宣言されています。この場合、サービスは、port: 6379 のトラフィックを、指定されている selector ラベルと一致するコンテナの targetPort: 6379 にルーティングします。デプロイにトラフィックをルーティングするには、デプロイで使用されている containerPorttargetPort と一致する必要があるのでご注意ください。

次のコマンドを実行して、Redis マスターのサービスを起動します。

kubectl create -f redis-master-service.yaml

サービスが作成されたことを確認します。

kubectl get service

NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.51.240.1     <none>        443/TCP    42s
redis-master   10.51.242.233   <none>        6379/TCP   12s

ステップ 2: Redis ワーカーを設定する

Redis マスターは単一のポッドですが、少数の Redis ワーカー レプリカを追加することで、可用性を高め、トラフィックの需要を満たすことができます。

Redis ワーカーポッドのデプロイが記述されている redis-slave-deployment.yaml マニフェスト ファイルを次に示します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis-slave
  # these labels can be applied automatically
  # from the labels in the pod template if not set
  # labels:
  #   app: redis
  #   role: slave
  #   tier: backend
spec:
  # this replicas value is default
  # modify it according to your case
  replicas: 2
  # selector can be applied automatically
  # from the labels in the pod template if not set
  # selector:
  #   matchLabels:
  #     app: guestbook
  #     role: slave
  #     tier: backend
  template:
    metadata:
      labels:
        app: redis
        role: slave
        tier: backend
    spec:
      containers:
      - name: slave
        image: gcr.io/google_samples/gb-redisslave:v1
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access an environment variable to find the master
          # service's host, comment out the 'value: dns' line above, and
          # uncomment the line below.
          # value: env
        ports:
        - containerPort: 6379

デプロイを行うと、マニフェスト ファイルで宣言されている設定を実現されます。たとえば、このマニフェスト ファイルでは、Redis ワーカーの 2 つのレプリカが定義されています。実行中のレプリカがない場合、デプロイはコンテナ クラスタで 2 つのレプリカを開始します。3 つ以上のレプリカが実行中の場合は、指定された設定を満たすためにいくつかのレプリカを停止させます。

この場合、デプロイ オブジェクトは 2 つのレプリカを指定します。Redis ワーカーのデプロイを作成するには、次のコマンドを実行します。

kubectl create -f redis-slave-deployment.yaml

ポッドのリストを照会して、2 つの Redis ワーカー レプリカが実行されていることを確認します。

$ kubectl get pods

NAME                           READY     STATUS    RESTARTS   AGE
redis-master-343230949-qfvrq   1/1       Running   0          17m
redis-slave-132015689-dp23k    1/1       Running   0          2s
redis-slave-132015689-xq9v0    1/1       Running   0          2s

redis-slave サービスの作成

ゲストブック アプリケーションは、データを読み取るために Redis ワーカーと通信する必要があります。Redis ワーカーを検出可能にするには、サービスを設定する必要があります。サービスは、一連のポッドに対して透過的な負荷分散を提供します。

redis-slave-service.yaml では、Redis ワーカーのサービス設定が定義されています。

apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    app: redis
    role: slave
    tier: backend
spec:
  ports:
    # the port that this service should serve on
  - port: 6379
  selector:
    app: redis
    role: slave
    tier: backend

このファイルでは、ポート 6379 で実行される redis-slave という名前のサービスが定義されています。サービスの selector フィールドは、前のステップで作成した Redis ワーカーポッドと一致することに注意してください。

次のコマンドを実行して、redis-slave サービスを作成します。

kubectl create -f redis-slave-service.yaml

サービスが作成されたことを確認します。

kubectl get service

NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.51.240.1     <none>        443/TCP    1m
redis-master   10.51.242.233   <none>        6379/TCP   49s
redis-slave    10.51.247.238   <none>        6379/TCP   3s

ステップ 3: ゲストブックのウェブ フロントエンドを設定する

ゲストブックの Redis ストレージが稼働したので、次にゲストブックのウェブサーバーを起動します。Redis ワーカーと同様、これはデプロイによって管理される複製されたサービスです。

このチュートリアルでは簡単な PHP フロントエンドを使用します。フロントエンドは、リクエストが読み取りか書き込みかに応じて、Redis ワーカー サービスまたはマスター サービスと通信するように設定されます。フロントエンドは簡単な JSON インターフェースを公開し、jQuery-Ajax ベースの UX を提供します。

ゲストブックのウェブサーバーのデプロイが記述されている frontend-deployment.yaml マニフェスト ファイルを次に示します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
  # these labels can be applied automatically
  # from the labels in the pod template if not set
  # labels:
  #   app: guestbook
  #   tier: frontend
spec:
  # this replicas value is default
  # modify it according to your case
  replicas: 3
  # selector can be applied automatically
  # from the labels in the pod template if not set
  # selector:
  #   matchLabels:
  #     app: guestbook
  #     tier: frontend
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below.
          # value: env
        ports:
        - containerPort: 80

ゲストブックのウェブ フロントエンドをデプロイするには、次のコマンドを実行します。

kubectl create -f frontend-deployment.yaml

ウェブ フロントエンドを示すラベルのリストを照会して、3 つのレプリカが実行されていることを確認します。

kubectl get pods -l app=guestbook -l tier=frontend

NAME                      READY     STATUS    RESTARTS   AGE
frontend-88237173-5p257   1/1       Running   0          40s
frontend-88237173-84036   1/1       Running   0          40s
frontend-88237173-j3rvr   1/1       Running   0          40s

上のマニフェスト ファイルでは、環境変数 GET_HOSTS_FROM=dns が指定されています。 この設定を提供されたゲストブックのウェブ フロントエンド アプリケーションは、ホスト名 redis-slaveredis-master を使用して DNS ルックアップを実行し、前のステップで作成した各サービスの IP アドレスを検索します。この概念は、DNS サービス検出と呼ばれます。

外部 IP アドレスでのフロントエンドの公開

前のステップで作成した redis-slave サービスと redis-master サービスは、サービスの種類がデフォルトの ClusterIP であるため、コンテナ クラスタ内でしかアクセスできません。ClusterIP は、サービスが指しているポッドのセットに対して単一の IP アドレスを提供します。この IP アドレスは、クラスタ内でのみアクセスできます。

しかし、ゲストブックのウェブ フロントエンド サービスは外部から認識できる必要があります。つまり、クライアントがコンテナ クラスタの外部からサービスをリクエストできるようにする必要があります。これを実現するには、サービス設定で type: LoadBalancer を指定します。frontend-service.yaml マニフェスト ファイルでは、この設定が次のように指定されています。

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  # type: LoadBalancer
  ports:
    # the port that this service should serve on
  - port: 80
  selector:
    app: guestbook
    tier: frontend

frontend サービスを作成するとき、Container Engine によりロードバランサと外部 IP アドレスが作成されます。これらのリソースは課金の対象となることに注意してください。ports セクションのポートの宣言では port: 80 が指定されており、targetPort は指定されていません。targetPort プロパティを省略すると、デフォルトで port フィールドの値になります。この場合、このサービスは、ポート 80 の外部トラフィックを、frontend のデプロイのコンテナのポート 80 にルーティングします。

サービスを作成するには、最初に、frontend-service.yaml ファイルで次の行のコメントを解除します。

 type: LoadBalancer

それから、次のコマンドを実行してサービスを作成します。

kubectl create -f frontend-service.yaml

ステップ 4: ゲストブックのウェブサイトにアクセスする

ゲストブックのサービスにアクセスするには、次のコマンドを実行して、先に設定したサービスの外部 IP を見つける必要があります。

kubectl get service frontend

NAME       CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
frontend   10.51.242.136   109.197.92.229     80:32372/TCP   1m

EXTERNAL-IP 列の IP アドレスをコピーし、ブラウザにページをロードします。

Container Engine で実行しているゲストブック

おめでとうございます。ゲストブックのエントリを追加してみてください。

ステップ 5: ウェブ フロントエンドをスケールアップする

ゲストブック アプリをしばらく運用していたら、アプリが突然注目を集めるようになったとします。そこで、フロントエンドのウェブサーバーを増やすことになりました。サーバーはデプロイ コントローラを使用するサービスとして定義されているので、増やすのは簡単です。

次のコマンドを実行して、frontend ポッドの数を 5 に増やします。

kubectl scale deployment frontend --replicas=5

デプロイの設定が、5 つのレプリカを実行するように更新されます。デプロイは、実行しているポッドの数をそれに合わせて調整します。これを確認するには、次のコマンドを実行します。

kubectl get pods

NAME                           READY     STATUS    RESTARTS   AGE
frontend-88237173-3s3sc        1/1       Running   0          1s
frontend-88237173-twgvn        1/1       Running   0          1s
frontend-88237173-5p257        1/1       Running   0          23m
frontend-88237173-84036        1/1       Running   0          23m
frontend-88237173-j3rvr        1/1       Running   0          23m
redis-master-343230949-qfvrq   1/1       Running   0          54m
redis-slave-132015689-dp23k    1/1       Running   0          37m
redis-slave-132015689-xq9v0    1/1       Running   0          37m

サイトへのアクセスが元のように少なくなったら、同じ方法でウェブサーバー ポッドの数を減らすことができます。

ステップ 6: クリーンアップする

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

  1. サービスを削除する: この手順では、frontend サービス用に作成された Cloud Load Balancer の割り当てを解除します。

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

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

    gcloud container clusters delete guestbook
    

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

Container Engine ドキュメント