前言

前文已经部署了高可用的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界面来创建:

截屏2021-04-20 上午11.18.03

这个过程很迅速,就可以看到2个Pod启动成功。

截屏2021-04-20 上午11.19.53

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属性:

截屏2021-04-20 下午3.19.25

如果是Rancher

截屏2021-04-20 下午3.21.57

IP问题

seata-server虽然部署成功,但是注册到Nacos上的IP是Kubernetes内部集群IP:

截屏2021-04-20 上午11.27.40

如此的话,seata客户端应用是无法访问到seata-server服务的,除非nacos和seata客户端应用也部署在Kubernetes集群内部,但显然目前无法进行这么大的变革。所以解决问题的方法就是让seata-server的注册IP是宿主机IP,查阅了seata官方文档,是支持相关配置的:

截屏2021-04-19 下午7.32.53

又查阅了Kubernetes相关的文档:用 Pod 字段作为环境变量的值

根据文档,修改YAML,如下:

截屏2021-04-19 下午7.30.44

使用Rancher配置如下

截屏2021-04-20 上午11.41.50

端口问题

理论上来说,使用Kubernetes部署应用应该无需关心IP和端口的问题,调度的过程应该是无条件的。但是因为我们使用的外部Nacos做服务注册,导致服务间调用必须明确知道服务的IP和端口号,无形中也给Pod的调度加上了条件:

(1)服务数量不能超过集群节点数

(2)端口号不能冲突,每个集群节点上只能部署一个服务

这也是目前架构带来的缺陷,后续如果集成springcloud-kubernetes倒是可以解决。端口问题也是选择HostPort方式的理由之一,Kubernetes获取Pod信息时无法获取端口号,也就无法想Nacos注册正确的端口号。

数据卷配置

数据卷就不细说了,跟Dokcer的概念差不太多,目前我只是映射了日志目录。


朱世伟
7 声望7 粉丝