简介:coredns_v1.8.0.tar.gz 面向在 Kubernetes 集群中部署与维护 DNS 服务的运维及开发人员,提供与 k8s v1.21.2 环境适配的 CoreDNS 镜像文件,可用于离线环境导入、集群 DNS 组件升级或故障排查时替换验证,适合具备一定容器与集群基础的中级使用者。压缩包共 8 个文件,约 40.62MB,以 4 个 json 清单与配置描述文件、2 个 tar 层归档及 2 个 version 版本标识文件为主,整体符合容器镜像分层存储结构,便于通过镜像仓库或本地导入方式加载使用。已有 409 人学习下载,说明该版本在同类环境中具有一定参考价值。借助包内完整的镜像层与清单信息,读者可快速完成 CoreDNS 镜像的离线分发与版本核对,减少因网络受限导致的拉取失败问题,并为集群 DNS 解析异常的定位与回滚提供可用的镜像基础。
1. 从一次 CoreDNS 镜像拉取失败说起:为什么我坚持用 coredns_v1.8.0.tar.gz 离线装
上周帮一个朋友排查集群故障,现象很典型:Pod 全在 Running,但服务之间互相调不通,nslookup一跑就超时。登上去一看,CoreDNS 的两个副本卡在 ImagePullBackOff,节点根本拉不到镜像。这种场景在隔离环境、内网机房、边缘节点上太常见了——集群能起来,DNS 起不来,整个 k8s 就等于半瘫。coredns_v1.8.0.tar.gz 这个离线包,就是给这类环境准备的:把镜像文件提前落到本地,绕开拉取环节,装完直接跑。这篇笔记按我实际部署的顺序写,从版本选择、镜像导入、配置调整到验证排错,新手能照着走通,熟手能对照看参数取舍。
2. 装前把环境列清楚:版本、依赖和镜像格式先对齐
动手之前先把三件事确认掉,能省掉后面一大半的返工:k8s 集群版本、容器运行时类型、以及这个 tar.gz 里到底是什么。coredns_v1.8.0 对应的是 CoreDNS 1.8.0 这个上游版本,它和 k8s 的兼容关系不是随便配的,选错了轻则 DNS 解析慢,重则整个集群域名解析全挂。
2.1 版本对应关系:1.8.0 适合哪些集群
CoreDNS 1.8.0 是 k8s 1.19 到 1.21 时期默认搭配的版本,这个区间的集群用它最稳。如果你跑的是 1.22 以后的集群,默认已经是 1.8.4 及以上,硬塞 1.8.0 一般也能跑,但要注意两处差异:一是 1.8.0 的kubernetes插件对 EndpointSlice 的支持不如后续版本完整,大集群下解析性能会有差别;二是 1.8.0 的配置语法里forward插件的健康检查参数和 1.9.x 略有不同。我的做法是:集群版本在 1.19~1.21,直接用 1.8.0;超出这个范围,先在小规模测试节点上验证一遍再铺开。
| 集群版本 | 建议 CoreDNS 版本 | 用 1.8.0 的风险点 |
|---|---|---|
| 1.19~1.21 | 1.8.0 | 无,原生匹配 |
| 1.22~1.23 | 1.8.4+ | EndpointSlice 支持不完整 |
| 1.24 及以上 | 1.9.x+ | 配置语法差异,需改 Corefile |
| 1.18 及以下 | 1.7.x | 部分插件参数不兼容 |
2.2 运行时确认:docker 还是 containerd
离线导入镜像的方式完全取决于节点用的是哪种运行时。这一步搞错,后面docker load完了发现集群根本不认,白忙一场。先在每个节点上确认:
# 查看节点使用的容器运行时 kubectl get nodes -o wide # 输出里 CONTAINER-RUNTIME 列会显示 docker:// 或 containerd:// # 如果节点上能登录,也可以直接查 systemctl status docker 2>/dev/null | head -3 systemctl status containerd 2>/dev/null | head -3kubectl get nodes -o wide的CONTAINER-RUNTIME列是最直接的判断依据。显示docker://的走docker load,显示containerd://的走ctr导入。注意 containerd 导入时要指定 namespace,k8s 用的是k8s.io,不指定的话镜像导进去了但 kubelet 看不见,这是最常见的翻车点之一。
2.3 解包看内容:tar.gz 里通常有什么
拿到 coredns_v1.8.0.tar.gz 先别急着导,解压看一眼结构,确认里面是镜像 tar 还是附带部署清单:
# 解压到临时目录 mkdir -p /tmp/coredns-offline && tar -zxvf coredns_v1.8.0.tar.gz -C /tmp/coredns-offline # 查看解压后的文件 ls -lh /tmp/coredns-offline/常见做法是包里就一个coredns_v1.8.0.tar镜像文件,有的打包者会额外放coredns.yaml部署清单和Corefile示例。如果只有镜像 tar,部署清单得从集群现有配置或官方模板拿;如果带了 yaml,先别直接用,里面的镜像 tag 和副本数要按自己集群改。解压后确认文件大小,正常 CoreDNS 镜像 tar 在 40MB 上下,明显偏小说明包不完整,重新拿。
3. 导入镜像并部署:docker 与 containerd 两条路径
环境确认完就进入实操。这一章的核心是把镜像落到每个节点,然后让 Deployment 能引用到它。两条路径分开写,按自己集群的运行时对号入座,别混着来。
3.1 docker 运行时:load 之后确认 tag
docker 环境相对简单,docker load导入后镜像直接进本地镜像库,kubelet 拉取时命中本地缓存。但有个细节:导入后的镜像 tag 必须和 Deployment 里写的一致,否则还是会去远端拉。
# 导入镜像 docker load -i /tmp/coredns-offline/coredns_v1.8.0.tar # 确认导入结果,重点看 REPOSITORY 和 TAG docker images | grep corednsdocker load -i的-i指定输入文件。导入完成后docker images应该能看到类似coredns/coredns 1.8.0的记录。如果 tag 显示为<none>,说明打包时没打 tag,需要手动补:
# 给无 tag 的镜像补上正确标签 docker tag <IMAGE_ID> coredns/coredns:1.8.0补 tag 时IMAGE_ID用上一步docker images里查到的实际 ID。这一步做完,节点本地就有coredns/coredns:1.8.0了,Deployment 里image字段写这个值即可命中。
3.2 containerd 运行时:ctr 导入必须带 namespace
containerd 环境是坑最多的地方。ctr images import默认导入到defaultnamespace,而 k8s 的 kubelet 只认k8s.io,所以必须显式指定:
# 导入到 k8s.io 命名空间,这是关键 ctr -n k8s.io images import /tmp/coredns-offline/coredns_v1.8.0.tar # 确认镜像在 k8s.io 下可见 ctr -n k8s.io images ls | grep coredns-n k8s.io这个参数不能省,省了就是导了个寂寞。导入后ctr -n k8s.io images ls能看到docker.io/coredns/coredns:1.8.0这样的完整引用。注意 containerd 里镜像名带 registry 前缀,Deployment 的image字段写coredns/coredns:1.8.0时,kubelet 会按docker.io/coredns/coredns:1.8.0去匹配,一般能对上;如果对不上,把 Deployment 里的 image 改成完整路径。
提示:多节点集群要在每个可能调度 CoreDNS 的节点上都导一遍,只导 master 不导 worker,Pod 漂移过去照样拉不到。
3.3 部署清单:副本数、资源限制和 tolerations
镜像到位后处理 Deployment。如果包里带了 yaml,重点改三处;没有就基于现有配置导出改:
# 导出集群现有的 coredns deployment 作为基础 kubectl -n kube-system get deployment coredns -o yaml > coredns-deploy.yaml改的时候盯住这几个字段:
spec: replicas: 2 # 至少 2 副本,单副本挂了 DNS 全断 template: spec: tolerations: # 关键:允许调度到有污点的节点 - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: coredns image: coredns/coredns:1.8.0 # 与本地导入的 tag 严格一致 resources: limits: memory: 170Mi # 1.8.0 默认内存上限,大集群可上调 requests: cpu: 100m memory: 70Mireplicas设 2 是底线,单副本在节点维护时直接导致解析中断。tolerations那段是很多人忽略的:如果集群 master 有 NoSchedule 污点而 CoreDNS 没配容忍,副本可能全挤在少数 worker 上,节点一挂就全灭。resources里内存上限 170Mi 是 1.8.0 的默认值,集群规模大、域名多的环境建议提到 256Mi 以上,否则 OOM 重启会变成常态。
应用清单:
kubectl apply -f coredns-deploy.yaml kubectl -n kube-system rollout status deployment corednsrollout status会阻塞等待滚动更新完成,看到successfully rolled out才算部署动作结束。如果卡住不动,多半是镜像还是没匹配上,回到 3.1 或 3.2 确认 tag。
4. Corefile 配置与避坑:解析规则写错比装不上更麻烦
镜像和 Deployment 都就位后,真正决定 DNS 行为的是 Corefile。这一章讲配置原理和几个高频翻车点,配置写错的表现往往不是起不来,而是「起来了但解析不对」,排查起来更费劲。
4.1 Corefile 结构:每个 block 管一类域名
Corefile 的语法是「域名或区域 + 花括号里的插件链」,每个 block 独立处理匹配的查询。1.8.0 的默认配置大致是这样:
.:53 { errors # 错误日志输出到标准错误 health { # 健康检查端点,默认 :8080 lameduck 5s # 退出前继续服务 5 秒,平滑下线 } ready # 就绪探针端点 :8181 kubernetes cluster.local in-addr.arpa ip6.arpa { # 集群内域名解析 pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 # 指标暴露端口 forward . /etc/resolv.conf # 集群外域名转发到节点 DNS cache 30 # 缓存 30 秒 loop # 检测转发环路,防止死循环 reload # 自动重载 Corefile 变更 }kubernetes插件那段负责cluster.local后缀的服务发现,pods insecure允许解析 Pod 记录,ttl 30控制记录缓存时间。forward . /etc/resolv.conf把集群外查询转给节点上的 DNS,这个路径在部分发行版上不是/etc/resolv.conf,得按实际改。loop插件别删,它专门检测「自己转发给自己」的环路,删了遇到配置错误就是无限循环打满 CPU。
4.2 修改 Corefile 的两种方式
改 Corefile 有两条路:改 ConfigMap 或直接改挂载文件。生产环境走 ConfigMap 更规范:
# 编辑 coredns 的 ConfigMap kubectl -n kube-system edit configmap coredns改完保存,如果 Corefile 里有reload插件,大约 30 秒内自动生效,不用重启 Pod。没有reload的话需要滚动重启:
kubectl -n kube-system rollout restart deployment corednsrollout restart会逐个替换 Pod,配合lameduck的平滑退出,解析中断窗口能压到很小。改之前建议先kubectl -n kube-system get configmap coredns -o yaml > coredns-cm-backup.yaml备份一份,改坏了能立刻回滚,这是后悔药。
4.3 上游 DNS 与缓存参数怎么调
forward指向的上游和cache的时长是两个最常调的参数。上游默认读节点/etc/resolv.conf,如果节点 DNS 本身不稳,可以显式指定:
forward . 10.0.0.2 10.0.0.3 { max_concurrent 1000 # 并发查询上限,大集群上调 policy sequential # 按顺序尝试上游,失败再换下一个 }max_concurrent默认 1000,查询量大的集群可以提到 2000 以上,但别盲目拉高,上游扛不住反而更慢。policy有random、round_robin、sequential三种,多上游时sequential行为最可预期。cache 30的 30 秒是折中值,服务发现变更频繁的环境可以降到 10~15 秒,代价是上游查询量上升;变更少的环境提到 60 秒能明显减负。
5. 常见问题排查:装完解析不通先查这五处
这一章是我踩过的坑汇总,按「现象 → 原因 → 解决」写,遇到问题按顺序对号入座,基本能覆盖 1.8.0 离线部署的绝大多数故障。
5.1 Pod 一直 ImagePullBackOff
现象:kubectl -n kube-system get pods显示 CoreDNS 副本卡在 ImagePullBackOff,describe里报failed to pull image。
原因:镜像没导到 Pod 所在节点,或者 tag 不匹配。containerd 环境还可能是导错了 namespace。
解决:先kubectl -n kube-system describe pod <pod名>看事件里的镜像全名,再到对应节点上ctr -n k8s.io images ls | grep coredns或docker images | grep coredns核对。名字差一个字符都算不匹配,按事件里的全名重新 tag 或重新导入。
5.2 DNS 解析超时但 Pod 是 Running
现象:CoreDNS 副本 Running,但集群内nslookup kubernetes.default超时。
原因:Service 的 ClusterIP 和 Endpoints 对不上,或者 kube-proxy 规则没同步。也可能是 Corefile 里kubernetes插件的区域写错。
解决:先查 Service 和 Endpoints:
kubectl -n kube-system get svc kube-dns kubectl -n kube-system get endpoints kube-dnsEndpoints 为空说明标签选择器和 Pod 标签不匹配,检查 Deployment 的labels和 Service 的selector。Endpoints 正常但解析超时,进 Pod 里直接测:
kubectl -n kube-system exec -it <coredns-pod> -- /coredns -conf /etc/coredns/Corefile看启动日志里插件加载是否报错,区域配置错误会在这里显形。
5.3 日志刷 loop 检测告警
现象:CoreDNS 日志持续输出plugin/loop: Loop detected,CPU 占用升高。
原因:forward指向的上游 DNS 又把查询转回了 CoreDNS 自己,形成环路。常见于节点/etc/resolv.conf里配的就是集群 DNS 地址。
解决:把forward改成显式指定外部上游,别读/etc/resolv.conf:
forward . 223.5.5.5 119.29.29.29改完等reload生效或重启。loop插件本身别删,它是发现问题的哨兵,删了环路还在只是看不见。
5.4 大集群下解析间歇性失败
现象:集群规模上千 Pod 后,偶发解析失败,重试又能成功。
原因:1.8.0 的kubernetes插件在 EndpointSlice 支持上不完整,加上max_concurrent默认值偏低,高并发时查询被丢弃。
解决:先把forward的max_concurrent提到 2000,cache适当延长;如果仍不缓解,评估升级到 1.8.4 以上。这是版本能力边界,配置调优只能缓解不能根治。
5.5 改完 Corefile 不生效
现象:ConfigMap 改了,Pod 也重启了,但解析行为没变。
原因:ConfigMap 挂载到 Pod 里有延迟,或者改的不是实际挂载的那个 ConfigMap;也可能是reload插件没启用且没重启。
解决:确认挂载来源kubectl -n kube-system get deployment coredns -o yaml | grep -A3 configMap,核对名字。改完等 1 分钟以上再测,急着验证就rollout restart。改之前备份 ConfigMap 的习惯在这里能救命。
6. 装完怎么验证跑通:三层测试和我的固定收尾动作
部署完不能只看 Pod Running 就收工,DNS 这东西「看起来正常」和「真的正常」差很远。我固定跑三层验证,从集群内到集群外逐层确认,任何一层不过都不算装完。
第一层,集群内服务解析。起一个临时 Pod 直接测:
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- \ nslookup kubernetes.default.svc.cluster.local返回里能看到kubernetes.default.svc.cluster.local对应的 ClusterIP 就算过。用busybox:1.28是因为新版本 busybox 的 nslookup 行为有变化,1.28 的输出最直观。
第二层,集群外域名解析。同一个临时 Pod 里测外部域名:
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- \ nslookup www.example.com能返回外部 IP 说明forward链路通。这一层失败基本就是 5.3 的环路问题或上游不可达。
第三层,看指标确认没有隐性异常。CoreDNS 自带 Prometheus 指标,端口 9153:
kubectl -n kube-system port-forward svc/kube-dns 9153:9153 & curl -s localhost:9153/metrics | grep -E 'coredns_dns_(requests_total|responses_total)'重点看responses_total里rcode="SERVFAIL"的比例,正常应该接近零。SERVFAIL 偏高说明上游或插件有问题,即使解析偶尔能通也别放过。
三层都过之后,我还会做一件事:把导入用的镜像 tar 和改过的 yaml、Corefile 一起归档到内部制品库,标注集群版本和导入方式。从那以后我每次离线部署 CoreDNS,都强制走一遍「解包核对 → 按运行时导入 → 三层验证 → 归档」这套动作,中间任何一步跳过,后面都可能用几小时的排查来还。希望帮到你。
本文还有配套的精品资源,点击获取