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


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

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

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

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

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

目標

次の操作を行い、GKE にアプリケーションをデプロイして実行します。

  1. Redis リーダーを設定する
  2. 2 つの Redis フォロワーを設定する
  3. ウェブ フロントエンドを設定する
  4. ウェブサイトにアクセスする
  5. ウェブ フロントエンドをスケールアップする

次の図は、これらの目標を達成して作成したクラスタ アーキテクチャの概要を示しています。

GKE クラスタのアーキテクチャ

費用

このドキュメントでは、課金対象である次の Google Cloudコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。

新規の Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

Cloud Shell には、このチュートリアルに必要な kubectlgcloud CLI などのソフトウェアがプリインストールされています。Cloud Shell を使用しない場合は、gcloud CLI をインストールする必要があります。

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. 外部 ID プロバイダ(IdP)を使用している場合は、まずフェデレーション ID を使用して gcloud CLI にログインする必要があります。

  4. gcloud CLI を初期化するには、次のコマンドを実行します。

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API:

    gcloud services enable container.googleapis.com
  8. Install the Google Cloud CLI.

  9. 外部 ID プロバイダ(IdP)を使用している場合は、まずフェデレーション ID を使用して gcloud CLI にログインする必要があります。

  10. gcloud CLI を初期化するには、次のコマンドを実行します。

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Make sure that billing is enabled for your Google Cloud project.

  13. Enable the GKE API:

    gcloud services enable container.googleapis.com
  14. 環境を準備する

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

    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 に置き換えます。

    クリーンアップ

    このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

    プロジェクトを削除する

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    個々のリソースの削除

    既存のプロジェクトを削除しない場合は、リソースを個別に削除します。

    1. 次のコマンドで frontend Service を削除します。

      kubectl delete service frontend
      
    2. GKE クラスタを削除します。

      gcloud container clusters delete guestbook
      

    次のステップ