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的域名解析配置场景。