Redis と PHP を使用して多層ウェブ アプリケーションを作成する

このチュートリアルでは、Google Kubernetes Engine(GKE)を使用して多層ウェブ アプリケーションを構築する方法を説明します。

このチュートリアルでは、次のことを行います。

  • 外部 IP アドレスとロードバランサを使用してウェブ アプリケーションを設定する。
  • 1 つのマスター(リーダー)と複数のレプリカ(フォロワー)を持つ Redis クラスタを作成する。

この例では、Kubernetes の次のコンセプトについて説明します。

  • 宣言型の構成: 構成には YAML マニフェスト ファイルを使用します。
  • Deployment: 複製された一連の Pod の構成を決定する Kubernetes リソースです。
  • Service: 一連の Pod に内部および外部ロードバランサを作成します。

環境を準備する

環境の設定手順は次のとおりです。

  1. 環境変数を設定します。

    export PROJECT_ID=PROJECT_ID
    export COMPUTE_LOCATION=COMPUTE_LOCATION
    

    次のように置き換えます。

  2. GitHub リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. 作業ディレクトリを変更します。

    cd kubernetes-engine-samples/quickstarts/guestbook/
    

GKE クラスタを作成する

GKE の Autopilot クラスタまたは Standard クラスタを作成します。

Autopilot

gcloud container clusters create-auto guestbook \
    --location=${COMPUTE_LOCATION} \

Standard

gcloud container clusters create guestbook \
    --location=${COMPUTE_LOCATION} \
    --num-nodes=4

クラスタに接続する

クラスタと通信を行うように kubectl を構成します。

gcloud container clusters get-credentials guestbook \
    --location=${COMPUTE_LOCATION}

Redis リーダーを設定する

このアプリケーションは Redis を使用してデータを保存します。アプリケーションは、Redis リーダー インスタンスにデータを書き込み、複数の Redis フォロワー インスタンスからデータを読み取ります。

  1. 次のマニフェストには、単一のレプリカ Redis リーダー Pod を実行する Kubernetes Deployment が記述されています。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: leader
            tier: backend
        spec:
          containers:
          - name: leader
            image: "docker.io/redis:6.0.5"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379

    マニフェストをクラスタに適用します。

    kubectl apply -f redis-leader-deployment.yaml
    
  2. Redis リーダー Pod が動作していることを確認します。

    kubectl get pods
    

    出力は次のようになります。

    NAME                           READY     STATUS    RESTARTS   AGE
    redis-leader-343230949-qfvrq   1/1       Running   0          43s
    

    STATUSPending から Running に変わるまでに数分かかることがあります。

Redis リーダー Service を作成する

このウェブ アプリケーションは、データを書き込むために Redis リーダーと通信する必要があります。Redis リーダー Pod にトラフィックをプロキシする Service を作成できます。

Service とは Kubernetes の抽象化機能の一つで、Pod の論理セットと、Pod へのアクセスを可能にするポリシーを定義するものです。Service を作成するときに、Pod のラベルに基づいてプロキシする Pod を記述します。

  1. 次のマニフェストには、Redis リーダーの Service が記述されています。

    apiVersion: v1
    kind: Service
    metadata:
      name: redis-leader
      labels:
        app: redis
        role: leader
        tier: backend
    spec:
      ports:
      - port: 6379
        targetPort: 6379
      selector:
        app: redis
        role: leader
        tier: backend

    このマニフェストには、ラベルセレクタのセットが含まれています。これらのラベルは、前のステップでデプロイしたラベルのセットと一致しています。したがって、この Service は、前の手順で作成した Redis リーダー Pod にネットワーク トラフィックをルーティングします。

    マニフェストの ports セクションでは、1 つのポート マッピングが宣言されています。Service は port: 6379 上のトラフィックを指定の selector ラベルと一致するコンテナの targetPort: 6379 にルーティングします。Deployment にトラフィックをルーティングするには、Deployment で使用されている containerPorttargetPort と一致する必要があります。

    マニフェストをクラスタに適用します。

    kubectl apply -f redis-leader-service.yaml
    
  2. GKE が Service を作成したことを確認します。

    kubectl get service
    

    出力は次のようになります。

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

Redis フォロワーを設定する

Redis リーダーは単一の Pod ですが、少数の Redis フォロワー(レプリカ)を追加することで、可用性を高め、トラフィックの需要を満たすことができます。

  1. 次のマニフェストには、Redis フォロワー Pod の Deployment が記述されています。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis-follower
      labels:
        app: redis
        role: follower
        tier: backend
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
            role: follower
            tier: backend
        spec:
          containers:
          - name: follower
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 6379
  2. マニフェストをクラスタに適用します。

    kubectl apply -f redis-follower-deployment.yaml
    
  3. 2 つの Redis フォロワー レプリカが実行されていることを確認します。

    kubectl get pods
    

    出力は次のようになります。

    NAME                              READY   STATUS    RESTARTS   AGE
    redis-follower-76588f55b7-bnsq6   1/1     Running   0          27s
    redis-follower-76588f55b7-qvtws   1/1     Running   0          27s
    redis-leader-dd446dc55-kl7nl      1/1     Running   0          119s
    

    STATUSPending から Running に変わるまでに数分かかることがあります。

Redis フォロワー Service を作成する

