kubernetes实战之四(Service)
kubernetes中的核心要素Service提供了一套简化的服务代理和发现机制,天然适应微服务架构,任何应用都可以非常轻易地运行在kubernetes中而无需对架构进行改动。
kubernetes中的Service是一种抽象概念,它定义了一个Pod逻辑集合以及访问它们的策略,Service和Pod之间的关联同样是通过Label来完成的。
Service的目标是提供一种桥梁,它会为访问者提供了一个固定访问地址,用于在访问时重定向到相应的后端,这使得非kubernetes原生应用程序,在无须为kubernetes编写特定代码的前提下,轻松访问后端。
一、Service基本定义
1.首先定义Replication Controller文件:my-nginx-rc.yaml
apiVersion:v1
kind:ReplicationController
metadata:
name:my-nginx
spec:
replicas:2
selector:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
-name:nginx
image:nginx
ports:
-containerPort:80
通过定义文件创建Replication Controller:
$kubectl create -f my-nginx-rc.yaml
2.其次定义Service文件:my-nginx-service.yaml
apiVersion:v1
kind:Service
metadata:
name:my-nginx
spec:
selector:
app:nginx
ports:
-port:80
targetPort:80
protocol:TCP
主要要素说明:
1.apiVersion:声明kubernetes的API版本,目前是v1。
2.kind:声明API对象的类型,这里类型是Service。
3.metadata:设置Service的元数据。
3.1.name:指定Service的名称,名称必须在Namespace内唯一
4.spec:配置Service的具体规格。
4.1.Selector:指定Service的Label Selector来匹配Pod的Label。
4.2.ports:设置Service的端口转发规则。
4.2.1.port:Service的端口
4.2.2.targetPort:被转发的后端端口
二、Service的基本操作
1.通过定义文件创建Service
$kubectl create -f my-nginx-service.yaml
也可以通过kubectl expose创建Service:
$kubectl expose relicationcontroller my-nginx --name=my-nginx --port=80 --target-port=80
2.查询Service
$kubectl get service my-nginx
3.查询Service详情
$kubectl describe service my-nginx
service作为Pod的访问入口,起到代理服务器的作用,而对于访问者来说,通过Service进行访问,无须直接感知Pod。
三、Service的虚拟IP
kubernetes分配给Service一个固定IP,这是一个虚拟IP(也称为ClusterIP),并不是一个真实存在的IP,而是由kubernetes虚拟出来的。
虚拟IP的范围通过kubernetes API Service的启动参数--service-cluster-ip-range配置。在Service定义中可以通过.spec.clusterIP指定虚拟IP,指定的IP必须在指定范围内,并且该虚拟IP未被分配使用。
虚拟IP属于kubernetes内部的虚拟网络,外部是寻址不到的。在kubernetes系统中,实际上是由kubernetes Proxy组件负责实现虚拟IP路由和转发的,所以kubernetes Node中我们都运行了kubernetes Proxy,从而在容器覆盖网络之上又实现了kubernetes层级的虚拟转发网络。
四、服务代理
在逻辑层面上,Service可以被认为是真实应用的抽象,每一个Service关联着一系列的Pod。在物理层面上,Service又是真实应用的代理服务器,对外表现为一个单一访问入口,通过kubernetes Proxy转发请求到Service关联的Pod。
Service同样是根据Label Selector来筛选Pod进行关联的,实际上kubernetes在Service和Pod之间通过Endpoints衔接,Endpoints同Service关联的Pod对应,可以认为是Service的服务代理后端,kubernetes会根据Service关联到的Pod的PodIP信息组合成一个Endpoints。
1.kubernetes创建Service的同时,会自动创建跟Service同名的Endpoints。
查看service对应的endPoints的配置文件:
$kubectl get endPoints my-nginx -o yaml
2.Service不仅可以代理Pod,还可以代理任意其他后端,比如运行在kubernetes外部的服务。
假设现在要使用一个Service代理外部MySQL服务,不用设置Service的Label Selector。
2.1.Service的定义文件:mysql-service.yaml:
apiVersion:v1
kind:Service
metadata:
name:mysql
spec:
ports:
-port:3036
targetPort:3036
protocol:TCP
2.2.同时定义跟Service同名的Endpoints,Endpoints中设置了MySQL的IP:192.168.3.180,Endpoints的定义文件mysql-endpoints.yaml:
apiVersion:v1
kind:Endpoits
metadata:
name:mysql
subsets:
-addresses:
-ip:192.168.3.180
ports:
-port:3036
protocol:TCP
通过定义文件创建Service和Endpoints:
$kubectl create -f mysql-service.yaml -f mysql-endPoints.yaml
当Service的Endpoints包含多个IP的时候,即服务代理存在多个后端,将进行请求的负载均衡,默认的负载均衡策略是轮询或者随机(根据kubernetes Proxy的模式决定)。
五、服务发现
kubernetes提供了强大的服务编排能力,微服务化应用的每一个组件都以Service进行抽象,组件和组件之间只需要访问Service即可用相互通信,而无需感知组件的集群变化。同时kubernetes为Service提供了服务发现的能力,组件和组件之间可以简单地相互发现。
kubernetes中支持两种服务发现方法:环境变量和DNS。
1.环境变量
当有Pod被创建的时候,kubernetes将为Pod设置每一个Service的相关环境变量,这些环境变量包括两种类型:
1.1.kubernetes Service环境变量
kubernetes为Servic设置的环境变量形式,包括:
{SVCNAME}_SERVICE_HOST
{SVCNAME}_SERVICE_PORT
{SVCNAME}_SERVICE_PORT_{PORTNAME}
其中的服务名和端口名转为大写,连字符转换为下划线。
1.2.Docker Link环境变量
相当于通过Docker的--link参数实现容器连接时设置的环境变量形式。
环境变量服务发现方式是kubernetes默认支持的,但是这种方式存在限制。
1.首先环境变量是租户隔离的,即Pod只能获取同Namespace中的Service环境变量。
2.其次Pod和Service的创建顺序是有要求的,即Service必须在Pod创建之前被创建,否则Service环境变量不会设置到Pod中。DNS服务发现方式则没有这些限制。
2.DNS方式
DNS服务发现方式需要kubernetes提供Cluster DNS支持,Cluster DNS会监控kubernetes API,为每一个Service创建DNS记录用于域名解析,这样在Pod中就可以通过DNS域名获取Service的访问地址。而对于一个Service,Cluster DNS会创建两条DNS记录:
[service_name].[namespace_name].[cluster_domain]
[service_name].[namespace_name].svc.[cluster_domain]
如何通过Cluster DNS进行Service的域名解析,需要了解Linux的DNS域名解析机制。
Pod中的容器使用容器宿主机的DNS域名解析配置,称为默认DNS配置。另外,如果kubernetes部署并设置了Cluster DNS支持,那么在创建Pod的时候,默认会将Cluster DNS的配置写入Pod中的DNS域名解析配置中,称为Cluster DNS配置。
六、发布Service
Service的虚拟IP是由kubernetes虚拟出来的内部网络,外部网络是无法寻址到的,但是有一些Service又需要对外暴露,比如Web前端。这时候就需要增加一层网络转发,即外网到内网的转发。
kubernetes提供了NodePort Service、LoadBalance Service和Ingress可以发布Service。
1.NodePort Service
NodePort Service是类型为NodePort的service,kubernetes除了会分配给NodePort Service一个内部虚拟IP,另外会在每个Node上暴露端口NodePort,外部网络可以通过[NodeIP]:[NodePort]访问到Service。
定义一个文NodePort Service件my-nginx-nodeport-service.yaml
apiVersion:v1
kind:Service
metadata:
name:my-nginx
spec:
selector:
app:nginx
ports:
-port:80
targetPort:80
protocol:TCP
type:NodePort
在NodePort Service定义中可以通过.spec.ports[].nodePort指定固定NodePort,NodePort的范围默认是30000~32767,可以通过kubernetes API Service的启动参数--service-node-port-range指定范围。
NodePort Service就可以通过[NodeIP]:[NodePort]访问,而当NodeIP是一个公网IP时,外部就可以访问到NodePort Service了。
2.LoadBalancer Service
LoadBalancer Service是类型为LoadBalancer的Service,LoadBalancer Service是建立在NodePort Service集群上的,kubernetes会分配给LoadBalancer Service一个内部的虚拟IP,并且暴露NodePort。除此之外,kubernetes请求底层云平台创建一个负载均衡器,将每个Node作为后端,负载均衡器将转发请求到[NodeIP]:[NodePort]。
LoadBalancer Service需要底层云平台支持创建负载均衡器,比如GCE。
定义一个文LoadBalancer Service件my-nginx-loadbalancer-service.yaml
apiVersion:v1
kind:Service
metadata:
name:my-nginx
spec:
selector:
app:nginx
ports:
-port:80
targetPort:80
protocol:TCP
type:LoadBalancer
kubernetes会分配给LoadBalancer Service一个内部的虚拟IP,并且暴露NodePort。进一步的,kubernetes请求底层云平台创建一个负载均衡器,作为访问LoadBalancer Service的外部访问入口。负载均衡器由底层云平台创建提供,会包含一个LoadBalancerIP,可以认为是LoadBalancer Service的外部IP。
3.Ingress
kubernetes提供了一种HTTP方式的路由转发机制,称为Ingress。Ingress的实现需要两个组件支持:Ingress Controller和HTTP代理服务器。HTTP代理服务器将会转发外部的HTTP请求到Service,而Ingress Controller则需要监控kubernetes API,实时更新HTTP代理服务器的转发规则。
定义一个Ingress文件:my-ingress.yaml
apiVersion:extensions/v1betal
kind:Ingress
metadata:
name:my-ingress
spec:
rules:
-host:my.example.com
http:
paths:
-path:/app
backend:
serviceName:my-app
servicePort:80
Ingress定义中的.spec.rules设置了转发规则,其中配置了一条规则,当HTTP请求的host为my.example.com且path为/app时,转发到Service my-app的80端口。
通过定义文件创建Ingress:
$kubectl create -f my-ingress.yaml
创建成功后可以查询Ingress:
$kubectl get ingress my-ingress
当Ingress创建成功后,需要Ingress Controller根据Ingress的配置,设置HTTP代理服务器的转发策略,外部通过HTTP代理服务器就可以访问到Service。
Ingress Controller和HTTP代理服务器是作为外部组件运行的。官方提供了GCE LoadBalancer作为HTTP代理服务器,另外也可以使用HAProxy或者Nginx等开源方案。

浙公网安备 33010602011771号