写点什么

网易数帆基于 K8s 的 Redis 云原生实践:从设计到大规模落地

2021 年 2 月 03 日

网易数帆基于K8s的Redis云原生实践:从设计到大规模落地

1. 背景


Redis 是各大业务系统中常用的缓存中间件,以解决巨大的网络流量和数据访问场景,并且通过中间件可以实现系统之间的解耦,并提升系统的可扩展性。


对于传统的 IT 资源,中间件的运维一般是需要运维人员全手动搭建和维护,自动化程度低,无法满足业务快速发展需求。


云计算时代的到来为企业灵活多变的业务和僵化的 IT 基础设施之间的尖锐矛盾提供了完美的解决方案。弹性的云计算资源根据业务流量进行扩缩,提高资源利用率;平台化的资源托管,解决了传统集群的运维繁琐问题;云计算重构了企业 IT 基础设施,在业务系统逐渐迁移到云上的过程中,中间件起到了至关重要的作用。


在云计算发展初期,大部分的中间件架设于物理机或者采用 OpenStack 搭建的虚拟云主机之上,通过 OpenStack 对资源的管理和虚拟化,加上具体中间件的运维逻辑实现的管控服务,实现中间件的运维和高可用管理。这种方式缺乏灵活性,无法满足用户多云、混合云等需求,并且由于 OpenStack 的虚拟化复杂性,管控服务的维护成本高。


云原生时代的应用轻量化,将与核心业务无关的能力剥离出去。这些能力将以中间件的形式下沉到基础设施中,成为云的一部分,从而加强和改善应用的运行环境,实现应用轻量化。


云原生赋于中间件新的内涵,即云原生中间件下沉到云基础设施,保持功能不变的情况下与应用解耦,在运行时为应用动态赋能,支撑上层应用系统。


云原生中间件是指在公有云、私有云和混合云等动态环境中,用于构建和运行可弹性扩展的应用,持续交付部署业务生产系统的分布式中间件。在这种大趋势下,网易数帆开始了轻舟云原生中间件的实践,除了本文介绍的 Redis,还包括 MySQL、Elasticsearch、Kafka、RocketMQ、RabbitMQ、ZooKeeper 等。

2. Redis 的云原生化

网易数帆基于云原生强大编排能力和 Kubernetes 的通用接口,通过自定义 Operator 实现状态中间件的云原生化,云原生化的 Redis 相对云主机虚拟化有更好的性能、更低的 IT 成本、更轻量级的资源管理、更灵活的调度策略、更快速的故障恢复和更强的系统自愈能力。

2.1 容器原生


采用容器技术对 Redis 进行服务部署,可以实现 Iaas 底层资源差异的隔离,利用灵活的容器编排技术,实现服务高可用部署。相比于云主机方案,容器方案可以做到采用更小的镜像,更快的启动速度和更轻量级的资源隔离方案,实现更小的性能损耗。


K8s 中 pod 通过 Request 和 Limit 对 CPU 和 Memory 进行资源控制,其中 Request 表示请求资源,主要用于 K8s 的调度,而 Limit 则是对 Node 资源的限制和保护,用户限制 Pod 自身占用资源,保护其他 Pod 的资源占用。


对于 Redis 服务,由于 Redis 服务的特殊性,Redis 为单服务进程模式,并且在特殊场景下会 fork 进程做一些备份或 aof 重写操作,并且会占用额外一部分内存 buffer,所以,


  • 对于 CPU 资源来说,对于 Redis 的 Pod,Request 采用 1 core,Limit 选择 2 core 或不限制

  • 对于内存资源,Request 是用户实际申请的容量,limit 设置为两倍的实际申请容量


这样既可以限制单个 pod 内存占用,又可以满足 Redis 本身在特定场景下对内存资源的额外占用,防止进程被 OOM。但是对于 cpu limit 的设定,经过线上验证,最终选择了不设置。下面是 Pod 中 cpu limit 的工作原理。



