容器化管理演进

演进过程

swarm

单集群,共享宿主机端口,服务发版有一定时间服务不可用。

k8s 原生控制器

多集群支持,支持简单的发布策略

主要为黑盒操作,即以修改 k8s 原生资源配置为主,无法实现灰度发布,蓝绿发布等高级功能。

随着容器化的持续进行,越来越多的业务跑到 k8s 集群上,目前已有 6 个不同集群对外提供服务。

目前 k8s 社区十分活跃,为了稳定性和安全性,版本升级较频繁,目前由 1.10,1.14,1.15,1.16 多个版本的集群并存。
此外,阿里云、私有云并行存在,基础设施不同。
多集群,公有云、多版本,集群差异较大,统一管理逻辑复杂,维护困难。

服务状态主要靠同步查询,难以渐进式控制发布过程。用户体验不够友好,查看状态需要手动刷新。

边界不清晰, 管理系统(chons)关注点太多,越来越复杂,不好维护。

封装不够完善,暴露了较多 k8s 内部细节给前端、以及用户,增加其认知成本。

扩展不方便,每暴露一个配置项,都需要新加接口,成本高。

组件控制器

k8s 是一个伟大的项目,为很多服务管理过程中常用的资源做了高度抽象,并且 k8s 系统高度通用、高度灵活,能够完成服务管理和维护的多种多样的需求。
因此同时 k8s 系统也是一个较复杂的系统。除了 k8s 专家,不论是开发和运维同学,拿到 k8s 的资源配置文件都显得过于复杂,搞得人一头雾水。

解决复杂计算机系统的问题的一个通用的方法就是利用分层的思想,在复杂系统之上再抽象出一层,分层管理:

  • 高级编程语言在汇编语言之上
  • 操作系统在驱动之上
  • 网络七层模型层层抽象

按照这个思路,为了依托 k8s 生态为公司服务管理平台持续赋能,以及更好地解决多集群精细化管理的问题,我们在 k8s 原生资源之上抽象出组件层,并采用 k8s CRD operator 的模式开发了组件控制器,每个控制器独立管理每个集群的服务:

  • 屏蔽 Deployment, StatefulSet, Service, Ingress 等内部实现细节,降低研发人员心智负担
  • 集群管理与上层业务调度解耦
  • 接近 k8s 原生资源的保障
  • 集群生命周期管理
  • 接近 k8s 原生资源的体验

k8s 组件图

设计思路

组件是一等公民

deployment 由 deployment controller 控制;
service 由 service controller 控制;
组件(component) 由 component controller 控制。

自定义 spec 以简洁的方式支持公司业务类型

采用 Config As A Service 支持灵活扩展,减少接口,减少开发成本。

例如最简单的服务定义可能包括:开发语言,服务类型,端口和镜像即可,如下 spec 部分所示。

apiVersion: component.luojilab.com/v1alpha1
kind: Component
metadata:
  name: nginx
spec:
  workloadType: Deployment
  developLanguage: python
  runType: server
  image: python-demo:latest
  port: 8080

在尽可能保持简洁的基础上,如果用户有特殊需求,必须也能支持。

向下兼容

支持老服务无感升级

方便升级

需要能够方便的进行集群级别的批量调整,比如配置调整,性能优化等。

灵活扩容

性能不足时,需支持灵活扩容

资源定义

type(GVK):

  • group(luojilab.com)
  • version(v1alpha1)
  • kind(Component)

meta:

  • label
  • annotation
  • create_datetime
  • update_datetime
  • delete_datetime

spec:

控制器的基本本原理

reconcile

所有接口幂等性

触发机制

level based trigger

edge based trigger

level + edge based trigger

模板化管理

集群差异管理

负载类型模板

开发语言模板

部署发版流程

滚动发布

灰度发布

状态变更感知

status 变更
event 事件推送

controller 升级/灰度

annotation:
"component.luojilab.com/unmanaged": true 则不会触发控制器,可用于选择组件是否接受控制器管理

资源定义升级

每个资源定义都有一个 GVK, group version kind
通过通用的 hub 可实现版本自动转换

比如 component v1alpha 时我们使用阿里云 slb 做负载均衡,在 v1beta 中我们改为采用自建 lb,可简单的通过定义一个转换器来实现。

component v1alpha
spec.svc.type = 'aliyun-slb'

component v1beta
spec.svc.type = 'luoji-slb'
并调用自建 lb 服务的接口创建并绑定新的 lb。

变更将在任何一次对资源的变更后自动触发,完成 spec 升级,同时切换至新的 lb ,业务方无感知。

分布式--高可用

多备单活,抢占锁

主备每个服务维护一个 workqueue 队列,每次更新请求和状态变更同时向主备的队列中发布,然后拿到抢占锁的队列执行操作。

分布式--水平扩展

k8s 默认监听机制下,资源控制器会监听全部资源。
如果遇到性能瓶颈,可以添加 controller id 索引,不同资源使用不同的控制器。

监控

metrics

参考

OAM

未来展望

1 serverless

2 弹性伸缩

3 服务亲和力感知

4 容器自动创建 --> 自动添加 worker 节点 --> 集群自动搭建


FingerLiu
562 声望28 粉丝

先广后精。Explore the whole world,and then do one thing but do it best.