11、中间件容器化

11、中间件容器化

1. 应用部署的通用步骤

1.1 必须了解要部署的东西

  • 架构:理解应用程序的架构和组件。

  • 配置:知道应用程序需要哪些配置参数。

  • 端口号:确定应用程序使用的端口。

  • 启动命令:了解启动应用程序所需的命令。

1.2 其次要有镜像

  • 镜像谁来做:确定谁负责创建和维护应用程序的镜像。应用是自己公司开发的,还是使用开源的应用。

1.3 找到最合适的部署方式

  • 是否有状态:考虑应用程序是否具有状态,这将影响如何在 Kubernetes 中部署它。

  • 配置分离:将配置文件与代码分开,以便于管理和更新。(如:是通过环境变量还是配置文件)

  • 部署文件来源:从何处获取部署文件,例如 GitHub 或其他版本控制系统。

  • 如何部署:选择适当的部署策略,如滚动升级或蓝绿部署。

1.4 程序如何被使用

  • 什么协议:确定应用程序使用的通信协议。
  • 内部还是外部:考虑应用程序是仅在集群内部使用,还是需要对外提供服务。

2. 中间件单实例部署

2.1 找到官方镜像:

选择带有 management 的稳定版本进行下载,并推送到私有镜像仓库保存

image-20240505192845198

[root@docker ~]# docker tag rabbitmq:3.13.2-management-alpine 10.0.0.138:5000/library/rabbitmq-alpine:3.13.2

[root@docker ~]# docker pull rabbitmq:3.13.2-management-alpine

[root@docker ~]# docker push 10.0.0.138:5000/library/rabbitmq-alpine:3.13.2

2.2 确认需要的配置(环境变量或配置文件):

如下图 rabbitmq(支持环境变量)消息队列是需要做持久化存储的,在后续可以申请动态pvc将文件目录(/var/lib/rabbitmq下)持久化。

image-20240505202518576

下图是redis的启动命令(可在dockerfile中查看) redis目前不支持环境变量只支持配置文件(需要用到ComfigMap)

image-20240505202112583

2.3 选择部署方式(Deployment或其他的):

可使用 ratel 等工具来生成 yaml 文件,也可以手写。

yaml配置文件如下(如果是部署redis可更改 name、镜像以及端口号即可):

[root@k8s-master01 yaml]# kubectl create ns public-service
[root@k8s-master01 yaml]# kubectl apply -f rabbitmq.yaml
apiVersion: v1
kind: Service #如果有ingress服务可以更改配置,或是需要外部机器访问也可改成Nodeport
metadata:
  name: rabbitmq
  namespace: public-service
spec:
  ports:
  - name: web
    port: 5672
    protocol: TCP
    targetPort: 5672
  - name: http
    port: 15672
    protocol: TCP
    targetPort: 15672
  selector:
    app: rabbitmq
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations: {}
  labels:
    app: rabbitmq
  name: rabbitmq
  namespace: public-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rabbitmq
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: rabbitmq
    spec:
      affinity: {}
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: rabbitmq:3.8.17-management
        imagePullPolicy: IfNotPresent
        lifecycle: {}
        livenessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 5672
          timeoutSeconds: 2
        name: rabbitmq
        ports:
        - containerPort: 5672
          name: web
          protocol: TCP
        readinessProbe:
          failureThreshold: 2
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          tcpSocket:
            port: 5672
          timeoutSeconds: 2
        resources:
          limits:
            cpu: 998m
            memory: 1019Mi
          requests:
            cpu: 251m
            memory: 501Mi
      restartPolicy: Always

2.4 配置访问(TCP或HTTP):

更改svc的类型为NodePort
[root@k8s-master01 yaml]# kubectl edit svc -n public-service

image-20240505204613801

image-20240505204842201

通过宿主机ip或vip+端口号进行访问测试

image-20240505204943899

由于前期镜像没有设置环境配置密码所以默认密码为guest/guest(不安全)

image-20240505205421648

所以可以修改yaml文件加上环境变量(新增后guest将自动被禁用)

[root@k8s-master01 yaml]# vim rabbitmq.yaml
#新增
       - name: RABBITMQ_DEFAULT_USER
          value: admin
        - name: RABBITMQ_DEFAULT_PASS
          value: huawei@123

image-20240505210153372

image-20240505210336261

需要重新修改svc为NodePort,并查看NodePort暴露的端口号

