Kubernetes 构建 Redis 集群

简介: Kubernetes 构建 Redis 集群


网络异常,图片无法展示
|

一、问题分析

本质上来说,在 k8s 上部署一个 redis 集群和部署一个普通应用没有什么太大的区别,但需要注意下面几个问题:

  1. Redis 是一个有状态应用
    这是部署 redis 集群时我们最需要注意的问题,当我们把 redis 以 pod 的形式部署在 k8s 中时,每个 pod 里缓存的数据都是不一样的,而且 pod 的 IP 是会随时变化,这时候如果使用普通的 deployment 和 service 来部署 redis-cluster 就会出现很多问题,因此需要改用 StatefulSet + Headless Service 来解决
  2. 数据持久化
    redis 虽然是基于内存的缓存,但还是需要依赖于磁盘进行数据的持久化,以便服务出现问题重启时可以恢复已经缓存的数据。在集群中,我们需要使用共享文件系统 + PV(持久卷)的方式来让整个集群中的所有 pod 都可以共享同一份持久化储存

二、概念介绍

在开始之前先来详细介绍一下几个概念和原理。

1、Headless Service

简单的说,Headless Service 就是没有指定 Cluster IP 的 Service,相应的,在 k8s 的 dns 映射里,Headless Service 的解析结果不是一个 Cluster IP,而是它所关联的所有 Pod 的 IP 列表

2、StatefulSet

StatefulSet是 k8s 中专门用于解决有状态应用部署的一种资源,总的来说可以认为它是Deployment/RC的一个变种,它有以下几个特性:

  1. StatefulSet 管理的每个 Pod 都有唯一的文档/网络标识,并且按照数字规律生成,而不是像 Deployment 中那样名称和 IP 都是随机的(比如 StatefulSet 名字为 redis,那么 pod 名就是 redis-0, redis-1 ...)
  2. StatefulSet 中 ReplicaSet 的启停顺序是严格受控的,操作第 N 个 pod 一定要等前 N-1 个执行完才可以
  3. StatefulSet 中的 Pod 采用稳定的持久化储存,并且对应的 PV 不会随着 Pod 的删除而被销毁

另外需要说明的是,StatefulSet 必须要配合 Headless Service 使用,它会在 Headless Service 提供的 DNS 映射上再加一层,最终形成精确到每个 pod 的域名映射,格式如下:

$(podname).$(headless service name)

有了这个映射,就可以在配置集群时使用域名替代 IP,实现有状态应用集群的管理

三、方案

借助 StatefulSet 和 Headless Service,集群的部署方案设计如下(图片来自参考文章):


网络异常,图片无法展示
|


配置步骤大概罗列如下:

  1. 配置共享文件系统 NFS
  2. 创建 PV 和 PVC
  3. 创建 ConfigMap
  4. 创建 Headless Service
  5. 创建 StatefulSet
  6. 初始化 redis 集群

实际操作

为了简化复杂度,这次先不配置 PV 和 PVC,直接通过普通 Volume 的方式来挂载数据。在K8s上搭建Mysql集群

1、创建 ConfigMap

先创建redis.conf配置文件

appendonly yescluster-enabled yescluster-config-file /var/lib/redis/nodes.confcluster-node-timeout 5000dir /var/lib/redisport 6379

然后kubectl create configmap redis-conf --from-file=redis.conf来创建 ConfigMap

2、创建 HeadlessService

apiVersion: v1kind: Servicemetadata:  name: redis-service  labels:    app: redisspec:  ports:  - name: redis-port    port: 6379  clusterIP: None  selector:    app: redis    appCluster: redis-cluster

3、创建 StatefulSet

apiVersion: apps/v1beta1kind: StatefulSetmetadata:  name: redis-appspec:  serviceName: "redis-service"  replicas: 6  template:    metadata:      labels:        app: redis        appCluster: redis-cluster    spec:      terminationGracePeriodSeconds: 20      affinity:        podAntiAffinity:          preferredDuringSchedulingIgnoredDuringExecution:          - weight: 100            podAffinityTerm:              labelSelector:                matchExpressions:                - key: app                  operator: In                  values:                  - redis              topologyKey: kubernetes.io/hostname      containers:      - name: redis        image: "registry.cn-qingdao.aliyuncs.com/gold-faas/gold-redis:1.0"        command:          - "redis-server"        args:          - "/etc/redis/redis.conf"          - "--protected-mode"          - "no"        resources:          requests:            cpu: "100m"            memory: "100Mi"        ports:            - name: redis              containerPort: 6379              protocol: "TCP"            - name: cluster              containerPort: 16379              protocol: "TCP"        volumeMounts:          - name: "redis-conf"            mountPath: "/etc/redis"          - name: "redis-data"            mountPath: "/var/lib/redis"      volumes:      - name: "redis-conf"        configMap:          name: "redis-conf"          items:            - key: "redis.conf"              path: "redis.conf"      - name: "redis-data"        emptyDir: {}

4、初始化 redis 集群

StatefulSet 创建完毕后,可以看到 6 个 pod 已经启动了,但这时候整个 redis 集群还没有初始化,需要使用官方提供的redis-trib工具。

我们当然可以在任意一个 redis 节点上运行对应的工具来初始化整个集群,但这么做显然有些不太合适,我们希望每个节点的职责尽可能地单一,所以最好单独起一个 pod 来运行整个集群的管理工具。

在这里需要先介绍一下redis-trib,它是官方提供的 redis-cluster 管理工具,可以实现 redis 集群的创建、更新等功能,在早期的 redis 版本中,它是以源码包里redis-trib.rb这个 ruby 脚本的方式来运作的(pip 上也可以拉到 python 版本,但我运行失败),现在(我使用的5.0.3)已经被官方集成进redis-cli中。

开始初始化集群,首先在 k8s 上创建一个 ubuntu 的 pod,用来作为管理节点:

kubectl run -i --tty redis-cluster-manager --image=ubuntu --restart=Never /bin/bash

进入 pod 内部先安装一些工具,包括wget,dnsutils,然后下载和安装 redis:

wget http://download.redis.io/releases/redis-5.0.3.tar.gztar -xvzf redis-5.0.3.tar.gzcd redis-5.0.3.tar.gz && make

编译完毕后redis-cli会被放置在src目录下,把它放进/usr/local/bin中方便后续操作

接下来要获取已经创建好的 6 个节点的 host ip,可以通过nslookup结合 StatefulSet 的域名规则来查找,举个例子,要查找redis-app-0这个 pod 的 ip,运行如下命令:

root@redis-cluster-manager:/# nslookup redis-app-0.redis-serviceServer:   10.96.0.10Address:  10.96.0.10#53
Name: redis-app-0.redis-service.gold.svc.cluster.localAddress: 172.17.0.10

172.17.0.10就是对应的 ip。这次部署我们使用 0,1,2 作为 Master 节点;3,4,5 作为 Slave 节点,先运行下面的命令来初始化集群的 Master 节点:

redis-cli --cluster create 172.17.0.10:6379 172.17.0.11:6379 172.17.0.12:6379


网络异常,图片无法展示
|


然后给他们分别附加对应的 Slave 节点,这里的cluster-master-id在上一步创建的时候会给出:

redis-cli --cluster add-node 172.17.0.13:6379 172.17.0.10:6379 --cluster-slave --cluster-master-id adf443a4d33c4db2c0d4669d61915ae6faa96b46


redis-cli --cluster add-node 172.17.0.14:6379 172.17.0.11:6379 --cluster-slave --cluster-master-id 6e5adcb56a871a3d78343a38fcdec67be7ae98f8


redis-cli --cluster add-node 172.17.0.16:6379 172.17.0.12:6379 --cluster-slave --cluster-master-id c061e37c5052c22f056fff2a014a9f63c3f47ca0

集群初始化后,随意进入一个节点检查一下集群信息:


网络异常,图片无法展示
|


至此,集群初始化完毕,我们进入一个节点来试试,注意在集群模式下redis-cli必须加上-c参数才能够访问其他节点上的数据:

网络异常,图片无法展示
|

5、创建 Service

现在进入 redis 集群中的任意一个节点都可以直接进行操作了,但是为了能够对集群其他的服务提供访问,还需要建立一个 service 来实现服务发现和负载均衡(注意这里的 service 和我们之前创建的 headless service 不是一个东西)

yaml 文件如下:

apiVersion: v1kind: Servicemetadata:  name: gold-redis  labels:    app: redisspec:  ports:  - name: redis-port    protocol: "TCP"    port: 6379    targetPort: 6379  selector:    app: redis    appCluster: redis-cluster

部署完做个测试:


网络异常,图片无法展示
|


很简单,到这里所有的工作就完毕了~


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2月前
|
人工智能 算法 调度
阿里云ACK托管集群Pro版共享GPU调度操作指南
本文介绍在阿里云ACK托管集群Pro版中,如何通过共享GPU调度实现显存与算力的精细化分配,涵盖前提条件、使用限制、节点池配置及任务部署全流程,提升GPU资源利用率,适用于AI训练与推理场景。
286 1
|
3月前
|
Kubernetes Devops 应用服务中间件
基于 Azure DevOps 与阿里云 ACK 构建企业级 CI/CD 流水线
本文介绍如何结合阿里云 ACK 与 Azure DevOps 搭建自动化部署流程,涵盖集群创建、流水线配置、应用部署与公网暴露,助力企业高效落地云原生 DevOps 实践。
359 1
|
2月前
|
弹性计算 监控 调度
ACK One 注册集群云端节点池升级:IDC 集群一键接入云端 GPU 算力,接入效率提升 80%
ACK One注册集群节点池实现“一键接入”,免去手动编写脚本与GPU驱动安装,支持自动扩缩容与多场景调度,大幅提升K8s集群管理效率。
254 89
|
4月前
|
存储 负载均衡 NoSQL
【赵渝强老师】Redis Cluster分布式集群
Redis Cluster是Redis的分布式存储解决方案,通过哈希槽(slot)实现数据分片,支持水平扩展,具备高可用性和负载均衡能力,适用于大规模数据场景。
368 2
|
2月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
446 5
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
290 9
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
3月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
7月前
|
缓存 NoSQL Java
Redis+Caffeine构建高性能二级缓存
大家好,我是摘星。今天为大家带来的是Redis+Caffeine构建高性能二级缓存,废话不多说直接开始~
1000 0
|
8月前
|
存储 NoSQL 数据库
Redis 逻辑数据库与集群模式详解
Redis 是高性能内存键值数据库,广泛用于缓存与实时数据处理。本文深入解析 Redis 逻辑数据库与集群模式:逻辑数据库提供16个独立存储空间,适合小规模隔离;集群模式通过分布式架构支持高并发和大数据量,但仅支持 database 0。文章对比两者特性,讲解配置与实践注意事项,并探讨持久化及性能优化策略,助你根据需求选择最佳方案。
313 5

推荐镜像

更多