k8s -- 浅谈什么是service服务、无头服务
server服务:在k8s集群中,service是一个抽象概念,它通过一个虚拟的IP映射指定的端口,将代理客户端发来的请求转到后端一组pod中的一个上。这是个神马意思呢?pod中的容器经常在不停地销毁和重建,因此pod的IP会不停的改变,如果客户端不知道pod的IP已经变化,继续访问之前的IP是无法访问容器。就算客户端知道了pod的IP变化了,每次重建后访问都需要更换IP,效率极为低下。这时候就有
一、service服务:
在k8s集群中,service是一个抽象概念,它通过一个虚拟的IP映射指定的端口,将代理客户端发来的请求转到后端一组pod中的一个上。
这是个神马意思呢?pod中的容器经常在不停地销毁和重建,因此pod的IP会不停的改变,如果客户端不知道pod的IP已经变化,继续访问之前的IP是无法访问容器。就算客户端知道了pod的IP变化了,每次重建后访问都需要更换IP,效率极为低下。这时候就有了service代理服务,类似于nginx代理,作为客户端和pod的中间层,在通过service.yaml 创建service资源后,随机虚拟创建一个固定的ip和port,这时候在创建pod,比如deployment类型的nginx,service资源通过标签选择器查找同名称空间下标签为刚才创建的deployment类型的名字为nginx资源进行绑定,就算pod不停地销毁和重建,并且不管有几个nginx的pod,都会跟这一个固定ip和port绑定,kubernetes内部会时刻更新这组关联关系,客户端访问固定ip和port,后端进行负载均衡机制分别访问不同的nginx的pod。pod的IP会不停的改变,但是service的ip和port不变。
其中上述讲到,如果pod控制器使用rc创建了多个pod副本,service还是固定一个ip和port,客户端访问固定ip和port,后端通过kube-proxy,实现负载均衡
vi service.yaml kind: Service apiVersion: v1 metadata: name: nginx namespace: default spec: ports: - protocol: TCP port: 80 targetPort: 8080 selector: app: nginx
其中这个service代理了所有deglut命名空间下具有app: nginx标签的pod,service资源定义了targetPort,访问我service资源固定IP+8080端口,负载均衡被重定向到后端pod的80端口,使用的TCP协议进行流量访问。 每个node节点都有一个组件kube-proxy,实际上是为service服务的,通过kube-proxy,实现流量从service到pod的转发,kube-proxy也可以实现简单的负载均衡功能。 kube-proxy代理模式:userspace方式:kube-proxy 在节点上为每一个服务创建一个临时端口,service的IP:port 过来的流量转发到这个临时端口上,kube-proxy会用内部的负载均衡机制(轮询),选择一个后端pod,然后建立iptables,把流量导入这个pod里面
其实service在kubernetes版本迭代中,有过几次变更。在kubernetes v1.0 中开始使用userspace proxy mode(用户空间代理态代理模式),kubernetes v1.1增加了iptables代理模式,kubernetes v1.2 默认把iptables当成kube-proxy的代理模式。在kubernetes v1.8 增加了性能更强劲的ipvs proxy mode。
例子:
创建一个nginx的dp和svc,查看过程:
了解:不同的命名空间是有隔离性的。各种资源只能在相同命名空间下,通过标签互相构建连接。所以不同名命空间下可以存在相同名字的标签,互不影响。
[root@hdss7-21 ~]# vi nginx-dp-svc.yaml
apiVersion: v1
kind: Service
metadata:
labels: ## 定义标签
app: nginx-dp ## 定义了svc在标签叫nginx-dp
name: nginx-dp ## 在命名空间下显示这个server资源的名字是nginx-dp
namespace: kube-system ## 在kube-system命名空间下
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-cs ## 标签选择器selector定义了要跟(server同命空间下的标签为nginx-cs的pod容器连接)
sessionAffinity: None
type: ClusterIP
创建server资源:
[root@hdss7-21 ~]# kubectl apply -f nginx-dp-svc.yaml
查看server资源:
[root@hdss7-21 ~]# kubectl get svc -o wide -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-dp ClusterIP 192.168.39.130 <none> 80/TCP 8s app=nginx-cs
[root@hdss7-21 ~]# curl 192.168.39.130:80
curl: (7) Failed connect to 192.168.39.130:80; Connection refused
创建deployment资源:
[root@hdss7-21 ~]# vi nginx-cs-dp.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: nginx-cs ## 定义了标签叫nginx-cs
name: nginx-cs ## 在命名空间下显示这个Deployment资源的名字是nginx-cs
namespace: kube-system ## 在kube-system命名空间下
spec:
replicas: 1
selector:
matchLabels:
app: nginx-cs
template:
metadata:
labels:
app: nginx-cs
spec:
tolerations:
- key: bxj
effect: NoSchedule
containers:
- image: nginx:latest
imagePullPolicy: IfNotPresent
name: nginx
创建Deployment资源:
[root@hdss7-21 ~]# kubectl apply -f nginx-cs-dp.yaml
查看容器,并访问容器80无问题:
[root@hdss7-21 ~]# kubectl get pod -o wide -n kube-system
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-cs-7679bbd57d-9v8p2 1/1 Running 0 8s 172.7.22.8 hdss7-22.host.com <none> <none>
[root@hdss7-21 ~]# curl 172.7.22.8:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
访问server的ClusterIP:
[root@hdss7-21 ~]# kubectl get svc -o wide -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-dp ClusterIP 192.168.39.130 <none> 80/TCP 3m46s app=nginx-cs
[root@hdss7-21 ~]# curl 192.168.39.130:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
给容器缩容为0,在访问server 的ClusterIP:
[root@hdss7-21 ~]# kubectl scale deployment nginx-cs --replicas=0 -n kube-system
[root@hdss7-21 ~]# curl 192.168.39.130:80
curl: (7) Failed connect to 192.168.39.130:80; Connection refused
[root@hdss7-21 ~]#
总结:server资源的标签,命名空间下的名字,都可以随意起。但是命名空间必须跟delpoyment资源是一个,否则无法连接。
二、常规的service服务和无头服务的区别:
常规的service服务和无头服务的区别
● service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现
● Headless service 无头服务,不需要cluster-IP,clusterIP为None的service,直接绑定具体的Pod的IP,无头服务经常用于statefulset的有状态部署。
注:server资源默认分配给cluster-IP是为了让客户端能访问。而server还提供了pod之间的相互发现,互相访问资源,他们不需要cluster-IP
无头服务yaml格式:
apiVersion: v1
kind: Service
metadata:
name: myweb-service
spec:
selector:
python: myweb
type: ClusterIP
clusterIP: None ## 集群IP为None
ports:
- port: 81
targetPort: 80
正常的service的yaml格式:
apiVersion: v1
kind: Service
metadata:
name: myweb-service
spec:
selector:
python: myweb
ports:
- port: 81
targetPort: 80
在yaml中,默认不写代表分配集群ClusterIP,声明None无ClusterIP
进入工具型Pod,并且在pod中查询service的解析地址 {ServiceName}.{Namespace}.svc.{ClusterDomain}
三、无头服务使用场景:
1、无头服务用于服务发现机制的项目或者中间件,如kafka和zookeeper之间进行leader选举,采用的是实例之间的实例IP通讯。
2、既然不需要负载均衡,则就不需要Cluster IP,如果没有Cluster IP则kube-proxy 不会处理它们, 并且kubernetes平台也不会给他创建负载均衡。
四、k8s内部资源互相调用解析:
通过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
解决Debian系统错误:E: Unable to locate package vim_fgx_123456的博客-CSDN博客
[root@7-22 ~]# cat nginx-ds.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ds
spec:
template:
metadata:
labels:
app: nginx-ds
spec:
containers:
- name: my-nginx
image: harbor.od.com:180/public/nginx:v1.7.9
ports:
- containerPort: 80
root@nginx-ds-68w5b:/etc/apt# curl 192.168.189.12
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
...
root@nginx-ds-68w5b:/etc/apt# curl nginx-ds.default.svc.cluster.local. # 容器内部可通过sercie资源访问同命名空间下的其他资源
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
...
root@nginx-ds-68w5b:/etc/apt#
五、无头服务使用环境:
4.1、中间件场景(识别未就绪的pod)
无头服务有一个很重要的场景是发现所有的pod(包括未就绪的pod),只有准备就绪的pod能够作为服务的后端。但有时希望即使pod没有准备就绪,服务发现机制也能够发现所有匹配服务标签选择器的pod。
比如zk集群,zk节点pod之间必须互相识别之后进行选举,pod状态才会变为就绪,使用无头服务完美的解决这个问题。
4.2、当不需要负载均衡
以及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:
更多推荐
所有评论(0)