本文介绍如何为PolarDB AI节点(VNode)上的Pod配置DNS,使其能够发现并访问Kubernetes集群内部的Service。默认情况下,PolarDB AI节点(VNode)上的Pod拥有独立的弹性网卡(ENI),直接接入您指定的VPC网络,这导致它们无法访问Kubernetes集群内部服务。为解决此问题,您可以为集群的CoreDNS服务创建一个内网负载均衡(SLB),并修改Pod的dnsConfig指向该SLB。通过此方案,PolarDB AI节点(VNode)上的Pod便能正确解析并访问集群内的服务,实现与集群内其他Pod的无缝通信。
工作原理
在标准的Kubernetes集群中,Pod的网络流量会经过其所在的物理节点(Node)。节点上的kube-proxy组件会拦截发往ClusterIP(一个虚拟IP)的流量,并将其转发到后端真实的服务Pod。然而,PolarDB AI节点(VNode)上的Pod拥有自己的弹性网卡(ENI)并直接连接到VPC,其网络路径绕过了物理节点的kube-proxy,因此无法识别和路由到ClusterIP。
本方案的原理是:
为集群内置的DNS服务(CoreDNS)创建两个内网
LoadBalancer类型的Service,分别用于处理TCP和UDP的DNS查询请求。LoadBalancer Service会自动创建阿里云负载均衡(SLB)实例,并获得一个稳定的VPC内网IP。
在PolarDB AI节点(VNode)上的Pod
dnsConfig中,将DNS服务器地址(nameservers)指定为上述SLB的内网IP。当PolarDB AI节点(VNode)上的Pod发起服务名称(如
my-service.default.svc.cluster.local)的解析请求时,请求会被发送到CoreDNS对应的SLB。CoreDNS收到请求后,将服务名解析为相应的IP地址并返回给Pod。
对于
Headless Service,返回后端所有Pod的IP列表。对于
LoadBalancer Service,返回其SLB的IP地址。
PolarDB AI节点(VNode)上的Pod获得IP地址后,即可直接与目标服务或Pod建立通信。
使用限制
用于解析的目标Service类型需为LoadBalancer Service或Headless Service。此方案不支持直接访问ClusterIP类型的Service。
配置Pod以访问集群内服务
流程概述
配置过程主要分为三步:首先为CoreDNS创建内网SLB服务,然后获取SLB的私网 IP,最后在您的PolarDB AI节点(VNode)上的Pod中配置dnsConfig指向该IP。
步骤一:为CoreDNS创建内网LoadBalancer Service
通过创建LoadBalancer类型的Service,将集群内部的CoreDNS服务暴露到VPC网络中,以便PolarDB AI节点(VNode)上的Pod可以访问。由于单个阿里云负载均衡(SLB)实例的监听不支持同时转发TCP和UDP协议,而DNS服务需要同时依赖这两种协议,因此您需要创建两个独立的Service。
使用以下YAML内容,创建一个名为
coredns-lb-services.yaml的文件。 该配置将创建两个Service,分别名为coredns-slb-udp和coredns-slb-tcp,它们都指向后端的CoreDNS Pod。# coredns-lb-services.yaml apiVersion: v1 kind: Service metadata: name: coredns-slb-udp namespace: kube-system annotations: # 指定创建私网类型的负载均衡实例 service.beta.kubernetes.io/backend-type: eni service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet" labels: k8s-app: coredns-slb-udp spec: type: LoadBalancer ports: - name: dns-udp port: 53 protocol: UDP targetPort: 53 selector: # 此选择器用于匹配 CoreDNS Pod 的标签,参考kubectl get pod -n kube-system --show-labels | grep coredns k8s-app: kube-dns --- apiVersion: v1 kind: Service metadata: name: coredns-slb-tcp namespace: kube-system annotations: # 指定创建私网类型的负载均衡实例 service.beta.kubernetes.io/backend-type: eni service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet" labels: k8s-app: coredns-slb-tcp spec: type: LoadBalancer ports: - name: dns-tcp port: 53 protocol: TCP targetPort: 53 selector: # 确保此选择器与您的 CoreDNS Pod 标签一致,kubectl get pod -n kube-system --show-labels | grep coredns k8s-app: kube-dns(重要)检查并修改Selector:在应用此文件前,请务必确认您集群中CoreDNS Pod的标签。执行以下命令查看:
kubectl get pod -n kube-system --show-labels | grep coredns在输出结果中找到CoreDNS Pod的
k8s-app标签。如果不是k8s-app=kube-dns,请将上面YAML文件中的selector值修改为正确的标签。执行以下命令,应用配置。
kubectl apply -f coredns-lb-services.yaml预期结果:
service/coredns-slb-udp created service/coredns-slb-tcp created
步骤二:获取CoreDNS LoadBalancer的私网IP
获取上一步创建的两个SLB实例的私网IP地址,用于后续配置Pod的DNS服务器。
执行以下命令,查看刚刚创建的两个Service的
EXTERNAL-IP:kubectl get service -n kube-system -l "k8s-app in (coredns-slb-udp, coredns-slb-tcp)"预期结果:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE coredns-slb-tcp LoadBalancer 172.xxx.xxx.164 192.168.26.103 53:31765/TCP 112s coredns-slb-udp LoadBalancer 172.xxx.xxx.25 192.168.26.102 53:30508/UDP 112s记录IP地址:记下这两个
EXTERNAL-IP(上述的192.168.26.103和192.168.26.102)。
步骤三:在Pod中配置dnsConfig
在您的应用Pod模板中,通过dnsConfig字段强制Pod使用您刚刚创建的CoreDNS SLB作为其DNS服务器。
在您的Deployment、StatefulSet或其他工作负载的Pod模板(
spec.template.spec)中,添加dnsPolicy和dnsConfig字段。dnsPolicy: "None":表示完全接管Pod的DNS配置,不再继承节点的设置。dnsConfig:用于定义自定义的DNS配置。searches:定义DNS搜索域。这使得您可以在Pod内直接使用服务名(如my.dns.search.suffix)。
以下是一个Nginx Pod的示例。请将其中的
nameservers列表替换为您在上一步中获取到的IP地址。将内容保存为my-app-pod.yaml。# my-app-pod.yaml apiVersion: v1 kind: Pod metadata: namespace: default name: dns-example spec: containers: - name: nginx image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 # 关键配置开始 dnsPolicy: "None" # 必须设置为 "None" 才能自定义 dnsConfig dnsConfig: nameservers: # 替换为上一步获取的 SLB 私网 IP - "192.168.26.103" - "192.168.26.102" # 以下是阿里云的公共DNS,建议保留,用于访问其他云产品 - "100.100.2.136" searches: # 推荐的搜索域列表,确保服务短名称能被正确解析 - default.svc.cluster.local - svc.cluster.local - cluster.local - my.dns.search.suffix #自定义 options: - name: ndots value: "2" - name: edns0 # 关键配置结束部署您的应用。
kubectl apply -f my-app-pod.yaml
步骤四:验证配置
检查Pod内的DNS配置:进入Pod查看
/etc/resolv.conf文件,确认配置已写入。kubectl exec -it dns-example -- cat /etc/resolv.conf预期结果:输出应包含您在
dnsConfig中设置的nameserver和search条目。search default.svc.cluster.local svc.cluster.local cluster.local my.dns.search.suffix nameserver 192.168.26.103 nameserver 192.168.26.102 nameserver 100.100.2.136 options edns0 ndots:2测试服务解析:
列出了集群中的服务(Service):此处包含一个
Headless Service。kubectl get svc返回结果如下:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 172.xxx.xxx.xxx <none> 443/TCP 28d my-headless-svc ClusterIP None <none> 80/TCP 6m58s列出了所有Pod的详细信息:
kubectl get pod -owide返回结果如下:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hello-pod 1/1 Running 0 15d 192.168.xxx.xxx cn-beijing.192.168.xxx.xxx <none> <none> my-webapp-deployment-5ff7474796-42xl4 1/1 Running 0 92s 192.168.16.7 cn-beijing.192.168.xxx.xxx <none> <none> my-webapp-deployment-5ff7474796-68bnz 1/1 Running 0 92s 192.168.xxx.xxx cn-beijing.192.168.xxx.xxx <none> <none>在Pod内部执行测试命令:
kubectl exec -it hello-pod -- sh wget -O- http://my-headless-svc:80返回结果如下:一个运行在虚拟节点上的Pod (
hello-pod),通过您配置的CoreDNS LoadBalancer,成功地解析了集群内部一个Headless Service(my-headless-svc) 的名称,并直接连接到了该服务背后的一个具体Pod(my-webapp-deployment-5ff7474796-42xl4)。这标志着您的DNS配置验证成功。Resolving my-headless-svc (my-headless-svc)... 192.168.16.7, 192.168.xxx.xxx Connecting to my-headless-svc (my-headless-svc)|192.168.16.7|:80... connected. HTTP request sent, awaiting response... 200 OK ...