Jenkins优化Kubernetes部署流水线

由于jenkins 版本升级导致以前的功能不能用了。主要是 kubernetes-plugin 配置文件位置换了。导致以前的配置文件丢失,在实践中又发现比以前更好的实现方式。故重新写个新版教程。
该篇文件需要配合 基于K8S构建企业级Jenkins CI/CD平台实战(二) 之 kubernetes-plugin 插件使用 观看

jenkins 安装

参考 基于K8S构建企业级Jenkins CI/CD平台实战(一) 之 环境搭建

Jenkins定制Agent

可以使用我个人已经编译好的 docker pull andanyoung/kubectl-maven-agent

由于官方提供了简单的 jenkins-agent。 如果我们的打包流程需要用到git、Java、Maven、Kubernetes的话,我们也需要将这些集成到行的 jenkins-agent 中。 我们基于Jenkins的官方基础镜像进行定制,Dockerfile如下:

FROM jenkins/inbound-agent:latest-jdk8

ARG MAVEN_VERSION=3.6.3
ARG KUBECTL_VERSION=v1.22.3

# tool
USER root
RUN apt-get update && \
  apt-get install -y curl && \
  apt-get clean

# maven
RUN curl -OL https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz && \
  tar -zxf ./apache-maven-${MAVEN_VERSION}-bin.tar.gz && \
  mv apache-maven-${MAVEN_VERSION} /usr/local && \
  rm -f apache-maven-${MAVEN_VERSION}-bin.tar.gz && \
  ln -s /usr/local/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/bin/mvn && \
  ln -s /usr/local/apache-maven-${MAVEN_VERSION} /usr/local/apache-maven && \
  mkdir -p /home/jenkins/.m2  && \
  chown -R jenkins:jenkins  /home/jenkins/.m2

# kubectl
RUN curl -OL https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
  chmod +x ./kubectl && \
  mv ./kubectl /usr/local/bin/kubectl && \
  ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
  echo $TZ > /etc/timezone 

VOLUME [ "/home/jenkins/.m2" ]

USER jenkins

ENTRYPOINT ["/usr/local/bin/jenkins-agent"]

# docker build --build-arg KUBECTL_VERSION=v1.22.3 --build-arg MAVEN_VERSION=3.6.3 -t "andanyoung/kubectl-maven-agent" .
# docker push andanyoung/kubectl-maven-agent

inbound-agent 和 nlp-slave 的区别

Jenkins agent 官方 Docker 镜像重命名了 。

  • jenkins/agent 镜像:原名称为jenkins/slave,从4.3-2 开始更名为
  • jenkins/agentjenkins/inbound-agent 镜像:原名称为 jenkins/jnlp-slave ,从 4.3-2 开始更名为 jenkins/inbound-agent
  • jenkins/ssh-agent 镜像:原名称为 jenkins/ssh-slave ,从 2.0.0 开始更名为 jenkins/ssh-agent

kubernetes-plugin 的使用

参考 基于K8S构建企业级Jenkins CI/CD平台实战(二) 之 kubernetes-plugin 插件使用

jenkins插件连接K8S配置

需要先安装pipeline插件, 建议不在 pipeline UI上配置pod创建模版,免得以后每来一个项目都要创建,管理不方便,建议使用pipeline统一 配置。
Kubernetes插件介绍:https://github.com/jenkinsci/kubernetes-plugin
配置路径 “系统管理” —> “系统设置” —> “云(翻到最后)” —> “Kubernetes”
新版已放到 “节点管理” -> “configureClouds” (> v2.343)

  • Name 处默认为 kubernetes,也可以修改为其他名称,如果这里修改了,下边在执行 Job 时指定 podTemplate() 参数 cloud 为其对应名称,否则会找不到,cloud 默认值取:kubernetes
  • Kubernetes URL jenkins找到 k8s的地址。 我填写了 https://kubernetes.default 这里我填写了 Kubernetes Service 对应的 DNS 记录,通过该 DNS 记录可以解析成该 Service 的 Cluster IP,注意:也可以填写 https://kubernetes.default.svc.cluster.local 完整 DNS 记录,因为它要符合 <svc_name>.<namespace_name>.svc.cluster.local 的命名方式,或者直接填写外部 Kubernetes 的地址 https://:。
  • Jenkins URL 是k8s 访问jenkins地址。这里我填写了 http://jenkins.default / http://jenkins.ops (这里是jenkins service 地址带上了命名空间)。跟上边类似,也是使用 Jenkins Service 对应的 DNS 记录,不过要指定为 8080 端口,因为我们设置暴漏 8080 端口。同时也可以用 http://:<Node_Port> 方式,例如我这里可以填 http://192.168.99.100:30645 也是没有问题的,这里的 30645 就是对外暴漏的 NodePort。
    注意 命名空间
  • Kubernetes 命名空间 可不写

