ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

CoreDNS v1.8.0 离线部署实战:从 tar.gz 到 K8s 集群 DNS 配置与避坑指南

CoreDNS v1.8.0 离线部署实战:从 tar.gz 到 K8s 集群 DNS 配置与避坑指南 简介coredns_v1.8.0.tar.gz 是面向 Kubernetes 集群运维与部署人员的 CoreDNS 镜像离线包适用于 k8s v1.21.2 环境。当集群无法直接访问镜像仓库或需要固定版本时可通过该包快速导入 CoreDNS v1.8.0 镜像解决 DNS 服务组件缺失、版本不匹配等问题适合具备一定容器与集群操作基础的中高级使用者。压缩包共 8 个文件以 4 个 json 清单与配置、2 个 tar 层文件及 2 个 version 版本标识为主整体约 40.62MB结构符合容器镜像分层规范便于校验与导入。目前已有 404 人学习下载。借助该资源读者可获得与 k8s v1.21.2 匹配的 CoreDNS 镜像完整内容用于离线部署、版本回滚或集群 DNS 故障排查减少因网络受限导致的部署阻碍。1. coredns_v1.8.0.tar.gz 到手之后一个离线部署场景的真实起点内网环境里搞 Kubernetes最头疼的往往不是编排本身而是那些看起来不起眼的依赖组件。coredns_v1.8.0.tar.gz 这个包就是我在一个完全断网的机房项目里被卡住的地方——集群起来了Pod 全是 Running但服务之间域名解析不了kube-dns 的 Service 后面一个 Endpoint 都没有。CoreDNS 作为 K8s 默认的集群 DNS负责把 Service 名、Pod 名翻译成 ClusterIP它不工作整个微服务调用链就是瘫的。这个 tar.gz 包通常包含源码、编译产物或者容器镜像的离线归档具体内容取决于打包方式但核心目标只有一个让你在没有外网的环境里把 CoreDNS 跑起来。适合谁看做私有云交付的、管离线集群的、以及想搞清楚 CoreDNS 到底怎么配置才不翻车的一线运维和平台工程师。接下来我会按「包怎么用 → 配置怎么写 → 坑怎么避」的顺序把 v1.8.0 这个版本的实际操作路径拆开讲。2. 拆开 coredns_v1.8.0.tar.gz从归档内容到运行形态的选型判断2.1 先看清包里有什么再决定怎么跑拿到一个 tar.gz第一反应不该是直接解压到生产目录而是先看结构。CoreDNS 的发布包一般有两种形态一种是源码包里面是 Go 文件、go.mod、Makefile另一种是二进制发布包里面直接有 coredns 可执行文件加一堆插件配置示例。v1.8.0 这个版本号对应的是 CoreDNS 的正式 release官方在 GitHub 上会提供 coredns_1.8.0_linux_amd64.tgz 这类命名但你这个包名是 coredns_v1.8.0.tar.gz多了个 v大概率是内部二次打包的产物。所以第一步是验货。# 不解压先看归档里有什么 tar -tzf coredns_v1.8.0.tar.gz | head -50 # 看文件数量和顶层目录结构 tar -tzf coredns_v1.8.0.tar.gz | awk -F/ {print $1} | sort -u逻辑说明tar -tzf只列出内容不落盘避免解压出一堆垃圾。awk那行是提取顶层目录名判断是单目录包裹还是散装文件。参数上-t是 list-z走 gzip-f指定文件顺序不能乱。如果看到顶层是coredns/或者coredns-1.8.0/说明是规范打包如果直接是core/、plugin/、go.mod那就是源码树你得自己编译。常见做法是如果包里已经有coredns二进制直接抽出来用如果没有就得在能联网的机器上交叉编译好再塞进去。v1.8.0 要求 Go 1.16 以上编译命令是go build -o coredns但离线环境往往连 Go 都没有所以更稳妥的是找一台同架构的联网机CGO_ENABLED0 GOOSlinux GOARCHamd64 go build出静态二进制再拷进内网。2.2 运行形态选型二进制裸跑还是容器化CoreDNS 在 K8s 里默认是以 Deployment 形式跑的镜像一般是coredns/coredns:1.8.0。但离线环境拉不到镜像你有两个选择一是把二进制挂进一个基础镜像里自己 build二是直接用 systemd 管二进制让 K8s 的 kubelet 通过静态 Pod 或者外部服务的方式接进去。我一般会优先走容器化因为 K8s 的 Service 发现机制依赖 Pod 网络裸二进制跑在宿主机上ClusterIP 的解析会绕一圈。如果走容器化Dockerfile 大概长这样FROM alpine:3.13 COPY coredns /coredns EXPOSE 53 53/udp ENTRYPOINT [/coredns]逻辑说明alpine 做基础镜像体积小COPY把从 tar.gz 里解出来的二进制放进去EXPOSE声明 DNS 的 TCP/UDP 端口。参数上注意53/udp必须显式写否则 K8s Service 只映射 TCPDNS 查询默认走 UDP 会失败。构建命令docker build -t coredns:1.8.0 .然后在离线节点上docker save成 tar 再docker load。如果走二进制裸跑systemd unit 文件关键部分[Service] ExecStart/opt/coredns/coredns -conf /etc/coredns/Corefile Restarton-failure LimitNOFILE1048576-conf指定配置文件路径LimitNOFILE要拉高CoreDNS 在高并发查询下文件描述符消耗很快默认 1024 会直接崩。这个参数是我踩过坑之后每次必加的。2.3 和 K8s 对接的两种模式ClusterIP 服务发现怎么配CoreDNS 要解析 K8s 的 Service 域名必须能访问 API Server。配置里核心是kubernetes插件.:53 { kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } forward . /etc/resolv.conf cache 30 loop reload loadbalance }逻辑说明kubernetes插件告诉 CoreDNS 去监听 Service 和 Pod 的变化cluster.local是 K8s 默认域名后缀。pods insecure表示允许解析 Pod IP 的反向记录不需要 TLS 验证。ttl 30控制缓存时间设太短查询压力大设太长服务变更后解析更新慢。forward . /etc/resolv.conf是把非集群域名转发给上游 DNS离线环境里如果/etc/resolv.conf指向的 DNS 不可达外部域名解析会超时这时候要么删掉 forward要么指向一个内网可用的 DNS。参数上fallthrough很关键当 kubernetes 插件查不到记录时是否把请求交给下一个插件。不写的话查不到就直接返回 NXDOMAIN不会走 forward。loop插件是防环的如果 CoreDNS 的上游指向自己它会检测到并报错退出。reload让配置变更后自动重载省得每次改 Corefile 都重启进程。3. 把 CoreDNS 塞进 K8sConfigMap、Deployment 和 Service 的联动配置3.1 Corefile 写进 ConfigMap 的正确姿势K8s 里 CoreDNS 的配置是放在 ConfigMap 里的名字通常是coredns命名空间kube-system。离线环境你没法kubectl apply在线 YAML得手写或者从包里找示例。关键字段apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system data: Corefile: | .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance }逻辑说明errors插件把错误日志打到标准输出排错必开。health提供健康检查端点lameduck 5s是优雅退出等待时间避免滚动更新时丢查询。ready插件给 readiness probe 用返回 200 表示插件都加载完了。prometheus :9153暴露监控指标离线环境如果没 Prometheus 可以不加但加了不碍事。loadbalance对 A 记录做轮询多副本时有用。写进 ConfigMap 后Deployment 里要挂载volumeMounts: - name: config-volume mountPath: /etc/coredns readOnly: true volumes: - name: config-volume configMap: name: coredns items: - key: Corefile path: Corefile参数上items那段是精确控制挂载哪个 key 到哪个文件名不写的话 ConfigMap 里所有 key 都会变成文件。readOnly必须 trueCoreDNS 不需要写配置目录。3.2 Deployment 副本数、资源限制和探针参数CoreDNS 的 Deployment 副本数默认是 2但离线小集群跑 1 个也够。资源限制这块requests 给 100m CPU / 70Mi 内存limits 给 200m / 170Mi 是官方推荐值但实际生产里查询量大的话 CPU 要往上加。我一般会设resources: limits: cpu: 500m memory: 256Mi requests: cpu: 100m memory: 128Mi探针配置livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /ready port: 8181逻辑说明initialDelaySeconds: 60是给 CoreDNS 加载插件留时间设太短会反复重启。failureThreshold: 5配合timeoutSeconds: 5意味着连续 25 秒不健康才杀 Pod避免网络抖动误杀。readiness 走/ready端口 8181这个端口是ready插件监听的只有所有插件都就绪才返回 200。3.3 Service 的 ClusterIP 和 kubelet 的 resolv.conf 指向CoreDNS 的 Service 名字必须是kube-dns这是 K8s 硬编码的kubelet 启动 Pod 时会把/etc/resolv.conf的 nameserver 指向这个 Service 的 ClusterIP。Service YAMLapiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: true kubernetes.io/name: CoreDNS spec: selector: k8s-app: kube-dns clusterIP: 10.96.0.10 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP - name: metrics port: 9153 protocol: TCP参数上clusterIP: 10.96.0.10是 K8s 默认的 DNS Service IP如果你的集群 Service CIDR 不是 10.96.0.0/12这个 IP 要改。selector必须匹配 Deployment 的 Pod 标签否则 Endpoint 为空解析直接失败。两个 53 端口一个 UDP 一个 TCP 都要开大响应包会走 TCP 重试。验证方法起一个 busybox Podnslookup kubernetes.default看能不能返回 ClusterIP。如果超时先kubectl get endpoints kube-dns -n kube-system看有没有后端 IP没有就是 selector 或 readiness 的问题。4. 避坑与排查CoreDNS v1.8.0 离线部署的五个血泪教训4.1 现象Pod 内 nslookup 超时但 CoreDNS 日志无报错原因kubelet 的/etc/resolv.conf里 nameserver 指向的 ClusterIP 和实际 Service IP 不一致。离线环境如果 kubelet 配置里clusterDNS写错了或者 Service CIDR 改过但没同步就会这样。CoreDNS 本身在跑但请求根本没到它那里。解决登录节点cat /var/lib/kubelet/config.yaml | grep clusterDNS对比kubectl get svc kube-dns -n kube-system的 ClusterIP。不一致就改 kubelet 配置重启 kubelet或者改 Service 的 clusterIP 字段需要删了重建。4.2 现象CoreDNS Pod 反复 CrashLoopBackOff日志显示plugin/loop: Loop detected原因Corefile 里forward . /etc/resolv.conf指向的上游 DNS 就是 CoreDNS 自己。离线环境里/etc/resolv.conf可能被配成了 127.0.0.1 或者节点上另一个 CoreDNS 实例的地址形成解析环。解决把 forward 指向一个确定的外部 DNS或者如果不需要外部解析直接删掉 forward 行只保留 kubernetes 插件。loop插件检测到环会主动退出这是保护机制不是 bug。4.3 现象Service 域名能解析但 Pod 域名解析返回 NXDOMAIN原因Corefile 里pods insecure没写或者写成了pods disabled。v1.8.0 里 pods 选项默认是 disabled必须显式开 insecure 才能解析 Pod IP 的反向记录和 Pod 名。解决确认 kubernetes 插件块里有pods insecure。改完 ConfigMap 后等reload插件自动加载或者kubectl rollout restart deployment coredns -n kube-system。4.4 现象大并发下 DNS 查询间歇性失败CoreDNS 日志出现read udp: i/o timeout原因节点上 conntrack 表满了UDP 53 的会话跟踪把表撑爆。这是 K8s 环境里 DNS 最经典的玄学问题跟 CoreDNS 本身没关系。解决调大nf_conntrack_max并且给 DNS 流量加 NOTRACK 规则。命令sysctl -w net.netfilter.nf_conntrack_max1048576 iptables -t raw -A PREROUTING -p udp --dport 53 -j NOTRACK iptables -t raw -A OUTPUT -p udp --sport 53 -j NOTRACK参数上nf_conntrack_max根据节点内存调一般 1M 起步。NOTRACK 规则让 DNS 的 UDP 包不走连接跟踪直接绕过 conntrack 表。4.5 现象CoreDNS 内存持续增长最终 OOMKilled原因cache插件的缓存没有上限查询量大的集群里缓存条目会无限膨胀。v1.8.0 的 cache 插件支持success和denial的条数限制但默认不限制。解决在 Corefile 的 cache 行加参数cache 30 { success 9984 denial 9984 prefetch 10 60s 10% }success和denial分别控制正向和否定缓存的条数上限prefetch是预取对热点域名提前刷新缓存。内存 limits 也要相应调大256Mi 是底线。5. 进阶技巧用 dnstap 和 metrics 把 CoreDNS 的黑匣子打开CoreDNS 跑起来只是第一步真正难的是出问题时你怎么知道它在想什么。v1.8.0 支持dnstap插件能把每一个 DNS 查询和响应以 protobuf 格式吐出来配合dnstap的接收端比如dnstap-receiver或者自己写个 Go 程序就能做全量查询审计。配置很简单在 Corefile 里加dnstap /tmp/dnstap.sock fullfull表示记录查询和响应两个方向。socket 文件路径自己定然后起一个接收进程读这个 socket。这个方案对排查「某个域名为什么解析慢」特别有用你能看到 CoreDNS 到底花了多少时间在哪个插件上。另一个更轻量的方式是prometheus插件暴露的指标。coredns_dns_request_duration_seconds是查询延迟直方图coredns_dns_responses_total按 rcode 分类统计响应码。离线环境没 Prometheus 的话直接curl http://coredns-pod-ip:9153/metrics也能看。我一般会关注两个指标coredns_dns_responses_total{rcodeSERVFAIL}突然升高说明上游 forward 出问题了coredns_cache_hits_total和coredns_cache_misses_total的比值低于 0.8 就说明缓存 TTL 设太短或者查询模式太分散。还有一个容易被忽略的点CoreDNS 的health插件默认监听:8080ready插件监听:8181这两个端口如果和宿主机上其他服务冲突Pod 会起不来但日志不一定明显。离线环境里节点上跑的东西杂部署前先ss -tlnp | grep -E 8080|8181|9153确认端口没被占。最后说个我自己的习惯每次改完 Corefile不要直接kubectl apply到生产先在测试命名空间起一个单副本的 CoreDNS用dig pod-ip 测试域名验证通过再推。CoreDNS 的配置错误往往不会让进程崩而是静默返回错误结果这种坑最难查。离线环境没有后悔药改之前kubectl get configmap coredns -n kube-system -o yaml coredns-backup.yaml备份一份花不了几秒钟但能救命。希望帮到你。本文还有配套的精品资源点击获取
返回列表