springboot项目部署到K8S

bash 复制代码
java后台
创建harbor镜像拉取Secret:

kubectl create secret docker-registry harbor-regcred \
  --docker-server= \ #harbor仓库地址
  --docker-username= \  #harbor 账号
  --docker-password= \ #harbor密码
  -n production

Dockerfile
FROM *harbor地址*/library/custom-jdk:1.8.0-alpine

LABEL maintainer="Winter Lee"

# 设置时区并安装字体包
RUN apk add --no-cache tzdata fontconfig ttf-dejavu && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

# 创建目录
RUN mkdir -p \
    /home/backend/jar_28888 \
    /home/backend/etc \
    /home/logs \
    /home/app/logs && \
    # 修改目录权限
    chmod -R 777 /home/app

WORKDIR /home

# 使用 ARG 定义动态路径
ARG JAR_PATH
COPY ${JAR_PATH} /home/backend/jar_28888/admin.jar

VOLUME /app/logs
EXPOSE 28888

# 添加无头模式参数并优化JVM参数
ENTRYPOINT ["java", \
           "-Djava.awt.headless=true", \
           "-Xms512m", \
           "-Xmx2048m", \
           "-DLOG_PATH=/app/logs", \
           "-jar", \
           "/jono/backend/jar_28888/admin.jar"]




JEKINS构建镜像推送到harbor私服

pipeline {
    agent any

    parameters {
        gitParameter(
            name: 'TAG_NAME',
            type: 'PT_TAG',
            description: '选择要构建的 Git 标签',
            branch: 'test',
            tagFilter: '*',
            sortMode: 'DESCENDING',
            defaultValue: ''
        )
    }

    environment {
        HARBOR_REG   = "harbor地址"
        PROJECT_NAME = "项目名称"
        IMAGE_NAME   = "镜像名称"
        // 使用Harbor凭证(需先在Jenkins创建)
        HARBOR_CRED = credentials('de3f0156-4c04-445d-9621-2f966ba40f28')
    }

    stages {
        stage('Checkout Code') {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: "refs/tags/${params.TAG_NAME}"]],
                    extensions: [
                        [$class: 'CloneOption', depth: 0, shallow: false]
                    ],
                    userRemoteConfigs: [[
                        url: '代码仓库地址',
                        credentialsId: '代码仓库凭证',
                        refspec: '+refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*'
                    ]]
                ])
            }
        }

        stage('Maven Build') {
            steps {
                dir('.') {
                    timeout(time: 15, unit: 'MINUTES') {
                        sh 'mvn clean package -P sit'
                    }
                    sh 'ls -l target/admin.jar'
                }
            }
        }
        
        // 新增:准备镜像标签
        stage('Prepare Image Tag') {
            steps {
                script {
                    // 清理标签名(替换非法字符为横杠,转小写)
                    env.IMAGE_TAG = params.TAG_NAME.replaceAll(/[^a-zA-Z0-9\\.-]/, '-').toLowerCase()
                    echo "使用镜像标签: ${env.IMAGE_TAG}"
                }
            }
        }

        stage('Docker Build') {
            steps {
                script {
                    // 安全登录Harbor
                    sh "echo ${HARBOR_CRED_PSW} | docker login -u ${HARBOR_CRED_USR} --password-stdin ${HARBOR_REG}"
                    
                    // 使用Git标签名作为镜像标签
                    sh """
                    docker build \\
                      --build-arg JAR_PATH=target/admin.jar \\
                      -t ${HARBOR_REG}/${PROJECT_NAME}/${IMAGE_NAME}:${env.IMAGE_TAG} \\
                      -f env/sit/Dockerfile \\
                      .
                    """
                }
            }
        }

        stage('Push to Harbor') {
            steps {
                script {
                    // 推送指定标签的镜像
                    sh "docker push ${HARBOR_REG}/${PROJECT_NAME}/${IMAGE_NAME}:${env.IMAGE_TAG}"
                }
            }
        }
    }

    post {
        always {
            script {
                // 清理本地镜像
                sh "docker rmi ${HARBOR_REG}/${PROJECT_NAME}/${IMAGE_NAME}:${env.IMAGE_TAG} || true"
                sh "docker logout ${HARBOR_REG}"
            }
            cleanWs()
        }
    }
}

K8s部署 yaml文件

## admin-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin-production
  namespace: production  # 建议使用独立命名空间
  labels:
    app: admin
    env: production
