带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

释放双眼,带上耳机,听听看~!

    Pod的讲解终于告一段落了,现在我们来一起学习Service。      

    Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。本章对Service的使用进行详细说明,包括Service的负载均衡机制、如何访问Service、Headless Service、DNS服务的机制和实践、Ingress 7层路由机制等。

   Service的yaml定义文件完整内容如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1apiVersion: v1        // Required
2kind: Service        // Required
3metadata:            // Required
4  name: string            // Required
5  namespace: string         // Required
6  labels:
7  - name: string
8  annotations:
9  - name: string
10spec:                             // Required
11  selector: []                              // Required
12  type: string                  // Required
13  clusterIP: string
14  sessionAffinity: string
15  ports:
16  - name: string
17    protocol: string
18    port: int
19    targetPort: int
20    nodePort: int
21  status:
22    loadBalancer:
23      ingress:
24        ip: string
25        hostname: string
26

apiVersion
string

v1
kind
string

Service
metadata
object

元数据
metadata.name
string

Service名称
metadata.namespace
string

命名空间,不指定默认为default
metadata.labels[] metadata.annotation[]
list list
 
自定义标签属性列表 自定义注释属性列表
spec
object

详细描述
spec.selector[]
list

label selector配置,将选择具有指定label标签的Pod 作为管理范围
spec.type
string

Service的类型,指定Service的访问方式,默认值为ClusterIP。 1.Cluster IP:虚拟的服务IP地址,该地址用于K8s集群内部的Pod访问,在Node上kube-prox通过设置的optables规则进行转发。 2.NodePort: 使用宿主机的端口,使能够访问各Node的外部客户端通过Node的IP地址和端口号就能访问服务。 3. LoadBalancer: 使用外接负载均衡器完成到服务的负载分发,需要在spec.status.loadBalancer字段指定外部负载均衡器的IP地址,并同时定义nodePort和clusterIP,用于公有云环境。
spec.clusterIP
string
 
虚拟服务IP地址,当type=clusterIP时,如果不指定。这系统进行自动分配,也可以手工指定:当type=loadBalancer时,这需要指定
spec.sessionAffinity
string
 
是否支持Session,可选值为ClusterIP,默认值为空。 clusterIP: 表示同一个客户端的访问请求都转发到同一个后端Pod
spec.ports[]
list
 
Service需要暴露的端口列表
spec.ports[].name
string
 
端口名称
spec.ports[].protocol
string
 
端口协议,支持TCP和UDP。默认为TCP
spec.ports[].port
init
 
服务监听的端口号
spec.ports[].targePort
int
 
需要转发到后端Pod的端口号
spec.ports[].nodePort
int
 
当spec.type=NodePort时,指定映射到物理机的端口号
status
object
 
当spec.type=LoadBalancer时,设置外部负载均衡的地址,用于公有云环境
status.loadBalancer
object
 
外部负载均衡器
status.loadBalancer.ingress
object
 
外部负载均衡器
status.loadBalancer.ingress.ip
string
 
外部负载均衡器的IP地址
status.loadBalancer.ingress.hostname
string
 
外部负载均衡器的主机名

Service 的基本用法

      一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现。例如,定义一个提供Web服务的RC,由两个Tomcat容器副组成,每个容器都通过containerPort设置提供服务的端口号为8080:

webapp-rc.yaml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1apiVersion: v1
2kind: ReplicationController
3metadata:
4  name: webapp
5spec:
6  replicas: 2
7  template:
8    metadata:
9      name: webapp
10      labels:
11        app: webapp
12    spec:
13      containers:
14      - name: webapp
15        image: tomcat
16        ports:
17        - containerPort: 8080
18

创建该RC之后获取该Pod的IP地址


1
2
1kubectl get pod -l app=webapp -o yaml | grep podIP
2

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

可以直接通过这两个Pod的IP地址和端口号访问Tomcat服务:

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

       直接通过Pod的IP地址和端口号可以访问到容器应用内的服务,但是Pod的IP地址是不可靠的,例如当Pod所在的Node发生故障时,Pod将被Kubernetes重新调度到另一个Node,Pod的IP地址将发生变化。更重要的是,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。Kubernetes中的Service就是用于解决这些问题的核心组件。

       以前面创建的webapp应用为例,为了让客户端应用访问到两个Tomcat Pod实例,需要创建一个Service来提供服务。Kubernetes提供了一种快速的方法,即通过kubectl expose命令来创建Service:


