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


このページでは、Google Kubernetes Engine(GKE) クラスタ内で Kubernetes Service を作成する方法について説明します。 Service を使用すると、一連の Pod エンドポイントを 1 つのリソースにグループ化できます。このグループにアクセスするさまざまな方法を構成できます。

このドキュメントでは、いくつかの演習を行います。各演習では、Service を作成して Pod を公開します。その後、その Service に HTTP リクエストを送信します。

このドキュメントの対象

組織のネットワーク アーキテクト、ネットワーク エンジニア、ネットワーク管理者、あるいはネットワーク アーキテクチャの定義、実装、メンテナンスを担当する他のチームと協力して、Ingress の構成を計画し、設計することをおすすめします。

デフォルトの GKE 構成

デフォルトでは固定クラスタ IP アドレスを取得し、クラスタ内のクライアントはそれを使って Service 内の Pod と通信できます。クライアントがこの IP アドレスにリクエストを送信すると、リクエストが Service 内の Pod の 1 つにルーティングされます。

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

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

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

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得する。

ClusterIP タイプの Service の作成

このセクションでは、ClusterIP タイプの Service を作成します。Kubernetes は、クラスタ内のノードからアクセスできる固定の IP アドレスを ClusterIP タイプの Service に作成します。詳しくは、ClusterIP をご覧ください。

kubectl apply

Deployment のマニフェストは次のとおりです。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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 の値をメモしておきます。

コンソール

Deployment を作成します。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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

    [ワークロード] に移動

  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 があることを確認できます。

Deployment を公開する Service を作成します。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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

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

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

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

コンソールではヘッドレス Service を作成できません。

Service にアクセスする

メンバー Pod ごとに、TCP ポート 8080 でリッスンするコンテナがあります。次のセクションでは、コンテナがポート 8080 でリッスンしないようにします。アプリの Dockerfile とソースコードを見ると、hello-app がポート 8080 でリッスンしていることがわかります。

次のコマンドを実行して、実行中の 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 に存在することを、事前に確認しておく必要があります。この演習では、コンテナがポート 8080 でリッスンするような操作は何も行いませんでした。アプリの Dockerfile とソースコードを見ると、hello-app がポート 8080 でリッスンしていることがわかります。

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

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

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

リクエストは、TCP ポート 80 上のいずれかのメンバー Pod(targetPort フィールドの値)に転送されます。

NodePort タイプの Service の作成

このセクションでは、NodePort タイプの Service を作成します。NodePort は、Kubernetes が固定のポート値を割り当てる Service のタイプです。NodePort Service には、nodePort 値を持つ任意のノードの IP アドレスを使用してアクセスできます。詳しくは、NodePort をご覧ください。

kubectl apply

Deployment のマニフェストは次のとおりです。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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
...

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

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

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

コンソール

Deployment を作成します。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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

    [ワークロード] に移動

  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 があることを確認できます。

Deployment を公開する Service を作成します。

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

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

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

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

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

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

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

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

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

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

  5. [送信元 IPv4 範囲] に「0.0.0.0/0」と入力します。

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

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

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

ノードの IP アドレスを取得する

いずれかのノードの外部 IP アドレスを見つけます。

kubectl get nodes --output wide

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

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

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

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 を作成します。LoadBalancer Service は、GKE コントローラが外部パススルー ネットワーク ロードバランサをプロビジョニングして構成する Service のタイプです。詳しくは、LoadBalancer をご覧ください。

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

コントローラがネットワーク ロードバランサを構成して固定 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

コンソール

Deployment を作成します。Deployment は、最新の Pod テンプレートを含む 3 つのレプリカを作成する Kubernetes コントローラです。

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

    [ワークロード] に移動

  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

ExternalName タイプの Service の作成

このセクションでは、ExternalName タイプの Service を作成します。ExternalName タイプの Service は、外部 DNS 名のための内部エイリアスを提供します。内部クライアントは、内部 DNS 名を使用してリクエストを行い、そのリクエストは外部名にリダイレクトされます。詳しくは、ExternalName をご覧ください。

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 を公開することもできます。このドキュメントで説明した 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. Google Cloud コンソールで [サービス] ページに移動します。

    サービスに移動

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

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

Deployment を削除する

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

    [ワークロード] に移動

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

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

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

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

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

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

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

次のステップ