前言
前文已经部署了高可用的Kubernetes集群以及Rancher集群,这两天正好需要提前部署seata-server,琢磨着正好趁这个风险不大的机会试验一下Kubernetes,特此记录下。
架构描述
在正式部署之前,我有必要描述下现有架构的现状。现有架构主要是基于SpringCloud框架搭建的微服务体系,配置中心和服务注册中心使用的都是阿里的Nacos组件。
从架构转型角度来说,全面切换至Kubernetes为基础的微服务体系肯定不够现实,从现有主流的方案来说,一般是使用Kubernetes做基础措施,利用其做服务编排调度,软件层面还是基于SpringCloud的开发方式,这也是比较现实的逐步切换的方案。
那么目前就架构来说,seata-server会部署在Kuberetes上管理,seata客户端应用使用Docker容器部署,Nacos服务是二进制方式物理安装。seata-server因为没有管理后台,所以并不需要对外暴露服务,只需要seata客户端应用能够进行服务间调用即可。
部署过程
本次过程描述重点并不是怎样部署才能使seata-server能够使用,而是通过Kubernetes部署应用的过程。
Seata官方文档支持Kubernetes的部署方式,并提供了YAML格式的资源文件(因为使用了Nacos方式,使用了自定义文件):
apiVersion: apps/v1
kind: Deployment
metadata:
name: seata-server
namespace: default
labels:
k8s-app: seata-server
spec:
replicas: 1
selector:
matchLabels:
k8s-app: seata-server
template:
metadata:
labels:
k8s-app: seata-server
spec:
containers:
- name: seata-server
image: docker.io/seataio/seata-server:latest
imagePullPolicy: IfNotPresent
env:
- name: SEATA_CONFIG_NAME
value: file:/root/seata-config/registry
ports:
- name: http
containerPort: 8091
protocol: TCP
volumeMounts:
- name: seata-config
mountPath: /root/seata-config
volumes:
- name: seata-config
configMap:
name: seata-server-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: seata-server-config
data:
registry.conf: |
registry {
type = "nacos"
nacos {
application = "seata-server" #根据需要配置nacos信息
serverAddr = "192.168.199.2"
}
}
config {
type = "nacos"
nacos {
serverAddr = "192.168.199.2"
group = "SEATA_GROUP"
}
}
可以通过以下命令提交资源:
kubectl apply -f seata-server.yaml
当然,也可以通过Rancher界面来创建:
这个过程很迅速,就可以看到2个Pod启动成功。
Pod外部访问方式
seata-server作为服务注册至Nacos上,为了满足服务间调用的需要,对应的Pod需要能够被集群外部访问到,这就牵扯到Kubernetes暴露服务的几种方式(粗略说一下):
直接定义Pod网络
hostNetwork: true和hostPort,这两种方法是直接配置Pod的网络,前者相当于直接使用宿主机网络,后者是做容器端口和主机节点端口映射。这种方式的缺点显而易见,由于Pod的调度,必须明确知道当前Pod所在节点的IP才能访问,而且由于指定端口,所以Pod数量不能超过总的集群节点数量。但是在我们这次的使用场景里不会出现这样的问题,seata客户端通过Nacos获取seata-server服务的地址进行调用,即使Pod的IP变化也没有关系,唯一需要注意的就是Pod数量不能超过集群总节点数量。
通过service
NodePort和LoadBalancer,前者在任何情况下都不建议采用,后者是暴露服务到公网的标准方式,详细的这里就不多说了。
Ingress
Ingress 可能是暴露服务的最强大方式, 但同时也是最复杂的。好吧有这句话已经够了,后面再单独研究。
通过以上篇幅其实答案已经有了,在这个场景下,我选择HostPort的方式,具体实现很简单,配置Pod,增加HostPort属性:
如果是Rancher
IP问题
seata-server虽然部署成功,但是注册到Nacos上的IP是Kubernetes内部集群IP:
如此的话,seata客户端应用是无法访问到seata-server服务的,除非nacos和seata客户端应用也部署在Kubernetes集群内部,但显然目前无法进行这么大的变革。所以解决问题的方法就是让seata-server的注册IP是宿主机IP,查阅了seata官方文档,是支持相关配置的:
又查阅了Kubernetes相关的文档:用 Pod 字段作为环境变量的值
根据文档,修改YAML,如下:
使用Rancher配置如下
端口问题
理论上来说,使用Kubernetes部署应用应该无需关心IP和端口的问题,调度的过程应该是无条件的。但是因为我们使用的外部Nacos做服务注册,导致服务间调用必须明确知道服务的IP和端口号,无形中也给Pod的调度加上了条件:
(1)服务数量不能超过集群节点数
(2)端口号不能冲突,每个集群节点上只能部署一个服务
这也是目前架构带来的缺陷,后续如果集成springcloud-kubernetes倒是可以解决。端口问题也是选择HostPort方式的理由之一,Kubernetes获取Pod信息时无法获取端口号,也就无法想Nacos注册正确的端口号。
数据卷配置
数据卷就不细说了,跟Dokcer的概念差不太多,目前我只是映射了日志目录。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。