文档首页/ 云容器引擎 CCE/ 最佳实践/ 容器/ CCE容器中域名解析的最佳实践
更新时间:2024-11-12 GMT+08:00

CCE容器中域名解析的最佳实践

本文档重点介绍在CCE容器中如何配置域名解析。

服务

  • 在创建工作负载(Deployment或ReplicaSet)之前,需要先创建与之相关联的服务。 因为Kubernetes在启动容器时,会为容器提供所有正在运行的服务作为环境变量。 例如,如果存在名为foo的服务,则所有容器将在其初始环境中获得以下变量。
    FOO_SERVICE_HOST=<the host the Service is running on>
    FOO_SERVICE_PORT=<the port the Service is running on>

    因此必须在Pod被创建之前创建它想要访问的任何Service, 否则环境变量将不会生效,而使用DNS则没有此限制。

  • CCE集群提供了CoreDNS插件作为集群中的DNS服务器。DNS服务器为新的Services监视Kubernetes API,并为每个Services创建一组DNS记录。 如果在整个集群中启用了DNS,则所有Pods应该能够自动对Services进行名称解析。
  • 除非绝对必要,否则不要为Pod指定hostPort。 将Pod绑定到hostPort时,它会限制Pod可以调度的位置数,因为每个<hostIP, hostPort, protocol>组合必须是唯一的。 如果您没有明确指定hostIP和protocol,Kubernetes将使用0.0.0.0作为默认hostIP和TCP作为默认protocol。

如果您只需要访问端口以进行调试,则可以使用apiserver proxy或kubectl port-forward。

如果您明确需要在节点上公开Pod的端口,请在使用hostPort之前考虑使用NodePort服务。

  • 避免使用hostNetwork,原因与hostPort相同。
  • 当您不需要kube-proxy负载均衡时,使用无头服务headless-services(ClusterIP被设置为None)以便于服务发现。

DNS

CCE的Kubernetes集群默认提供了一个DNS插件Service,即使用CoreDNS自动为其它Service指派DNS域名。 如果它在集群中处于运行状态,可以通过如下命令来检查:

kubectl get services coredns --namespace=kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.0.0.10    <none>        53/UDP,53/TCP   8m

如果没有在运行,可以describe这个pod查看没有启用的原因。 假设已经有一个Service,它具有一个长久存在的IP, 一个为该IP指派名称的DNS服务器(coredns集群插件),可以通过标准做法,使在集群中的任何Pod都能与该Service通信。可以运行另一个curl应用来进行测试,启用新的pod并通过进入容器内部curl当前这个service的域名,查看是否能正确解析域名。当然,有的场景下是无法curl通的,这与接下来的Dns的查找原理与配置有关。

使用CCE提供的托管式Kubernetes创建Pod,Pod的域名解析参数采用了一些默认值,没有开放全部的dnsConfig配置。在使用时候,您需要了解清楚提供的默认配置。典型的一个配置是ndots ,如果您在Pod内访问的域名字符串,数量在ndots阈值范围内,则被认为是Kubernetes集群内部域名,会被追加 ..svc.cluster.local后缀。

DNS查找原理与规则

DNS域名解析配置文件 /etc/resolv.conf

nameserver 10.247.x.x
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:3

参数说明:

  • nameserver:域名解析服务器。
  • search:域名的查找后缀规则,查找配置越多,说明域名解析查找匹配次数越多,这里匹配有3个后缀,则查找规则至少6次,因为IPv4,IPv6都要匹配一次。
  • options:域名解析选项,多个KV值;其中典型的有ndots ,访问的域名字符串内的点字符数量超过ndots值,则认为是完整域名,直接解析,如不足,则追加 ..svc.cluster.local后缀。

Kubernetes的dnsConfig配置说明

  • nameservers:将用作Pod的DNS服务器的IP地址列表。最多可以指定3个IP地址。当Pod dnsPolicy设置为“ None”时,列表必须至少包含一个IP地址,否则此属性是可选的。列出的服务器将合并到从指定的DNS策略生成的基本名称服务器,并删除重复的地址。
  • searches:Pod中主机名查找的DNS搜索域列表。此属性是可选的。指定后,提供的列表将合并到从所选DNS策略生成的基本搜索域名中,并删除重复的域名。Kubernetes最多允许6个搜索域。
  • options:可选的对象列表,其中每个对象可以具有name属性(必需)和value属性(可选)。此属性中的内容将合并到从指定的DNS策略生成的选项中,并删除重复的条目。

详情请参考:Kubernetes官网的dns配置说明

