kubernetes中的DNS
CoreDns
官网地址:https://coredns.io/
Kubernetes DNS 服务: https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/dns-custom-nameservers/
kubectl get pods -l k8s-app=kube-dns -n kube-system
## 查看多个Pod中的日志信息
for p in $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name); do kubectl logs --namespace=kube-system $p; done
kubectl -n kube-system get ConfigMap coredns -o yaml
配置示例
.:53 {
errors
health {
lameduck 5s
}
ready
## 自定义 hosts 解析特定域名
hosts {
192.168.10.151 www.test.com
fallthrough
}
## 内部域名替换外部域名
rewrite stop {
name regex (.*)\.mgmt\.pix\.yun\.com {1}.default.svc.cluster.local
answer name (.*)\.default\.svc\.cluster\.local {1}.mgmt.pix.yun.com
}
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
}
- CoreDNS配置详解
DNS 调试
## ContOS
yum -y install bind-utils
nslookup www.example.com 192.168.10.8
dig +short www.baidu.com .
## POD测试DNS
kubectl run -it --rm --tty debug --image=busybox -- sh
nslookup www.baidu.com
exit
Ingress
的域名访问
打通目的
对于 HTTP 类型的服务,我们可以通过 Ingress 资源以“虚拟主机”的形式将服务暴露出来,但是在内网环境下,这些域名通常都无法直接访问。
如何在各个节点以及客户端同步域名解析配置?
如何进行域名解析?
如何在集群内也能进行域名解析?
如何在 Ingress 资源变动时自动更新域名解析配置?
前两个问题其实是想引出自建 DNS 服务的话题,通过自建 DNS 服务,可以很方便的实现内网环境中各节点以及客户端的域名解析,第三个问题是指将集群的 CoreDNS 做一个兜底 forward 到自建 DNS 服务,第四个问题是指通过 ExternalDNS 将 Ingress 资源的配置自动同步到自建 DNS 中。
实践方案
单纯自建 DNS 的话其实可以使用的软件有很多,但是出于对轻量级和配置 ExternalDNS 的考虑就直接使用 CoreDNS 作为 DNS 服务器软件。另外 CoreDNS 本身已经能够实现域名解析了,但也仅仅是只能进行静态域名解析,因此需要给它搭配一个 ETCD 数据库,后续 ExternalDNS 在读取到 Ingress 配置后也会将其写入到 ETCD 中。
此时自建 DNS 已经能够解析 Ingress 资源中配置的域名了,但是为了让集群内也能通过自建 DNS 进行域名解析,还需配置集群内的 CoreDNS 进行兜底 forward 到自建 DNS。
最终的各个组件之间的关系如下图所示:

自建 ETCD
ETCD
并没有采用官方推荐的etcd-operator
方式进行安装,而是直接使用了Bitnami Chart
,因为Bitnami Chart
的镜像基本都在DockerHub
易于访问。
安装ETCD
cat > values.etcd.yaml << EOF
auth:
rbac:
create: false
EOF
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
## helm pull bitnami/etcd --version 8.3.7
helm upgrade etcd bitnami/etcd --install --namespace devops-dns --create-namespace --values values.etcd.yaml --version 8.3.7
## etcdctl 命令行测试工具
kubectl run etcd-client --restart="Never" --image docker.io/bitnami/etcd:3.5.4-debian-11-r22 --env ETCDCTL_ENDPOINTS="etcd.etcd.svc.cluster.local:2379" --namespace devops-dns --command -- sleep infinity
kubectl exec --namespace devops-dns -it etcd-client -- bash
安装自建 CoreDNS
主要修改了服务暴露方式以及直接改写的 CoreDNS Chart
默认的 Corefile
插件配置:
安装CoreDNS
cat > values.CoreDNS.yaml << EOF
isClusterService: false
servers:
- zones:
- zone: .
port: 53
plugins:
- name: errors
- name: health
configBlock: |-
lameduck 5s
- name: ready
- name: hosts
configBlock: |-
fallthrough
- name: etcd
configBlock: |-
endpoint http://etcd.devops-dns.svc.cluster.local:2379
fallthrough
- name: forward
parameters: . 114.114.114.114
- name: cache
parameters: 30
- name: loop
- name: reload
- name: loadbalance
EOF
helm repo add coredns https://coredns.github.io/helm
helm repo update
## kubectl delete clusterrole coredns-coredns
## kubectl delete clusterrolebinding coredns-coredns
## helm pull coredns/coredns --version 1.19.4
helm upgrade coredns coredns/coredns --install --namespace devops-dns --create-namespace --values values.CoreDNS.yaml --version 1.19.4
其中 endpoint 是指 ETCD 数据库的地址,由于安装 ETCD 时已经通过 NodePort 方式暴露了端口因而可以直接采用宿主机地址 + 端口的方式访问。可以在 hosts 插件块中硬编码一些域名解析,也可以让其直接引用宿主机的 hosts 文件,还可以借助 template 插件 配置泛解析。最后兜底转发到 114 DNS 服务器。
###### 测试CoreDNS是否可用 ######
## kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
kubectl run -i --rm --tty debug --image=busybox -- sh
## 测试公网域名能否解析
nslookup www.baidu.com
## 退出容器自动删除容器
exit
安装ExternalDNS
ExternalDNS
目的是,将Kubernetes的Service/Ingress暴露的服务(的DNS记录)同步给外部的其他的Provider。
- bitnami chart: https://artifacthub.io/packages/helm/bitnami/external-dns
- https://github.com/kubernetes-sigs/external-dns
- https://github.com/JasonvanBrackel/kubernetes-external-dns-in-rancher
ExternalDNS 也是为了图镜像易于访问直接使用 Bitnami Chart
ExternalDNS
cat > values.ExternalDNS.yaml << EOF
txtOwnerId: k8s-240
provider: coredns
coredns:
etcdEndpoints: "http://etcd.devops-dns.svc.cluster.local:2379"
EOF
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
## helm pull bitnami/external-dns --version 6.7.4
helm upgrade external-dns bitnami/external-dns --install --namespace devops-dns --create-namespace --values values.ExternalDNS.yaml --version 6.7.4
日志:当 Ingress 资源变动时可以从
ExternalDNS
的日志中看到新的 DNS 记录被写入到 ETCD 中。
修改集群的DNS
将集群内的 CoreDNS 兜底转发到自建 DNS
## 查看自建的coredns在集群内的ip地址
kubectl -n etcd get svc | grep coredns
kubectl -n kube-system edit ConfigMap coredns
## 指定域名的转发规则
devops.kk:53 {
errors
forward . 10.233.46.37
loop
reload
}
devops.tr:53 {
errors
forward . 10.233.46.37
loop
reload
}
将集群内的 CoreDNS 兜底转发到自建 DNS
## kubectl -n kube-system get ConfigMap nodelocaldns -o yaml
devops.kk:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.46.37
}
devops.tr:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.46.37
}
测试
cat > nginx.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
external-dns.alpha.kubernetes.io/hostname: "nginx.devops.kk"
spec:
rules:
- host: nginx.devops.kk
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
EOF
kubectl apply -f nginx.yaml
kubectl get all
kubectl get ingress
kubectl -n etcd get svc
kubectl -n kube-system get svc
## 下面两个地址都可以解析域名 nginx.devops.kk 即成功
nslookup nginx.devops.kk 10.233.46.37
nslookup nginx.devops.kk 10.233.0.3
## 删除测试资源
kubectl delete -f nginx.yaml