文章目录

  • ​​01 引言​​
  • ​​02 DNS服务在k8s的发展​​
  • ​​2.1 SkyDNS​​
  • ​​2.2 KubeDNS​​
  • ​​2.3 CoreDNS​​
  • ​​03 搭建CoreDNS服务​​
  • ​​3.1 修改每个Node上kubelet的DNS启动参数​​
  • ​​3.2 部署CoreDNS服务​​
  • ​​3.2.1 ConfigMap​​
  • ​​3.2.2 Deployment​​
  • ​​3.2.3 Service​​
  • ​​04 服务名的DNS解析​​
  • ​​05 CoreDNS配置​​
  • ​​5.1 示例一:设置插件​​
  • ​​5.2 示例二:自定义域名​​
  • ​​5.3 示例三:转发域名查询到上游DNS服务器上​​
  • ​​06 引言​​

01 引言

声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记

作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,这就需要一个集群范围内的DNS服务来完成从服务名到​​ClusterIP​​地址的解析。

02 DNS服务在k8s的发展

2.1 SkyDNS

k8s教程(service篇)-DNS服务搭建和配置_云原生

在Kubernetes1.2版本时,DNS服务是由​​SkyDNS​​提供的,它由4个容器组成(kube2sky、skydns、etcd和healthz):

  • kube2sky容器:监控Kubernetes中Service 资源的变化,根据Service的名称和IP地址信息生成DNS记录,并将其保存到etcd 中;
  • skydns容器:从etcd中读取DNS记录,并为客户端容器应用提供DNS查询服务
  • healthz容器:提供对skydns服务的健康检查功能。

2.2 KubeDNS

k8s教程(service篇)-DNS服务搭建和配置_Deployment_02

从Kubernetes1.4版本开始,SkyDNS组件便被KubeDNS替换,主要考虑的是SkyDNS组件之间通信较多,整体性能不高

KubeDNS由3个容器组成(kubedns、dnsmasq和sidecar),去掉了SkyDNS中的etcd存储,将DNS记录直接保存在内存中,以提高查询性能:

  • kubedns容器
  • dnsmasq容器:从kubedns中获取DNS记录,提供DrS缓存,为客户端容器应用提供DNS查询服务;
  • sidecar容器:提供对kubedns和dnsmasq服务的健康检查功能。

2.3 CoreDNS

k8s教程(service篇)-DNS服务搭建和配置_容器化技术_03


从Kubernetes1.11版本开始,Kubernetes集群的DNS服务由CoreDNS提供

  • 它是由go语言实现的一套高性能、插件式,易于扩展的DNS服务端;
  • 解决了KubeDNS的一些问题, 例如dnsmasq的安全漏洞、externalName不能使用stubDomains进行设置等等;
  • 支持自定义DNS记录及配置upstream DNS Server,可以统一管理Kubernetes基于服务的内部DNS和数据中心的物理DNS;
  • 它没有使用多个容器的架构,只用一个容器便实现了KubeDNS内3个容器的全部功能。

03 搭建CoreDNS服务

3.1 修改每个Node上kubelet的DNS启动参数

修改每个Node上kubelet的启动参数,在其中加上以下两个参数:

  • ​--cluster-dns=169.169.0.100​​:为DNS服务的ClusterIP地址。
  • ​--cluster-domain=cluster.local​​:为在DNS服务中设置的域名。

然后重启kubelet服务。

3.2 部署CoreDNS服务

部署CoreDNS服务时需要创建3个资源对象:1个ConfigMap、1个Deployment和1个Service

在启用了RBAC的集群中,还可以设置ServiceAccount、ClusterRole 、ClusterRoleBinding对CoreDNS容器进行权限设置。

3.2.1 ConfigMap

ConfigMap 的 “coredns” 主要设置CoreDNS的主配置文件Corefile的内容,其中可以定义各种域名的解析方式和使用的插件,示例如下:

apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
labels:
addonmanager.kubernetes.io/mode: EnsureExists
data:
Corefile: |
cluster.local{
errors
health{
lameduck 5s
}
ready
kubernetes cluster.local 169.169.0.0/16{
fallthrough in-addr.arpa ip6.arpa
}
prometheus: 9153
forward ./etc/resolv.conf
cache 30
loop
reload
loadbalance
}
. {
cache 30
loadbalance
forward /etc/resolv.conf
}

3.2.2 Deployment

Deployment 的“coredns” 主要设置​​CoreDNS​​容器应用的内容。

其中,​​replicas​​​副本的数量通常应该根据集群的规模和服务数量确定,如果单个​​CoreDNS​​​进程不足以支撑整个集群的​​DNS​​​查询,则可以通过水平扩展提高查询能力。由于​​DNS​​​服务是​​Kubernetes​​​集群的关键核心服务,所以建议为其​​Deployment​​设置自动扩缩容控制器,自动管理其副本数量。

另外,对资源限制部分(​​CPU​​限制和内存限制)的设置也应根据实际环境进行调整:

