jenkins+gitlab+k8s自动化部署

1. 创建jenkins容器

docker run --name jenkins --user=root -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v  /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker -v /usr/local/maven3:/usr/local/maven3 -d jenkins/jenkins

解释docker脚本

  • -v /var/jenkins_home:/var/jenkins_home :指定jenkins主要目录位置
  • -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime : 指定容器时区 应该也可以用 -e TZ="Asia/Shanghai 但是没有测试
  • -v /var/run/docker.sock:/var/run/docker.sock : 指定宿主机docker位置,让容器内也能使用docker命令 ,k8s也可以这么设置,但是还没试
  • -v /usr/bin/docker:/usr/bin/docker :和上面一样, 指定宿主机docker位置,让容器内也能使用docker命令 ,k8s也可以这么设置,但是还没试
  • -v /usr/local/maven3:/usr/local/maven3 : 指定宿主机maven位置,让容器内也能使用maven3 命令
  • -p 8080:8080 : 指定jenkins访问端口

2. 启动jenkens,

  1. 访问页面:http://host:8080

  2. 初始密码:

    Jenkins initial setup is required. An admin user has been created and a password generated.
    Please use the following password to proceed to installation:
    
    8a9754c9ced144568f5a14be449fd801
    
    This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
    
  3. 选择推荐安装,因为里面有很多现有的插件

3. 安装相关插件

  1. Git Parameter
  2. Gitlab

4. 设置jenkins时区

image
image
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')

5. 创建凭证(注意设置的凭证ID,在下面的Pipeline script中都有使用到)

image
1. 创建gitlab凭证
image
2. 创建远程docker私有库凭证

在新凭据设置界面,类型选择为“Username with password”,ID设置为“aliyun-docker”(此处的ID必须与Jenkinsfile中的保持一致)。Username与Password分别设置为镜像私库的用户名和密码。

image
3. 创建k8s配置文件凭证

k8s中使用kubectl命令时需要yaml格式的服务器及授权信息配置文件。这里将kubectl的yaml配置文件的内容以base64编码后保存在jenkins的凭据中。pipeline任务执行时,先从jenkins凭据中获取内容,进行base64解码后将配置保存为~/.kube/config文件。kubectl的配置文件的内容如下(位置在/root/.kube/config):

image

k8s配置文件样例:

apiVersion: v1
kind: Config
clusters:
- name: "test"
  cluster:
    server: "https://xxxxx"
    api-version: v1
    certificate-authority-data: "xxxxxx"

users:
- name: "user1"
  user:
    token: "xxxx"

contexts:
- name: "test"
  context:
    user: "user1"
    cluster: "test"

current-context: "test"

6. 创建项目(我们选择创建流水线项目)

image
Pipeline script与SCM介绍
image
不同点

Pipeline script

  1. 在脚本中有parameters时,执行构建时可以选择参数值,例如选择git分支;
  2. 拉取git代码时需要自己写checkout脚本
  3. 拉取git代码时需要自己指定文件夹名称
  4. Pipeline script模式好像不会在每一个docker中拉一次代码,看日志时没有看到具体是怎么做的

SCM

  1. 在脚本中有parameters时,不能选择参数,只能使用默认值(可能是没玩明白)
  2. 拉取git代码不能动态变化拉取的git分支,因为jenkinsfile就在代码里需要先拉代码才能得到相关脚本
  3. 拉取git代码时不需要自己指定文件夹名称,默认就是项目名称,好像也不能更改
  4. 在使用docker关键字时,在每个docker容器内部都会拉取一遍代码,也就是说每个docker容器内都有一个重复的副本
相同点

他们使用相同的Pipeline 脚本,除了拉取代码部分需要稍作更改,其他可以完全复制(复制时注意进入项目的路径)

经过对比,我们选择使用Pipeline script方式,因为这样在设置参数时相对灵活

7. Pipeline script 脚本

注意Pipeline script 脚本不能有注释(//xxx),不能有分号(;)否则会执行失败

pipeline{
    agent any

    options {
        timeout(time: 1, unit: 'HOURS') 
        skipStagesAfterUnstable()
    }
    
    environment {
        
        K8S_CONFIG = credentials('k8s-config')
        ALIYUN_DOCKER = credentials('aliyun-docker')
        APP_NAME = 'xh-zuul-backend'
        IMAGE_SERVER = 'registry.cn-beijing.aliyuncs.com'
        IMAGE_NAME = 'space_dev'
    }
    
    parameters {
        string(name: 'TAG', defaultValue: 'v8.0.0', description: '镜像和k8s的tag')
        gitParameter(branchFilter: 'origin/(.*)', defaultValue: ' master', description: '父级项目分支', name: 'ZUUL_BACKEND_BRANCH',  type: 'PT_BRANCH', useRepository: 'http://gitlab.mixinr.com:18080/mixinr-web/xh-zuul-backend.git')
    }
    
    stages {
        stage('Checkout git'){
            steps{
                dir("${APP_NAME}"){
                    git branch: "${ZUUL_BACKEND_BRANCH}", credentialsId: 'xhmh-gitlab', url: 'http://gitlab.mixinr.com:18080/mixinr-web/xh-zuul-backend.git'
                }
            }
            
        }
        stage('Maven package'){
            agent {
                docker {
                    image 'maven:3-jdk-8-alpine'
                    args "-v /root/local/.m2:/root/.m2 -v ${WORKSPACE}/${APP_NAME}:/root/project"
                }
            }
            steps{
                sh """
                    cd /root/project
                    mvn clean package -U -Dmaven.test.skip=true 
                """
            }
        }
        stage('Docker build'){
            steps{
                sh """
                    cd ${WORKSPACE}/${APP_NAME}
                    docker build -t ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG} .
                    docker login -u ${ALIYUN_DOCKER_USR} -p ${ALIYUN_DOCKER_PSW} ${IMAGE_SERVER}
                    docker push ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG}
                    docker rmi  ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG}
                """
            }
        }

        stage('Deploy k8s') {
            agent {
                docker {
                    image 'lwolf/helm-kubectl-docker'
                    args "-v ${WORKSPACE}/${APP_NAME}:/root/project"
                }
            }
            steps {
                sh """
                    mkdir -p ~/.kube
                    echo ${K8S_CONFIG}  | base64 -d > ~/.kube/config
                    cd /root/project
                    echo export IMAGE_URL=${IMAGE_SERVER}   export IMAGE_TAG=${TAG} export APP_NAME=${APP_NAME} export IMAGE_NAME=${IMAGE_NAME}  > param.txt
                    source  param.txt && envsubst < k8s-deployment.yml > k8s-deployment-tmp.yml
                    kubectl apply -f k8s-deployment-tmp.yml -n test
                """
            }
        }
        

        
    }
    
}

参数解释

详细的语法讲解:https://www.cnblogs.com/cay83/p/7537840.html

  1. 设置可选的操作
 options {
        //执行的timeout
        timeout(time: 1, unit: 'HOURS') 
        //状态为Unstable时跳过后面的stage
        skipStagesAfterUnstable()
    }
  1. environment指令指定一系列键值对,这些键值对将被定义为所有step或stage-specific step的环境变量,具体取决于environment指令在Pipeline中的位置。
environment {
        K8S_CONFIG = credentials('k8s-config')
        ALIYUN_DOCKER = credentials('aliyun-docker')
        APP_NAME = 'xh-zuul-backend'
        IMAGE_SERVER = 'registry.cn-beijing.aliyuncs.com'
        IMAGE_NAME = 'space_dev'
    }
  • K8S_CONFIG : 为k8s中kubectl命令的yaml配置文件内容,数据保存为jenkins的“Secret Text”类型的凭据,用credentials方法从凭据中获取。这里保存的yaml配置文件内容以base64编码格式保存,在设置凭据时先要进行base64编码。(此base64编码是非必须的,如果直接保存原文,下面Jenkinsfile中需要去掉base64 -d 解码)
  • ALIYUN_DOCKER:阿里云镜像仓库的用户密码,数据保存为jenkins的“username and password”类型的凭据,用credentials方法从凭据中获取。使用时通过ALIYUN_DOCKER_USR获取用户名,ALIYUN_DOCKER_PSW获取密码。
  • APP_NAME:设置的项目名称
  • IMAGE_SERVER:设置的镜像server
  • IMAGE_NAME:设置的镜像名称
  1. 设置变量,在使用Pipeline script 脚本模式时,每一个在parameters块中声明的参数都要在构建时指定参数,如下:

    image

    点击 Build with Parameters进行构建,设置用于构建项目的参数

parameters {
        string(name: 'TAG', defaultValue: 'v8.0.0', description: '镜像和k8s的tag')
        gitParameter(branchFilter: 'origin/(.*)', defaultValue: ' master', description: '父级项目分支', name: 'ZUUL_BACKEND_BRANCH',  type: 'PT_BRANCH', useRepository: 'http://xxx.mixinr.com/xh-zuul-backend.git')
    }
  • TAG:设置了一个tag,用于指定创建的镜像tag和k8s部署的tag
  • ZUUL_BACKEND_BRANCH:设置git分支参数,动态拉取指定git库的分支,现在使用了branchFilter对分支进行了过滤,注意:拉取选择的分支jenkins会在前面加上origin路径,例如:选择了origin/master,实际jenkins在拉取代码时变成了origin/origin/master,所以要注意分支名称
  1. stages说明,只是一个用户自定义的阶段集合,steps只是stage中必须要有的结构,具体执行的操作都要放到steps块中
  • Checkout git:拉取git代码

    stage('Checkout git'){
         steps{
             dir("${APP_NAME}"){
                        git branch: "${ZUUL_BACKEND_BRANCH}", credentialsId: 'xhmh-gitlab', url: 'http://gitlab.mixinr.com:18080/mixinr-web/xh-zuul-backend.git'
              }
        }
                
    }
    
    • dir("${APP_NAME}") : 创建了一个文件夹,名称是上面定义的APP_NAME
    • git:
      • branch :指定了分支
      • credentialsId : 指定了git的凭证,xhmh-gitlab是我们在上面创建gitlab的凭证id
      • url:指定了拉取的代码url地址
  • 对项目进行maven打包操作,agent是设置代理,使用什么环境执行下面steps操作

    stage('Maven package'){
         agent {
             docker {
                  image 'maven:3-jdk-8-alpine'
                  args "-v /root/local/.m2:/root/.m2 -v ${WORKSPACE}/${APP_NAME}:/root/project"
             }
         }
         steps{
             sh """
                  cd /root/project
                  mvn clean package -U -Dmaven.test.skip=true 
              """
          }
    }
    
    • WORKSPACE:该参数是jenkins默认的环境变量,他的值是当前jenkens所在目录+workspace+创建的流水线名称,相当于执行了pwd命令,在该项目中路径为:/var/jenkins_home/workspace/pipline-demo
    • docker :指定了使用docker容器的方式运行steps中的代码
      • image:指定要拉取的镜像
      • args:设置一些参数,这些参数会在直接写到docker run中
    • sh:执行shell脚本
  • docker build :执行了一些docker命令

    stage('Docker build'){
        steps{
            sh """
                cd ${WORKSPACE}/${APP_NAME}
                docker build -t ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG} .
                docker login -u ${ALIYUN_DOCKER_USR} -p ${ALIYUN_DOCKER_PSW} ${IMAGE_SERVER}
                docker push ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG}
                docker rmi  ${IMAGE_SERVER}/${IMAGE_NAME}/${APP_NAME}:${TAG}
            """
         }
    }
    
  • 部署到k8s,agent是设置代理,使用什么环境执行下面steps操作

    stage('Deploy k8s') {
        agent {
            docker {
                image 'lwolf/helm-kubectl-docker'
                args "-v ${WORKSPACE}/${APP_NAME}:/root/project"
            }
        }
        steps {
            sh """
                mkdir -p ~/.kube
                echo ${K8S_CONFIG}  | base64 -d > ~/.kube/config
                cd /root/project
                echo export IMAGE_URL=${IMAGE_SERVER}   export IMAGE_TAG=${TAG} export APP_NAME=${APP_NAME} export IMAGE_NAME=${IMAGE_NAME}  > param.txt
                source  param.txt && envsubst < k8s-deployment.yml > k8s-deployment-tmp.yml
                kubectl apply -f k8s-deployment-tmp.yml -n test
            """
        }
    }
    
    • docker :指定了使用docker容器的方式运行steps中的代码

      • image:指定要拉取的镜像,这个镜像中有k8s的客户端
      • args:设置一些参数,这些参数会在直接写到docker run中
    • sh:

      • echo ${K8S_CONFIG} | base64 -d > ~/.kube/config : 使用docker的方式执行kubectl命令。在执行前先将K8S_CONFIG中的内容进行base64解密并存为~/.kube/config配置文件,这样在docker容器中就能使用

      • envsubst:使用envsubst命令将k8s的部署文件设置对应参数;例如:k8s-deployment.yml

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: $APP_NAME-deployment
          labels:
            app: $APP_NAME
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: $APP_NAME
          template:
            metadata:
              labels:
                app: $APP_NAME
            spec:
              containers:
              - name: $APP_NAME
                image: $IMAGE_URL/$IMAGE_NAME/$APP_NAME:$IMAGE_TAG
                ports:
                - containerPort: 40080
        
- kubectl apply:部署到k8s

8. 开始构建项目

  1. 点击立即构建

    image
  2. 报错,查看控制台,鼠标放到#29上点击

    image
  3. 查看控制台信息发现是没有设置参数

    image
  4. 刷新项目页面,发现立即构建变成了Build with Parameters

    image
  5. 点击配置,看到参数化构建过程已经被勾选,里面的参数就是设置Pipeline script脚本中的Parameters参数,这也是和SCM不一样的地方,如果是使用SCM,就不会有构建参数的过程了

    image
  1. 再次点击build with 选择参数后构建
    image
  2. 构建成功,鼠标放到上面可以看某一阶段的log日志

    image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342