Java容器化实践:Docker+K8s部署Spring Boot应用全流程

传统部署的“午夜惊魂”与容器化救赎

凌晨两点,刺耳的电话铃声撕裂了夜的宁静。“王工,生产环境订单服务挂了!客户无法支付!”运维小明的声音带着颤抖。我跌跌撞撞冲到电脑前,发现测试环境跑得好好的服务,在生产服务器上因JDK版本冲突轰然倒塌——这已是本月第三次环境不一致引发的故障。

当传统部署遭遇云原生时代:服务器配置的“雪花效应”(每台环境都独一无二)、依赖冲突的“俄罗斯轮盘赌”、扩缩容的“龟速响应”... 这些问题在微服务架构下被指数级放大。

而此刻,容器化技术如同普罗米修斯之火照亮了黑暗:Docker标准化应用封装,Kubernetes(K8s)提供分布式调度能力。本文将带你亲历Spring Boot应用从代码到集群的完整容器化蜕变之旅。


第一章:破茧——容器化前的认知重构

1.1 容器化核心思想:颠覆传统部署逻辑

理论基石

  • OCI标准(Open Container Initiative):容器镜像的通用规范,确保跨平台兼容性

  • 隔离性:利用Linux Namespace(进程/网络隔离)和Cgroups(资源限制)实现沙箱环境

  • 不可变基础设施:镜像构建后永不修改,任何变更需重建镜像

实战:体验容器魔法

# ===== 宿主机环境验证部分 =====
# 显示宿主机操作系统信息(应为CentOS 8)
cat /etc/os-release

# 列出当前系统进程(验证宿主机环境)
ps aux

# ===== 容器操作部分 =====
# 启动Ubuntu容器并进入交互模式
# -it: 分配交互式终端(i: interactive, t: tty)
# --rm: 容器退出后自动删除容器文件系统
# ubuntu:22.04: 使用官方Ubuntu 22.04镜像
# bash: 在容器内启动bash shell
docker run -it --rm ubuntu:22.04 bash

# ===== 容器内部操作 =====
# 显示容器内操作系统信息(应为Ubuntu 22.04)
cat /etc/os-release

# 查看容器内进程列表(仅显示容器内进程)
ps aux

# 退出容器并终止容器进程
exit

# ===== 返回宿主机验证 =====
# 再次确认宿主机操作系统(应仍为CentOS)
cat /etc/os-release

# 检查容器是否已自动删除(应无正在运行的容器)
docker ps -a
1.2 Spring Boot的容器化基因

Spring Boot 2.3+ 原生支持构建优化:

  • 分层JAR(Layered JAR):自动分离依赖/资源/应用代码                                                                                                                                                                                            

<?xml version="1.0" encoding="UTF-8"?>
<!-- 项目基础配置 -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 模型版本(固定值) -->
    <modelVersion>4.0.0</modelVersion>
    
    <!-- 父项目声明(继承Spring Boot默认配置) -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>  <!-- 要求2.3+版本支持分层特性 -->
        <relativePath/>
    </parent>

    <!-- 项目坐标 -->
    <groupId>com.example</groupId>
    <artifactId>demo-application</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <!-- 项目名称和描述 -->
    <name>demo-application</name>
    <description>Spring Boot Layered JAR Demo</description>

    <!-- 项目属性配置 -->
    <properties>
        <java.version>11</java.version>  <!-- JDK版本要求 -->
        <docker.image.prefix>myrepo</docker.image.prefix>  <!-- 镜像前缀 -->
    </properties>

    <!-- 项目依赖 -->
    <dependencies>
        <!-- Spring Boot基础starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 构建配置 -->
    <build>
        <plugins>
            <!-- Spring Boot Maven插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${project.parent.version}</version>  <!-- 继承父版本 -->
                <configuration>
                    <!-- 启用分层JAR支持 -->
                    <layers>
                        <enabled>true</enabled>  <!-- 关键配置:激活分层特性 -->
                    </layers>
                    <!-- 可选:自定义分层配置(默认使用spring-boot-layer.xml) -->
                    <!-- <layers>
                        <enabled>true</enabled>
                        <configuration>${project.basedir}/src/layers.xml</configuration>
                    </layers> -->
                </configuration>
                <executions>
                    <!-- 绑定repackage目标到package阶段 -->
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            
            <!-- 可选:Docker构建插件 -->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <configuration>
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                    <tag>${project.version}</tag>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • 健康检查端点:/actuator/health 天然适配K8s存活探针


