環境
- Kubernetes 1.24
KubernetesのServiceリソースとは
難しい。公式ドキュメントだと
Podの集合で実行されているアプリケーションをネットワークサービスとして公開する抽象的な方法
としか書かれていない。自分としては「複数のPodに共通のIPアドレス提供するなど、ロードバランサとDNSを設定するためのリソース」で落ち着いた。
ServiceのIPアドレス確認
まずはNginxのDeploymentを作成してみる
kubectl create deploy nginx --image=nginx
そしてServiceリソースを作成
kubectl expose deploy nginx --port=80 --target-port=80
諸々割り当てられたIPアドレスを確認してみる
❯ kubectl get svc nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx ClusterIP 10.96.184.249 <none> 80/TCP 13s ~ ❯ kubectl get ep nginx NAME ENDPOINTS AGE nginx 10.244.0.77:80 30s ~ ❯ kubectl get pods --selector=app=nginx -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-8f458dc5b-qr65w 1/1 Running 0 3m16s 10.244.0.77 ubuntu01 <none> <none>
- ServiceのClusterIP: 10.96.184.249
- PodのIPアドレス: 10.244.0.77
つまり10.96.184.249へアクセスすると、ロードバランサによって10.244.0.77へルーティングされるということになる
DNSでアクセスする
IPアドレスわかるんだからこれでOK、とはならない。KubernetesではIPアドレスの変化が激しいからいつ 10.96.184.249 が変わってもおかしくない。
そこで標準でDNSサービスが提供されている。
同じNamespace内に適当なPodを立てて中に入って検証する
kubectl create deploy debugger --image=thr3a/debugger -- sleep infinity
サービス名である「nginx」で名前を引ける。ちゃんとnginx ServiceのClusterIPである 10.96.184.249 が返ってきている。
/ # nslookup nginx Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx.test.svc.cluster.local Address: 10.96.184.249
なんで出来るのかっていうとKubernetes内にDNSサーバーがあるから。コンテナ内の /etc/resolv.conf を見てみる
/ # cat /etc/resolv.conf search test.svc.cluster.local svc.cluster.local cluster.local nameserver 10.96.0.10 options ndots:5
もちろんcurlでアクセス可能
/ # curl nginx <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } ....(略
サービス名だけでアクセス出来るのは同一Namespace内のみ。それ以外は「
# namespaceがtest以外の場合 nslookup nginx.test.svc.cluster.local
スケールしてみるとどうなるのか
nginx Deploymentをスケールアウトさせてみるとどうなるのか。試しにレプリカセットを2に増やしてみる。
$ kubectl scale deploy nginx --replicas=2
するとエンドポイントのIPが増える。Nginxのログ見てるとわかるが、均一にアクセスが負荷分散されている。
❯ kubectl get ep nginx NAME ENDPOINTS AGE nginx 10.244.0.205:80,10.244.0.77:80 5m46s
Headless Serviceを試す
ServiceのclusterIP(.spec.clusterIP)の値を None
に設定すると、Headless Serviceになる。つまりService自体にロードバランサー機能は持たず、IPアドレスも持たなくなる。
物は試しに一度Serviceを削除してから --cluster-ip=None
を追加して再作成してみる。
kubectl expose deploy nginx --port=80 --target-port=80 --cluster-ip=None
epは変わらず
❯ kubectl get ep nginx NAME ENDPOINTS AGE nginx 10.244.0.205:80,10.244.0.77:80 5m46s
が、DNSで名前を引くとIPがPodの数だけ返ってくる。
/ # nslookup nginx Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx.test.svc.cluster.local Address: 10.244.0.205 Name: nginx.test.svc.cluster.local Address: 10.244.0.77
digコマンドだとIPアドレスが解決できない
digコマンドはデフォルトでは resolv.confのsearchを考慮しない。よってnslookup相当のことがしたければ
dig nginx +search
と明示的にsearchオプションを付ける必要がある。