在kubernetes中部署Jenkins并简单使用

在kubernetes中部署Jenkins并简单使用

一、动态生成Slave

1.1、简介

之前我们都是在物理机或者虚拟机上部署jenkins,但是这种部署方式会有一些难点,如下:

  • 主 Master 发生单点故障时,整个流程都不可用了
  • 每个 Slave 的配置环境不一样,来完成不同语言的编译打包等操作,但是这些差异化的配置导致管理起来非常不方便,维护起来也是比较费劲
  • 资源分配不均衡,有的 Slave 要运行的 job 出现排队等待,而有的 Slave 处于空闲状态
  • 资源有浪费,每台 Slave 可能是物理机或者虚拟机,当 Slave 处于空闲状态时,也不会完全释放掉资源。

正因为上面的这些种种痛点,我们渴望一种更高效更可靠的方式来完成这个 CI/CD 流程,而 Docker 虚拟化容器技术能很好的解决这个痛点,又特别是在 Kubernetes 集群环境下面能够更好来解决上面的问题,下图是基于 Kubernetes 搭建 Jenkins 集群的简单示意图:

在kubernetes中部署Jenkins并简单使用

从图上可以看到 Jenkins Master 和 Jenkins Slave 以 Pod 形式运行在 Kubernetes 集群的 Node 上,Master 运行在其中一个节点,并且将其配置数据存储到一个 Volume 上去,Slave 运行在各个节点上,并且它不是一直处于运行状态,它会按照需求动态的创建并自动删除。

这种方式的工作流程大致为:当 Jenkins Master 接受到 Build 请求时,会根据配置的 Label 动态创建一个运行在 Pod 中的 Jenkins Slave 并注册到 Master 上,当运行完 Job 后,这个 Slave 会被注销并且这个 Pod 也会自动删除,恢复到最初状态。

这种方式部署给我们带来如下好处:

  • 服务高可用,当 Jenkins Master 出现故障时,Kubernetes 会自动创建一个新的 Jenkins Master 容器,并且将 Volume 分配给新创建的容器,保证数据不丢失,从而达到集群服务高可用。
  • 动态伸缩,合理使用资源,每次运行 Job 时,会自动创建一个 Jenkins Slave,Job 完成后,Slave 自动注销并删除容器,资源自动释放,而且 Kubernetes 会根据每个资源的使用情况,动态分配 Slave 到空闲的节点上创建,降低出现因某节点资源利用率高,还排队等待在该节点的情况。
  • 扩展性好,当 Kubernetes 集群的资源严重不足而导致 Job 排队等待时,可以很容易的添加一个 Kubernetes Node 到集群中,从而实现扩展。

1.2、部署

1、创建PV、PVC,为Jenkins提供数据持久化:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 172.16.1.128
    path: /data/k8s/jenkins

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: devops
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

2、创建角色授权

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-sa
  namespace: devops

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: jenkins-cr
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get","list","watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: jenkins-crd
roleRef:
  kind: ClusterRole
  name: jenkins-cr
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: jenkins-sa
  namespace: devops

1、在Kubernetes中部署Jenkins,新建Deployment,jenkins-deploy.yaml

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops 
spec:
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccount: jenkins-sa
      containers:
      - name: jenkins
        image: jenkins/jenkins:lts
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        - containerPort: 50000
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:
        - name: jenkinshome
          mountPath: /var/jenkins_home
      securityContext:
        fsGroup: 1000
      volumes:
      - name: jenkinshome
        persistentVolumeClaim:
          claimName: jenkins-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: devops 
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: NodePort
  ports:
  - name: web
    port: 8080
    targetPort: web
    nodePort: 30002
  - name: agent
    port: 50000
    targetPort: agent

5、创建上面的资源清单

# kubectl apply -f jenkins-rbac.yaml
# kubectl apply -f jenkins-pvc.yaml
# kubectl apply -f jenkins-deploy.yaml

启动如果报如下错误(因为我们容器里是以jenkins用户启动,而我们NFS服务器上是root启动,所以没有权限):