image-20240505210931103

成功访问!

image-20240505210950227

3. k8s和传统架构管理中间件的区别

image-20240505211735373

3.1 传统架构管理中间件

image-20240505212459662

  1. 新建集群:这是开始建立中间件集群的第一步。
  2. 申请服务器:在这个阶段,需要向IT部门或云服务提供商申请新的服务器资源来支持集群。
  3. 下载软件包:通过官方网站或其他可信来源下载中间件软件包。
  4. 配置相关配置文件:安装和配置中间件软件,包括设置参数、网络配置等。
  5. 启动服务:完成配置后,启动中间件服务以使其在新服务器上运行。
  6. 建立集群:将这些服务器添加到现有的集群中,形成一个完整的中间件集群。

当现有集群无法满足需求时,需要通过增加更多服务器来扩展集群规模。整个过程可能需要手动操作或者使用自动化工具来简化管理和维护工作。

3.2 k8s如何管理中间件

通过包管理工具是可以很方便管理一些比较复杂的应用,比如 MySQL 集群、Redis 集群等,可以一键式创建集群、扩容、备份等。

常用的两种包管理工具是 OperatorHelm

image-20240505220902743

Helm:更倾向于无状态应用的部署,比如公司的服务、某些不需要持久化数据的中间件、不需要实现额外功能的服务,比如备份、回滚等。

Operator:管理更为复杂的有状态服务,比如 MySQL 集群、 Redis 集群、Rook 等。并且可以利用 Operator 实现扩容、备份、 回滚等功能,

两种工具的实现难度是不一样的。比如自己写一个 Helm 的 Chart(Helm包的名称叫Chart),只需要将相关的模板文件放在Chart的 templates 目录,然后抽离相关的配置,放置于 values.yaml,模板文件通过 go template 语法即可生成相关的资源文件并加载到Kubernetes中。而 Operator 需要自己动手编写一个控制器,这个控制器可以解析自己定义的 CRD(Custom Resource Define,自定义资源类型),然后生成相关的资源文件并加载到 Kubernetes 中。想要实现上述所讲的备份、回滚等功能,也需要自己编写相应的代码实现。所以 Operator 需要一定的开发能力,可以用 Golang、Java 等语言。

4. 中间件要不要部署至k8s集群

非生产环境:使用K8s管理比较推荐

生产环境:需要考虑性能、持久化、稳定性等问题。

一般情况下,我们除了mysql之外,其实其他的都是可以部署在k8s集群当中的。

因为mysql是对存储是有直接性的要求。你直接在传统操作上面去部署你的mysql的这个实例,它直接用的是本地的系统。所以说它的存储速度是非常快的,而如果是部署在虚拟机的话,它的存储其实也是需要有网络上的消耗。

企业是在这个云环境上搭服务的话。其实比较推荐直接使用云厂商的这个mysql服务。

5. 使用Operator在K8s中安装Redis集群

Operator仓库:https://operatorhub.io/

如果在官方仓库没有对应的组件的Operator(官方不想收录),可以在github上搜。

image-20240505225015011

如图上的Operator就很好用(首选),但是该Operator里必须要有后端存储(生产环境必备,但实验环境未必有部署)并且安装方式是使用helm管理(既有Operator又有helm)不利于初学者学习,所以以下创建使用另一个作为示例。

5.1 创建Operator和CRD

git hub上官方网址

国内渠道:git clone https://gitee.com/dukuan/td-redis-operator.git
[root@k8s-master01 ~]# cd td-redis-operator
[root@k8s-master01 td-redis-operator]# kubectl create -f deploy/deploy.yaml
[root@k8s-master01 td-redis-operator]# kubectl get pod -n redis
NAME                        READY   STATUS    RESTARTS   AGE
operator-6dfbd8b785-pxh5f   1/1     Running   0          58s

#修改cluster.yaml
[root@k8s-master01 td-redis-operator]# cat cr/redis_cluster.yaml
apiVersion: cache.tongdun.net/v1alpha1
kind: RedisCluster
metadata:
  name: redis-cluster-trump
  namespace: redis
spec:
  app: cluster-trump
  capacity: 32768
  dc: hz
  env: demo
  image: tongduncloud/redis-cluster:0.2
  monitorimage: tongduncloud/redis-exporter:1.0
  netmode: NodePort   #修改网络模式
  proxyimage: tongduncloud/predixy:1.0
  proxysecret: "zzb"  #代理密码
  realname: zzb       #负责人
  secret: zzb         #redis密码
  size: 3
  storageclass: ""    #后端存储(sc)
  vip: ""             #vip无实际功能

