当前位置:网站首页>Kubernetes:(九)coredns(浪不动了)
Kubernetes:(九)coredns(浪不动了)
2022-08-04 01:40:00 【糖醋·小排顾】
目录
一:什么是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节点上应用
docker pull docker.io/coredns/coredns:1.6.1
docker tag coredns:1.6.1 harbor.od.com/public/coredns:v1.6.1
docker push harbor.od.com/public/coredns:v1.6.1
配置nginx虚拟主机
vim /etc/nginx/conf.d/k8s-yaml.od.com.conf
server {
listen 80;
server_name k8s-yaml.od.com;
location / {
autoindex on;
default_type text/plain;
root /data/k8s-yaml;
}
}
mkdir /data/k8s-yaml;
nginx -qt && nginx -s reload
配置dns解析node节点
vim /var/named/od.com.zone
$ORIGIN od.com.
$TTL 600 ; 10 minutes
@ IN SOA dns.od.com. dnsadmin.od.com. (
2020070603 ; serial
10800 ; refresh (3 hours)
900 ; retry (15 minutes)
604800 ; expire (1 week)
86400 ; minimum (1 day)
)
NS dns.od.com.
$TTL 60 ; 1 minute
dns A 10.4.7.11
harbor A 10.4.7.200
k8s-yaml A 10.4.7.200
systemctl restart named
4.2创建coredns的资源配置清单
以下资源配置清单,都是参考官网改出来的
mkdir -p /data/k8s-yaml/coredns
4.2.1rbac集群权限清单
清单文件存放到 master主机data/k8s-yaml/coredns/coredns_1.6.1/
cat >/data/k8s-yaml/coredns/rbac.yaml <<EOF
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
---
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
EOF
4.2.2configmap配置清单
cat >/data/k8s-yaml/coredns/cm.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
log
health
ready
kubernetes cluster.local 192.168.0.0/16 #service资源cluster地址
forward . 10.4.7.11 #上级DNS地址
cache 30
loop
reload
loadbalance
}
EOF
4.2.3depoly控制器清单
cat >/data/k8s-yaml/coredns/dp.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: coredns
kubernetes.io/name: "CoreDNS"
spec:
replicas: 1
selector:
matchLabels:
k8s-app: coredns
template:
metadata:
labels:
k8s-app: coredns
spec:
priorityClassName: system-cluster-critical
serviceAccountName: coredns
containers:
- name: coredns
image: harbor.od.com/public/coredns:v1.6.1
args:
- -conf
- /etc/coredns/Corefile
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
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
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
EOF
4.2.4service资源清单
cat >/data/k8s-yaml/coredns/svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: coredns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: coredns
clusterIP: 192.168.0.2
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
- name: metrics
port: 9153
protocol: TCP
EOF
4.3创建资源并验证
在任意NODE节点执行配置都可以
4.3.1验证服务能够访问
dig -t A harbor.od.com +short
4.3.2创建资源
kubectl create -f http://k8s-yaml.od.com/coredns/rbac.yaml
kubectl create -f http://k8s-yaml.od.com/coredns/cm.yaml
kubectl create -f http://k8s-yaml.od.com/coredns/dp.yaml
kubectl create -f http://k8s-yaml.od.com/coredns/svc.yaml
4.3.3查看创建情况
kubectl get all -n kube-system
kubectl get svc -o wide -n kube-system
dig -t A www.baidu.com @192.168.0.2 +short
4.3.4使用dig测试解析
dig -t A www.baidu.com @192.168.137.20 +short
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
kubectl create deployment nginx-dp --image=harbor.zq.com/public/nginx:v1.17.9 -n kube-public
~]# kubectl get deployments -n kube-public
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-dp 1/1 1 1 35s
~]# kubectl get pod -n kube-public
NAME READY STATUS RESTARTS AGE
nginx-dp-568f8dc55-rxvx2 1/1 Running 0 56s
给pod创建一个service
kubectl expose deployment nginx-dp --port=80 -n kube-public
~]# kubectl -n kube-public get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-dp ClusterIP 192.168.63.255 <none> 80/TCP 11s
验证是否可以解析
~]# dig -t A nginx-dp @192.168.137.20 +short
# 发现无返回数据,难道解析不了
# 其实是需要完整域名:服务名.名称空间.svc.cluster.local.
~]# dig -t A nginx-dp.kube-public.svc.cluster.local. @192.168.137.20 +short
可以看到我们没有手动添加任何解析记录,我们nginx-dp的service资源的IP,已经被解析了:
进入到pod内部再次验证
~]# kubectl -n kube-public exec -it nginx-dp-568f8dc55-rxvx2 /bin/bash
-qjwmz:/# apt update && apt install curl
-qjwmz:/# ping nginx-dp
为什么在容器中不用加全域名?
-qjwmz:/# cat /etc/resolv.conf
nameserver 192.168.137.20
search kube-public.svc.cluster.local svc.cluster.local cluster.local host.com
options ndots:5
当我进入到pod内部以后,会发现我们的dns地址是我们的coredns地址,以及搜索域中已经添加了搜索域:
kube-public.svc.cluster.local
五:coredns配置
5.1K8sDNS策略
Kubernetes 中 Pod 的 DNS 策略有四种类型:
- Default(默认预设):Pod 继承所在主机上的 DNS 配置;
- ClusterFirst(集群优先):K8s 的默认设置;先在 K8s 集群配置的 coreDNS 中查询,查不到的再去继承自主机的上游 nameserver 中查询;
- ClusterFirstWithHostNet(宿主机与k8s共存):对于网络配置为 hostNetwork 的 Pod 而言,其 DNS 配置规则与 ClusterFirst 一致;
- None(无策略):忽略 K8s 环境的 DNS 配置,只认 Pod 的 dnsConfig 设置。
5.2resolv.conf
在部署 pod 的时候,如果用的是 K8s 集群的 DNS,那么 kubelet 在起 pause 容器的时候,会将其 DNS 解析配置初始化成集群内的配置。
如创建了一个叫 my-nginx 的 deployment,其 pod 中的 resolv.conf 文件如下:
# DNS 服务的 IP,即coreDNS 的 clusterIP
nameserver 169.254.25.10
# DNS search 域。解析域名的时候,将要访问的域名依次带入 search 域,进行 DNS 查询
# 比如访问your-nginx,其进行的 DNS 域名查询的顺序是:your-nginx.default.svc.cluster.local. -> your-nginx.svc.cluster.local. -> your-nginx.cluster.local.
search default.svc.cluster.local svc.cluster.local cluster.local
# 其他项,最常见的是 dnots。dnots 指的是如果查询的域名包含的点 “.” 小于 5,则先走search域,再用绝对域名;如果查询的域名包含点数大于或等于 5,则先用绝对域名,再走search域
# K8s 中默认的配置是 5。
options ndots:5
5.3coreDNSCorefile文件
coreDNS 实现了应用的插件化,用户可以选择所需的插件编译到可执行文件中;CoreDNS 的配置文件是 Corefile 形式的,coreDNS 的 configMap如下所示:
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health
# 指明 cluster.local 后缀的域名,都是 kubernetes 内部域名,coredns 会监听 service 的变化来维护域名关系,所以cluster.local 相关域名都在这里解析
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
# CoreDNS 的监控地址为:http://localhost:9153/metrics
prometheus :9153
# proxy 指 coredns 中没有找到记录,则去 /etc/resolv.conf 中的 nameserver 请求解析,而 coredns 容器中的 /etc/resolv.conf 是继承自宿主机的。
# 实际效果是如果不是 k8s 内部域名,就会去默认的 dns 服务器请求解析,并返回给 coredns 的请求者。
forward . /etc/resolv.conf
cache 30 # 允许缓存
loop # 如果找到循环,则检测简单的转发循环并停止 CoreDNS 进程
reload # 允许 Corefile 的配置自动更新。在更改 ConfigMap 后两分钟,修改生效
loadbalance # 这是一个循环 DNS 负载均衡器,可以在答案中随机化 A,AAAA 和 MX 记录的顺序
}
kind: ConfigMap
metadata:
creationTimestamp: "2019-06-10T03:19:01Z"
name: coredns
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 秒延时。
具体原因可参见:
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 个项目。
# 其中cluster.local、in-addr.arpa、ip6.arpa表示kubernetes插件会处理域名后缀为cluster.local的所有域名以及处理所有的in-addr.arpa中的反向dns查找和ip6.arpa形式域名,其中kuberne# 集群域名后缀是在kubelet参数中配置的,默认值为cluster.local
apiVersion: v1
data:
Corefile: |
cluster.local:53 {
errors
cache {
success 9984 30 # 对于成功的缓存最多缓存9984条域名解析记录,缓存时间为30s
denial 9984 5 # 对于失败的缓存最多缓存9984条域名解析记录,缓存时间为5s
}
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
health 169.254.25.10:9254
}
in-addr.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
}
ip6.arpa:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . 10.233.0.3 {
force_tcp
}
prometheus :9253
}
.:53 {
errors
cache 30
reload
loop
bind 169.254.25.10
forward . /etc/resolv.conf
prometheus :9253
}
kind: ConfigMap
nodelocaldns + coredns方案,DNS查询流程如下所示:
边栏推荐
- JS 保姆级贴心,从零教你手写实现一个防抖debounce方法
- Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
- 快速入门EasyX图形编程
- GNSS文章汇总
- Vant3 - click on the corresponding name name to jump to the next page corresponding to the location of the name of the TAB bar
- FeatureNotFound( bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested:
- Array_Sliding window | leecode brushing notes
- 持续投入商品研发,叮咚买菜赢在了供应链投入上
- 一篇文章看懂JS闭包,从执行上下文角度解析有趣的闭包
- 字符串变形
猜你喜欢
随机推荐
多线程 之 JUC 学习篇章一 创建多线程的步骤
- heavy OpenCV 】 【 mapping
C 学生管理系统_分析
一个项目的整体测试流程有哪几个阶段?测试方法有哪些?
The 600MHz band is here, will it be the new golden band?
Android interview questions and answer analysis of major factories in the first half of 2022 (continuously updated...)
typescript58 - generic classes
How to copy baby from Taobao (or Tmall store) through API interface to Pinduoduo interface code docking tutorial
nodejs安装及环境配置
【store商城项目01】环境准备以及测试
工程制图名词解释-重点知识
2022 China Computing Power Conference released the excellent results of "Innovation Pioneer"
nodejs+npm的安装与配置
idea中diagram使用
天地图坐标系转高德坐标系 WGS84转GCJ02
持续投入商品研发,叮咚买菜赢在了供应链投入上
Continuing to invest in product research and development, Dingdong Maicai wins in supply chain investment
5.scrapy中间件&分布式爬虫
JS 保姆级贴心,从零教你手写实现一个防抖debounce方法
Slipper —— 虚点,最短路