[root@master manifests]# kubectl logs jenkins-688c6cd5fd-lj6zg -n devops 
touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

然后给我们NFS服务器上的目录授权即可:

# chown -R 1000 /data/k8s/jenkins/jenkins

然后登录网站,因为我们Service是采用NodePort类型,其端口为30002,我们直接在浏览器用这个端口访问:

在kubernetes中部署Jenkins并简单使用

密码可以通过如下命令获得:

# cat /data/k8s/jenkins/secrets/initialAdminPassword 
12b503a274354e09a465b4f76664db70

然后安装插件到安装完成。

1.3、配置

1、安装插件kubernetes

在kubernetes中部署Jenkins并简单使用

2、填写Kubernetes和Jenkins的配置信息
配置管理->系统配置->新增cloud。

在kubernetes中部署Jenkins并简单使用

在kubernetes中部署Jenkins并简单使用

在kubernetes中部署Jenkins并简单使用


按照图中红色框中填写,其中Kubernetes命名空间填写我们Jenkins所在的命名空间。
备注:
如果连接测试失败,很可能是权限问题,我们就需要把ServiceAccount的凭证jenkins-sa添加进来。

3、配置Pod模板

在kubernetes中部署Jenkins并简单使用


另外需要挂载两个主机目录:

  1. /var/run/docker.sock:该文件是用于 Pod 中的容器能够共享宿主机的 Docker;
  2. /root/.kube:这个目录挂载到容器的/root/.kube目录下面这是为了让我们能够在 Pod 的容器中能够使用 kubectl 工具来访问我们的 Kubernetes 集群,方便我们后面在 Slave Pod 部署 Kubernetes 应用;

在kubernetes中部署Jenkins并简单使用


避免一些权限不足,需要配置ServiceAccount

在kubernetes中部署Jenkins并简单使用

1.4、测试

1、创建一个项目

在kubernetes中部署Jenkins并简单使用

2、在标签位置填写我们前面模板中定义的Label

在kubernetes中部署Jenkins并简单使用

3、直接在构建处执行shell进行测试

在kubernetes中部署Jenkins并简单使用

然后点击构建,在终端可以看到整个过程:

[root@master manifests]# kubectl get pod -n devops -w
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-6595ddd5d-m5fvd   1/1     Running   0          144m
jenkins-slave-kkc2b       0/1     Pending   0          0s
jenkins-slave-kkc2b       0/1     Pending   0          0s
jenkins-slave-kkc2b       0/1     ContainerCreating   0          0s
jenkins-slave-kkc2b       1/1     Running             0          3s
jenkins-slave-kkc2b       1/1     Terminating         0          31s
jenkins-slave-kkc2b       1/1     Terminating         0          31s

也可以在jenkins里看日志如下:

在kubernetes中部署Jenkins并简单使用

二、Pipeline

2.1、简介

Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排可视化的工作。
Jenkins Pipeline 有几个核心概念:

  • Node:节点,一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境,比如我们之前动态运行的 Jenkins Slave 就是一个 Node 节点
  • Stage:阶段,一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作,比如:Build、Test、Deploy,Stage 是一个逻辑分组的概念,可以跨多个 Node
  • Step:步骤,Step 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供,比如命令:sh 'make',就相当于我们平时 shell 终端中执行 make 命令一样。

Pipeline的使用:

  • Pipeline 脚本是由 Groovy 语言实现的
  • Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)语法
  • Pipeline 也有两种创建方法:可以直接在 Jenkins 的 Web UI 界面中输入脚本;也可以通过创建一个 Jenkinsfile 脚本文件放入项目源码库中
  • 一般我们都推荐在 Jenkins 中直接从源代码控制(SCMD)中直接载入 Jenkinsfile Pipeline 这种方法

2.2、创建

2.2.1、简单的Pipeline

直接 在Jenkins的WEB UI上输入脚本。

在kubernetes中部署Jenkins并简单使用


在kubernetes中部署Jenkins并简单使用


