3.6 控制器之Service

一、Service类型

1. ClusterIP类型

在这里插入图片描述
如上图所示,ClusterIP把客户端的请求通过负载均衡路由到集群后端的pod中,ClusterIP类型的service主要在每个node节点上使用ipvs,将发到ClusterIP service端口的数据,转发到后端pod的kube-proxy中,然后kube-proxy内部实现负载均衡方法,查询到ClusterIP service下对应的pod的地址和端口,进而把数据转发给对应pod的地址和端口。
k8s实现上述数据请求转发的原理如下图所示:
当执行kubectl create 命令后,向apiServer发送了创建ClusterIp service的命令,然后apiServer把创建后的数据存储到etcd中;
每一个node节点都有一个kube-proxy进程,该进程负责监控etcd的变化,即感知service的变化,然后把路由规则写入到pod中的ipvs规则中,ipvs使用NAT技术把流量转发至pod中。
在这里插入图片描述
应用示例如下:
首先建立一个deployment.yaml用于部署多个pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeployment
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
    spec:
      containers:
      - name: myapp
        image: mynginx:v0.3
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80

然后创建一个ClusterIp service,实现负载均衡

apiVersion: v1
kind: Service
metadata:
  name: myservice
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 8080
    targetPort: 80

分别创建资源如下:

#创建development
[root@k8s-master01 cluster_work]# kubectl apply -f deployment.yaml 
deployment.apps/mydeployment created

#创建service
[root@k8s-master01 cluster_work]# kubectl apply -f cluster_service.yaml 
service/myservice created

#查询pod及IP
[root@k8s-master01 cluster_work]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
mydeployment-67667dddf9-gbl8c   1/1     Running   0          15s   10.244.2.99    k8s-node02   <none>           <none>
mydeployment-67667dddf9-nzzxc   1/1     Running   0          15s   10.244.1.102   k8s-node01   <none>           <none>
mydeployment-67667dddf9-tj896   1/1     Running   0          15s   10.244.2.98    k8s-node02   <none>           <none>

#查询创建的myservice,集群地址为10.107.4.138
[root@k8s-master01 cluster_work]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP    2m12s
myservice    ClusterIP   10.107.4.138   <none>        8080/TCP   8s

#请求service
[root@k8s-master01 cluster_work]# curl 10.107.4.138:8080
hello lzj, this is version 3

通过上述命令,已经请求到服务,下面通过ipvsadm -Ln查看一下路由规则,发现10.107.4.138:8080路由到了10.244.2.99:80、10.244.2.98:80、10.244.1.102:80
在这里插入图片描述
I

2、NodePort类型

NodePort类型的服务,在创建Service的时候将服务类型设置NodePort即可。设置服务类型为NodePort时,集群会在每个节点上打开一个端口,可以通过节点的IP+节点端口访问节点,然后节点把流量重定向到集群的Service服务,最后通过集群的IP+集群端口,负债均衡到后端的Pod应用。当服务类型设置为NodePort时,外部流量不仅可以通过集群IP+端口访问后端Pod应用,还可以通过节点的Ip+端口访问集群服务,然后通过集群服务负载到后端Pod应用中。
在这里插入图片描述
示例如下,deployment继续用上面的mydeployment,下面创建NodePort类型的yaml文件nodeport.yaml

apiVersion: v1  		#版本
kind: Service  			#资源类型
metadata:
  name: mynodeport 		#service资源的名字
  namespace: default 	#资源的名称空间
spec:
  type: NodePort 		#服务类型NodePort
  selector:  			#pod标签选择器
    app: myapp
    release: stabel
  ports:
  - name: http  		#端口名称别名
    port: 8080  		#集群对外暴露的端口,通过该端口可以访问集群
    targetPort: 80 		#pod端口
    nodePort: 31463 	#集群节点端口,通过该端口可以访问集群服务
#创建服务
[root@k8s-master01 cluster_work]# kubectl apply -f nodeport.yaml 
service/mynodeport created

#查询服务,mynodeport即为新创建的服务
[root@k8s-master01 cluster_work]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          2d23h
mynodeport   NodePort    10.106.33.216   <none>        8080:31463/TCP   16s

#通过节点IP+节点暴露端口访问服务
[root@k8s-master01 cluster_work]# curl 192.168.137.100:31463
hello lzj, this is version 3
[root@k8s-master01 cluster_work]# curl 192.168.137.10:31463
hello lzj, this is version 3
[root@k8s-master01 cluster_work]# curl 192.168.137.20:31463
hello lzj, this is version 3

#通过集群IP+集群端口访问后端pod应用
[root@k8s-master01 cluster_work]# curl 10.106.33.216:8080
hello lzj, this is version 3

3. ExternalName类型服务

service集群可以将集群外部的服务暴露给集群内部的pod,当pod访问集群外部的服务时只需要访问service服务即可,当外部的服务地址变化时,只需要重新把外部服务的地址绑定在service,在service中创建endpoit即可。如下图所示
在这里插入图片描述
上述服务即为Service中的ExternalName类型服务,在创建服务资源时需要将type设置为ExternalName。如下yaml所示

apiVersion: v1
kind: Service
metadata:
  name: external-svc-endpoint
spec:
  type: ExternalName
  externalName: www.baidu.com
  ports:
  - name: http
    port: 80

当服务创建完成后,集群内的pod可以通过external-svc-endpoint.default.svc.cluster.local域名访问www.baidu.com,这样pod就直接访问到了外部的服务。

4、Headless服务

上述创建Cluster Service,客户端访问Cluster Service后端的pod服务时,先访问Cluster IP,然后Cluster IP负载到后端的pod。但如果客户端访问pod时不需要通过Cluster Ip,而是直接访问到后端的pod,通过本节的headless服务即可实现该功能。headless为无头服务,即把ClusterIp字段设置为None即可。客户端访问后端pod时,可以通过coreDNS查找pod的IP,可以由多个pod。coreDNS会返回多个pod的IP,然后客户端直接链接到后端的pod。客户端访问后端pod时,如果有多个pod,客户端只能通过轮询后端pod的方式进行访问,没有其它负载方式。

4.1 创建headless无头服务

创建headless时只需把clusterIP字段设置成None,其它保持与Cluster IP类型的服务保持一致。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-headless
spec:
  clusterIP: None   	#无头服务
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx

通过yaml文件创建Deployment和Service后,查看headless服务,发现已经创建了三个访问点Endpoints: 10.244.2.215:80,10.244.2.216:80,10.244.2.217:80,正是三个pod的地址和端口。

[root@k8s-master01 headless_work]# kubectl describe service nginx-headless
Name:              nginx-headless
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"nginx-headless","namespace":"default"},"spec":{"clusterIP":"None"...
Selector:          app=nginx
Type:              ClusterIP
IP:                None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.215:80,10.244.2.216:80,10.244.2.217:80 + 1 more...
Session Affinity:  None
Events:            <none>

4.2 无头服务发现未就绪pod

客户端访问后端pod服务时,通过coreDNS解析pod的地址后,提供给客户端进行访问,
只需在service.spec.publishNotReadyAddresses字段设置true值,表示pod未准备就绪的也添加到coreDNS解析的列表中,该字段默认false,表示未准备就绪的pod不会添加到coreDNS解析列表,客户端是请求不到未准备就绪的pod。

apiVersion: v1
kind: Service
metadata:
  name: nginx-headless
spec:
  clusterIP: None
  publishNotReadyAddresses: true 	#未准备就绪的pod添加到DNS解析列表中,未就绪的pod也就开始提供服务了
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值