pipeline { agent any parameters { choice(name: 'env', choices: ['dev', 'test', 'prod'], description: '部署环境(dev/test/prod)') string(name: 'NAMESPACE', defaultValue: 'portal', description: 'Kubernetes 命名空间') string(name: 'DOMAIN', defaultValue: '', description: 'Ingress 域名(留空则不创建 Ingress)') } environment { PROJECT_NAME = 'portal-service' MODULE_NAME = 'portal-service-server' MAVEN_HOME = '/usr/local/apache-maven-3.9.9' HARBOR_HOST = '8.130.28.21:81' KUBECONFIG_PATH = '/root/.kube/config' NODE1_IP = '172.27.73.147' NODE2_IP = '172.27.73.146' HARBOR_USER = 'admin' HARBOR_PASSWORD = 'Hfln@1024' SPRING_PROFILES_ACTIVE = "${params.env}" } stages { stage('🧬 拉取 Git 代码') { steps { script { echo ">>> 正在拉取 Git 代码..." checkout scm echo ">>> 拉取完成 ✅" } } } stage('📦 Maven 构建项目') { steps { script { echo ">>> 开始构建模块 ${MODULE_NAME}" sh "${MAVEN_HOME}/bin/mvn clean package -DskipTests -pl ${MODULE_NAME} -am" echo ">>> 构建完成 ✅" } } } stage('🐳 构建并推送 Docker 镜像') { steps { script { def imageTag = "${HARBOR_HOST}/${params.env}/${PROJECT_NAME}:${BUILD_NUMBER}" echo ">>> 构建 Docker 镜像: ${imageTag}" sh """ docker login -u ${HARBOR_USER} -p ${HARBOR_PASSWORD} ${HARBOR_HOST} docker build --build-arg env=${params.env} -t ${imageTag} . docker push ${imageTag} docker rmi ${imageTag} """ echo ">>> 镜像推送完成 ✅" } } } stage('🔍 测试节点能否拉取镜像') { steps { script { def imageTag = "${HARBOR_HOST}/${params.env}/${PROJECT_NAME}:${BUILD_NUMBER}" echo ">>> 测试节点能否拉取镜像..." sh """ ssh root@${NODE1_IP} docker login -u ${HARBOR_USER} -p ${HARBOR_PASSWORD} ${HARBOR_HOST} && docker pull ${imageTag} || echo '[❌ 节点 node1 拉取失败]' ssh root@${NODE2_IP} docker login -u ${HARBOR_USER} -p ${HARBOR_PASSWORD} ${HARBOR_HOST} && docker pull ${imageTag} || echo '[❌ 节点 node2 拉取失败]' """ } } } stage('🚀 部署到 Kubernetes') { steps { script { def imageTag = "${HARBOR_HOST}/${params.env}/${PROJECT_NAME}:${BUILD_NUMBER}" def domain = params.DOMAIN.trim() def ingressBlock = domain ? """ --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ${PROJECT_NAME} annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: ${domain} http: paths: - path: / pathType: Prefix backend: service: name: ${PROJECT_NAME} port: number: 80 """ : "" echo ">>> 开始部署至 Kubernetes 命名空间:${params.NAMESPACE}" sh """ export KUBECONFIG=${KUBECONFIG_PATH} kubectl get ns ${params.NAMESPACE} || kubectl create ns ${params.NAMESPACE} kubectl apply -n ${params.NAMESPACE} -f - <>> ✅ 部署完成,访问地址:http://${domain}/" } else { echo ">>> ✅ 部署完成,访问地址:http://${NODE1_IP}:30085/" } } } } } post { success { echo "✅ 构建 & 部署成功 🎉" script { echo "🧹 清理本地旧镜像(保留最近 3 个)" sh """ docker images --format '{{.Repository}}:{{.Tag}} {{.CreatedAt}}' | \ grep '${HARBOR_HOST}/${params.env}/${PROJECT_NAME}:' | \ sort -rk2 | \ tail -n +4 | \ awk '{print \$1}' | \ xargs -r docker rmi || true """ } } failure { echo "❌ 构建或部署失败,请检查日志。" } always { echo "🧼 清理 Jenkins 工作目录..." cleanWs() } } }