为了持续构建、持续集成交付,提高研发效率和加速产出成功交付,使用kubesphere配置devops流水线,以实现自动化构建和部署。

一、开启kubesphere的devops配置

参考:https://kubesphere.io/zh/docs/v3.4/pluggable-components/devops/
启动后系统组件中devops状态:
image.png

二、创建企业空间-创建devops项目

如果devops项目一直处于等待状态,查看devops jenkins相关容器日志。
如果报错:ldap认证错误
可能是因为修改了密码,没有同步到jenkins。修改admin密码后,使用新密码登录jenkins,http://ip:30180/
然后重启devops
kubectl -n kubesphere-devops-system rollout restart deploy devops-apiserver

三、配置准备

配置凭证

包括:kubeconfig、dockerhub镜像仓库、git密钥
image.png

配置maven settings.xml

在配置字典中找到ks-devops-agent,修改MavenSetting的值。

四、项目准备

测试项目主要包括两个子项目,file-system和user项目。提交到代码仓库。

需要准备Dockerfile用于docker镜像构建。

FROM --platform=linux/amd64 openjdk:8u102-jdk
VOLUME /tmp
COPY file-system/target/istio-demo-file-system.jar app.jar
RUN mkdir /logs
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]

准备deploy.yaml用于将构建产物部署到k8s平台。

这个文件可以从kubesphere工作负载-对应项目的yaml拷贝,
修改image的值:

'${REGISTRY}/${APP_NAME}:${BUILD_NUMBER}'

修改后在执行时可能会遇到报错:
ERROR: ERROR: Cannot create property=spec for JavaBean=class V1Deployment {
这里可能是yaml配置文件有部分标签或值无法正常识别,这时可以使用idea的kubernetes插件,将yaml中灰色或者报错的地方修改或移除。

修改后的配置文件如下:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: istio-demo-file-system-v1
  namespace: istio-demo
  labels:
    app: istio-demo-file-system
    app.kubernetes.io/name: istio-demo
    app.kubernetes.io/version: v1
    version: v1
  annotations:
    deployment.kubernetes.io/revision: '41'
    kubesphere.io/creator: admin
    servicemesh.kubesphere.io/enabled: 'true'
spec:
  replicas: 1
  selector:
    matchLabels:
      app: istio-demo-file-system
      app.kubernetes.io/name: istio-demo
      app.kubernetes.io/version: v1
      version: v1
  template:
    metadata:
      labels:
        app: istio-demo-file-system
        app.kubernetes.io/name: istio-demo
        app.kubernetes.io/version: v1
        version: v1
      annotations:
        kubesphere.io/creator: admin
        kubesphere.io/imagepullsecrets: '{"container-qyf8w3":"dockerhub-iflydocs"}'
        kubesphere.io/restartedAt: '2023-08-08T01:37:15.205Z'
        logging.kubesphere.io/logsidecar-config: '{}'
        sidecar.istio.io/inject: 'true'
    spec:
      volumes:
        - name: host-time
          hostPath:
            path: /etc/localtime
            type: ''
        - name: volume-81qw4i
          configMap:
            name: istio-demo-config
            defaultMode: 420
      containers:
        - name: container-qyf8w3
          image: '${REGISTRY}/${APP_NAME}:${BUILD_NUMBER}'
          ports:
            - name: http-8081
              containerPort: 8081
              protocol: TCP
          resources: {}
          volumeMounts:
            - name: host-time
              readOnly: true
              mountPath: /etc/localtime
            - name: volume-81qw4i
              readOnly: true
              mountPath: /etc/config/map
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      serviceAccountName: default
      serviceAccount: default
      securityContext: {}
      imagePullSecrets:
        - name: dockerhub-iflydocs
      schedulerName: default-scheduler
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

pom.xml中配置maven私有仓库地址

    <repositories>
        <repository>
            <id>central</id>
            <url>https://maven.xx.com/repository/xx-group/</url>
        </repository>
    </repositories>

项目结构:

image.png

五、创建流水线

创建流水线

编辑jenkinsfile文件

pipeline {
  agent {
    node {
      label 'maven'
    }

  }
  stages {
    stage('Clone repository') {
      agent none
      steps {
        git(url: 'https://xx/istio-demo.git', credentialsId: 'git-devops', branch: 'build', changelog: true, poll: false)
      }
    }

    stage('mvn package') {
      agent none
      steps {
        container('maven') {
          sh 'mvn -f file-system/pom.xml clean package -DskipTests'
        }

      }
    }

    stage('docker build') {
      parallel {
        stage('build file-system') {
          agent none
          steps {
            container('maven') {
              sh '/usr/bin/docker build -t $APP_NAME -f $APP_NAME/Dockerfile .'
            }

          }
        }

      }
    }

    stage('docker push') {
      parallel {
        stage('push file-system') {
          agent none
          steps {
            container('maven') {
              withCredentials([usernamePassword(credentialsId : 'dockerhub-docs' ,passwordVariable : 'HUB_PWD' ,usernameVariable : 'HUB_USER' ,)]) {
                sh 'echo "$HUB_PWD"| docker login $REGISTRY -u "$HUB_USER" --password-stdin'
                sh 'docker tag $APP_NAME:latest $REGISTRY/$APP_NAME:$BUILD_NUMBER'
                sh 'docker push $REGISTRY/$APP_NAME:$BUILD_NUMBER'
                sh 'printenv'
              }

            }

          }
        }

      }
    }
    stage('deploy ') {
             steps {
                 container ('maven') {
                      withCredentials([
                          kubeconfigFile(
                          credentialsId: env.KUBECONFIG_CREDENTIAL_ID,
                          variable: 'KUBECONFIG')
                          ]) {
                          sh 'envsubst < file-system/deploy.yaml | kubectl apply -f -'
                      }
                 }
             }
        }

  }
  environment {
    REGISTRY = 'docker.xx.com'
    DOCKERHUB_USERNAME = 'admin'
    APP_NAME = 'file-system'
    DOCKERHUB_CREDENTIAL = credentials('dockerhub-docs')
    KUBECONFIG_CREDENTIAL_ID = 'kubeconfig-test'
    PROJECT_NAME = 'istem-demo'
  }
}

主要流程节点:

克隆代码、打包生成jar、构建docker镜像、上传到镜像仓库、将应用部署到k8s集群。
image.png

六、构建、部署

运行流水线:

image.png

构建产物:

image.png

部署验证:

查看对应部署项目容器是否更新,镜像版本是否更新。

以上内容在kubesphere 3.3.2中验证。