十三、K8s自定义资源Operator
十三、K8s自定义资源Operator
文章目录
- 十三、K8s自定义资源Operator
- 1、什么是Operator
- 1.1 Operator定义
- 1.2 Operator使用场景:
- 1.3 Operator组成
- 1.4 Operator和Helm对比
- 2、在 K8s 集群中安装 Redis 集群
- 2.1 安装 Operator 和 CRD
- 2.2 安装集群
- 2.3 设置 Redis 集群密码
- 2.4 在 K8s 外部访问 Redis 集群
- 2.5 卸载集群
- 3、使用 Operator 安装 MySQL 集群
- 3.1 安装 Operator 和 CRD
- 3.2 创建 NDB Cluster
- 3.3 访问测试
- 3.4 集群外部访问
- 3.5 删除集群
1、什么是Operator
1.1 Operator定义
Operator是一种用于扩展K8s API的自定义控制器,可以实现在原生资源对象上进行自定义资源类型。通过Operator,也可以实现将复杂的任务转化对K8s资源的操作,让应用程序的管理和维护更加简单和规范。
1.2 Operator使用场景:
- 简化复杂应用的管理:像管理K8s资源一样管理复杂的系统
- 一致性操作:通过资源定义决定行为,各个环境可以统一配置
- 扩展集群能力:自定义资源类型,扩展集群的调度能力
1.3 Operator组成
- CRD:Custom Resource Definitions,Operator使用k8s的CRD来定义新的资源类型,新的类型可像核心资源被管理,比如定义一个叫做Database的CRD,可以用于一键启动一个数据库实例。
- Controller:Operator控制器,该控制器监视自定义资源的状态,并根据用户的配置自动执行相应的操作,比如创建一个数据库,执行一次备份任务等。
1.4 Operator和Helm对比
- Helm:
- 适合简单的应用程序或微服务,尤其是那些不需要复杂运维任务的应用
- 开发简单,无需深入了解开发知识
- Operator:
- 适合复杂的应用程序(如数据库、消息队列、缓存系统等),除部署外,也需要一些额外任务的应用,比如备份等
- 开发稍微复杂,需要了解相关开发知识
2、在 K8s 集群中安装 Redis 集群
Redis Cluster 是 Redis 的分布式部署模式,可以让多个 Redis 实例以集群的方式运行,从而提供高可用性、水平扩展和数据冗余的能力。Redis Cluster 通过分片(Sharding)和复制(Replication)技术,确保数据可以在多个节点之间分布,并且在节点故障时能够自动恢复。
推荐 Operator:https://operatorhub.io/operator/redis-operator
仓库地址:https://github.com/OT-CONTAINER-KIT/redis-operator
国内仓库:https://gitee.com/dukuan/redis-operator
官方文档:https://ot-redis-operator.netlify.app/docs/
架构
2.1 安装 Operator 和 CRD
# 添加 Operator 的 Helm 仓库:
[root@k8s-master01 ~]# helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/# 安装 Operator 和 CRD:
[root@k8s-master01 ~]# helm install redis-operator ot-helm/redis-operator --namespace ot-operators --create-namespace
NAME: redis-operator
LAST DEPLOYED: Sun Jun 29 08:16:50 2025
NAMESPACE: ot-operators
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing redis-operator.Your release is named redis-operator.To learn more about the release, try:$ helm status redis-operator$ helm get all redis-operator# 查看创建的 CRD:
[root@k8s-master01 ~]# kubectl get crd | grep redis
redis.redis.redis.opstreelabs.in 2025-06-29T00:16:46Z
redisclusters.redis.redis.opstreelabs.in 2025-06-29T00:16:47Z
redisreplications.redis.redis.opstreelabs.in 2025-06-29T00:16:47Z
redissentinels.redis.redis.opstreelabs.in 2025-06-29T00:16:48Z# 查看 Pod:
[root@k8s-master01 ~]# kubectl get po -n ot-operators
NAME READY STATUS RESTARTS AGE
redis-operator-68b7b4c9f8-dtjrr 1/1 Running 0 3m40s# 如果无法连外网,可以使用国内的仓库进行离线安装,已同步国内的镜像仓库
# crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis-operator:v0.20.2
2.2 安装集群
# 创建 Redis 集群的资源文件:
[root@k8s-master01 ~]# vim redis-cluster.yaml
[root@k8s-master01 ~]# cat redis-cluster.yaml
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisCluster
metadata:name: redis-cluster
spec:clusterSize: 3clusterVersion: v7persistenceEnabled: truekubernetesConfig:image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:v7.0.15imagePullPolicy: IfNotPresentstorage:volumeClaimTemplate:spec:storageClassName: nfs-csi # 生产上不建议使用NFSaccessModes: ["ReadWriteOnce"]resources:requests:storage: 1Gi[root@k8s-master01 ~]# kubectl create -f redis-cluster.yaml -n public-service# 查看pod状态
[root@k8s-master01 ~]# kubectl get po -n public-service
NAME READY STATUS RESTARTS AGE
redis-cluster-follower-0 1/1 Running 0 33s
redis-cluster-follower-1 1/1 Running 0 26s
redis-cluster-follower-2 1/1 Running 0 20s
redis-cluster-leader-0 1/1 Running 2 (83s ago) 89s
redis-cluster-leader-1 1/1 Running 0 60s
redis-cluster-leader-2 1/1 Running 0 39s# 查看 RedisCluster 状态:
[root@k8s-master01 ~]# kubectl get rediscluster -n public-service
NAME CLUSTERSIZE READYLEADERREPLICAS READYFOLLOWERREPLICAS
redis-cluster 3 3 3
# 查看 Redis 集群状态:
[root@k8s-master01 ~]# kubectl exec -ti redis-cluster-leader-0 -n public-service -- bash
redis-cluster-leader-0:/data$ redis-cli
127.0.0.1:6379> CLUSTER info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_ping_sent:274
cluster_stats_messages_pong_sent:271
cluster_stats_messages_sent:545
cluster_stats_messages_ping_received:268
cluster_stats_messages_pong_received:274
cluster_stats_messages_meet_received:3
cluster_stats_messages_received:545
total_cluster_links_buffer_limit_exceeded:0# 查看集群节点状态:
127.0.0.1:6379> CLUSTER NODES
e7f1e66cd4f329292494b180eef228544a6173d5 172.16.85.199:6379@16379,redis-cluster-leader-0 myself,master - 0 1751207832000 1 connected 0-5460
5513c90d5bfc92e29400207f2892d546950e9056 172.16.58.226:6379@16379,redis-cluster-follower-1 slave efb4a3641bb8b244a020a49741da746e406d7c9a 0 1751207832000 2 connected
540db0e0a90acfb0a334beef8bb28ed72a3b9a26 172.16.85.202:6379@16379,redis-cluster-follower-2 slave 96d23f632eb74396ccbe6cd100461e7fc8a466c2 0 1751207832749 3 connected
01c8b60089fc8807e579aa704c95be98774e5a4d 172.16.85.201:6379@16379,redis-cluster-follower-0 slave e7f1e66cd4f329292494b180eef228544a6173d5 0 1751207831739 1 connected
96d23f632eb74396ccbe6cd100461e7fc8a466c2 172.16.85.200:6379@16379,redis-cluster-leader-2 master - 0 1751207833762 3 connected 10923-16383
efb4a3641bb8b244a020a49741da746e406d7c9a 172.16.58.225:6379@16379,redis-cluster-leader-1 master - 0 1751207833000 2 connected 5461-10922# 创建 Redis Key 测试
redis-cluster-leader-0:/data$ redis-cli -c
127.0.0.1:6379> set a test
-> Redirected to slot [15495] located at 172.16.85.200:6379
OK
172.16.85.200:6379> get a
"test"
2.3 设置 Redis 集群密码
# 使用 Secret 存储 Redis 密码
[root@k8s-master01 ~]# vim secret.yaml
[root@k8s-master01 ~]# cat secret.yaml
---
apiVersion: v1
kind: Secret
metadata:name: redis-secret
stringData:password: yunwei
type: Opaque[root@k8s-master01 ~]# kubectl create -f secret.yaml -n public-service
# 更新 Redis 集群配置:
[root@k8s-master01 ~]# vim redis-cluster.yaml
[root@k8s-master01 ~]# cat redis-cluster.yaml
....kubernetesConfig:image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:v7.0.15imagePullPolicy: IfNotPresentredisSecret:name: redis-secretkey: password
....# 重新创建集群(删除重建才会生效)
[root@k8s-master01 ~]# kubectl delete -f redis-cluster.yaml -n public-service
[root@k8s-master01 ~]# kubectl create -f redis-cluster.yaml -n public-service# 查看pod
[root@k8s-master01 ~]# kubectl get po -n public-service
NAME READY STATUS RESTARTS AGE
redis-cluster-follower-0 1/1 Running 0 17s
redis-cluster-follower-1 1/1 Running 0 12s
redis-cluster-follower-2 1/1 Running 0 6s
redis-cluster-leader-0 1/1 Running 0 33s
redis-cluster-leader-1 1/1 Running 0 28s
redis-cluster-leader-2 1/1 Running 0 22s
# 登录测试:
[root@k8s-master01 ~]# kubectl exec -ti redis-cluster-follower-0 -n public-service -- bash
redis-cluster-follower-0:/data$ redis-cli -c -a yunwei
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_ping_sent:91
cluster_stats_messages_pong_sent:96
cluster_stats_messages_meet_sent:1
cluster_stats_messages_sent:188
cluster_stats_messages_ping_received:96
cluster_stats_messages_pong_received:92
cluster_stats_messages_received:188
total_cluster_links_buffer_limit_exceeded:0
2.4 在 K8s 外部访问 Redis 集群
如果需要在 K8s 外部访问 Redis 集群(生产环境不推荐
),就要把 Redis 集群暴露出去,此时可以把 Service 更改为 NodePort:
[root@k8s-master01 ~]# cat redis-cluster.yaml
....kubernetesConfig:service:serviceType: NodePort # 改成NodePort即可image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:v7.0.15imagePullPolicy: IfNotPresentredisSecret:name: redis-secretkey: password
2.5 卸载集群
# 直接通过 yaml 文件删除即可:[root@k8s-master01 ~]# kubectl delete -f redis-cluster.yaml -n public-service
3、使用 Operator 安装 MySQL 集群
MySQL NDB Cluster 是一个分布式、高可用的数据库系统,适用于需要高并发读写、低延迟和高可用性的应用场景。MySQL NDB Cluster 基于 NDB(Network Database)存储引擎,并通过多个节点协同工作来提供数据的分布存储和故障恢复能力。
MySQL 集群安装推荐 Operator:https://operatorhub.io/operator/ndb-operator
官方文档:https://dev.mysql.com/doc/ndb-operator/8.4/en/
仓库地址:https://github.com/mysql/mysql-ndb-operator
国内仓库:https://gitee.com/dukuan/mysql-ndb-operator
架构
组件介绍:
- 管理节点:Management Node,负责管理和配置整个 NDB Cluster。保存了 NDB 集群的配置信息,包括 Data Node、SQL Node。管理节点不直接参与数据存储或事务处理,主要负责集群的管理和监控,确保集群的正常运行。
- 数据节点:Data Node,数据节点是集群中实际存储数据的节点,负责存储一部分数据,并且数据会在多个 Data Node 之间进行分区和复制,以实现高可用性和负载均衡。
- SQL 节点:SQL Node,SQL Node 是用户与 NDB Cluster 交互的主要入口,提供了标准的 MySQL SQL 接口,允许用户通过 SQL 查询、插入、更新和删除数据。
- NDBAPI:可以直接与 NDB 存储引擎进行交互的接口。
3.1 安装 Operator 和 CRD
# 下载部署文件:
[root@k8s-master01 ~]# git clone https://gitee.com/dukuan/mysql-ndb-operator.git# 创建 Operator:
[root@k8s-master01 ~]# cd mysql-ndb-operator/
[root@k8s-master01 mysql-ndb-operator]# kubectl apply -f deploy/manifests/ndb-operator.yaml -n ndb-operator# 查看 Pod
[root@k8s-master01 mysql-ndb-operator]# kubectl get po -n ndb-operator
NAME READY STATUS RESTARTS AGE
ndb-operator-app-5f8547d4b-hps2g 1/1 Running 0 8m35s
ndb-operator-webhook-server-78d5d44bb5-92c77 1/1 Running 0 8m35s# 如果无法连外网,可以使用国内的仓库进行离线安装,已同步国内的镜像仓库
# crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/community-ndb-operator:9.1.0-1.6.0
3.2 创建 NDB Cluster
# 创建一个 NDB Cluster:
[root@k8s-master01 ~]# vim ndb-cluster.yaml
[root@k8s-master01 ~]# cat ndb-cluster.yaml
apiVersion: mysql.oracle.com/v1
kind: NdbCluster
metadata:name: example-ndb
spec:image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/community-cluster:9.1.0redundancyLevel: 1 # 指定数据副本的数量,生产环境大于等于 2dataNode:nodeCount: 1 # 指定数据副本的数量,生产环境大于等于 2pvcSpec:storageClassName: nfs-csiaccessModes: ["ReadWriteOnce"]resources:requests:storage: 10GimysqlNode:nodeCount: 1 # 指定数据副本的数量,生产环境大于等于 2pvcSpec:storageClassName: nfs-csiaccessModes: ["ReadWriteOnce"]resources:requests:storage: 10Gi
# 创建集群:
[root@k8s-master01 ~]# kubectl create ns ndb-cluster[root@k8s-master01 ~]# kubectl create -f ndb-cluster.yaml -n ndb-cluster# 查看 Pod 状态:
[root@k8s-master01 ~]# kubectl get po -n ndb-cluster
NAME READY STATUS RESTARTS AGE
example-ndb-mgmd-0 1/1 Running 0 4m57s
example-ndb-mysqld-0 1/1 Running 0 75s
example-ndb-ndbmtd-0 1/1 Running 0 4m48s# 查看集群状态:
[root@k8s-master01 ~]# kubectl get ndbcluster -n ndb-cluster
NAME REPLICA MANAGEMENT NODES DATA NODES MYSQL SERVERS AGE UP-TO-DATE
example-ndb 1 Ready:1/1 Ready:1/1 Ready:1/1 5m2s True
3.3 访问测试
# 集群创建后,会有一些 Service 可以访问到集群内部:
[root@k8s-master01 ~]# kubectl get svc -n ndb-cluster
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-ndb-mgmd ClusterIP 10.104.25.157 <none> 1186/TCP 5m37s
example-ndb-mysqld ClusterIP 10.101.140.23 <none> 3306/TCP 115s
example-ndb-ndbmtd ClusterIP None <none> 1186/TCP 5m28s
# 首先登录到 SQL 节点,然后使用 ndb_mgm 查看集群状态
[root@k8s-master01 ~]# kubectl exec -ti example-ndb-mysqld-0 -n ndb-cluster -- bash
Defaulted container "mysqld-container" out of: mysqld-container, ndb-pod-init-container (init), mysqld-init-container (init)
bash-5.1# ndb_mgm -c example-ndb-mgmd
-- NDB Cluster -- Management Client --
ndb_mgm> SHOW
Connected to management server at example-ndb-mgmd port 1186 (using cleartext)
Cluster Configuration
---------------------
[ndbd(NDB)] 1 node(s)
id=2 @172.16.58.230 (mysql-9.1.0 ndb-9.1.0, Nodegroup: 0, *)[ndb_mgmd(MGM)] 1 node(s)
id=1 @172.16.85.210 (mysql-9.1.0 ndb-9.1.0)[mysqld(API)] 6 node(s)
id=147 (not connected, accepting connect from any host)
id=148 @172.16.85.211 (mysql-9.1.0 ndb-9.1.0)
id=149 (not connected, accepting connect from example-ndb-mysqld-1.example-ndb-mysqld.ndb-cluster.svc.cluster.local)
id=150 (not connected, accepting connect from example-ndb-mysqld-2.example-ndb-mysqld.ndb-cluster.svc.cluster.local)
id=151 (not connected, accepting connect from any host)
id=152 (not connected, accepting connect from any host)
# 也可以通过 MySQL 客户端链接集群,首先查看集群的访问密码:
[root@k8s-master01 ~]# base64 -d <<< $(kubectl -n ndb-cluster get secret example-ndb-mysqld-root-password -o jsonpath={.data.password})
pFWE8AwPocQ5qiGR# 登录 MySQL:
bash-5.1# mysql -h example-ndb-mysqld -uroot -ppFWE8AwPocQ5qiGR
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 111
Server version: 9.1.0-cluster MySQL Cluster Community Server - GPLCopyright (c) 2000, 2024, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| ndbinfo |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)mysql>
3.4 集群外部访问
如果想要在集群外部访问,可以创建一个 SQL Node NodePort 类型的 Service:
[root@k8s-master01 ~]# vim ndbcluster-svc-nodeport.yaml
[root@k8s-master01 ~]# cat ndbcluster-svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:name: example-ndb-mysqld-nodeportnamespace: ndb-cluster
spec:ports:- name: mysqld-service-port-0port: 3306protocol: TCPtargetPort: 3306selector:mysql.oracle.com/node-type: mysqldmysql.oracle.com/v1: example-ndbsessionAffinity: Nonetype: NodePort# 创建该 Service:
[root@k8s-master01 ~]# kubectl create -f ndbcluster-svc-nodeport.yaml# 查看端口:
[root@k8s-master01 ~]# kubectl get -f ndbcluster-svc-nodeport.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-ndb-mysqld-nodeport NodePort 10.110.189.195 <none> 3306:30314/TCP 11s
接下来即可通过节点 IP:30314 访问该集群。
3.5 删除集群
# 直接删除资源即可:
[root@k8s-master01 ~]# kubectl delete -f ndb-cluster.yaml -n ndb-cluster
此博客来源于:https://edu.51cto.com/lecturer/11062970.html