如何基于k8s开发高可靠服务?容器云牛人有话说

author author     2022-11-02     401

关键词:

技术分享图片
?
?

k8s 是当前主流的容器编排服务,它主要解决「集群环境」下「容器化应用」的「管理问题」,主要包括如下几方面:
?
? 容器集群管理

  • 编排?
  • 调度?
  • 访问?

? 基础设施管理

  • 计算资源?
  • 网络资源?
  • 存储资源?
    ?

k8s 的强大依赖于它良好的设计理念和抽象,吸引了越来越多的开发者投入到 k8s 社区,把 k8s 作为基础设施运行服务的公司也逐步增多。
?
在设计理念方面,k8s 只有 APIServer 与 etcd (存储) 通信,其他组件在内存中维护状态,通过 APIServer 持久化数据。管理组件动作的触发是 level-based 而非 edge-based,并根据资源「当前状态」和「期望状态」进行相应动作。k8s 采用分层设计,基于各类抽象接口、由不同的插件满足不同的需求。
?
在抽象方面,不同的 workload 服务于不同的应用,如针对无状态应用的 Deployment、针对有状态应用的 StatefulSet 等。在访问管理方面,Service 解耦了集群内部服务访问方和提供者,Ingress 提供了集群外部到集群内部的访问管理。
?
k8s 虽然有良好的设计理念和抽象,但陡峭的学习曲线和不完善的开发资料极大增加了应用开发的难度。
?
本次分享将基于笔者的开发实践,以 MySQL on k8s 为例,描述如何基于 k8s 开发高可靠应用,尽可能抽象出最佳实践,降低基于 k8s 开发高可靠应用的成本。

?

MySQL on k8s

?
应用的设计和开发不能脱离业务需求,对 MySQL 应用的需求如下:

  1. 数据高可靠?
  2. 服务高可用?
  3. 易使用?
  4. 易运维?
    ?
    为了实现上述需求,需要依靠 k8s 和应用两方面协同工作,即开发基于 k8s 高可靠应用,既需要 k8s 相关的知识,也需要应用领域内的知识。
    ?
    下述将根据上述需求来分析相应的解决方案。

1.数据高可靠

数据的高可靠一般依赖于这几方面:

  • 冗余?
  • 备份/恢复?
    ?
    我们使用 Percona XtraDB Cluster 作为 MySQL 集群方案,它是 multi-master 的 MySQL 架构,实例间基于 Galera Replication 技术实现数据的实时同步。这种集群方案可以避免 master-slave 架构的集群在主从切换时可能出现的数据丢失现象,进一步提升数据的可靠性。
    ?
    ?技术分享图片
    ?
    ??备份方面,我们使用 xtrabackup 作为备份/恢复方案,实现数据的热备份,在备份期间不影响用户对集群的正常访问。
    ?
    提供「定时备份」的同时,我们也提供「手动备份」,以满足业务对备份数据的需求。
    ?
    2.服务高可用
    ?
    这里从「数据链路」和「控制链路」两个角度来分析。
    ?
    「数据链路」是用户访问 MySQL 服务的链路,我们使用 3 主节点的 MySQL 集群方案,通过 TLB (七牛自研的四层负载均衡服务) 对用户提供访问入口。TLB 既实现了访问层面对 MySQL 实例的负载均衡,又实现了对服务的健康检测,自动摘除异常的节点,同时在节点恢复时自动加入该节点。如下图:
    ?
    技术分享图片
    ??基于上述 MySQL 集群方案和 TLB,一个或两个节点的异常不会影响用户对 MySQL 集群的正常访问,确保 MySQL 服务的高可用。
    ?
    「控制链路」是 MySQL 集群的管理链路,分为两个层面:
  • 全局控制管理?
  • 每个 MySQL 集群的控制管理

全局控制管理主要负责「创建/删除集群」「管理所有 MySQL 集群状态」等,基于 Operator 的理念来实现。每个 MySQL 集群有一个控制器,负责该集群的「任务调度」「健康检测」「故障自动处理」等。
?

这种拆解将每个集群的管理工作下放到每个集群中,降低了集群间控制链路的相互干扰,同时又减轻了全局控制器的压力。
如下图:
?
技术分享图片
??这里简单介绍下 Operator 的理念和实现。
?
Operator 是 CoreOS 公司提出的一个概念,用来创建、配置、管理复杂应用,由两部分构成:
?

Resource

  • 自定义资源?
  • 为用户提供一种简单的方式描述对服务的期望?
    ?Controller
  • 创建 Resource?
  • 监听 Resource 的变更,用来实现用户对服务的期望?
    ?