5.2 创建Redis集群

kubectl create -f cr/redis_cluster.yaml

image-20240505234015337

提示内存不足

使用kubectl edit deploy -n redis predixy-redis-cluster-trump 修改并退出

image-20240505234316672

5.3 查看集群状态

kubectl get rediscluster -n redis redis-cluster-trump -oyaml

image-20240506000151012

image-20240506000052386

manager为图形化管理工具

集群内使用 redis-cluster-trump访问,集群外使用predixy-redis-cluster-trump

[root@k8s-master01 td-redis-operator]# kubectl exec -ti redis-cluster-trump-0-0 -c redis-cluster-trump-0 -n redis -- bash # -C 指定进入redis容器
[root@redis-cluster-trump-0-0 /]# redis-cli  #使用客户端工具进行测试
127.0.0.1:6379> auth zzb	#使用auth + 密码 进行认证
OK

127.0.0.1:6379> cluster info	#查看集群状态
cluster_state:ok

127.0.0.1:6379> cluster nodes	#查看集群主节点和从节点的状态
3a12a1423dbd12dbf5bbdf693951436bf0f8114b 172.16.85.195:6379@16379 myself,master - 0 1714925659000 1 connected 0-5460
0757712e9338cca65992cc64ab44aa534d19b73d 172.16.135.131:6379@16379 slave 09a8dda7a28be21a2134eb2ec6347c7819d19839 0 1714925659553 4 connected
d3e56d58ce2cfd1d9283354a0b4040d7bf566bfe 172.16.58.252:6379@16379 slave 3a12a1423dbd12dbf5bbdf693951436bf0f8114b 0 1714925660456 1 connected
7f80b27a1e6a01a824a52c47e74aa411b59f126c 172.16.58.251:6379@16379 slave f5259511f5d62acdec5fa3d069dc229f04c044d2 0 1714925659553 3 connected
f5259511f5d62acdec5fa3d069dc229f04c044d2 172.16.85.197:6379@16379 master - 0 1714925660054 3 connected 10923-16383
09a8dda7a28be21a2134eb2ec6347c7819d19839 172.16.85.194:6379@16379 master - 0 1714925659453 4 connected 5461-10922


127.0.0.1:6379> set a 1 #创建一个key a是key 1是值
(error) MOVED 15495 172.16.85.197:6379	#显示已分配到172.16.85.197:6379节点

[root@redis-cluster-trump-0-0 /]# redis-cli -h 172.16.85.197 #连接节点测试
172.16.85.197:6379> auth zzb
OK
172.16.85.197:6379> set a 1
OK
172.16.85.197:6379> get a
"1"

[root@redis-cluster-trump-0-0 /]# redis-cli -h redis-cluster-trump.redis -c	#连接智能客户端(svc中cluster的).redis为指定命名空间(跨命名空间) -c 自动跳转节点(MOVED)无需退出重连
[root@redis-cluster-trump-0-0 /]# redis-cli predixy-redis-cluster-trump	#使用代理登录(不需要做跳转了)

5.4 部署、使用图形化管理工具

[root@k8s-master01 td-redis-operator]# vim deploy/web-deploy.yaml #修改redis密码(因为该程序集群内redis密码是写死的)对外的代理密码可不一样。

image-20240506004313407

kubectl create -f deploy/web-deploy.yaml (有报错没关系)

[root@k8s-master01 td-redis-operator]# kubectl get svc -n redis (查看manager对外暴露的端口号)

成功登录并尝试创建实例。

image-20240506010252613

由于是测试环境没有那么大的内存所以创建的pod会一直处于pending状态

使用edit修改(不是所有的operator都可以用edit修改,因为这些资源并不是k8s创建的而是operator,所以修改后还会变回来)

[root@k8s-master01 td-redis-operator]# kubectl edit sts -n redis

删掉所有affinity(保证副本部署在同一个机器,测试环境没那么多机器),以及修改所有的requests(cpu改为100m)

image-20240506011013236

删除 pending 的 pod 使其重建

image-20240506011606491

image-20240506012859320

修改代理的requests (limits改为2Gi requests改为128Mi)

