Kubernetes v1.21 [stable]
Kubernetesでは、EndpointSliceにはネットワークエンドポイントの集合への参照が含まれます。 コントロールプレーンは、セレクターが指定されているKubernetes ServiceのEndpointSliceを自動的に作成します。 これらのEndpointSliceには、Serviceセレクターに一致するすべてのPodへの参照が含まれています。 EndpointSliceは、IPファミリー、プロトコル、ポート番号、およびService名の一意の組み合わせによってネットワークエンドポイントをグループ化します。 EndpointSliceオブジェクトの名前は有効なDNSサブドメイン名である必要があります。
一例として、以下にexampleというKubernetes Serviceによって所有されるサンプルのEndpointSliceオブジェクトを示します。
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: example-abc
labels:
kubernetes.io/service-name: example
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.1.2.3"
conditions:
ready: true
hostname: pod-1
nodeName: node-1
zone: us-west2-a
既定では、コントロールプレーンはEndpointSliceを作成・管理し、それぞれのエンドポイント数が100以下になるようにします。
--max-endpoints-per-slicekube-controller-managerフラグを設定することで、最大1000個まで設定可能です。
EndpointSliceは内部トラフィックのルーティング方法に関して、kube-proxyに対する信頼できる唯一の情報源(source of truth)として機能します。
EndpointSliceは次の2種類のアドレスをサポートします。
各EndpointSliceオブジェクトは、特定のIPアドレス種別を表します。
IPv4とIPv6の両方が利用可能なServiceがある場合は、少なくとも2つのEndpointSliceオブジェクト(IPv4用とIPv6用)が存在します。
EndpointSlice APIはコンシューマーの役に立つエンドポイントの状態を保持しています。
状態にはserving、terminating、readyの3種類があります。
Kubernetes v1.26 [stable]
serving状態は、そのエンドポイントが現在レスポンスを返していることを示し、Serviceトラフィックのターゲットとして使用されるべきであることを表します。
Podをバックに持つエンドポイントでは、PodのReady状態に対応します。
Kubernetes v1.26 [stable]
terminating状態は、そのエンドポイントが終了処理中であることを示します。
Podをバックに持つエンドポイントでは、この状態はPodが最初に削除された時点に設定されます(つまりdeletionタイムスタンプを受け取った時点であり、通常はPodのコンテナが終了する前)。
Serviceプロキシは通常、terminating状態のエンドポイントを無視しますが、利用可能なエンドポイントがすべてterminating状態である場合は、servingとterminatingの両方が設定されているエンドポイントへトラフィックをルーティングすることがあります(これは、基盤となるPodのローリングアップデート中にServiceのトラフィックが失われないようにするためです)。
ready状態は、実質的には"servingかつterminatingではない"ことを確認するためのショートカットです(ただし、spec.publishNotReadyAddressesがtrueに設定されているServiceでは、常にtrueになります)。
EndpointSliceに属する各エンドポイントは、関連するトポロジーの情報を持つことができます。 トポロジー情報には、エンドポイントの配置場所、および対応するノードやゾーンに関する情報が含まれます。 これらは、EndpointSliceの各エンドポイントに対する以下のフィールドで利用できます。
nodeName - このエンドポイントが存在するノードの名前。zone - このエンドポイントが存在するゾーン。ほとんどの場合、コントロールプレーン(具体的には、EndpointSliceコントローラー)が、EndpointSliceオブジェクトを作成および管理します。 EndpointSliceには、サービスメッシュの実装など、他のさまざまなユースケースがあり、他のエンティティまたはコントローラーがEndpointSliceの追加セットを管理する可能性があります。
複数のエンティティが互いに干渉することなくEndpointSliceを管理できるようにするために、KubernetesはEndpointSliceを管理するエンティティを示すendpointslice.kubernetes.io/managed-byというラベルを定義します。
EndpointSliceコントローラーは、自身が管理するすべてのEndpointSliceに対して、このラベルの値としてendpointslice-controller.k8s.ioを設定します。
EndpointSliceを管理するその他のエンティティも同様に、このラベルに一意な値を設定する必要があります。
ほとんどのユースケースでは、EndpointSliceはEndpointSliceオブジェクトがエンドポイントを追跡するServiceによって所有されます。
これは、各EndpointSlice上のownerリファレンスとkubernetes.io/service-nameラベルによって示されます。
これにより、Serviceに属するすべてのEndpointSliceを簡単に検索できるようになっています。
それぞれのEndpointSliceにはポートの集合があり、リソース内のすべてのエンドポイントに適用されます。 Serviceが名前付きポートを使用した場合、Podは同じ名前のポートに対して、結果的に異なるターゲットポート番号を持つことがあり、そのため異なるEndpointSliceが必要になる場合があります。
コントロールプレーンはEndpointSliceをできる限り埋めようとしますが、積極的にリバランスを行うことはありません。 コントローラーのロジックは極めて単純で、以下のようになっています。
ここで重要なのは、3番目のステップでEndpointSliceを完全に分散させることよりも、EndpointSliceの更新を制限することを優先していることです。 たとえば、もし新しい追加するべきエンドポイントが10個あり、2つのEndpointSliceにそれぞれ5個の空きがあった場合、このアプローチでは2つの既存のEndpointSliceを埋める代わりに、新しいEndpointSliceが作られます。 言い換えれば、1つのEndpointSliceを作成する方が、複数のEndpointSliceを更新するよりも好ましいということです。
各ノード上で実行されているkube-proxyはEndpointSliceを監視しており、EndpointSliceに加えられた変更はクラスター内のすべてのノードに送信されるため、比較的コストの高い処理になります。 先ほどのアプローチは、たとえ複数のEndpointSliceが埋まらない結果になるとしても、すべてのノードへ送信しなければならない変更の数を抑制することを目的としています。
現実的には、こうしたあまり理想的ではない分散が発生することは稀です。 EndpointSliceコントローラーによって処理されるほとんどの変更は、既存のEndpointSliceに収まるほど十分小さくなるためです。 そうでなかったとしても、すぐに新しいEndpointSliceが必要になる可能性が高いです。 また、Deploymentのローリングアップデートでは、すべてのPodとそれに対応するエンドポイントが置き換えられるため、EndpointSliceも自然に再配置されます。
EndpointSliceの変更の性質上、エンドポイントは同時に複数のEndpointSliceで表される場合があります。 これは、さまざまなEndpointSliceオブジェクトへの変更が、さまざまな時間にKubernetesクライアントのウォッチ/キャッシュに到達する可能性があるために自然に発生します。 EndpointSliceを使用する実装では、エンドポイントを複数のスライスに表示できる必要があります。
EndpointSlice APIのクライアントは、Serviceに関連づけられた既存のすべてのEndpointSliceをイテレートして、一意のネットワークエンドポイントの完全な一覧を構築する必要があります。 異なるEndpointSliceに同じエンドポイントが重複して存在する可能性がある点に注意が必要です。
このようなエンドポイントの集約および重複排除を実行する方法のリファレンス実装は、kube-proxy内のEndpointSliceCacheのコードにあります。
Kubernetes v1.33 [deprecated]
EndpointSlice APIは旧来のEndpoint APIを置き換えるものです。 kube-proxyがEndpointリソースに基づいてトラフィックをルーティングすることを前提としている古いコントローラーやユーザーワークロードとの互換性を維持するために、クラスターのコントロールプレーンは、ユーザーが作成したほとんどのEndpointリソースを対応するEndpointSliceにミラーリングします。
(ただし、この機能はEndpoint APIの他の部分と同様に非推奨です。 セレクターを持たないServiceに対してEndpointを手動で指定するユーザーは、Endpointリソースを作成してミラーリングさせるのではなく、EndpointSliceリソースを直接作成する必要があります。)
コントロールプレーンは、次の場合を除いて、Endpointリソースをミラーリングします。
endpointslice.kubernetes.io/skip-mirrorラベルがtrueに設定されている。control-plane.alpha.kubernetes.io/leaderアノテーションを持っている。個々のEndpointリソースは、複数のEndpointSliceに変換される場合があります。 これは、Endpointリソースに複数のサブセットがある場合、または複数のIPファミリ(IPv4およびIPv6)を持つエンドポイントが含まれている場合に発生します。 サブセットごとに最大1000個のアドレスがEndpointSliceにミラーリングされます。