サービスを使用したアプリケーションの公開

このページでは、Google Kubernetes Engine(GKE) クラスタ内で Kubernetes Service を作成する方法について説明します。Service のコンセプトや種類の説明については、Service をご覧ください。

はじめに

Service とは、一連の Pod エンドポイントを 1 つのリソースにグループ化したものです。このグループにアクセスするさまざまな方法を構成できます。デフォルトでは固定クラスタ IP アドレスを取得し、クラスタ内のクライアントはそれを使って Service 内の Pod と通信できます。クライアントがこの IP アドレスにリクエストを送信すると、リクエストが Service 内の Pod の 1 つにルーティングされます。

Service には、次の 5 つのタイプがあります。

  • ClusterIP(デフォルト)
  • NodePort
  • LoadBalancer
  • ExternalName
  • Headless

デフォルトでは、Autopilot クラスタは一般公開されます。限定公開の Autopilot クラスタを使用する場合は、Cloud NAT を構成して、アウトバウンド インターネット接続(DockerHub からのイメージの pull など)を行う必要があります。

このトピックにはいくつかの演習があります。各演習では、Deployment を作成し、Service を作成してその Pod を公開します。次に、その Service に HTTP リクエストを送信します。

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API が有効になっていることを確認します。
  • Google Kubernetes Engine API の有効化
  • Google Cloud CLI がインストールされていることを確認します。
  • 次のいずれかの方法で、プロジェクトにデフォルトの Google Cloud CLI 設定をセットアップします。
    • プロジェクトのデフォルトの設定全般を確認する場合は、gcloud init を使用します。
    • gcloud config を使用して、プロジェクト ID、ゾーン、リージョンを個別に設定します。

    gcloud init

    1. gcloud init を実行して、次の操作を行います。

      gcloud init

      リモート サーバーで SSH を使用している場合は、--console-only フラグを指定して、コマンドがブラウザを起動しないようにします。

      gcloud init --console-only
    2. Google Cloud アカウントを使用できるように、gcloud CLI の承認手順を行います。
    3. 新しい構成を作成するか、既存の構成を選択します。
    4. Google Cloud プロジェクトを選択します。
    5. デフォルトの Compute Engine ゾーンを選択します。
    6. デフォルトの Compute Engine リージョンを選択します。

    gcloud config

    1. デフォルトのプロジェクト ID を設定します。
      gcloud config set project PROJECT_ID
    2. デフォルトの Compute Engine リージョン(例: us-central1)を設定します。
      gcloud config set compute/region COMPUTE_REGION
    3. デフォルトの Compute Engine ゾーン(例: us-central1-c)を設定します。
      gcloud config set compute/zone COMPUTE_ZONE
    4. gcloud を最新バージョンに更新します。
      gcloud components update

    デフォルトの場所を設定することで、gcloud CLI のエラー(One of [--zone, --region] must be supplied: Please specify location など)を防止できます。

ClusterIP タイプの Service の作成

このセクションでは、ClusterIP タイプの Service を作成します。

kubectl apply

Deployment のマニフェストは次のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: metrics
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

このマニフェストを my-deployment.yaml という名前のファイルにコピーし、次のようにして Deployment を作成します。

kubectl apply -f my-deployment.yaml

次のようにして、3 つの Pod が実行中であることを確認します。

kubectl get pods

出力に、実行中の 3 つの Pod が表示されます。

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          7s
my-deployment-dbd86c8c4-qfw22   1/1     Running   0          7s
my-deployment-dbd86c8c4-wt4s6   1/1     Running   0          7s

ClusterIP タイプの Service のマニフェストは次のとおりです。

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  type: ClusterIP
  # Uncomment the below line to create a Headless Service
  # clusterIP: None
  selector:
    app: metrics
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

この Service には、次の 2 つのラベルを指定するセレクタがあります。

  • app: metrics
  • department: sales

事前に作成した Deployment 内の各 Pod は、これら 2 つのラベルを有しています。そのため、Deployment 内の Pod はこの Service のメンバーになります。

マニフェストを my-cip-service.yaml という名前のファイルにコピーして、Service を作成します。

kubectl apply -f my-cip-service.yaml

Kubernetes が固定内部アドレスを Service に割り当てるまで待ってから、次のようにして Service を表示します。

kubectl get service my-cip-service --output yaml

出力に、clusterIP の値が表示されます。

spec:
  clusterIP: 10.59.241.241

後で使用できるように、clusterIP の値をメモしておきます。

Console

