このページに記載されている情報は古い可能性があります
このページの更新日は英語版よりも古いため、記載されている情報が古い可能性があります。最新の情報をご覧になりたい方は英語版のページをご覧ください: Service
Kubernetesにおいて、Serviceとは、 クラスター内で1つ以上のPodとして実行されているネットワークアプリケーションを公開する方法です。
KubernetesにおけるServiceの主要な目的の一つは、既存のアプリケーションを改修することなく、サービスディスカバリの仕組みを利用できるようにすることです。 Pod内で実行するコードは、クラウドネイティブな環境向けに設計されたものでも、コンテナ化した古いアプリケーションでも構いません。 Serviceを使用することで、その複数のPodがネットワーク上でアクセス可能になり、クライアントから通信できるようになります。
Deploymentを使用してアプリケーションを実行する場合、DeploymentはPodを動的に作成、削除します。 常に、どれだけのPodが動作していて健全な状態であるかは分からず、健全なPodの名前すら分からない可能性もあります。 KubernetesのPodは、クラスターの望ましい状態に一致させるために作成、削除されます。 Podは一時的なリソースです(個々のPodに対して、信頼性が高く永続的であるとは期待すべきではありません)。
各Podは独自のIPアドレスを取得します(Kubernetesは、ネットワークプラグインがこれを保証することを期待しています)。 クラスター内の特定のDeploymentで、ある時点で実行されているPodの集合は、少し時が経過すると、異なるPodの集合になっている可能性があります。
これは、とある問題につながります。 Podの集合(「バックエンド」と呼びます)がクラスター内の他のPod(「フロントエンド」と呼びます)に機能を提供する場合、フロントエンドがワークロードのバックエンド部分を使用できるように、どのようにして接続対象のIPアドレスを発見し、追跡するのでしょうか?
ここで Service の登場です。
Kubernetesの一部であるService APIは、Podのグループをネットワーク経由で公開するための抽象化です。 各Serviceオブジェクトは、エンドポイントの論理的な集合(通常、これらのエンドポイントはPodです)および、Podの公開方法についてのポリシーを定義します。
例として、3つのレプリカで実行されているステートレスな画像処理バックエンドについて考えます。 これらのレプリカは互いに代替可能です—フロントエンドはどのバックエンドを使用するかを気にしません。 バックエンドを構成する実際のPodは変化する可能性がありますが、フロントエンドのクライアントはそれを意識する必要はなく、バックエンドの集合を自身で追跡すべきでもありません。
Serviceという抽象化により、この分離が可能になります。
Serviceが対象とするPodは、通常、ユーザーが定義するセレクターによって決定されます。 Serviceのエンドポイントを定義する他の方法については、セレクター なし のServiceを参照してください。
ワークロードがHTTPを使用する場合、Ingressを使用して、Webトラフィックがワークロードに到達する方法を制御できます。 IngressはServiceタイプではありませんが、クラスターへのエントリポイントとして機能します。 Ingressを使用すると、ルーティングルールを単一のリソースに統合できるため、クラスター内で個別に実行されている複数のワークロードコンポーネントを、単一のリスナーの背後で公開できます。
KubernetesのGateway APIは、IngressやServiceを超える追加機能を提供します。 GatewayはCustomResourceDefinitionを使用して実装された拡張APIの一種であり、クラスターに追加することで、クラスター内で実行されているネットワークサービスへのアクセスを設定できます。
アプリケーションでサービスディスカバリにKubernetes APIを使用できる場合、APIサーバーに問い合わせて一致するEndpointSliceを取得できます。 KubernetesはService内のPodの集合が変更されるたびに、そのServiceのEndpointSliceを更新します。
ネイティブではないアプリケーションの場合、KubernetesはアプリケーションとバックエンドのPodの間にネットワークポートまたはロードバランサーを配置する方法を提供します。
いずれの場合でも、ワークロードはこれらのサービスディスカバリの仕組みを使用して、接続先を見つけることができます。
Serviceはオブジェクトです(PodやConfigMapがオブジェクトであるのと同じです)。
Kubernetes APIを使用してServiceの定義を作成、表示、変更できます。
通常はkubectlのようなツールを使用して、これらのAPI呼び出しを行います。
例えば、TCPポート9376でリッスンし、app.kubernetes.io/name=MyAppというラベルが付けられたPodの集合があるとします。
そのTCPリスナーを公開するServiceを定義できます:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
このマニフェストを適用すると、デフォルトのClusterIP Serviceタイプで「my-service」という名前の新しいServiceが作成されます。
このServiceは、app.kubernetes.io/name: MyAppラベルを持つすべてのPodのTCPポート9376を対象とします。
KubernetesはこのServiceに対してIPアドレス(ClusterIP)を割り当てます。 このIPアドレスは仮想IPアドレスメカニズムによって使用されます。 このメカニズムの詳細については、仮想IPとServiceプロキシを参照してください。
このServiceのコントローラーは、セレクターに一致するPodを継続的にスキャンし、ServiceのEndpointSliceの集合に対して必要に応じて更新を行います。
Serviceオブジェクト名は、有効なRFC 1035ラベル名である必要があります。
portをtargetPortにマッピングできます。
ただし、デフォルトでは、利便性のためにtargetPortはportフィールドと同じ値に設定されます。This is a stable feature in Kubernetes, and has been since version v1.37. It was first available in the v1.34 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate RelaxedServiceNameValidation, Kubernetes ignores it but does not report any error.
RelaxedServiceNameValidationフィーチャーゲートは、Serviceオブジェクト名が数字で始まることを許可します。
このフィーチャーゲートが有効化されている場合、Serviceオブジェクト名は有効なRFC 1123ラベル名である必要があります。
Pod内のポート定義には名前が含まれ、ServiceのtargetPort属性でこれらの名前を参照できます。
例えば、次のようにServiceのtargetPortをPodのポートにバインドできます:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app.kubernetes.io/name: proxy
ports:
- name: name-of-service-port
protocol: TCP
port: 80
targetPort: http-web-svc
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app.kubernetes.io/name: proxy
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
name: http-web-svc
これは、Serviceに異なるポート番号で同じネットワークプロトコルを提供する複数のPodが混在している場合でも、単一の設定された名前を使用して機能します。 これにより、Serviceのデプロイと進化に大きな柔軟性がもたらされます。 たとえば、バックエンドソフトウェアの次のバージョンでPodが公開するポート番号を変更しても、クライアントを壊すことはありません。
ServiceのデフォルトプロトコルはTCPです。 他のサポートされているプロトコルも使用できます。
多くのServiceは複数のポートを公開する必要があるため、Kubernetesは単一のServiceに対して、複数のポート定義をサポートしています。
各ポート定義は、同じprotocolを持つことも、異なるものを持つことも可能です。
Serviceは、セレクターを使ってKubernetes Podへのアクセスを抽象化するのが一般的です。 ただし、セレクター無しで対応するEndpointSliceオブジェクトを使用すれば、クラスター外のバックエンドなど、他の種類のバックエンドも抽象化できます。
例えば:
これらのいずれのシナリオでも、Podに一致するセレクターを指定 せずに Serviceを定義できます。 例えば:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
このServiceにはセレクターが含まれないため、対応するEndpointSliceオブジェクトは自動的に作成されません。 EndpointSliceオブジェクトを手動で追加することで、実行されているネットワークアドレスとポートにServiceをマッピングできます。 例えば、次のように定義します:
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-1 # 慣習で、EndpointSliceの名前にプレフィックスとしてService名を使用します
labels:
# "kubernetes.io/service-name"ラベルを設定する必要があります。
# その値はServiceの名前と一致させてください
kubernetes.io/service-name: my-service
addressType: IPv4
ports:
- name: http # 上記で定義したServiceポート名と一致させる必要があります
appProtocol: http
protocol: TCP
port: 9376
endpoints:
- addresses:
- "10.4.5.6"
- addresses:
- "10.1.2.3"
Service用にEndpointSliceオブジェクトを作成する場合、EndpointSliceには任意の名前を使用できます。
ただし、名前空間内の各EndpointSliceは一意の名前である必要があります。
EndpointSliceにkubernetes.io/service-nameラベルを設定することで、EndpointSliceをServiceに関連付けられます。
エンドポイントのIPは次のものであっては いけません: ループバック(IPv4の場合は127.0.0.0/8、IPv6の場合は::1/128)、またはリンクローカル(IPv4の場合は169.254.0.0/16と224.0.0.0/24、IPv6の場合はfe80::/64)。
エンドポイントIPアドレスは、他のKubernetes ServiceのClusterIPにすることはできません。 これは、kube-proxyが宛先として仮想IPをサポートしていないためです。
自身で作成するEndpointSlice、または独自のコード内で作成するEndpointSliceの場合、endpointslice.kubernetes.io/managed-byラベルに使用する値も選択するべきです。
EndpointSliceを管理する独自のコントローラーコードを作成する場合は、"my-domain.example/name-of-controller"のような値の使用を検討してください。
サードパーティツールを使用している場合は、ツールの名前をすべて小文字で使用し、スペースやその他の句読点をダッシュ(-)に変更してください。
kubectlのようなツールを直接使用してEndpointSliceを管理する場合は、"staff"や"cluster-admins"のような、手動で管理していることを説明する名前を使用してください。
Kubernetes自身のコントロールプレーンによって管理されるEndpointSliceを識別する予約語である"controller"の使用は避けてください。
セレクターの無いServiceへのアクセスは、セレクターがある場合と同じように機能します。 セレクターの無いServiceの例では、トラフィックはEndpointSliceマニフェストで定義された2つのエンドポイントのいずれかにルーティングされます: ポート9376上の10.1.2.3または10.4.5.6へのTCP接続です。
kubectl port-forward service/<service-name> forwardedPort:servicePortのようなアクションは、Serviceにセレクターが無い場合、この制約により失敗します。
これにより、Kubernetes APIサーバーが、呼び出し元に未許可のエンドポイントへのプロキシとして使用されることを防ぐことができます。ExternalName Serviceは、セレクターを持たず、代わりにDNS名を使用するServiceの特殊なケースです。
詳細については、ExternalNameセクションを参照してください。
EndpointSliceは、Serviceの背後にあるネットワークエンドポイントのサブセット(スライス)を表すオブジェクトです。
Kubernetesクラスターは、各EndpointSliceが保持するエンドポイントの数を追跡します。 特定のServiceに紐づくエンドポイント数が多く、しきい値に達した場合、Kubernetesは新しい空のEndpointSliceを追加し、そこに新たなエンドポイント情報を保存します。 デフォルトでは、既存のすべてのEndpointSliceがそれぞれ、少なくとも100個のエンドポイントを含むと、Kubernetesは新しいEndpointSliceを作成します。 Kubernetesは、追加のエンドポイントを追加する必要性が生じるまで、新しいEndpointSliceを作成しません。
このAPIの詳細については、EndpointSliceを参照してください。
EndpointSlice APIは、従来のEndpoints APIの後継です。 非推奨となったEndpoints APIには、EndpointSliceと比較していくつかの問題があります:
このため、すべてのクライアントはEndpointsではなくEndpointSlice APIを使用することをお勧めします。
Kubernetesでは、単一のEndpointsオブジェクトに格納できるエンドポイントの数は制限されています。 Serviceに1000個を超えるエンドポイントが存在する場合、KubernetesはEndpointsオブジェクト内のデータを切り捨てます。 Serviceは複数のEndpointSliceにリンクできるため、1000個という制限はレガシーのEndpoints APIにのみ影響します。
その場合、KubernetesはEndpointsオブジェクトに格納する最大1000個のバックエンドエンドポイントを選択し、Endpointsにendpoints.kubernetes.io/over-capacity: truncatedというアノテーションを設定します。
コントロールプレーンはまた、バックエンドのPod数が1000未満に減少した場合、このアノテーションを削除します。
トラフィックは引き続きバックエンドに送信されますが、レガシーのEndpoints APIに依存するロードバランシング機構は、利用可能なバックエンドのエンドポイントのうち最大1000個にのみトラフィックを送信します。
同様に、APIの制限によって、Endpointsを手動で更新して1000個を超えるエンドポイントを持つようにすることはできません。
appProtocolフィールドは、各Serviceポートに対してアプリケーションプロトコルを指定する方法を提供します。
これは、実装が理解するプロトコルに対して、より高度な動作を提供するためのヒントとして使用されます。
このフィールドの値は、対応するEndpointsおよびEndpointSliceオブジェクトに反映されます。
このフィールドは、標準のKubernetesラベル構文に従います。 有効な値は次のいずれかです:
mycompany.com/my-custom-protocolのような実装定義のプレフィックス付きの名前。
Kubernetes定義のプレフィックス付きの名前:
| プロトコル | 説明 |
|---|---|
kubernetes.io/h2c |
RFC 7540で説明されている平文のHTTP/2 |
kubernetes.io/ws |
RFC 6455で説明されている平文のWebSocket |
kubernetes.io/wss |
RFC 6455で説明されているTLS上のWebSocket |
一部のServiceでは、複数のポートを公開する必要があります。 Kubernetesでは、単一のServiceオブジェクトに複数のポート定義を設定できます。 Serviceに複数のポートを使用する場合、曖昧さを避けるために、すべてのポートに名前を付ける必要があります。 例えば、下記のように設定します:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
Kubernetesの名前全般と同様に、ポート名は小文字の英数字と-のみを含む必要があります。
ポート名は英数字で始まり、英数字で終わる必要もあります。
例えば、123-abcやwebという名前は有効ですが、123_abcや-webは無効です。
アプリケーションの一部(例えば、フロントエンド)で、Serviceをクラスターの外部からアクセス可能な外部IPアドレスとして公開したい場合があります。
KubernetesのServiceタイプを使用すると、必要なServiceの種類を指定できます。
利用可能なtypeの値とその動作は次の通りです:
ClusterIPtypeを指定しない場合に使用されるデフォルトです。
IngressまたはGatewayを使用して、Serviceをパブリックインターネットに公開できます。NodePortNodePort)でServiceを公開します
NodePortを利用可能にするために、Kubernetesは、type: ClusterIPのServiceを要求した場合と同じように、ClusterIPアドレスを設定します。LoadBalancerExternalNameexternalNameフィールドの内容(例えば、ホスト名api.foo.bar.example)にマッピングします。
このマッピングにより、クラスターのDNSサーバーがその外部ホスト名の値を持つCNAMEレコードを返すように設定されます。
いかなる種類のプロキシも設定されません。Service APIのtypeフィールドは階層的な機能として設計されており、上位のタイプは下位のタイプの機能を含みます。
ただし、この階層的な設計には例外があります。
ロードバランサーのNodePort割り当てを無効にすることで、LoadBalancer Serviceを定義できます。
type: ClusterIPこのデフォルトのServiceタイプでは、クラスターが予約済みのIPアドレスプールからIPアドレスが割り当てられます。
他のいくつかのServiceタイプは、ClusterIPタイプを基盤として構築されています。
.spec.clusterIPを"None"に設定したServiceを定義すると、KubernetesはIPアドレスを割り当てません。
詳細については、ヘッドレスServiceを参照してください。
Service作成リクエストの一部として、独自のclusterIPアドレスを指定できます。
指定するためには、.spec.clusterIPフィールドを設定します。
例えば、再利用したい既存のDNSエントリがある場合や、特定のIPアドレス用に設定されていて再設定が困難なレガシーシステムがある場合などです。
選択するIPアドレスは、APIサーバーに設定されているservice-cluster-ip-range CIDR範囲内の有効なIPv4またはIPv6アドレスである必要があります。
無効なclusterIPアドレスの値でServiceを作成しようとすると、APIサーバーは問題が発生したことを示す422 HTTPステータスコードを返します。
Kubernetesがどのように、2つの異なるServiceが同じIPアドレスを使用しようとする際のリスクと影響を軽減するかについては、衝突の回避を参照してください。
type: NodePorttypeフィールドをNodePortに設定すると、Kubernetesコントロールプレーンは--service-node-port-rangeフラグで指定された範囲(デフォルト: 30000-32767)からポートを割り当てます。
各ノードはそのポート(すべてのノードで同じポート番号)をServiceにプロキシします。
割り当てられたポートは、Serviceの.spec.ports[*].nodePortフィールドで確認できます。
NodePortを使用すると、独自のロードバランシングソリューションのセットアップや、Kubernetesで完全にサポートされていない環境の構成、あるいはノードのIPアドレスの直接公開さえ可能になります。
NodePortタイプのServiceの場合、Kubernetesはさらにポート(Serviceのプロトコルに合わせてTCP、UDP、またはSCTP)を割り当てます。
クラスター内のすべてのノードは、割り当てられたポートをリッスンし、Serviceに関連付けられた準備完了状態のエンドポイントの1つにトラフィックを転送するように自身を構成します。
適切なプロトコル(例: TCP)と適切なポート(そのServiceに割り当てられたポート)を使用して任意のノードに接続することで、クラスター外からtype: NodePortのServiceにアクセスできます。
特定のポート番号が必要な場合は、nodePortフィールドに値を指定できます。
コントロールプレーンはそのポートを割り当てるか、APIのトランザクションが失敗したことを報告します。
つまり、ポートの衝突を自分で処理する必要があります。
また、NodePortによる使用のために設定された範囲内の有効なポート番号を使用する必要があります。
以下は、NodePort値(この例では、30007)を指定したtype: NodePortのServiceのマニフェストの例です:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app.kubernetes.io/name: MyApp
ports:
- port: 80
# デフォルトでは、利便性のために`targetPort`は
# `port`フィールドと同じ値に設定されます。
targetPort: 80
# オプションのフィールド
# デフォルトでは、利便性のためにKubernetesコントロールプレーンは
# 範囲(デフォルト: 30000-32767)からポートを割り当てます
nodePort: 30007
NodePortサービスへのポート割り当てのポリシーは、自動割り当てと手動割り当ての両方のシナリオに適用されます。 ユーザーが特定のポートを使用するNodePortサービスを作成する場合、ターゲットポートはすでに割り当てられている別のポートと競合する可能性があります。
この問題を回避するため、NodePortサービスのポート範囲は2つの帯域に分割されています。 動的なポート割り当てはデフォルトで上位の帯域を使用し、上位の帯域が使い尽くされると下位帯域を使用することがあります。 ユーザーは、下位の帯域から割り当てることでポート衝突のリスクを低減することができます。
デフォルトのNodePortの範囲である30000-32767を使用する場合、各帯域は次のように分割されます:
静的帯域と動的帯域がどのように計算されるかの詳細は、NodePort Serviceへのポート割り当てにおける衝突の回避を参照してください。
type: NodePort ServiceのカスタムIPアドレス設定NodePortサービスを提供するために特定のIPアドレスを使用するよう、クラスター内のノードを設定できます。 各ノードが複数のネットワークに接続されている場合(例: アプリケーショントラフィック用のネットワークと、ノード間およびコントロールプレーン間のトラフィック用の別のネットワーク)に、この設定が必要になることがあります。
ポートをプロキシする特定のIPアドレスを指定する場合は、kube-proxyの--nodeport-addressesフラグ、またはkube-proxy設定ファイルの同等のnodePortAddressesフィールドを特定のIPブロックに設定できます。
このフラグは、カンマ区切りのIPブロックリスト(例: 10.0.0.0/8、192.0.2.0/25)を受け取り、kube-proxyがこのノードのローカルとみなすIPアドレス範囲を指定します。
例えば、--nodeport-addresses=127.0.0.0/8フラグでkube-proxyを起動すると、kube-proxyはNodePortサービスに対してループバックインターフェースのみを選択します。
--nodeport-addressesのデフォルトは空のリストです。
これは、kube-proxyがNodePortに対して利用可能なすべてのネットワークインターフェースを考慮する必要があることを意味します。(これは以前のKubernetesリリースとも互換性があります。)
<NodeIP>:spec.ports[*].nodePortおよび.spec.clusterIP:spec.ports[*].portとして表示されます。
kube-proxyの--nodeport-addressesフラグまたはkube-proxy設定ファイルの同等のフィールドが設定されている場合、<NodeIP>はフィルタリングされたノードのIPアドレス(または複数のIPアドレスの可能性)になります。type: LoadBalancer外部ロードバランサーをサポートするクラウドプロバイダーでは、typeフィールドをLoadBalancerに設定すると、Service向けにロードバランサーがプロビジョニングされます。
実際のロードバランサーの作成は非同期で行われ、プロビジョニングされたバランサーに関する情報はServiceの.status.loadBalancerフィールドで公開されます。
たとえば、次のように設定します:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
clusterIP: 10.0.171.239
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 192.0.2.127
外部ロードバランサーからのトラフィックはバックエンドのPodに転送されます。 負荷分散の方法は、クラウドプロバイダーが決定します。
type: LoadBalancerのServiceを実装するために、Kubernetesは通常、まずtype: NodePortのServiceをリクエストした場合と同等の変更を行います。
その後、cloud-controller-managerコンポーネントが外部ロードバランサーを設定し、割り当てられたNodePortにトラフィックを転送します。
クラウドプロバイダーの実装でサポートされている場合、LoadBalancerタイプのServiceを設定してNodePortの割り当てを省略できます。
一部のクラウドプロバイダーではloadBalancerIPを指定できます。
その場合、ユーザーが指定したloadBalancerIPでロードバランサーが作成されます。
loadBalancerIPフィールドが指定されていない場合、ロードバランサーは一時的なIPアドレスで設定されます。
loadBalancerIPを指定しても、クラウドプロバイダーがこの機能をサポートしていない場合、設定したloadbalancerIPフィールドは無視されます。
Serviceの.spec.loadBalancerIPフィールドはKubernetes v1.24で非推奨になりました。
このフィールドは仕様が不十分で、実装によって意味が異なっていました。 また、デュアルスタックネットワーキングをサポートできません。 このフィールドは将来のAPIバージョンで削除される可能性があります。
(プロバイダー固有の)アノテーションを介してServiceのロードバランサーIPアドレスの指定をサポートするプロバイダーと統合する場合は、その方法に切り替えてください。
Kubernetesとロードバランサーの統合コードを書いている場合は、このフィールドの使用を避けてください。 ServiceではなくGatewayと統合するか、同等の詳細を指定するService上の独自の(プロバイダー固有の)アノテーションを定義できます。
ロードバランサーによるヘルスチェックは現代のアプリケーションにとって重要です。
これらはロードバランサーがトラフィックをディスパッチするサーバー(仮想マシンまたはIPアドレス)を決定するために使用されます。
Kubernetes APIはKubernetesが管理するロードバランサーに対してヘルスチェックをどのように実装する必要があるかを定義していません。
代わりに、クラウドプロバイダー(および統合コードを実装する人々)によって動作が決定されます。
ロードバランサーによるヘルスチェックはServiceのexternalTrafficPolicyフィールドをサポートする文脈で広く使用されています。
This is a stable feature in Kubernetes, and has been since the 1.26 release. You can no longer toggle this feature (the associated feature gate has been removed).
デフォルトでは、LoadBalancerタイプのServiceで複数のポートが定義されている場合、すべてのポートは同じプロトコルを持つ必要があり、そのプロトコルはクラウドプロバイダーがサポートするものでなければなりません。
フィーチャーゲートMixedProtocolLBService(v1.24以降のkube-apiserverではデフォルトで有効)により、複数のポートが定義されている場合、LoadBalancerタイプのServiceで異なるプロトコルを使用できます。
spec.allocateLoadBalancerNodePortsフィールドをfalseに設定することで、type: LoadBalancerのServiceに対するNodePort割り当てをオプションで無効にできます。
これは、NodePortを使用せずに、トラフィックをPodに直接ルーティングするロードバランサー実装に対してのみ使用してください。
デフォルトでは、spec.allocateLoadBalancerNodePortsはtrueであり、LoadBalancerタイプのServiceは引き続きNodePortを割り当てます。
既に割り当て済みのNodePortを持つ既存のServiceに対してspec.allocateLoadBalancerNodePortsをfalseに設定しても、それらのNodePortは自動的に割り当て解除されません。
NodePortの割り当てを解除するには、すべてのServiceポートのnodePortsエントリを明示的に削除する必要があります。
typeがLoadBalancerに設定されたServiceの場合、.spec.loadBalancerClassフィールドを使用すると、クラウドプロバイダーのデフォルト以外のロードバランサー実装を使用できます。
デフォルトでは、.spec.loadBalancerClassは設定されておらず、クラスターが--cloud-providerコンポーネントフラグを使用してクラウドプロバイダーで設定されている場合、LoadBalancerタイプのServiceはクラウドプロバイダーのデフォルトロードバランサー実装を使用します。
.spec.loadBalancerClassを指定すると、指定されたクラスに一致するロードバランサー実装がServiceを監視していると想定されます。
デフォルトのロードバランサー実装(たとえば、クラウドプロバイダーが提供するもの)は、このフィールドが設定されたServiceを無視します。
spec.loadBalancerClassはLoadBalancerタイプのServiceにのみ設定できます。
一度設定すると、変更できません。
spec.loadBalancerClassの値はラベル形式の識別子である必要があり、"internal-vip"や"example.com/internal-vip"などのプレフィックスをオプションとして持つことができます。
プレフィックスのない名前はエンドユーザー向けに予約されています。
This is a stable feature in Kubernetes, and has been since the 1.32 release. You can no longer toggle this feature (the associated feature gate has been removed).
type: LoadBalancerのServiceの場合、コントローラーは.status.loadBalancer.ingress.ipModeを設定できます。
.status.loadBalancer.ingress.ipModeは、ロードバランサーIPの動作方法を指定します。
これは.status.loadBalancer.ingress.ipフィールドも指定されている場合にのみ指定できます。
.status.loadBalancer.ingress.ipModeには、「VIP」と「Proxy」の2つの値が設定できます。
デフォルト値は「VIP」で、これはトラフィックがロードバランサーのIPとポートを宛先として設定された状態でノードに配信されることを意味します。
「Proxy」に設定する場合、クラウドプロバイダーのロードバランサーがトラフィックを配信する方法に応じて、2つのケースがあります:
Service実装はこの情報を使用してトラフィックルーティングを調整できます。
混在環境では、同じ(仮想)ネットワークアドレスブロック内のServiceからトラフィックをルーティングする必要がある場合があります。
スプリットホライズンDNS環境では、エンドポイントへの外部トラフィックと内部トラフィックの両方をルーティングできるように、2つのServiceが必要です。
内部ロードバランサーを設定するには、使用しているクラウドサービスプロバイダーに応じて、次のいずれかのアノテーションをServiceに追加します:
いずれかのタブを選択してください。
metadata:
name: my-service
annotations:
networking.gke.io/load-balancer-type: "Internal"
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
metadata:
name: my-service
annotations:
service.kubernetes.io/ibm-load-balancer-cloud-provider-ip-type: "private"
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/openstack-internal-load-balancer: "true"
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/cce-load-balancer-internal-vpc: "true"
metadata:
annotations:
service.kubernetes.io/qcloud-loadbalancer-internal-subnetid: subnet-xxxxx
metadata:
annotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet"
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/oci-load-balancer-internal: true
type: ExternalNameExternalNameタイプのServiceは、my-serviceやcassandraのような典型的なセレクターではなく、ServiceをDNS名にマッピングします。
これらのServiceはspec.externalNameパラメーターで指定します。
たとえば、このServiceの定義は、prod Namespace内のmy-service Serviceをmy.database.example.comにマッピングします:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
type: ExternalNameのServiceはIPv4アドレスの文字列を受け入れますが、文字列をIPアドレスとしてではなく、数字で構成されたDNS名として扱います(ただし、インターネットでは、DNSにそのような名前を設定することは許可されていません)。
IPv4アドレスに似た外部名を持つServiceはDNSサーバーによって解決されません。
ServiceをIPアドレスに直接マッピングしたい場合は、ヘッドレスServiceの使用を検討してください。
ホストmy-service.prod.svc.cluster.localを検索すると、クラスターのDNSサービスはmy.database.example.comを持つCNAMEレコードを返します。
my-serviceへのアクセスは他のServiceと同じように機能しますが、重要な違いは、リダイレクトがプロキシや転送を介してではなく、DNSレベルで発生することです。
後でデータベースをクラスター内に移動することにした場合、Podを起動し、適切なセレクターまたはエンドポイントを追加し、Serviceのtypeを変更できます。
ExternalNameを使用すると、HTTPやHTTPSを含む一部の一般的なプロトコルで問題が発生する可能性があります。 ExternalNameを使用する場合、クラスター内のクライアントが使用するホスト名は、ExternalNameが参照する名前とは異なります。
ホスト名を使用するプロトコルの場合、この違いによりエラーや予期しないレスポンスが発生する可能性があります。
HTTPリクエストには、オリジンサーバーが認識しないHost:ヘッダーが含まれることになります。
また、TLSサーバーは、クライアントが接続したホスト名と一致する証明書を提供できなくなります。
時には、負荷分散や単一のService IPが不要な場合があります。
この場合、ClusterIPアドレス(.spec.clusterIP)に明示的に"None"を指定することで、いわゆる ヘッドレスService を作成できます。
ヘッドレスServiceを使用すると、Kubernetesの実装に縛られることなく、他のサービスディスカバリ機構と連携できます。
ヘッドレスServiceの場合、ClusterIPは割り当てられず、kube-proxyはこれらのServiceを処理せず、プラットフォームによる負荷分散やプロキシは行われません。
ヘッドレスServiceにより、クライアントは好みのPodに直接接続できます。
ヘッドレスServiceは仮想IPアドレスとプロキシを使用してルートやパケット転送を設定しません。
その代わりに、ヘッドレスServiceはクラスターのDNSサービスを通じて提供される内部DNSレコードを介して、個々のPodのエンドポイントIPアドレスを報告します。
ヘッドレスServiceを定義するには、.spec.typeをClusterIPに設定し(typeのデフォルトでもあります)、さらに.spec.clusterIPをNoneに設定します。
文字列値のNoneは特殊なケースであり、.spec.clusterIPフィールドを未設定のままにすることとは異なります。
DNSが自動的に設定される方法は、Serviceにセレクターが定義されているかどうかによって異なります:
セレクターを定義するヘッドレスServiceの場合、エンドポイントコントローラーはKubernetes APIでEndpointSliceを作成し、ServiceのPodを直接指すAまたはAAAAレコード(IPv4またはIPv6アドレス)を返すようにDNS設定を変更します。
セレクターを定義しないヘッドレスServiceの場合、コントロールプレーンはEndpointSliceオブジェクトを作成しません。 ただし、DNSシステムは次のいずれかを検索して設定します:
type: ExternalName ServiceのDNS CNAMEレコードExternalName以外のすべてのServiceタイプについて、Serviceの準備完了エンドポイントのすべてのIPアドレスに対するDNS A/AAAAレコード
セレクターなしでヘッドレスServiceを定義する場合、portはtargetPortと一致する必要があります。
クラスター内で実行されているクライアントに対して、Kubernetesは、環境変数とDNSという2つの主要なServiceの検出方法をサポートしています。
Podがノード上で実行されると、kubeletはアクティブな各Serviceに対して環境変数のセットを追加します。
{SVCNAME}_SERVICE_HOSTと{SVCNAME}_SERVICE_PORT変数が追加されます。
ここで、Service名は大文字に変換され、ハイフンはアンダースコアに変換されます。
たとえば、TCPポートとして6379を公開し、ClusterIPアドレスとして10.0.0.11が割り当てられたService redis-primaryは、次の環境変数を生成します:
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11
PodがServiceにアクセスする必要があり、環境変数を使用してポートとClusterIPをクライアントPodに公開する場合、クライアントPodが作成される前にServiceを作成する必要があります。 そうしないと、クライアントPodに環境変数が設定されません。
DNSのみを使用してServiceのClusterIPを検出する場合は、この順序の問題を気にする必要はありません。
Kubernetesは、Docker Engineの「レガシーコンテナリンク」機能と互換性のある変数もサポートし、提供しています。
これが、Kubernetesにおいて、どのように実装されているかを確認するには、makeLinkVariablesを参照してください。
アドオンを使用して、KubernetesクラスターのDNSサービスを設定できます(そしてほぼ常に設定すべきです)。
CoreDNSなどのクラスター対応のDNSサーバーは、新しいServiceについてKubernetes APIを監視し、それぞれに対してDNSレコードのセットを作成します。 クラスター全体でDNSが有効になっている場合、すべてのPodはDNS名によってServiceを自動的に解決できるはずです。
たとえば、KubernetesのNamespace my-nsにmy-serviceというServiceがある場合、コントロールプレーンとDNS Serviceが連携してmy-service.my-nsのDNSレコードを作成します。
my-ns Namespace内のPodは、my-serviceの名前解決を行うことでServiceを見つけることができるはずです(my-service.my-nsも機能します)。
他のNamespace内のPodは、名前をmy-service.my-nsとして修飾する必要があります。
これらの名前は、Serviceに割り当てられたClusterIPに解決されます。
Kubernetesは、名前付きポートに対するDNS SRV(Service)レコードもサポートしています。
my-service.my-ns ServiceにプロトコルがTCPに設定されたhttpという名前のポートがある場合、_http._tcp.my-service.my-nsに対してDNS SRVクエリを実行して、httpのポート番号とIPアドレスを検出できます。
Kubernetes DNSサーバーは、ExternalName Serviceにアクセスする唯一の方法です。
ExternalNameの解決に関する詳細情報は、ServiceとPodに対するDNSを参照してください。
仮想IPとServiceプロキシでは、Kubernetesが仮想IPアドレスを使用してServiceを公開するために提供する機構について詳しく説明しています。
.spec.internalTrafficPolicyおよび.spec.externalTrafficPolicyフィールドを設定して、Kubernetesが正常な("ready")バックエンドにトラフィックをルーティングする方法を制御できます。
詳細については、トラフィックポリシーを参照してください。
.spec.trafficDistributionフィールドは、Kubernetes Service内のトラフィックルーティングに影響を与える別の方法を提供します。
トラフィックポリシーが厳密なセマンティック保証に焦点を当てているのに対し、トラフィック分散では 優先設定(トポロジー的に近いエンドポイントへのルーティングなど)を表現できます。
これにより、パフォーマンス、コスト、または信頼性の最適化に役立ちます。
Kubernetes 1.37では、次のフィールド値がサポートされています:
PreferSameZonePreferSameNodePreferClose(非推奨)PreferSameZoneの旧称にあたるエイリアスであり、この名称が示す対象が明確ではないため推奨されません。フィールドが設定されていない場合、実装はデフォルトのルーティング戦略を適用します。
詳細については、トラフィック分散を参照してください。
特定のクライアントからの接続が毎回同じPodに渡されるようにしたい場合、クライアントのIPアドレスに基づいてセッションアフィニティを設定できます。 詳細については、セッションアフィニティを参照してください。
もし、1つ以上のクラスターノードに転送する外部IPが複数ある場合、Kubernetes ServiceはそれらをexternalIPsで公開できます。
外部IP(宛先IPとして)とServiceに一致するポートでネットワークトラフィックがクラスターに到達すると、Kubernetesが設定したルールとルートにより、トラフィックがそのServiceのエンドポイントの1つにルーティングされることが保証されます。
Serviceを定義する際、任意のServiceタイプに対してexternalIPsを指定できます。
以下の例では、"my-service"という名前のServiceは、"198.51.100.32:80"(.spec.externalIPs[]と.spec.ports[].portから計算)でTCPを使用してクライアントからアクセスできます。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app.kubernetes.io/name: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 49152
externalIPs:
- 198.51.100.32
externalIPsの割り当てを管理しません。
これらはクラスター管理者の責任です。ServiceはKubernetes REST APIにおいてトップレベルのリソースです。 詳細については、Service APIオブジェクトを参照してください。
Serviceと、それがKubernetesにどのように適合するかについて、さらに学習してください:
さらなる背景情報については、以下を参照してください: