11、中间件容器化
11、中间件容器化
1. 应用部署的通用步骤
1.1 必须了解要部署的东西:
-
架构:理解应用程序的架构和组件。
-
配置:知道应用程序需要哪些配置参数。
-
端口号:确定应用程序使用的端口。
-
启动命令:了解启动应用程序所需的命令。
1.2 其次要有镜像:
- 镜像谁来做:确定谁负责创建和维护应用程序的镜像。应用是自己公司开发的,还是使用开源的应用。
1.3 找到最合适的部署方式:
-
是否有状态:考虑应用程序是否具有状态,这将影响如何在 Kubernetes 中部署它。
-
配置分离:将配置文件与代码分开,以便于管理和更新。(如:是通过环境变量还是配置文件)
-
部署文件来源:从何处获取部署文件,例如 GitHub 或其他版本控制系统。
-
如何部署:选择适当的部署策略,如滚动升级或蓝绿部署。
1.4 程序如何被使用:
- 什么协议:确定应用程序使用的通信协议。
- 内部还是外部:考虑应用程序是仅在集群内部使用,还是需要对外提供服务。
2. 中间件单实例部署
2.1 找到官方镜像:
选择带有 management 的稳定版本进行下载,并推送到私有镜像仓库保存
[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下)持久化。
下图是redis的启动命令(可在dockerfile中查看) redis目前不支持环境变量只支持配置文件(需要用到ComfigMap)
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
通过宿主机ip或vip+端口号进行访问测试
由于前期镜像没有设置环境配置密码所以默认密码为guest/guest(不安全)
所以可以修改yaml文件加上环境变量(新增后guest将自动被禁用)
[root@k8s-master01 yaml]# vim rabbitmq.yaml
#新增
- name: RABBITMQ_DEFAULT_USER
value: admin
- name: RABBITMQ_DEFAULT_PASS
value: huawei@123
需要重新修改svc为NodePort,并查看NodePort暴露的端口号
成功访问!
3. k8s和传统架构管理中间件的区别
3.1 传统架构管理中间件
- 新建集群:这是开始建立中间件集群的第一步。
- 申请服务器:在这个阶段,需要向IT部门或云服务提供商申请新的服务器资源来支持集群。
- 下载软件包:通过官方网站或其他可信来源下载中间件软件包。
- 配置相关配置文件:安装和配置中间件软件,包括设置参数、网络配置等。
- 启动服务:完成配置后,启动中间件服务以使其在新服务器上运行。
- 建立集群:将这些服务器添加到现有的集群中,形成一个完整的中间件集群。
当现有集群无法满足需求时,需要通过增加更多服务器来扩展集群规模。整个过程可能需要手动操作或者使用自动化工具来简化管理和维护工作。
3.2 k8s如何管理中间件
通过包管理工具是可以很方便管理一些比较复杂的应用,比如 MySQL 集群、Redis 集群等,可以一键式创建集群、扩容、备份等。
常用的两种包管理工具是 Operator 和 Helm。
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上搜。
如图上的Operator就很好用(首选),但是该Operator里必须要有后端存储(生产环境必备,但实验环境未必有部署)并且安装方式是使用helm管理(既有Operator又有helm)不利于初学者学习,所以以下创建使用另一个作为示例。
5.1 创建Operator和CRD
国内渠道: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
提示内存不足
使用kubectl edit deploy -n redis predixy-redis-cluster-trump 修改并退出
5.3 查看集群状态
kubectl get rediscluster -n redis redis-cluster-trump -oyaml
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密码是写死的)对外的代理密码可不一样。
kubectl create -f deploy/web-deploy.yaml (有报错没关系)
[root@k8s-master01 td-redis-operator]# kubectl get svc -n redis (查看manager对外暴露的端口号)
成功登录并尝试创建实例。
由于是测试环境没有那么大的内存所以创建的pod会一直处于pending状态
使用edit修改(不是所有的operator都可以用edit修改,因为这些资源并不是k8s创建的而是operator,所以修改后还会变回来)
[root@k8s-master01 td-redis-operator]# kubectl edit sts -n redis
删掉所有affinity(保证副本部署在同一个机器,测试环境没那么多机器),以及修改所有的requests(cpu改为100m)
删除 pending 的 pod 使其重建
修改代理的requests (limits改为2Gi requests改为128Mi)
[root@k8s-master01 td-redis-operator]# kubectl edit deploy -n redis predixy-redis-cluster-test
可在web界面中进行修改等操作
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重建的话,数据会丢失)
Tips:虽然有缩容操作,但不推荐使用
卸载集群
kubectl delete rediscluster redis-cluster-trump -n redis
或者通过控制台页面删除
6. Helm安装Zookeeper集群、Kafka集群
使用Helm管理中间件集群的流程如下:
6.1 安装Helm客户端
首先集群中需要有一个Helm的客户端,用来执行增删改查命令,和Kubectl类似。
上传至宿主机进行解压安装(放置/usr/local/bin目录下就无需进入目录使用./helm)
6.2 拉取chart仓库、安装Zookeeper
之后需要找到对应的Chart(可以在中间件的官网或者GitHub中查找),比如安装Redis、Zookeeper集群的包。这个包和镜像类似,都是放在一个仓库中,镜像放在镜像仓库,Chart放在Chart仓库。
以下使用方式一进行安装演示:先下载后安装 #后续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目录下)
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
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
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训练营、“我为什么这么菜”知乎博主等资料文档,感谢无私奉献!