欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

025.掌握Service-SVC基础使用

程序员文章站 2022-03-26 22:55:00
一 Service简介 1.1 Service概念 Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。 1.2 Service定义详解 1 apiVersion: v1 #必须,a ......

一 service简介

1.1 service概念

service是kubernetes的核心概念,通过创建service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

1.2 service定义详解

  1 apiversion: v1		#必须,api版本
  2 kind: service		#必须,类型为service
  3 metadata:			#必须,元数据
  4   name: string		#必须,service名称
  5   namespace: string		#必须,命名空间,默认为default
  6   labels:			#自定义标签属性列表
  7     - name: string
  8   annotations:		#自定义注解属性列表
  9     - name: string
 10 spec:			#必须,详细描述
 11   selector: []		#必须,label selector配置
 12   type: clusterip		#必须,serice类型,详见如下
 13   sessionaffinity: string	#虚拟服务ip地址,当选择type=clusterip时,若不指定,则系统进行自动分配;当type=loadbalancer时,需要指定
 14   ports:			#service需要暴露的端口列表
 15   - name: string		#端口名称
 16     protocol:		#端口协议,支持tcp和udp,默认为tcp
 17     port: int		#服务监听的端口号
 18     targetport: 8080	#需要转发到后端pod的端口号
 19     nodeport: int		#当spec.type=nodeport时,指定映射到物理机的端口号
 20 status:			#当spec.type=loadbalancer时,设置外部负载均衡的地址,用于公有云
 21   loadbalancer:		#外部负载均衡器
 22     ingress:		#外部负载均衡器
 23       ip: string		#外部负载均衡器的ip地址
 24       hostname: string	#外部负载均衡器的主机名
spec.type:service的类型,指定service的访问方式,默认为clusterip。
  • clusterip:虚拟的服务ip地址,该地址用于kubernetes集群内部的pod访问,在node上kube-proxy通过设置的iptables规则进行转发;
  • nodeport:使用宿主机的端口,使能够访问各node的外部客户端通过node的ip地址和端口号就能访问服务;
  • loadbalancer:使用外接负载均衡器完成到服务的负载分发,需要在spec.status.loadbalancer字段指定外部负载均衡器的ip地址,并同时定义nodeport和clusterip,用于公有云。

二 service基本使用

2.1 service的基本用法

一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过tcp/ip机制及监听ip和端口号来实现。
示例:定义一个提供web服务的rc,由两个tomcat容器副本组成,每个容器都通过containerport设置提供服务的端口号为8080。
[root@k8smaster01 study]# cat webapp-rc.yaml
  1 apiversion: v1
  2 kind: replicationcontroller
  3 metadata:
  4   name: webapp
  5 spec:
  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
[root@k8smaster01 study]# kubectl create -f webapp-rc.yaml
[root@k8smaster01 study]# kubectl get pods -l app=webapp -o yaml | grep podip
podip: 172.24.9.88
podip: 172.24.9.199
[root@k8smaster01 study]# curl 172.24.9.88:8080

直接通过pod的ip地址和端口号可以访问到容器应用内的服务,但是pod的ip地址是不可靠的,例如当pod所在的node发生故障时,pod将被kubernetes重新调度到另一个node,pod的ip地址将发生变化。
如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。kubernetes中的service就是用于解决这些问题的核心组件。
service示例:以如上webapp应用为例,为了让客户端应用访问到两个tomcat pod实例,可以创建一个service来提供服务。kubernetes提供了一种快速的方法,即通过kubectl expose命令来创建service。
[root@k8smaster01 study]# kubectl expose rc webapp
[root@k8smaster01 study]# kubectl get svc | grep -e 'name|webapp'
name type cluster-ip external-ip port(s) age
webapp clusterip 10.10.10.51 <none> 8080/tcp 45s
[root@k8smaster01 study]# curl 10.10.10.51:8080 #测试访问
提示:如上service地址10.10.10.51:8080的访问被自动负载分发到后端两个pod。
service示例2:通过service配置文件暴露服务。
[root@k8smaster01 study]# vi webappsvc.yaml
  1 apiversion: v1
  2 kind: service
  3 metadata:
  4   name: webappservice
  5 spec:
  6   ports:
  7   - port: 8081
  8     targetport: 8080
  9   selector:
 10     app: webapp
[root@k8smaster01 study]# kubectl create -f webappsvc.yaml
[root@k8smaster01 study]# kubectl get svc | grep -e 'name|webappser'
name type cluster-ip external-ip port(s) age
webappservice clusterip 10.10.10.83 <none> 8081/tcp 22s
提示:如上service定义中的关键字段是ports和selector。本例中ports定义部分指定了service所需的虚拟端口号为8081,由于与pod容器端口号8080不一样,所以需要再通过targetport来指定后端pod的端口号。selector定义部分设置的是后端pod所拥有的label:app=webapp。
[root@k8smaster01 study]# curl 10.10.10.83:8081 #访问测试
  • service负载分发策略:roundrobin和sessionaffinity
    • roundrobin:轮询模式,即轮询将请求转发到后端的各个pod上。
    • sessionaffinity:基于客户端ip地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到后端的某个pod上,之后从相同的客户端发起的请求都将被转发到后端相同的pod上。