工作流程如下图所示:?
?
技术分享图片
?
??即:

  1. 注册 CR (CustomResource) 资源?
  2. 监听 CR objects 的变更?
  3. 用户对该 CR 资源进行 CREATE/UPDATE/DELETE 操作?
  4. 触发相应的 handler 进行处理?
    ?
    我们根据实践,对开发 Operator 做了如下抽象:
    ??
    技术分享图片
    ?
    CR 抽象为这样的结构体:
    ??
    技术分享图片
    ?
    对 CR ADD/UPDATE/DELETE events 的操作,抽象为如下接口:
    ??
    ?技术分享图片
    ?
    在上述抽象的基础上,七牛提供了一个简单的 Operator 框架,透明化了创建 CR、监听 CR events 等的操作,将开发 Operator 的工作变的更为简单。?
    ?
    我们开发了 MySQL Operator 和 MySQL Data Operator,分别用来负责「创建/删除集群」和「手动备份/恢复」工作。
    ?
    由于每个 MySQL 集群会有多种类型的任务逻辑,如「数据备份」「数据恢复」「健康检测」「故障自动处理」等,这些逻辑的并发执行可能会引发异常,故需要任务调度器来协调任务的执行,Controller 起到的就是这方面的作用:
    ?
    技术分享图片
    ??
    通过 Controller 和各类 Worker,每个 MySQL 集群实现了自运维。
    ?
    在「健康检测」方面,我们实现了两种机制:
    ? 被动检测?
    ? 主动检测???
    「被动检测」是每个 MySQL 实例向 Controller 汇报健康状态,「主动检测」是由 Controller 请求每个 MySQL 实例的健康状态。这两种机制相互补充,提升健康检测的可靠度和及时性。
    ?
    对于健康检测的数据,Controller 和 Operator 均会使用,如下图所示:
    ??
    技术分享图片
    ?
    Controller 使用健康检测数据是为了及时发现 MySQL 集群的异常,并做相应的故障处理,故需要准确、及时的健康状态信息。它在内存中维护所有 MySQL 实例的状态,根据「主动检测」和「被动检测」的结果更新实例状态并做相应的处理。
    ?
    Operator 使用健康检测数据是为了向外界反映 MySQL 集群的运行情况,并在 Controller 异常时介入到 MySQL 集群的故障处理中。
    ?
    在实践中,由于健康检测的频率相对较高,会产生大量的健康状态,若每个健康状态都被持久化,那么 Operator 和 APIServer 均会承受巨大的访问压力。由于这些健康状态仅最新的数据有意义,故在 Controller 层面将待向 Operator 汇报的健康状态插入到一个有限容量的 Queue 中,当 Queue 满时,旧的健康状态将被丢弃。
    ?

    当 Controller 检测到 MySQL 集群异常时,将会进行故障自动处理。
    ?
    先定义故障处理原则:
    ? 不丢数据?
    ? 尽可能不影响可用性?
    ? 对于已知的、能够处理的故障进行自动处理?
    ? 对于未知的、不能够处理的故障不自动处理,人工介入???
    在故障处理中,有这些关键问题:?
    ? 故障类型有哪些?
    ? 如何及时检测和感知故障?
    ? 当前是否出现了故障?
    ? 出现的故障是哪种故障类型?
    ? 如何进行处理???
    针对上述关键问题,我们定义了 3 种级别的集群状态:
    ?

    Green
    ? 可以对外服务?
    ?运行节点数量符合预期?
    Yellow
    ?可以对外服务?
    ?运行节点数量不符合预期?
    Red
    ?不能对外服务?
    ?

同时针对每个 mysqld 节点,定义了如下状态:
?

Green
? 节点在运行?
? 节点在 MySQL 集群中?
Yellow?
? 节点在运行?
? 节点不在 MySQL 集群中?
Red-clean?
? 节点优雅退出?
Red-unclean?
? 节点非优雅退出?
Unknown?
? 节点状态不可知?
?

