• Kubernetes:(九)coredns(浪不动了)


    目录

    一:什么是coredns?

    二:coreDNS局限性

    三:coredns的用途

    四:coredns的部署

    4.1获取coredns的docker镜像

    4.2创建coredns的资源配置清单

    4.2.1rbac集群权限清单

    4.2.2configmap配置清单

    4.2.3depoly控制器清单

    4.2.4service资源清单

    4.3创建资源并验证

    4.3.1验证服务能够访问

    4.3.2创建资源

    4.3.3查看创建情况

    4.3.4使用dig测试解析

    4.3.5创建一个service资源来验证

    五:coredns配置

    5.1K8sDNS策略

    5.2resolv.conf

    5.3coreDNSCorefile文件 

    六:node local dns 

    6.1DNS间歇性5秒延迟

    6.2NodeLocal DNSCache

    一:什么是coredns?

    CoreDNS是DNS服务器软件,通常用于在容器化环境(尤其是Kubernetes管理的环境)中支持服务发现功能。

    与BIND的配置文件的语法相比,CoreDNS的Corefile(称为)非常简单。基本的基于CoreDNS的DNS服务器的Corefile通常只有几行,而且相对而言,易于阅读。

    CoreDNS使用插件来提供DNS功能。因此,有一个用于缓存的插件和一个用于转发的插件,一个用于配置从文件读取区域数据的主DNS服务器的插件,以及一个插件用于配置辅助DNS服务器。不仅可以直接配置每个插件(请参阅上一段落),而且,如果不需要插件,则无需配置它,也不会执行其代码。这使CoreDNS更快,更安全。

    coredns和其他的诸如bind、knot、powerdns、unbound等DNS服务不同的是:coredns非常的灵活,并且几乎把所有的核心功能实现都外包给了插件。比如说如果你想要在coredns中加入Prometheus的监控支持,那么只需要安装对应的prometheus插件并且启用即可,因此官方也说coredns是由插件驱动的。

    CoreDNS不仅是灵活,安全的DNS服务器,而且还直接与包括Kubernetes在内的许多容器编排系统集成。这意味着容器化应用程序的管理员可以轻松地设置DNS服务器来调解和促进容器之间的通信。


    二:coreDNS局限性

    CoreDNS目前确实存在一些重大限制,并且它并不适用于所有可能的DNS服务器。其中最主要的是CoreDNS(至少在撰写本文时为最新版本)不支持完全递归。换句话说,CoreDNS无法处理查询,方法是从DNS名称空间的根目录开始,查询根DNS服务器并遵循引用,直到从权威DNS服务器之一获得答案为止。相反,它依赖于其他DNS服务器(通常称为转发器)。


    三:coredns的用途

    coreDNS 是一个灵活可扩展的 DNS 服务器,通常用于在容器化环境(尤其是kubernetes管理的环境)中支持服务发现功能,可以作为 Kubernetes 集群 DNS,在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样,coreDNS 项目由 CNCF 托管。

    coredns在K8S中的用途,主要是用作服务发现,也就是服务(应用)之间相互定位的过程。

    在k8s中,用service资源代理pod,通过暴露service资源的固定地址(集群IP),来解决以上POD资源变化产生的IP变动问题,但是针对service还存在以下问题:

    • service IP地址难以记忆
    • service资源可能也会被销毁和创建
    • pod ip本身也有需要暴漏的需求

    为了解决以上问题,引入了coredns,在K8S,其主要用于服务发现,也就是服务(应用)之间相互定位的过程。


    四:coredns的部署

    我们使用声明式向k8s中交付容器的方式,来部署服务

    4.1获取coredns的docker镜像

    以下操作可以在任意节点上完成,推荐在master上做,因为接下来制作coredns的k8s配置清单也是在运维主机master上创建后,再到node节点上应用

    1. docker pull docker.io/coredns/coredns:1.6.1
    2. docker tag coredns:1.6.1 harbor.od.com/public/coredns:v1.6.1
    3. docker push harbor.od.com/public/coredns:v1.6.1
    1. 配置nginx虚拟主机
    2. vim /etc/nginx/conf.d/k8s-yaml.od.com.conf
    3. server {
    4. listen 80;
    5. server_name k8s-yaml.od.com;
    6. location / {
    7. autoindex on;
    8. default_type text/plain;
    9. root /data/k8s-yaml;
    10. }
    11. }
    12. mkdir /data/k8s-yaml;
    13. nginx -qt && nginx -s reload

    配置dns解析node节点

    1. vim /var/named/od.com.zone
    2. $ORIGIN od.com.
    3. $TTL 600 ; 10 minutes
    4. @ IN SOA dns.od.com. dnsadmin.od.com. (
    5. 2020070603 ; serial
    6. 10800 ; refresh (3 hours)
    7. 900 ; retry (15 minutes)
    8. 604800 ; expire (1 week)
    9. 86400 ; minimum (1 day)
    10. )
    11. NS dns.od.com.
    12. $TTL 60 ; 1 minute
    13. dns A 10.4.7.11
    14. harbor A 10.4.7.200
    15. k8s-yaml A 10.4.7.200
    16. systemctl restart named

    4.2创建coredns的资源配置清单

    以下资源配置清单,都是参考官网改出来的

    mkdir -p /data/k8s-yaml/coredns

    4.2.1rbac集群权限清单

    清单文件存放到 master主机data/k8s-yaml/coredns/coredns_1.6.1/

    1. cat >/data/k8s-yaml/coredns/rbac.yaml <
    2. apiVersion: v1
    3. kind: ServiceAccount
    4. metadata:
    5. name: coredns
    6. namespace: kube-system
    7. labels:
    8. kubernetes.io/cluster-service: "true"
    9. addonmanager.kubernetes.io/mode: Reconcile
    10. ---
    11. apiVersion: rbac.authorization.k8s.io/v1
    12. kind: ClusterRole
    13. metadata:
    14. labels:
    15. kubernetes.io/bootstrapping: rbac-defaults
    16. addonmanager.kubernetes.io/mode: Reconcile
    17. name: system:coredns
    18. rules:
    19. - apiGroups:
    20. - ""
    21. resources:
    22. - endpoints
    23. - services
    24. - pods
    25. - namespaces
    26. verbs:
    27. - list
    28. - watch
    29. ---
    30. apiVersion: rbac.authorization.k8s.io/v1
    31. kind: ClusterRoleBinding
    32. metadata:
    33. annotations:
    34. rbac.authorization.kubernetes.io/autoupdate: "true"
    35. labels:
    36. kubernetes.io/bootstrapping: rbac-defaults
    37. addonmanager.kubernetes.io/mode: EnsureExists
    38. name: system:coredns
    39. roleRef:
    40. apiGroup: rbac.authorization.k8s.io
    41. kind: ClusterRole
    42. name: system:coredns
    43. subjects:
    44. - kind: ServiceAccount
    45. name: coredns
    46. namespace: kube-system
    47. EOF

    4.2.2configmap配置清单

    1. cat >/data/k8s-yaml/coredns/cm.yaml <<EOF
    2. apiVersion: v1
    3. kind: ConfigMap
    4. metadata:
    5. name: coredns
    6. namespace: kube-system
    7. data:
    8. Corefile: |
    9. .:53 {
    10. errors
    11. log
    12. health
    13. ready
    14. kubernetes cluster.local 192.168.0.0/16 #service资源cluster地址
    15. forward . 10.4.7.11 #上级DNS地址
    16. cache 30
    17. loop
    18. reload
    19. loadbalance
    20. }
    21. EOF

    4.2.3depoly控制器清单

    1. cat >/data/k8s-yaml/coredns/dp.yaml <
    2. apiVersion: apps/v1
    3. kind: Deployment
    4. metadata:
    5. name: coredns
    6. namespace: kube-system
    7. labels:
    8. k8s-app: coredns
    9. kubernetes.io/name: "CoreDNS"
    10. spec:
    11. replicas: 1
    12. selector:
    13. matchLabels:
    14. k8s-app: coredns
    15. template:
    16. metadata:
    17. labels:
    18. k8s-app: coredns
    19. spec:
    20. priorityClassName: system-cluster-critical
    21. serviceAccountName: coredns
    22. containers:
    23. - name: coredns
    24. image: harbor.od.com/public/coredns:v1.6.1
    25. args:
    26. - -conf
    27. - /etc/coredns/Corefile
    28. volumeMounts:
    29. - name: config-volume
    30. mountPath: /etc/coredns
    31. ports:
    32. - containerPort: 53
    33. name: dns
    34. protocol: UDP
    35. - containerPort: 53
    36. name: dns-tcp
    37. protocol: TCP
    38. - containerPort: 9153
    39. name: metrics
    40. protocol: TCP
    41. livenessProbe:
    42. httpGet:
    43. path: /health
    44. port: 8080
    45. scheme: HTTP
    46. initialDelaySeconds: 60
    47. timeoutSeconds: 5
    48. successThreshold: 1
    49. failureThreshold: 5
    50. dnsPolicy: Default
    51. volumes:
    52. - name: config-volume
    53. configMap:
    54. name: coredns
    55. items:
    56. - key: Corefile
    57. path: Corefile
    58. EOF

    4.2.4service资源清单

    1. cat >/data/k8s-yaml/coredns/svc.yaml <
    2. apiVersion: v1
    3. kind: Service
    4. metadata:
    5. name: coredns
    6. namespace: kube-system
    7. labels:
    8. k8s-app: coredns
    9. kubernetes.io/cluster-service: "true"
    10. kubernetes.io/name: "CoreDNS"
    11. spec:
    12. selector:
    13. k8s-app: coredns
    14. clusterIP: 192.168.0.2
    15. ports:
    16. - name: dns
    17. port: 53
    18. protocol: UDP
    19. - name: dns-tcp
    20. port: 53
    21. - name: metrics
    22. port: 9153
    23. protocol: TCP
    24. EOF

    4.3创建资源并验证

    在任意NODE节点执行配置都可以

    4.3.1验证服务能够访问

    dig -t A harbor.od.com  +short

    4.3.2创建资源

    1. kubectl create -f http://k8s-yaml.od.com/coredns/rbac.yaml
    2. kubectl create -f http://k8s-yaml.od.com/coredns/cm.yaml
    3. kubectl create -f http://k8s-yaml.od.com/coredns/dp.yaml
    4. kubectl create -f http://k8s-yaml.od.com/coredns/svc.yaml

    4.3.3查看创建情况

    1. kubectl get all -n kube-system
    2. kubectl get svc -o wide -n kube-system
    3. dig -t A www.baidu.com @192.168.0.2 +short

    4.3.4使用dig测试解析

    1. dig -t A www.baidu.com @192.168.137.20 +short
    2. dig -t A harbor.od.com @192.168.137.20 +short

    4.3.5创建一个service资源来验证

    先查看kube-public名称空间有没有pod

    kubectl get pod  -n kube-public

    如果没有则先创建pod

    1. kubectl create deployment nginx-dp --image=harbor.zq.com/public/nginx:v1.17.9 -n kube-public
    2. ~]# kubectl get deployments -n kube-public
    3. NAME READY UP-TO-DATE AVAILABLE AGE
    4. nginx-dp 1/1 1 1 35s
    5. ~]# kubectl get pod -n kube-public
    6. NAME READY STATUS RESTARTS AGE
    7. nginx-dp-568f8dc55-rxvx2 1/1 Running 0 56s

    给pod创建一个service

    1. kubectl expose deployment nginx-dp --port=80 -n kube-public
    2. ~]# kubectl -n kube-public get service
    3. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    4. nginx-dp ClusterIP 192.168.63.255 <none> 80/TCP 11s

    验证是否可以解析

    1. ~]# dig -t A nginx-dp @192.168.137.20 +short
    2. # 发现无返回数据,难道解析不了
    3. # 其实是需要完整域名:服务名.名称空间.svc.cluster.local.
    4. ~]# dig -t A nginx-dp.kube-public.svc.cluster.local. @192.168.137.20 +short

    可以看到我们没有手动添加任何解析记录,我们nginx-dp的service资源的IP,已经被解析了:

    进入到pod内部再次验证

    1. ~]# kubectl -n kube-public exec -it nginx-dp-568f8dc55-rxvx2 /bin/bash
    2. -qjwmz:/# apt update && apt install curl
    3. -qjwmz:/# ping nginx-dp

    为什么在容器中不用加全域名?

    1. -qjwmz:/# cat /etc/resolv.conf
    2. nameserver 192.168.137.20
    3. search kube-public.svc.cluster.local svc.cluster.local cluster.local host.com
    4. options ndots:5

    当我进入到pod内部以后,会发现我们的dns地址是我们的coredns地址,以及搜索域中已经添加了搜索域:kube-public.svc.cluster.local


    五:coredns配置

    5.1K8sDNS策略

    Kubernetes 中 Pod 的 DNS 策略有四种类型:

    1. Default(默认预设):Pod 继承所在主机上的 DNS 配置;
    2. ClusterFirst(集群优先):K8s 的默认设置;先在 K8s 集群配置的 coreDNS 中查询,查不到的再去继承自主机的上游 nameserver 中查询;
    3. ClusterFirstWithHostNet(宿主机与k8s共存):对于网络配置为 hostNetwork 的 Pod 而言,其 DNS 配置规则与 ClusterFirst 一致;
    4. None(无策略):忽略 K8s 环境的 DNS 配置,只认 Pod 的 dnsConfig 设置。

    5.2resolv.conf

    在部署 pod 的时候,如果用的是 K8s 集群的 DNS,那么 kubelet 在起 pause 容器的时候,会将其 DNS 解析配置初始化成集群内的配置。

    如创建了一个叫 my-nginx 的 deployment,其 pod 中的 resolv.conf 文件如下:

    1. # DNS 服务的 IP,即coreDNS 的 clusterIP
    2. nameserver 169.254.25.10
    3. # DNS search 域。解析域名的时候,将要访问的域名依次带入 search 域,进行 DNS 查询
    4. # 比如访问your-nginx,其进行的 DNS 域名查询的顺序是:your-nginx.default.svc.cluster.local. -> your-nginx.svc.cluster.local. -> your-nginx.cluster.local.
    5. search default.svc.cluster.local svc.cluster.local cluster.local
    6. # 其他项,最常见的是 dnots。dnots 指的是如果查询的域名包含的点 “.” 小于 5,则先走search域,再用绝对域名;如果查询的域名包含点数大于或等于 5,则先用绝对域名,再走search域
    7. # K8s 中默认的配置是 5。
    8. options ndots:5

    5.3coreDNSCorefile文件 

    coreDNS 实现了应用的插件化,用户可以选择所需的插件编译到可执行文件中;CoreDNS 的配置文件是 Corefile 形式的,coreDNS 的 configMap如下所示:

    1. apiVersion: v1
    2. data:
    3. Corefile: |
    4. .:53 {
    5. errors
    6. health
    7. # 指明 cluster.local 后缀的域名,都是 kubernetes 内部域名,coredns 会监听 service 的变化来维护域名关系,所以cluster.local 相关域名都在这里解析
    8. kubernetes cluster.local in-addr.arpa ip6.arpa {
    9. pods insecure
    10. upstream
    11. fallthrough in-addr.arpa ip6.arpa
    12. }
    13. # CoreDNS 的监控地址为:http://localhost:9153/metrics
    14. prometheus :9153
    15. # proxy 指 coredns 中没有找到记录,则去 /etc/resolv.conf 中的 nameserver 请求解析,而 coredns 容器中的 /etc/resolv.conf 是继承自宿主机的。
    16. # 实际效果是如果不是 k8s 内部域名,就会去默认的 dns 服务器请求解析,并返回给 coredns 的请求者。
    17. forward . /etc/resolv.conf
    18. cache 30 # 允许缓存
    19. loop # 如果找到循环,则检测简单的转发循环并停止 CoreDNS 进程
    20. reload # 允许 Corefile 的配置自动更新。在更改 ConfigMap 后两分钟,修改生效
    21. loadbalance # 这是一个循环 DNS 负载均衡器,可以在答案中随机化 A,AAAA 和 MX 记录的顺序
    22. }
    23. kind: ConfigMap
    24. metadata:
    25. creationTimestamp: "2019-06-10T03:19:01Z"
    26. name: coredns
    27. namespace: kube-system

    六:node local dns 

    6.1DNS间歇性5秒延迟

    由于 Linux 内核中的缺陷,在 Kubernetes 集群中你很可能会碰到恼人的 DNS 间歇性 5 秒延迟问题。

    原因是镜像底层库 DNS 解析行为默认使用 UDP 在同一个 socket 并发 A 和 AAAA 记录请求,由于 UDP 无状态,两个请求可能会并发创建 conntrack 表项,如果最终 DNAT 成同一个集群 DNS 的 Pod IP 就会导致 conntrack 冲突,由于 conntrack 的创建和插入是不加锁的,最终后面插入的 conntrack 表项就会被丢弃,从而请求超时,默认 5s 后重试,造成现象就是 DNS 5 秒延时。

    具体原因可参见:

    issues-56903
    Weave works分析

    6.2NodeLocal DNSCache

    NodeLocal DNSCache通过在集群上运行一个dnsCache daemonset来提高clusterDNS性能和可靠性。相比于纯coredns方案,nodelocaldns + coredns方案能够大幅降低DNS查询timeout的频次,提升服务稳定性。

    nodelocaldns配置如下,nodelocaldns只配置了一个server,监听默认的UDP 53端口,4个zone。域名后缀为cluster.local的所有域名以及in-addr.arpa和ip6.arpa形式域名走coredns进行域名解析,其他外部域名使用宿主机的/etc/resolv.conf文件配置的nameserver进行解析。

    缓存分为 256 个分片,每个分片默认最多可容纳 39 个项目 - 总大小为 256 * 39 = 9984 个项目。

    1. # 其中cluster.local、in-addr.arpa、ip6.arpa表示kubernetes插件会处理域名后缀为cluster.local的所有域名以及处理所有的in-addr.arpa中的反向dns查找和ip6.arpa形式域名,其中kuberne# 集群域名后缀是在kubelet参数中配置的,默认值为cluster.local
    2. apiVersion: v1
    3. data:
    4. Corefile: |
    5. cluster.local:53 {
    6. errors
    7. cache {
    8. success 9984 30 # 对于成功的缓存最多缓存9984条域名解析记录,缓存时间为30s
    9. denial 9984 5 # 对于失败的缓存最多缓存9984条域名解析记录,缓存时间为5s
    10. }
    11. reload
    12. loop
    13. bind 169.254.25.10
    14. forward . 10.233.0.3 {
    15. force_tcp
    16. }
    17. prometheus :9253
    18. health 169.254.25.10:9254
    19. }
    20. in-addr.arpa:53 {
    21. errors
    22. cache 30
    23. reload
    24. loop
    25. bind 169.254.25.10
    26. forward . 10.233.0.3 {
    27. force_tcp
    28. }
    29. prometheus :9253
    30. }
    31. ip6.arpa:53 {
    32. errors
    33. cache 30
    34. reload
    35. loop
    36. bind 169.254.25.10
    37. forward . 10.233.0.3 {
    38. force_tcp
    39. }
    40. prometheus :9253
    41. }
    42. .:53 {
    43. errors
    44. cache 30
    45. reload
    46. loop
    47. bind 169.254.25.10
    48. forward . /etc/resolv.conf
    49. prometheus :9253
    50. }
    51. kind: ConfigMap

    nodelocaldns + coredns方案,DNS查询流程如下所示:

  • 相关阅读:
    将C语言中的命名格式改为Java中的驼峰式命名
    ubuntu 安装 mariadb,如何创建用户,并远程连接
    【知识专栏丨python数分实战】电商数据分析案例
    硬件系统工程师宝典(45)-----电源、时钟电路布局小技巧
    Vue3中使用el-table遇到的问题
    抖音短视频所有问题的详细攻略——今抖云创
    Java网关的统一异常处理
    这是什么APP?有谁知道的嘛?
    高并发场景中,数据库都有哪些优化手段?不会还有人不知道吧
    年龄越大,越要小心逢九年
  • 原文地址:https://blog.csdn.net/ver_mouth__/article/details/126138729