有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。无头 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。
DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。
(1)带选择算符的服务
对定义了选择算符的无头服务,Endpoint 控制器在 API 中创建了 Endpoints 记录, 并且修改 DNS 配置返回 A 记录(地址),通过这个地址直接到达 Service 的后端 Pod 上。
(2)无选择算符的服务
1)对没有定义选择算符的无头服务,Endpoint 控制器不会创建 Endpoints 记录。 然而 DNS 系统会查找和配置,无论是:对于 ExternalName 类型的服务,查找其 CNAME 记录。
2)对所有其他类型的服务,查找与 Service 名称相同的任何 Endpoints 的记录。
无头(Headless)服务(没有集群 IP)也会以 my-svc.my-namespace.svc.cluster-domain.example 这种名字的形式被指派一个 DNS A 或 AAAA 记录。 与普通服务不同,这一记录会被解析成对应服务所选择的 Pod 集合的 IP。 客户端要能够使用这组 IP,或者使用标准的轮转策略从这组 IP 中进行选择。
接下来通过两个无头(Headless)服务来带领读者理解其特点。
(1)例子1,我们将实现一个带有选择运算符的无头(Headless)服务,验证其特性。
(2)例子2,我们将实现一个无选择运算符的无头(Headless)服务,验证其特性。
例子1,我们创建一个带有标签选择器的服务nginx-service-headless。
第一步,编辑一个无头服务的yaml文件,其Service的定义与之前的定义的唯一区别是添加了一个属性clusterIP: None,Deployment的定义与之前的定义相同。
apiVersion: v1
kind: Service
metadata:
name: nginx-service-headless
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
clusterIP: None # 无头服务
selector:
app: nginx # 定义此Service关联的Pod对应的标签
type: ClusterIP # 此Service类型为ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels: # 定义Deployment关联的Pod的标签
app: nginx
replicas: 3 # 告诉Deployment运行的Pod实例数目
template: # Pod的模板
metadata:
labels:
app: nginx # Pod的标签
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
第二步,应用这个yaml文件,创建对应的Service与Pod等资源。
kubectl apply -f 2-service-headless.yaml
第三步,查看创建资源的概况,如图所示,Service nginx-service-headless 的CLUSTER-IP为None。
[root@kubernetes-master01 service]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-6b474476c4-27gqr 1/1 Running 0 4m29s
pod/nginx-deployment-6b474476c4-6w5zl 1/1 Running 0 4m29s
pod/nginx-deployment-6b474476c4-ww74l 1/1 Running 0 4m29s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-service-headless ClusterIP None 80/TCP 4m29s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 3/3 3 3 4m29s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-6b474476c4 3 3 3 4m29s
第四步,查看Service nginx-service-headless 后面关联的Pod,如图所示,关联的Pod都是正常的,是我们定义的相同标签的三个Pod。
[root@kubernetes-master01 service]# kubectl describe service nginx-service-headless
Name: nginx-service-headless
Namespace: default
Labels:
Annotations: Selector: app=nginx
Type: ClusterIP
IP: None
Port: 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.51:80,10.244.1.52:80,10.244.2.20:80
Session Affinity: None
Events:
[root@kubernetes-master01 service]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-deployment-6b474476c4-27gqr 1/1 Running 0 7m47s 10.244.2.20
nginx-deployment-6b474476c4-6w5zl 1/1 Running 0 7m47s 10.244.1.52
nginx-deployment-6b474476c4-ww74l 1/1 Running 0 7m47s 10.244.1.51
第五步,随机登录到一个Pod中,查看的DNS记录情况,结果如图所示,会显示后面的所有的关联的Pod的IP,需要用户根据情况,从中选择要访问的具体Pod。
sh-4.4# nslookup nginx-service-headless
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: nginx-service-headless.default.svc.cluster.local
Address: 10.244.1.51
Name: nginx-service-headless.default.svc.cluster.local
Address: 10.244.2.20
Name: nginx-service-headless.default.svc.cluster.local
Address: 10.244.1.52
除了带有标签选择符的无头(Headless)服务,来进行第二个例子,创建一个不带有标签选择符的无头(Headless)服务。
服务最常见的是抽象化对 Kubernetes Pod 的访问,但是它们也可以抽象化其他种类的后端。 实例:
(1)希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。
(2)希望服务指向另一个 名字空间(Namespace) 中或其它集群中的服务。
(3)你正在将工作负载迁移到 Kubernetes。 在评估该方法时,你仅在 Kubernetes 中运行一部分后端。
在任何这些场景中,都能够定义没有选择算符的 Service。 实例:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
clusterIP: None # 无头服务
type: ClusterIP # 此Service类型为ClusterIP
由于此服务没有选择算符,因此不会自动创建相应的 Endpoint 对象。 我们可以通过手动添加 Endpoint 对象,将服务手动映射到运行该服务的网络地址和端口,其中关联的为资源对象Endpoints中的metadata.name字段,需要是我们定义的服务的名字。
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.20.40.150
ports:
- port: 80
说明:
(1)端点 IPs 必须不可以 是:本地回路(IPv4 的 127.0.0.0/8, IPv6 的 ::1/128)或 本地链接(IPv4 的 169.254.0.0/16 和 224.0.0.0/24,IPv6 的 fe80::/64)。
(2)端点 IP 地址不能是其他 Kubernetes 服务的集群 IP,因为 kube-proxy 不支持将虚拟 IP 作为目标。
(3)访问没有选择算符的 Service,与有选择算符的 Service 的原理相同。 请求将被路由到用户定义的 Endpoint,YAML 中为:10.20.40.150:80(TCP)。
将上面的yaml文件,在Kubernetes集群中应用,查看效果,如图所示,这个无头Service的Endpoints已经挂载上了我们定义的10.20.40.150:80的服务上面。
[root@kubernetes-master01 service]# kubectl describe service my-service
Name: my-service
Namespace: default
Labels:
Annotations: Selector:
Type: ClusterIP
IP: None
Port: 80/TCP
TargetPort: 80/TCP
Endpoints: 10.20.40.150:80
Session Affinity: None
Events:
如果你对容器化技术的相关知识感兴趣,可以阅读:秀丽的容器化技术Kubernetes专栏https://blog.csdn.net/jiangxiulilinux/category_10955709.html
本专栏特点: