Jenkins 在 Kubernetes 上的最佳实践

2023年 1月 4日 30.4k 0

1. 配置较大的 -Xms -Xmx 参数

Jenkins 是由 Java 编写的编排引擎, 在 Full GC 时会 Stop The World(STW)。在大规模构建时, STW 可能会导致 Jenkins 无法处理新的请求。为了避免频繁的 STW, 同时增大并发量, 建议设置较大的堆, -Xms3g -Xmx6g -XX:MaxRAM=6g。具体数值可以根据监控值来设置, Java Full GC 之后, 内存占用会陡降。

2. request 不要设置太小

request 设置太小, 可能会导致 Jenkins 运行起来之后, 节点资源不足, 引发驱逐, 甚至压垮节点。request 应该接近真实值, 如果有足够的机器资源, 应该配置亲和性, 让 Jenkins 尽可能运行在单独的机器上。request >= 1.25 * JVM 最大堆内存, limit >= 2 * JVM 最大堆内存。

3. IO 性能不能差

Jenkins 使用磁盘文件存储数据, 每条流水线、每次构建都会占用一个文件目录, 产生大量文件。通常流水线数量有限, 但在构建历史达到 10000+ 级别时, 会感受到 IO 对 Jenkins 的影响。如果使用本地存储, 推荐使用高性能的 SSD。如果是使用网络存储, 需要高性能的网络支持, 同时加大客户端的缓存池。

4. 较大的 jenkins_home 的磁盘空间

磁盘满时, Jenkins 将不能工作, 在 Jenkins 后台会有错误提示。建议对 Jenkins 的工作目录进行磁盘使用率监控, 并配置告警规则。如果没有监控告警系统, 那么建议直接设置一个较大的磁盘空间给 /var/jenkins_home 目录。因为有一些 Storage Class 不支持动态扩容, 当磁盘满时, 就只能手动拷贝迁移了。

5. 使用 Kubernetes plugin 在 Kuberntes 上构建

基于物理机、虚拟机的构建, 增加了运维成本、限制了并发的数量。使用 Kubernetes plugin 插件在 Kubernetes 上进行构建能充分利用云原生易扩展、易维护的优势, 进行大规模的构建。参考:在 Kubernetes 上动态创建 Jenkins Slave 。由于构建比较占用资源, 为了避免对集群的影响, 可以配置亲和性, 将构建 Pod 集中到指定的节点执行。

6. 使用 CasC 管理 Jenkins 的配置

通过 Jenkins 页面进行各种构建、安全等配置, 不仅繁琐、不易维护, 而且不能够复用。使用 CasC 插件, 允许用户将 Jenkins 的配置, 通过文本的形式进行描述, 还可以放置到 Git 仓库中进行版本管理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
jenkins:
  securityRealm:
    ldap:
      configurations:
        - groupMembershipStrategy:
            fromUserRecord:
              attributeName: "memberOf"
          inhibitInferRootDN: false
          rootDN: "dc=acme,dc=org"
          server: "ldaps://ldap.acme.org:1636"

  nodes:
    - permanent:
        name: "static-agent"
        remoteFS: "/home/jenkins"
        launcher:
          jnlp:
            workDirSettings:
              disabled: true
              failIfWorkDirIsMissing: false
              internalDir: "remoting"
              workDirPath: "/tmp"

  slaveAgentPort: 50000
  agentProtocols:
    - "jnlp2"

7. 使用 Custom WAR Packager 打包 Jenkins

在部署一套新的 Jenkins 环境时, 会需要安装大量插件, 非常影响部署速度, 同时插件是否能正常下载也存在不确定性。Custom WAR Packager 允许用户将 Jenkins 、配置、插件打包成一个完整的 war 包或者镜像。这样无论是开发测试, 还是线上部署, 都可以很方便的部署, 并且环境一致, 而用户只需要写一个 yaml 文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
bundle:
  groupId: com.dev
  artifactId: "jenkins"
  description: "Jenkins Custom With Package"
  vendor: "Jenkins Project"
buildSettings:
  docker:
    base: jenkins/jenkins:2.277.4
    tag: shaowenchen/jenkins:2.277.4
    build: true
war:
  groupId: org.jenkins-ci.main
  artifactId: jenkins-war
  source:
    version: 2.277.4
plugins:
  - groupId: io.jenkins
    artifactId: configuration-as-code
    source:
      version: "1.47"
libPatches:
  - groupId: "org.jenkins-ci.main"
    artifactId: "remoting"
    source:
      git: https://github.com/jenkinsci/remoting.git
systemProperties: {
     jenkins.model.Jenkins.slaveAgentPort: "50000",
     jenkins.model.Jenkins.slaveAgentPortEnforce: "true"}
groovyHooks:
  - type: "init"
    id: "initScripts"
    source: 
      dir: scripts
casc:
  - id: "jcasc-config"
    source:
      dir: jenkins.yml

8. Jenkins Shared Libraries

在使用 Groovy 编写 Pipeline 的过程中, 经常会有大量重复代码。Jenkins 共享库提供函数级别的共享, 可以在不同流水线之间复用同一套函数逻辑, 对于平台建设、大规模使用场景适用。不仅能加快 Pipeline 编写, 还方便维护、平滑升级。

1
2
3
4
5
@Library('utils') import org.foo.Utilities
def utils = new Utilities(this)
node {
  utils.mvn 'clean package'
}

9. 定期重启 Jenkins Master

虽然你会做很多的优化, 但是最后发现重启依然能解决很多的问题。每隔一段时间, 大约一个月, 就会 Agent 连不上, 构建并发上不去, 失败率增加等问题。这是重启一下 Jenkins Master 服务, CICD 系统又恢复了正常, 只是整个服务中断了几分钟。因此, 在没有多个 Jenkins Master 可以切换时, 定期告诉用户, 需要停机短暂维护, 非常有用。

10. 参考

  • https://www.jenkins.io/zh/doc/book/pipeline/shared-libraries/
  • https://github.com/jenkinsci/configuration-as-code-plugin
  • https://github.com/jenkinsci/custom-war-packager
  • https://zhuanlan.zhihu.com/p/370241822

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论