k8s上部署redis集群app
本质上来说,在k8s上部署一个redis集群和部署一个普通应用没有什么太大的区别,但需要注意下面几个问题:
- REDIS是一个有状态应用 这是部署redis集群时我们最需要注意的问题,当我们把redis以pod的形式部署在k8s中时,每个pod里缓存的数据都是不一样的,而且pod的IP是会随时变化,这时候如果使用普通的deployment和service来部署redis-cluster就会出现很多问题,因此需要改用StatefulSet + Headless Service来解决
- 数据持久化 redis虽然是基于内存的缓存,但还是需要依赖于磁盘进行数据的持久化,以便服务出现问题重启时可以恢复已经缓存的数据。在集群中,我们需要使用共享文件系统 + PV(持久卷)的方式来让整个集群中的所有pod都可以共享同一份持久化
Headless Service
简单的说,Headless Service就是没有指定Cluster IP的Service,相应的,在k8s的dns映射里,Headless Service的解析结果不是一个Cluster IP,而是它所关联的所有Pod的IP列表
StatefulSet
StatefulSet
是k8s中专门用于解决有状态应用部署的一种资源,总的来说可以认为它是Deployment/RC
的一个变种,它有以下几个特性:
- StatefulSet管理的每个Pod都有唯一的文档/网络标识,并且按照数字规律生成,而不是像Deployment中那样名称和IP都是随机的(比如StatefulSet名字为redis,那么pod名就是redis-0, redis-1 ...)
- StatefulSet中ReplicaSet的启停顺序是严格受控的,操作第N个pod一定要等前N-1个执行完才可以
- StatefulSet中的Pod采用稳定的持久化储存,并且对应的PV不会随着Pod的删除而被销毁
另外需要说明的是,StatefulSet必须要配合Headless Service使用,它会在Headless Service提供的DNS映射上再加一层,最终形成精确到每个pod的域名映射,格式如下:
$(podname).$(headless service name)
有了这个映射,就可以在配置集群时使用域名替代IP,实现有状态应用集群的管理
配置步骤大概罗列如下:
- 配置共享文件系统NFS
- 创建PV和PVC
- 创建ConfigMap
- 创建Headless Service
- 创建StatefulSet
- 初始化redis集群
实际操作
由于使用的是minikube的单node环境,为了简化复杂度,这次先不配置PV和PVC,直接通过普通Volume的方式来挂载数据
创建ConfigMap
先创建redis.conf
配置文件
appendonly yes cluster-enabled yes requirepass 123456 cluster-config-file /var/lib/redis/nodes.conf cluster-node-timeout 5000 dir /var/lib/redis port 6379
然后kubectl create configmap redis-conf --from-file=redis.conf
来创建ConfigMap
创建HeadlessService
apiVersion: v1 kind: Service metadata: name: redis-service labels: app: redis spec: ports: - name: redis-port port: 6379 clusterIP: None selector: app: redis appCluster: redis-cluster
创建StatefulSet
apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: redis-app spec: 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: {}
创建Service
现在进入redis集群中的任意一个节点都可以直接进行操作了,但是为了能够对集群其他的服务提供访问,还需要建立一个service来实现服务发现和负载均衡(注意这里的service和我们之前创建的headless service不是一个东西)
yaml文件如下:
apiVersion: v1 kind: Service metadata: name: gold-redis labels: app: redis spec: ports: - name: redis-port protocol: "TCP" port: 6379 targetPort: 6379 selector: app: redis appCluster: redis-cluster
初始化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.gz tar -xvzf redis-5.0.3.tar.gz cd 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-service Server: 10.96.0.10 Address: 10.96.0.10#53 Name: redis-app-0.redis-service.gold.svc.cluster.local Address: 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
参数才能够访问其他节点上的数据:
如何确定Redis集群中各个节点的主从关系 1.首先通过命令(以192.168.203.141为例,-c代表集群的意思) ./redis-cli -h 192.168.203.141 -p 8001 -c 2.然后在输入 cluster nodes 命令,然后就会显示出各个节点的主从信息了 3.连接redis查看主从信息 info replication
作者:南辞、归
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律