网络配置

更新时间:
复制为 MD 格式

本文介绍如何为PolarDB AI节点(VNode)上的Pod配置DNS,使其能够发现并访问Kubernetes集群内部的Service。默认情况下,PolarDB AI节点(VNode)上的Pod拥有独立的弹性网卡(ENI),直接接入您指定的VPC网络,这导致它们无法访问Kubernetes集群内部服务。为解决此问题,您可以为集群的CoreDNS服务创建一个内网负载均衡(SLB),并修改PoddnsConfig指向该SLB。通过此方案,PolarDB AI节点(VNode)上的Pod便能正确解析并访问集群内的服务,实现与集群内其他Pod的无缝通信。

工作原理

在标准的Kubernetes集群中,Pod的网络流量会经过其所在的物理节点(Node)。节点上的kube-proxy组件会拦截发往ClusterIP(一个虚拟IP)的流量,并将其转发到后端真实的服务Pod。然而,PolarDB AI节点(VNode)上的Pod拥有自己的弹性网卡(ENI)并直接连接到VPC,其网络路径绕过了物理节点的kube-proxy,因此无法识别和路由到ClusterIP

本方案的原理是:

  1. 为集群内置的DNS服务(CoreDNS)创建两个内网LoadBalancer类型的Service,分别用于处理TCPUDPDNS查询请求。

  2. LoadBalancer Service会自动创建阿里云负载均衡(SLB)实例,并获得一个稳定的VPC内网IP。

  3. PolarDB AI节点(VNode)上的Pod dnsConfig中,将DNS服务器地址(nameservers)指定为上述SLB的内网IP。

  4. PolarDB AI节点(VNode)上的Pod发起服务名称(如my-service.default.svc.cluster.local)的解析请求时,请求会被发送到CoreDNS对应的SLB。

  5. CoreDNS收到请求后,将服务名解析为相应的IP地址并返回给Pod。

    • 对于Headless Service,返回后端所有PodIP列表。

    • 对于LoadBalancer Service,返回其SLBIP地址。

  6. PolarDB AI节点(VNode)上的Pod获得IP地址后,即可直接与目标服务或Pod建立通信。

使用限制

用于解析的目标Service类型需为LoadBalancer ServiceHeadless 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)实例的监听不支持同时转发TCPUDP协议,而DNS服务需要同时依赖这两种协议,因此您需要创建两个独立的Service。

  1. 使用以下YAML内容,创建一个名为coredns-lb-services.yaml的文件。 该配置将创建两个Service,分别名为coredns-slb-udpcoredns-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
  2. (重要)检查并修改Selector:在应用此文件前,请务必确认您集群中CoreDNS Pod的标签。执行以下命令查看:

    kubectl get pod -n kube-system --show-labels | grep coredns

    在输出结果中找到CoreDNS Podk8s-app标签。如果不是k8s-app=kube-dns,请将上面YAML文件中的selector值修改为正确的标签。

  3. 执行以下命令,应用配置。

    kubectl apply -f coredns-lb-services.yaml

    预期结果:

    service/coredns-slb-udp created
    service/coredns-slb-tcp created

步骤二:获取CoreDNS LoadBalancer的私网IP

获取上一步创建的两个SLB实例的私网IP地址,用于后续配置PodDNS服务器。

  1. 执行以下命令,查看刚刚创建的两个ServiceEXTERNAL-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
  2. 记录IP地址:记下这两个EXTERNAL-IP(上述的192.168.26.103192.168.26.102)。

步骤三:在Pod中配置dnsConfig

在您的应用Pod模板中,通过dnsConfig字段强制Pod使用您刚刚创建的CoreDNS SLB作为其DNS服务器。

  1. 在您的Deployment、StatefulSet或其他工作负载的Pod模板(spec.template.spec)中,添加dnsPolicydnsConfig字段。

    • dnsPolicy: "None":表示完全接管PodDNS配置,不再继承节点的设置。

    • dnsConfig:用于定义自定义的DNS配置。

    • searches:定义DNS搜索域。这使得您可以在Pod内直接使用服务名(如my.dns.search.suffix)。

  2. 以下是一个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
      # 关键配置结束
  3. 部署您的应用。

    kubectl apply -f my-app-pod.yaml

步骤四:验证配置

  1. 检查Pod内的DNS配置:进入Pod查看/etc/resolv.conf文件,确认配置已写入。

    kubectl exec -it dns-example -- cat /etc/resolv.conf

    预期结果:输出应包含您在dnsConfig中设置的nameserversearch条目。

    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
  2. 测试服务解析:

    1. 列出了集群中的服务(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
    2. 列出了所有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>
    3. 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
      ...