为什么是Docker?
库依赖问题
- apt/yum依赖
实施过程中,离线环境包管理器(e.g. yum apt)经常碰到此类问题:
--> Running transaction check
// ...
Error: Package: 1:java-1.8.0-openjdk-devel-1.8.0.161-2.b14.el7.x86_64 (/java-1.8.0-openjdk-devel-1.8.0.161-2.b14.el7.x86_64)
Requires: java-1.8.0-openjdk(x86-64) = 1:1.8.0.161-2.b14.el7
Installed: 1:java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64 (installed)
java-1.8.0-openjdk(x86-64) = 1:1.8.0.171-8.b10.el7_5
Available: 1:java-1.8.0-openjdk-1.8.0.161-2.b14.el7.x86_64 (local)
java-1.8.0-openjdk(x86-64) = 1:1.8.0.161-2.b14.el7
容器镜像因为预先已经在流水线环境打包完成,包含所有依赖,所以不会出现这种问题。
为什么是Kubernetes?
实例数量协调
假如在虚拟机上启动3个实例,开发者需要SSH登录或者使用Ansible/Puppet等工具进行部署。
这个时候,需要进行水平扩展,那该怎么做?显然你需要"一点"工作要做,自行脑补一下。
在k8s环境里,只需要修改yaml格式的Deployment编排文件的一个字段就可以了!这就是k8s最酷的地方。
假如有个更高级点的需求,根据实例总体负载情况,自动调整实例数量。虚拟机环境下那该怎么做?显然干不了。
在k8s环境里,可以给Deployment关联一个HPA,HPA周期性获取Deployment管辖下容器CPU等负载情况,自动调节副本数量。
版本回滚和升级
还是老规矩,脑部虚拟机场景下的升级和回滚方式。
在k8s环境里,只需要修改编排文件的镜像tag, 进行全部实例的统一回滚和升级。
另外,为了保持服务的持续可用性,可以设置升级/回滚过程中,最大不可用的实例数量。
跨语言与技术栈
kubernetes以运维视角解决了很多微服务问题。
假如在虚拟机上启动了3个实例,现在数据库的IP地址换了,配置文件需要SSH连接一个一个改。
k8s也提供了类似Spring Cloud技术栈的配置中心的功能,叫做配置字典ConfigMap。
比如上面的统一配置问题,如果我有一个go语言写的web服务集成进来,Spring Cloud的配置中心就解决不了配置统一性问题了。但是配置字典是通过Mount技术挂载到容器文件系统里的,它是和语言技术栈无关的。
当然不仅仅是统一配置问题,比如服务发现,API网关等,都是语言无关的,
为什么是流水线?
- 流水线的核心在于自动化信仰,人工干预零容忍,能够在无人为干预下进行预定义的批量式,填鸭式的任务。
- 统一的CI/CD流程能够促进团队开发者在很多方面保持一致和同步。
静态代码检查
Java变量命名中典型的驼峰式(CamelCase), 静态代码检查能够检测开发者代码中的不规范命名,在团队间形成良好的编码风格。
流水线管理所有Git仓库,可将"静态代码检测"作为一个环节加入构建任务中,进行代码质量检测。
漏洞扫描
Apache Log4j是被广泛应用的第三方日志中间件,但是自2021年12月7日公开爆出8个"核弹级"漏洞。让开发者肉眼去检查那么多项目的pom.xml文件显然不可能; 即使有了自动化检查工具,检查那么多git仓库也不现实。
流水线管理所有Git仓库,可将"漏洞扫描"作为一个环节加入构建任务中,进行漏洞扫描,报告生成/上传。
版本集中管理
版本不仅仅是artifact(e.g. jar包), 还是配置文件,二进制文件,启动脚本 etc.
流水线可以读取artifact规则,将此版本相关文件全部打包进一个压缩包(tar.gz),并将Git版本信息写入.
版本artifact压缩包会统一上传到OSS对象存储,供团队人员下载。
异构环境集成
如果让一个开发者打包支持以下矩阵的artifact:
| OS\Arch | X86_64 | ARM64 |
|---|---|---|
| CentOS | - | - |
| Ubuntu | - | - |
| Kylin v10 Desktop/Server | - | - |
| Windows 10 | - | - |
这一定是个头疼的问题,简单重复而繁琐。
流水线可以通过团队统一的针对某个技术栈的自动化打包脚本打包artifact,并统一上传至版本服务器。
如果是容器镜像场景,生成多架构支持镜像,上传至Docker Registry.
自动化测试
自动化测试根据不同的测试场景启动的时间点不同
- 单元测试: 测试方法逻辑正确性(e.g. JUnit等), 发生在打包阶段。
- Restful接口测试: 验证业务逻辑,发生在部署完成且Readiness探测成功后。
持续部署
如果让一个开发者手工部署版本至多环境,还是用矩阵表示:
| 环境\用途 | 开发 | 预发布 |
|---|---|---|
| 虚拟机 | - | - |
| Kubernetes | - | - |
| Docker-Compose | - | - |
这一定是个头疼的问题,复杂而繁琐。首先需要开发者具备的熟悉多种部署环境的能力,比如他需要熟悉kubernetes/docker-compose。
DevOps人员,开发者,运维协同在Git仓库定义部署编排文件,把部署复杂的细节封装在内部,给外部人员抽象出一个统一的接口。叫做"我更新了代码,你登录UI看下效果!"
另外,流水线还能够处理版本回滚/升级。