CoreDNS的主要功能是通过插件系统实现的。CoreDNS实现了一种链式插件结构,将DNS的逻辑抽象成了一个个插件,能够灵活的组合使用。
常用的插件如下:
◎ loadbalance:提供基于DNS的负载均衡功能。
◎ loop:检测在DNS解析过程中出现的简单循环问题。
◎ cache:提供前端缓存功能。
◎ health:对Endpoint进行健康检查。
◎ kubernetes:从Kubernetes中读取zone数据。
◎ etcd:从etcd读取zone数据,可以用于自定义域名记录。
◎ file:从RFC1035格式文件中读取zone数据。
◎ hosts:使用/etc/hosts文件或者其他文件读取zone数据,可以用于自定义域名记录。
◎ auto:从磁盘中自动加载区域文件。
◎ reload:定时自动重新加载Corefile配置文件的内容。
◎ forward:转发域名查询到上游DNS服务器。
◎ proxy:转发特定的域名查询到多个其他DNS服务器,同时提供到多个DNS服务器的负载均衡功能。
◎ prometheus:为Prometheus系统提供采集性能指标数据的URL。
◎ pprof:在URL路径/debug/pprof下提供运行时的性能数据。
◎ log:对DNS查询进行日志记录。
◎ errors:对错误信息进行日志记录。
在下面的示例中为域名“cluster.local“设置了一些列插件,包括errors、health、kubernetes、prometheus、forward、cache、loop、reload和loadbalance,在进行域名解析时,这些插件将以从上到下的顺序依次执行:
cluster.local{
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward ./etc/resolov.conf
cache 30
loop
reload
loadbalance
}
另外,etcd和hosts插件都可以用于用户自定义域名的记录。
下面是使用etcd插件的配置示例,将以 “.com” 结尾的域名记录配置为从etcd中获取,并将域名记录保存在/skydns路径下:
{
etcd com{
path /skydns
endpoint https://20.0.40.51:2379
upstreamm /etc/resolv.conf
}
cache 160 com
loadbalance
proxy . /etc/resolv.cof
}
如果用户在etcd中插入一条“10.1.1.1 mycompany.com”DNS记录:
etcdctl put /skydns/com/mycompany '{"host": "10.1.1.1", "ttl":60}'
库护短应用就能访问域名 “mycompany.com”了:
nslookup mycompany.com
foreard和proxy插件都可以用于配置上游DNS服务器,当CoreDNS中查询不到域名时,会到其他DNS服务器上进行查询。在实际环境中,可以将kubernetes集群外部的dns纳入CoreDNS,进行统一的DNS管理。
此处实验可以先行了解(没有ca认证不能做成),后面讲到ca认证会详细讲解。
除了使用集群范围的DNS服务(如CoreDNS),在Pod级别也能设置DNS相关策略和配置。
在Pod的YAML配置文件中通过spec.dnsPolicy字段设置DNS策略,例如:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
dnsPolicy: Default
目前可以设置的DNS策略如下。
◎ Default:继承Pod所在宿主机的DNS设置。
◎ ClusterFirst:优先使用Kubernetes环境的DNS服务(如CoreDNS提供的域名解析服务),将无法解析的域名转发到从宿主机继承的DNS服务器。
◎ ClusterFirstWithHostNet:与ClusterFirst相同,对于以hostNetwork模式运行的Pod,应明确指定使用该策略。
◎ None:忽略Kubernetes环境的DNS配置,通过spec.dnsConfig自定义DNS配置。这个选项从Kubernetes 1.9版本开始引入,到Kubernetes 1.10版本升级为Beta版,到Kubernetes 1.14版本升级为稳定版。
自定义DNS配置可以通过spec.dnsConfig字段进行设置,可以设置下列信息。
◎ nameservers:一组DNS服务器的列表,最多可以设置3个。
◎ searches:一组用于域名搜索的DNS域名后缀,最多可以设置6个。
◎ options:配置其他可选DNS参数,例如ndots、timeout等,以name或name/value对的形式表示。
以下面的dnsConfig为例:
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.2.3.4
searches:
- ns1.svc.cluster.local
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
该Pod被成功创建之后,容器内的DNS配置文件/etc/resolv.confg的内容将被系统设置:
表示该Pod完全使用自定义的DNS配置,不再使用kubernetes环境的DNS服务。
根据前面的Service的使用说明,我们知道Service的表现形式为IP:Port,即工作在TCP/IP层。而对于基于HTTP的服务来说,不同的URL地址经常对应到不同的后端服务或者虚拟服务器(Virtual Host),这些应用层的转发机制仅通过Kubernetes的Service机制是无法实现的。
从Kubernetes1.1版本开始新增Ingress资源对象,用于将不同URL的访问请求转发到后端不同的Service,以实现HTTP层的业务路由机制。Kubernetes使用了一个Ingress策略定义和一个具体的Ingress Controller,两者结合并实现了一个完整的Ingress负载均衡器。
使用Ingress进行负载分发时,Ingress Controller基于Ingress规则将客户端请求直接转发到Service对应的后端Endpoint(Pod)上,这样会跳过kube-proxy的转发功能,kube-proxy不在其作用。如果Ingress Controller提供的是对外服务,则实际上实现的是边缘路由器的功能。
其中:
为使用Ingress,需要创建Ingress Controller(带一个默认backend服务)和Ingress策略设置来共同完成。
在定义Ingress策略之前,需要先部署Ingress Controller,以实现为所有后端Service都提供一个统一的入口。Ingress Controller需要实现基于不同HTTP URL向后转发的负载分发规则,并可以灵活设置7层负载分发策略。如同公有云服务商能够提供该类型的HTTP路由LoadBalancer,则也可设置其他Ingress Controller。
在Kubernetes中,Ingress Controller将以Pod的形式运行,监控API Server的/ingress接口后端的backend services,如果Service 发生变化,则Ingress Controller应自动更新其转发规则。
下面的例子使用Nginx来实现一个Ingress Controller,需要实现的基本逻辑如下。
(1)监听API Server,获取全部Ingress的定义。
(2)基于Ingress的定义,生成Nginx所需的配置文件/etc/nginx/nginx.conf。
(3)执行nginx -s reload命令,重新加载nginx.conf配置文件的内容。
本例使用谷歌提供的nginx-ingress-controller镜像来创建Ingress Controller该Ingress Controller以daemonset的形式进行创建,在每个Node上都将启动一个Nginx服务。
这里为Nginx容器设置了hostPort,将容器应用监听的80和443端口映射到物理机上,是的客户端应用可以通过URL地址“http://物理机:80” 或“https://物理机:443” 来访问该Ingress Controller。这使得Nginx类似于通过NodePort映射到物理机的Service,成为代替Kube-proxy的HTTP层的Load Balancer:
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ingress-lb
labels:
name: nginx-ingress-lb
namespace: kube-system
spec:
template:
metadata:
labels:
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.9.0-beta.2
name: nginx-ingress-lb
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 1
ports:
- containerPort: 80
hostPort: 80
- containerPort: 443
hostPort: 443
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
args:
- /nginx-ingress-controller
- --default-backend-service=${POD_NAMESPACE}/default-http-backend
为了让Ingress Controller正常启动,还需要为它配置一个默认的backend,用于在客户端访问的URL地址不存在时,返回一个正确的404应答。这个backend服务用任何应用实现都可以,只要满足对根路径“/”的访问返回404应答,并且提供/healthz路径以使kubelet完成对它的健康检查。另外,由于Nginx通过default-backend-service的服务名称(Service Name)去访问它,所以需要DNS服务正确运行:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: default-http-backend
labels:
k8s-app: default-http-backend
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: default-http-backend
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backedn
image: registry.cn-hangzhou.aliyuncs.com/google_containers/defaultbackend:1.0
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: kube-system
labels:
k8s-app: default-http-backend
spec:
ports:
- port: 80
targetPort: 8080
selector:
k8s-app: default-http-backend
通过Kubectel create命令创建backend服务;
创建nginx-ingress-controller;
在此处出现了问题,目前没有解决,
报错如下:(有能力解决的小伙伴,可以解决哦)
本例对mywebsite.com网站的访问设置Ingress策略,定义对其/demo路径的访问转发到后端webapp Service的规则:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mywebsite-ingress
spec:
rules:
- host: mywebsite.com
http:
paths:
- path: /demo
backend:
serviceName: webapp
servicePort: 8080
这个Ingress的定义,说明对目标地址http://mywebsite.com/demo的访问将被转发到集群中的Service webapp即webapp:8080/demo上。
在Ingress生效之前,需要先将webapp服务部署完成。同时需要注意Ingress中path的定义,需要与后端真实Service提供的path一致,否则将被转发到一个不存在的path上,引发错误。这里以webapp例子为例,假设myweb服务已经部署完毕并正常运行,myweb提供的Web服务的路径也为/demo。
在成功创建该Ingress后,查看其ADDRESS列,如果显示了所有nginx-ingress-controller Pod的IP地址,则表示Nginx已经设置好后端Service的Endpoint,该Ingress可以正常工如果ADDRESS列为空,则通常说明Nginx未能正确连接到后端Service,需要排错。
登录任一nginx-ingress-controller Pod,查看其自动生成的nginx.conf配置文件的内容,可以看到对mywebsite.com/demo的转发
规则的正确配置。
由于Ingress Controller容器通过hostPort将服务端口号80映射到了所有Node上,所以客户端可以通过任意Node访问mywebsite.com提供的服务。
需要说明的是,客户端只能通过域名mywebsite.com访问服务,这时要求客服端或者DNS将mywebsite.com域名解析到后端多个Node的真实IP低智商。
通过curl访问mywebsite.com提供的服务(可以用-resolve参数模拟DNS解析,目标地址为域名;也可以用-H‘Host:mywebsit.com’参数设置HTTP头中要访问的域名,目标地址为IP地址),可以得到myweb返回的网页内容。
curl --resolve mywebsite.com:80:192.168.18.3 http://mywebsite.com/demon/
curl -H 'Host:mywebsite.com' http://192.168.18.3/demo/
如果通过浏览器访问,那么需要先在本机上设置域名mywebsite.com对应的IP地址,再到浏览器上进行访问。以Windows为例,修改hosts文件,加入一行记录
192.168.18.3 mywebsie.com
然后在浏览器的地址栏输入http://mywebsite.com/demo/,就能够访问Ingress提供的服务了。
小结:
本节内容到此结束
虽然很多实例没有做,当时后续会补充说明的,谢谢大家的支持!