[root@k8s-master01 td-redis-operator]# kubectl edit deploy -n redis predixy-redis-cluster-test

image-20240506013459654

可在web界面中进行修改等操作

image-20240506013958465

5.5 扩容和删除Redis集群

扩容Redis集群
[root@k8s-master01 td-redis-operator]# vim cr/redis_cluster.yaml
size: 4	#将size从 3 改为 4
[root@k8s-master01 td-redis-operator]# kubectl replace -f cr/redis_cluster.yaml

#或直接使用edit修改
[root@k8s-master01 td-redis-operator]# kubectl edit rediscluster -n redis 

[root@k8s-master01 td-redis-operator]# kubectl get rediscluster -n redis redis-cluster-trump -oyaml #查看主从结构(注意如果没有配置动态存储,当所有主从pod重建的话,数据会丢失)

image-20240506005157365

Tips:虽然有缩容操作,但不推荐使用

卸载集群

kubectl delete rediscluster redis-cluster-trump -n redis

或者通过控制台页面删除

6. Helm安装Zookeeper集群、Kafka集群

使用Helm管理中间件集群的流程如下:

6.1 安装Helm客户端

首先集群中需要有一个Helm的客户端,用来执行增删改查命令,和Kubectl类似。

image-20240506020721492

上传至宿主机进行解压安装(放置/usr/local/bin目录下就无需进入目录使用./helm)

image-20240506021233273

image-20240506021418994

6.2 拉取chart仓库、安装Zookeeper

之后需要找到对应的Chart(可以在中间件的官网或者GitHub中查找),比如安装Redis、Zookeeper集群的包。这个包和镜像类似,都是放在一个仓库中,镜像放在镜像仓库,Chart放在Chart仓库。

image-20240506020652115

image-20240506020856733

以下使用方式一进行安装演示:先下载后安装 #后续kafka会用方式二(直接安装,无需下载)

[root@k8s-master01 soft]# helm repo add bitnami https://charts.bitnami.com/bitnami	#添加helm repo

[root@k8s-master01 soft]# helm pull bitnami/zookeeper #下载zookeeper最新版本

[root@k8s-master01 soft]# tar xf zookeeper-13.2.0.tgz #解压

[root@k8s-master01 zookeeper]# vim values.yaml	#可修改values.yaml相应配置:副本数(replicaCount)、auth(用户名密码)、持久化(生产环境下persistence. enabled: true 以及 storageClass: ""改为动态存储的名称)

[root@k8s-master01 zookeeper]# helm install -n public-service zookeeper . #进行安装(要在zookeeper目录下)

image-20240506030157319

image-20240506030236041

6.3 安装Kafka(依赖Zookeeper版本演示)

老版本kafka的选主或是负载均衡依赖Zookeeper实现,而新版本则是依赖自身的 Kafka Raft 协议

Tips:Kafka在2.8 版本引入了 Kafka Raft 协议的实验性支持,随后Kafka 3.0(及其之后的稳定版本),Kafka 正式开始提供移除 Zookeeper 依赖的生产就绪功能)

安装方式二:直接安装,无需下载
helm install kafka bitnami/kafka \
--set controller.replicaCount=0 \
--set kraft.enabled=false \
--set zookeeper.enabled=false \
--set broker.replicaCount=3 \
--set externalZookeeper.servers=zookeeper \
--set broker.persistence.enabled=false \
--set listeners.client.protocol=PLAINTEXT \
--set listeners.controller.protocol=PLAINTEXT \
--set listeners.interbroker.protocol=PLAINTEXT \
--set listeners.external.protocol=PLAINTEXT -n public-service
#保留kafka安装时产生的配置命令
To create a pod that you can use as a Kafka client run the following commands:

    kubectl run kafka-client --restart='Never' --image docker.io/bitnami/kafka:3.7.0-debian-12-r3 --namespace public-service --command -- sleep infinity 	#创建客户端工具
    kubectl exec --tty -i kafka-client --namespace public-service -- bash	#进入客户端工具

    PRODUCER:	#生产者:
        kafka-console-producer.sh \
            --broker-list kafka-broker-0.kafka-broker-headless.public-service.svc.cluster.local:9092,kafka-broker-1.kafka-broker-headless.public-service.svc.cluster.local:9092,kafka-broker-2.kafka-broker-headless.public-service.svc.cluster.local:9092 \
            --topic test

    CONSUMER:	#消费者
        kafka-console-consumer.sh \
            --bootstrap-server kafka.public-service.svc.cluster.local:9092 \
            --topic test \
            --from-beginning