脚本内容:

node {
  stage('Clone') {
    echo "1.Clone Stage"
  }
  stage('Test') {
    echo "2.Test Stage"
  }
  stage('Build') {
    echo "3.Build Stage"
  }
  stage('Deploy') {
    echo "4. Deploy Stage"
  }
}

然后保存--> 点击构建--> 观察日志

在kubernetes中部署Jenkins并简单使用


输出符合我们脚本内容。

2.2.2、在slave中运行Pipeline

上面对Jenkins的Pipeline做了简单的测试,但是其并未在我们的Slave中运行,如果要在Slave中运行,其就要使用我们前面添加的Label,如下:

node('joker-jnlp') {
    stage('Clone') {
      echo "1.Clone Stage"
    }
    stage('Test') {
      echo "2.Test Stage"
    }
    stage('Build') {
      echo "3.Build Stage"
    }
    stage('Deploy') {
      echo "4. Deploy Stage"
    }
}

然后我们保存并点击构建,观察Pod的变化:

[root@master ~]# kubectl get pod -n devops  -w
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-6595ddd5d-m5fvd   1/1     Running   0          2d23h
jenkins-slave-vq8wf       0/1     Pending   0          0s
jenkins-slave-vq8wf       0/1     Pending   0          0s
jenkins-slave-vq8wf       0/1     ContainerCreating   0          0s
jenkins-slave-vq8wf       1/1     Running             0          2s
jenkins-slave-vq8wf       1/1     Terminating         0          27s
jenkins-slave-vq8wf       1/1     Terminating         0          27s

我们可以看到其依据我们定义的模板动态生成了jenkins-slave的Pod,我们在Jenkins的日志中查看:

在kubernetes中部署Jenkins并简单使用


可以看到两个的名字是一样的。

2.2.3、部署完整应用

部署应用的流程如下:

  • 编写代码
  • 测试
  • 编写 Dockerfile
  • 构建打包 Docker 镜像
  • 推送 Docker 镜像到仓库
  • 编写 Kubernetes YAML 文件
  • 更改 YAML 文件中 Docker 镜像 TAG
  • 利用 kubectl 工具部署应用

所以基本的Pipeline脚本框架应该如下:

node('joker-jnlp') {
    stage('Clone') {
      echo "1.Clone Stage"
    }
    stage('Test') {
      echo "2.Test Stage"
    }
    stage('Build') {
      echo "3.Build Docker Image Stage"
    }
    stage('Push') {
      echo "4.Push Docker Image Stage"
    }
    stage('YAML') {
      echo "5. Change YAML File Stage"
    }
    stage('Deploy') {
      echo "6. Deploy Stage"
    }
}

第一步:克隆代码

stage('Clone') {
    echo "1.Clone Stage"
    git url: "https://github.com/baidjay/jenkins-demo.git"
    script {
        build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
    }
    echo "${build_tag}"
}

我们这里采用和git commit的记录为镜像的 tag,这里有一个好处就是镜像的 tag 可以和 git 提交记录对应起来,也方便日后对应查看。但是由于这个 tag 不只是我们这一个 stage 需要使用,下一个推送镜像是不是也需要,所以这里我们把这个 tag 编写成一个公共的参数,把它放在 Clone 这个 stage 中。

第二步:测试

stage('Test') {
      echo "2.Test Stage"
    }

测试可以是单测,也可以是工具,我们这里就简单存在这个步骤。

第三步:构建镜像

stage('Build') {
    echo "3.Build Docker Image Stage"
    sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ."
}

这一步我们就使用到上面定义的build_tag变量。

第四步:推送镜像

stage('Push') {
    echo "4.Push Docker Image Stage"
    sh "docker login --username=www.565361785@qq.com registry.cn-hangzhou.aliyuncs.com -p xxxxx"
    sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}"
}

配置Jenkins,隐藏用户名密码信息:

在kubernetes中部署Jenkins并简单使用


其中ID:AliRegistry 是我们后面要用的值。
这样我们上面的脚本就可以定义如下:

stage('Push') {
    echo "4.Push Docker Image Stage"
    withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) {
        sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}"
        sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}"
    }
}

注意我们这里在 stage 中使用了一个新的函数withCredentials,其中有一个 credentialsId 值就是我们刚刚创建的 ID 值,而对应的用户名变量就是 ID 值加上 User,密码变量就是 ID 值加上 Password,然后我们就可以在脚本中直接使用这里两个变量值来直接替换掉之前的登录 docker hub 的用户名和密码,现在是不是就很安全了,我只是传递进去了两个变量而已,别人并不知道我的真正用户名和密码,只有我们自己的 Jenkins 平台上添加的才知道。

第五步:更改YAML文件

stage('YAML') {
    echo "5. Change YAML File Stage"
    sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
    sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
}

其YAML文件为(YAML文件放在项目根目录):

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: jenkins-demo
spec:
  template:
    metadata:
      labels:
        app: jenkins-demo
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:<BUILD_TAG>
        imagePullPolicy: IfNotPresent
        name: jenkins-demo
        env:
        - name: branch
          value: <BRANCH_NAME>

第六步:部署
部署阶段我们增加人工干预,可能需要将该版本先发布到测试环境、QA 环境、或者预览环境之类的,总之直接就发布到线上环境去还是挺少见的,所以我们需要增加人工确认的环节,一般都是在 CD 的环节才需要人工干预,比如我们这里的最后两步,我们就可以在前面加上确认,比如:
我们将YAML这一步改为:

stage('YAML') {
    echo "5. Change YAML File Stage"
    def userInput = input(
        id: 'userInput',
        message: 'Choose a deploy environment',
        parameters: [
            [
                $class: 'ChoiceParameterDefinition',
                choices: "Dev\nQA\nProd",
                name: 'Env'
            ]
        ]
    )
    echo "This is a deploy step to ${userInput.Env}"
    sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
    sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
    sh "sed -i 's#cnych/jenkins-demo#registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo#' k8s.yaml"
}

然后再部署阶段:

stage('Deploy') {
    echo "6. Deploy Stage"
    if (userInput.Env == "Dev") {
      // deploy dev stuff
    } else if (userInput.Env == "QA"){
      // deploy qa stuff
    } else {
      // deploy prod stuff
    }
    sh "kubectl apply -f k8s.yaml"
}

由于这一步也属于部署的范畴,所以我们可以将最后两步都合并成一步,我们最终的Pipeline脚本如下:

node('joker-jnlp') {
    stage('Clone') {
    echo "1.Clone Stage"
    git url: "https://github.com/baidjay/jenkins-demo.git"
    script {
        build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
    }
    echo "${build_tag}"
    }
    stage('Test') {
      echo "2.Test Stage"
    }
    stage('Build') {
    echo "3.Build Docker Image Stage"
    sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ."
    }
    stage('Push') {
    echo "4.Push Docker Image Stage"
    withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) {
        sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}"
        sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}"
    }
    }
    stage('Deploy') {
    echo "5. Change YAML File Stage"
    def userInput = input(
        id: 'userInput',
        message: 'Choose a deploy environment',
        parameters: [
            [
                $class: 'ChoiceParameterDefinition',
                choices: "Dev\nQA\nProd",
                name: 'Env'
            ]
        ]
    )
    echo "This is a deploy step to ${userInput}"
    sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
    sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
    echo "6. Deploy Stage"
    if (userInput == "Dev") {
      // deploy dev stuff
    } else if (userInput == "QA"){
      // deploy qa stuff
    } else {
      // deploy prod stuff
    }
    sh "kubectl apply -f k8s.yaml -n default"
    }
}

然后构建面板如下:

在kubernetes中部署Jenkins并简单使用

然后查看Pod日志如下:

[root@master jenkins]# kubectl logs jenkins-demo-789fdc6878-5pzbx
Hello, Kubernetes!I'm from Jenkins CI!

2.2.4、Jenkinsfile

