中间件容器化部署实现方案的前期调研

原创 吴就业 160 0 2023-05-27

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/19553f0725bf45bf92a014aa4c071de7

作者:吴就业
链接:https://wujiuye.com/article/19553f0725bf45bf92a014aa4c071de7
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

中间件容器化部署是为了实现GitOps模式的持续交付,实现部署即代码。痛点在于大多数中间件都是有状态的,本篇介绍如何实现有状态中间件的容器化部署。

常见中间件要实现容器化部署,需要解决以下问题:

  1. 对于网关类中间件,作为流量入口,虽然是无状态类型的中间件,但由于需要提供固定ip配置SLB,因此容器化部署就需要解决固定ip的问题。
  2. 对于存储类中间件,是有状态类型的中间件,容器重启后需要能访问同一个“持久化存储设备”,数据不容忍丢失,因此容器化部署需要解决持久化存储问题。

网关项目容器化部署解决方案

关于Ingress Controller

Ingress是k8s提供将集群内部服务(Service)暴露外部访问的定义http路由规则的资源,Ingress资源本身只是定义http路由策略,需要依赖Ingress Controller实现Ingress资源的路由策略。

Ingress Controller本身也是一个Service,通过设置Service的类型为NodePort(使用节点IP)或者ExternalIP、云服务提供商提供的LoadBalancer暴露给外部访问。 ingress原理图

BFE Ingress Controller

BFE Ingress Controller是基于BFE实现的Ingress Controller,用于支持在Kubernetes中部署使用BFE进行七层流量代理转发,并能使用Ingress进行流量接入。

BFE Ingress Controller通过监听Service、Endpoints、Secrets、Namespace资源实现服务发现,TLS证书配置;通过监听Ingress资源触发生成新的配置文件并Reload,将Ingress资源定义的http/https路由规则转为bfe的路由配置,并通过调用bfe暴露的基于http协议的local reload接口通知bfe进程刷新配置。

示例:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-http-ingress
  annotations:
    kubernetes.io/ingress.class: bfe  
spec:
  tls:
  - hosts:
      - test.com
      secretName: test-com-tls-secret
  rules:
  - host: test.com
    http:
      paths:
      - path: /api/user
        pathType: Prefix
        backend:
          service:
            name: test-user
            port:
              number: 8080

此示例的意思是,配置一个Ingress资源,名称为test-http-ingress,ingress类型是bfe(标识该Ingress由BFE Ingress Controller处理),配置了一个host路由规则,将通过test.com域名访问,且路径前缀为/api/user的http请求转发给test-user服务的8080端口。还为test.com配置了tls证书,对应的secret资源名称为test-com-tls-secret。

Nginx Ingress Controller

Nginx Ingress Controller是基于Nginx实现的Ingress Controller,用于支持在Kubernetes中部署使用Nginx进行流量代理转发,并能使用Ingress进行流量接入。原理同前面介绍的BFE Ingress Controller。

示例:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-http-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - test.com
    secretName: test-com-tls-secret
  rules:
  - host: test.com
    http:
      paths:
      - path: /api/user
        pathType: Prefix
        backend:
          service:
            name: test-user
            port:
              number: 8080

此示例的意思是,配置一个Ingress资源,名称为test-http-ingress,ingress类型是nginx(标识该Ingress由Nginx Ingress Controller处理),配置了一个host路由规则,将通过test.com域名访问,且路径前缀为/api/user的http请求转发给test-user服务的8080端口。同样还为test.com配置了tls证书,对应的secret资源名称为test-com-tls-secret。

总结

使用Ingress实现流量入口是k8s的推荐方案,只需要为域名配置tls secret资源、ingress资源,配置路由规则,就可以由Ingress Controller将流量转发给后端服务。每新增一个微服务只需要创建一个Ingress资源。

Ingress Controller只是让网关实现Ingress资源描述的能力,真是解决将网关暴露给外网访问,解决静态IP问题的,是将Ingress Controller的Service的类型配置为LoadBalancer,利用云服务提供商实现的LoadBalancer解决静态IP问题。或是将Ingress Controller的Service的类型配置为NodePort,可使用任意一个Pod所在的Node的IP访问;如果是ExternalIP,则使用ExternalIP访问。如果是私有云,可自己实现LoadBalancer。

