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


このページでは、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 を使用する場合は、gcloud CLI をインストールして初期化します。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得します。
* GKE クラスタを作成します

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

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

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

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

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

Console

Deployment を作成する

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

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

  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 を作成します。

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

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. 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. 確認のメッセージが表示されたら、[削除] をクリックします。

次のステップ