一、基于DNS的服务发现
ClusterDNS(CoreDNS)是Kubernetes集群的必备附件,负责为Kubernetes提供名称解析和服务发现。每个Service对象在创建时都会生成一个遵循”<service>.<ns>.svc.<zone>”格式的名称,由ClusterDNS为该名称生成资源记录。service、ns、zone分别代表服务的名称、名称空间的名称和集群的域名,当域名后缀未明确指定时,集群默认使用的域名为clusterip.local。
每个Service在CoreDNS上都会有A/AAAA、SRV和PTR类型的DNS资源记录。A记录列出特定主机名的IP地址;SRV记录了哪台计算机提供了哪一个服务(端口名解析为端口号);PTR记录是A记录的逆向记录,负责将IP地址解析为域名。
- 根据ClusterIP的地址类型,为IPv4生成A记录,为IPv6生成AAAA记录
- <service>.<ns>.svc.<zone>.<ttl> IN A <cluster-ip>
- <service>.<ns>.svc.<zone>.<ttl> IN AAAA <cluster-ip>
- 为每个定义了名称的端口生成一个SRV记录,未命名的端口号则不具有此记录_<port>._<proto>.<service>.<ns>.svc.<zone>.<ttl> IN SRV <weight> <priority> <port-number> <service>.<ns>.svc.<zone>.
- 对于每个给定的A记录(eg:a.b.c.d)或AAAA记录(eg:a1a2a3a4:b1b2b3b4:c1c2c3c4:d1d2d3d4:e1e2e3e4:f1f2f3f4:g1g2g3g4:h1h2h3h4)都要生成PTR记录,它们各自的格式如下:
- <d>.<c>.<b>.<a>.in-addr-arpa. <ttl> IN PTR <service>.<ns>.svc.<zone>.
- h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.
CoreDNS会持续监听API Server上Service资源对象的变动。一旦发现有新建的 Service 对象,就创建一个从 Service 名称映射到 ClusterIP 的域名记录。这样 Service 就不必自行向 DNS 进行注册,CoreDNS 控制器会关注新创建的 Service 对象,并实现后续的 DNS 过程。
Pod内的每一个容器在/etc/resolv.conf中生成容器使用到的DNS服务器,由ClusterDNS参数的值设定,其取值为kube-system名称空间下的Service对象kube-dns的ClusterIP,默认为10.96.0.10,这些配置信息在kubelet创建Pod时自动注入。其服务名称为kube-dns.kube-system.svc.cluster.local。而DNS搜索域的值由clusterDomain参数的值设定,当部署Kubernetes集群未明确指定时,其值按照搜索次序依次为NameSpaceName.svc.cluster.local、svc.cluster.local和cluster.local。
如下显示结果来自随机选择的一个容器的/etc/resolv.conf中的显示。
同时,Pod可直接向集群上的ClusterDNS发起服务名称和端口名称解析请求从而完成服务发现。各服务名称也支持短格式,由搜索域补全后缀。
如下操作是进入用于测试的客户端Pod对象后针对Service对象demoapp-svc做服务名称解析、PTR反解和SRV解析。在SRV解析中解析http的端口的返回结果为80。
kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --restart=Always -it --command -- /bin/bash
host -t A demoapp-svc
host -t PTR 10.97.72.1
host -t SRV _http._tcp.demoapp-svc
如果请求解析其它名称空间中的Service对象名称,则需要指明服务名称和名称空间。下面以kube-dns.kube-system为例进行解析请求。PTR、SRV这些类型的解析都类似。
host -t A kube-dns.kube-system
二、Pod的DNS解析策略
Kubernetes支持在单个Pod资源规范上自定义DNS解析策略和配置,它们分别使用spec.dnsPolicy和spec.dnsConfig进行定义,并组合生效。
Kubernetes支持如下DNS解析策略,它们定义在spec.dnsPolicy上。
- Default:使用Pod所在节点的DNS服务完成域名解析。
- ClusterFirst:默认值。优先使用Kubernetes集群的DNS服务器解析名称,将无法解析的域名交由Pod所在节点的DNS服务器来完成名称解析。
- ClusterFirstWithHostNet:专用于在设置了hostNetwork的Pod对象上使用的ClusterFirst策略。
- Node:忽略Kubernetes集群的默认设置,仅使用由dnsConfig自定义的配置。
Pod资源的自定义DNS配置类型如下,它定义在spec.dnsConfig字段上。
- nameservers:DNS名称服务器列表,它附加在dnsPolicy生成的DNS名称服务器之后。
- searches <[]string>:DNS名称解析时的搜索域,它附加在dnsPolicy生成的搜索域之后。
- options <[]Object>:DNS解析选项列表,它将会同dnsPolicy生成的解析选项合并成最终生效的定义。
如下示例中定义的 Pod资源完全使用自定义的配置。它通过将dnsPolicy设置为Node从而忽略Kubernetes集群的DNS配置信息,并在dnsConfig中自定义了要使用的DNS服务、搜索域和DNS解析选项。
vim pod-with-dnspolicy.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-dnspolicy
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
dnsPolicy: None
dnsConfig:
nameservers:
- 10.96.0.10
- 223.5.5.5
- 223.6.6.6
searches:
- svc.cluster.local
- cluster.local
- ilinux.io
options:
- name: ndots
value: "5"
kubectl apply -f pod-with-dnspolicy.yaml
将此Pod资源创建到集群后,可以看到类似如下内容的/etc/resolv.conf配置文件。
三、Headless Service
ClusterIP、NodePort、LoadBalancer类型的Service对象可通过不同入口来接收和分发客户端请求,且它们都具有集群IP地址(ClusterIP)。但一些场景就不用Service对象的负载均衡功能以及ClusterIP,而是借助ClusterDNS代替实现这部分功能。对于那些没有ClusterIP的Service对象称为Headless Service。有两种情形:
- 有标签选择器:也有与Service同名的Endpoint资源。ClusterDNS将Service的A记录直接解析为后端端点的IP。这也是狭义的Headless Service。
- 无标签选择器:也没有与Service同名的Endpoint资源。为ExternalName类型的Service创建CNAME记录,对应值由spec.externalName字段指定。
3.1 Headless Service
定义此类型的Service资源时,需要将ClusterIP字段的值设置为None即可定义为Headless类型。在如下示例中,它拥有标签选择器,因而能够自动创建与Service同名的Endpoint资源。
vim demoapp-headless-svc.yaml
---
kind: Service
apiVersion: v1
metadata:
name: demoapp-headless-svc
spec:
clusterIP: None
selector:
app: demoapp
ports:
- port: 80
targetPort: 80
name: http
kubectl apply -f demoapp-headless-svc.yaml
apply后,从其资源详情中可以看到,demoapp-headless-svc没有ClusterIP,但因标签选择器能够匹配到Pod资源,因此它拥有端点记录。
由解析记录可得,该Headless Service记录在ClusterDNS的A记录的相关解析结果正是通过标签选择器关联到的后端的PodIP。因此,客户端发起的请求将直接接入Pod对象,其接入的Pod资源是由DNS服务器收到请求后以轮询方式返回的PodIP。换句话说,这里的负载均衡功能是由DNS服务器完成的,而非Service实现的。
针对PodIP做反向解析(PTR),其格式为<hostname>.<subdomain>.<service>.<ns>.svc.<zone>,其中<subdomain>可省略。若<hostname>也未定义,则<hostname>的值来自IP地址,IP地址a.b.c.d对应的主机名为a-b-c-d。
3.2 ExternalName Service
ExternalName Service是一种特殊类型的Service资源,它不需要使用标签选择器关联Pod对象,也没有Endpoints,但需要使用spec.externalName字段定义一个CNAME记录,用于返回真正提供服务到位服务名称的别名。ClusterDNS会为此类型的Service自动生成<service>.<ns>.svc.<zone>.<ttl> IN CNAME <extname>格式的DNS记录。
vim externalname-redis-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: externalname-redis-svc
namespace: default
spec:
type: ExternalName
externalName: redis.ik8s.io
ports:
- protocol: TCP
port: 6379
targetPort: 6379
nodePort: 0
selector: {}
kubectl apply -f externalname-redis-svc.yaml
externalname-redis-svc这个Service创建完成后,解析服务名称时ClusterDNS先将服务名称以CNAME格式解析为别名(spec.externalName字段定义的名称),再将其解析为IP地址。
标签:Service,Kubernetes,svc,Headless,名称,DNS,Pod,解析 From: https://blog.51cto.com/u_15796303/6474535