Kubernetes学习总结(16)—— Kubernetes 实战之部署 Redis 集群
一、问题分析
本质上来说在 k8s 上部署一个 redis 集群和部署一个普通应用没有什么太大的区别,但需要注意下面几个问题:
Redis 是一个有状态应用:这是部署 redis 集群时我们最需要注意的问题,当我们把 redis 以 pod 的形式部署在 k8s 中时,每个 pod 里缓存的数据都是不一样的,而且 pod 的 IP 是会随时变化,这时候如果使用普通的 deployment 和 service 来部署 redis-cluster 就会出现很多问题,因此需要改用 StatefulSet + Headless Service 来解决。
数据持久化: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
的一个变种,它有以下几个特性:
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,实现有状态应用集群的管理
三、方案
借助 SetatefulSet 和 Headless Service,集群的部署方案设计如下(图片来自参考文章):
配置步骤大概罗列如下:
配置共享文件系统NFS
创建PV和PVC
创建ConfigMap
创建Headless Service
创建StatefulSet
初始化redis集群
四、实际操作
为了简化复杂度,这次先不配置 PV 和 PVC,直接通过普通 Volume 的方式来挂载数据。Kubernetes学习总结(15)—— Kubernetes 实战之部署 Mysql 集群
1、创建 ConfigMap
先创建redis.conf
配置文件
appendonly yes
cluster-enabled yes
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。
2、创建 HeadlessService
apiVersion: v1
kind: Service
metadata:name: redis-servicelabels:app: redis
spec:ports:- name: redis-portport: 6379clusterIP: Noneselector:app: redisappCluster: redis-cluster
3、创建 StatefulSet
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:name: redis-app
spec:serviceName: "redis-service"replicas: 6template:metadata:labels:app: redisappCluster: redis-clusterspec:terminationGracePeriodSeconds: 20affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- redistopologyKey: kubernetes.io/hostnamecontainers:- name: redisimage: "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: rediscontainerPort: 6379protocol: "TCP"- name: clustercontainerPort: 16379protocol: "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.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#53Name: 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 adf443a4d33c4db2c0d4669d61915ae6faa96b46redis-cli --cluster add-node 172.17.0.14:6379 172.17.0.11:6379 --cluster-slave --cluster-master-id 6e5adcb56a871a3d78343a38fcdec67be7ae98f8redis-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: v1
kind: Service
metadata:name: gold-redislabels:app: redis
spec:ports:- name: redis-portprotocol: "TCP"port: 6379targetPort: 6379selector:app: redisappCluster: redis-cluster
部署完做个测试:
Kubernetes学习总结(16)—— Kubernetes 实战之部署 Redis 集群相关推荐
- 在K8s上部署Redis 集群
一.前言 架构原理:每个Master都可以拥有多个Slave.当Master下线后,Redis集群会从多个Slave中选举出一个新的Master作为替代,而旧Master重新上线后变成新Master的 ...
- k8s部署redis集群
K8S部署Redis Cluster集群 kubernetes部署单节点redis: https://www.cnblogs.com/zisefeizhu/p/14282299.html Redis ...
- 通过operator部署redis集群(ucloud版)
operator部署有状态的应用会简单很多 github文档:https://github.com/ucloud/redis-cluster-operator#deploy-redis-cluster ...
- Centos6.6部署Redis集群
Centos6.6部署Redis集群 1 环境准备 1 环境安装redis 1 安装ruby 2 配置redis主从环境 3 部署redis sentinel服务器 5 集群使用 13 当前集群环境说 ...
- 三台机器使用Docker部署Redis集群
三台机器使用Docker部署Redis集群 我们这里采用Docker在三台服务器上面进行Redis集群的搭建,它方便快捷.容易上手. 1.集群原理 在Redis集群中,所以的节点彼此关联,节点内部通过 ...
- operator部署redis集群
operator部署redis集群 1.现在operator的redis相关包 git clone https://github.com/ucloud/redis-cluster-operator.g ...
- docker部署redis集群_Docker部署Redis集群----第九节(docker-redis哨兵集群“轮询分流”篇实例一)...
到此,我们的 Redis 哨兵集群就结束了,本篇章是第九篇章,也是使用集群方式的实例一来实现php的轮询分流. 1.准备工作: 在我们上一篇章实现redis 哨兵集群的基础上开始,在服务器上部署php ...
- 2万字好文!手把手教你实现 Docker 部署 Redis 集群
点击上方 "程序员小乐"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 关注订阅号「程序员小乐」,收看更多精彩内容 每日英文 Life is not ...
- docker部署redis集群实现动态扩缩容
目录 思考 分布式存储的解决方案 哈希取余分区 一致性哈希算法分区 哈希槽分区 采用哈希槽分区 部署三主三从(docker) 准备工作 创建3主3从redis实例 进入容器中,构建主从关系 主从容错切 ...
最新文章
- Python+OpenCV 图像处理系列(5)—— 图像 ROI 操作及通道的拆分合并
- LeetCode Integer to Roman(数字转罗马)
- Stanford UFLDL教程 白化
- typedef enum的用法(枚举)
- Angular路由跳转时,如何传递信息
- 我的世界1.11服务器咋发信息,我的世界进服务器怎么注册怎么发信息
- kotlin编译失败_Kotlin使用GraalVM开发原生命令行应用
- 宁夏小学三年级计算机下册教案,宁夏信息技术教案
- 【转】8 个效果惊人的 WebGL/JavaScript 演示
- 《跟菜鸟学Cisco UC部署实战》-上线了(线下培训班开班,见百度云)
- 如何使用PowerShell将VS Code扩展导出到另一台计算机
- java布尔三目运算符_Java关系运算符,boolean运算符,三元运算符
- FCKeditor使用
- 联想电脑重装win7系统详细图文教程
- MATLAB实现 ICA 鸡尾酒会语音分离
- https 单向认证和双向认证
- !-- --与%-- --%
- 怎样安装linux系统
- 《大家的日语3》语法整理1~48课
- 压力表负值表示什么_弹簧管式压力表轻敲变动量居然有负值,我不知道是不是我学的不好,还是计量所所长脑子有病...
热门文章
- 中小学计算机听课记录表,小学数学听课记录范文表格
- matlab 分数 函数,Matlab 中 residuez函数的使用
- java中路由的使用方法_java – 在camel路由中使用方法作为生产者
- java年月日时分秒格式_Java 日期时间 LocalDate LocalTime LocalDateTime类
- 真空压力变送器怎么样零点标定_对于变送器你知道多少?
- 哪个不是python合法的标识符_哪个不是python合法标识符
- 智能计米器jk76怎么安装_春节智能锁消费指南:只看价格的后果有多严重?
- ros_readbagfile:未找到命令的解决方法
- C++新特性探究(七):初始化列表(Initialization List)
- 计算机配置cpo,使用域组策略及脚本统一配置防火墙-20210421070355.docx-原创力文档...