目录

一、jenkins配置kubernetes

1、安装kubernetes插件

2、配置Kubernetes 地址

二、配置Pod Templates

1、创建Pod Templates

2、配置jnlp-slave容器

3、制作tools-slave镜像

4、配置tools-slave容器

三、配置Jenkinsfile文件

1、配置动态slave构建

四、开始整活  


一、jenkins配置kubernetes

        Jenkins的slave端,没有任务的时候处于闲置状态,slave节点多的话造成资源浪费;是否可以利用kubernetes的Pod来启动slave,动态slave pod来执行构建任务,本文主要介绍利用kubernetes动态创建slave执行构建任务,执行完毕自动销毁。

1、安装kubernetes插件

[系统管理] -> [插件管理] -> [搜索kubernetes]->直接安装,报错是依赖无影响

kubesphere中 jenkins 升级 jenkins kubernetes插件_运维

2、配置Kubernetes 地址

[系统管理] -> [系统配置] ->Cloud -> [Add a new cloud]

kubesphere中 jenkins 升级 jenkins kubernetes插件_jenkins_02

 

kubesphere中 jenkins 升级 jenkins kubernetes插件_kubernetes_03

 

二、配置Pod Templates

1、创建Pod Templates

        Pod Templates相当于k8s集群的pod,包含两个容器分别是jnlp和tools

  • 名称:jnlp-slave
  • 命名空间:jenkins
  • 标签列表:jnlp-slave,作为agent的label选择用
  • 连接 Jenkins 的超时时间(秒) :300,设置连接jenkins超时时间
  • 节点选择器:agent=true
  • 工作空间卷:选择hostpath,设置/opt/jenkins_jobs/,注意需要设置chown -R 1000:1000 /opt/jenkins_jobs/权限,否则Pod没有权限

kubesphere中 jenkins 升级 jenkins kubernetes插件_slave_04

kubesphere中 jenkins 升级 jenkins kubernetes插件_slave_05

kubesphere中 jenkins 升级 jenkins kubernetes插件_流水线_06

2、配置jnlp-slave容器

        jenkins默认配置一个jnlp容器用于连接k8s集群创建slave构建,但是该容器并不包含常用的docker、java、kubectl等命令,我们在此基础上需要集成很多工具,能不能创建一个新的容器,让新容器来做具体的任务,我们采用权限分离的方式:

        jnlp-slave容器只用来负责连接jenkins-master;针对不同的构建环境(java、python、go、nodejs),可以制作不同的容器,来执行对应的任务,针对本次k8s自动部署容器的任务,我们制作一个tools镜像来完成。

kubesphere中 jenkins 升级 jenkins kubernetes插件_运维_07

[root@k8s-node2 myblog]# docker inspect 911d6dcfc160 | grep ENTRYPOINT
                "ENTRYPOINT [\"jenkins-agent\"]"

jnlp默认启动参数查看
jnlp默认镜像地址可以直接写,也可以先构建下任务看看系统默认启动的容器

3、制作tools-slave镜像

        tools-slave镜像不像jnlp镜像是的系统自带,需要根据需求个性化构建,制作一个tools镜像,集成常用的工具,来完成常见的构建任务,需要注意的几点:

  • 使用alpine基础镜像,自身体积比较小
  • 替换国内安装源
  • 为了使用docker,安装了docker
  • 为了克隆代码,安装git
  • 为了后续做python的测试等任务,安装python环境
  • 为了在容器中调用kubectl的命令,拷贝了kubectl的二进制文件
  • 为了认证kubectl,需要在容器内部生成.kube目录及config文件
# 创建个目录准备手动构建镜像
$ mkdir tools;
$ cd tools;
$ cp `which kubectl` .
$ cp ~/.kube/config .
vim Dockerfile

FROM alpine
LABEL maintainer="rui@email.com"
USER root

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories && \
    apk update && \
    apk add  --no-cache openrc docker git curl tar gcc g++ make \
    bash shadow openjdk8 python2 python2-dev py-pip python3-dev openssl-dev libffi-dev \
    libstdc++ harfbuzz nss freetype ttf-freefont && \
    mkdir -p /root/.kube && \
    usermod -a -G docker root

COPY config /root/.kube/

