説明
StatefulSet は serviceName で指定した Headless Service を使い、Pod ごとの安定したネットワーク名を提供します。その Service は同じネームスペースに別途作成し、セレクターを StatefulSet の Pod ラベルに合わせる必要があります。名前の指定だけで Service が自動作成されたり、DNS と接続が保証されたりするわけではありません。
想定される影響
- Pod ごとの名前解決やメンバー間の通信に失敗する場合があります。
- Service のセレクターが別の Pod を指すと、意図したワークロードへの接続に障害が生じる場合があります。
対処方法
- 同じネームスペースに clusterIP: None の Headless Service を用意し、serviceName をその名前に合わせてください。セレクター、Pod ラベル、実際の待ち受けポートも確認してください。
- 既存の通常の Service を Headless に変更する前に、再作成と接続中断の影響を計画してください。適用後に EndpointSlice、Pod の準備状態、Pod ごとの DNS と実際の接続を確認してください。
例
app ネームスペースを使う既存の nginx の例です。ネームスペースは別途用意し、10.0.0.20 はクラスターの Service アドレス範囲内で利用可能な値にする必要があります。通常の Service から Headless への変更では、Service の再作成が必要になる場合があります。
変更前
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: app
spec:
clusterIP: 10.0.0.20
selector:
app: other
ports:
- port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: app
spec:
serviceName: nginx
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
通常の ClusterIP Service で、セレクターも StatefulSet の Pod ラベルと異なります。必要な Pod ごとの Headless Service 接続を提供しません。
変更後
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: app
spec:
clusterIP: None
selector:
app: nginx
ports:
- port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: app
spec:
serviceName: nginx
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
同じ nginx という名前の Service を Headless にし、セレクターを Pod ラベルに合わせます。準備状態とクラスターのネットワークを踏まえ、実際の DNS と接続を確認する必要があります。