spec:
  replicas: 2
  revisionHistoryLimit: 5 #进行滚动更新后,保留的历史版本数
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%       # 最大激增Pod数
      maxUnavailable: 25% # 最大不可用Pod数
  selector:
    matchLabels:
      app: admin
      env: production
  template:
    metadata:
      labels:
        app: admin
        env: production
    spec:
      securityContext:    # 安全上下文
        runAsUser: 1000
        runAsGroup: 3000
        fsGroup: 2000
      containers:
      - name: admin
        image: *代码仓库地址/项目名称*/admin:44-sit-202505231400
        ports:
        - containerPort: 28888
        volumeMounts:
        - name: etc-volume
          mountPath: /home/backend/etc
          readOnly: true  # 根据实际需求设置读写权限
        resources:        # 资源限制(根据实际需求调整)
          limits:
            cpu: "1"
            memory: 1Gi
          requests:
            cpu: "0.5"
            memory: 512Mi
        livenessProbe:    # 存活探针
          httpGet:
            path: /admin/captchaImage
            port: 28888
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:   # 就绪探针
          httpGet:
            path: /admin/captchaImage
            port: 28888
          initialDelaySeconds: 20
          periodSeconds: 5
      volumes:
      - name: etc-volume
        hostPath:
          path: /tmp/etc
          type: DirectoryOrCreate
      imagePullSecrets:   # 镜像拉取凭证(需提前创建)
      - name: harbor-regcred
      affinity:           # 调度策略
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values: ["admin"]
              topologyKey: kubernetes.io/hostname
## admin-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: admin-service
  namespace: production
spec:
  type: NodePort         # 根据实际网络架构选择
  selector:
    app: admin
    env: production
  ports:
  - protocol: TCP
    port: 28888
    targetPort: 28888
    nodePort: 31000

滚动更新: 
只有修改了 deployment 配置文件中的 template 中的属性后,才会触发更新操作

修改 nginx 版本号
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

kubectl set image deployment/admin-production *harbor地址*/*项目名称*/admin=44-sit-202505231400

或者通过 kubectl edit deployment/nginx-deployment 进行修改

查看滚动更新的过程
kubectl rollout status deploy <deployment_name>

查看部署描述,最后展示发生的事件列表也可以看到滚动更新过程
kubectl describe deploy <deployment_name>

通过 kubectl get deployments 获取部署信息,UP-TO-DATE 表示已经有多少副本达到了配置中要求的数目

通过 kubectl get rs 可以看到增加了一个新的 rs

通过 kubectl get pods 可以看到所有 pod 关联的 rs 变成了新的

回滚:
有时候你可能想回退一个Deployment,例如,当Deployment不稳定时,比如一直crash looping。

默认情况下,kubernetes会在系统中保存前两次的Deployment的rollout历史记录,以便你可以随时会退(你可以修改revision history limit来更改保存的revision数)。


案例:
更新 deployment 时参数不小心写错,如 nginx:1.9.1 写成了 nginx:1.91
kubectl set image deployment/nginx-deploy nginx=nginx:1.91

监控滚动升级状态,由于镜像名称错误,下载镜像失败,因此更新过程会卡住
kubectl rollout status deployments nginx-deploy

结束监听后,获取 rs 信息,我们可以看到新增的 rs 副本数是 2 个
kubectl get rs

通过 kubectl get pods 获取 pods 信息,我们可以看到关联到新的 rs 的 pod,状态处于 ImagePullBackOff 状态

为了修复这个问题,我们需要找到需要回退的 revision 进行回退
通过 kubectl rollout history deployment/nginx-deploy 可以获取 revison 的列表

通过 kubectl rollout history deployment/nginx-deploy --revision=2 可以查看详细信息

确认要回退的版本后,可以通过 kubectl rollout undo deployment/nginx-deploy 可以回退到上一个版本

也可以回退到指定的 revision
kubectl rollout undo deployment/nginx-deploy --to-revision=2

再次通过 kubectl get deployment 和 kubectl describe deployment 可以看到,我们的版本已经回退到对应的 revison 上了

可以通过设置 .spec.revisonHistoryLimit 来指定 deployment 保留多少 revison,如果设置为 0,则不允许 deployment 回退了。


发布新版本操作流程
1. 修改 YAML 文件
yaml
# deployment.yaml 示例片段
spec:
  template:
    spec:
      containers:
      - name: your-app
        image: local.harbor.com/sw/sw-web:NEW_TAG  # 修改为新镜像标签
        ports:
        - containerPort: 8088
2. 应用新配置
bash
# 使用 kubectl apply 更新部署
kubectl apply -f deployment.yaml -n your-namespace

# 观察滚动更新进度(实时查看Pod重建过程)
kubectl rollout status deployment/your-deployment -n your-namespace
3. 验证新版本
bash
# 查看当前Pod状态
kubectl get pods -n your-namespace -l app=your-app-label

# 检查新版本日志
kubectl logs -f <new-pod-name> -n your-namespace

# 执行健康检查(替换为你的健康检查路径)
kubectl exec <new-pod-name> -n your-namespace -- curl -I http://localhost:8088/web/
二、回滚操作流程
方法一:使用 Kubernetes 内置回滚(推荐)
bash
# 1. 查看部署历史版本
kubectl rollout history deployment/your-deployment -n your-namespace

# 输出示例
REVISION  CHANGE-CAUSE
1         Initial deployment
2         Update image to v1.2.3
3         Update image to v1.2.4  <--- 当前问题版本

