導入
Pod の IP が変わってしまう問題を解決するのが Service です。Service は「このラベルが付いた Pod たち」をひとまとめにして、ずっと変わらない仮想の住所(名前と IP) を与えてくれます。宛先を Service に向けておけば、裏で Pod が入れ替わっても気にせず通信を続けられます。
説明
第2章で見た ラベルとセレクタ を思い出してください。Pod には app: web のような ラベル(付箋) を貼れます。Service は セレクタ(selector) で「app: web の付箋が付いた Pod を全部宛先にする」と宣言します。誰が対象かを IP ではなく付箋で決めるので、Pod が作り直されても、同じ付箋さえ付いていれば自動的に対象に含まれます。
apiVersion: v1
kind: Service
metadata:
name: web-svc # この名前が宛先になる
spec:
selector:
app: web # このラベルを持つPodを束ねる
ports:
- port: 80 # Serviceが受けるポート
targetPort: 8080 # 転送先(Pod側)のポート
この Service には ClusterIP と呼ばれる、クラスタ内で不変の仮想 IP が割り当てられます。他の Pod は「web-svc の 80 番」に送るだけでよく、Service が受け取ったリクエストを、対象 Pod のどれか1つへ**振り分け(ロードバランス)**ます。同じ付箋の Pod が3つあれば、アクセスは3つに分散されます。
graph TB
Client["呼び出す側のPod"] --> SVC["Service: web-svc<br/>ClusterIP 固定"]
SVC --> P1["Pod (app: web)"]
SVC --> P2["Pod (app: web)"]
SVC --> P3["Pod (app: web)"]
では Service は「今どの Pod が生きているか」をどう知っているのでしょうか。裏側では Endpoints(エンドポイント) という仕組みが、セレクタに合致する Pod の IP 一覧を常に最新に保っています。Pod が増えれば一覧に追加され、消えれば一覧から外れます。Service はこの一覧を見て振り分けるため、私たちは Pod の増減を意識せずに済むのです。
Service の ClusterIP は、Service を消さない限り変わりません。「変わる Pod の IP」を「変わらない Service の IP」で包み隠す、というのが k8s ネットワーキングの基本発想です。