kubernetes_13_普通Service和无头Service
系列文章目录
文章目录
- 系列文章目录
- 前言
- 一、普通Service
- 2.1 有选择器的普通service
- 2.2 无选择器的普通service
- 二、无头Service
- 2.1 理论:无头Service
- 2.2 实践:无头Service
- 小问题:nslookup:command not found
- 2.3 小结:无头Service
- 2.3.1 常规的service服务和无头服务的区别
- 2.3.2 k8s资源通过Service调用(外部调用和内部调用)
- 2.3.3 无头Service使用两个场景
- 场景1:有状态的中间件场景(使用无头Service识别未就绪的pod)
- 场景2:当不需要负载均衡以及Service IP时可以使用无头Service
- 总结
前言
一、普通Service
2.1 有选择器的普通service
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app.kubernetes.io/name: proxy
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
name: http-web-svc
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app.kubernetes.io/name: proxy
ports:
- name: name-of-service-port
protocol: TCP
port: 80
targetPort: http-web-svc
2.2 无选择器的普通service
步骤1:部署pod
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app.kubernetes.io/name: proxy
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
步骤2:部署service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
步骤3:部署endpoints
apiVersion: v1
kind: Endpoints
metadata:
# 这里的 name 要与 Service 的名字相同
name: nginx-service
subsets:
- addresses:
- ip: 192.168.159.44 # 需要绑定的pod的地址
ports:
- port: 80 # 需要绑定的pod的端口
三个文件 service - endpoint - pod
service 和 endpoint 通过在同一个命名空间里面,使用相同的 metadata.name 绑定
endpoint 和 pod 通过 pod 的虚拟ip和端口绑定
如果删除 endpoints.yaml
二、无头Service
在一个集群中有这个几个组件:pod-a,svc-b,pod-b1,pod-b2。当 pod-a 想访问 pod-b 中的应用程序时,先会把请求打到 svc-b,再由 svc-b 将请求随机转发到 pod-b1或 pod-b2。
如果有个需求:pod-a 需要同时连接到 pod-b1和 pod-b2 ,这时再采用 svc-b 转发显然已经不能满足需求了。那 pod-a 该如何获取到 pod-b1和 pod-b2 的 IP 地址呢?采用 handless service 就可以实现。
2.1 理论:无头Service
有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 “None” 来创建 Headless Service。
无头service相对于普通service的缺点:没有clusterIP,无法负载均衡到绑定的Pod
无头service相对于普通service的优点:
普通servcie,只能给service下面一个pod发消息
无头service,给service下面所有pod发消息
你可以使用一个无头 Service 与其他服务发现机制进行接口,而不必与 Kubernetes 的实现捆绑在一起。
对于无头 Services 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。
带选择算符的服务:对定义了选择算符的无头服务,Endpoints 控制器在 API 中创建了 Endpoints 记录, 并且修改 DNS 配置返回 A 记录(IP 地址),通过这个地址直接到达 Service 的后端 Pod 上。
无选择算符的服务:对没有定义选择算符的无头服务,Endpoints 控制器不会创建 Endpoints 记录。 然而 DNS 系统会查找和配置,无论是:
(1) 对于 ExternalName 类型的服务,查找其 CNAME 记录
(2) 对所有其他类型的服务,查找与 Service 名称相同的任何 Endpoints 的记录
2.2 实践:无头Service
vi service.yaml
# dns-service.yaml
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
name: busybox
clusterIP: None # handless service
ports:
- name: foo
port: 1234
targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
kubectl get all -o wide
nslookup default-subdomain.default.svc.cluster.local 10.96.0.10
普通Service和无头Service使用nslookup的区别:
普通 service 域名获取到的是 service 自己的 IP 地址。
无头 service 域名获取到的是 service 绑定的所有的Pod IP 地址列表(因为无头Service自己没有IP地址)
注意:k8s中有三个和网络相关的系统Pod
proxy 负载均衡,service 绑定 deployment/statefulset/daemonset/job/cronjob
calico 节点之间网络通信
dns 域名解析,包括 ClusterFirst 和 Default
了解:不同的命名空间是有隔离性的。各种资源只能在相同命名空间下,通过标签互相构建连接。所以不同名命空间下可以存在相同名字的标签,互不影响。
小问题:nslookup:command not found
问题:CentOS7 上 nslookup:command not found
# 安装
yum -y install bind-utils
# 测试
nslookup baidu.com
对于nslookup baidu.com
的输出结果
第一段内容为dns地址,包括端口号#DNSD端口号53。
第二段内容为解析结果。
2.3 小结:无头Service
2.3.1 常规的service服务和无头服务的区别
常规的service服务和无头服务的区别
● service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现
● Headless service 无头服务,不需要cluster-IP,clusterIP为None的service,直接绑定具体的Pod的IP,无头服务经常用于statefulset的有状态部署。
注:service资源默认分配给cluster-IP是为了让客户端能访问。而service还提供了pod之间的相互发现,互相访问资源,他们不需要cluster-IP
2.3.2 k8s资源通过Service调用(外部调用和内部调用)
外部调用:通过deployment 资源,生成pod控制器,通过控制器生成一份或多份的pod。同命名空间下,创建service资源,service 资源的yaml 配置连接同命名空间下的那个标签lables的资源,通过此方式连接了刚刚创建的pod控制器资源,同时默认service 资源的yaml 配置生成一个集群IP+port,也就是反向代理后端刚刚连接上的deployment(pod控制器)资源,客户端访问集群IP+port,就会负载均衡的方式访问绑定的pod,通过kube-proxy组件进行资源的调度,负载。
内部调用:内部的资源,比如另一个pod控制器想访问deployment(pod控制器)的资源,由于deployment可能启动多份pod,而且pod的IP也会变化,所以k8s内部资源通过IP方式互相通信是不可能的。但是lables是不变,而serice操作了此过成,通过service资源绑定后,访问service资源的解析地址(nginx-ds.default.svc.cluster.local.)即可进行容器的服务互相发现。调用方式不是集群IP+port
小结:外部访问k8s集群是通过service暴露的 宿主机ip:宿主机port 来完成,k8s集群内部访问是通过 serviceName.namespace 来完成。
2.3.3 无头Service使用两个场景
无头服务使用两个场景:
1、无头服务用于服务发现机制的项目或者中间件,如kafka和zookeeper之间进行leader选举,采用的是实例之间的实例IP通讯。
2、既然不需要负载均衡,则就不需要Cluster IP,如果没有Cluster IP则kube-proxy 不会处理它们, 并且kubernetes平台也不会给他创建负载均衡。
场景1:有状态的中间件场景(使用无头Service识别未就绪的pod)
有状态的中间件场景(识别未就绪的pod)
无头服务有一个很重要的场景是发现所有的pod(包括未就绪的pod),只有准备就绪的pod能够作为服务的后端。但有时希望即使pod没有准备就绪,服务发现机制也能够发现所有匹配服务标签选择器的pod。
比如zk集群,zk节点pod之间必须互相识别之后进行选举,pod状态才会变为就绪,使用无头服务完美的解决这个问题。
场景2:当不需要负载均衡以及Service IP时可以使用无头Service
当不需要负载均衡以及Service IP时
还是以zk场景为例,zk节点之间通讯的端口是2888和3888,确实也不需要负载均衡以及Service IP。而提供给客户端的端口是2181,只有它需要,所以结合以上2个场景:
无头服务(用于zk pod之间彼此的通讯和选举的):
apiVersion: v1
kind: Service
metadata:
name: zk-hs
labels:
app: zk
spec:
# 这使得服务成为无头服务
clusterIP: None
ports:
- port: 2888
name: server
- port: 3888
name: leader-election
selector:
app: zk
正常的service给客户端的(需要负载均衡和cluster ip的):
apiVersion: v1
kind: Service
metadata:
name: zk-cs
labels:
app: zk
spec:
ports:
- port: 2181
name: client
selector:
总结
本文重点是无头Service,这种用的比较少,毕竟默认的Service就是type为ClusterIP,是有头的。
第一,将普通Service和无头Service对比起来,更容易看懂无头Service
第二,从开发中的应用来将无头Service,更容易理解,普通Service是提供给外网访问,无头Service是为了发现所有 selector-label 的Pod.
完!