如何使用ServiceAccount令牌部署Jenkins构建并推送至Nexus的Docker镜像?
完善Jenkinsfile的Kubernetes部署阶段(ServiceAccount令牌认证)
一、先在Kubernetes集群准备部署用的ServiceAccount
- 创建ServiceAccount及权限绑定yaml文件(命名为
jenkins-deploy-sa.yaml):
apiVersion: v1 kind: ServiceAccount metadata: name: jenkins-deployer namespace: default # 根据实际部署命名空间修改 --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: jenkins-deployer-binding subjects: - kind: ServiceAccount name: jenkins-deployer namespace: default roleRef: kind: ClusterRole name: edit # 生产环境建议自定义最小权限Role,避免过度授权 apiGroup: rbac.authorization.k8s.io
- 应用yaml并提取ServiceAccount令牌:
kubectl apply -f jenkins-deploy-sa.yaml # 获取关联的Secret名称 SECRET_NAME=$(kubectl get sa jenkins-deployer -n default -o jsonpath='{.secrets[0].name}') # 解码得到令牌明文 kubectl get secret $SECRET_NAME -n default -o jsonpath='{.data.token}' | base64 -d
二、Jenkins端配置凭据
- 登录Jenkins,进入「凭据」→「系统」→「全局凭据」,点击「添加凭据」
- 选择「Secret text」类型,把上面得到的令牌粘贴到「Secret」字段,设置凭据ID为
k8s-deployer-token(可自定义,后续Jenkinsfile需对应),添加描述后保存
三、修正Jenkinsfile的相关配置
1. 补充环境变量
在environment块中添加K8s和Docker仓库相关变量:
environment { // 原有变量保留 NEXUS_VERSION = "nexus3" NEXUS_PROTOCOL = "http" NEXUS_URL = "you-ip-addr-here:8081" NEXUS_REPOSITORY = "maven-nexus-repo" NEXUS_CREDENTIAL_ID = "nexus-user-credentials" // 新增变量 NEXUS_DOCKER_REPOSITORY = "docker-hosted-repo" // Nexus中创建的Docker宿主仓库名称 K8S_CLUSTER_SERVER = "https://your-k8s-api-server:6443" // K8s API地址 K8S_NAMESPACE = "default" // 部署目标命名空间 }
2. 完善「Build Image」阶段的镜像标签
修改docker build命令,加上Nexus仓库前缀和版本标签,确保后续能推送到正确地址:
stage('Build Image') { steps { sh "echo 'building..'" git credentialsId: 'bitbucket-server:50001e738fa6dafbbe7e336853ced1fcbc284fb18ea8cda8b54dbfa3a7bc87b9', url: 'http://192.168.1.30:7990/scm/jen/spring-boot-microservice.git', branch: 'master' ./gradlew build // 仅构建镜像,无需运行jar包 docker build -t "${NEXUS_PROTOCOL}://${NEXUS_URL}/${NEXUS_DOCKER_REPOSITORY}/springio/gs-spring-boot-docker:${pom.version}" . } }
3. 修正「Push Image into Nexus registry」阶段
原阶段是上传Maven构件,替换为推送Docker镜像的逻辑:
stage('Push Image into Nexus registry') { steps { script { pom = readMavenPom file: "pom.xml"; // 登录Nexus Docker仓库并推送镜像 docker.withRegistry("${NEXUS_PROTOCOL}://${NEXUS_URL}", NEXUS_CREDENTIAL_ID) { docker.image("${NEXUS_PROTOCOL}://${NEXUS_URL}/${NEXUS_DOCKER_REPOSITORY}/springio/gs-spring-boot-docker:${pom.version}").push() } } } }
4. 完善「Deploy Image from Nexus registry into Kubernetes」阶段
使用ServiceAccount令牌配置kubectl上下文,完成镜像部署:
stage('Deploy Image from Nexus registry into Kubernetes') { steps { script { pom = readMavenPom file: "pom.xml"; // 从Jenkins凭据获取K8s令牌 withCredentials([string(credentialsId: 'k8s-deployer-token', variable: 'K8S_TOKEN')]) { // 配置kubectl上下文 sh """ kubectl config set-cluster k8s-cluster --server=${K8S_CLUSTER_SERVER} --insecure-skip-tls-verify=true kubectl config set-credentials jenkins-deployer --token=${K8S_TOKEN} kubectl config set-context k8s-context --cluster=k8s-cluster --user=jenkins-deployer --namespace=${K8S_NAMESPACE} kubectl config use-context k8s-context """ // 示例:创建Deployment(也可使用提前下载的Helm Chart部署) sh """ cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: spring-boot-app namespace: ${K8S_NAMESPACE} spec: replicas: 1 selector: matchLabels: app: spring-boot-app template: metadata: labels: app: spring-boot-app spec: containers: - name: app-container image: ${NEXUS_PROTOCOL}://${NEXUS_URL}/${NEXUS_DOCKER_REPOSITORY}/springio/gs-spring-boot-docker:${pom.version} ports: - containerPort: 8080 imagePullSecrets: - name: nexus-docker-secret # K8s中拉取Nexus私有镜像的Secret,需提前创建 EOF """ // 可选:创建Service暴露应用(可复用下载的Helm Chart中的配置) sh "kubectl apply -f ./helm/service.yaml" } } } }
补充:K8s镜像拉取Secret创建
由于Nexus是私有Docker仓库,需提前在K8s中创建拉取用的Secret:
kubectl create secret docker-registry nexus-docker-secret \ --docker-server=${NEXUS_URL} \ --docker-username=nexus-user \ --docker-password=nexus-password \ --namespace=${K8S_NAMESPACE}
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