Controller 收集到所有 MySQL 节点状态后,会根据这些节点的状态推算 MySQL 集群的状态。当检测到 MySQL 集群状态不是 Green 时,会触发「故障处理」逻辑,该逻辑会根据已知的故障处理方案进行处理。若该故障类型未知,人工介入处理。整个流程如下图:
?
技术分享图片
?
??由于每种应用的故障场景和处理方案不同,这里不再叙述具体的处理方法。
?
3.易使用
?
我们基于 Operator 的理念实现了高可靠的 MySQL 服务,为用户定义了两类资源,即 QiniuMySQL 和 QiniuMySQLData。前者描述用户对 MySQL 集群的配置,后者描述手动备份/恢复数据的任务,这里以 QiniuMySQL 为例。
?
用户可通过如下简单的 yaml 文件触发创建 MySQL 集群的操作:
??
?技术分享图片
?
在集群创建好后,用户可通过该 CR object 的 status 字段获取集群状态:
??
技术分享图片
?
这里再引入一个概念:Helm。?
?
Helm 是为 k8s 提供的包管理工具,通过将应用打包为 Chart,标准化了 k8s 应用的交付、部署和使用流程。
?
Chart 本质上是 k8s yaml 文件和参数文件的集合,这样可以通过一个 Chart 文件进行应用的交付。Helm 通过操作 Chart,可一键部署、升级应用。
?
由于篇幅原因及 Helm 操作的通用性,这里不再描述具体的使用过程。
?
4.易运维
?
除了上述实现的「健康检测」「故障自动处理」以及通过 Helm 管理应用的交付、部署,在运维过程中还有如下问题需要考虑:
? 监控/告警?
? 日志管理?
?
我们通过 prometheus + grafana 做监控/告警服务,服务将 metric 数据以 HTTP API 暴露给 prometheus,由 prometheus server 定时拉取。开发人员在 grafana 上将 prometheus 中的监控数据可视化,根据对监控图表和应用的把握,在监控图中设置告警线,由 grafana 实现告警。
?
这种先可视化监控后告警的方式,极大程度上增强了我们对应用运行特征的把握,明确需要关注的指标和告警线,降低无效告警的产生量。
?
在开发中,我们通过 gRPC 实现服务间的通信。在 gRPC 生态系统中,有个名为 go-grpc-prometheus 的开源项目,通过在服务中插入几行简单的代码,就可以实现对 gRPC server 所有 rpc 请求的监控打点。
?
对于容器化服务,日志管理包括「日志收集」和「日志滚动」两方面维度。
?
我们将服务日志打到 syslog 中,再通过某种手段将 syslog 日志转入到容器的 stdout/stderr 中,方便外部采用常规的方式进行日志收集。同时,在 syslog 中配置了 logrotate 功能,自动进行日志的滚动操作,避免日志占满容器磁盘空间引发服务异常。
?
为了提升开发效率,我们使用?https://github.com/phusion/baseimage-docker?作为基础镜像,其中内置了 syslog 和 lograte 服务,应用只关心把日志打入 syslog 即可,不用关心日志的收集和日志滚动问题。
?

小结

?
通过上述描述,完整的 MySQL 应用架构如下:
?
技术分享图片
?
??在开发基于 k8s 的高可靠 MySQL 应用过程中,随着对 k8s 和 MySQL 理解的深入,我们不断进行抽象,逐步将如下通用的逻辑和最佳实践以模块的方式实现:

  • Operator 开发框架?
  • 健康检测服务?
  • 故障自动处理服务?
  • 任务调度服务?
  • 配置管理服务?
  • 监控服务?
  • 日志服务?
  • etc.???
    随着这些通用逻辑和最佳实践的模块化,在开发新的基于 k8s 的高可靠应用时,开发者可像「搭积木」一样将与 k8s 相关的交互快速搭建起来,这样的应用由于已经运用了最佳实践,从一开始就具备高可靠的特性。同时,开发者可将注意力从 k8s 陡峭的学习曲线转移到应用自身领域,从应用自身加强服务的可靠性。
    ?

牛人说

?
牛人说专栏致力于技术人思想的发现,其中包括技术实践、技术干货、技术见解、成长心得,还有一切值得被发现的技术内容。我们希望集合最优秀的技术人,挖掘独到、犀利、具有时代感的声音。
?
?

云容器引擎:让企业it创新更简单更可靠

云容器引擎:让企业IT创新更简单更可靠互联网+时代,如何帮助企业实现应用快速交付,迅速响应业务变化抓住商机?华为CCE云容器引擎定义企业级容器云,助你成功!云容器引擎是一种高性能可扩展的容器服务,为企业提供应... 查看详情

如何基于k8s多租能力构建serverlesscontainer

当前Kubernetes已经成为名副其实的企业级容器编排规范,很多云平台都开始提供兼容Kubernetes接口的容器服务。而在多用户支持方面,多数平台选择直接提供专属虚机集群,用户需要花费大量精力处理集群规模、资源利用率、费用... 查看详情

大海航行靠舵手华为云靠什么征服k8s?

...行、服务发现、扩容缩容等整一套功能,本质上可看作是基于容器技术的mini-PaaS平台。Kubernetes的目标是让开发者可以像管理产品一样管理服务,同时提高资源的利用率,让开发者更关注在应用开发本身,高可用的事情交给Kubernet... 查看详情