在默认情况下,kubernetes采用roundrobin模式对客户端请求进行负载分发,同时可以通过设置service.spec.sessionaffinity=clientip来启用sessionaffinity策略。这样,同一个客户端ip发来的请求就会被转发到后端固定的某个pod上了。
通过service的定义,kubernetes实现了一种分布式应用统一入口的定义和负载均衡机制。service还可以进行其他类型的设置,例如设置多个端口号、直接设置为集群外部服务,或实现为headless service(无头服务)模式。

2.2 多端口service

有时一个容器应用也可能提供多个端口的服务,那么在service的定义中也可以相应地设置为将多个端口对应到多个应用服务。
示例1:如下,service设置了两个端口号,并且为每个端口号都进行了命名。
[root@k8smaster01 study]# vi twoportservice.yaml
  1 apiversion: v1
  2 kind: service
  3 metadata:
  4   name: webapp
  5 spec:
  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
[root@k8smaster01 study]# vi kubednsservice.yaml
  1 apiversion: v1
  2 kind: service
  3 metadata:
  4   name: kube-dns
  5   namespace: kube-system
  6   labels:
  7     k8s-app: kube-dns
  8     kubernetes.io/cluster-service: "true"
  9     kubernetes.io/name: "kubedns"
 10 spec:
 11   selector:
 12     k8s-app: kube-dns
 13   clusterip: 169.169.0.100
 14   ports:
 15   - name: dns
 16     port: 53
 17     protocol: udp
 18 
 19   - name: dns-tcp
 20     port: 53
 21     protocol: tcp

2.3 外部服务service

在某些环境中,应用系统需要将一个外部数据库、另一个集群或namespace中的服务作为服务的后端,则可通过创建一个无label selector的service来实现。
[root@k8smaster01 study]# vi noselectorservice.yaml
  1 apiversion: v1
  2 kind: service
  3 metadata:
  4   name: my-service
  5 spec:
  6   ports:
  7   - protocol: tcp
  8     port: 80
  9     targetport: 80
[root@k8smaster01 study]# kubectl create -f noselectorservice.yaml
如上定义创建的是一个不带标签选择器的service,即无法选择后端的pod,系统不会自动创建endpoint,因此需要手动创建一个和该service对应的endpoint,用于指向实际的后端访问地址。
如下所示的endpoint的定义文件:
[root@k8smaster01 study]# vi noselectorendpoint.yaml
  1 apiversion: v1
  2 kind: endpoints
  3 metadata:
  4   name: my-service
  5 subsets:
  6 - addresses:
  7   - ip: 47.96.145.131
  8   ports:
  9   - port: 80
[root@k8smaster01 study]# kubectl create -f noselectorendpoint.yaml
[root@k8smaster01 study]# kubectl get svc | grep -e 'name|my-service'
name type cluster-ip external-ip port(s) age
my-service clusterip 10.10.10.211 <none> 80/tcp 3s
[root@k8smaster01 study]# curl 10.10.10.211
025.掌握Service-SVC基础使用
提示:如上所示,访问没有标签选择器的service和带有标签选择器的service一样,请求将会被路由到由用户手动定义的后端endpoint上。

三 headless service

3.1 无头服务简介

在某些应用场景中,若需要人为指定负载均衡器,不使用service提供的默认负载均衡的功能,或者应用程序希望知道属于同组服务的其他实例。kubernetes提供了headless service来实现这种功能,即不为service设置clusterip(入口ip地址),仅通过label selector将后端的pod列表返回给调用的客户端。
此场景中,service就不再具有一个特定的clusterip地址,对其进行访问将获得包含label“app=nginx”的全部pod列表,然后客户端程序自行决定如何处理这个pod列表。
例如,statefulset就是使用headless service为客户端返回多个服务地址的。
对于“去中心化”类的应用集群,headless service非常适合。

3.2 nginx场景实验

通过对headless service搭建nginx集群,从而自动实现应用集群的创建。
[root@k8smaster01 study]# vi nginx-service.yaml #创建service
  1 apiversion: v1
  2 kind: service
  3 metadata:
  4   labels:
  5     name: nginx-svc
  6   name: nginx-svc
  7 spec:
  8   ports:
  9   - protocol: tcp
 10     port: 80
 11     targetport: 80
 12   selector:
 13     name: nginx-demo			#定义selector
 14   clusterip: none
[root@k8smaster01 study]# kubectl create -f nginx-service.yaml
[root@k8smaster01 study]# vi nginx-deployment.yaml
  1 apiversion: apps/v1
  2 kind: deployment
  3 metadata:
  4   labels:
  5     name: nginx-demo
  6   name: nginx-demo
  7 spec:
  8   replicas: 2
  9   selector:
 10     matchlabels:
 11       name: nginx-demo
 12   template:
 13     metadata:
 14       labels:
 15         name: nginx-demo
 16     spec:
 17       containers:
 18       - name: nginx
 19         image: nginx:1.7.9
 20         ports:
 21         - containerport: 80
 22           name: web
[root@k8smaster01 study]# kubectl create -f nginx-deployment.yaml
[root@k8smaster01 study]# kubectl create -f nginx-service.yaml
[root@k8smaster01 study]# kubectl get svc -o wide
[root@k8smaster01 study]# kubectl get pods -o wide
[root@k8smaster01 study]# nslookup nginx-svc.default.svc.cluster.local 10.10.190.170
025.掌握Service-SVC基础使用
提示:由上可知,通过解析svc的地址,直接解析出来的为pod的ip。