Kaynağa Gözat

修改jenkinsfile

yangliu 2 ay önce
ebeveyn
işleme
2b978437d2
1 değiştirilmiş dosya ile 83 ekleme ve 161 silme
  1. 83 161
      Jenkinsfile

+ 83 - 161
Jenkinsfile

@@ -3,21 +3,21 @@ pipeline {
 
     parameters {
         choice(name: 'env', choices: ['dev', 'test', 'prod'], description: '部署环境')
-        string(name: 'NAMESPACE', defaultValue: 'portal-frontend', description: 'K8s 命名空间')
-        booleanParam(name: 'FORCE_UPDATE_CONFIG', defaultValue: false, description: '强制更新配置(包括 Deployment 和 Ingress)')
+        string(name: 'NAMESPACE', defaultValue: 'hfln-dev', description: 'K8s 命名空间')
     }
 
     environment {
-        PROJECT_NAME    = 'portal-frontend'
-        BUILD_DIR       = 'dist'
-        NODE_ENV        = 'production'
-        HARBOR_HOST     = '8.130.28.21:81'
-        KUBECONFIG_PATH = '/root/.kube/config'
-        HARBOR_USER     = 'admin'
-        HARBOR_PASS     = 'Hfln@1024'
+        PROJECT_NAME       = 'portal-service-frontend'
+        BUILD_DIR          = 'dist'
+        NODE_ENV           = 'production'
+        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_PASS        = 'Hfln@1024'
         HARBOR_RETENTION_ID = '1'
-        DOMAIN          = 'radar-power.asia'
-        TLS_SECRET      = 'portal-tls'
+        DOMAIN             = 'radar-power.asia'
     }
 
     stages {
@@ -25,10 +25,10 @@ pipeline {
             steps {
                 script {
                     env.HARBOR_PROJECT = params.env
-                    env.IMAGE_TAG = "${HARBOR_HOST}/${env.HARBOR_PROJECT}/${PROJECT_NAME}:${BUILD_NUMBER}"
+                    env.IMAGE_TAG = "${env.HARBOR_HOST}/${env.HARBOR_PROJECT}/${env.PROJECT_NAME}:${BUILD_NUMBER}"
                     echo ">>> 环境:${params.env}, Harbor项目:${env.HARBOR_PROJECT}, K8s命名空间:${params.NAMESPACE}"
-                    echo ">>> 域名:${env.DOMAIN}, TLS Secret:${env.TLS_SECRET}"
-                    echo ">>> 强制更新配置:${params.FORCE_UPDATE_CONFIG}"
+                    echo ">>> IMAGE_TAG = ${env.IMAGE_TAG}"
+                    echo ">>> 域名:https://${env.DOMAIN}/"
                 }
             }
         }
@@ -40,196 +40,120 @@ pipeline {
             }
         }
 
-        stage('🔐 配置 Ingress 控制器') {
+        stage('🔧 构建 Docker 镜像') {
             steps {
                 script {
                     sh """
-                        export KUBECONFIG=${KUBECONFIG_PATH}
-
-                        echo ">>> 配置 Ingress 控制器为 LoadBalancer 类型..."
-                        kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"type":"LoadBalancer"}}' || echo "⚠️  修改失败,可能已经是 LoadBalancer 类型"
-
-                        echo ">>> 当前 Ingress 控制器状态:"
-                        kubectl get svc ingress-nginx-controller -n ingress-nginx
+                        docker login -u ${env.HARBOR_USER} -p ${env.HARBOR_PASS} ${env.HARBOR_HOST}
+                        docker build --build-arg ENV=${params.env} -t ${env.IMAGE_TAG} .
                     """
+                    echo "✅ 镜像构建成功:${env.IMAGE_TAG}"
                 }
             }
         }
 
-        stage('🔧 构建 Docker 镜像') {
+        stage('🚀 推送镜像到 Harbor') {
             steps {
                 script {
                     sh """
-                        docker login -u ${HARBOR_USER} -p ${HARBOR_PASS} ${HARBOR_HOST}
-                        docker build --build-arg ENV=${params.env} -t ${IMAGE_TAG} .
+                        docker push ${env.IMAGE_TAG}
+                        docker rmi ${env.IMAGE_TAG} || true
                     """
-                    echo "✅ 镜像构建成功:${IMAGE_TAG}"
+                    echo "✅ 镜像推送并本地清理完成"
                 }
             }
         }
 
-        stage('🚀 推送镜像到 Harbor') {
+        stage('🔍 测试节点能否拉取镜像') {
             steps {
                 script {
+                    echo ">>> 测试节点能否拉取镜像..."
                     sh """
-                        docker push ${IMAGE_TAG}
-                        docker rmi ${IMAGE_TAG}
+                        ssh root@${env.NODE1_IP} docker login -u ${env.HARBOR_USER} -p ${env.HARBOR_PASS} ${env.HARBOR_HOST} && docker pull ${env.IMAGE_TAG} || echo '[❌ 节点 ${env.NODE1_IP} 拉取失败]'
+                        ssh root@${env.NODE2_IP} docker login -u ${env.HARBOR_USER} -p ${env.HARBOR_PASS} ${env.HARBOR_HOST} && docker pull ${env.IMAGE_TAG} || echo '[❌ 节点 ${env.NODE2_IP} 拉取失败]'
                     """
-                    echo "✅ 镜像推送并本地清理完成"
                 }
             }
         }
 
-        stage(' Kubernetes 部署') {
+        stage('📦 部署到 Kubernetes(带 Ingress)') {
             steps {
                 script {
-                    sh """
-                        export KUBECONFIG=${KUBECONFIG_PATH}
-
-                        # 确保命名空间存在
-                        kubectl get ns ${params.NAMESPACE} >/dev/null 2>&1 || kubectl create ns ${params.NAMESPACE}
-
-                        # 如果强制更新配置或 Deployment 不存在,则重新创建
-                        if [ "${params.FORCE_UPDATE_CONFIG}" = "true" ] || ! kubectl get deployment ${PROJECT_NAME} -n ${params.NAMESPACE} >/dev/null 2>&1; then
-
-                            if [ "${params.FORCE_UPDATE_CONFIG}" = "true" ]; then
-                                echo ">>> 强制更新配置,删除现有资源..."
-                                kubectl delete deployment ${PROJECT_NAME} -n ${params.NAMESPACE} --ignore-not-found=true
-                                kubectl delete svc ${PROJECT_NAME} -n ${params.NAMESPACE} --ignore-not-found=true
-                                kubectl delete ingress ${PROJECT_NAME}-ingress -n ${params.NAMESPACE} --ignore-not-found=true
-                            fi
+                    def ingressBlock = """---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: ${env.PROJECT_NAME}
+  namespace: ${params.NAMESPACE}
+  annotations:
+    nginx.ingress.kubernetes.io/rewrite-target: /
+spec:
+  tls:
+  - hosts:
+    - ${env.DOMAIN}
+    secretName: portal-tls
+  rules:
+  - host: ${env.DOMAIN}
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: ${env.PROJECT_NAME}
+            port:
+              number: 80
+"""
 
-                            echo ">>> 创建 Deployment 和 Service..."
-                            kubectl apply -n ${params.NAMESPACE} -f - <<EOF
-apiVersion: apps/v1
+                    def deployYaml = """apiVersion: apps/v1
 kind: Deployment
 metadata:
-  name: ${PROJECT_NAME}
+  name: ${env.PROJECT_NAME}
+  namespace: ${params.NAMESPACE}
 spec:
   replicas: 2
   selector:
     matchLabels:
-      app: ${PROJECT_NAME}
+      app: ${env.PROJECT_NAME}
   template:
     metadata:
       labels:
-        app: ${PROJECT_NAME}
+        app: ${env.PROJECT_NAME}
     spec:
       containers:
-      - name: ${PROJECT_NAME}
-        image: ${IMAGE_TAG}
+      - name: ${env.PROJECT_NAME}
+        image: ${env.IMAGE_TAG}
         ports:
         - containerPort: 80
-        resources:
-          requests:
-            memory: "128Mi"
-            cpu: "100m"
-          limits:
-            memory: "256Mi"
-            cpu: "200m"
-        livenessProbe:
-          httpGet:
-            path: /
-            port: 80
-          initialDelaySeconds: 30
-          periodSeconds: 10
-        readinessProbe:
-          httpGet:
-            path: /
-            port: 80
-          initialDelaySeconds: 5
-            periodSeconds: 5
+        env:
+        - name: NODE_ENV
+          value: "${params.env}"
 ---
 apiVersion: v1
 kind: Service
 metadata:
-  name: ${PROJECT_NAME}
+  name: ${env.PROJECT_NAME}
+  namespace: ${params.NAMESPACE}
 spec:
-  type: ClusterIP
+  type: NodePort
   selector:
-    app: ${PROJECT_NAME}
+    app: ${env.PROJECT_NAME}
   ports:
   - port: 80
     targetPort: 80
-    protocol: TCP
-EOF
+    nodePort: 30088
+${ingressBlock}
+"""
 
-                            echo ">>> 创建 Ingress..."
-                            kubectl apply -n ${params.NAMESPACE} -f - <<EOF
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
-  name: ${PROJECT_NAME}-ingress
-  annotations:
-    kubernetes.io/ingress.class: nginx
-    nginx.ingress.kubernetes.io/ssl-redirect: "true"
-    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
-    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
-    nginx.ingress.kubernetes.io/ssl-passthrough: "false"
-    nginx.ingress.kubernetes.io/proxy-body-size: "8m"
-    nginx.ingress.kubernetes.io/rewrite-target: /
-    nginx.ingress.kubernetes.io/ssl-ciphers: "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384"
-    nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2 TLSv1.3"
-spec:
-  tls:
-  - hosts:
-    - ${env.DOMAIN}
-    secretName: ${env.TLS_SECRET}
-  rules:
-  - host: ${env.DOMAIN}
-    http:
-      paths:
-      - path: /
-        pathType: Prefix
-        backend:
-          service:
-            name: ${PROJECT_NAME}
-            port:
-              number: 80
-EOF
-
-                        else
-                            # 只更新镜像
-                            echo ">>> Deployment 已存在,仅更新镜像..."
-                            kubectl set image deployment/${PROJECT_NAME} ${PROJECT_NAME}=${IMAGE_TAG} -n ${params.NAMESPACE}
-                            echo "✅ 镜像更新完成"
-                        fi
-
-                        # 显示部署状态
-                        echo ">>> 部署状态:"
-                        kubectl get all -n ${params.NAMESPACE}
-                        kubectl get ingress -n ${params.NAMESPACE}
-
-                        echo "✅ 应用部署完成!"
-                        echo "�� 访问地址:https://${env.DOMAIN}"
-                        echo " 注意:请确保域名 ${env.DOMAIN} 已正确解析到集群"
-                    """
-                }
-            }
-        }
-
-        stage('🔍 部署验证') {
-            steps {
-                script {
+                    writeFile file: 'deploy.yaml', text: deployYaml
                     sh """
-                        export KUBECONFIG=${KUBECONFIG_PATH}
-
-                        echo ">>> 验证部署状态..."
-
-                        # 检查 Pod 状态
-                        kubectl get pods -n ${params.NAMESPACE} -l app=${PROJECT_NAME}
-
-                        # 检查 Service 状态
-                        kubectl get svc -n ${params.NAMESPACE} ${PROJECT_NAME}
-
-                        # 检查 Ingress 状态
-                        kubectl get ingress -n ${params.NAMESPACE} ${PROJECT_NAME}-ingress
-
-                        # 检查 TLS Secret
-                        kubectl get secret -n ${params.NAMESPACE} ${env.TLS_SECRET}
-
-                        echo "✅ 部署验证完成"
+                        export KUBECONFIG=${env.KUBECONFIG_PATH}
+                        kubectl get ns ${params.NAMESPACE} >/dev/null 2>&1 || kubectl create ns ${params.NAMESPACE}
+                        kubectl apply -f deploy.yaml
+                        kubectl rollout status deployment/${env.PROJECT_NAME} -n ${params.NAMESPACE} --timeout=120s || echo '[rollout timeout or incomplete]'
                     """
+
+                    echo ">>> ✅ 部署完成,访问地址:https://${env.DOMAIN}/ (请确保 DNS 已指向 Ingress 公网 IP 且 secret portal-tls 已创建)"
                 }
             }
         }
@@ -237,7 +161,7 @@ EOF
         stage('🧹 清理本地旧镜像(保留最新3个)') {
             steps {
                 script {
-                    def baseImage = "${HARBOR_HOST}/${env.HARBOR_PROJECT}/${PROJECT_NAME}"
+                    def baseImage = "${env.HARBOR_HOST}/${env.HARBOR_PROJECT}/${env.PROJECT_NAME}"
                     sh """
                         docker images ${baseImage} --format "{{.Repository}}:{{.Tag}}" \\
                         | grep -v latest \\
@@ -250,7 +174,7 @@ EOF
             }
         }
 
-        stage(' 清理悬空镜像 <none>') {
+        stage('🧼 清理 dangling 镜像') {
             steps {
                 script {
                     sh """
@@ -261,14 +185,13 @@ EOF
             }
         }
 
-        stage(' 触发 Harbor 镜像保留策略') {
+        stage('🔁 触发 Harbor 镜像保留策略(可选)') {
             steps {
                 script {
                     sh """
-                        curl -u ${HARBOR_USER}:${HARBOR_PASS} -X POST \\
-                        "http://${HARBOR_HOST}/api/v2.0/retentions/${HARBOR_RETENTION_ID}/executions"
+                        curl -u ${env.HARBOR_USER}:${env.HARBOR_PASS} -X POST "http://${env.HARBOR_HOST}/api/v2.0/retentions/${env.HARBOR_RETENTION_ID}/executions" || echo '[retention trigger failed]'
                     """
-                    echo "✅ Harbor 镜像保留策略已触发"
+                    echo "✅ Harbor 镜像保留策略已触发(若配置)"
                 }
             }
         }
@@ -276,8 +199,7 @@ EOF
 
     post {
         success {
-            echo "✅ 构建 & 部署成功!"
-            echo "🌐 应用可通过 https://${env.DOMAIN} 访问"
+            echo "✅ 构建 & 部署成功 🎉"
         }
         failure {
             echo "❌ 构建或部署失败,请检查日志"
@@ -286,4 +208,4 @@ EOF
             cleanWs()
         }
     }
-}
+}