第四章:服务-让客户端发现pod并与之通信

本章内容包括:

  • 创建服务资源,利用单个地址访问一组pod
  • 发现集群中的服务
  • 将服务公开给外部客户端
  • 从集群内部连接外部服务
  • 控制pod与服务关联
  • 排除服务故障

上一章学习了如何通过ReplicaSet以及类似的资源部署运行pod的事。尽管特定的pod可以独立的应对外部刺激,但现在大多数的应用都需要根据外部请求做出响应。例如,就微服务而言,通常需要对集群内部其他应用,以及来自集群外部客户端的HTTP请求做出响应。

pod需要一种寻找其他pod的方法来使用其他pod提供的服务。如果没有kubernetes,系统管理员需要在应用的配置文件中明确指出服务的精确的IP地址或者主机名来配置每个客户端应用,但在kubernetes中不适用这种方法:

  • pod是短暂的:它们随时会启动或者关闭,无论是为了给其他pod提供空间而从节点中移除,或者是pod的副本数增加或减少,以及节点异常导致的pod变动。
  • kubernetes会在pod启动前给已经调度到节点上的pod分配IP地址,因此客户端不可能提前知道提供服务pod的IP地址。
  • 水平伸缩意味着多个pod可以提供相同的服务,每个pod都有自己的地址。
    为了解决以上问题,kubernetes提供了一种解决方法----服务(service)。

1 服务介绍

kubernetes服务是一种为一组功能相同的pod提供单一不变的接入点的资源。当服务存在时,它的IP和端口不会改变。客户端通过IP地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个pod上。通过这种方式,客户端不需要知道每个提供服务的pod的地址,这样这些pod就能被随意的在集群中增加或删除。

举个例子,现在有三个pod对外提供前端服务,一个pod为前端提供后端服务,结合上服务如下图所示:
在这里插入图片描述

2 创建服务

服务的后端可能不止一个pod。服务的连接对所有的后端pod是负载均衡的,可以使用标签选择器来指定哪些pod属于同一组。

创建服务最简单的办法就是使用kubectl expose,但推荐使用yaml描述文件来创建服务。

apiVersion: v1
kind: Service
metadata:
  name: kubia
spec:
  ports:
  - port: 80    # 服务可用端口
    targetPort: 8080  # 转发到的容器端口
    protocol: TCP # 默认TCP,支持TCP/UDP/SCTP
  selector:
    app: kubia   # 转到具有指定标签的pod上,不指定将无法转发流量

以上的yaml创建了一个叫kubia的Service资源,对外开放80端口,将外部请求转发到具有app: kibia标签的pod上的8080端口。

创建好后,我们来查看一下服务的信息

[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   13d

创建好之后,看到SVC有一个集群地址,类型是ClusterIP,这个因为只是集群地址,所以只能集群内部访问。

测试服务

可以通过以下几种方法向服务发送请求:

  • 创建一个pod,它将请求发送到服务的集群IP并记录响应。可以通过查看pod日志检查服务的响应。
  • 使用ssh远程登录到一个Kubernetes节点上使用curl命令。
  • 通过kubectl exec命令在一个已经存在的pod上执行curl命令。

在运行的容器中执行命令

# -- 代表这kubectl命令项的结束
# 如果不适用--,那么后面的-s会被解析成kubectl的选项,意思为连接到一个http://10.96.0.1的API服务器
[root@master ~]# kubectl exec kubia-97qvk -- curl -s http://10.96.0.1
You've hit kubi-gzwik

以上命令在执行时的顺序为:

  • 利用Kubernetes执行curl命令,curl命令向一个后端有三个pod服务的IP发送了HTTP请求;
  • Kubernetes服务代理截取该连接,在三个pod中随机选取一个pod,将请求转发给它;
  • Node.js在pod中运行处理请求,并返回带有pod名称的HTTP响应;
  • curl命令向标准输出打印返回值,该返回值被kubectl截取并打印到主机的标准输出。

会话亲和性

如果执行多次同样的命令,每次都会随机向不同的pod请求。因为服务代理通常将每个连接随机指向选择后端pod中的一个,即使连接来自于同一个客户端。如果想要把同一个客户端IP产生的请求每次都指向同一个pod,可以设置服务的sessionAffinity属性为ClientIP(默认为None)。

apiVersion: v1
kind: Service
metadata:
  name: kubia
spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig: 
	  clientIP: 
		  timeoutSeconds: 3600  # 亲和性过期时间
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: kubia

Kubernetes服务并不支持基于cookie的亲和性,因为服务不在HTTP层面上工作。服务处理TCP和UDP包,并不关心其中的载荷内容,而cookie是HTTP协议中的一部分。Web服务器可能会使用长连接导致就算不设置会话亲和性,请求也每次会打到同一个pod上。

同一个服务暴露多个端口

创建的服务可以暴露一个端口也可以暴露多个端口。创建一个有多端口的服务时,必须给每个端口指定名字。

apiVersion: v1
kind: Service
metadata:
  name: kubia
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: https
    port: 443
    targetPort: 8443
  selector:
    app: kubia

这样创建的服务就能把80端口的流量转发给容器8080端口,443端口转发给8443端口。标签选择器应用基于整个服务,不能对每个端口做单独的配置。如果不同的pod有不同的端口映射关系,需要创建两个服务。

使用命名的端口

可以在pod的定义中给容器端口命名,这样就能在服务的声明中使用名字来指定特定的端口号,这样会使得服务更加清晰。

apiVersion: V1
kind: pod
metadata:
	name: kubia
spec:
	containers:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值