logo

20221224

KubernetesでCoreDNSがループしてしまう問題への対処

1年前にも Kubernetes クラスターを自力で組んでトラブルシューティングしてみる【The Hard Way】の記事の中で軽く解説したネタです。

環境

  • Ubuntu 22.04
  • Kubernetes v1.26.0
  • kubeadm v1.26.0

問題

Kubernetes クラスター内で名前解決に使われる CoreDNS の Pod が CrashLoopBackOff になってしまい再起動を繰り返す問題が発生することがあります。

# kubectl -n kube-system logs coredns-787d4945fb-6kb5t
.:53
[INFO] plugin/reload: Running configuration SHA512 = 591cf328cccc12bc490481273e738df59329c62c0b729d94e8b61db9961c2fa5f046dd37f1cf888b953814040d180f52594972691cd6ff41be96639138a43908
CoreDNS-1.9.3
linux/amd64, go1.18.2, 45b0a11
[FATAL] plugin/loop: Loop (127.0.0.1:34129 -> :53) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 1033981844954998931.6641498229839068582."

原因

https://coredns.io/plugins/loop/#troubleshooting

Ubuntu 18.04 以降などの最近のディストリビューションで、ローカルの DNS スタブリゾルバ (systemd-resolved) が使われるようになったことが原因です。Kubelet の設定ファイル /var/lib/kubelet/config.yaml を見るとデフォルトでは下記のように設定されています。

resolvConf: /run/systemd/resolve/resolv.conf

ここで指定されているファイル /run/systemd/resolve/resolv.conf が kubelet によって、CoreDNS コンテナに渡されます。デフォルトでは中身は以下のようになっているはずです。

# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).
# Do not edit.
#
# This file might be symlinked as /etc/resolv.conf. If you're looking at
# /etc/resolv.conf and seeing this text, you have followed the symlink.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs should typically not access this file directly, but only
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
# different way, replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.1
search .

OS 上ではスタブリゾルバがいるので 127.0.0.1 を DNS とするように設定されていますが、CoreDNS のコンテナ内ではそのコンテナ自身を指すことになります。結果的にループしてしまい、クラッシュします。

解決方法

原因は上記の通りなので、127.0.0.1 ではない外部の DNS サーバーを設定すれば解決できます。

/run/systemd/resolve/resolv.conf は systemd-resolved の管理下にある自動生成ファイルですので、大元の設定ファイル /etc/systemd/resolved.conf を修正し、systemd-resolved を再起動することで /run/systemd/resolve/resolv.conf を再生成させます。

その後新しい resolv.conf の内容を反映させるために kubelet と Container runtime (containerd) を再起動します。

NAMESERVER_ADDRESSES=8.8.8.8
sed -i "s/^DNS=127.0.0.1$/DNS=${NAMESERVER_ADDRESSES}/" /etc/systemd/resolved.conf
systemctl restart systemd-resolved
systemctl restart kubelet
systemctl restart containerd

CoreDNS が無事 Running になれば OK です。

root@controlplane:~# kubectl -n kube-system get po -w
NAME                                      READY   STATUS             RESTARTS     AGE
calico-kube-controllers-7bdbfc669-w4xxt   1/1     Running            0            2m57s
calico-node-2f2qc                         1/1     Running            0            15m
coredns-787d4945fb-6kb5t                  0/1     CrashLoopBackOff   5 (7s ago)   16m
coredns-787d4945fb-q5bhz                  0/1     CrashLoopBackOff   5 (7s ago)   16m
etcd-controlplane                         1/1     Running            0            16m
kube-apiserver-controlplane               1/1     Running            0            16m
kube-controller-manager-controlplane      1/1     Running            0            16m
kube-proxy-692c8                          1/1     Running            0            16m
kube-scheduler-controlplane               1/1     Running            0            16m
coredns-787d4945fb-6kb5t                  0/1     Running            6 (19s ago)   16m
coredns-787d4945fb-6kb5t                  1/1     Running            6 (19s ago)   16m
coredns-787d4945fb-q5bhz                  0/1     Running            6 (25s ago)   16m
coredns-787d4945fb-q5bhz                  1/1     Running            6 (25s ago)   16m