测试并验证

通过 Kubernetes 安装 Jenkins Master 完毕并且已经配置好了连接,接下来,我们可以配置 Job 测试一下是否会根据配置的 Label 动态创建一个运行在 Docker Container 中的 Jenkins Slave 并注册到 Master 上,而且运行完 Job 后,Slave 会被注销并且 Docker Container 也会自动删除吧!

创建一个 Pipeline 类型 Job 并命名为 my-k8s-jenkins-pipeline,然后在 Pipeline 脚本处填写一个简单的测试脚本如下:

def label = "mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, cloud: 'kubernetes')
{
    node(label) {
        stage('Run shell') {
            sh 'sleep 30s'
            sh 'echo hello world.'
        }
    }
}

node(label ) 中的 label :匹配 node 配置 为 label的节点。

podTemplate(label) 中的 label: 定义 节点 node 运行 podTemplate 的 label ,也就是 节点node的 label

可以看出 podTemplate 和node 配置并没有相关,只需要label 相关联

创建 kubernetes pod tempalte

请添加图片描述

请添加图片描述
请添加图片描述

运行docker命令

在Kubernetes集群内部,Kubernetes映射/var/run/docker.sock(因此我们共享相同的Docker sock)。 将jenkins用户添加到默认docker用户组下, 从而保证jenkins可以直接访问/var/run/docker.sock

usermod -a -G docker jenkins

配置 kubernetes凭证

参考k8s 带你一步步 创建用户账号(User Account), 最终生成一个用户账号 和一个kube配置文件

#请添加图片描述请添加图片描述

测试Pipeline

podTemplate (inheritFrom: "maven-kubectl"){
    node(POD_LABEL) {
            stage('Run shell') {
                sh 'echo hello world'
                sh 'kubectl config view'
                sh 'docker version'
            }
            
            stage('k8s') { 
                
                kubeconfig(credentialsId: '586b9f76-15d3-4d35-8c76-28e02b144ce9') {
                    sh 'kubectl config view'
                    sh "kubectl get pod -n prod"
                }
        }
    }
}

采用配置文件的方式就不用写 serverUrl 了。因为配置文件就包含serverUrl

构建SpringBoot脚本

  • 1.先在k8s里创建 deployment。yml如下
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ces-purchase
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pod-purchase
  template:
    metadata:
      labels:
        app: pod-purchase
    spec:
      affinity:
        # 反亲和性调度 使各个pod不在同个node里
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                topologyKey: kubernetes.io/hostname
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - pod-purchase
      imagePullSecrets:
        - name: harborregcred
      containers:
        - name: pod-ces-purchase
          image: docker.aliuncle.top:8000/ces/ces-purchase-impl:1.1-SNAPSHOT
          imagePullPolicy: Always
          resources:
            limits:
              memory: 2G
            requests:
              memory: 2G
          lifecycle:
            postStart:
              exec:
                command:
                  - sleep
                  - 30s
            preStop:
              exec:
                command:
                  - sh
                  - '-c'
                  - >-
                    curl -X "POST"
                    "http://localhost:8080/actuator/serviceregistry?status=DOWN"
                    -H "Content-Type:
                    application/vnd.spring-boot.actuator.v2+json;charset=UTF-8"
                  - sleep 30s
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 60
            timeoutSeconds: 10
            periodSeconds: 120
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 10
            timeoutSeconds: 10
            periodSeconds: 120
          env:
            - name: SW_AGENT_NAME
              value: ces-purchase
            - name: SW_AGENT_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
              valueFrom:
                configMapKeyRef:
                  name: skywalking-cm
                  key: skywalking.collector.backend_service

  • 2.jenkins 只负责拉代码,打包,调用k8s更新方法