Deployment を作成する

  1. コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. [ デプロイ] をクリックします。

  3. [コンテナ] で [既存のコンテナ イメージ] を選択します。

  4. [イメージパス] に「us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。

  5. [完了]、[続行] の順にクリックします。

  6. [構成] の [アプリケーション名] に「my-deployment」と入力します。

  7. [ラベル] で、次のラベルを作成します。

    • キー: app値: metrics
    • キー: department値: sales
  8. [クラスタ] で、Deployment を作成するクラスタを選択します。

  9. [デプロイ] をクリックします。

  10. Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。

Service を作成して Deployment を公開する

  1. 上の [デプロイの詳細] ページで、 [アクション] > [公開] をクリックします。
  2. [公開] ダイアログの [ポート マッピング] で、次の値を設定します。

    • ポート: 80
    • ターゲット ポート: 8080
    • プロトコル: TCP
  3. [サービスタイプ] プルダウン リストから [クラスタの IP] を選択します。

  4. [公開] をクリックします。

  5. Service の準備が整うと、[サービスの詳細] ページが開き、Service に関する詳細情報が表示されます。[Cluster IP] で、Kubernetes によって Service に割り当てられた IP アドレスをメモしておきます。これは、内部クライアントが Service を呼び出すために使用できる IP アドレスです。

Service にアクセスする

次のコマンドを実行して、実行中の Pod を一覧表示します。

kubectl get pods

出力で、my-deployment で始まる Pod 名のうち 1 つをコピーします。

NAME                            READY   STATUS    RESTARTS   AGE
my-deployment-dbd86c8c4-h5wsf   1/1     Running   0          2m51s

次のようにして、実行中のいずれかのコンテナでシェルを起動します。

kubectl exec -it POD_NAME -- sh

POD_NAME は、my-deployment 内のいずれかの Pod の名前に置き換えます。

シェルで、curl をインストールします。

apk add --no-cache curl

コンテナから、クラスタの IP アドレスとポート 80 を使用して Service へのリクエストを行います。80 は、Service の port フィールドの値であるのでご注意ください。Service のクライアントが使用するポートです。

curl CLUSTER_IP:80

CLUSTER_IP は、Service 内の clusterIP の値に置き換えます。

リクエストは、TCP ポート 8080 上のいずれかのメンバー Pod(targetPort フィールドの値)に転送されます。なお、Service の各メンバー Pod には、ポート 8080 でリッスンするコンテナが必要です。

レスポンスには hello-app の出力が含まれます。

Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-h5wsf

コンテナのシェルを終了するには、「exit」と入力します。

NodePort タイプの Service の作成

このセクションでは、NodePort タイプの Service を作成します。

kubectl apply

Deployment のマニフェストは次のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50000
spec:
  selector:
    matchLabels:
      app: metrics
      department: engineering
  replicas: 3
  template:
    metadata:
      labels:
        app: metrics
        department: engineering
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50000"

マニフェスト内の env オブジェクトに注目してください。env オブジェクトでは、実行中のコンテナの PORT 環境変数の値が 50000 になることを指定しています。hello-app アプリケーションは、PORT 環境変数で指定されたポートでリッスンします。つまり、この演習では、ポート 50000 でリッスンするようコンテナに指示しています。

このマニフェストを my-deployment-50000.yaml という名前のファイルにコピーし、次のようにして Deployment を作成します。

kubectl apply -f my-deployment-50000.yaml

次のようにして、3 つの Pod が実行中であることを確認します。

kubectl get pods

NodePort タイプの Service のマニフェストは次のとおりです。

apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  type: NodePort
  selector:
    app: metrics
    department: engineering
  ports:
  - protocol: TCP
    port: 80
    targetPort: 50000

マニフェストを my-np-service.yaml という名前のファイルにコピーして、Service を作成します。

kubectl apply -f my-np-service.yaml

Service を表示します。

kubectl get service my-np-service --output yaml

出力に、nodePort の値が表示されます。

...
  spec:
    ...
    ports:
    - nodePort: 30876
      port: 80
      protocol: TCP
      targetPort: 50000
    selector:
      app: metrics
      department: engineering
    sessionAffinity: None
    type: NodePort
...

クラスタ内のノードに外部 IP アドレスが割り当てられている場合は、次のようにして、いずれかのノードの外部 IP アドレスを見つけます。

kubectl get nodes --output wide

出力に、ノードの外部 IP アドレスが表示されます。

NAME          STATUS    ROLES     AGE    VERSION        EXTERNAL-IP
gke-svc-...   Ready     none      1h     v1.9.7-gke.6   203.0.113.1

すべてのクラスタに外部 IP アドレスを持つノードがあるわけではありません。たとえば、プライベート クラスタ内のノードは外部 IP アドレスを持ちません。

