このページでは、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
を実行して最新のバージョンを取得する。
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
クリーンアップ
このページの演習を完了したら、アカウントで不要な請求が発生しないように、以下の手順でリソースを削除します。
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 削除] をクリックします。
確認のメッセージが表示されたら、[削除] をクリックします。