跳至主要內容

kubernetes中的DNS

知识库容器技术kubernetes建设Kuberneteskubesphere大约 5 分钟

CoreDns

官网地址:https://coredns.io/open in new window

Kubernetes DNS 服务: https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/dns-custom-nameservers/open in new window

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。

最终的各个组件之间的关系如下图所示:

dns方案
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。

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