環境
難しい。公式ドキュメントだと
Podの集合で実行されているアプリケーションをネットワークサービスとして公開する抽象的な方法
としか書かれていない。自分としては「複数のPodに共通のIPアドレス提供するなど、ロードバランサとDNSを設定するためのリソース」で落ち着いた。
まずは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
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
....(略
サービス名だけでアクセス出来るのは同一Namespace内のみ。それ以外は「..svc.」のようにフルパスでアクセスしなくてはいけない。
# 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オプションを付ける必要がある。
参考リンク