Nodelocaldns在最新版kubernetes集群的部署以及问题解决

关于K8S域名解析遭遇5秒延迟的问题(UDP并发导致的内核模块conntrack竞争),早先看到Weaveworks这篇经典文章和最近左耳朵耗子团队赵锟的视频技术分享,一直没有时间部署和验证,今天终于在PC上vagrant的集群操练一把,还是发现一些问题,值得记录一下,先放参考链接:

Racy conntrack and DNS lookup timeouts - Weaveworks 经典文章

技术分享:Kubernetes Networking Model (赵锟) 耗子出品,必属精品

Coredns+Nodelocaldns cache解决Coredns域名解析延迟 华为这篇文章翻译烂,凑合看

组件 版本
K8S集群版本 v1.21.3
Containerd版本 cri-containerd-cni-1.5.4-linux-amd64.tar.gz
Nodelocaldns版本 1.17.0

集群基础镜像

1
2
3
4
5
6
7
- pause:3.4.1
- kube-apiserver:v1.21.3
- kube-controller-manager:v1.21.3
- kube-scheduler:v1.21.3
- kube-proxy:v1.21.3
- etcd:3.4.13-0
- coredns:v1.8.0

基于vagrant + ansible role的组合搭建一套集群还是很方便的,这次搭建集群顺便彻底用containerd一个解压即可用的二进制包替换了docker,也发现config.toml里面配置的insecure registry用户名密码不生效问题,尚未解决,奇怪的是ctr和crictl命令行带用户名密码去拉镜像是没问题的。

由于下载google的镜像需要一些办法,所以顺手把相关的镜像已经push在docker.io/ajasonwang下面了,部署过程精简为一个ansible role如下,已省略部分内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- name: update kubelet dns setting
shell: |
sed -i 's/__PILLAR__DNS__SERVER__/10.96.0.10/g' /tmp/nodelocaldns.yaml
sed -i 's/__PILLAR__LOCAL__DNS__/169.254.20.10/g' /tmp/nodelocaldns.yaml
sed -i 's/__PILLAR__DNS__DOMAIN__/cluster.local/g' /tmp/nodelocaldns.yaml
run_once: true

- name: Pull nodelocaldns images
command: crictl pull --creds "{{ dockerRegistryUser }}":"{{ dockerRegistryPasswd }}" "{{ dockerInsecureRegistries }}/{{ item }}"
with_items:
- k8s-dns-node-cache:1.17.0

- name: Install nodelocaldns
command: kubectl apply -f /tmp/nodelocaldns.yaml
delegate_to: "{{ play_hosts | first }}"

- name: update kubelet dns setting
shell: |
sed -i 's/10.96.0.10/169.254.20.10/g' /var/lib/kubelet/config.yaml

- name: Restart kubelet service
systemd:
daemon_reload: yes
name: kubelet
state: restarted

按照以上步骤部署nodelocaldns之后在worker节点尝试验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat>dnsutils-for-node-local-dns.yaml<<EOF
apiVersion: v1
kind: Pod
metadata:
name: dnsutils
namespace: default
spec:
containers:
- name: dnsutils
image: docker.io/ajasonwang/dnsutils:latest
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
EOF

验证命令:

kubectl exec -i -t dnsutils – nslookup kubernetes.default

居然报解析不到,查看CoreDNS日志

kubectl logs –namespace=kube-system -l k8s-app=kube-dns

错误如下:

[INFO] plugin/ready: Still waiting on: “kubernetes”
E0819 14:15:26.023715 1 reflector.go:138] pkg/mod/k8s.io/client-go@v0.21.1/tools/cache/reflector.go:167: Failed to watch *v1.EndpointSlice: failed to list *v1.EndpointSlice: endpointslices.discovery.k8s.io is forbidden: User “system:serviceaccount:kube-system:coredns” cannot list resource “endpointslices” in API group “discovery.k8s.io” at the cluster scope
[INFO] plugin/ready: Still waiting on: “kubernetes”

进一步搜索发现这个权限错误居然是是coredns的一个bug, 于是编辑coredns的clusterrole配置

kubectl edit clusterrole system:coredns

内容,在最后面追加

  • apiGroups:
    • discovery.k8s.io
      resources:
    • endpointslices
      verbs:
    • list
    • watch

最终问题解决

[root@master1 vagrant]# kubectl exec -i -t dnsutils – nslookup kubernetes.default
Server: 169.254.20.10
Address: 169.254.20.10#53

Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1

K8S的新版本总是会有一些bug,好在总有早鸟走在前面。


Nodelocaldns在最新版kubernetes集群的部署以及问题解决
https://ajasonwang.github.io/2021/08/21/nodelocaldns/
作者
Wang Jia
发布于
2021年8月21日
许可协议