上面的图说明了 CPU limit 的工作原理,场景 1 中通过cfs_quota_us配置的单个容器的 limit 时间片是 200ms,在两个线程的情况下不会发生产生 throttle;场景 2 中,如果是 10 线程的应用,则在相同的 quota 配置下,会出现 10 个线程先同时调度运行 20ms,再触发 cpu throttle 被调度强制回收 cpu 使用权。


可以通过上述的工作原理,配置 cpu limit 会在某些场景下触发 cpu throttle,产生慢查询,通过slowlog get命令甚至可能看到普通的INFO命令统计耗时可能会超过 10ms。


并且在 Linux kernel 4.18 之前,由于存在调度 bug,该问题更加严重。所以对于 Redis 服务,本来为单进程服务,不会对 cpu 资源无限制滥用,应尽量避免配置容器的 cpu limit。


$ cat /sys/fs/cgroup/cpu,cpuaact/cpu.statnr_periods 45474775nr_throttled 281291throttled_time 21533704485135
复制代码


上面nr_throttled统计的含义是 cpu 被限制运行的次数。

2.2 服务状态

对于 Redis 中间件,本身就是状态服务,而 K8s 起初是为无状态服务设计。好在 K8s 可以通过自定义资源 CRD 来自定义 Controller 完成状态服务的控制。


对于有状态的 Redis 而言,需要考虑到数据分布、pod 的异常、副本的复制、状态的恢复等。



通过自定义 Controller 来完成像 Redis 有状态服务的自动化管理,Controller 具有状态服务的数据分布、pod 的异常、副本的复制、状态的恢复等专业运维技能,对用户而言,当机器宕机,用户也不需要介入运维,Redis 似乎完成了从有状态服务向无状态服务转变。


  • 高可用调度


K8s 的原生调度器无法实现对 Redis 对高可用的调度限制,增加了对于 node 节点、az 可用域和多机房的调度控制。



  1. 支持单 node 节点集群调度的 pod 数量上限,防止单个 Redis 集群的 pod 集中调度到单个 node 节点,存在宕机风险。

  2. 支持单机房调度 Pod 数量上限,防止在多可用域部署场景下,单个可用域可调度的 pod 数量过大,无法容忍单个可用域故障导致的服务不可用风险。

  3. 支持多机房选择,支持在多可用域基础设施环境下,通过机房的调度定义,可以灵活对 Redis 集群定义可用域部署策略。


  • 状态管理


Redis 单集群规模能达到上百分片,所以采用单个 Statefulset 管理灵活性差,并且无法快速定位资源对应的数据分片,所以我们采用了单个 Statefulset 管理单个 Redis 集群分片的方式,单个 Redis 集群可能有上百个 Statefulset 组成。使用更细粒度的控制,可以做到运维粒度更小,对资源的控制并发度更加可控。


  1. 反亲和配置。对于单可用域的集群,保证单个分片的 pod 调度到不同的 node 节点;对于多可用域的集群,保证单个分片的 pod 调度到不同的可用域。

  2. 滚动升级。滚动升级是指的对实例的资源规格变更或者 Redis 版本的升级,Operator 可以通过对 Statefulset 和 Redis cluster 的状态控制,实现无缝的资源重建,整个过程可以通过并发度调整来调整整个滚动升级的速度。

  3. 实例重启、重建。Pod 异常后会删除重新创建,创建的新 Pod 的 IP 会发生变化,所以在新 Pod 创建后,Operator 会首先清理旧的实例信息,然后将新启动的 Pod 作为新的 Redis 实例节点加入集群,通过数据复制重建 Redis 集群分片的数据高可用。

2.3 状态声明和事件通知



集群的状态通过 Reconcile 完成,Reconcile 时,通过对集群当前状态的计算和声明的状态进行对比,如果不满足声明的状态,则进行对应的操作,如:


  1. 集群停服状态。

  2. 调度 configmap 状态。

  3. service 状态。

  4. 规格和版本变更状态。

  5. 主动运维操作状态。

  6. 集群状态异常修复。

  7. 集群资源和配置状态。

  8. proxy 资源资源。

  9. 定时任务检查。