docker圣经:大白话说docker底层原理,6w字实现docker自由(代码片段)

...的价值Docker巨大的价值Docker是一个开源的应用容器引擎,基于Go语言开发。Docker遵从Apache2.0协议开源。Docker的本质:先来说说Docker的本质Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任... 查看详情

聊聊k8s(文末送书~)(代码片段)

...使用数字8代替,就成为了K8S。开个玩笑,本文从开发人员的视角带大家理解一下Kubernetes。当然,文末还会给你送上一份惊喜。概述在JAVA开发中使用dockerrun命令配合上自建的Docker仓库可以很容易部署JAVA服务,但是... 查看详情

k8s应用案例介绍——阿里云

...云原生领域的发展。阿里云的Kubernetes大规模实践经验:如何基于Kubernetes推动阿里巴巴应用运维技术栈走向云原生如何推动Kubernetes自身的技术进步充分挖掘云原生时代的红利助力阿里巴巴大幅降低双11的IT成本。容器在阿里巴巴... 查看详情

k8s高可用版本部署(代码片段)

...核的namespace功能实现容器的资源隔离k8s的namespace:是基于名称实现项目容器的隔离,叫命 查看详情

高并发实战

...keeper_source_code.gitNettynetty是JBOSS提供的一个JAVA开源框架,是基于NIO的客户端/服务器编程框架,它既能开发高并发,高可用,高可靠性的网络服务器程序,也可以开发高可用,高可靠的客户端程序Redis一个可以快速存储的内存数据库,Redis是R... 查看详情

kubeadm实现的高可用(代码片段)

...整的生态环境2.什么是kubernetes  首先,他是一个全新的基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服... 查看详情

k8s之为pod创建基于http的存活探针(代码片段)

Kubernets有以下三种探测容器的机制1、HTTPGET探针对容器的IP地址(你指定的端口和路径)执行HTTPGET请求。如果探测器收到响应,并且响应状态码不代表错误(换句话说,如果HTTP响应状态码是2XX或3XX),则认为探测成功。如果服务... 查看详情

容器生态系统(续)

...为集群在分布式环境中运行。    容器编排引擎基于容器的应用一般会采用微服务架构。在这种架构下,应用被划分为不同的组件,并以服务的形式运行在各自的容器中,通过API对外提供服务。为了保证应用的高可用,... 查看详情

k8s(代码片段)

...包含有节点代理kubelet和Master组件(APIs,scheduler,etc),一切都基于分布式的存储系统  以下是摘自凌风探梅的总结.什么是kubernetes  首先,他是一个全新的基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器... 查看详情

基于coredns和k8s构建云原生场景下的企业级dns

...术,就是在转向云原生技术的过程中。在容器化进程中,如何保持业务的平稳迁移,如何将现有的一些服务设施一并进行容器化迁移,也是众多企业较为关注的点。以DNS为例,如何构建一个云原生的企业DNS系统?CoreDNS简介CoreDNS... 查看详情

大海航行靠舵手华为云靠什么征服k8s?

...行、服务发现、扩容缩容等整一套功能,本质上可看作是基于容器技术的mini-PaaS平台。Kubernetes的目标是让开发者可以像管理产品一样管理服务,同时提高资源的利用率,让开发者更关注在应用开发本身,高可用的事情交给Kubernet... 查看详情

mac上java开发软件

...ubernetes(理论+实战)Kubernetes(k8s)是一个全新的基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资... 查看详情

k8s学习圣经:大白话说k8s底层原理,14w字实现k8s自由(代码片段)

...操(学习圣经)Kubernets简称k8s,用于自动部署,扩展和管理容器化应用程序的开源系统。也就是能帮我们部署和管理分布式系统。学习Kubernets的相关资料中文官网:https://kubernetes.io/zh-cn/docs/官方文档:https://kubernetes.io/zh/docs/home/(... 查看详情

基于prometheus监控k8s集群

...如果你还没有安装库k8s集群,情参考: 从零开始搭建基于calico的kubenetes前言kubernetes显然已成为各大公司亲睐的容器编排工具,各种私有云公有云平台基于它构建,那么,我们怎么监控集群中的所有容器呢?目前有三套方案... 查看详情

容器网络通,但业务网络不通,怎么办?

...通过curl测试也没通,那到底是不是业务自身的问题?该如何排查此类呢?是不是k8s或docker的bug呢?问题二描述:大家都知道etcd作为k8s集群的核心数据存储系统,堪称是k8s的大脑,所以etcd的稳定级别要求不言而喻了,那么大家试... 查看详情