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. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud CLI をインストールします。
  3. gcloud CLI を初期化するには:

    gcloud init
  4. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. GKE API を有効にします。

    gcloud services enable container.googleapis.com
  7. Google Cloud CLI をインストールします。
  8. gcloud CLI を初期化するには:

    gcloud init
  9. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  10. Google Cloud プロジェクトで課金が有効になっていることを確認します

  11. GKE API を有効にします。

    gcloud services enable container.googleapis.com

環境を準備する

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

  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 アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

    Google Cloud プロジェクトを削除します。

    gcloud projects delete PROJECT_ID

個々のリソースを削除する

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

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

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

    gcloud container clusters delete guestbook
    

次のステップ