由于 Reconcile 过程成本较高,并且默认情况下,如果没有订阅的事件发生 Reconcile 的周期性触发时间 30s,时间较长,需要通过一定的手段加快异常发现的速度和状态异常告警。



通过增加 Healthy checker,周期性的对每个 Redis 集群进行状态检查,如果检查到集群本身存在异常,首先进行事件告警,然后将对应的 Custom resource 加入 Reconcile 队列,触发一次全量 Reconcile,使集群状态调整到正常状态。

2.4 观测性

可观测性包含了监控、告警、日志聚合、分布式跟踪和依赖分析等部分,通过收集处理数据来定位问题,并简化信息的访问,实时深入的观察整个应用系统的健康状态,从业务资源计量等多个维度进行度量。日志、指标和请求跟踪是可观测性的基础。



Redis 的监控采用的经典的 Exporter+Promethus 的方案,搜集的监控数据通过自定义的 Grafana 前端将服务状态可视化。



服务的告警分为两类,其中一类就是 Promethus 的监控指标状态监控告警,另一类的 Operator 主动发出的 Event 事件告警。状态监控告警主要负责的是集群本身运行指标的一些异常监控,如:连接数、内存使用率、CPU 使用率、数据淘汰、网络带宽等;事件告警主要是 Operator 发现的一些集群异常、Operator 进行的一些变更操作失败或者事件通知。


Operator 本身的日志和 Redis 的日志也会通过 filebeat 收集到 Elasticsearch 中,用于实时搜索异常。

2.5 弹性伸缩

得益于 K8s 的声明式 API,可以通过更改声明的资源规模可以对集群进行无损弹性扩容和缩容。


如根据流量波峰波谷规律,可定期在波峰到来时对 Proxy 进行扩容,波峰过后对 Proxy 进行缩容;


根据业务的数据容量规律,可一键对 Redis cluster 分片扩容缩容和数据均衡。



2.6 服务形态

轻舟中间件 Redis 包含了常用的 Redis 服务形态,有哨兵模式和集群模式,并且服务接入方式也有多种:


  • 原生 redis cluster 模式,兼容原生使用方式



  • redis cluster + proxy 模式,屏蔽集群细节



  • redis cluster + istio 模式,配合微服务的云原生使用方式



  • 原生 sentinel 模式,兼容哨兵使用方式



  • VIP 模式,固定 IP,客户端采用单节点使用方式,仍然保留高可用



3. 平台化



以云平台(Cloud Planform)的形式提供服务将中间件功能下沉到基础设施,以云平台的形式对外输出能力,提供中间件的接口供用户按需调用,并且通过平台可以实现多云和混合云的部署管控能力,用户无需关注中间件服务的下层资源调度与运维,更加聚焦轻量级的业务应用。


轻舟平台提供了完善的认、用户管理、角色权限、操作审计、监控、OpenAPI 等完善的平台能力,使得中间件和业务联系更加紧密,实现全栈云原生化。


4. 落地场景

轻舟中间件 Redis 已经实现大规模落地,包括在网易集团内部网易云音乐、网易传媒和网易严选生产环境大规模落地,使得集团内部的 Redis 运维效率和服务可用性大幅提升,同时也通过网易数帆商业化平台在金融领域落地,将诞生于互联网公司的云原生中间件能力输送到传统行业数字化业务中。

2021 年 2 月 03 日 11:291761

评论 2 条评论

发布
用户头像
这篇很好
2021 年 02 月 04 日 08:38
回复
感谢池老师认可!
2021 年 02 月 08 日 16:00
回复
没有更多了
发现更多内容

什么?还不懂c++vector的用法,你凭什么勇气来的!

良知犹存

c++

LAXCUS 大数据集群操作系统:一个分布式分时共享 E 级系统软件(六)

陈泽云

