このページでは、Google Kubernetes Engine(GKE)における Kubernetes Service とその使用方法について説明します。Service には、さまざまなタイプがあり、一連の Pod エンドポイントを 1 つのリソースにグループ化するために使用できます。Service の作成方法については、Service を使用したアプリケーションの公開をご覧ください。
Kubernetes Service とは
Service の目的は、一連の Pod エンドポイントを 1 つのリソースにグループ化することです。このグループにアクセスするさまざまな方法を構成できます。デフォルトでは固定クラスタ IP アドレスを取得し、クラスタ内のクライアントはそれを使って Service 内の Pod と通信できます。クライアントがこの IP アドレスにリクエストを送信すると、リクエストが Service 内のポッドの 1 つにルーティングされます。
Service は、セレクタを使用してメンバーの Pod を識別します。Pod が Service のメンバーとして識別されるには、セレクタで指定されたすべてのラベルが Pod に設定されている必要があります。ラベルは、オブジェクトに関連する任意の Key-Value ペアです。
次の Service マニフェストのセレクタには 2 つのラベルが指定されています。selector
フィールドでは、app: metrics
ラベルと department:engineering
ラベルの両方を持つ Pod がこの Service のメンバーであることを示しています。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: metrics
department: engineering
ports:
...
Kubernetes Service を使用する理由
Kubernetes クラスタの各 Pod は内部 IP アドレスを持ちます。しかし、Deployment 内の Pod が稼働して停止すると、IP アドレスが変わります。このため、Pod IP アドレスを直接使用しても意味はありません。Service を使用すると、メンバー Pod の IP アドレスが変更されても、Service の存続期間中に固定の IP アドレスを取得できます。
Service はロード バランシングも提供します。クライアントは単一の固定 IP アドレスを呼び出しますが、リクエストは Service のメンバーである Pod 全体で負荷分散されます。
Kubernetes Services のタイプ
Service には、次の 5 つのタイプがあります。
ClusterIP(デフォルト): 内部クライアントが内部の固定 IP アドレスにリクエストを送信します。
NodePort: クライアントは、Service が指定した 1 つ以上の
nodePort
値を使用して、ノードの IP アドレスにリクエストを送信します。LoadBalancer: クライアントがネットワーク ロードバランサの IP アドレスにリクエストを送信します。
ExternalName: 内部クライアントが、外部 DNS 名のエイリアスとして Service の DNS 名を使用します。
Headless: headless Service は、Pod のグループ化を行うものの、固定 IP アドレスは必要ない場合に使用します。
NodePort
タイプは ClusterIP
の拡張タイプです。したがって、NodePort
タイプの Service はクラスタ IP アドレスを使用します。
LoadBalancer
タイプは NodePort
の拡張タイプです。したがって、LoadBalancer
タイプの Service は、クラスタ IP アドレスと 1 つ以上の nodePort
値を使用します。
ClusterIP タイプの Service
ClusterIP
タイプの Service を作成すると、Kubernetes が、クラスタ内のノードからアクセス可能な固定の IP アドレスを作成します。
ClusterIP タイプの Service のマニフェストは次のとおりです。
apiVersion: v1
kind: Service
metadata:
name: my-cip-service
spec:
selector:
app: metrics
department: sales
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 8080
kubectl apply -f [MANIFEST_FILE]
を使用して Service を作成できます。Service を作成したら、kubectl get service
を使用して固定の IP アドレスを確認できます。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
my-cip-service ClusterIP 10.11.247.213 none 80/TCP
クラスタ内のクライアントが Service を呼び出すときに、クラスタの IP アドレスと、Service マニフェストの port
フィールドで指定された TCP ポートが使用されます。リクエストは、いずれかのメンバー Pod の、targetPort
フィールドに指定された TCP ポートに転送されます。前の例で、クライアントは 10.11.247.213
の TCP ポート 80 で Service を呼び出します。リクエストは、いずれかのメンバー Pod の TCP ポート 8080 に転送されます。メンバー Pod には、TCP ポート 8080 をリッスンするコンテナが必要です。ポート 8080 でリッスンするコンテナがない場合、「接続失敗」、「このサイトにアクセスできません」などのメッセージがクライアントに表示されます。
NodePort タイプの Service
NodePort
タイプの Service を作成すると、Kubernetes が nodePort
値を割り当てます。この nodePort
値と任意のノードの IP アドレスを使用して Service にアクセスします。
NodePort
タイプの Service のマニフェストは次のとおりです。
apiVersion: v1
kind: Service
metadata:
name: my-np-service
spec:
selector:
app: products
department: sales
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 8080
Service を作成したら、kubectl get service -o yaml
を使用して仕様を表示し、nodePort
値を確認します。
spec:
clusterIP: 10.11.254.114
externalTrafficPolicy: Cluster
ports:
- nodePort: 32675
port: 80
protocol: TCP
targetPort: 8080
外部クライアントは、nodePort
で指定された TCP ポートとノードの外部 IP アドレスを使用して Service を呼び出します。リクエストは、いずれかのメンバー Pod の、targetPort
フィールドに指定された TCP ポートに転送されます。
たとえば、1 つのクラスタノードの外部 IP アドレスが 203.0.113.2
とします。前の例では、外部クライアントは 203.0.113.2
の TCP ポート 32675 で Service を呼び出しています。リクエストは、いずれかのメンバー Pod の TCP ポート 8080 に転送されます。メンバー Pod には、TCP ポート 8080 でリッスンするコンテナが必要です。
NodePort
Service タイプは ClusterIP
Service タイプの拡張です。したがって、内部クライアントはこの Service を次の 2 つの方法で呼び出すことができます。
clusterIP
とport
を使用する。- ノードの IP アドレスと
nodePort
を使用する。
一部のクラスタ構成では、外部アプリケーション ロードバランサで NodePort
タイプの Service が使用されます。
外部アプリケーション ロードバランサはプロキシ サーバーであり、このトピックの LoadBalancer タイプの Service で説明されている外部パススルー ネットワーク ロードバランサとは根本的に異なります。
LoadBalancer タイプの Service
LoadBalancer タイプの Service の詳細については、LoadBalancer Service のコンセプトをご覧ください。
ExternalName タイプの Service
ExternalName
タイプの Service は、外部 DNS 名のための内部エイリアスを提供します。内部クライアントは、内部 DNS 名を使用してリクエストを行い、そのリクエストは外部名にリダイレクトされます。
ExternalName
タイプの Service のマニフェストは次のとおりです。
apiVersion: v1
kind: Service
metadata:
name: my-xn-service
spec:
type: ExternalName
externalName: example.com
Service を作成すると、Kubernetes は内部クライアントが Service の呼び出しで使用する DNS 名を作成します。上記の例では、DNS 名は my-xn-service.default.svc.cluster.local です。内部クライアントが my-xn-service.default.svc.cluster.local にリクエストを送ると、そのリクエストは example.com にリダイレクトされます。
ExternalName
タイプは、根本的に他の Service タイプと異なります。ExternalName
タイプの Service は、このトピックの冒頭で説明した Service の定義に該当しません。ExternalName
タイプの Service は、一連の Pod に関連付けられておらず、固定の IP アドレスがありません。ExternalName
タイプの Service は、内部 DNS 名から外部 DNS 名へのマッピングです。
ヘッドレス Service
ヘッドレス Service は、クラスタ IP アドレスを割り振らない Kubernetes Service の一種です。代わりに、ヘッドレス Service は DNS を使用して Service に関連付けられた Pod の IP アドレスを公開します。これにより、プロキシを経由することなく Pod に直接接続できるようになります。
ヘッドレス Service は、以下のようなさまざまなシナリオで役立ちます。
Pod 間のロード バランシング: ヘッドレス Service を使用して Pod 間で負荷を分散できます。これを実装するには、負荷を分散させる Pod に一致するセレクタを含む Service を作成します。すると、その Service は、セレクタに一致するすべての Pod にトラフィックを均等に分散します。
Service ディスカバリ: ヘッドレス Service を使用して Service ディスカバリを実装できます。これを実装するには、名前とセレクタを含む Service を作成します。ヘッドレス Service の DNS レコードには、セレクタに一致する Service の背後にある Pod のすべての IP が含まれます。クライアントはこれらの DNS レコードを使用して、Service に関連付けられた Pod の IP アドレスを見つけることができます。
Pod への直接アクセス: クライアントは、ヘッドレス Service に関連付けられた Pod に直接接続できます。これは、ロードバランサや DNS サーバーなど、基盤となる Pod に直接アクセスする必要がある Service に役立ちます。
柔軟性: ヘッドレス Service は、ロードバランサ、DNS サーバー、分散データベースなど、さまざまな異なるトポロジを作成するために使用できます。
セレクタがあるヘッドレス Service では解決できない特別なネットワーク要件がワークロードにある場合は、セレクタなしのヘッドレス Service を使用することもできます。ヘッドレス Service は、コントロール プレーンが EndpointSlice オブジェクトを作成しないため、Kubernetes クラスタ自体に配置されていない Service へのアクセスに便利なツールです。この詳細については、セレクタなしの Service をご覧ください。
ヘッドレス Service のマニフェストの例を次に示します。
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
clusterIP: None
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
ヘッドレス Service を作成したら、DNS をクエリすることで Service に関連付けられている Pod の IP アドレスを見つけることができます。たとえば、次のコマンドは nginx Service に関連付けられている Pod の IP アドレスを一覧表示します。
dig +short nginx.default.svc.cluster.local
Kubernetes のクエリ拡張を使用するもう一つの例:
dig +short +search nginx
1 つのコマンドで 1 つのヘッドレス Service を作成できます。また、ヘッドレス Service は更新やスケールが簡単です。
kubectl create service clusterip my-svc --clusterip="None" --dry-run=client -o yaml > [file.yaml]
Service の抽象化
一部のネットワーク インターフェースでリッスンするプロセスではないという点では、Service は抽象的な概念です。抽象化の一部は、クラスタノードの iptables ルールで実装されます。抽象化の他の部分は、Service のタイプに応じて、外部パススルー ネットワーク ロードバランサまたは外部アプリケーション ロードバランサで実装されます。
任意の Service ポート
Service マニフェストの port
フィールドの値は任意ですが、targetPort
の値は任意ではありません。メンバー Pod には、targetPort
でリッスンするコンテナが必要です。
次の例は LoadBalancer
タイプの Service で、port
の値は 50000 に設定されています。
apiVersion: v1
kind: Service
metadata:
name: my-ap-service
spec:
clusterIP: 10.11.241.93
externalTrafficPolicy: Cluster
ports:
- nodePort: 30641
port: 50000
protocol: TCP
targetPort: 8080
selector:
app: parts
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.200
クライアントは、203.0.113.200
の TCP ポート 50000 で Service を呼び出します。リクエストは、いずれかのメンバー Pod の TCP ポート 8080 に転送されます。
複数のポート
Service の ports
フィールドは、ServicePort オブジェクトの配列です。ServicePort オブジェクトには次のフィールドがあります。
name
protocol
port
targetPort
nodePort
複数の ServicePort がある場合、それぞれの ServicePort に一意の名前が必要です。
次の例は LoadBalancer
タイプの Service で、ServicePort
オブジェクトが 2 つあります。
apiVersion: v1
kind: Service
metadata:
name: my-tp-service
spec:
clusterIP: 10.11.242.196
externalTrafficPolicy: Cluster
ports:
- name: my-first-service-port
nodePort: 31233
port: 60000
protocol: TCP
targetPort: 50000
- name: my-second-service-port
nodePort: 31081
port: 60001
protocol: TCP
targetPort: 8080
selector:
app: tests
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.201
前の例で、クライアントは 203.0.113.201
の TCP ポート 60000 で Service を呼び出します。リクエストは、メンバー Pod の TCP ポート 50000 に転送されます。クライアントが 203.0.113.201
の TCP ポート 60001 で Service を呼び出すと、リクエストはメンバー Pod の TCP ポート 8080 に転送されます。
メンバー Pod には、TCP ポート 50000 でリッスンするコンテナと TCP ポート 8080 でリッスンするコンテナが必要です。2 つのスレッドを持つ 1 つのコンテナにすることも、同じ Pod で実行される 2 つのコンテナにすることもできます。
Service エンドポイント
Service を作成すると、Kubernetes は Service と同じ名前の Endpoints オブジェクトを作成します。Kubernetes は、Endpoints オブジェクトを使用して、どの Pod が Service のメンバーかを記録します。
シングルスタック Service とデュアルスタック Service
IPv6 Service は、ClusterIP
タイプまたは NodePort
タイプを作成できます。GKE では、プレビュー期間中、LoadBalancer
タイプのデュアルスタック Service がサポートされます。これに SLA やテクニカル サポートは付属しません。
これらの Service タイプごとに、IPv4、IPv6、デュアルスタックのいずれかの Service として、ipFamilies
フィールドと ipFamilyPolicy
フィールドを定義できます。
次のステップ
- Kubernetes Services の詳細を確認する
- Service を使用してアプリケーションを公開する
- StatefulSet の詳細を確認する
- Ingress の詳細を確認する