ファイアウォール ルールを作成して、ノードポートの TCP トラフィックを許可します。

gcloud compute firewall-rules create test-node-port \
    --allow tcp:NODE_PORT

NODE_PORT は、Service の nodePort フィールドの値に置き換えます。

Console

Deployment を作成する

  1. コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. [ デプロイ] をクリックします。

  3. [コンテナ] で [既存のコンテナ イメージ] を選択します。

  4. [イメージパス] に「us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。

  5. [ 環境変数を追加] をクリックします。

  6. [キー] に「PORT」、[] に「50000」と入力します。

  7. [完了]、[続行] の順にクリックします。

  8. [構成] の [アプリケーション名] に「my-deployment-50000」と入力します。

  9. [ラベル] で、次のラベルを作成します。

    • キー: app値: metrics
    • キー: department値: engineering
  10. [クラスタ] で、Deployment を作成するクラスタを選択します。

  11. [デプロイ] をクリックします。

  12. Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。

Service を作成して Deployment を公開する

  1. 上の [デプロイの詳細] ページで、 [アクション] > [公開] をクリックします。
  2. [公開] ダイアログの [ポート マッピング] で、次の値を設定します。

    • ポート: 80
    • ターゲット ポート: 50000
    • プロトコル: TCP
  3. [サービスのタイプ] プルダウン リストから [ノードポート] を選択します。

  4. [公開] をクリックします。

  5. Service の準備が整うと、[サービスの詳細] ページが開き、Service に関する詳細情報が表示されます。[ポート] で、Kubernetes によって Service に割り当てられた [ノードポート] をメモしておきます。

ノードポート用のファイアウォール ルールを作成する

  1. コンソールの [ファイアウォール] ページに移動します。

    [ファイアウォール] に移動

  2. [ ファイアウォール ルールを作成] をクリックします。

  3. [名前] に「test-node-port」と入力します。

  4. [ターゲット] プルダウン リストから [ネットワーク上のすべてのインスタンス] を選択します。

  5. [ソース IP の範囲] に「0.0.0.0/0」と入力します。

  6. [プロトコルとポート] で [指定したプロトコルとポート] をオンにします。

  7. [tcp] チェックボックスをオンにして、メモしたノードポートの値を入力します。

  8. [作成] をクリックします。

クラスタノードの一つで外部 IP アドレスを見つける

  1. コンソールで Google Kubernetes Engine のページに移動します。

    Google Kubernetes Engine に移動

  2. この演習で使用しているクラスタの名前をクリックします。

  3. [クラスタの詳細] ページで [ノード] タブをクリックします。

  4. [ノードプール] でノードプールの名前をクリックして、[ノードプールの詳細] ページを開きます。

  5. [インスタンス グループ] で、インスタンス グループの名前をクリックします。

  6. ノードのリストで、外部 IP アドレスの 1 つをメモしておきます。

Service にアクセスする

ブラウザのアドレスバーに次のように入力します。

NODE_IP_ADDRESS:NODE_PORT

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

  • NODE_IP_ADDRESS: 前のタスクでサービスを作成したときに見つかった、いずれかのノードの外部 IP アドレスです。
  • NODE_PORT: ノードポートの値。

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

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50000-6fb75d85c9-g8c4f

LoadBalancer タイプの Service の作成

このセクションでは、LoadBalancer タイプの Service を作成します。

kubectl apply

Deployment のマニフェストは次のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment-50001
spec:
  selector:
    matchLabels:
      app: products
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: products
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50001"

この Deployment のコンテナは、ポート 50001 でリッスンすることに注意してください。

このマニフェストを my-deployment-50001.yaml という名前のファイルにコピーし、次のようにして Deployment を作成します。

kubectl apply -f my-deployment-50001.yaml

次のようにして、3 つの Pod が実行中であることを確認します。

kubectl get pods

LoadBalancer タイプの Service のマニフェストは次のとおりです。

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50001

マニフェストを my-lb-service.yaml, という名前のファイルにコピーし、Service を作成します。

kubectl apply -f my-lb-service.yaml

LoadBalancer タイプの Service を作成すると、Google Cloud コントローラが起動し、ネットワーク ロードバランサが構成されます。コントローラがネットワーク ロードバランサを構成して固定 IP アドレスを生成するまで、少し待ちます。

Service を表示します。

kubectl get service my-lb-service --output yaml

出力の loadBalancer:ingress の下に固定の外部 IP アドレスが表示されます。

...
spec:
  ...
  ports:
  - ...
    port: 60000
    protocol: TCP
    targetPort: 50001
  selector:
    app: products
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.10

