概述
DNS作为k8s的关键基础服务,在配置不合理,集群规模较大时,DNS容易出现解析超时、解析失败等现象。本文介绍Kubernetes集群中CoreDNS配置优化的最佳实践,帮助您避免此类问题。
前提条件
- 创建一个云容器引擎集群,具体操作步骤请参见新建云容器引擎集群。
- 通过kubectl连接集群,详情请参见通过kubectl连接集群。
- 安装CoreDNS插件(推荐安装CoreDNS最新版本),详情请参见CoreDNS介绍。
实践方案
CoreDNS配置优化方案包含客户端和服务端的实践。
- 在客户端,您可以通过使用合适的容器镜像,优化域名解析请求,增加节点DNS缓存等方式来降低解析时延和减少解析异常。
- 优化域名解析请求
- 选择合适的容器镜像
- 避免IPVS缺陷导致的DNS概率性解析超时
- 使用节点DNS缓存(NodeLocal DNSCache)
- 谨慎调整节点的DNS配置
- 在服务端,您可以合理的调整CoreDNS部署状态或者调整CoreDNS配置来提升集群CoreDNS的可用性和吞吐量。
- 监控CoreDNS运行状态
- 合理调整CoreDNS部署状态
- 合理配置CoreDNS
优化域名解析请求
DNS域名解析请求作为Kubernetes最高频的网络行为之一,我们可以通过以下方式优化域名解析请求:
- 优化容器内resolv.conf文件:容器内配置域名的不同写法决定了域名解析的效率,关于resolv.conf文件中ndots和search两个参数的机制详情,请参见:DNS策略。
- 优化域名配置:当容器内应用需要访问某域名,建议该域名按以下原则配置,可以最大程度减少域名解析尝试次数和耗时。
- 同命名空间下,Pod访问Service,优先使用
访问,其中service-name代指Service名称。 - 不同命名空间下,Pod访问另一个命名空间的Service,优先使用
. 访问,其中namespace-name代指Service所处的命名空间。 - Pod访问集群外部域名时,优先使用FQDN类型域名访问,这类域名通过常见域名最后加半角句号(.)的方式来指定地址,可以避免search搜索域拼接带来的多次无效搜索,例如需要访问天翼云,则优先使用FQDN类型域名来访问。
- 同命名空间下,Pod访问Service,优先使用
- 使用连接池:当一个容器应用需要频繁请求另一服务时,推荐使用连接池。连接池可以缓存上游服务的链接信息,避免每次访问服务时域名解析和创建TCP连接的开销。
- 使用本地DNS缓存:当集群规模增大,DNS解析请求量变多,可以考虑在节点缓存DNS(NodeLocal DNSCache)解析结果,具体操作,请参见:NodeLocal DNSCache加速。
选择合适的容器镜像
如果在云容器引擎集群中部署的应用容器使用了Alpine作为基础镜像,可能会因为下述musl libc特性导致无法正常解析域名,此时建议尝试更换基础镜像,如Debian、CentOS等。Alpine容器镜像内置的musl libc库与标准的glibc存在以下差异:
- 3.3版本及更早版本的Alpine不支持search参数,不支持搜索域,无法完成服务发现。
- 并发请求
etc/resolve.conf
中配置的多个DNS服务器,导致节点DNS缓存的优化失效。 - 并发使用同一Socket请求A和AAAA记录,在旧版本内核上会触发Conntrack源端口冲突导致丢包问题。
避免IPVS缺陷导致的DNS概率性解析超时问题
当集群的kube-proxy负载均衡模式为IPVS时,缩容或重启CoreDNS可能会遇到DNS概率性解析超时的问题。该问题由社区Linux内核缺陷导致,具体信息请查看社区。
您可以通过使用节点DNS缓存(NodeLocal DNSCache),降低IPVS缺陷的影响,具体操作请参见:NodeLocal DNSCache加速。
使用节点DNS缓存(NodeLocal DNSCache)
节点DNS缓存(NodeLocal DNSCache)可以提升服务发现的稳定性和性能,详情请参见:NodeLocal DNSCache加速。
谨慎调整节点的DNS配置
CoreDNS启动时会默认获取实例所在节点 /etc/resolve.conf
中的DNS配置,而且在CoreDNS重启之前不会再重新加载该节点上的resolve.conf配置。建议保持集群中各个节点的resolve.conf配置一致,并在修改CoreDNS实例所在节点resolve.conf文件后及时重启CoreDNS。
监控CoreDNS状态
云容器引擎监控组件默认配置了CoreDNS相关的指标监控和告警规则。具体安装操作请参见集群监控。
合理调整集群CoreDNS部署状态
CoreDNS应部署于您的Kubernetes集群中,默认情况下与您的业务容器运行在同样的集群节点上,注意事项如下:
- 合理调整CoreDNS副本数
- 合理分配CoreDNS副本运行的位置
- 手动扩容副本数
- 基于CPU负载指标自动扩容副本数(HPA)
合理调整CoreDNS副本数
建议您在任何情况下设置CoreDNS副本数应至少为2,且副本数维持在一个合适的水位以承载整个集群的解析。
CoreDNS所能提供的域名解析QPS与CPU消耗成正相关,开启缓存的情况下,单个CPU可以支撑10000+ QPS的域名解析请求。不同类型的业务对域名请求的QPS需求存在较大差异,您可以观察每个CoreDNS副本的峰值CPU使用量,如果其在业务峰值期间占用CPU大于一核,建议您对CoreDNS进行副本扩容。无法确定峰值CPU使用量时,可以保守采用副本数和集群节点数1:8的比值来部署,即每扩容8个集群节点,增加一个CoreDNS副本,但副本数不应大于10。针对100节点以上的集群,推荐使用节点DNS缓存NodeLocal DNSCache。
- 当集群节点数目长时间较为固定时,可以手动扩容副本数。
- 如果集群节点数持续增长,可以设置自动扩容副本数。
合理分配CoreDNS副本运行的位置
建议您在部署CoreDNS副本时,应将CoreDNS副本打散在不同可用区、不同集群节点上,避免单节点、单可用区故障。CoreDNS默认配置了按节点的弱反亲和性,可能会因为节点资源不足导致部分或全部副本部署在同一节点上,如果遇到这种情况,请删除Pod重新触发其调度来调整。
CoreDNS所运行的集群节点应避免CPU、内存用满的情况,否则会影响域名解析的QPS和响应延迟。当集群节点条件允许时,可以考虑使用自定义参数将CoreDNS调度至独立的集群节点上,以提供稳定的域名解析服务。关于CoreDNS调度至独立的集群节点的方式,请参见使用自定义参数完成CoreDNS独占部署。
手动扩容副本数
当集群节点数长时间较为固定时,您可以通过以下命令扩容CoreDNS副本数。
kubectl scale --replicas={target} deployment/coredns -n kube-system
基于CPU负载指标自动扩容副本数(HPA)
由于HPA会频繁触发CoreDNS副本缩容,建议您不要使用容器水平扩缩容(HPA),如果您的场景下必须依赖于HPA,请参考以下基于CPU负载的策略配置:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: coredns-hpa
namespace: kube-system
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: coredns
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 50
合理配置CoreDNS
云容器引擎仅提供CoreDNS的默认配置,您应关注配置中的各个参数、优化其配置,以使CoreDNS可以为您的业务容器正常提供DNS服务。CoreDNS的配置非常灵活。
早期版本随Kubernetes集群部署的CoreDNS默认配置可能存在一些风险,推荐您按以下方式检查和优化:
- 合理调整CoreDNS的资源Request和Limit
- 关闭kube-dns服务的亲和性配置
- 配置CoreDNS优雅退出
- 配置Ready就绪探针插件