万里长征,貌似我们的任务完成了,其实不然,我们这里只是完成了一次手动的添加任务的构建过程,在实际的工作实践中,我们更多的是将 Pipeline 脚本写入到 Jenkinsfile 文件中,然后和代码一起提交到代码仓库中进行版本管理。现在我们将上面的 Pipeline 脚本拷贝到一个 Jenkinsfile 中,将该文件放入上面的 git 仓库中,但是要注意的是,现在既然我们已经在 git 仓库中了,是不是就不需要 git clone 这一步骤了,所以我们需要将第一步 Clone 操作中的 git clone 这一步去掉。
如下:

node('joker-jnlp') {
    stage('Prepare') {
    echo "1.Prepare Stage"
    script {
        build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
    }
    echo "${build_tag}"
    }
    stage('Test') {
      echo "2.Test Stage"
    }
    stage('Build') {
    echo "3.Build Docker Image Stage"
    sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ."
    }
    stage('Push') {
    echo "4.Push Docker Image Stage"
    withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) {
        sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}"
        sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}"
    }
    }
    stage('Deploy') {
    echo "5. Change YAML File Stage"
    def userInput = input(
        id: 'userInput',
        message: 'Choose a deploy environment',
        parameters: [
            [
                $class: 'ChoiceParameterDefinition',
                choices: "Dev\nQA\nProd",
                name: 'Env'
            ]
        ]
    )
    echo "This is a deploy step to ${userInput}"
    sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
    sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
    echo "6. Deploy Stage"
    if (userInput == "Dev") {
      // deploy dev stuff
    } else if (userInput == "QA"){
      // deploy qa stuff
    } else {
      // deploy prod stuff
    }
    sh "kubectl apply -f k8s.yaml -n default"
    }
}

然后我们更改上面的 jenkins-demo 这个任务,点击 Configure -> 最下方的 Pipeline 区域 -> 将之前的 Pipeline Script 更改成 Pipeline Script from SCM,然后根据我们的实际情况填写上对应
的仓库配置,要注意 Jenkinsfile 脚本路径。

在kubernetes中部署Jenkins并简单使用

在实际的项目中,往往一个代码仓库都会有很多分支的,比如开发、测试、线上这些分支都是分开的,一般情况下开发或者测试的分支我们希望提交代码后就直接进行 CI/CD 操作,而线上的话最好增加一个人工干预的步骤,这就需要 Jenkins 对代码仓库有多分支的支持,当然这个特性是被 Jenkins 支持的。
然后新建一个 Jenkinsfile 文件,配置如下:

node('joker-jnlp') {
    stage('Prepare') {
        echo "1.Prepare Stage"
        checkout scm
        script {
            build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
            if (env.BRANCH_NAME != 'master') {
                build_tag = "${env.BRANCH_NAME}-${build_tag}"
            }
        }
    }
    stage('Test') {
      echo "2.Test Stage"
    }
    stage('Build') {
        echo "3.Build Docker Image Stage"
        sh "docker build -t registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag} ."
    }
    stage('Push') {
        echo "4.Push Docker Image Stage"
        withCredentials([usernamePassword(credentialsId: 'AliRegistry', passwordVariable: 'AliRegistryPassword', usernameVariable: 'AliRegistryUser')]) {
            sh "docker login -u ${AliRegistryUser} registry.cn-hangzhou.aliyuncs.com -p ${AliRegistryPassword}"
            sh "docker push registry.cn-hangzhou.aliyuncs.com/ik9s/jenkins-demo:${build_tag}"
        }
    }
    stage('Deploy') {
        echo "5. Deploy Stage"
        if (env.BRANCH_NAME == 'master') {
            input "确认要部署线上环境吗?"
        }
        sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml"
        sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s.yaml"
        sh "kubectl apply -f k8s.yaml --record"
    }
}

在第一步中我们增加了checkout scm命令,用来检出代码仓库中当前分支的代码,为了避免各个环境的镜像 tag 产生冲突,我们为非 master 分支的代码构建的镜像增加了一个分支的前缀,在第五步中如果是 master 分支的话我们才增加一个确认部署的流程,其他分支都自动部署,并且还需要替换 k8s.yaml 文件中的环境变量的值。