第二章:化蝶——Docker镜像构建实战

2.1 Dockerfile深度优化策略

关键指令解析



# ===== 阶段1:构建阶段 =====
# 使用官方Maven镜像作为构建环境
# - 包含JDK17(eclipse-temurin)
# - 指定小版本号保证可重现构建
FROM maven:3.8.6-eclipse-temurin-17 AS build

# 设置工作目录(后续操作均在此目录执行)
WORKDIR /app

# 先单独复制POM文件(利用Docker缓存层)
# - 只有当pom.xml变化时才会执行后续RUN指令
COPY pom.xml .

# 下载所有依赖到本地缓存(加速后续构建)
# - -B:批处理模式,避免输出ANSI颜色代码
# - go-offline:下载主依赖(但可能仍需要在线执行插件)
RUN mvn -B dependency:go-offline

# 复制源代码(在依赖下载完成后)
# - 使用./src确保只复制src目录内容而非目录本身
COPY src ./src

# 执行打包(跳过测试)
# - -DskipTests:不执行测试用例(测试应在CI阶段完成)
# - 此时会生成分层JAR(需pom.xml配置了layers.enabled=true)
RUN mvn package -DskipTests

# ===== 阶段2:运行时阶段 =====
# 使用轻量级JRE基础镜像
# - eclipse-temurin:官方维护的OpenJDK发行版
# - 17-jre-alpine:基于Alpine Linux的JRE17镜像(约80MB)
FROM eclipse-temurin:17-jre-alpine

# 设置容器内工作目录
WORKDIR /app

