一、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节点之间通讯的端口是28883888,确实也不需要负载均衡以及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:

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