三、BlueOcean

我们这里使用 BlueOcean 这种方式来完成此处 CI/CD 的工作,BlueOcean 是 Jenkins 团队从用户体验角度出发,专为 Jenkins Pipeline 重新设计的一套 UI 界面,仍然兼容以前的 fressstyle 类型的 job,BlueOcean 具有以下的一些特性:

  • 连续交付(CD)Pipeline 的复杂可视化,允许快速直观的了解 Pipeline 的状态
  • 可以通过 Pipeline 编辑器直观的创建 Pipeline
  • 需要干预或者出现问题时快速定位,BlueOcean 显示了 Pipeline 需要注意的地方,便于异常处理和提高生产力
  • 用于分支和拉取请求的本地集成可以在 GitHub 或者 Bitbucket 中与其他人进行代码协作时最大限度提高开发人员的生产力。

BlueOcean 可以安装在现有的 Jenkins 环境中,也可以使用 Docker 镜像的方式直接运行,我们这里直接在现有的 Jenkins 环境中安装 BlueOcean 插件:登录 Jenkins Web UI -> 点击左侧的 Manage Jenkins -> Manage Plugins -> Available -> 搜索查找 BlueOcean -> 点击下载安装并重启

在kubernetes中部署Jenkins并简单使用

3.1、创建Pipeline

点击创建:

在kubernetes中部署Jenkins并简单使用


在kubernetes中部署Jenkins并简单使用

获取Token的步骤:

在kubernetes中部署Jenkins并简单使用


在kubernetes中部署Jenkins并简单使用


在kubernetes中部署Jenkins并简单使用

然后获取Token:

在kubernetes中部署Jenkins并简单使用

创建完成如下所示:

在kubernetes中部署Jenkins并简单使用


原文地址:https://blog.51cto.com/15080014/2653652

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


基础环境、流程图1)流程图jenkinspipeline发布应用2)、jenkins上安装kubectl#主节点上查看kubectl位置[root@k8s01~]#whichkubectl/usr/bin/kubectl#将k8s节点的kubectl文件cp至jenkinsscp10.0.0.101:/usr/bin/kubectl.cp./kubectl/usr/local/bin/kubectl
本节是建立在流水线入门内容的基础上,而且,应当被当作一个参考。对于在实际示例中如何使用流水线语法的更多信息,请参阅本章在流水线插件的2.5版本中的使用Jenkinsfile部分,流水线支持两种离散的语法,具体如下对于每种的优缺点,参见语法比较。正如本章开始讨论的,流水线最
Linuxcentos7安装Jenkins(jenkins-2.227-1.1.noarch.rpm)时遇到问题:1.出现问题1:安装jenkins一直失败,提示Nosuchfileordirectory[helen@linuxprobeJenkins]$sudorpm-ivhjenkins-2.227-1.1.noarch.rpmPreparing...####################
作为一个拥有很多账号的当代美少女,忘记用户名密码什么的是再正常不过的事了。“忘记密码”这一功能给我真的带来了很大的福音啊。但是最近重新使用Jenkins时,看到需要输入用户名密码,顿时脑子一片空白。经过一系列的查找,终于解决了问题,害,只有把方法记下来才是王道,以后妈妈再
Jenkins、GitLab和Maven(Nexus)完成自动构建迈向持续集成持续集成,毋庸置疑的是这是两部分要求,一个是持续一个是集成,那么持续和集成到底表示了什么要求和含义呢?其中的集成比较容易理解就是指开发人员将自己开发的代码不断地交付给全部系统的代码,在Git仓的概念之下也就是不断地
 下载文档https://www.jenkins.io/zh/download/  Debian下载1.下载安装keyhttps://pkg.jenkins.io/debian-stable/jenkins.io.key  
