作者:运维有术星主
KubeSphere 基于 Jenkins 的 DevOps 系统是专为 Kubernetes 中的 CI/CD 工作流设计的,它提供了一站式的解决方案,帮助开发和运维团队用非常简单的方式构建、测试和发布应用到 Kubernetes。它还具有插件管理、Binary-to-Image (B2I)、Source-to-Image (S2I)、代码依赖缓存、代码质量分析、流水线日志等功能。
DevOps 系统为用户提供了一个自动化的环境,应用可以自动发布到同一个平台。它还兼容第三方私有镜像仓库(如 Harbor)和代码库(如 GitLab/GitHub/SVN/BitBucket)。它为用户提供了全面的、可视化的 CI/CD 流水线,打造了极佳的用户体验,而且这种兼容性强的流水线能力在离线环境中非常有用。
本文档旨在成为您的技术指南,逐步引导您开启 KubeSphere 的 DevOps 之旅。我们将深入探索如何开启 DevOps 插件,如何规划设计一个完整的 DevOps 流水线并编写 Jenkins 流水线配置文件。通过本文档的实战案例,您将能够掌握从理论到实践的全过程,为您的项目带来持续集成和持续部署的自动化体验。
随着 59 张高清大图的辅助,本文档将确保您在每一个步骤中都能获得清晰的指导和深刻的见解。无论您是 DevOps 的新手还是希望在 KubeSphere 上实现 DevOps 流程的老手,本文档都将为您提供宝贵的知识和实践技巧。
实战服务器配置(架构 1:1 复刻小规模生产环境,配置略有不同)
主机名 | IP | CPU | 内存 | 系统盘 | 数据盘 | 用途 |
---|---|---|---|---|---|---|
ksp-registry | 192.168.9.90 | 4 | 8 | 40 | 200 | Harbor 镜像仓库 |
ksp-control-1 | 192.168.9.91 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-control-2 | 192.168.9.92 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-control-3 | 192.168.9.93 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-worker-1 | 192.168.9.94 | 8 | 16 | 40 | 100 | k8s-worker/CI |
ksp-worker-2 | 192.168.9.95 | 8 | 16 | 40 | 100 | k8s-worker |
ksp-worker-3 | 192.168.9.96 | 8 | 16 | 40 | 100 | k8s-worker |
ksp-storage-1 | 192.168.9.97 | 4 | 8 | 40 | 400+ | ElasticSearch/Longhorn/Ceph/NFS |
ksp-storage-2 | 192.168.9.98 | 4 | 8 | 40 | 300+ | ElasticSearch/Longhorn/Ceph |
ksp-storage-3 | 192.168.9.99 | 4 | 8 | 40 | 300+ | ElasticSearch/Longhorn/Ceph |
ksp-gpu-worker-1 | 192.168.9.101 | 4 | 16 | 40 | 100 | k8s-worker(GPU NVIDIA Tesla M40 24G) |
ksp-gpu-worker-2 | 192.168.9.102 | 4 | 16 | 40 | 100 | k8s-worker(GPU NVIDIA Tesla P100 16G) |
ksp-gateway-1 | 192.168.9.103 | 2 | 4 | 40 | 自建应用服务代理网关/VIP:192.168.9.100 | |
ksp-gateway-2 | 192.168.9.104 | 2 | 4 | 40 | 自建应用服务代理网关/VIP:192.168.9.100 | |
ksp-mid | 192.168.9.105 | 4 | 8 | 40 | 100 | 部署在 k8s 集群之外的服务节点(Gitlab 等) |
合计 | 15 | 68 | 152 | 600 | 2100+ |
实战环境涉及软件版本信息
现在,新部署的 KubeSphere v3.4.1 开启 DevOps 插件会有问题,具体描述见 KubeSphere 镜像构建器(S2I)服务证书过期(x509)问题。
在开启之前我们先修复存在的问题。
helm -n kubesphere-devops-system delete devops
$ kubectl -n kubesphere-system get deployments ks-installer --no-headers -o custom-columns=:.spec.template.spec.containers[0].image
kubesphere/ks-installer:v3.4.1
$ kubectl -n kubesphere-system patch deployments ks-installer --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "kubesphere/ks-installer:v3.4.1-patch.0"}]'
更新镜像后 ks-installer
会自动重启并根据 ClusterConfiguration
里的配置安装各个开启的未安装的模块。
以admin
用户登录 KubeSphere 控制台,点击左上角的「平台管理」,选择「集群管理」。
点击 「定制资源定义」,在搜索栏中输入 clusterconfiguration
,点击搜索结果查看其详细页面。
定制资源定义(CRD)允许用户在不新增 API 服务器的情况下创建一种新的资源类型,用户可以像使用其他 Kubernetes 原生对象一样使用这些定制资源。
ks-installer
右侧的三个竖点 ,选择编辑 YAML。devops
,将 enabled
的 false
改为 true
。完成后,点击右下角的确定,保存配置,保存之后 KubeSphere 会自动安装 devops 插件。devops:
enabled: true
jenkinsCpuLim: 1
jenkinsCpuReq: 0.5
jenkinsMemoryLim: 4Gi
jenkinsMemoryReq: 4Gi
jenkinsVolumeSize: 16Gi
注意:上面的参数配置是默认值,仅适用于测试环境,生产环境建议根据规模调大参数值。
$ kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f
正确执行后,输出结果如下 :
PLAY RECAP *********************************************************************
localhost : ok=26 changed=14 unreachable=0 failed=0 skipped=21 rescued=0 ignored=0
Start installing monitoring
Start installing multicluster
Start installing openpitrix
Start installing network
Start installing devops
**************************************************
Waiting for all tasks to be completed ...
task network status is successful (1/5)
task openpitrix status is successful (2/5)
task multicluster status is successful (3/5)
task monitoring status is successful (4/5)
task devops status is successful (5/5)
**************************************************
Collecting installation results ...
#####################################################
### Welcome to KubeSphere! ###
#####################################################
......
kubesphere-devops-system
命名空间的资源运行状态。$ kubectl get all -n kubesphere-devops-system
NAME READY STATUS RESTARTS AGE
pod/devops-28717020-l769w 0/1 Completed 0 14m
pod/devops-apiserver-858fdcc978-hwxbf 1/1 Running 0 15m
pod/devops-controller-989995d9f-wc6hs 1/1 Running 0 15m
pod/devops-jenkins-df4d7cd4b-pkmhn 1/1 Running 0 15m
pod/s2ioperator-0 1/1 Running 0 14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/devops-apiserver ClusterIP 10.233.42.51 9090/TCP 15m
service/devops-jenkins NodePort 10.233.48.8 80:30180/TCP 15m
service/devops-jenkins-agent ClusterIP 10.233.3.210 50000/TCP 15m
service/s2ioperator-metrics-service ClusterIP 10.233.60.160 8080/TCP 15m
service/s2ioperator-trigger-service ClusterIP 10.233.13.255 8081/TCP 15m
service/webhook-server-service ClusterIP 10.233.1.199 443/TCP 15m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/devops-apiserver 1/1 1 1 15m
deployment.apps/devops-controller 1/1 1 1 15m
deployment.apps/devops-jenkins 1/1 1 1 15m
NAME DESIRED CURRENT READY AGE
replicaset.apps/devops-apiserver-858fdcc978 1 1 1 15m
replicaset.apps/devops-controller-989995d9f 1 1 1 15m
replicaset.apps/devops-jenkins-df4d7cd4b 1 1 1 15m
NAME READY AGE
statefulset.apps/s2ioperator 1/1 45m
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/devops 0/30 * * * * False 0 14m 15m
NAME COMPLETIONS DURATION AGE
job.batch/devops-28717020 1/1 15s 14m
注意:实际部署中会增加 Minio 、OpenLDAP,还有一组 Argo CD 的服务组件。
登录KubeSphere 管理控制台,依次点击「平台管理」->「集群管理」->「系统组件」,检查 DevOps 标签页中的所有组件是否都处于健康状态。如果是,组件安装成功。
本文仅演示,如何创建单管理员用户实现企业空间中创建项目和管理 DevOps 项目,更复杂、更贴近生产环境的多用户模式请参考官方文档 创建企业空间、项目、用户和平台角色
安装 KubeSphere 之后,您需要向平台添加具有不同角色的用户,以便他们可以针对自己授权的资源在不同的层级进行工作。一开始,系统默认只有一个用户 admin
,具有 platform-admin
角色。在本步骤中,我将创建一个示例用户 opsxlab
。
admin
身份使用默认帐户和密码 (admin/P@88w0rd
) 登录 Web 控制台。企业空间是 KubeSphere 多租户系统的基础,是管理项目、DevOps 项目和组织成员的基本逻辑单元。
opsxlab
设置为企业空间管理员。完成后,点击创建。opsxlab
身份重新登录,验证是否能成功登录。在此步骤中,您需要使用在上一步骤中创建的帐户 opsxlab
来创建项目。KubeSphere 中的项目与 Kubernetes 中的命名空间相同,为资源提供了虚拟隔离。
opsxlab
身份登录 KubeSphere Web 控制台,点击企业空间 opsxlab
,进入企业空间概览。opsxlab
),点击确定。您还可以为项目添加别名和描述。在项目中,点击刚创建的项目查看其详情页面。
在项目的概览页面,默认情况下未设置项目配额。您可以点击编辑配额并根据需要指定资源请求和限制(例如:CPU 和内存的限制分别设为 1 Core 和 1000 Gi)。
opsxlab
身份登录 KubeSphere 控制台,转到 DevOps 项目,然后点击创建。opsxlab-devops
),然后点击确定,也可以为该项目添加别名和描述。KubeSphere 官方提供的示例项目中的 Jenkinsfile-online
流水线设计更贴近生产环境,流程比较复杂,小白理解起来可能会有困难。为了让小白快速上手 KubeSphere DevOps 的功能,我设计了一个简化版的流程。
本文我们基于 Jenkins 模拟生产环境应用发布的流程,实现如下的 DevOps 流水线任务:
TAG_NAME
的镜像推送至 Harbor 镜像仓库。TAG_NAME
标签的镜像标记为 latest
,并推送至 Harbor 镜像仓库。TAG_NAME
标签镜像部署到生产环境,此阶段需要审核。opsxlab-devops
)通常情况下,构建应用程序的过程中需要拉取不同的依赖项。这可能会导致某些问题,例如拉取时间长和网络不稳定,这会进一步导致构建失败。
我们可以配置一个节点或一组节点,专门用于持续集成 (CI)。这些 CI 节点可以通过使用缓存来加快构建过程。为我们流水线提供更可靠和稳定的环境。
执行下面的命令,标记节点 ksp-worker-1
作为 CI 节点:
kubectl label nodes ksp-worker-1 node-role.kubernetes.io/worker=ci --overwrite
Step1:在 Gitee 上执行下面的任务。
Step2:在 KubeSphere 控制台上执行下面的任务。
opsxlab
身份登录 KubeSphere 控制台。opsxlab-gitee
opsxlab
Step1:在 Harbor 上执行下面的任务。
devops
,系统会自动增加 robot- 的前缀,过期时间选择,永不过期。说明: 您的机器人名称前缀可能是
robot$
,请到「配置管理」-「系统设置」中修改。
Step2:在 KubeSphere 控制台上执行下面的任务。
opsxlab
身份登录 KubeSphere 控制台。opsxlab-harbor
robot-devops
接下来,我们创建 kubeconfig 凭证。
opsxlab
身份登录 KubeSphere 控制台。opsxlab-kubeconfig
创建完成的所有凭证列表如下所示:
项目 URL 为 https://github.com/kubesphere/devops-maven-sample
,操作过程参考如下:
在 Gitee 个人主页,点击「右上角的加号」,选择「从 GitHub/GitLab 导入仓库」。
仓库类型选择私有,并填写其它信息,点击「导入」。
成功导入后的内容如下:
根据流水线规划设计,直接在 Master
分支新建一个 Jenkinsfile-sample
实现简化版流水线。
说明: 实际使用中,本文示例的流水线不会直接到代码仓库拉取 Jenkinsfile-sample
文件。将该文件存入代码仓库的 master
分支,是为了实现版本管理和后续的实验。
master
分支,点击右上角的加号按钮,点击「新建文件」。pipeline {
agent {
node {
label 'maven'
}
}
parameters {
string(name:'BRANCH_NAME',defaultValue: 'master',description:'')
string(name:'TAG_NAME',defaultValue: '',description:'')
}
environment {
DOCKER_CREDENTIAL_ID = 'opsxlab-harbor'
GITHUB_CREDENTIAL_ID = 'opsxlab-gitee'
KUBECONFIG_CREDENTIAL_ID = 'opsxlab-kubeconfig'
REGISTRY = 'registry.opsxlab.cn:8443'
DOCKERHUB_NAMESPACE = 'opsxlab'
GITHUB_ACCOUNT = 'opsxlab'
APP_NAME = 'devops-maven-sample'
GIT_REPOSITORY_URL = 'https://gitee.com'
}
stages {
stage('拉取代码') {
steps {
git(url: "${GIT_REPOSITORY_URL}/${GITHUB_ACCOUNT}/${APP_NAME}.git", credentialsId: "${GITHUB_CREDENTIAL_ID}", branch: "$BRANCH_NAME", changelog: true, poll: false)
}
}
stage ('编译测试') {
steps {
container ('maven') {
sh 'mvn clean test'
}
}
}
stage ('编译构建') {
steps {
container ('maven') {
sh 'mvn clean package -DskipTests'
}
}
}
stage ('制作并推送镜像') {
steps {
container ('maven') {
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {
sh 'echo "$DOCKER_PASSWORD" | podman login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'podman build -f Dockerfile-online -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME .'
sh 'podman push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME'
}
}
}
}
stage('推送 latest 标签'){
when{
branch 'master'
}
steps{
container ('maven') {
sh 'podman tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
sh 'podman push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest '
}
}
}
stage('部署到 k8s Prod 集群') {
when{
branch 'master'
}
steps {
input(id: 'deploy-to-dev', message: 'deploy to K8s Prod?')
container ('maven') {
withCredentials([
kubeconfigFile(credentialsId: env.KUBECONFIG_CREDENTIAL_ID, variable: 'KUBECONFIG')]) {
sh 'envsubst < deploy/prod-all-in-one/devops-sample.yaml | kubectl apply -f -'
}
}
}
}
}
}
重要变量说明:
条目 | 值 | 描述信息 |
---|---|---|
DOCKER_CREDENTIAL_ID | opsxlab-harbor | 您在 KubeSphere 中为 Harbor(DockerHub) 帐户设置的名称,用于访问 Harbor (DockerHub) 仓库。 |
GITHUB_CREDENTIAL_ID | opsxlab-gitee | 您在 KubeSphere 中为 Gitee (GitHub)帐户设置的名称,用于访问 Gitee (GitHub)仓库。 |
KUBECONFIG_CREDENTIAL_ID | opsxlab-kubeconfig | 您在 KubeSphere 中为 kubeconfig 设置的名称,用于访问运行中的 Kubernetes 集群。 |
REGISTRY | docker.io | 默认为 docker.io ,用作推送镜像的地址。 |
DOCKERHUB_NAMESPACE | opsxlab | 请替换为您的 Harbor(DockerHub) 的命名空间,一般为帐户名,也可以替换为该帐户下的项目名称。 |
GITHUB_ACCOUNT | opsxlab | 请替换为您的 Gitee (GitHub)帐户名。例如,如果您的 GitHub 地址是 https://github.com/kubesphere/ ,则您的 GitHub 帐户名为 kubesphere ,也可以替换为该帐户下的 Organization 名称。 |
APP_NAME | devops-maven-sample | 应用名称,对应 Gitee (GitHub)上的项目仓库名称。 |
GIT_REPOSITORY_URL | https://gitee.com | Git 仓库服务器地址,本文使用 https://gitee.com |
master
分支中的文件。Dockerfile 中使用的基础镜像为 DockerHub 上的 java:8u92-jre-alpine
,网络受限的用户可以提前拉取该镜像到本地镜像仓库,并修改 Dockerfile 文件。
master
分支,点击根目录中的文件 Dockerfile-online
。FROM registry.opsxlab.cn:8443/library/java:8u92-jre-alpine
WORKDIR /home
COPY target/*.jar /home
ENTRYPOINT java -jar *.jar
Master
分支中的文件。接下来我们在 KubeSphere 上创建一个项目 kubesphere-sample-prod
,代表生产环境。待流水线成功运行,将在这个项目中自动创建应用程序的相关部署 (Deployment) 和服务 (Service)。
opsxlab
身份登录 KubeSphere。在您创建 DevOps 项目的企业空间中创建项目 kubesphere-sample-prod
。opsxlab
身份登录 KubeSphere。转到 DevOps 项目 opsxlab-devops
,点击创建。jenkinsfile-sample
并在流水线类别下拉列表中选择流水线。备注: 流水线详情页显示同步状态,即 KubeSphere 和 Jenkins 的同步结果。若同步成功,您会看到成功图标中打上绿色的对号。
Jenkinsfile-sample
文件的内容,点击「确定」。master
,点击「确定」。说明: 第一次运行时,可能不会弹出设置参数窗口,请立即点击「运行记录」,停止对应的任务后。再次点击「运行」。
部署到 K8s Prod 集群
阶段暂停,您需要手动点击绿色的 Proceed 按钮,继续流水线任务。特殊说明:
input
来指定由谁审核流水线。如果您想指定一个用户(例如 project-admin
)来审核,您可以在 Jenkinsfile 中添加一个字段。Jenkinsfile-sample
中单独定义。v0.0.1和 latest
的镜像。kubesphere-sample-prod
项目,并创建相应的部署和服务。转到这个项目,预期结果如下所示:环境 | URL | 命名空间 | 部署 | 服务 |
---|---|---|---|---|
Production | http://{$NodeIP}:{$30961} | kubesphere-sample-prod | ks-sample | ks-sample |
$ kubectl get svc -n kubesphere-sample-prod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ks-sample NodePort 10.233.10.213 8080:30961/TCP 1h
curl
访问 {$NodeIP}:{$NodePort}。$ curl 192.168.9.91:30961
Really appreciate your star, that's the power of our life.
免责声明:
本文由博客一文多发平台 OpenWrite 发布!