作者:gfengwong
原文链接
KubeSphere 的 DevOps 模块介绍
- KubeSphere 应用可插拔的 DevOps 模块实现 DevOps 性能;
- DevOps 驱动 Jenkins 实现具体的操作,例如流水线等。
DevOps 与 KubeSphere 的关系如下图, 具体的组件介绍。
集成的亮点
DevOps 与 Jenkins 集成严密且优雅,从构建、部署到应用保护纯云原生形式实现:
- 一键部署;
- 一个参数启用 DevOps 性能;
- 一个 K8s 集群内即可实现从 Jenkins、流水线的全生命周期。
具体集成阐明
用户应用 KubeSphere 平台的 DevOps 性能时,调用 devops-api 发送申请,DevOps 收到申请后,局部申请间接调用 jenkins 进行操作,局部申请通过更新 devops-controller 监听的资源,通过 devops-controller 来操作 Jenkins。
运行流水线阶段,Jenkins 配置了 K8s 动静 slave:
- Jenkins pod 信息(镜像、卷等)发送给 K8s;
- K8s 启动 Jenkins slave pod 并通过近程协定与 Jenkins master 建设连贯;
- 运行流水线;
- 运行结束之后依据设置删除/保留创立的 pod。
Jenkins 镜像构建
Jenkins 自身是一个 Java 利用,以后也没有提供官网的云原生计划,KubeSphere 通过上面几个我的项目定制了本人的镜像:
- custom-war-packager 定制本人的 Jenkins 并生成 Docker 镜像或者 war 镜像;
- formulas 通过 formula.yaml 定制本人的 Jenkins,针对中国区优化;
- ks-jenkins 定制了 KubeSphere 本人的 Jenkins 镜像 应用了 jcli 集成了 cwp。
ks-devops 我的项目中的 formulas 装置了所有须要的 Jenkins 插件次要有
- Blue Ocean 提供了 Jenkins 的 restful API;
- kubernetes 提供了动静 slave 能力;
- kubesphere-token-auth 集成 KubeSphere 权限体系;
- 其余。
Jenkins 与 DevOps 的部署
ks-installer(Ansible) 生成环境变量,次要有:
- 要不要应用 ksauth;
- 生成 ksauth 应用的明码;
- 次要环境变量在 https://github.com/kubesphere... ;
- helm 部署 DevOps 和 Jenkins helm 我的项目。
ks-devops-helm-chart:
这个我的项目外面次要有三个 chart。
- DevOps
部署 devops-apiserver 和 devops-controller。
留神 ⚠️ 这里有一个 cronjob 作用为清理执行过的流水线记录,定期执行 ks pip gc
。
次要部署的资源有:
deployment
- devops-apiserver
- devops-controller
cronjob
- devops
configmap
- devops-config
- jenkins-agent-config
- Jenkins
Jenkins 配置:
- Maven 配置
charts/ks-devops/charts/jenkins/templates/jenkins-agent-config.yaml
配置 Jenkins dynamic slave
charts/ks-devops/charts/jenkins/templates/jenkins-casc-config.yml
- 自动化配置 Jenkins Configure Clouds
- 配置 K8s 认证
- 配置 pod volume image lable 等
- 会将下面的 Maven 配置挂在到 Maven 容器中
- 将 Maven 配置和 casc 配置以 configmap 的形式挂在到 Jenkins 容器的
/var/jenkins_home/casc_configs
, 从 helm 的 value 获取 value.yaml
charts/ks-devops/charts/jenkins/values.yaml
中定义了:- 环境变量 从 value 读出配置到容器中,设置了登陆用的用户名明码
初始化脚本 -- 在 helm 渲染 Jenkins deploy 时挂载到 configmap 中
- mariler 插件 -- 绑定邮箱
- K8s 插件 -- 创立 K8s credential
- RBAC 配置
Jenkins pod 初始化:
K8s 插件配置
charts/ks-devops/charts/jenkins/templates/config.yaml
config.xml
- 创立 role
kubesphere-user
所有资源只读并绑定到authenticated
用户 - ladp 配置,对接 kubesphere ladp
- cloud 配置:pod template container 配置、挂载等等,包含 Maven 配置、Docker sock 等
- 创立 role
apply_config.sh jenkins 工作目录初始化
slave-to-master-security-kill-switch
禁用 agent 访问控制机制- 拷贝 config.xml 到容器
/var/jenkins_home
将用于初始化的 groovy 文件拷贝到
/var/jenkins_home/init.groovy.d
- 初始化用于 cloud 的 credential
Kubernetes service account
- Mailer 模块初始化
- RBAC 初始化:创立 admin 和 kubesphere-user 对应的 role 做绑定
- Sonarqube 初始化
- 用户初始化,创立 admin 用户并设置明码
- 初始化用于 cloud 的 credential
deployment
charts/ks-devops/charts/jenkins/templates/jenkins-master-deployment.yaml
设置环境变量
- jvm 参数
- admin 用户名明码
- 超时配置
- 邮箱配置
- limit 留神:默认 memory 为 2g,个别是不够用的,跑多个工作就会引起 pod crash,所以至多设置成 4g
- initContainer 运行
/var/jenkins_config/apply_config.sh
初始化 jenkins 配置,如装置插件、配置 cloud、rbac 等等
到这里 Jenkins pod 就创立进去了,咱们能够间接开始应用 Jenkins 运行流水线了。
Jenkins K8s 动静 slave
KubeSphere 内置 Jenkins
配置:
KubeSphere 通过 ks-install 和 helm 都配置好了,无需独自配置。
应用:
以流水线为例,groovy 中增加以下字段会依照 'base'
去匹配 pod 的 lable,匹配到了会应用这个 label 的 pod 模板启动 pod 运行流水线,上面有两个 pipeline 脚本,第一个是选定了 pod 的模板的会启动一个 pod 来执行,第二个 any,如果设置了 master 节点为 Only build jobs with label expressions matching this node
将会启动 base pod 来运行,如果抉择 Use this node as much as possible
则会在 Jenkins 本身的容器/服务器上运行,如果是一般 job 的话,勾选Restrict where this project can be run
且填写 Label Expression
抉择要运行的 label,和 pipeline 相似。
pipeline { agent { node { label 'base' } } stages { stage('Run shell') { steps { sh 'echo hello world' } } }}
pipeline { agent any stages { stage('Run shell') { steps { sh 'echo hello world' } } }}
独立部署的 Jenkins
cloud 配置 K8s:
Manage Node → Configure Clouds。
- K8s;
- K8s URL:K8s apiserver 地址, 与 KubeSphere 自带的 Jenkins 不同的是应用了集群外部链接;
- K8s Namespace:slave pod 运行的 namespace;
- Credentials:应用 secret file,上传 kubeconfig 与 KubeSphere 自带的 Jenkins 不同的是应用了
kubernetes service account
; - 应用 WebSocket 通信 -- 应用 Jenkins tunnel 通信;
- Jenkins URL:Jenkins API 地址;
- 其余:其余的 pod 配置按需配置即可,这里和 KubeSphere 的一样。
Q & A
应用 Maven 构建时,Maven 仓库如何配置?
pod 所应用的 Maven 配置是挂载进去的,能够通过 Jenkins->Configuration->Maven Project Configuration 配置
KubeSphere → Jenkins → K8s,认证是如何实现的?
KubeSphere 与 Jenkins 的认证:
Jenkins 插件 kubesphere-token-auth-plugin
集成 KubeSphere 的认证体系,在 KubeSphere 调用 Jenkins 时,都须要通过 ks-apiserver 进行 token 的 review, 通过之后再调用 Jenkins 执行理论动作
Jenkins 应用驱动 K8s 实现动静 slave:
- Jenkins 的 deployment 中申明了
serviceAccountName
devops-jenkins
; - 启动的 pod 会将对应 serviceAccount 的 token 写入 pod 文件系统中
/var/run/secrets/kubernetes.io/serviceaccount/token
; - Jenkins K8s 插件会去读 pod 文件系统的 token,这样就能够通过 token 来调度 K8s 资源实现 slave pod 的创立删除。
如果是外置 Jenkins 则无奈通过读取 token 来连贯 K8s,须要手动创立 serviceAccount、clusterRole、clusterRoleBinding,而后将 token 以 Secret text 或者将 ca 证书以 Secret file 模式或将 kubconfig 以 Secret file 模式写入 credentials。
部署应用问题
误删 apiserivice
kubectl delete --all apiservice
解决形式
参照:https://github.com/kubernetes...
将 kube-apiserver.yaml
移到其余文件夹,这时 kube-apiserver 的 pod 会 down 掉。
mv /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/
在其余 API 失常的节点删除这个 pod,再将配置文件移回去,即可复原。
KubeSphere API 服务无奈启动
版本:KubeSphere v3.3.0。
谬误形容
install failed, ks-controller CrashLoopBackOff
E1116 00:55:15.113761 1 notification_controller.go:113] get /, Kind= informer error, no matches for kind "Config" in version "notification.kubesphere.io/v2beta1"F1116 00:55:15.113806 1 server.go:340] unable to register controllers to the manager: no matches for kind "Config" in version "notification.kubesphere.io/v2beta1"
解决形式
参照:kubectl apply -f https://raw.githubusercontent.com/kubesphere/notification-manager/master/config/bundle.yaml。
kubectl apply -f https://raw.githubusercontent.com/kubesphere/notification-manager/master/config/bundle.yaml
JNLP 容器无奈启动
JNLP 是 Jenkin 的近程调用协定。
[root@k8s-1 ~]# kubectl logs -f -n kubesphere-devops-worker base-w9dpq jnlpWarning: SECRET is defined twice in command-line arguments and the environment variableWarning: AGENT_NAME is defined twice in command-line arguments and the environment variableSep 14, 2022 11:29:43 AM hudson.remoting.jnlp.Main createEngineINFO: Setting up agent: base-w9dpqSep 14, 2022 11:29:44 AM hudson.remoting.jnlp.Main$CuiListener <init>INFO: Jenkins agent is running in headless mode.Sep 14, 2022 11:29:44 AM hudson.remoting.Engine startEngineINFO: Using Remoting version: 4.10Sep 14, 2022 11:29:44 AM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDirINFO: Using /home/jenkins/agent/remoting as a remoting work directorySep 14, 2022 11:29:44 AM org.jenkinsci.remoting.engine.WorkDirManager setupLoggingINFO: Both error and output logs will be printed to /home/jenkins/agent/remotingSep 14, 2022 11:29:44 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Locating server among [http://172.16.80.38:8080/]Sep 14, 2022 11:29:44 AM hudson.remoting.jnlp.Main$CuiListener errorSEVERE: http://172.16.80.38:8080/tcpSlaveAgentListener/ is invalid: 404 Not Foundjava.io.IOException: http://172.16.80.38:8080/tcpSlaveAgentListener/ is invalid: 404 Not Found at org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.resolve(JnlpAgentEndpointResolver.java:219) at hudson.remoting.Engine.innerRun(Engine.java:724) at hudson.remoting.Engine.run(Engine.java:540)
Sep 14, 2022 11:33:41 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Locating server among [http://devops-jenkins.kubesphere-devops-system:80/]Sep 14, 2022 11:33:42 AM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolveINFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping]Sep 14, 2022 11:33:42 AM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolveINFO: Remoting TCP connection tunneling is enabled. Skipping the TCP Agent Listener Port availability checkSep 14, 2022 11:33:42 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Agent discovery successful Agent address: devops-jenkins-agent.kubesphere-devops-system Agent port: 50000 Identity: 13:ea:2b:ab:b5:16:70:70:89:58:d1:66:2b:62:b1:16Sep 14, 2022 11:33:42 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: HandshakingSep 14, 2022 11:33:42 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Connecting to devops-jenkins-agent.kubesphere-devops-system:50000Sep 14, 2022 11:33:42 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Trying protocol: JNLP4-connectSep 14, 2022 11:33:42 AM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader runINFO: Waiting for ProtocolStack to start.Sep 14, 2022 11:33:46 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: Remote identity confirmed: 13:ea:2b:ab:b5:16:70:70:89:58:d1:66:2b:62:b1:16Sep 14, 2022 11:33:46 AM hudson.remoting.jnlp.Main$CuiListener statusINFO: ConnectedSep 14, 2022 11:33:58 AM org.csanchez.jenkins.plugins.kubernetes.KubernetesSlave$SlaveDisconnector callINFO: Disabled agent engine reconnects.
附录:认证备忘
ks-installer/roles/ks-core/init-token/tasks/main.yaml
生成一个随机值 secret;- 部署 KubeSphere 的时候初始化通过
ks-installer/roles/ks-core/init-token/files/jwt-script/jwt.sh
生成了一个 jwt token 入参为下面生成的字符串和 '{"email": "admin@kubesphere.io","username": "admin","token_type": "static_token"}'; - 通过生成的 token 和 secret 创立 secret 名为 kubesphere-secret;
- 部署 DevOps 的时候将填入
authentication.jwtSecret devops.password
通过 helm 部署 DevOps; - 部署 Jenkin 的明码为写死的"P@ssw0rd";
- admin password 生成了一个随机的 22 位字符串写入 Jenkins pod 环境变了并通过读取 configmap devops-jenkins 启动 Jenkins。
参考资料
- jcli
- jcli 使用手册
- custom-war-packager
- Jenkins Kubernetes 插件
- KubeSphere DevOps 3.0 流水线开发指南
- Jenkins 基于 Kubernetes 动态创建 pod
- Can I use Jenkins kubernetes plugin when Jenkins server is outside of a kubernetes cluster?
- kubernetes-jenkins-integration
本文由博客一文多发平台 OpenWrite 公布!