このウェブ アプリケーションは、データを読み取るために Redis フォロワーと通信する必要があります。Redis フォロワーを検出できるようにするには、Service を設定する必要があります。

  1. 次のマニフェストには、Redis フォロワーの Service が記述されています。

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

    このマニフェストでは、Service をポート 6379 で実行することを指定しています。Service の selector フィールドは、前の手順で作成した Redis フォロワー Pod と一致しています。

    マニフェストをクラスタに適用します。

    kubectl apply -f redis-follower-service.yaml
    
  2. GKE が Service を作成したことを確認します。

    kubectl get service
    

    出力は次のようになります。

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

アプリケーションのウェブ フロントエンドを設定する

アプリケーション用の Redis ストレージを用意できたので、ウェブサーバーを起動してみましょう。フロントエンドも Redis フォロワーと同様に Kubernetes Deployment を使用してデプロイされます。

ウェブ アプリケーションは PHP フロントエンドを使用します。このフロントエンドは、リクエストが読み取りか書き込みかに応じて、Redis フォロワー Service またはリーダー Service と通信するように構成されています。フロントエンドは JSON インターフェースを公開し、jQuery Ajax ベースの UI を提供します。

  1. 次のマニフェストには、ウェブサーバーの Deployment が記述されています。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
    spec:
      replicas: 3
      selector:
        matchLabels:
            app: guestbook
            tier: frontend
      template:
        metadata:
          labels:
            app: guestbook
            tier: frontend
        spec:
          containers:
          - name: php-redis
            image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
            env:
            - name: GET_HOSTS_FROM
              value: "dns"
            resources:
              requests:
                cpu: 100m
                memory: 100Mi
            ports:
            - containerPort: 80

    このマニフェスト ファイルでは、環境変数 GET_HOSTS_FROM=dns が指定されています。ウェブ フロントエンド アプリケーションに構成を提供すると、フロントエンド アプリケーションは redis-followerredis-leader というホスト名を使用して DNS ルックアップを実行します。DNS ルックアップは、前の手順で作成した Service の IP アドレスを検索します。このコンセプトは、DNS サービス ディスカバリと呼ばれます。

    マニフェストをクラスタに適用します。

    kubectl apply -f frontend-deployment.yaml
    
  2. レプリカが動作していることを確認します。

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

    出力は次のようになります。

    NAME                        READY   STATUS    RESTARTS   AGE
    frontend-7b78458576-8kp8s   1/1     Running   0          37s
    frontend-7b78458576-gg86q   1/1     Running   0          37s
    frontend-7b78458576-hz87g   1/1     Running   0          37s
    

外部 IP アドレスでフロントエンドを公開する

現在の構成では、前のステップで作成した redis-follower Service と redis-leader Service は GKE クラスタの内部でのみアクセスできます。これは、Service のデフォルト タイプが ClusterIP であるためです。

ClusterIP Service は、Service が参照している一連の Pod に単一の IP アドレスを提供します。この IP アドレスは、クラスタ内でのみアクセスできます。

ウェブ フロントエンド サービスを外部からアクセスできるようにするには、要件に応じて Service 構成で type: LoadBalancer または type: NodePort を指定します。

次のマニフェストには、LoadBalancer タイプの Service が記述されています。

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  type: LoadBalancer
  ports:
    # the port that this service should serve on
  - port: 80
  selector:
    app: guestbook
    tier: frontend

ports セクションのポートの宣言では port: 80 が指定されており、targetPort は指定されていません。targetPort プロパティを省略した場合、デフォルトで port フィールドの値が使用されます。この場合、この Service はポート 80 の外部トラフィックを frontend Deployment のコンテナのポート 80 に転送します。

マニフェストをクラスタに適用します。

kubectl apply -f frontend-service.yaml

frontend Service の作成時には、GKE によりロードバランサと外部 IP アドレスが作成されます。これらのリソースは課金の対象となります

アプリケーションのウェブサイトにアクセスする

アプリケーションのウェブサイトにアクセスするには、frontend Service の外部 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 列に <pending> が表示されることがあります。これには数分かかることがあります。 Does not have minimum availability などのエラーが表示された場合は、数分待ちます。この一時的なエラーが発生するのは、変更を行うために GKE がノードを再作成するためです。

IP アドレスをコピーして、ブラウザでページを開きます。

GKE で動作するウェブ アプリケーション

メッセージを入力して [Submit] をクリックし、エントリを追加してみてください。入力したメッセージはフロントエンドに表示されます。このメッセージは、作成した Service を介してデータが Redis に正常に追加されたことを示します。

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

しばらく前から運用していたアプリケーションが突然注目を集めるようになりました。そこで、フロントエンドのウェブサーバーを増やすことにしました。そのためには、Pod の数を増やす必要があります。

  1. frontend Pod の数をスケールアップします。

    kubectl scale deployment frontend --replicas=5
    

    出力は次のようになります。

    deployment.extensions/frontend scaled
    
  2. 実行中のレプリカの数を確認します。

    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-leader-343230949-qfvrq     1/1       Running   0          54m
    redis-follower-132015689-dp23k   1/1       Running   0          37m
    redis-follower-132015689-xq9v0   1/1       Running   0          37m
    

    同じコマンドを使用して、frontend Pod の数をスケールダウンできます。ただし、51 に置き換えます。