日記マン

動画広告プロダクトしてます。Go, Kubernetesが好きです。

DaemonSetの名前解決でハマったのでメモ

Kubernetesで、Pod内部のコンテナ同士は、localhostで通信できる。
では、Pod同士の通信には、基本的にはServiceで公開したもの同士で、割り振られるDNSを利用して通信できる。
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pods

セットアップ

cloud "namespace: ns-foo" as foo {
    component "pod-foo" as A
}
cloud "namespace: ns-bar" as bar {
    component "pod-bar" as B
}

A <--> B : <<How?>>

まずは、 app=foo ラベルで紐づかれた svc-foo と pod-foo
(※実際のyamlとかなり省略してる)

kind: Service
metadata:
    name: svc-foo
    namespace: ns-foo
    labels:
        app: foo
spec:
    selector:
        matchLabels:
            app: foo

---

kind: Pod
metadata:
    name: pod-foo
    namespace: ns-foo
    labels:
        app: foo
spec:
    subdomain: foo-subdomain # 任意で、サブドメインを指定できる

つづいて、 app=bar で紐づいた svc-barpod-bar

kind: Service
metadata:
    name: svc-bar
    namespace: ns-bar
    labels:
        app: bar
spec:
    selector:
        matchLabels:
            app: bar

---

kind: Pod
metadata:
    name: pod-bar
    namespace: ns-bar
    labels:
        app: bar
spec: # サブドメインを設定しない

kubeDNS

ここで、 kube-dnskube-proxy についておさらいする。
あなたが Serviceリソース定義を kube-apiserver に送信したとき、 (kubectl apply -f )
apiserver はリクエストを受け付けると etcd にリソース内容を永続化する。
kubernetesクラスタに常駐している kube-dnskube-proxy が、そのイベントを検知し、
kube-proxy はリソースで定義された通りのルーティングを、
kube-dns は名前解決を担当して動いてくれる。

わかりやすいページ https://tech.uzabase.com/entry/2017/09/12/164756

上述のService svc-foo は、 kube-dns により

pod-foo.foo-subdomain.ns-foo.svc.cluster.local --> svc-foo のIP

DNSとServiceのIPが紐づけられ、
kube-proxy により

svc-foo のIP --> Pod の IP
(この例ではService : Pod 1:1 だが、実際の運用は Service : Deployment(ReplicaSet) になるため、
複数のレプリカに対しラウンドロビンでルーティングする。

という風に紐づけられる。

というわけで

pod-foo から pod-bar に通信するDNSは、
pod-bar.ns-bar.svc.cluster.local でOK
pod-bar から pod-foo
pod-foo.foo-subdomain.ns-foo.svc.cluster.local でOK

DaemonSetでDNS解決ができなくてハマった

promtail をDaemonSetで起動して、Serviceとして公開している lokiDNS名義でログストリームを送信しようとしたら、
dns lookupできないエラーがでた。

promtailコンテナの中に入って /etc/resolv.conf みにいって確認したら、
kube-dns による名前解決が存在しなかった。
Deploymentリソースなどであれば、勝手に kube-dns のlookupが効いたけど、
DaemonSetリソースだと kube-dns のlookup が反映されていなかった。

https://varu3.hatenablog.com/entry/2018/05/24/200311

このページが詳しい。
解決策からいうと、
hostNetwork: truednsPolicy: ClusterFirstWithHostNet を設定してあげれば、
その DaemonSet からも KubeDNSの名前解決で他のPodと通信ができる。

なんでDaemonSetにkube-dnsが適用されていないのか?

ここのアンサーがそれっぽい。
https://stackoverflow.com/questions/53888389/difference-between-daemonsets-and-deployments

Kube-dns responsibility is to discover the service IP using its name and even one replica of kube-dns is enough to resolve the service name to its IP and hence we make kube-dns a deployment because we don't need kube-dns on every node.

DaemonSetはノードに一つだけ起動されるリソースである。
ノードに複数のレプリカを配置する前提のDeploymentとはそこが決定的に違う。
そのため、ノードに一つしかないDaemonSetはIPも一つなので、
わざわざDNSによる名前解決は必要ない。

多分そういう理由・・・。自信はない。