K8S & Jenkins CICD

公司内部各个开发团队,一直有独立运作的习惯,持续集成基本是各自的Jenkins,又由于办公内网,没有足够的硬件资源,搭建ceph这类的分布式存储(我也尝试用几台虚机,搭建了ceph,并测试了存储io,性能感人的差,经费也下不来),所以Jenkins 也一直放在K8S集群外。接下里简单记录一下目前的使用方式

  1. Jenkins添加集群信息:

    image-20201101221351225

  2. 添加用于构建镜像的docker主机,实际上镜像打包还可以通过maven的插件,开发同事在本地开发构建时便是通过maven的docker插件。

    image-20201101221444117

  3. 编写Jenkins的Dockerfile(略,springcloud微服务的话,官方有一个案例,拿来开始改改就可以用了)

  4. 仓库里添加jenkinsfile,在此需要考虑到各种语言的编译过程的包的缓存,用来加速下一次构建编译的速度,以下便是将maven本地仓库的本地路径,挂载到PVC中。

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    pipeline {
    agent {
    kubernetes {
    cloud 'k8s-api-cs-software.sunvalley.com.cn'
    nodeSelector 'app=jenkins'
    idleMinutes 5
    yaml """
    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    app: jenkins-jnlp
    spec:
    containers:
    - name: jnlp
    image: harbor.sunvalley.com.cn/library/jenkins-jnlp-slave:3.35-5
    - name: maven
    image: cs-harbor.sunvalley.com.cn/library/maven-base-image:3.0.5
    command:
    - cat
    tty: true
    volumeMounts:
    - mountPath: /data/m2_dev/
    name: m2-dev
    - name: docker-ci
    image: harbor.sunvalley.com.cn/library/docker-ci:v19.03.5
    command:
    - cat
    tty: true
    volumeMounts:
    - mountPath: /var/run/docker.sock
    name: docker-sock
    - mountPath: /data/m2_dev/
    name: m2-dev
    - name: kubectl-tools
    image: harbor.sunvalley.com.cn/library/kubectl-tools:1.16.3
    command:
    - cat
    tty: true
    volumes:
    - name: docker-sock
    hostPath:
    path: /var/run/docker.sock
    - name: m2-dev
    hostPath:
    path: /data/m2_dev/
    """
    // serviceAccountName: admin-sample-user
    }
    }
    stages {
    stage('Run maven') {
    steps {
    // container('maven') {
    // sh 'mvn -B -f pom.xml -s /data/m2_dev/settings.xml clean package -Dmaven.test.skip=true -pl com.sunvalley:mwp-message-center -am -Pdev1 -e -U'
    // }
    // container('docker-ci') {
    // dir(path: "mwp-message-center") {
    // script {
    // docker.withRegistry('https://cs-harbor.sunvalley.com.cn', 'harbor' ){
    // def customImage = docker.build("cs-harbor.sunvalley.com.cn/internal/${env.JOB_NAME}:${env.GIT_COMMIT}")
    // customImage.push()
    // }
    // }
    // }
    // }
    container('kubectl-tools') {
    // sh "sed -i 's/<PROJECT_NAME>/${env.JOB_NAME}/' deployment.yaml"
    // sh "sed -i 's/<BUILD_TAG>/${env.GIT_COMMIT}/' deployment.yaml"
    // sh 'kubectl apply -f deployment.yaml'
    sh "kubectl get pods"
    }
    }
    }
    }
    }
  1. Jenkinsfile 无论时声明式还是脚本式。都不是yaml语法,Jenkins自身提供了一个Linter,不过呀。总是在界面上切来切去。有点麻烦。如果是vscode用户可以用下面的插件,毕竟项目多了,jenkinsfile 熟悉了,这个工作会帮上忙。

    image-20201031090430764

然而,也有需要吐糟的地方,Jenkins的插件管理,管理起来好崩溃。有些插件会依赖另一个插件的高版本。所以升级插件的时候,一并把依赖插件一起升级了。举例就是pipeline的升级,把Jenkins maven插件一并升级了。结果新的Jenkins maven的版本不支持jdk1.6。 老旧的java项目构建时报错。又比如jenkins k8s cloud 的插件的部分功能,在较新的Jenkins上才能运行(也是测试了好久才发现),文档半点没提。甚至试过在升级jenkins插件的是,官方下载中心垮掉了。第二天才恢复。

再吐糟一点,Jenkins的agent,需要回调master的端口来通讯,我们目前是固定了50000端口。在跨公网的场景下,就有点为难了,我不想暴露50000端口到公网啊。

还有呀,Jenkins 的K8S 插件,目前不支持在构建编译过程中, 调用两个K8S集群。描述个案例:我在内网自建的K8S构建后,最后一步再apply到AWS的EKS。(还要花点时间,寻找到优雅的解决方式)

Author: Chandler Kwok
Link: http://yoursite.com/2020/10/31/K8S-Jenkins-CICD/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.