流水线建设从Jenkins部署开始Jenkins是一个独立的开源自动化服务器,可以用来自动化,例如构建、测试和部署软件等各种任务,是一个实现CI(持续集成)的很好的工具。Jenkins可以通过本地系统包、Docker安装,甚至可以在安装Java运行时环境的机器上独立运行。JenkCI/CD的概念谈到持
原因:这种情况是SSHServer中的RemoteDirectory路径不存在。解决方法:重新输入目标服务器中存在的路径。      
什么是持续集成持续集成(Continuousintegration,简称CI)指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。通过持续集成,团
Tomcat安装:1.下载Tomcat包:http:/omcat.apache.org/并解压2.启动:双击bin\startup.bat文件浏览器访问:http://localhost:8080/3.Tomcat配置登录:打开confomcat-users.xml文件添加如下代码:<rolerolename="manager-gui"/><userusername="admin"password=&q
文章目录jenkinscron笔记简介H符号(hash的简写)别名例子jenkinscron笔记简介jenkinscron遵循普通cron的语法,略有不同,每行包含五个字段可以使用Tab和空行分割分钟小时日月周0-590-231-311-120-7(0和7都表示周日)可以使用以下操作符为一个字段指定多个值(按照
1.nginx的配置location/jenkinsno{indexindex.htmlindex.htm;proxy_passhttp://127.0.0.1:8081;proxy_connect_timeout3000s;proxy_send_timeout3000s;proxy_read_timeout3000s;prox
1、下载安装插件下载地址:http://files.jetbrains.org.cn/aliyun-oss.hpi在Jenkins中安装插件,请到ManageJenkins->Advanced->Upload,上传插件(.hpi文件)安装完毕后请重新启动Jenkins2、搜索安装jenkins插件安装3、安装完成以后配置阿里云oss账号oss这边设置:(账号的权限也要
首先将构建历史清除Jenkins构建历史删除与重置然后进入Jenkins服务器工作目录oot/.jenkinstar-czvfjobs.tarjobs 将jobs打包将job.tar文件复制到新Jenkins服务器相同目录下解压tar包 tar-zxvfjob.tar登录新JenkinsJenkins-系统管理-读取配置,只有点击了读取配置,原
一、动态生成Slave1.1、简介之前我们都是在物理机或者虚拟机上部署jenkins,但是这种部署方式会有一些难点,如下:主Master发生单点故障时,整个流程都不可用了每个Slave的配置环境不一样,来完成不同语言的编译打包等操作,但是这些差异化的配置导致管理起来非常不方便,维护起来也是
from jenkins import Jenkins# 判断job是否运行结束def build():    job = 'branch-deploy-wap'    params = {        'server_ip': '10.160.30.XXX',        'server_username': 'root',        'server_userpass&#
背景client端执行webUI自动化测试时依赖操作系统上安装了对应的浏览器,并且浏览器与驱动要进行版本的对应——而selenium是可以部署集群,通过远程的方式执行对应的自动化用例,方便高效。原理1、通过代码可知,自动化运行的主类接收了任务id,获取到任务信息后根据任务类型判断进行接口
背景工具选择架构设计及技术实现参数设计断言持续集成测试集编写总结  一、背景1.目前公司发展比较迅速,还处于不停堆业务阶段,所以迭代比较频繁,导致人工回归的成本越来越大2.在有限的测试资源情况下,开发自测的需求占比不低,后端频繁发布容易心里没底
本地pycharm打开项目,运行自动化项目下载项目代码,并用pycharm打开项目gitclonehttps://gitee.com/iread9527/iInterface_python.git进入iInterface_python目录下,cdiInterface_python使用pip3install-rrequirements.txt命令,安装python项目依赖的第三方库使
Jenkins邮件设置一、简介最近有朋友问Jenkins邮件设置的问题,想起来当时也是碰到不少坑,网上看了很多博客说的解决办法根本没有用。最后我解决了这个问题,在此记录一下,希望能够帮助到在网上搜了半天仍然徒劳无功的朋友们,我懂那种失败了一次又一次的感觉,希望能帮到大家。二、配置步