Ingress Controller本质也是CRD(自定义资源定义)+ 自定义Controller(即Operator),只不过这是k8s官方提供的资源定义(Ingress),并将实现Ingress资源描述的功能的自定义控制器称为Ingress Controller,因此不叫Operator。目前istio、nginx、bfe、kong、haproxy等流量网关都提供了Ingress Controller的实现。

数据存储中间件容器化部署解决方案

数据存储中间件才涉及到数据的持久化存储,因此持久化存储解决方案,就是解决数据存储中间件容器化的方案。

在k8s集群上部署有状态应用

通常需要持久化存储且对数据一致性0容忍的应用都是有状态应用。k8s提供StatefulSet控制器用来部署有状态应用,它管理具有唯一身份标识的多个pod(每个pod都有一个持久化的、唯一的ID),每个 pod 可以有自己的持久化存储卷。即便StatefulSet中的单个pod发生故障,持久化的pod标识符能够将现有的Volume(卷)与Kubernetes新启的pod进行匹配,以取代发生故障的pod。

持久化存储Volume

K8S支持静态PV和动态PV:

一、通过使用远程块存储实现计算存储分离

可以利用rdb、cephfs的k8s StorageClass,将mysql、kafka的数据存储到远程块存储/分布式文件系统。

CephFS-Provisioner

cephfs-provisioner是kubernetes官方社区提供的Cephfs的StorageClass支持,主要watch kubernetes中PVC资源的 CURD事件,然后创建PV。 cephfs-provisioner工作原理图

RBD-Provisioner

rbd-provisioner是kubernetes官方社区提供的Ceph RBD的StorageClass支持,主要watch kubernetes中PVC资源的 CURD事件,然后创建PV。

二、通过节点亲和性实现持久化存储

在申请资源的时候,按照虚拟机部署的规格去购买虚拟机,满足CPU、内存、硬盘的要求,将购买的节点加入k8s集群,并为这些节点打标签。

例如,部署mysql的节点,标签设置为mysql-node,这样编写mysql的StatefulSet时,通过配置节点亲和性,将pod部署到mysql-node节点上。

但是该方案无法实现计算存储分离,动态扩缩容显的无能为力。另外要求其它pod不能部署到这几个节点。

总结

使用PV+PVC方式,实际就是挂载一个远程文件系统/块存储设备,存在网络I/O性能开销,具体性能影响,要看远程文件系统/块存储设备的实现原理,可能会利用本地磁盘暂存+内存缓存减少一些网络I/O的开销,但肯定比不上使用节点本地磁盘,并且出现问题较难排查,需要有这方面的专家才敢这么去做。因此对于Mysql这类有状态的中间件,我们目前还是当成IaC资源申请使用,不考虑容器化部署。

#云原生

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

Operator实战2:实现webhook修改Job的最大重试次数

terraform-controller默认Job会一直重试,导致重复申请资源。

Operator实战1:使用kubebuilder开发一个部署web服务的Operator

举一个非常简单的需求场景,仅用于介绍如何使用kubebuilder开发一个Operator,非真实需求场景。

中间件云原生利器:Operator,Operator是什么?

新的云原生中间件很难短时间内覆盖到企业项目中,企业走云原生这条道路,还需要考虑传统中间件如何上云的问题。最需要解决的是如何容器化部署,以及自动化运维。这就不得不借助Operator了。

从2023年北京站全球架构师峰会看云原生发展趋势

Serverless、ServiceMesh是2023年全球架构师峰会(北京站)出现频率最高的词,本篇将从这两个方面分享笔者参会了解到的一些信息。

云原生企业级实战笔记专栏开篇介绍

在实战的过程中,我自己做了很多笔记,从模糊到清晰,逐渐了解云原生架构,不仅参与了中间件容器化架构改造与自动化部署Operator开发,还参与了IaC基础设施即代码的开发,kubevela terraform Addon插件开发,从应用层到中间件到基础设施都有参与,整条链路的一些核心原理都非常清晰。