DnsPolicy域名解析的几种场景应用

POD里的DNS策略可以对每个Pod进行设置,支持三种策略:Default、ClusterFirst、None。

  • Default:表示Pod里面的DNS配置继承了宿主机上的DNS配置。简单来说,就是该Pod的DNS配置会跟宿主机完全一致,也就是和node上的dns配置是一样的。
  • ClusterFirst:相对于上述的Default,ClusterFirst是完全相反的操作,它会预先把kube-dns(或CoreDNS)的信息当作预设参数写入到该Pod内的DNS配置。ClusterFirst是默认的pod设置,若没有在Pod内特别描述PodPolicy,则会将dnsPolicy预设为ClusterFirst。不过ClusterFirst还有一个冲突,如果您的Pod设置了HostNetwork=true,则ClusterFirst就会被强制转换成Default。
  • None:表示会清除Pod预设的DNS配置,当dnsPolicy设置成这个值之后,Kubernetes不会为Pod预先载入任何自身逻辑判断得到的DNS配置。因此若要将dnsPolicy的值设为None,为了避免Pod里面没有配置任何DNS,建议再添加dnsConfig来描述自定义的DNS参数。

请参阅下面的DNS配置场景:

场景一:采用自定义DNS

采用自己建的DNS来解析Pods中的应用域名配置,可以参考以下代码配置,此配置在Pod中的DNS可以完全自定义,适用于已经有自己建的DNS,迁移后的应用也不需要去修改相关的配置。

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster.local
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

场景2:采用kubernets的DNS插件CoreDNS

优先使用Kubernetes的DNS服务解析,失败后再使用外部级联的DNS服务解析。

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: ClusterFirst

场景3:采用公网域名解析

适用于Pods中的域名配置都在公网访问,这样的话Pods中的应用都从外部的DNS中解析对应的域名。

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: Default

场景4:采用HostNet的DNS解析

如果在Pod中使用hostNetwork:true来配置网络,pod中运行的应用程序可以直接看到宿主机的网络接口,宿主机所在的局域网上所有网络接口都可以访问到该应用程序,配置如下所示:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

如果不加上dnsPolicy: ClusterFirstWithHostNet,即便pod默认使用宿主机的DNS,也会导致容器内不能通过service name访问K8s集群中其他Pod。

CoreDNS配置

1、CoreDNS ConfigMap选项

查看默认的CoreDns的配置文件:

Corefile: |
  .:53 {
      errors
      health
      kubernetes cluster.local in-addr.arpa ip6.arpa {
         pods insecure
         upstream
         fallthrough in-addr.arpa ip6.arpa
      }
      prometheus :9153
      forward . /etc/resolv.conf
      cache 30
      loop
      reload
      loadbalance

参数说明:

  • error:错误记录到stdout。
  • health:CoreDNS的运行状况报告为http://localhost:8080/health。
  • kubernetes:CoreDNS将根据Kubernetes服务和Pod的IP回复DNS查询。
  • prometheus:CoreDNS的度量标准可以在http://localhost:9153/Prometheus格式的指标中找到;可以通过http://localhost:9153/metrics获取prometheus格式的监控数据。
  • proxy、forward:任何不在Kubernetes集群域内的查询都将转发到预定义的解析器(/etc/resolv.conf);本地无法解析后,向上级地址进行查询,默认使用宿主机的/etc/resolv.conf配置。
  • cache:启用前端缓存。
  • loop:检测简单的转发循环,如果找到循环则停止CoreDNS进程。
  • reload:允许自动重新加载已更改的Corefile。编辑ConfigMap配置后,请等待两分钟以使更改生效。
  • loadbalance:这是一个循环DNS负载均衡器,可以在答案中随机化A,AAAA和MX记录的顺序。

2、配置外部dns

有些服务不在Kubernetes内部,在内部环境内需要通过dns去访问,名称后缀为carey.com。

carey.com:53 {
        errors
        cache 30
        proxy . 10.150.0.1
    }

完整的配置文件:

Corefile: |
  .:53 {
      errors
      health
      kubernetes cluster.local in-addr.arpa ip6.arpa {
         pods insecure
         upstream
         fallthrough in-addr.arpa ip6.arpa
      }
      prometheus :9153
      forward . /etc/resolv.conf
      cache 30
      loop
      reload
      loadbalance
  }
  carey.com:53 {
      errors
      cache 30
      proxy . 10.150.0.1
  }

当前CCE的插件管理支持配置存根域,相比较直接编辑comfigmap更加灵活方便,无需关注pod的域名解析配置场景。