k8s 分组发布的实现

分组发布的实现:

1、创建新的 Deployment,实例数量是第一个分组的数量,apply;

2、修改当前的 Deployment,实例数量减去第一个分组的数量,apply;

3、修改新的 Deployment ,加上第二个分组的数量,apply;

4、修改当前的 Deployment,减去第二个分组的数量,apply;

5、剩下的分组依次进行;

6、最终新的 Deployment 为线上,删掉之前的 Deployment。

因为 Deployment 名称不让修改,无法一直保持一个名称,可以把名称带上时间戳后缀。

通用集群发布设计

核心概念

1、服务:我们把相同程序(二进制)产生的进程集合叫做服务,是一个比较大的概念;
2、模板:发布用的通用配置,包括:运行目录、包构建信息、目标目录、前置命令、停止命令、启动命令、后置命令、并发度、超时时间等等;
3、集群:就是普通集群的概念,比如 etcd 集群、ES 集群、pxc 集群等;
4、实例:集群中的一个进程;
5、机房:机器所属的机房;
6、分组:包含若干个实例,用于分批发布;
7、KV:Key-Value 对,用于渲染配置文件;
8、配置:特指 ansible yml 文件,用于配置环境,包括创建目录、渲染配置文件到目标目录等。

关联关系

1、一个服务的程序可以发布出 N 个集群;
2、服务的模板应用于服务关联的所有集群;
3、一个服务可以定义若干个 KV 和配置,并被应用于所有集群的所有实例;
4、对于每个集群,可以自定义 KV 和配置,优先级高于服务级别的 KV 和配置;
5、对于每个实例,可以自定义 KV 和配置,优先级高于集群级别的 KV 和配置;
6、对于每个集群,可以定义分组,比如 0、1、2;
7、发布时一个分组发布完成后,会暂停;
8、机房是用于控制并发度的:同时发布的机房数量;
9、关于并发度,发布一个服务,服务对应多个集群,集群对应多个实例,所以支持:
1)、集群间并发度:同时发布几个集群;
2)、对于一个集群,一个一个分组发,串行;
3)、机房间并发度:对于一个分组,同时发布几个机房(中的实例),如果并发度是 1,就一个机房一个机房发;
4)、服务器并发度:对于一个分组里每个机房里的机器设置的并发度。

其他

1、模板里面有启动命令,但是每个集群的进程名不能一样,这个问题怎么解决?
模板支持使用 {{ process_name }} 这种语法,启动前先渲染成真正的命令。
process_name 则可以在集群 KV 中定义。

和服务树关联的系统

服务树是运维系统中最重要也是最基础的基础组件,基于服务树我们可以方便的统一管理很多资源和系统,包括:

1. 机器管理
2. 权限系统
3. 监控系统
4. 数据展示(系统资源)和可用率展示(节点关联服务)
5. 配置管理
6. 服务发现
7. 部署系统

这七个系统基于服务树节点各司其职:
1. 机器管理负责管理节点下面的机器,包括机器列表、初始化、重启等;
2. 权限系统负责管理节点下面机器的登陆权限、已经其他子系统的查看修改等权限;
3. 监控系统基于节点来管理监控,基于节点增加和删除监控非常简单;
4. 数据展示和可用率展示负责展示节点下面的机器的系统资源使用情况和节点关联服务的可用率情况;
5. 配置管理负责系统基础环境和应用基础环境,装机时指定服务节点,装机后环境会被自动初始化好(我们使用 Puppet)。

事实上 1 – 5 点我们已经有了比较丰富的经验,这里不再赘述,重点阐述一下 6 – 7 点。


服务发现

服务发现需要实现服务变更后自动发现、负载均衡等基本特性,还可以实现某些高级特性,比如区域化解析、CNAME(路由切换)、关系图谱和安全注册。

设计可以参考这篇文章的设计。

这里我们只讨论一下服务发现需要的数据结构,最基本的数据结构包括下面两个部分。

