kubernetesはserviceの仕組みの中でVIPを使って背後の複数podへのルーティングを管理していて、多くのケースではよしなにやってくれるので便利なのだが、以前Nettyを使ってservice間のコネクションを管理していて、背後にある複数podへの接続が偏る問題に悩んでいた。やりたいこととしては、背後のpod達に完全に均等に接続を振りたいのに、serviceを使うとランダム要素を排除することができず、一定の確率でコネクションがかたよってしまう。
そのときは接続数を増やす(たとえば3バックエンドに対して3コネクションだとどこかに偏ってしまう可能性大だが、3バックエンドに対して300コネクションはれば平均に回帰するのでだいたい均等になる)&一定時間ごとに接続を貼り直すという対策をとったが、headless serviceを使う手もあるというのを最近知った。
きっかけとしてはこの記事で、gRPCも似たような問題に遭遇することがある。
Kubernetes上でgRPCサービスを動かす | SOTA
- 公式ドキュメント
- headless serviceについて(日本語)
上記の記事を読むと、serviceのclusterIPをNoneで起動すればheadless serviceになるみたいなので、試してみた。
まずは普通にサービスを起動する場合。
ローカルのminikubeを立ち上げておいて、
minikube start helm init
ingress controller + バックエンドnginxの組み合わせの公式のhelm chartで試してみる
helm install stable/nginx-ingress --set defaultBackend.replicaCount=3
ingress-controllerのpodが1つ、backendのpodが1つできている。
ᐅ kubectl get pods NAME READY STATUS RESTARTS AGE opinionated-saola-nginx-ingress-controller-7b64bf5b74-gk6pw 0/1 Running 0 9s opinionated-saola-nginx-ingress-default-backend-759d876cd-pkgsr 1/1 Running 0 9s opinionated-saola-nginx-ingress-default-backend-759d876cd-sbdnr 1/1 Running 0 9s opinionated-saola-nginx-ingress-default-backend-759d876cd-zr8ng 1/1 Running 0 9s
ᐅ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15m opinionated-saola-nginx-ingress-controller LoadBalancer 10.100.231.194 <pending> 80:32561/TCP,443:32723/TCP 24s opinionated-saola-nginx-ingress-default-backend ClusterIP 10.97.231.34 <none> 80/TCP 24s
今回はClusterIPが貼られているのでheadlessではない。この場合はnslookup
で引いてもClusterIPが返ってくる。
# nslookup opinionated-saola-nginx-ingress-default-backend Server: 10.96.0.10 Address: 10.96.0.10#53 Non-authoritative answer: Name: opinionated-saola-nginx-ingress-default-backend.default.svc.cluster.local Address: 10.97.231.34
次にheadless serviceで起動した場合。
helm install stable/nginx-ingress --set defaultBackend.replicaCount=3 --set defaultBackend.service.clusterIP=None
backendのClusterIPをNoneにした。
ᐅ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19m original-pig-nginx-ingress-controller LoadBalancer 10.108.233.23 <pending> 80:30045/TCP,443:30788/TCP 6s original-pig-nginx-ingress-default-backend ClusterIP None <none> 80/TCP 6s
# nslookup original-pig-nginx-ingress-default-backend Server: 10.96.0.10 Address: 10.96.0.10#53 Name: original-pig-nginx-ingress-default-backend.default.svc.cluster.local Address: 172.17.0.5 Name: original-pig-nginx-ingress-default-backend.default.svc.cluster.local Address: 172.17.0.6 Name: original-pig-nginx-ingress-default-backend.default.svc.cluster.local Address: 172.17.0.8
この場合には、3つのアドレスが返ってくる。
headless serviceを使えば各podのIPに直接アクセスできるので、接続の偏りの問題があるときに、クライアント側での対処方法として使えそう。