apiversion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/name: "CoreDNS"
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
spec:
priorityClassName: system-cluster-critical
tolerations:
- key: "CriticalAddonsonly"
operator: "Exists"
nodeSelector:
kubernetes.io/os: linux
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values: ["kube-dns"]
topologyKey: kubernetes.io/hostname
containers:
- name: coredns
image: coredns/coredns:1.7.0
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 170Mi
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
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- a11
readOnlyRootFilesystem: true
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile

3.2.3 Service

Service“kube-dns” 是DNS服务的配置,这个服务需要设置固定的​​ClusterIP​​​地址,也需要将所有​​Node​​​上的​​kubelet​​​启动参数​​--cluster-dns​​​都设置为这个​​ClusterIP​​ 地址:

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"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 169.169.0.100
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
- name: metrics
port: 9153
protocol: TCP

使用​​kubectl create​​命令依次把资源对象创建,然后可以看到创建成功:

k8s教程(service篇)-DNS服务搭建和配置_云原生_04

04 服务名的DNS解析

接下来使用一个带有 nslookup工具 的pod来验证DNS是否正常工作。

apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- name: busybox
image: gcr.io/google containers/busybox
command:
- sleep
- "3600"

在该容器成功启动后,通过​​kubectl exec<container_id>--nslookup​​进行测试:

k8s教程(service篇)-DNS服务搭建和配置_kubernetes_05


可以看到,通过DNS服务器 169.169.0.100 成功解析了redis-master服务的IP地址 169.169.8.10


如果某个Service属于不同的命名空间,那么在进行Service查找时,需要补充
Namespace的名称,将其组合成完整的域名

下面以查找kube-dns服务为例,将其所在**Namespace“kube-system”**补充在服务名之后,用 “.” 连接为 “kube- dns.kube-system,即可查询成功:

k8s教程(service篇)-DNS服务搭建和配置_kubernetes_06


如果仅使用 “kube-dns” 进行查找,则会失败:

nslookup: can't resolve 'kube-dns'

05 CoreDNS配置

CoreDNS的主要功能是通过插件系统实现的,CoreDNS实现了一种链式插件结构,将DNS的逻辑抽象成了一个个插件,能够灵活组合使用。常用的插件如下:

插件

描述

loadbalance

提供基于DNS的负载均衡功能

loop

检测在DNS解析过程中出现的简单循环问题

cache

提供前端缓存功能

health

对Endpoint进行健康检查

kubernetes

从Kubernetes中读取zone数据

etcd

从etcd中读取zone数据,可用于自定义域名记录

file

从RFC 1035格式文件中读取zone数据

hosts

使用/etc/hosts文件或者其他文件读取zone数据,可用于自定义域名记录

auto

从磁盘中自动加载区域文件

reload

定时自动重新加载Corefile配置文件的内容

forward

转发域名查询到上游DNS服务器上

prometheus

为Prometheus系统提供采集性能指标数据的URL

pprof

在URL路径/debug/pprof下提供运行时的性能数据

log

对DNS查询进行日志记录

errors

对错误信息进行日志记录

5.1 示例一:设置插件

在下面的示例中为域名 “cluster.local” 设置了一系列插件,包括errors、 health、ready、kubernetes、prometheus、forward、cache、loop、reload和 loadbalance,在进行域名解析时,这些插件将以从上到下的顺序依次执行:

cluster.local {
errors
health{
lameduck 5s
}
ready
kubernetes cluster.local 169.169.0.0/16 {
fallthrough in-addr.arpa ip6.arpa
}
prometheus: 9153
forward ./etc/resolv.conf
cache 30
loop
reload
loadbalance
}

5.2 示例二:自定义域名

另外,etcd和hosts插件都可以用于用户自定义域名记录。

下面是使用​​etcd​​​插件的配置示例,将以“​​.com​​​”结尾的域名记录配置为从etcd中获取,并将域名记录保存在​​/skydns​​路径下:

{
etcd com{
path /skydns
endpoint http://192.168.18.3:2379
upstream /etc/resolv.conf
}
cache 160 com
loadbalance
proxy /etc/resolv.conf
}

如果用户在etcd中插入一条“10.1.1.1 mycompany” DNS记录:

$ ETCDCTL_API=3 etcdctl put "/skydns/com/mycompany" '["host":"10.1.1.","ttl":60]'

客户端应用就能访问域名"mycompany.com"了:

$ nslookup mycompany.com
Server: 169.169.0.100
Address: 169.169.0.100#53

Name: mycompany.com
Address: 10.1.1.1

5.3 示例三:转发域名查询到上游DNS服务器上

forward插件用于配置上游DNS服务器或其他DNS服务器,当在CoreDNS中查
询不到域名时,会到其他DNS服务器上进行查询。在实际环境中,可以将Kubernetes集群外部的DNS纳入CoreDNS,进行统一的DNS管理。

06 引言

本文主要讲解k8s里面的DNS服务搭建与配置,希望能帮助到大家,谢谢大家的阅读,本文完!