1. 容器及容器编排技术科普
1.1 什么是容器
容器技术是可以将应用及其整个运行时环境(包括需要的所有文件)一起进行打包和隔离。从而让您可以在不同环境(如开发、测试和生产等环境)之间轻松迁移应用,同时还可保留应用的全部功能。
1.2 容器和虚拟机区别
虚拟机本质是模拟--> 利用的是CPU提供的虚拟化技术
虚拟化是使用软件在计算机硬件上创建抽象层的过程,该抽象层允许将单个计算机的硬件元素划分为多个虚拟计算机。
操作系统(OS)及其应用程序从单个主机服务器或主机服务器池共享硬件资源。每个VM都需要自己的底层操作系统,并且硬件是虚拟化的。管理程序或虚拟机监视器是创建和运行VM的软件,固件或硬件。它位于硬件和虚拟机之间,是虚拟化服务器所必需的。
容器的本质是隔离-->利用的是Linux操作系统提供的API进行
直接使用当前操作系统资源,但是进行了可见性的隔离和访问限制。每个容器共享主机操作系统内核,通常也包括二进制文件和库。共享组件是只读的。共享操作系统资源(如库)可以显着减少重现操作系统代码的需要,并且意味着服务器可以通过单个操作系统安装来运行多个工作负载。因此容器非常轻 - 它们只有几兆字节,只需几秒钟即可启动。
所以容器资源利用率高于虚拟机(同时隔离性差于虚拟机)
三种主要隔离
- 资源可见性隔离:
Linux 的命名空间机制提供了以下多种不同的命名空间,包括:
CLONE_NEWCGROUP(物理资源)、CLONE_NEWIPC(进程通信相关)、CLONE_NEWNET(网络)、CLONE_NEWNS(文件系统)、CLONE_NEWPID(进程ID)、CLONE_NEWUSER(用户)、CLONE_NEWUTS(主机名)
Fork进程时作为参数传入就可以进行隔离调用
- 文件目录隔离:
重新创建一个新的文件目录视图 (例如:BusyBox) 并且把根目录进行映射 Chroot
- 物理资源(CPU、硬盘、内存等)限制隔离:
CGroup技术
1.3 容器有什么优势?
容器共享相同的操作系统内核,并将应用进程与系统的其他部分隔离开来,因此整个容器能够在各种开发、测试和生产配置中移动、打开和使用。因为容器是轻量级和可移植的,它们为加快开发和满足业务需求创造了机会。
容器还有利于明确划分职责范围,减少开发和运维团队间的冲突。这样,开发人员可以全心投入应用开发,而运维团队则可专注于基础架构维护。
1.4 什么是容器编排技术
虽然容器化有非常多的好处,但是随着容器越来越多出现了一系列新问题:
● 单机不足以支持更多的容器
● 分布式环境下容器如何通信?
● 如何协调和调度这些容器?
● 如何在升级应用程序时不会中断服务?
● 如何监视应用程序的运行状况?
● 如何批量重新启动容器里的程序?
● ...
因此容器编排技术应运而生,容器编排是指自动化容器的部署、管理、扩展和联网。容器编排可以为部署和管理成百上千个容器和主机的提供便利。
容器编排可以在使用容器的任何环境中使用。它可以帮助您在不同环境中部署相同的应用,而无需重新设计。通过将微服务放入容器,就能更加轻松地编排各种服务(包括存储、网络和安全防护)。
2. 云原生技术
基于容器化技术,我们能够提供稳定的构建和部署运行环境,能够对以上环境进行快速地扩容和移植。
随着互联网及软件行业的发展,业界对日益庞大增长的应用构建和部署的思考,也有一定沉淀,基于容器化和应用微服务架构的实践经验,2015 年 Google等业界头部厂商主导成立了云原生计算基金会(CNCF)。
最初的定义
起初 CNCF 对云原生(Cloud Native)的定义包含以下三个方面:
-
应用容器化
-
面向微服务架构
-
应用支持容器的编排调度
重定义
到了 2018 年,随着近几年来云原生生态的不断壮大,云原生基金会的组织成员越来越多,所涵盖的发展目标和内容已经超出原有定义,为了避免对生态发展的限制,CNCF 为云原生进行了重新定位:
以下是 CNCF 对云原生的重新定义(中英对照)摘录:
Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。
同时,业界对云原生技术时代的应用也做出了一定的总结:
现代应用的十二范式(The Twelve-Factor App):
-
基准代码:一份基准代码,多份部署。基准代码和应用之间总是保持一一对应的关系。所有部署的基准代码相同,但每份部署可以使用其不同的版本。
-
依赖:显式声明依赖关系。应用程序一定通过依赖清单,确切地声明所有依赖项。
-
配置:在环境中存储配置。将应用的配置存储于环境变量中。环境变量可以非常方便地在不同的部署间做修改,却不动一行代码。
-
后端服务:把后端服务当作附加资源。应用不会区别对待本地或第三方服务。对应用程序而言,两种都是附加资源。
-
构建,发布,运行:严格区分构建,发布,运行这三个步骤。
-
进程:以一个或多个无状态进程运行应用。应用的进程必须无状态且无共享。
-
端口绑定:通过端口绑定提供服务。应用完全自我加载而不依赖任何网络服务器就可以创建一个面向网络的服务。
-
并发:通过进程模型进行扩展。开发人员可以运用这个模型去设计应用架构,将不同工作分配给不同的进程类型。
-
易处理:快速启动和优雅终止可最大化健壮性。应用的进程是可支配的,意思是说它们可以瞬间开启或停止。
-
开发环境与线上环境等价:尽可能保持开发、预发布、线上环境相同。应用想要做到持续部署就必须缩小本地与线上差异。
-
日志:把日志当作事件流。应用本身考虑存储自己的输出流。不应该试图去写或者管理日志文件。
-
管理进程:后台管理任务当作一次性进程运行。一次性管理进程应该和正常的常驻进程使用同样的环境。
3. 37手游CI/CD系统介绍
CI/CD系统的核心目标,包括:
-
促使和推动业务应用向云原生形态和云原生思想靠拢
-
通过自动化流程,快速的应用管理,利用云原生技术,支撑业务工程稳定集成部署,减低应用创建和迭代的中间人力操作成本和风险
-
作为基座,承载更多业务应用不断地接入云原生开发体系
-
对已有的非云原生模式(如虚拟机部署等)旧应用进行过渡兼容。
3.1 CI/CD系统基础理念介绍
3.1.1 基准代码(GITOPS)
基准代码和应用之间总是保持一一对应的关系:
● 一旦有多个基准代码,就不能称为一个应用,而是一个分布式系统。分布式系统中的每一个组件都是一个应用,每一个应用可以分别使用12-Factor进行开发。
● 多个应用共享一份基准代码是有悖于 12-Factor 原则的。解決方案是将共享的代码拆分为独立的类库,然后使用 依赖管理 策略去加载它们。
尽管每个应用只对应一份基准代码,但可以同时存在多份部署。每份部署相当于运行了一个应用的实例。通常会有一个生产环境,一个或多个预发布环境。此外,每个开发人员都会在自己本地环境运行一个应用实例,这些都相当于一份部署。
总结:分支区分部署实例,如测试分支、预发布分支、生产分支,对不同类型的分支,应该使用不同的流程/触发管理
3.1.2 构建,发布,运行分离
基准代码转化为一份部署(非开发环境)需要以下三个阶段:
○ 构建阶段是指将代码仓库转化为可执行包的过程。构建时会使用指定版本的代码,获取和打包 依赖项,编译成二进制文件和资源文件。
○ 发布阶段会将构建的结果和当前部署所需 配置 相结合,并能够立刻在运行环境中投入使用。
○ 运行阶段(或者说"运行时") 是指针对选定的发布版本,在执行环境中启动一系列应用程序 进程。
○
图:代码被构建,然后和配置结合成为发布版本
总结:一次构建,多次部署,多次运行
3.2.3 环境配置绑定
在环境中存储配置
通常,应用的 配置 在不同部賽(预发布、生产环境、开发环境等等)间会有很大差异。这其中包括:
○ 数据库,redis,以及其他 后端服务 的配置
○ 第三方服务的认证配置,如腾讯,阿里想关的云服务等
○ 每份部署特有的配置,如域名等
解决:CI/CD系统通过发布时根据部署指令动态注入环境ID,根据环境ID与配置的映射关系找出需要的配置
3.2 CI/CD系统关键技术
3.2.1 系统核心模块组成
以下为CI/CD系统的核心系统架构图,主要包括:
-
项目管理
-
资源管理
-
配置管理
-
日志服务
-
用户系统
-
运行调度系统
3.2.2 系统运转核心流程
以下为CI/CD系统的核心流程运转示意图:
以上所有操作均在统一管理后台完成,且每一个操作都有自动化的快捷跳转和提示,具有流畅的操作体验和用户反馈,完整覆盖开发构建、发布应用操作闭环。
3.2.3 流水线上的体验优化
● 项目管理
与gitlab api 深度交互,提供gitlab数据源快捷操作,下拉式选择,仓库可见性与gitlab保持一致
● 自动触发构建
- 创建新项目时自动添加Gitlab项目回调
- 支持分支/Tag通配构建 一键开启自动构建
● 灵活的构建申明选择
- 推荐:将构建流程声明维护在代码仓库(GitOps)
2. 入门:使用devops小组提供的基础模板
3. 进阶:开发自定义自己的构建流
● 自动化的镜像管理推送
Q:系统怎么知道构建好的镜像要推送到哪些仓库 ,部署时又使用哪个仓库的镜像?
A: 每个容器集群都会关联一个镜像ID,当项目触发构建时,会遍历所有项目已关联的容器集群,然后找到所有的镜像进行推送,部署时会动态地根据不同部署目标集群进行镜像字段更新
更深的体验优化:
自动检查对应集群命名空间和镜像密钥自动创建
暂时未解决的:不同镜像仓库创建新命名空间未有标准化API,所以仍需手动创建新项目命名空间才能Push镜像成功
● 发布限制
环境类型绑定机制:测试环境类型只能关联测试环境,生产环境只能关联生产分支,因此只有生产分支才能发布到生产环境集群,从根源上解决分支管理规范
● 发布
定制化地快捷注入常用K8s模板功能 自动化动态注入ACM变量,实现部署环境ID和配置自动化绑定,解决环境配置标准化问题
注意:多版本兼容方案,避免元数据覆盖
优先级:
部署YML(文件/模板) > 集群运行 YML > 动态注入配置
● 标准化回调
提供标准化回调webhook,支撑各模块人员对接后续开发,以支持更丰富的流水线场景(目前已支持构建,部署通知,自动化测试触发,容器启动,扩容通知等)
3.2.4 标准化集群容器状态面板管理
实现不同厂商云平台操作面板的收敛,实际上查看集群80%模板状态就能满足80%的正常开发需求,发布等操作可以通过系统进行,其他20%少数需求应该由运维操作。
实现各云厂商控制台开发人员子权限收敛
3.3 基于云原生技术对传统服务器持续集成和持续部署
云原生技术其中最核心的是容器技术,而在大规模落地容器和云原生技术部署应用时,最为主流的解决方案是使用kubernetes(简称:K8s)集群进行容器编排和管理,但基于K8s集群的应用部署方案和集成过程,都和传统服务器的集成过程有较大区别,其中主要体现在应用服务访问编排(包括服务间调用和集群外部访问),以及应用生命周期管理等等。
K8s的核心CI/CD流程主要为:
-
通过代码版本管理获取源代码
-
通过Dockerfile等容器镜像构建描述文件构建应用容器镜像
-
上传应用容器镜像到镜像仓库(包括容器镜像仓库授权过程)
-
通过YML配置文件声明式描述K8s集群期望应用版本(基于上文步骤和上传构建的镜像)和运行状态及访问拓扑资源
-
等待K8s集群自动按照声明式状态创建(滚动更新)应用运行容器及建立访问拓扑资源
CI/CD系统在容器镜像构建过程,加入部署层,实现了传统服务器使用容器构建技术的兼容
其中相关配置有三个关键参数和部署执行器程序(deployer):
- 部署层文件来源阶段(stage)
指定了在原始容器镜像构建过程中,哪一层的文件会作为构建产物文件被部署
- 部署目标文件列表
指定了在原始容器镜像构建过程中,哪一些文件(来源于部署层文件来源阶段)会作为构建产物文件被部署
- 部署层基础镜像
指定了来源于部署层文件来源阶段的部署目标文件列表会被储存于什么基础镜像中
- 部署执行器程序(deployer)
此程序被提前储存在部署层基础镜像中,或在运行部署镜像时通过文件挂载方式注入部署容器,会接受来自于CI/CD系统的部署参数,通过运行容器镜像(docker run或K8s Job)创建部署执行容器(每个部署目标服务器独立),将储存在同容器内的部署目标远程传输到指定部署目标服务器和远程执行部署程序
- 部署执行器程序接受的部署参数包括:
• 要部署的目标文件
• 要部署的目标服务器地址
• 要执行的部署脚本(主要分为文件传输前、文件传输后) 完整流程图如下:
总结
在37手游发布系统的设计中,我们积极拥抱了容器技术与云原生技术,使得其具有快速构建、部署和管理应用程序的能力,目前37手游近600多个微服务都接入了发布系统,通过完善的,高度自动化的CI/CD流程支撑了37手游日常业务工程稳定集成部署,减低应用创建和迭代的中间人力操作成本和风险 ,成为了推动创新和提高37手游业务效率的重要工具。
最后,再附上37手游的Slogan: "创新点亮梦想,分享成就未来,相信创造奇迹" 。
资料来源: