以下の記事で k8s の headless service と pod の名前解決を学んだので記録します。間違ってたらツッコミください。
Keycloak + Infinispanで分散キャッシュをしてセッション共有・冗長化する方法
https://qiita.com/uturned0/items/37d2ce64d04a3f3a5dd2
kubernetes pods の 名前解決
dockerから乗り換えてずっとよくわからなかったのが名前解決。一つのnamespaceにpod-A, Bがある時、お互いの名前解決はどうやってするのでしょうか? docker networkなら同じnetworkにあれば簡単に行けるのが、k8sだとできません。k8sではpod間の通信は serviceを通じて行う仕組みになっているそうです。
ただ、ちなみに k8s では同じnamespaceにあるpod同士は通信が可能です。podのIP addressを指定すれば ping も返ってきます。
pod-A $ ping -c1 172.18.5.221 # pod-B
PING 172.18.5.221 (172.18.5.221) 56(84) bytes of data.
64 bytes from 172.18.5.221: icmp_seq=1 ttl=62 time=1.25 ms
しかし、わかりやすいpod名でアクセスする方法は分かりませんでした。chatGPTはserviceを作ればできるというけれども、serviceに名前解決をして返ってくるのはserviceのIP addressであって pod の IP Addressではありません。
headless-service を作って擬似的にpodの名前解決をする
pod 間で名前解決をしたい場合は headless-service を使うことができます。これは(私からすると)不思議なserviceです。podがserviceのFQDNに名前解決をすると pod の ip address が返ってきます。serviceのselectorで特定のpodを指定していれば、特定のpodの名前解決をすることができます。ここでは、複数のpodを指定したselectorで試してみます。
official doc
まず headless service を作ってみましょう。残念ながら headless: true
のような分かりやすい設定は存在せず、 clusterIP: None
がそのスイッチとなっています。(分かりづらい...)
---
apiVersion: v1
kind: Service
metadata:
name: headless-service
namespace: myapp
spec:
clusterIP: None # <------ これが headless service に必須の設定です
selector:
app: myapp
kubectl apply -f headless-service.yml
でこのリソースを作成しましょう。
このサービスを使うと、podは以下のフォーマットに即したFQDNで名前解決を行うことができます。
<service-name>.<namespace-name>.svc.cluster.local
この場合は、以下の FQDN になります。
headless-service.myapp.svc.cluster.local
podの中から実際にリクエストをしてみます。 .53
と .221
の pod の名前解決がされます。2つの順番は必ず .53
が上で、一貫性があります。
$ dig a +short headless-service.myapp.svc.cluster.local
172.18.3.53
172.18.5.221
$ dig a +short headless-service.myapp.svc.cluster.local
172.18.3.53
172.18.5.221
$ dig a +short headless-service.myapp.svc.cluster.local
172.18.3.53
172.18.5.221
$ dig a +short headless-service.myapp.svc.cluster.local
172.18.3.53
172.18.5.221
ここで pod の数を増やすと、当然返却されるIP addressも増えます。つまり headless serviceは、一つの FQDN で selector に対応する全ての pod の ip addressをまとめて返す DNS service だと考えることができます。infinispan ではこの FQDN を使って、namespace 内の inifinispan nodes を discover(発見)します。
headless service の名前解決は一貫しているため、このままでは DNS round robinはされません。それはclientの責務であり、clientの実装次第になるそうです。例えば、 host
コマンドは内部でランダムな並び替えを実行するため、DNS round robin されたような出力をします。以下の例では .221
と .53
いずれかが先頭に表示されます。
$ host headless-service.myapp.svc.cluster.local
headless-service.myapp.svc.cluster.local has address 172.18.5.221
headless-service.myapp.svc.cluster.local has address 172.18.3.53
$ host headless-service.myapp.svc.cluster.local
headless-service.myapp.svc.cluster.local has address 172.18.3.53
headless-service.myapp.svc.cluster.local has address 172.18.5.221
$ host headless-service.myapp.svc.cluster.local
headless-service.myapp.svc.cluster.local has address 172.18.3.53
headless-service.myapp.svc.cluster.local has address 172.18.5.221
$ host headless-service.myapp.svc.cluster.local
headless-service.myapp.svc.cluster.local has address 172.18.5.221
headless-service.myapp.svc.cluster.local has address 172.18.3.53
以上、k8sのserviceは難しいという学びの記録でした。