人工智能 大数据 算法

IMC总决赛精彩对战应接不暇,英特尔酷睿极致性能燃爆比赛现场!

intel001

微众银行大数据平台建设方案

康月牙Rita

大数据 开源 金融 平台 微众银行

【涂鸦物联网足迹】涂鸦云平台接口列表

IoT云工坊

人工智能 接口 物联网 API 智能家居

高交会科技盛宴:“科技改变生活,创新驱动发展”

13530558032

“双11”购物狂欢节,所有女生走进了谁的直播间?

BonreeAPM

APM AIOPS 拨测 直播 用户体验

【Mycat】作为Mycat核心开发者,怎能不来一波Mycat系列文章?

冰河

分布式事务 分布式数据库 系统架构 分布式存储 mycat

面试,到底在考察什么?

程序员架构进阶

面试 方法论

LAXCUS 大数据集群操作系统:一个分布式分时共享 E 级系统软件(七)

陈泽云

人工智能 大数据 算法

轻松云上揽胜中华,靠的就是这份聪明的“地图”!

华为云开发者社区

MySQL 数据库 postgresql AI 地图

云图说|多模态AI开发套件HiLens Kit:超强算力彰显云上实力

华为云开发者社区

人工智能 开发者 物联网 机器人 华为云

阿里P8架构师“墙裂”推荐:Java程序员必读的架构进阶热门书籍,值得学习!

Java成神之路

Java 程序员 架构 面试 编程语言

多线程并发主题-ThreadLocalRandom类

Geek_896619

Java 并发编程 线程

mongodb 源码实现系列 - 网络传输层模块实现四

杨亚洲(专注mongodb及高性能中间件)

MySQL 数据库 mongodb 高性能 分布式数据库mongodb

手把手教你本地 k8s 集群搭建云原生 Tekton CICD 流水线

比伯

Java 大数据 编程 架构 计算机

阿里大牛说:你凭什么搞不懂SpringBoot,Cloud,Nginx与Docker

小Q

Java 学习 编程 架构 面试

《迅雷链精品课》第三课:区块链主流框架分析

迅雷链

区块链 区块链方案 区块链+ 区块链应用

C++多元组tuple使用方法?你熟悉吗?快来看看吧

良知犹存

c++

我就是增发、健身、养猫、社交通通拥有的锦鲤本鲤

脑极体

mPaaS 客户端问题排查之漫长的 3s 等待之谜

阿里云金融线TAM SRE专家服务团队

mPaaS

java-File对象

Isuodut

Teambition 网盘 VS 阿里云盘:阿里这个浓眉大眼的也开始玩赛马了?

郭旭东

阿里云 阿里云网盘

Github标星67.9k的微服务架构以及架构设计模式笔记我真的爱了

Java架构之路

Java 程序员 架构 面试 编程语言

WE大会上,科学家们是怎样治愈“小破球”的?

脑极体

握草!美团P8整理的280页超详细Docker实战文档简直太香了,让你对如日中天的Docker有更深入的了解。

Java架构之路

Java 程序员 架构 面试 编程语言

亲测三遍!8步搭建一个属于自己的网站

华为云开发者社区

MySQL Linux 开发者 网站 华为云

一位Java大牛结合自己的业务和平台多年来在Netty实践中积累的经验总结《Netty进阶之路:跟着案例学Netty》。

Java成神之路

Java 程序员 架构 面试 编程语言

作为一名Java程序员,技术栈的广度深度都不够还想要高薪?请先把这些技术掌握再说。

Java成神之路

Java 程序员 架构 面试 编程语言

DeFi质押挖矿系统开发技术

薇電13242772558

区块链 defi

为什么我就面试阿里P6,好不容易过2面,3面来个架构师来吊打我?

小Q

Java 学习 程序员 架构 面试

微服务架构下如何保证事务的一致性

微服务架构下如何保证事务的一致性

网易数帆基于K8s的Redis云原生实践:从设计到大规模落地-InfoQ