作者:任建伟,某知名互联网公司云原生工程师,容器技术信徒,云原生领域的实践者。
在接触容器化之前,我们团队内部的应用一直都是基于虚拟机运管,由开发人员自行维护。
由于面向多开发部门服务,而开发人员运维能力参差不齐,所以每次部署新的环境时往往都要耗费大量时间。
针对部署难的问题,我们将部分组件、服务容器化,采用 Docker 发布管理解决了部分问题,但仍未降低对开发人员的运维技能要求。
下面是我们基于虚拟机管理开发环境的流程:
从上图中我们也能发现当前架构存在的问题:
shell
运维,专业性过强;针对上述提到的痛点,我们决定对运维架构进行改造。新建运管平台,技术选型整体基于云原生,优先选取 CNCF 项目。
Kubernetes 成为了我们平台底座的不二选择, 但 Kubernetes 原生的 Dashboard 不太满足实际使用需求。
而从头开发一套 workbench
又耗时耗力,由此我们目光转向了开源社区。
此时,一个集颜值 + 强大功能于一身的开源项目进入我们视野。是的,它便是 KubeSphere。
而 KubeSphere
愿景是打造一个以 Kubernetes
为内核的云原生分布式操作系统,它的架构可以非常方便地使第三方应用与云原生生态组件进行即插即用(plug-and-play)的集成,支持云原生应用在多云与多集群的统一分发和运维管理。
对于 KubeSphere
能否作为部署平台,最终结论如下:
KubeSphere
虽功能强大,但更适合作为管理端使用,不太适合面向普通用户。
我们需要本地化一套 workbench
,简化部分功能,屏蔽专业性术语(如工作负载、容器组、安全上下文等)。
本地化部分内容如下:
事实上,我们本地化的重点是应用管理,但是 KubeSphere
功能过于强大、特性过于灵活,导致配置起来项过于繁琐。
针对部分配置项我们采用设置默认值的方式,而非交由用户去配置。(比如:容器安全上下文、同步主机时间、镜像拉取策略、更新策略、调度策略等)
改造后的运维架构如下:
基于 KubeSphere 的运管平台整体架构如下:
环境信息表:
名称 | 版本 | 说明 |
---|---|---|
kukekey | v1.0.1 | KubeSphere 安装工具 |
kubesphere | v3.0.0 | 基于 K8s 的面向云原生应用的分布式操作系统 |
kuberentes | v1.18.6 | 容器编排系统 |
docker | v19.03.15 | 容器引擎 |
CentOS | 7 | 操作系统 |
kernel | 5.4 | 操作系统内核 |
本地化部署流程如下:
1️⃣ 基于 harbor 搭建私有镜像库。
2️⃣ 离线下载并上传 kubesphere 依赖镜像至私有 harbor 内,project 名称保持不变。
3️⃣ 本地化 B2I 基础镜像,本地化如下内容:
windows
字体。4️⃣ 本地化应用商店初始化镜像(openpitrix/release-app
)。
由于预置的 chart
有很多我们实际并未使用,所以我们删除预置了 chart
,并导入实际所需 chart
(包括本地化的中间件 chart
、中台 chart
)
5️⃣ 镜像 GC。
针对频繁构建的 repo
,配置合理的 GC
策略:
基于 KubeKey 1.0.1 部署了三主多从节点 K8s v1.18.6 集群:
使用 KubeKey 1.0.1 新增三个存储节点并打上污点标签,搭建 Rook 集群
对于存储的替换主要出于以下方面考虑:
基于 KubeKey 1.0.1 部署了 KubeSphere,未作本地化修改。
CI/CD
部分我们并没有使用 KubeSphere 提供的流水线功能,而是选择 gitlab-runner + ArgoCD
方案。
CI
部分利用 gitlab-ci
切换构建时特性,我们抽象出了 provider
概念。provider
本质为工具 / 程序的容器化封装,提供某一方面能力了。如:
java
程序构建时环境,内置私有 nexus
配置;nodejs
程序构建时环境,内置私有 npm
源配置;smtp
交互程序,用于邮件通知;使用时,只需引用并传递相应参数即可:
variables:
AAA: xxx
BBB: yyy
stages:
- build
- scan
- email
build:
stage: build
image: harbor.devops.io/devops/maven-provider
tags:
- k8s-runner
script:
- mvn clean package
only:
refs:
- develop
changes:
- src/**/*
scan:
stage: scan
image: harbor.devops.io/devops/sonar-provider
tags:
- k8s-runner
script: xxx
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
email:
stage: email
image: harbor.devops.io/devops/sendmail
tags:
- k8s-runner
script:
- /work/send-mail sonar --email-to=$EMAIL_TO_LIST --email-cc=$EMAIL_CC_LIST --sonar-project-id=$PROJECT_NAME --sonar-internal-url=$SONAR_INTERNAL_ADDR --sonar-external-url=$SONAR_EXTERNAL_ADDR
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
CD
部分,我们利用 chart
对应用进行定义,并将 chart
剥离于开发库,独立于配置库进行管理,用于 ArgroCD
同步。
对于配置库与开发库分离,主要出于以下考虑:
CI Pipeline
场景下,将清单更改推送到同一个 Git
存储库可能会触发构建作业和 Git
提交触发器的无限循环。 使用一个单独的 repo
来推送配置更改,可以防止这种情况发生。角色方面,我们定义了三种类型角色,职责如下:
通过引入 KubeSphere 平台以及 CI/CD
,效率提升明显:
workbench
运维,由于屏蔽了专业性词汇术语,降低使用者学习成本。日志查看、应用更新等操作更为便捷;在一年多的容器平台使用过程中,我们遇到了蛮多的小问题,这里我举几个有代表性的例子:
存在问题:
在使用 kubesphere v3.0 的过程中我们发现:不断通过 B2I 构建应用,会产生大量的 B2I 任务记录,并且 minio 内上传的程序包文件越来越多,且并没有相应的清理策略。
解决方案:
开发定时 job
, 定期进行清理。
存在问题:
初期,我们使用 CentOS7
默认的 3.10 版本内核。
解决方案:
升级内核版本至 5.x。
存在问题:
KubeSphere 预装的 jaeger
不支持 dubbo
协议,无法对 dubbo
应用进行监控。
解决方案:
利用 SkyWalking 用于链路追踪,并在基础镜像内埋点。
解决方案:
将缺少 windows
字体安装至 B2I
基础镜像内。
由于部分应用部署于 K8s 外部,针对这部分应用我们选择 Endpoint + ExternalName + Ingress
的方式进行路由。
1️⃣ 有状态应用的 Operator
开发
当前有状态应用依赖 helm hook
管理, 且功能单一。 未来我们计划,针对常用有状态应用,开发对应 operator
,提供创建、扩容、备份等常用功能。
2️⃣ CNI 迁移至 Cilium
选取 Cilium
替换 Calico
主要出于以下考虑 :
Cilium
为 CNCF
毕业项目,活跃度高;Cilium
基于 eBPF
实现,在粒度和效率上实现了对系统和应用程序的可观测性和控制;Cilium
安全防护功能更强,提供了过滤单个应用协议请求的能力,例如 :
GET
方法和 /public/.*
路径的 HTTP
请求,拒绝所有其他请求;service1
在 Kafka
主题 topic1
上生产,允许 service2
在 topic1
上消费,拒绝所有其他 Kafka 消息;HTTP
报头 X-Token:[0-9]+
出现在所有 REST
调用中。3️⃣ cri 由 Docker 替换为 Containerd
4️⃣ 容器文件浏览器功能开发
当前阶段,开发人员下载容器内文件的需求,只能由运维人员使用 kubectl cp
的方式协助获取,后续我们规划开发容器文件浏览器相应功能。
5️⃣ 容器宿主机系统替换为 rocky
,以应对 CentOS
停止维护。
本文由博客一文多发平台 OpenWrite 发布!
|