image-20240506030446977

6.4 Kafka集群测试

使用之前保存的命名进行测试
    kubectl run kafka-client --restart='Never' --image docker.io/bitnami/kafka:3.7.0-debian-12-r3 --namespace public-service --command -- sleep infinity 	#创建客户端工具
    kubectl exec --tty -i kafka-client --namespace public-service -- bash	#进入客户端工具
  
  
@kafka-client:/$ kafka-console-producer.sh \	#复制生产者的命令
            --broker-list kafka-broker-0.kafka-broker-headless.public-service.svc.cluster.local:9092,kafka-broker-1.kafka-broker-headless.public-service.svc.cluster.local:9092,kafka-broker-2.kafka-broker-headless.public-service.svc.cluster.local:9092 \
            --topic test
>hello
>nihao

            

>kafka-console-consumer.sh \	#复制消费者的命令
            --bootstrap-server kafka.public-service.svc.cluster.local:9092 \
            --topic test \
            --from-beginning
>hello
>nihao

6.5 安装新版Kafka(可以不依赖Zookeeper)

删除之前的Zookeeper和Kafka

image-20240506032851953

helm install kafka-kraft bitnami/kafka \
--set kraft.enabled=true \
--set zookeeper.enabled=false \
--set controller.replicaCount=3 \
--set controller.persistence.enabled=false \
--set broker.persistence.enabled=false \
--set listeners.client.protocol=PLAINTEXT \
--set listeners.controller.protocol=PLAINTEXT \
--set listeners.interbroker.protocol=PLAINTEXT \
--set listeners.external.protocol=PLAINTEXT -n public-service
To create a pod that you can use as a Kafka client run the following commands:

    kubectl run kafka-kraft-client --restart='Never' --image docker.io/bitnami/kafka:3.7.0-debian-12-r3 --namespace public-service --command -- sleep infinity
    kubectl exec --tty -i kafka-kraft-client --namespace public-service -- bash

    PRODUCER:
        kafka-console-producer.sh \
            --broker-list kafka-kraft-controller-0.kafka-kraft-controller-headless.public-service.svc.cluster.local:9092,kafka-kraft-controller-1.kafka-kraft-controller-headless.public-service.svc.cluster.local:9092,kafka-kraft-controller-2.kafka-kraft-controller-headless.public-service.svc.cluster.local:9092 \
            --topic test

    CONSUMER:
        kafka-console-consumer.sh \
            --bootstrap-server kafka-kraft.public-service.svc.cluster.local:9092 \
            --topic test \
            --from-beginning

#后续测试和6.4相同不做重复

7. Helm基础命令

基础命令:

查询一个包:helm search

#例如
[root@k8s-master01 ~]# helm search repo bitnami/redis --versions #或者 -l APP version为redis的版本
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
bitnami/redis           19.1.5          7.2.4           Redis(R) is an open source,  ...
bitnami/redis           19.1.4          7.2.4           Redis(R) is an open source,  ...
bitnami/redis           19.1.3          7.2.4           Redis(R) is an open source,  ...

下载一个包:helm pull

[root@k8s-master01 ~]# helm pull bitnami/redis-cluster --version [CHART VERSION] #不指定版本(chart)默认下载最新

查看(现在命名空间helm安装的chart):helm list #(-A 可查看所有命名空间)

查看安装参数:helm get values

[root@k8s-master01 ~]# helm get values -n public-service kafka-kraft

Tips: 使用本地安装(方式一)就无法使用此命令查看。

创建一个包:helm create

安装一个包:helm install

更新:helm upgrade

Tips:当使用本地安装的方法,可修改配置后直接使用helm upgrade更新。而使用直接安装(方式二)需要把之前安装时的参数都带上不然会被覆盖掉

删除:helm delete

8. Helm v3 Chart目录层级解析

未完

注:本篇学习笔记内容参考杜宽的《云原生Kubernetes全栈架构师》,视频、资料文档等,大家可以多多支持!还有YinJayChen语雀k8s训练营“我为什么这么菜”知乎博主等资料文档,感谢无私奉献!

posted @ 2024-07-01 02:45  zzbao  阅读(71)  评论(0)    收藏  举报