Console

Deployment を作成する

  1. コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. [ デプロイ] をクリックします。

  3. [コンテナ] で [既存のコンテナ イメージ] を選択します。

  4. [イメージパス] に「us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。

  5. [ 環境変数を追加] をクリックします。

  6. [キー] に「PORT」、[] に「50001」と入力します。

  7. [完了]、[続行] の順にクリックします。

  8. [構成] の [アプリケーション名] に「my-deployment-50001」と入力します。

  9. [ラベル] で、次のラベルを作成します。

    • キー: app値: products
    • キー: department値: sales
  10. [クラスタ] で、Deployment を作成するクラスタを選択します。

  11. [デプロイ] をクリックします。

  12. Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。

Service を作成して Deployment を公開する

  1. 上の [デプロイの詳細] ページで、 [アクション] > [公開] をクリックします。
  2. [公開] ダイアログの [ポート マッピング] で、次の値を設定します。

    • ポート: 60000
    • ターゲット ポート: 50001
    • プロトコル: TCP
  3. [サービスのタイプ] プルダウン リストから、[ロードバランサ] を選択します。

  4. [公開] をクリックします。

  5. Service の準備が整うと、[サービスの詳細] ページが開き、Service に関する詳細情報が表示されます。[ロードバランサ] で、ロードバランサの外部 IP アドレスをメモしておきます。

Service にアクセスする

GKE がロードバランサを構成するまで数分待ちます。

ブラウザのアドレスバーに次のように入力します。

LOAD_BALANCER_ADDRESS:60000

LOAD_BALANCER_ADDRESS は、ロードバランサの外部 IP アドレスに置き換えます。

レスポンスには hello-app の出力が含まれます。

Hello, world!
Version: 2.0.0
Hostname: my-deployment-50001-68bb7dfb4b-prvct

Service 内の port の値は任意であるのでご注意ください。上記の例では、port の値に 60000 を使用することで、これを示しています。

ExternalName タイプの Service の作成

このセクションでは、ExternalName タイプの Service を作成します。

ExternalName タイプの Service は、外部 DNS 名のための内部エイリアスを提供します。内部クライアントは、内部 DNS 名を使用してリクエストを行い、そのリクエストは外部名にリダイレクトされます。

ExternalName タイプの Service のマニフェストは次のとおりです。

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

上記の例では、DNS 名は my-xn-service.default.svc.cluster.local です。内部クライアントが my-xn-service.default.svc.cluster.local にリクエストを送ると、そのリクエストは example.com にリダイレクトされます。

kubectl expose を使用した Service の作成

Service マニフェストを作成する方法のほかに、kubectl expose を使って Deployment を公開することによって Service を作成することもできます。

my-deployment を公開するには、このトピックで前述したように、次のコマンドを入力できます。

kubectl expose deployment my-deployment --name my-cip-service \
    --type ClusterIP --protocol TCP --port 80 --target-port 8080

my-deployment-50000 を公開するには、このトピックで前述したように、次のコマンドを入力できます。

kubectl expose deployment my-deployment-50000 --name my-np-service \
    --type NodePort --protocol TCP --port 80 --target-port 50000

my-deployment-50001 を公開するには、このトピックで前述したように、次のコマンドを入力できます。

kubectl expose deployment my-deployment-50001 --name my-lb-service \
    --type LoadBalancer --port 60000 --target-port 50001

クリーンアップ

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

kubectl apply

Service を削除する

kubectl delete services my-cip-service my-np-service my-lb-service

Deployment を削除する

kubectl delete deployments my-deployment my-deployment-50000 my-deployment-50001

ファイアウォール ルールを削除する

gcloud compute firewall-rules delete test-node-port

Console

Service を削除する

  1. コンソールの [サービス] ページに移動します。

    サービスに移動

  2. このチュートリアルで作成した Service を選択し、[ 削除] をクリックします。

  3. 確認のメッセージが表示されたら、[削除] をクリックします。

Deployment を削除する

  1. コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  2. このチュートリアルで作成した Deployment を選択し、[ 削除] をクリックします。

  3. 確認を求められたら、[Delete Horizontal Pod Autoscalers associated with selected Deployments] チェックボックスをオンにして、[削除] をクリックします。

ファイアウォール ルールを削除する

  1. コンソールの [ファイアウォール] ページに移動します。

    [ファイアウォール] に移動

  2. test-node-port チェックボックスをオンにして、[ 削除] をクリックします。

  3. 確認のメッセージが表示されたら、[削除] をクリックします。

次のステップ