KubeBlocks × 快手|是否应在 Kubernetes 上运行 Redis?快手这样做!

导读

针对无状态服务,业界已拥有成熟解决方案,但对于有状态服务(如数据库、Redis)是否适合容器化与 K8s 托管,仍存在争议。本文基于快手在 Redis 云原生化实践中的经验,探讨有关有状态服务的云原生化思考及应对方案。

在推进 Redis 云原生化过程中,快手与 KubeBlocks 社区合作,低成本实现了技术方案的落地。在单集群编排层面,快手通过扩展 KubeBlocks InstanceSet 的能力边界,更好地支持角色定义、探测与更新策略,实现了 Pod 与 PVC 直接管理、异构配置等特性,并结合 Component、Shard 和 Cluster 抽象,构建了完整的 Redis 集群管理体系。

针对超大规模部署需求,快手将 KubeBlocks Operator 解耦为联邦集群和成员集群两部分。其中,InstanceSet Controller 部署于成员集群,而 Cluster 和 Component Operator 则运行在联邦层。通过自研的 Fed-InstanceSet 控制器,巧妙解决了实例全局唯一编号和跨集群管控等技术难题,实现了大规模 Redis 集群的统一调度和运维。

快手的实践证明,将数据库运行在 K8s 上是完全可行的,Redis 容器化带来的性能损耗在可接受范围内(不超过10%),云原生化带来的资源利用率提升和运维效率改善带来了显著收益。

如果您对在 K8s 上运行 Redis 或者其他数据库感兴趣,可扫码添加 KubeBlocks 小助手,了解技术详情。

扫码备注「公司+职位」,添加小助手

作者简介

刘裕惺,快手高级软件工程师。曾就职于阿里云和快手的云原生团队,专注于云原生领域,在云原生技术的开源、商业化和扩展方面拥有丰富的经验。刘裕惺也是 CNCF/Dragonfly 项目的 Maintainer 之一,也是 CNCF/Sealer 项目的 Maintainer 之一。目前专注于推动快手有状态业务的云原生转型。

一、背景

随着行业技术的不断演进,快手的基础设施顺应技术潮流逐步迈向云原生化。在各业务团队的支持下,容器云成为服务与基础设施的新界面,目前在快手无状态服务已基本全面实现 Kubernetes (K8s) 的云原生化。然而,有状态服务的云原生化之路却仍然充满了挑战:

  • 有状态服务究竟是否适合在 K8S上运行?
  • 有状态服务的云原生化如何实现与落地?

以 Redis 为例,它是快手广泛使用的有状态服务之一,超大规模是其显著特征。即使微小的优化在如此庞大的规模下也能为企业带来巨大的收益。在面向未来的长期规划中,快手高度认可 Redis 云原生化带来的潜在价值,尤其是资源利用率提升带来的成本优化。本文基于快手 Redis 云原生化实践中的经验,深入剖析有状态服务的云原生化思考及应对策略。

二、有状态服务是否适合运行在K8S上?

有状态服务运行在K8S上的风险与收益

将有状态服务运行在 Kubernetes 上的收益显而易见:

  • 提升资源利用率:通过“合池”、“统一调度”和“混部”,优化资源使用,显著降低成本。
  • 提高运维效率:利用 Kube
Kubernetes 环境中部署 Redis 的 Cluster 模式,可以通过以下步骤实现高可用的 Redis 集群。 ### 部署 Redis Cluster 的关键组件 1. **StatefulSet**:用于管理 Redis 节点的有状态服务,确保每个 Pod 有唯一的、稳定的网络标识和持久化存储。 2. **Service**:为每个 Redis Pod 提供稳定的访问入口,支持 Cluster 内部通信。 3. **Headless Service**:用于暴露 StatefulSet 中的每个 Pod,确保 Redis 节点可以相互发现。 4. **ConfigMap 或 Init Container**:用于初始化 Redis Cluster,执行 `redis-cli --cluster create` 命令。 ### 示例部署配置 以下是一个简化的 Kubernetes 部署文件示例,包括 StatefulSet 和 Service 的定义: ```yaml apiVersion: v1 kind: Service metadata: name: redis-cluster spec: type: ClusterIP ports: - port: 6379 name: client - port: 16379 name: gossip clusterIP: None selector: app: redis-cluster ``` ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster spec: serviceName: redis-cluster replicas: 6 selector: matchLabels: app: redis-cluster template: metadata: labels: app: redis-cluster spec: containers: - name: redis image: redis:6.2 ports: - containerPort: 6379 name: client - containerPort: 16379 name: gossip command: - "redis-server" - "--cluster-enabled" - "yes" - "--cluster-config-file" - "/var/lib/redis-cluster/nodes.conf" - "--cluster-node-timeout" - "5000" - "--appendonly" - "yes" volumeMounts: - name: redis-data mountPath: /var/lib/redis-cluster volumes: - name: redis-data persistentVolumeClaim: claimName: redis-pvc ``` ### 初始化 Redis Cluster 在 Redis Pod 启动后,需要通过 `redis-cli` 初始化 Cluster。可以通过一个 Init Container 或 Job 来执行以下命令: ```bash redis-cli --cluster create <pod1-ip>:6379 <pod2-ip>:6379 ... --cluster-replicas 1 ``` 该命令将创建一个包含主从节点的 Redis Cluster,确保数据的高可用性[^2]。 ### 集群验证与测试 部署完成后,可以使用 `redis-cli` 连接到任意一个 Pod,执行 Cluster 相关命令验证集群状态: ```bash kubectl exec -it redis-cluster-0 -- redis-cli cluster info ``` 返回结果显示 `cluster_state:ok`,并且 `cluster_known_nodes` 和 `cluster_size` 与实际节点数一致[^2]。 ### 外部访问 Redis Cluster 由于 Redis Cluster 的请求会自动重定向,直接通过 NodePort 暴露服务可能无法正常工作。可以通过部署 `redis-cluster-proxy` 来实现对外代理访问,确保客户端可以连接到 Cluster 中的任意节点,由 Proxy 负责请求的转发和重定向[^3]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值