我们可以在Chart.yaml中定义每个项目的chart名称(类似安装包名),如
apiVersion: v2 name: your-chart-name description: A Helm chart for Kubernetes type: application version: 1.0.0 appVersion: 1.16.0在values.yaml中定义模板文件中需要用到的变量,如
#部署Pod的副本数,即运行多少个容器 replicaCount: 1 #容器镜像配置 image: repository: registry.cn-hangzhou.aliyuncs.com/demo/demo pullPolicy: Always # Overrides the image tag whose default is the chart version. tag: "dev" #镜像仓库访问凭证 imagePullSecrets: - name: aliyun-registry-secret #覆盖启动容器名称 nameOverride: "" fullnameOverride: "" #容器的端口暴露及环境变量配置 container: port: 8000 env: [] #ServiceAccount,默认不创建 serviceAccount: # Specifies whether a service account should be created create: false # Annotations to add to the service account annotations: {} name: "" podAnnotations: {} podSecurityContext: {} # fsGroup: 2000 securityContext: {} # capabilities: # drop: # - ALL # readOnlyRootFilesystem: true # runAsNonRoot: true # runAsUser: 1000 #使用NodePort的service,默认为ClusterIp service: type: NodePort port: 8000 #外部访问Ingress配置,需要配置hosts部分 ingress: enabled: true annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" hosts: - host: demo.com paths: ["/demo"] tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local #.... 省略了其它默认参数配置这里在默认生成的基础上添加了container部分,可以在这里指定容器的端口号而不用去改模板文件(让模板文件在各个项目通用,通常不需要做更改),同时添加env的配置,可以在helm部署时往容器里传入环境变量。将Service type从默认的ClusterIp改为了NodePort。部署同类型的不同项目时,只需要根据项目情况配置Chart.yaml与values.yaml两个文件的少量配置项,templates目录下的模板文件可直接复用。
部署时需要在K8s环境中从Docker镜像仓库拉取镜像,因此需要在K8s中创建镜像仓库访问凭证(imagePullSecrets)
# 登录Docker Registry生成/root/.docker/config.json文件 sudo docker login --username=your-username registry.cn-shenzhen.aliyuncs.com # 创建namespace develop(我这里是根据项目的环境分支名称建立namespace) kubectl create namespace develop # 在namespace develop中创建一个secret kubectl create secret generic aliyun-registry-secret --from-file=.dockerconfigjson=http://www.likecs.com/root/.docker/config.json --type=kubernetes.io/dockerconfigjson --namespace=develop JenkinsfileJenkinsfile是Jenkins pipeline配置文件,遵循Groovy语法,对于Spring Boot项目的构建部署, 编写Jenkinsfile脚本文件如下,
image_tag = "default" //定一个全局变量,存储Docker镜像的tag(版本) pipeline { agent any environment { GIT_REPO = "${env.gitlabSourceRepoName}" //从Jenkins Gitlab插件中获取Git项目的名称 GIT_BRANCH = "${env.gitlabTargetBranch}" //项目的分支 GIT_TAG = sh(returnStdout: true,script: 'git describe --tags --always').trim() //commit id或tag名称 DOCKER_REGISTER_CREDS = credentials('aliyun-docker-repo-creds') //docker registry凭证 KUBE_CONFIG_LOCAL = credentials('local-k8s-kube-config') //开发测试环境的kube凭证 KUBE_CONFIG_PROD = "" //credentials('prod-k8s-kube-config') //生产环境的kube凭证 DOCKER_REGISTRY = "registry.cn-hangzhou.aliyuncs.com" //Docker仓库地址 DOCKER_NAMESPACE = "your-namespace" //命名空间 DOCKER_IMAGE = "${DOCKER_REGISTRY}/${DOCKER_NAMESPACE}/${GIT_REPO}" //Docker镜像地址 INGRESS_HOST_DEV = "dev.your-site.com" //开发环境的域名 INGRESS_HOST_TEST = "test.your-site.com" //测试环境的域名 INGRESS_HOST_PROD = "prod.your-site.com" //生产环境的域名 } parameters { string(name: 'ingress_path', defaultValue: '/your-path', description: '服务上下文路径') string(name: 'replica_count', defaultValue: '1', description: '容器副本数量') } stages { stage('Code Analyze') { agent any steps { echo "1. 代码静态检查" } } stage('Maven Build') { agent { docker { image 'maven:3-jdk-8-alpine' args '-v $HOME/.m2:/root/.m2' } } steps { echo "2. 代码编译打包" sh 'mvn clean package -Dfile.encoding=UTF-8 -DskipTests=true' } } stage('Docker Build') { agent any steps { echo "3. 构建Docker镜像" echo "镜像地址: ${DOCKER_IMAGE}" //登录Docker仓库 sh "sudo docker login -u ${DOCKER_REGISTER_CREDS_USR} -p ${DOCKER_REGISTER_CREDS_PSW} ${DOCKER_REGISTRY}" script { def profile = "dev" if (env.gitlabTargetBranch == "develop") { image_tag = "dev." + env.GIT_TAG } else if (env.gitlabTargetBranch == "pre-release") { image_tag = "test." + env.GIT_TAG profile = "test" } else if (env.gitlabTargetBranch == "master"){ // master分支则直接使用Tag image_tag = env.GIT_TAG profile = "prod" } //通过--build-arg将profile进行设置,以区分不同环境进行镜像构建 sh "docker build --build-arg profile=${profile} -t ${DOCKER_IMAGE}:${image_tag} ." sh "sudo docker push ${DOCKER_IMAGE}:${image_tag}" sh "docker rmi ${DOCKER_IMAGE}:${image_tag}" } } } stage('Helm Deploy') { agent { docker { image 'lwolf/helm-kubectl-docker' args '-u root:root' } } steps { echo "4. 部署到K8s" sh "mkdir -p /root/.kube" script { def kube_config = env.KUBE_CONFIG_LOCAL def ingress_host = env.INGRESS_HOST_DEV if (env.gitlabTargetBranch == "pre-release") { ingress_host = env.INGRESS_HOST_TEST } else if (env.gitlabTargetBranch == "master"){ ingress_host = env.INGRESS_HOST_PROD kube_config = env.KUBE_CONFIG_PROD } sh "echo ${kube_config} | base64 -d > /root/.kube/config" //根据不同环境将服务部署到不同的namespace下,这里使用分支名称 sh "helm upgrade -i --namespace=${env.gitlabTargetBranch} --set replicaCount=${params.replica_count} --set image.repository=${DOCKER_IMAGE} --set image.tag=${image_tag} --set nameOverride=${GIT_REPO} --set ingress.hosts[0].host=${ingress_host} --set ingress.hosts[0].paths={${params.ingress_path}} ${GIT_REPO} ./helm/" } } } } }Jenkinsfile定义了整个自动化构建部署的流程:
Code Analyze,可以使用SonarQube之类的静态代码分析工具完成代码检查,这里先忽略
Maven Build,启动一个Maven的Docker容器来完成项目的maven构建打包,挂载maven本地仓库目录到宿主机,避免每次都需要重新下载依赖包