このページでは、Google Kubernetes Engine(GKE)で Kubernetes Service を作成し、アプリケーションを公開することで、内部ネットワークまたはインターネットからアプリケーションにアクセスできるようにする方法について説明します。5 つの Service タイプ(ClusterIP、NodePort、LoadBalancer、ExternalName、Headless)について説明します。
このチュートリアルでは、Deployment の作成方法、Service を使用して Deployment を公開する方法、Deployment にアクセスする方法について、各 Service タイプに応じた例を示します。
このページは、クラウド リソースのプロビジョニングと構成、アプリとサービスのデプロイを行うオペレーターとデベロッパーを対象としています。 Google Cloudのコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。
このページを読む前に、kubectl の使い方を理解しておいてください。
はじめに
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コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
- すでに Autopilot クラスタまたは Standard クラスタが存在していることを確認する。新しいクラスタを作成するには、Autopilot クラスタの作成をご覧ください。
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 を作成する
- Google Cloud コンソールの [ワークロード] ページに移動します。 
- [add_box デプロイ] をクリックします。 
- [コンテナの指定] で [既存のコンテナ イメージ] を選択します。 
- [イメージパス] に「 - us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。
- [完了]、[続行] の順にクリックします。 
- [構成] の [アプリケーション名] に「 - my-deployment」と入力します。
- [ラベル] で、次のラベルを作成します。 - キー: app、値:metrics
- キー: department、値:sales
 
- キー: 
- [クラスタ] で、Deployment を作成するクラスタを選択します。 
- [デプロイ] をクリックします。 
- Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。 
Service を作成して Deployment を公開する
- 上の [デプロイの詳細] ページで、list [アクション] > [公開] をクリックします。
- [公開] ダイアログの [ポート マッピング] で、次の値を設定します。 - ポート: 80
- ターゲット ポート: 8080
- プロトコル: TCP
 
- ポート: 
- [サービスタイプ] プルダウン リストから [クラスタの IP] を選択します。 
- [公開] をクリックします。 
- 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 を作成する
- Google Cloud コンソールの [ワークロード] ページに移動します。 
- [add_box デプロイ] をクリックします。 
- [コンテナの指定] で [既存のコンテナ イメージ] を選択します。 
- [イメージパス] に「 - us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。
- [add 環境変数を追加] をクリックします。 
- [キー] に「 - PORT」、[値] に「- 50000」と入力します。
- [完了]、[続行] の順にクリックします。 
- [構成] の [アプリケーション名] に「 - my-deployment-50000」と入力します。
- [ラベル] で、次のラベルを作成します。 - キー: app、値:metrics
- キー: department、値:engineering
 
- キー: 
- [クラスタ] で、Deployment を作成するクラスタを選択します。 
- [デプロイ] をクリックします。 
- Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。 
Service を作成して Deployment を公開する
- 上の [デプロイの詳細] ページで、list [アクション] > [公開] をクリックします。
- [公開] ダイアログの [ポート マッピング] で、次の値を設定します。 - ポート: 80
- ターゲット ポート: 50000
- プロトコル: TCP
 
- ポート: 
- [サービスのタイプ] プルダウン リストから [ノードポート] を選択します。 
- [公開] をクリックします。 
- Service の準備が整うと、[サービスの詳細] ページが開き、Service に関する詳細情報が表示されます。[ポート] で、Kubernetes によって Service に割り当てられた [ノードポート] をメモしておきます。 
ノードポート用のファイアウォール ルールを作成する
- Google Cloud コンソールの [ファイアウォール ポリシー] ページに移動します。 
- [add_box ファイアウォール ルールを作成] をクリックします。 
- [名前] に「 - test-node-port」と入力します。
- [ターゲット] プルダウン リストから [ネットワーク上のすべてのインスタンス] を選択します。 
- [送信元 IPv4 範囲] に「 - 0.0.0.0/0」と入力します。
- [プロトコルとポート] で [指定したプロトコルとポート] をオンにします。 
- [tcp] チェックボックスをオンにして、メモしたノードポートの値を入力します。 
- [作成] をクリックします。 
ノードの 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 を作成する
- Google Cloud コンソールの [ワークロード] ページに移動します。 
- [add_box デプロイ] をクリックします。 
- [コンテナの指定] で [既存のコンテナ イメージ] を選択します。 
- [イメージパス] に「 - us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0」と入力します。
- [add 環境変数を追加] をクリックします。 
- [キー] に「 - PORT」、[値] に「- 50001」と入力します。
- [完了]、[続行] の順にクリックします。 
- [構成] の [アプリケーション名] に「 - my-deployment-50001」と入力します。
- [ラベル] で、次のラベルを作成します。 - キー: app、値:products
- キー: department、値:sales
 
- キー: 
- [クラスタ] で、Deployment を作成するクラスタを選択します。 
- [デプロイ] をクリックします。 
- Deployment の準備が整うと、[デプロイの詳細] ページが開きます。[マネージド Pod] で、Deployment に 1 つ以上の実行中の Pod があることを確認できます。 
Service を作成して Deployment を公開する
- 上の [デプロイの詳細] ページで、list [アクション] > [公開] をクリックします。
- [公開] ダイアログの [ポート マッピング] で、次の値を設定します。 - ポート: 60000
- ターゲット ポート: 50001
- プロトコル: TCP
 
- ポート: 
- [サービスのタイプ] プルダウン リストから、[ロードバランサ] を選択します。 
- [公開] をクリックします。 
- 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
Service を表示する
作成した Service は、 Google Cloud コンソールの [サービス] ページで確認できます。
また、App Hub で、サポートされるビジネス機能のコンテキスト内でサービスを表示することもできます。App Hub は、すべてのアプリケーションとそれに関連するサービスの概要を一元的に提供します。
App Hub でサービスを表示するには、 Google Cloud コンソールの [App Hub] ページに移動します。
マネージド Kubernetes サービスとして、GKE はリソースの作成または削除時に、Service メタデータ(特にリソース URI)を App Hub に自動的に送信します。この常時オンのメタデータ取り込みにより、App Hub でのアプリケーションの構築と管理が容易になります。
App Hub でサポートされているリソースについて詳しくは、サポートされているリソースをご覧ください。
プロジェクトに App Hub を設定する方法については、App Hub を設定するをご覧ください。
クリーンアップ
このページの演習を完了したら、アカウントで不要な請求が発生しないように、以下の手順でリソースを削除します。
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 の削除
- Google Cloud コンソールの [サービス] ページに移動します。 
- このチュートリアルで作成した Service を選択し、[delete 削除] をクリックします。 
- 確認のメッセージが表示されたら、[削除] をクリックします。 
Deployment の削除
- Google Cloud コンソールの [ワークロード] ページに移動します。 
- このチュートリアルで作成した Deployment を選択し、[delete 削除] をクリックします。 
- 確認を求められたら、[Delete Horizontal Pod Autoscalers associated with selected Deployments] チェックボックスをオンにして、[削除] をクリックします。 
ファイアウォール ルールの削除
- Google Cloud コンソールの [ファイアウォール ポリシー] ページに移動します。 
- test-node-port チェックボックスをオンにして、[delete 削除] をクリックします。 
- 確認のメッセージが表示されたら、[削除] をクリックします。