1
2
1kubectl expose rc webapp
2

    查看新创建的Service,可以看到系统为它分配了一个虚拟的IP地址(ClusterIP),Service所需的端口号则从Pod中的containerPort复制而来:

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

接下来就可以通过Service的IP地址和Service的端口号访问该Service了:

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

这里,对Service地址10.111.79.254:8080的访问被自动负载分发到了后端两个Pod之一。

      除了使用kubectl expose命令创建Service,我们也可以通过配置文件定义Service,再通过kubectl create命令进行创建。例如对于前面的webapp应用,我们可以设置一个Service,代码如下:


1
2
3
4
5
6
7
8
9
10
11
1apiVersion: v1
2kind: Service
3metadata:
4  name: webapp1
5spec:
6  ports:
7  - port: 8081
8    targetPort: 8080
9  selector:
10    app: webapp
11

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

      Service定义中的关键字段是ports和selector。本例中ports定义部分指定了Service所需的虚拟端口号为8081,由于与Pod容器端口号8080不一样,所以需要再通过targetPort来指定后端Pod的端口号。selector定义部分设置的是后端Pod所拥有的label:app=webapp。

目前Kubernetes提供了两种负载分发策略:RoundRobin和SessionAffinity,具体说明如下:

◎ RoundRobin:轮询模式,即轮询将请求转发到后端的各个Pod上。
◎ SessionAffinity:基于客户端IP地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个Pod上,之后从相同的客户端发起的请求都将被转发到后端相同的Pod上。

       在默认情况下,Kubernetes采用RoundRobin模式对客户端请求进行负载分发,但我们也可以通过设置service.spec.sessionAffinity=ClientIP来启用SessionAffinity策略。这样,同一个客户端IP发来的请求就会被转发到后端固定的某个Pod上了。

       通过Service的定义,Kubernetes实现了一种分布式应用统一入口的定义和负载均衡机制。Service还可以进行其他类型的设置,例如设置多个端口号、直接设置为集群外部服务,或实现为Headless Service(无头服务)模式。

多端口Service

      有时一个容器应用也可能提供多个端口的服务,那么在Service的定义中也可以相应地设置为将多个端口对应到多个应用服务。在下面的例子中,Service设置了两个端口号,并且为每个端口号都进行了命名:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1apiVersion: v1
2kind: Service
3metadata:
4  name: webapp2
5spec:
6  ports:
7  - port: 8080
8    targetPort: 8080
9    name: web
10  - port: 8005
11    targetPort: 8005
12    name: management
13  selector:
14    app: webapp
15

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

另一个例子是两个端口号使用了不同的4层协议—TCP和UDP:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1apiVersion: v1
2kind: Service
3metadata:
4  name: webapp3
5spec:
6  ports:
7  - port: 8080
8    protocol: UDP
9    name: tdp
10  - port: 8080
11    protocol: TCP
12    name: tcp
13  selector:
14    app: webapp
15

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

外部服务Service

     在某些环境中,应用系统需要将一个外部数据库作为后端服务进行连接,或将另一个集群或Namespace中的服务作为服务的后端,这时可以通过创建一个无Label Selector的Service来实现:


1
2
3
4
5
6
7
8
9
10
1kind: Service
2apiVersion: v1
3metadata:
4  name: my-service
5spec:
6  ports:
7  - protocol: TCP
8    port: 80
9    targetPort: 80
10

     

通过该定义创建的是一个不带标签选择器的Service,即无法选择后端的Pod,系统不会自动创建Endpoint,因此需要手动创建一个和该Service同名的Endpoint,用于指向实际的后端访问地址。创建Endpoint的配置文件内容如下:


1
2
3
4
5
6
7
8
9
10
11
1kind: Endpoints
2apiVersion: v1
3metadata:
4  name: my-service
5subsets:
6- addresses:
7  - ip: 1.2.3.4
8  ports:
9  - port: 8080
10
11

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

 

  访问没有标签选择器的Service和带有标签选择器的Service一样,请求将会被路由到由用户手动定义的后端Endpoint上。

带你玩转kubernetes-k8s(第29篇:k8s-深入掌握Service:定义详解)

 

    小结:

            本节内容到此结束,是不是觉得很简单呢?

            觉得简单,说明我们已经入k8s的门了,继续加油!

            多多点关注哦~

            

给TA打赏
共{{data.count}}人
人已打赏
安全运维

故障复盘的简洁框架-黄金三问

2021-9-30 19:18:23

安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索