def k8s_deployment = project_name
//def run_env = "pre"
def app_name = project_name
//项目git 地址
def git_address = "http://git.***.com/ces/ces-application/${project_name}.git"
//项目git 分支地址
def git_branch = "prod"
//git 证书ID
def git_auth = "andnayang-git"  

def docker_path = run_env == "pre" ? "ces_pre":"ces"
//打包镜像名称
def docker_image_name = "docker.**.top:8000/${docker_path}/${app_name}-impl"
//打包镜像tag
def docker_image_tag = BUILD_NUMBER
//docker registry 地址
def docker_registry = "docker.***.top:8000" 
def docker_registry_auth = "a83fa85e-5753-484b-9076-79baa2d6d437"   

def docker_host = "tcp://192.168.0.192:2375"
def APM_OPT = '${APM_OPT}'

podTemplate (inheritFrom: "maven-kubectl"){
  node(POD_LABEL){
      // 第一步
      stage('拉取代码'){
         git branch: "${git_branch}", credentialsId: "${git_auth}", url: "${git_address}"
      }
      // 第二步
      stage('代码编译'){
          sh "mvn clean package -Dmaven.test.skip=true -P${run_env}"
      }
      // 第三步
      stage('构建镜像'){
          //Harbor镜像仓库登录验证,
          withCredentials([usernamePassword(credentialsId: "${docker_registry_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
            sh """
              echo '
                FROM docker.***.top:8000/common/jdk8

                MAINTAINER ***@qq.com
                
                ENTRYPOINT /usr/bin/java -Djava.security.egd=file:/dev/./urandom -javaagent:/root/agent/skywalking-agent.jar ${APM_OPT} -jar app.jar
                
                COPY ${app_name}-impl/target/${app_name}-impl.jar app.jar
              ' > Dockerfile
              export DOCKER_HOST="${docker_host}"
              docker login -u ${username} -p ${password} ${docker_registry}
              docker build -t ${docker_image_name}:${docker_image_tag} .
              docker push ${docker_image_name}:${docker_image_tag}
            """
            }
      }
      // 第四步
  
    stage('部署到K8S平台'){
        kubeconfig(credentialsId: '586b9f76-15d3-4d35-8c76-28e02b144ce9') {
                    // sh "kubectl rollout restart -n ${run_env} deployment ${k8s_deployment}"
                     sh "kubectl set image deployments/${app_name} pod-${app_name}=${docker_image_name}:${docker_image_tag} -n ${run_env}"
        }
             
            //sh 'kubectl config view'
            //sh "kubectl set image deployments/hello-k8s pod-hello-k8s=andanyoung/springboot-hello:${docker_image_tag} -n pre"
    }
        
  }
}

上游jenkins 并发构建

  • 配置

请添加图片描述
请添加图片描述

  • pipeline
pipeline {
     agent any 
     stages {
         stage('deploy stage') {
             steps {
                 script{
                    //把选择的项目信息转为数组
                    def selectedProjects = "${project_name}".split(',')
                    for (job in selectedProjects){
                        echo "${job} 正在构建发布"
                        build wait: false, propagate: false, job: 'ces-application', parameters: [string(name: 'project_name', value: "${job}"), string(name: 'run_env', value: 'prod')]
                       // build wait: false, propagate: false,  job: "${job}"
                        // 传入gitParameter参数  $mbranch为本次pipeline流水线执行时传入的参数,然后将参数值 传入给每个执行构建任务中
                        echo "${job} 完成构建发布."
                    }
                 }
             }
         }
     }
}

  • 效果
    请添加图片描述

参考

  • http://idcsec.com/2019/03/27/%E7%94%A8jenkins%E5%8A%A8%E6%80%81%E4%BC%B8%E7%BC%A9%E5%92%8Ckubernetes%E4%B8%BA%E5%BA%94%E7%94%A8%E8%AE%BE%E7%BD%AEci-cd-%E6%B5%81%E7%A8%8B/
  • https://www.coder4.com/homs_online/ch06-cd/jenkins-k8s-optimize.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值