# 从构建阶段复制生成的JAR文件
# - 通配符匹配避免写死文件名
# - 目标命名为app.jar简化后续命令
COPY --from=build /app/target/*.jar ./app.jar

# 解压分层JAR(需要Spring Boot 2.3+)
# - Djarmode=layertools:激活Spring Boot分层工具
# - extract:将JAR按层解压到当前目录
RUN java -Djarmode=layertools -jar app.jar extract && \
    # 删除原始JAR文件减少镜像体积
    rm app.jar

# 按依赖层级从下到上复制(优化镜像层缓存)
# 1. 依赖层(变化频率最低)
COPY --from=build /app/target/dependencies/ ./
# 2. Spring Boot加载器层
COPY --from=build /app/target/spring-boot-loader/ ./
# 3. 应用层(变化频率最高)
COPY --from=build /app/target/application/ ./

# 设置容器启动命令
# - 直接使用Spring Boot的JarLauncher启动
# - 数组形式避免shell解析
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

# ===== 可选优化 =====
# 1. 时区配置(中国时区)
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata && \
    ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && \
    echo $TZ > /etc/timezone

# 2. JVM内存限制(根据容器cgroup限制自动计算)
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"

# 3. 健康检查(Spring Boot Actuator端点)
HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget -qO- http://localhost:8080/actuator/health || exit 1

性能优化点

  1. 多阶段构建:分离构建/运行时环境,缩小镜像体积(Alpine基础镜像仅~80MB)

  2. 依赖缓存:利用dependency:go-offline避免重复下载

  3. 分层利用:Spring Boot分层解压,充分利用Docker镜像层缓存

2.2 镜像构建与仓库推送
#!/bin/bash
# ===== 镜像构建阶段 =====
# 使用Dockerfile构建镜像(当前目录需包含Dockerfile)
# -t:指定镜像标签(格式:名称:版本)
# . :表示使用当前目录作为构建上下文
# --no-cache:可选参数,强制重新构建(忽略缓存)
docker build -t order-service:1.0.0 .

# ===== 镜像验证阶段 =====
# 列出本地镜像,确认构建成功
# | grep:过滤显示目标镜像
docker images | grep order-service

# 测试运行容器(可选验证)
# -d:后台运行
# -p:端口映射(主机端口:容器端口)
# --rm:容器退出后自动删除
docker run -d -p 8080:8080 --rm --name order-service-test order-service:1.0.0

# 检查容器日志(验证启动是否成功)
docker logs -f order-service-test

# 停止测试容器(验证完成后)
docker stop order-service-test

# ===== 仓库推送阶段 =====
# 登录阿里云容器镜像服务
# --username:阿里云账号用户名
# registry.cn-hangzhou.aliyuncs.com:阿里云Registry地址
# 密码需交互式输入或通过环境变量传递
docker login --username=yourname registry.cn-hangzhou.aliyuncs.com

# 标记镜像(符合阿里云命名规范)
# 格式:registry.cn-区域.aliyuncs.com/命名空间/镜像名:版本
docker tag order-service:1.0.0 registry.cn-hangzhou.aliyuncs.com/yourns/order-service:1.0.0

# 推送镜像到远程仓库
docker push registry.cn-hangzhou.aliyuncs.com/yourns/order-service:1.0.0

# ===== 安全扫描阶段 =====
# 使用Trivy进行漏洞扫描(需提前安装或使用Docker方式运行)
# --rm:扫描完成后自动删除容器
# -v:挂载Docker守护进程套接字
# image:指定扫描目标镜像
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    aquasec/trivy image order-service:1.0.0

# ===== 高级安全扫描(带报告生成)=====
# 生成JSON格式漏洞报告
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    -v $(pwd):/report aquasec/trivy image \
    --format json --output /report/trivy-scan.json \
    order-service:1.0.0

# 生成HTML报告(需jq工具)
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
    aquasec/trivy image --format template \
    --template "@contrib/html.tpl" \
    --output trivy-scan.html \
    order-service:1.0.0

# ===== 清理阶段 =====
# 删除本地镜像(可选)
docker rmi order-service:1.0.0
docker rmi registry.cn-hangzhou.aliyuncs.com/yourns/order-service:1.0.0

# 登出镜像仓库
docker logout registry.cn-hangzhou.aliyuncs.com

第三章:腾飞——Kubernetes集群部署

3.1 Kubernetes核心对象精讲
对象作用Spring Boot映射
Pod最小调度单元(1-n容器)应用主容器+Sidecar(如日志采集)
Deployment声明式更新控制器应用副本数管理/滚动更新
Service网络抽象与负载均衡内部服务访问入口
Ingress外部HTTP(S)流量接入域名路由管理
3.2 部署清单详解(deployment.yaml)
# ====== Deployment配置 ======
apiVersion: apps/v1  # Kubernetes API版本
kind: Deployment     # 资源类型:部署控制器
metadata:
  name: order-service  # 部署名称(需符合DNS子域名规范)
  namespace: production  # 指定命名空间(默认default)
  labels:
    app.kubernetes.io/name: order-service  # 标准标签格式
    app.kubernetes.io/version: "1.0.0"
spec:
  replicas: 3  # 副本数量(高可用保障)
  revisionHistoryLimit: 5  # 保留的历史版本数(用于回滚)
  selector:    # 标签选择器(匹配Pod)
    matchLabels:
      app.kubernetes.io/name: order-service
  strategy:    # 更新策略
    type: RollingUpdate  # 滚动更新(默认策略)
    rollingUpdate:
      maxSurge: 25%      # 可临时超出replicas的Pod数量(25%*3=0.75→1个)
      maxUnavailable: 0  # 更新期间不可用Pod数(零停机保障)
  template:    # Pod模板
    metadata:
      labels:  # 必须匹配selector中的标签
        app.kubernetes.io/name: order-service
        app.kubernetes.io/version: "1.0.0"
      annotations:  # 注解(非标识性元数据)
        prometheus.io/scrape: "true"  # 允许Prometheus抓取指标
        prometheus.io/port: "8080"
    spec:
      containers:
      - name: main  # 主容器名称
        image: registry.cn-hangzhou.aliyuncs.com/yourns/order-service:1.0.0  # 镜像地址
        imagePullPolicy: IfNotPresent  # 镜像拉取策略(本地有则不再拉取)
        ports:
        - name: http  # 端口命名(Service中可引用)
          containerPort: 8080  # 容器暴露端口
          protocol: TCP
        env:  # 环境变量注入
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: JAVA_OPTS
          value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
        resources:  # 资源约束
          requests:  # 最小资源需求(调度依据)
            memory: "512Mi"
            cpu: "500m"  # 0.5个CPU核心
          limits:    # 最大资源限制(防止OOM)
            memory: "1024Mi"
            cpu: "1000m"  # 1个CPU核心
        livenessProbe:  # 存活探针(失败重启容器)
          httpGet:
            path: /actuator/health/liveness  # Spring Boot Actuator端点
            port: http
            scheme: HTTP
          initialDelaySeconds: 30  # 容器启动后30秒开始探测
          periodSeconds: 10        # 每10秒探测一次
          timeoutSeconds: 5       # 探测超时时间
          failureThreshold: 3     # 连续失败3次判定为不健康
        readinessProbe:  # 就绪探针(失败从Service摘除流量)
          httpGet:
            path: /actuator/health/readiness
            port: http
            scheme: HTTP
          initialDelaySeconds: 20  # 比liveness更早开始
          periodSeconds: 5
          successThreshold: 1     # 成功1次即标记为就绪
        volumeMounts:  # 配置文件挂载
        - name: config
          mountPath: /app/config
      volumes:  # 卷定义
      - name: config
        configMap:  # 使用ConfigMap注入配置
          name: order-service-config

# ====== Service配置 ======
apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: production
spec:
  type: ClusterIP  # 服务类型(默认ClusterIP)
  selector:  # 选择器需匹配Pod标签
    app.kubernetes.io/name: order-service
  ports:
  - name: http
    port: 80       # Service对外端口
    targetPort: http  # 指向Pod中命名的端口
    protocol: TCP

# ====== Ingress配置 ======
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: order-service
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2  # URL重写规则
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"  # 文件上传大小限制
spec:
  ingressClassName: nginx  # 指定Ingress控制器类型
  rules:
  - host: orders.example.com  # 域名配置
    http:
      paths:
      - path: /api(/|$)(.*)  # 路径匹配规则
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 80

# ====== ConfigMap配置 ======
apiVersion: v1
kind: ConfigMap
metadata:
  name: order-service-config
  namespace: production
data:  # Spring Boot外部化配置
  application-prod.yml: |
    server:
      servlet:
        context-path: /api
    spring:
      datasource:
        url: jdbc:mysql://mysql.production:3306/orders
        username: ${DB_USERNAME}
        password: ${DB_PASSWORD}
3.3 服务暴露(service.yaml + ingress.yaml)
# ====== Service配置 ======
apiVersion: v1  # Kubernetes核心API版本
kind: Service   # 资源类型:服务
metadata:
  name: order-service  # 服务名称(DNS可解析)
  namespace: production  # 所属命名空间(需与Deployment匹配)
  labels:
    app.kubernetes.io/name: order-service  # 标准标签
    app.kubernetes.io/version: "1.0.0"
spec:
  type: ClusterIP  # 服务类型(默认值,集群内访问)
  selector:  # 选择器必须匹配Pod标签
    app.kubernetes.io/name: order-service
  ports:
    - name: http  # 端口命名(支持命名路由)
      protocol: TCP  # 协议类型(支持TCP/UDP/SCTP)
      port: 80  # 服务暴露端口(集群内访问端口)
      targetPort: 8080  # 容器实际端口(需与containerPort一致)
      # 可选:nodePort: 30080  # NodePort类型时指定节点端口

# ====== Ingress配置 ======
apiVersion: networking.k8s.io/v1  # Ingress API版本
kind: Ingress  # 资源类型:Ingress
metadata:
  name: order-ingress  # Ingress名称
  namespace: production  # 必须与Service同命名空间
  annotations:  # 注解控制Ingress行为
    # 重写路径规则($1表示捕获组)
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    # 连接超时设置
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    # 请求体大小限制
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    # 启用CORS
    nginx.ingress.kubernetes.io/enable-cors: "true"
    # SSL重定向(需配合TLS使用)
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx  # 指定Ingress控制器类型
  tls:  # TLS配置(HTTPS)
  - hosts:
      - orders.yourcompany.com  # 域名需与rules匹配
    secretName: order-tls-secret  # 引用包含证书的Secret
  rules:
  - host: orders.yourcompany.com  # 对外域名
    http:
      paths:
      - path: /api/orders(/|$)(.*)  # 路径匹配规则
        pathType: Prefix  # 匹配类型(Prefix/Exact/ImplementationSpecific)
        backend:
          service:
            name: order-service  # 转发目标服务
            port: 
              number: 80  # 服务端口(非容器端口)

部署命令

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

第四章:翱翔——进阶运维与调优

# ====== 4.1 金丝雀发布配置(Flagger) ======
apiVersion: flagger.app/v1beta1  # Flagger CRD API版本
kind: Canary                     # 资源类型:金丝雀发布
metadata:
  name: order-service            # 金丝雀资源名称
  namespace: production          # 必须与目标Deployment同命名空间
spec:
  # 目标工作负载引用
  targetRef:
    apiVersion: apps/v1          # 目标资源API版本
    kind: Deployment             # 目标资源类型
    name: order-service          # 目标Deployment名称
  # 服务配置(用于生成金丝雀服务)
  service:
    port: 8080                   # 服务端口
    portName: http               # 端口命名(可选)
    # 流量路由策略(可选)
    trafficPolicy:
      loadBalancer:
        consistentHash:
          httpCookie:
            name: canary-cookie  # 基于Cookie的会话保持
  # 发布分析配置
  analysis:
    interval: 1m                 # 检查间隔
    threshold: 5                 # 失败次数阈值
    iterations: 10               # 总迭代次数(默认10)
    metrics:                     # 监控指标
    - name: request-success-rate # HTTP请求成功率
      thresholdRange:
        min: 99                 # 最低成功率99%
      interval: 1m              # 指标采集间隔
    - name: latency-p95         # 95分位延迟
      threshold: 500            # 延迟阈值500ms
      interval: 30s             # 短间隔监控延迟
    # 可选的Webhook验证(调用外部系统)
    webhooks:
      - name: load-test
        type: pre-rollout        # 发布前执行
        url: http://load-test-service:8080/
        timeout: 30s
        metadata:
          type: locust           # 压力测试工具类型
          cmd: "run -t 60s"      # 测试命令

# ====== 4.2 配置中心集成 ======
# ConfigMap定义(Spring Cloud Config)
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config               # 配置映射名称
  namespace: production          # 命名空间需匹配应用
data:                            # 配置数据
  application-prod.yaml: |       # Spring Boot配置文件名
    spring:
      datasource:
        url: jdbc:mysql://mysql-prod:3306/orders
        hikari:
          maximum-pool-size: 15
    management:
      endpoints:
        web:
          exposure:
            include: "*"        # 开放所有监控端点

# Deployment中的挂载配置
spec:
  containers:
  - name: main
    # 环境变量注入(优先于配置文件)
    env:
    - name: SPRING_CONFIG_LOCATION
      value: "file:/config/"    # 指定配置搜索路径
    # 配置文件挂载
    volumeMounts:
    - name: config-volume
      mountPath: /config         # 挂载到容器内路径
      readOnly: true
  volumes:
  - name: config-volume
    configMap:
      name: app-config          # 引用ConfigMap名称
      items:                    # 可选:筛选特定文件
      - key: application-prod.yaml
        path: application.yaml  # 重命名配置文件

# ====== 4.3 监控体系配置 ======
# Spring Boot Actuator配置(application-prod.yaml片段)
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,metrics  # 暴露的关键端点
      base-path: /actuator       # 端点基础路径
  metrics:
    export:
      prometheus:
        enabled: true           # 启用Prometheus格式输出
    tags:
      application: ${spring.application.name}  # 添加应用标签

# Prometheus ServiceMonitor(需安装Prometheus Operator)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: order-service-monitor
  namespace: monitoring         # 通常放在独立命名空间
  labels:
    release: prometheus-stack  # 匹配Prometheus选择器
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: order-service  # 匹配Service标签
  endpoints:
  - port: http                 # 监控Service的命名端口
    path: /actuator/prometheus # 指标端点路径
    interval: 15s              # 抓取间隔
    scheme: HTTP
    honorLabels: true          # 保留原有标签
  namespaceSelector:
    matchNames:
    - production               # 目标命名空间

# Grafana仪表板配置(ConfigMap方式)
apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-order-dashboard
  namespace: monitoring
  labels:
    grafana_dashboard: "1"     # 被Grafana自动加载
data:
  order-service.json: |        # 仪表板JSON文件
    {
      "title": "Order Service",
      "panels": [...],
      "__inputs": [...]
    }

实时监控JVM内存/GC次数/HTTP请求延迟等核心指标


第五章:云原生启示录

当我们回望开头的“午夜惊魂”,容器化方案已彻底解决:

  • ✅ 环境一致性:Docker镜像消除“雪花服务器”

  • ✅ 秒级扩缩容kubectl scale deploy/order-service --replicas=10

  • ✅ 零停机更新:滚动更新+就绪探针双保险

  • ✅ 故障自愈:K8s自动重启异常Pod

真实收益数据(某电商平台统计):

  • 部署频率提升:从周级到日均20+次

  • 资源利用率:物理机CPU使用率从35%→68%

  • 故障恢复:平均恢复时间(MTTR)从4小时→3分钟

“容器化不是万能药,但它是云原生时代的入场券” —— CNCF基金会CTO Chris Aniszczyk


附录:关键命令速查

场景命令
查看Pod日志kubectl logs -f pod/order-service-xxx
进入容器调试kubectl exec -it pod/xxx -- bash
滚动更新触发kubectl set image deploy/order-service main=registry...:2.0.0
HPA自动扩缩容kubectl autoscale deploy order-service --cpu-percent=80 --min=2 --max=20

思考题:验证你的容器化理解

  1. 镜像构建优化:当Spring Boot依赖未变更时,如何利用Docker缓存机制加速构建?

  2. 探针配置:某服务启动需60秒,如何设置readinessProbe避免流量过早进入?

  3. 故障模拟:如何强制触发K8s对Pod的健康检查重启?

  4. 安全加固:为什么容器应以非root用户运行?如何在Dockerfile实现?

答案提示:

  1. 分离COPY pom.xml与COPY src步骤

  2. 设置initialDelaySeconds: 70

  3. kubectl exec -it <pod> -- kill 1

  4. 使用USER指令,参考eclipse-temurin的non-root用户


此刻,你的Spring Boot应用已完成从“单体服务器难民”到“云原生公民”的蜕变。当再次接到凌晨告警电话,你从容登录K8s控制台,一键扩容、回滚、诊断——窗外晨曦微露,容器化的世界静待征服。

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司铭鸿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值