# 2. 回滚到指定版本
kubectl rollout undo deployment/your-deployment --to-revision=2 -n your-namespace

# 3. 验证回滚状态
kubectl rollout status deployment/your-deployment -n your-namespace
方法二:通过旧版 YAML 文件回滚
bash
# 1. 检出旧版本YAML文件(假设使用Git管理)
git checkout v1.2.3 -- deployment.yaml

# 2. 应用旧配置
kubectl apply -f deployment.yaml -n your-namespace --force

# 3. 确认回滚完成
kubectl get pods -n your-namespace -l app=your-app-label
三、最佳实践建议
1. 版本追踪策略
bash
# 每次修改YAML文件后提交Git(带版本标签)
git add deployment.yaml
git commit -m "Update to v1.2.4"
git tag v1.2.4
git push origin master --tags
2. 增强部署可靠性
yaml
# 在YAML中添加健康检查
livenessProbe:
  httpGet:
    path: /healthz
    port: 8088
  initialDelaySeconds: 15
  periodSeconds: 20

readinessProbe:
  httpGet:
    path: /ready
    port: 8088
  initialDelaySeconds: 5
  periodSeconds: 10
3. 自动记录变更原因
bash
# 使用 kubectl 注解记录变更信息
kubectl annotate deployment/your-deployment \
  kubernetes.io/change-cause="Update to v1.2.4 for feature X" \
  -n your-namespace --overwrite
4. 多环境验证流程
bash
# 先发布到测试环境
kubectl apply -f deployment.yaml -n test-env

# 运行自动化测试
curl -X POST http://your-ci-server/run-tests

# 测试通过后发布生产
kubectl apply -f deployment.yaml -n prod-env
四、常见问题排查
1. 如果回滚失败
bash
# 查看部署详细状态
kubectl describe deployment/your-deployment -n your-namespace

# 检查事件日志
kubectl get events -n your-namespace --sort-by=.metadata.creationTimestamp
2. 保留历史版本数量控制
yaml
# 在YAML中配置 revisionHistoryLimit
spec:
  revisionHistoryLimit: 5  # 保留最近5个版本


更新版本的时候可以添加 --record记录操作内容
[root@k8s-master ~]#  kubectl set image deployment/web-production -n production web=web:v20250523_1.0.0 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/web-production image updated
[root@k8s-master ~]# kubectl rollout history deployment/web-production -n production
deployment.apps/web-production 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment/web-production web=web:v20250523_1.0.0 --namespace=production --record=true

查看对应revision的更新内容
kubectl rollout history deployment/web-production -n production --revision=2
deployment.apps/web-production with revision #2
Pod Template:
  Labels:       app=web
        env=production
        pod-template-hash=764cdbc6c4
  Annotations:  kubernetes.io/change-cause: kubectl set image deployment/web-production web=web:v20250523_1.0.0 --namespace=production --record=true
  Containers:
   web:
    Image:      web:v20250523_1.0.0
    Port:       8088/TCP
    Host Port:  0/TCP
    Limits:
      cpu:      200m
      memory:   1Gi
    Requests:
      cpu:      100m
      memory:   512Mi
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

版本回退操作 
回退到revision 为1的版本
[root@k8s-master ~]# kubectl rollout undo deployment/web-production -n production --to-revision=1
deployment.apps/web-production rolled back
[root@k8s-master ~]# kubectl rollout history deployment/web-production -n production
deployment.apps/web-production 
REVISION  CHANGE-CAUSE
2         kubectl set image deployment/web-production web=web:v20250523_1.0.0 --namespace=production --record=true
3         <none>
查看回滚进度
kubectl rollout status deployment/web-production -n production

扩容缩容
kubectl scale --replicas=5 deployment web-production -n production  通过修改replicas的值完成扩容和缩容 


暂停和恢复
kubectl rollout pause deploy web-production -n production
kubectl rollout resume deploy web-production -n production
相关推荐
bahdkdsq29 分钟前
Docker——Redis
运维·docker·容器
一一Null32 分钟前
Linux-网络管理
linux·运维·服务器
yourkin66634 分钟前
为什么要使用nginx?
运维·nginx
GUET_一路向前3 小时前
【git】在Linux系统下clone指定分支
linux·运维·git
云和数据.ChenGuang3 小时前
运维技术教程之Jenkins上的known_hosts文件
运维·servlet·jenkins·自动化监控·运维技术教程
云心雨禅3 小时前
Ubuntu GRUB菜单密码重置教程
linux·运维·ubuntu
Lum11044 小时前
MER-Factory:多模态情感识别与推理数据集自动化工厂API参考
运维·自动化
Bella的成长园地5 小时前
linux 系统依赖包查询命令汇总
linux·运维·服务器
hweiyu006 小时前
Linux 命令:uname
linux·运维·服务器
Lum11047 小时前
MER-Factory:多模态情感识别与推理数据集自动化工厂工具介绍
运维·人工智能·深度学习·计算机视觉·语言模型·自然语言处理·自动化