IPVS 模式安装 NodeLocalDNS
背景
TKE 对 NodeLocalDNS 进行了产品化支持,直接在扩展组件里面就可以一键安装到集群,参考 NodeLocalDNSCache 扩展组件说明 ,但是有一种情况不支持:集群网络是 GlobalRouter 且 kube-proxy 转发模式 IPVS。
本文介绍如何为 GlobalRouter + IPVS 的 TKE 集群安装 NodeLocalDNS。
前提条件
- 集群网络模式为 GlobalRouter。
- kube-proxy 的模式为 IVPS。
- 配置好了 TKE 集群的 kubeconfig,可以用 kubectl 操作 TKE 集群。
- 安装了 helm 和 kustomize。
安装方法
git clone --depth 1 https://github.com/tke-apps/nodelocaldns.git
cd nodelocaldns
make
原 理:
- 自动获取 kubernetes nodelocaldns 插件最新 yaml 模板和当前集群
kube-dns
的ClusterIP
并填充模板生成最终的nodelocaldns.yaml
在当前目录。 - 自动将生成的
nodelocaldns.yaml
部署到当前集群。
如果你使用 GitOps 方式部署应用,可只执行
make yaml
来生成nodelocaldns.yaml
,然后将该 yaml 文件放入 GitOps 使用的仓库中。
修改 kubelet 参数
如果要让 DNS 缓存组件生效,还需要配置节点上的 kubelet 参数:--cluster-dns=169.254.20.10
。
IPVS 模式集群由于需要为所有 Service 在
kube-ipvs0
这个 dummy 网卡上绑对应的 Cluster IP,以实现 IPVS 转发,所以 localdns 就无法再监听集群 DNS 的 Cluster IP。而 kubelet 的--cluster-dns
默认指向的是集群 DNS 的 Cluster IP 而不是 localdns 监听的地址,安装 localdns 之后集群中的 Pod 默认还是使用的集群 DNS 解析,所以我们需要修改 kubelet 的--cluster-dns
参数。
可以通过以下脚本进行修改并重启 kubelet 来生效:
sed -i 's/CLUSTER_DNS.*/CLUSTER_DNS="--cluster-dns=169.254.20.10"/' /etc/kubernetes/kubelet
systemctl restart kubelet
挨个手动配置不太现实,下面介绍自动化的配置方法。
配置增量节点
新建节点或节点池里指定节点初始化后的【自定义脚本】,这样就可以让节点初始化后自动执行脚本来配置 kubelet 参数:
已有的节点池也可以通过修改节点池配置来指定自定义脚本。
修改存量节点
可以 ansible 来批量修改,ansible 安装方式参考 官方文档: Installing Ansible 。
安装好 ansible 之后,按照以下步骤操作:
-
导出所有节点 IP 到
hosts.ini
:kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}' | tr ' ' '\n' | grep -vE '^169\.254\.*' > hosts.ini
-
准备脚本
modify-kubelet.sh
:sed -i 's/CLUSTER_DNS.*/CLUSTER_DNS="--cluster-dns=169.254.20.10"/' /etc/kubernetes/kubelet
systemctl restart kubelet -
准备可以用于节点登录的 ssh 秘钥或密码 (秘钥改名为 key,并执行
chmod 0600 key
) -
使用 ansible 在所有节点上运行脚本
modify-kubelet.sh
:- 使用秘钥的示例:
ansible all -i hosts.ini --ssh-common-args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --user root --private-key=key -m script -a "mo dify-kubelet.sh"
- 使用密码的示例:
ansible all -i hosts.ini --ssh-common-args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" -m script --extra-vars "ansible_user=root an sible_password=yourpassword" -a "modify-kubelet.sh"
注: 如果节点使用的 ubuntu 系统,默认 user 是 ubuntu,可以自行替换下,另外 ansible 参数再加上
--become --become-user=root
以便让 ansible 执行脚本时拥有 root 权限,避免操作失败。 - 使用秘钥的示例:
关于存量 Pod
集群中正在运行的存量 Pod 还是会使用旧的集群 DNS,等重建后会自动切换到 localdns,新创建的 Pod 也都会默认使用 localdns。
一般没特别需要的情况下,可以不管存量 Pod,等下次更新, Pod 重建后就会自动切换到 localdns;如果想要立即切换,可以将工作负载滚动更新触发 Pod 重建来实现手动切换。
关于 NodeLocalDNS 版本
安装方法中使用的开源项目所使用的 NodeLocalDNS addon 的 YAML 是 Kubernetes 官方提供的 YAML 自动替换生成的,实时保持最新版本。
官方的依赖镜像
registry.k8s.io/dns/k8s-dns-node-cache
在国内无法拉取,已替换为 DockerHub 上的 mirror 镜像 k8smirror/k8s-dns-node-cache,会周期性的自动同步最新的 tag,可放心使用。