基于kubernets的CI/CD

背景

组件:Kubernetes,Gitlab,Jenkins
最近基于Flask开发了小型web后端。通过CI/CD进行发布部署,记录下整个CI/CD流程。

流程

Gitlab和Jenkins项目关联

设置项目

构建Dockerfile

提前构建好Docker镜像, 包含环境需要的依赖。

FROM 172.30.140.21/xxx/security:1.0  #从本地Harbor仓库获取自己构建的基础镜像
WORKDIR /opt/flask-security
COPY . .
CMD [ "sh", "-c", "uwsgi --ini uwsgi/uwsgi.ini && tail -f uwsgi/uwsgi.log" ]

Jenkinsfile

# 此Jenkinsfile文件在被Jenkins拉取项目源码后执行
def label = "slave-${UUID.randomUUID().toString()}"

// 调用的基础镜像
podTemplate(label: label, containers: [
  containerTemplate(name: ‘kubectl‘, image: ‘172.30.140.21/xxx/kubectl:v1.15.3‘, command: ‘cat‘, ttyEnabled: true),
  containerTemplate(name: ‘docker‘, image: ‘172.30.140.21/xxx/docker-cli:19.03.8‘, command: ‘cat‘, ttyEnabled: true),
  containerTemplate(name: ‘python-env‘, image: ‘172.30.140.21//security:1.0‘, command: ‘cat‘, ttyEnabled: true),
  containerTemplate(name: ‘jnlp‘, image: ‘172.30.140.21/xxx/jnlp-slave:4.0.1-1‘, alwaysPullImage: false, privileged: true, args: ‘${computer.jnlpmac} ${computer.name}‘)
], serviceAccount: ‘jenkins‘, volumes: [
  hostPathVolume(mountPath: ‘/home/jenkins/.kube‘, hostPath: ‘/root/.kube‘),
  hostPathVolume(mountPath: ‘/var/run/docker.sock‘, hostPath: ‘/var/run/docker.sock‘)
]) {
  node(label) {
    def myRepo = checkout scm
    def gitCommit = myRepo.GIT_COMMIT
    def gitBranch = myRepo.GIT_BRANCH
    def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
    def imageUri = "172.30.140.21"
    def imageHub = "xxx"
    def imageApp = "flask-security"
    def image = "${imageUri}/${imageHub}/${imageApp}"

    stage(‘单元测试‘) {
      echo "Part1.单元测试-test"
    }
    stage(‘代码编译打包‘) {
      try {
        container(‘python-env‘) {
            echo "Part2.代码编译打包"
        }
      } catch (exc) {
        println "构建失败 - ${currentBuild.fullDisplayName}"
        throw(exc)
      }
    }
    stage(‘构建Docker镜像‘) {
      withCredentials([usernamePassword(credentialsId: ‘xxx-habor‘, passwordVariable: ‘DOCKER_HUB_PASSWORD‘, usernameVariable: ‘DOCKER_HUB_USER‘)]) {
        container(‘docker‘) {
          echo "Part3.构建Docker镜像"
          sh """
            docker login ${imageUri} -u ${DOCKER_HUB_USER} -p ${DOCKER_HUB_PASSWORD}
            docker build -t ${image}:${imageTag} .
            docker push ${image}:${imageTag}
            """
        }
      }
    }
    stage(‘修改部署文件‘) {
      echo "Part4.修改YAML文件参数"
      def ciEnv = "dev"
      if (gitBranch == "origin/master") {
        ciEnv = "prod"
      }
      sh "sed -i ‘s/<IMAGE_URI>/${imageUri}/g‘ manifests/flask-security.yaml"
      sh "sed -i ‘s/<IMAGE_HUB>/${imageHub}/g‘ manifests/flask-security.yaml"
      sh "sed -i ‘s/<IMAGE_APP>/${imageApp}/g‘ manifests/flask-security.yaml"
      sh "sed -i ‘s/<BUILD_TAG>/${imageTag}/g‘ manifests/flask-security.yaml"
      sh "sed -i ‘s/<BRANCH_NAME>/${ciEnv}/g‘ manifests/flask-security.yaml"
    }
    stage(‘推送Kubernetes‘) {
      container(‘kubectl‘) {
       echo "Part5.部署应用到 K8S"
       sh "kubectl apply -f manifests/flask-security.yaml"
       sh "kubectl apply -f manifests/flask-security-service.yaml"
       sh "kubectl apply -f manifests/flask-security-ingress.yaml"
       sh "kubectl rollout status -f manifests/flask-security.yaml"
       echo "6.部署成功"
      }
    }
  }
}

配置Kubernetes运行的manifests文件

  1. flask-security.yml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-security-<BRANCH_NAME>
  namespace: elk-portal
  labels:
    app: flask-security
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask-security
  template:
    metadata:
      labels:
        app: flask-security
    spec:
      containers:
      - name: flask-security
        image: <IMAGE_URI>/<IMAGE_HUB>/<IMAGE_APP>:<BUILD_TAG>
        imagePullPolicy: Always
        ports:
        - containerPort: 80
  1. flask-security-service.yml
kind: Service
apiVersion: v1
metadata:
  namespace: elk-portal
  name: flask-security-service
spec:
  selector:
    app: flask-security
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

基于kubernets的CI/CD

上一篇:php伪随机数漏洞 以及脚本php_mt_seed的使用教程


下一篇:接口自动化测试 之 request、 的 json 和 data传参的 区别