Service

このページでは Kubernetes Services について説明します。また、この Service を Google Kubernetes Engine で使用する方法についても説明します。Service の作成方法については、Service を使用したアプリケーションの公開をご覧ください。

Service とは

Service とは、一連のポッド エンドポイントを 1 つのリソースにグループ化したものです。このグループには、さまざまな方法でアクセスできます。デフォルトでは、クラスタ内のクライアントが Service 内のポッドとの通信に使用する固定のクラスタ IP アドレスを取得します。クライアントがこの IP アドレスにリクエストを送信すると、リクエストが Service 内のポッドの 1 つにルーティングされます。

Service は、セレクタを使用してメンバーのポッドを識別します。ポッドが Service のメンバーとして識別されるには、セレクタで指定されたすべてのラベルがポッドに設定されている必要があります。ラベルは、オブジェクトに関連する任意の Key-Value ペアです。

次の Service マニフェストのセレクタには 2 つのラベルが指定されています。selector フィールドは、この Service のメンバーが app: metricsdepartment:engineering の両方のラベルを持つことを表しています。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: metrics
    department: engineering
  ports:
  ...

Service を利用する理由

Kubernetes クラスタでは、各ポッドに内部 IP アドレスがあります。しかし、Deployment 内のポッドが稼働して停止すると、IP アドレスが変わります。このため、ポッド IP アドレスを直接使用しても意味はありません。Service を使用すると、メンバーポッドの IP アドレスが変更されても、Service の存続期間中に固定の IP アドレスを取得できます。

Service は負荷分散としても機能します。クライアントは単一の固定 IP アドレスを呼び出しますが、リクエストは Service のメンバーであるポッド全体で負荷分散されます。

Service のタイプ

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

  • ClusterIP(デフォルト): 内部クライアントが内部の固定 IP アドレスにリクエストを送信します。

  • NodePort: クライアントは、Service が指定した 1 つ以上の nodePort 値を使用して、ノードの IP アドレスにリクエストを送信します。

  • LoadBalancer: クライアントがネットワーク ロードバランサの IP アドレスにリクエストを送信します。

  • ExternalName: 内部クライアントが、外部 DNS 名のエイリアスとして Service の DNS 名を使用します。

  • Headless: headless service は、ポッドのグループ化を行う場合に使用できますが、固定 IP アドレスは必要ありません。

NodePortClusterIP の拡張タイプです。したがって、NodePort タイプの Service はクラスタ IP アドレスを使用します。

LoadBalancerNodePort の拡張タイプです。したがって、LoadBalancer タイプの Service は、クラスタ IP アドレスと複数の 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 ポートが使用されます。リクエストは、いずれかのメンバーポッドの TCP ポート(targetPort フィールドで指定)に転送されます。前の例では、クライアントは 10.11.247.213 の TCP ポート 80 で Service を呼び出します。リクエストは、いずれかのメンバーポッドの TCP ポート 8080 に転送されます。メンバーポッドには、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 を呼び出します。リクエストは、いずれかのメンバーポートの TCP ポート(targetPort フィールドで指定)に転送されます。

たとえば、1 つのクラスタノードの外部 IP アドレスが 203.0.113.2 とします。前の例では、外部クライアントは 203.0.113.2 の TCP ポート 32675 で Service を呼び出しています。リクエストは、いずれかのメンバーポッドの TCP ポート 8080 に転送されます。メンバーポッドには、TCP ポート 8080 でリッスンするコンテナが必要です。

NodePort Service タイプは ClusterIP タイプの拡張です。したがって、内部クライアントはこの Service を次の 2 つの方法で呼び出すことができます。

  • clusterIPport を使用する。
  • ノードの内部 IP アドレスと nodePort を使用する。

クラスタ構成によっては、Google Cloud HTTP(S) ロードバランサNodePort タイプの Service が使用されることがあります。詳細については、Ingress での HTTP 負荷分散の設定をご覧ください。

HTTP(S) ロードバランサはプロキシ サーバーで、このトピックの LoadBalancer タイプの Service で説明するネットワーク ロードバランサとは基本的に異なります。

LoadBalancer タイプの Service

LoadBalancer タイプの Service を作成すると、Google Cloud Controller が起動し、プロジェクト内にネットワーク ロードバランサが構成されます。ロードバランサには、プロジェクトの外部からアクセス可能な固定の IP アドレスが設定されます。

ネットワーク ロードバランサはプロキシ サーバーではありません。パケットを送信元 IP アドレスと宛先 IP アドレスを変更せずにそのまま転送します。

LoadBalancer タイプの Service のマニフェストは次のとおりです。

apiVersion: v1
kind: Service
metadata:
  name: my-nlb-service
spec:
  selector:
    app: metrics
    department: engineering
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080

Service を作成したら、kubectl get service -o yaml を使用して仕様を表示し、固定の外部 IP アドレスを確認します。

spec:
  clusterIP: 10.11.242.115
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32676
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
  status:
    loadBalancer:
      ingress:
      - ip: 203.0.113.100

上の出力では、ネットワーク ロードバランサの IP アドレスが loadBalancer:ingress: の下に表示されています。外部クライアントは、ロードバランサの IP アドレスと port で指定された TCP ポートを使用して Service を呼び出します。リクエストは、いずれかのメンバーポートの TCP ポート(targetPort で指定)に転送されます。前の例では、クライアントは 203.0.113.100 の TCP ポート 80 で Service を呼び出します。リクエストは、いずれかのメンバーポッドの TCP ポート 8080 に転送されます。メンバーポッドには、TCP ポート 8080 でリッスンするコンテナが必要です。

LoadBalancer Service タイプは NodePort タイプの拡張で、このタイプは ClusterIP タイプの拡張です。

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 タイプは、基本的に他の Service タイプと異なります。ExternalName タイプの Service は、このトピックの冒頭で説明した Service の定義に該当しません。ExternalName タイプの Service は、一連のポッドに関連付けられておらず、固定の IP アドレスがありません。ExternalName タイプの Service は、内部 DNS 名から外部 DNS 名へのマッピングです。

Service の抽象化

一部のネットワーク インターフェースでリッスンするプロセスではないという点では、Service は抽象的な概念です。抽象化の一部は、クラスタノードの iptables ルールで実装されます。Service のタイプによっては、抽象化の他の部分がネットワーク負荷分散または HTTP(S) 負荷分散で実装されます。

任意の Service ポート

Service マニフェストの port フィールドの値は任意ですが、targetPort の値は任意ではありません。メンバーポッドには、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 を呼び出します。リクエストは、いずれかのメンバーポッドの 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 を呼び出します。リクエストは、メンバーポッドの TCP ポート 50000 に転送されます。クライアントが 203.0.113.201 の TCP ポート 60001 で Service を呼び出すと、リクエストはメンバーポッドの TCP ポート 8080 に転送されます。

メンバーポッドには、TCP ポート 50000 でリッスンするコンテナと TCP ポート 8080 でリッスンするコンテナが必要です。2 つのスレッドを持つ 1 つのコンテナにすることも、同じポッドで実行される 2 つのコンテナにすることもできます。

Service エンドポイント

Service を作成すると、Kubernetes は Service と同じ名前の Endpoints オブジェクトを作成します。Kubernetes は、Endpoints オブジェクトを使用して、どのポッドが Service のメンバーかを記録します。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Kubernetes Engine のドキュメント