CodeDNS与CoreFile
一、CodeDNS介绍
DNS作为服务发现机制的基本功能, 在集群内需要能够通过服务名对服务进行访问, 这就需要一个集群范围内的DNS服务来完成从服务名到ClusterIP地址的解析。 DNS服务在Kubernetes的发展过程中经历了3个阶段, 接下来进行讲解。
在Kubernetes 1.2版本时, DNS服务是由SkyDNS提供的, 它由4个容器组成: kube2sky、 skydns、 etcd和healthz。 kube2sky容器监控Kubernetes中Service资源的变化, 根据Service的名称和IP地址信息生成DNS记录, 并将其保存到etcd中; skydns容器从etcd中读取DNS记录, 并为客户端容器应用提供DNS查询服务; healthz容器提供对skydns服务的健康检查功能。
SkyDNS的总体架构
从Kubernetes 1.4版本开始, SkyDNS组件便被KubeDNS替换, 主要考虑的是SkyDNS组件之间通信较多, 整体性能不高。 KubeDNS由3个容器组成: kubedns、 dnsmasq和sidecar, 去掉了SkyDNS中的etcd存储,将DNS记录直接保存在内存中, 以提高查询性能。 kubedns容器监控Kubernetes中Service资源的变化, 根据Service的名称和IP地址生成DNS记录, 并将DNS记录保存在内存中; dnsmasq容器从kubedns中获取DNS记录, 提供DNS缓存, 为客户端容器应用提供DNS查询服务; sidecar提供对kubedns和dnsmasq服务的健康检查功能。
KubeDNS的总体架构
从Kubernetes 1.11版本开始, Kubernetes集群的DNS服务便由CoreDNS提供。 CoreDNS是CNCF基金会孵化的一个项目, 是用Go语言实现的高性能、 插件式、 易扩展的DNS服务端, 目前已毕业。 CoreDNS解决了KubeDNS的一些问题, 例如dnsmasq的安全漏洞、 externalName不能使用stubDomains进行设置, 等等。 CoreDNS支持自定义DNS记录及配置upstream DNS Server, 可以统一管理Kubernetes基于服务的内部DNS和数据中心的物理DNS。 它没有使用多个容器的架构, 只用一个容器便实现了KubeDNS内3个容器的全部功能。
CoreDNS的总体架构
二、Corefile配置说明
root@easzlab-deploy:~/jiege-k8s# cat coredns-v1.9.3.yaml
# __MACHINE_GENERATED_WARNING__ apiVersion: v1 kind: ServiceAccount metadata: name: coredns namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: Reconcile name: system:coredns rules: - apiGroups: - "" resources: - endpoints - services - pods - namespaces verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults addonmanager.kubernetes.io/mode: EnsureExists name: system:coredns roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:coredns subjects: - kind: ServiceAccount name: coredns namespace: kube-system --- apiVersion: v1 kind: ConfigMap metadata: name: coredns namespace: kube-system labels: addonmanager.kubernetes.io/mode: EnsureExists data: Corefile: | .:53 { errors #将错误日志发往标准输出stdout health { #在CoreDNS的 http://localhost:8080/health 端口提供 CoreDNS 服务的健康报告。 lameduck 5s } ready #待所有插件就绪后通过8181端口响应“200 OK”以报告就绪状态,访问该接口会返回 200 OK。 kubernetes magedu.local in-addr.arpa ip6.arpa { #CoreDNS 将基于 kubernetes service name进行 DNS 查询并返回查询记录给客户端. pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 #CoreDNS 的度量指标数据以 Prometheus 的key-value的格式在http://localhost:9153/metrics URI上提供。 #forward . /etc/resolv.conf { forward . 223.6.6.6 { #不是Kubernetes 集群内的其它任何域名查询都将转发到 预定义的目的 max_concurrent 1000 } cache 600 #启用 service解析缓存, 单位为秒。 loop #检测域名解析是否有死循环, 如coredns转发给内网DNS服务器, 而内网DNS服务器又转发给coredns, 如果发现解析是死循环, 则强制中止 CoreDNS 进程(kubernetes会重建)。 reload #检测corefile是否更改,在重新编辑configmap 配置后, 默认2分钟后会优雅的自动加载。 loadbalance #轮训DNS域名解析, 如果一个域名存在多个记录则轮训解析。 } myserver.online { forward . 172.16.88.254:53 }
--- apiVersion: apps/v1 kind: Deployment metadata: name: coredns namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: # replicas: not specified here: # 1. In order to make Addon Manager do not reconcile this replicas parameter. # 2. Default is 1. # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on. replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 selector: matchLabels: k8s-app: kube-dns template: metadata: labels: k8s-app: kube-dns spec: securityContext: seccompProfile: type: RuntimeDefault priorityClassName: system-cluster-critical serviceAccountName: coredns affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: k8s-app operator: In values: ["kube-dns"] topologyKey: kubernetes.io/hostname tolerations: - key: "CriticalAddonsOnly" operator: "Exists" nodeSelector: kubernetes.io/os: linux containers: - name: coredns image: harbor.magedu.net/baseimages/coredns:1.9.3 imagePullPolicy: IfNotPresent resources: limits: memory: 256Mi cpu: 200m requests: cpu: 100m memory: 70Mi args: [ "-conf", "/etc/coredns/Corefile" ] volumeMounts: - name: config-volume mountPath: /etc/coredns readOnly: true ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP - containerPort: 9153 name: metrics protocol: TCP livenessProbe: httpGet: path: /health port: 8080 scheme: HTTP initialDelaySeconds: 60 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 5 readinessProbe: httpGet: path: /ready port: 8181 scheme: HTTP securityContext: allowPrivilegeEscalation: false capabilities: add: - NET_BIND_SERVICE drop: - all readOnlyRootFilesystem: true dnsPolicy: Default volumes: - name: config-volume configMap: name: coredns items: - key: Corefile path: Corefile --- apiVersion: v1 kind: Service metadata: name: kube-dns namespace: kube-system annotations: prometheus.io/port: "9153" prometheus.io/scrape: "true" labels: k8s-app: kube-dns kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "CoreDNS" spec: selector: k8s-app: kube-dns clusterIP: 10.100.0.2 ports: - name: dns port: 53 protocol: UDP - name: dns-tcp port: 53 protocol: TCP - name: metrics port: 9153 protocol: TCP
CoreDNS的主要功能是通过插件系统实现的。CoreDNS实现了一种链式插件结构,将DNS的逻辑抽象成了一个个插件,能够灵活组合使用。
常用的插件如下。
- errors: 将错误日志发往标准输出stdout
- health: 在CoreDNS的 http://localhost:8080/health 端口提供 CoreDNS 服务的健康报告。
- ready: 待所有插件就绪后通过8181端口响应“200 OK”以报告就绪状态,访问该接口会返回 200 OK。
- kubernetes: CoreDNS 将基于 kubernetes service name进行 DNS 查询并返回查询记录给客户端.
- prometheus: CoreDNS 的度量指标数据以 Prometheus 的key-value的格式在http://localhost:9153/metrics URI上提供。
- forward: 不是Kubernetes 集群内的其它任何域名查询都将转发到 预定义的目的
- server, 如 (/etc/resolv.conf或IP(如8.8.8.8)).
- cache: 启用 service解析缓存, 单位为秒。
- loop: 检测域名解析是否有死循环, 如coredns转发给内网DNS服务器, 而内网DNS服务器又转发给coredns, 如果发现解析是死循环, 则强制中止 CoreDNS 进程(kubernetes会重建)。
- reload: 检测corefile是否更改,在重新编辑configmap 配置后, 默认2分钟后会优雅的自动加载。
- loadbalance: 轮训DNS域名解析, 如果一个域名存在多个记录则轮训解析。
- etcd: 从etcd中读取zone数据, 可用于自定义域名记录。
- hosts: 使用/etc/hosts文件或者其他文件读取zone数据, 可用于自定义域名记录。
- file: 从RFC1035格式文件中读取zone数据。
- auto: 从磁盘中自动加载区域文件。
- pprof: 在URL路径/debug/pprof下提供运行时的性能数据。
- log: 对DNS查询进行日志记录。
三、Pod之间访问流程
CodeDNS解析流程:
- 当podA需要访问podB时,podA会在本地/etc/hosts查找podB信息,如果能查到相关信息,就会直接访问;
- 如果查询不到,会去找与之相邻上一级CoreDNS,CoreDNS会通过自己身缓存信息查找与podB相关信息;
- 如果查询不到,会找etcd服务查找有关podB信息,然后将其反馈给podA;
- 如果etcd没有查到,就会通过CodeDNS服务访问外部公网,在互联网查找与之相匹配的信息。