RUN rm -rf /var/cache/apk/* 
#-----------------安装 kubectl--------------------#
COPY kubectl /usr/local/bin/
RUN chmod +x /usr/local/bin/kubectl
# ------------------------------------------------#
执行镜像构建并推送到仓库中,blog必须存在于harbor:
 $ docker build . -t 192.168.0.121:5000/myblog/tools:v1
 $ 确认harboe运行中:cd /usr/local/bin/harbor/;./install
 $ docker push 192.168.0.121:5000/myblog/tools:v1

kubesphere中 jenkins 升级 jenkins kubernetes插件_kubernetes_08

我们可以直接使用该镜像做测试:

# 启动临时镜像做测试
# 主要是确认下这个镜像是否满足我们构建需要的环境
$ docker run -v /var/run/docker.sock:/var/run/docker.sock --rm -ti 192.168.0.121:5000/myblog/tools:v1 bash
# / git clone http://xxxxxx.git
# / kubectl get no
# / python3
#/ docker

4、配置tools-slave容器

        更新Jenkins中的PodTemplate,添加tools镜像,注意同时要先添加名为jnlp的container,因为我们是使用自定义的PodTemplate覆盖掉默认的模板,jnlp的container已经添加好了:

         在卷栏目,添加卷,Host Path Volume,不然在容器中使用docker会提示docker服务未启动

kubesphere中 jenkins 升级 jenkins kubernetes插件_流水线_09

三、配置Jenkinsfile文件

1、配置动态slave构建

        之前是配置好固定jenkins_slave节点进行任务构建,现在采用动态生产k8s容器方式进行构建,构建时启动容器,构建完成销毁,需要配置两个地方

     

1、agent { label 'jnlp-slave'}需要配置成Pod Templates的标签
        2、container('tools') {
                 checkout scm
                }在需要slave执行的步骤指定容器名称,我们本次使用tools容器执行任务

        3、slave容器push harbor无权限,可以把用户密码配到jenkins的secret,或者利用rbac        思路也不错

                sh 'docker login -u admin -p Harbor12345  192.168.0.121:5000'
 

pipeline {
    agent { label 'jnlp-slave'}

    options {
                buildDiscarder(logRotator(numToKeepStr: '10'))
                disableConcurrentBuilds()
                timeout(time: 20, unit: 'MINUTES')
                gitLabConnection('gitlab')
        }

    environment {
        IMAGE_REPO = "192.168.0.121:5000/myblog/myblog"
        DINGTALK_CREDS = credentials('dingTalk')
        TAB_STR = "\n                   \n                  "
    }

    stages {
        stage(' 配置环境变量:') {
            steps {
                script{
                    sh "git log --oneline -n 1 > gitlog.file"
                    env.GIT_LOG = readFile("gitlog.file").trim()
                }
                sh 'printenv'
            }
        }
        stage('检测GIT分支:') {
            steps {
                container('tools') {
                  checkout scm
                }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS = env.STAGE_NAME + "OK!" + env.TAB_STR
                }
            }
        }
        stage('Docker构建镜像:') {
            steps {
                container('tools') {
                  retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
                }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "OK!" + env.TAB_STR
                }
            }
        }
        stage('Docker推送镜像:') {
            steps {
                container('tools') {
                  sh 'docker login -u admin -p Harbor12345  192.168.0.121:5000'
                  retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
                }
                    env.BUILD_TASKS += env.STAGE_NAME + "OK!" + env.TAB_STR
                }
            }
        }
        stage('K8s集群部署容器:') {
            steps {
                container('tools') {
                  sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' deploy/*"
                  timeout(time: 1, unit: 'MINUTES') {
                      sh "kubectl apply -f deploy/"
                  }
                }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                }
            }
        }
    }
    post {
        success {
            echo 'Congratulations!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "^v^ 构建成功 ^v^ \n**项目名称**:rui  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${BRANCH_NAME}   \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        failure {
            echo 'Oh no!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "-_-# 构建失败 -_-# \n**项目名称**:rui  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${BRANCH_NAME}  \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        always {
            echo 'I will always say Hello again!'
        }
    }
}

四、开始整活  

        通过Jenkinsfile配置kubernetes创建动态容器slave,实现demo项目自动发布kubenetes环境

        git提交后,jenkins收到任务,开始构建,此时会多一个jnlp-slave-xxxx名字的pod,这个pod包括两个container,首先通过jnlp容器连接至jenkins-master,然后通过tools容器进行一系列构建操作,构建完成后pod自动销毁,jenkins把构建结果发送给钉钉。

[root@k8s-master harbor]# kubectl get po -n jenkins
NAME                             READY   STATUS    RESTARTS   AGE
gitlab-84d466bb4f-8ds6f          1/1     Running   4          2d5h
jenkins-master-6b4c77dcc-6p6kt   1/1     Running   3          2d6h
jnlp-slave-jjd1b                 2/2     Running   0          109s
postgres-74cc98f9d-8m8nv         1/1     Running   5          2d5h
redis-66b4464f88-758vt           1/1     Running   5          2d5h
[root@k8s-master harbor]# kubectl -n jenkins get po
NAME                             READY   STATUS    RESTARTS   AGE
gitlab-84d466bb4f-8ds6f          1/1     Running   4          2d6h
jenkins-master-6b4c77dcc-6p6kt   1/1     Running   3          2d6h
postgres-74cc98f9d-8m8nv         1/1     Running   5          2d6h
redis-66b4464f88-758vt           1/1     Running   5          2d6h
您在 /var/spool/mail/root 中有新邮件

kubesphere中 jenkins 升级 jenkins kubernetes插件_slave_10