1. 服务的基础信息

1). 服务唯一标识,我们采用服务节点字符串来表示;
2). 服务启动端口。

虽然服务发现基于服务节点,但是服务发现系统对于服务节点下面的机器有独立的一份存储,服务发现系统和服务节点的机器信息对齐可以采用程序的守护进程来保证,在发布一台机器之后守护进程会自动向服务发现系统注册,并向服务节点注册,在停止一台机器的服务之前,先从服务发现系统删除,并从服务节点删除。

2. 机器列表、负责均衡算法

机器列表就是当前服务正在运行的机器列表,我们可以对机器指定负载均衡算法。

比如:
1). WRR,应当支持对节点下面的机器指定权重,默认权重一样;
2). 一致性哈希;
3). 其他算法。

除了上面这两种,我们增加了另外两种比较特殊的数据,LVS 和 Nginx,因为除了这里所说的服务发现系统,LVS 和 Nginx 作为代理也实现了服务发现的功能。增加 LVS 和 Nginx 信息是为了当 LVS 和 Nginx 后面的服务更新之后自动通知 LVS 和 Nginx 。

3. LVS 信息

需要的信息如下:
1). VIP;
2). Src Port;
3). Dest PORT(目的 IP 即是服务节点下机器 IP);
4). 其他信息(比如 syn_proxy、persistence_timeout、weight)。

当 LVS 后面的服务(Nginx)发布时,动态通知 LVS (怎么通知再讨论)摘除或增加,注意需要保证摘除和增加时流量无损。

4. Nginx 信息

需要的信息如下:
1). 服务所属的 domain 和 uri,可以有多个,对于每个 domain,还需要知道启用端口、日志路径、证书文件等;
2). upstream 名称;
3). 其他属性,可以自定义,比如 ip_hash。

当 Nginx 后面的服务(Webapp)发布时,动态通知 Nginx (怎么通知再讨论)摘除或增加,注意需要保证摘除和增加时流量无损。


部署系统

部署系统基于一个服务节点,对服务节点下面的机器进行部署(这里是机器的部署,Docker 部署额外讨论)。

1. 部署系统的组件

简单的说,部署系统至少需要三个组件:
Build Server
控制中心
执行 Agent

简单的流程:
1. Build Server 接受编译请求,编译通过后传入产品库;
2. 控制中心接收部署请求,通过 RPC 连接 Agent;
3. Agent 解析部署请求,开始执行部署工作,Agent 需要支持暂停、停止、查看日志等功能;
4. 控制中心需要支持查看任务状态等功能。

2. 环境管理

这里可以分为基础环境管理和应用环境管理。

基础环境包括:
内存参数、用户、文件句柄、基础软件包、sshd 配置等。

应用环境是指应用需要的环境,比如 Java、tomcat 等,因为我们都是基于虚拟机,每台机器只有一个应用,不存在混布的问题,所以应用环境可以直接在装机时初始化。

基础环境和应用环境通过上面第 5 点的配置管理解决,在装机时指定服务节点, 装机之后即可初始化好基础环境和应用环境。

3. 应用程序配置

通过 Puppet 解决,指定不同的 env 生成不同的配置文件。

4. 部署的扩展

在 Agent 端使用进程守护工具,比如 God,可以带来很多好处(需要做二次开发),比如:
1. 实现统一的停起方式和查看方式;
2. 实现定时任务,比如可以用来解决日志切割问题;
3. 和服务树系统对接,自动把服务信息和机器名注册到服务树;
4. 和监控系统对接,自动生成采集监控数据的 cron 脚本,并注册监控项和报警策略;
5. 和测试系统对接,实现自动化测试;
6. 和 LVS 和服务发现系统对接,自动和 LVS、服务发现系统关联。

这几点里面其中和运维系统的关联很重要。


参考:

服务树设计参考两篇文章 服务管理平台一个关于如何管理海量机器的关联结构模型