第1篇:K8s 核心概念精讲:Pod、Deployment、Service 与 Namespace——Java 开发者快速上手指南

本文适合:有 Java 开发经验、Docker 基础、想系统入门 K8s 的工程师


前言:为什么 Java 开发者必须学 Kubernetes?

如果你曾经被以下问题困扰过,那这篇文章就是为你写的:

  • 上线新版本时要停服维护,用户投诉不断
  • 大促期间服务器撑不住,手动扩容永远比流量来得慢
  • 十几个微服务各有各的配置,部署一次耗费半天
  • 某个实例挂了,凌晨三点被告警短信吵醒

Kubernetes(简称 K8s)正是为解决这些问题而生的。它是 Google 内部运行十几年的 Borg 系统的开源版本,如今已成为云原生时代事实上的容器编排标准

对于 Java SaaS 开发者而言,K8s 不只是"运维的事"------它深刻影响着你的应用如何打包、如何暴露接口、如何感知配置变化。更重要的是,随着 AI 大模型推理服务越来越多地以容器形式交付,K8s 成了连接 Java 业务层与 AI 能力层的核心底座。

本文是系列的开篇,我们会用大量类比和图示 ,把 K8s 中最核心的四个概念------PodDeploymentServiceNamespace------讲透讲明白,并全程结合 Java SaaS 场景。


一、K8s 整体架构速览

在深入具体对象之前,先建立一张"地图"。

bash 复制代码
┌─────────────────────────────────────────────────────┐
│                   Kubernetes 集群                    │
│                                                     │
│  ┌──────────────────────┐  ┌─────────────────────┐  │
│  │   Control Plane      │  │   Worker Nodes      │  │
│  │  ┌────────────────┐  │  │  ┌───────────────┐  │  │
│  │  │  API Server    │  │  │  │  kubelet      │  │  │
│  │  ├────────────────┤  │  │  ├───────────────┤  │  │
│  │  │  Scheduler     │  │  │  │  kube-proxy   │  │  │
│  │  ├────────────────┤  │  │  ├───────────────┤  │  │
│  │  │  etcd          │  │  │  │  容器运行时     │  │  │
│  │  ├────────────────┤  │  │  │  (containerd) │  │  │
│  │  │  Controller    │  │  │  └───────────────┘  │  │
│  │  │  Manager       │  │  │                     │  │
│  │  └────────────────┘  │  │  Pod  Pod  Pod  Pod │  │
│  └──────────────────────┘  └─────────────────────┘  │
└─────────────────────────────────────────────────────┘

你需要记住的核心角色

组件 类比 职责
API Server 前台接待 所有操作的入口,kubectl 命令最终都发给它
etcd 数据库 存储集群所有状态,是 K8s 的"大脑记忆"
Scheduler 调度员 决定 Pod 运行在哪个 Node 上
Controller Manager 保安队长 持续确保实际状态 = 期望状态
kubelet 节点执行者 在每个 Worker Node 上执行命令,管理 Pod

💡 Java 开发者类比:如果把 K8s 集群比作一个微服务架构,Control Plane 就是注册中心 + 配置中心 + 任务调度器的合体,Worker Node 就是执行业务逻辑的服务实例。


二、Pod:K8s 的最小调度单元

2.1 Pod 是什么?

很多人第一次看到 Pod 这个概念时会问:它跟容器有什么区别?

一句话区分 :容器(Container)是隔离的运行环境,Pod 是 K8s 管理容器的最小单元,一个 Pod 里可以运行一个或多个紧密协作的容器,它们共享网络命名空间和存储卷。

想象你的 Java SaaS 应用需要一个主服务容器,旁边还跑着一个日志收集的 sidecar 容器。这两个容器封装在同一个 Pod 里,它们像室友一样共享 localhost 网络,但对外是统一的 IP。

bash 复制代码
┌─────────────────────── Pod ───────────────────────┐
│                                                   │
│  ┌────────────────┐    ┌────────────────────────┐ │
│  │  Java 主容器    │    │  Fluentd 日志 sidecar   │ │
│  │  :8080         │    │                        │ │
│  └────────────────┘    └────────────────────────┘ │
│                                                   │
│  共享 Network Namespace(同一 IP)                  │
│  共享 Volume(日志目录挂载点)                        │
└───────────────────────────────────────────────────┘
         │
      Pod IP: 10.244.1.23

2.2 写第一个 Pod YAML

理解了概念,动手写一个部署 Spring Boot 应用的 Pod:

这段 YAML 是你与 K8s"对话"的语言。每个字段都是一次声明:你期望的状态是什么,K8s 负责实现它。

yaml 复制代码
# java-saas-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: java-saas-app
  namespace: production          # 所属命名空间,后文详解
  labels:
    app: java-saas
    version: "1.0.0"
    tier: backend
spec:
  containers:
    - name: spring-boot-app
      image: your-registry/java-saas:1.0.0
      ports:
        - containerPort: 8080    # 容器监听端口(仅声明用,不等于对外暴露)
      env:
        - name: SPRING_PROFILES_ACTIVE
          value: "production"
        - name: DB_HOST
          value: "mysql-service"  # 通过 Service 名称访问数据库,后文详解
      resources:
        requests:                # 调度时保证分配的最低资源
          memory: "512Mi"
          cpu: "250m"            # 250 毫核 = 0.25 个 CPU 核心
        limits:                  # 容器能使用的最大资源(超出会被限速/OOM Kill)
          memory: "1Gi"
          cpu: "1000m"
      readinessProbe:            # 就绪探针:何时接受流量
        httpGet:
          path: /actuator/health/readiness
          port: 8080
        initialDelaySeconds: 30  # 容器启动后等 30 秒再检查
        periodSeconds: 10
      livenessProbe:             # 存活探针:何时重启容器
        httpGet:
          path: /actuator/health/liveness
          port: 8080
        initialDelaySeconds: 60
        periodSeconds: 15
        failureThreshold: 3      # 连续失败 3 次才重启,避免误杀

⚠️ 踩坑记录 #1:资源 requests/limits 不设会有什么后果?

笔者曾在测试集群忘记设置 resources,导致某个内存泄漏的 Java 应用把整个 Node 的内存耗尽,节点上所有 Pod 全部被驱逐,引发雪崩。生产环境务必设置 limits ,同时 requests 不要设得太低,否则 JVM 在 Node 上启动时争抢内存会导致 GC 频繁。

Java 应用的 memory limits 建议比 JVM -Xmx 大 20-30%,为 JVM 堆外内存(Metaspace、DirectBuffer 等)留余量。

2.3 为什么不直接用 Pod 部署生产应用?

Pod 本身没有自愈能力。如果 Pod 所在的 Node 宕机,Pod 不会自动迁移到其他 Node。这就是为什么实际生产中,我们几乎不直接创建 Pod,而是通过 Deployment 来管理。


三、Deployment:让 Pod 具备生产级能力

3.1 Deployment 解决的三个核心问题

想象你是一家 SaaS 公司的架构师,你的 Java 服务需要:

  1. 高可用:至少 3 个实例同时运行,任意一个挂了自动拉起
  2. 滚动发布:新版本逐步替换旧版本,不停服
  3. 一键回滚:发现新版本有 Bug,能立刻退回上一版

Deployment 正是为此而生。它在 Pod 之上增加了一个控制层,声明"我想要 3 个副本",K8s 的 Controller Manager 就会持续让现实与声明保持一致。

bash 复制代码
Deployment
    │
    └── ReplicaSet(副本集,由 Deployment 自动管理)
            │
            ├── Pod #1  (java-saas-app-7d9f8b-xk2p1)
            ├── Pod #2  (java-saas-app-7d9f8b-mn4q7)
            └── Pod #3  (java-saas-app-7d9f8b-pz8r3)

ReplicaSet 是 Deployment 和 Pod 之间的中间层,每次更新 Deployment 的镜像,都会创建一个新的 ReplicaSet,滚动替换旧 ReplicaSet 的 Pod。你不需要直接操作 ReplicaSet,这是 Deployment 的内部实现。

3.2 生产级 Deployment YAML 详解

下面这份配置包含了你在实际项目中会需要的大部分重要字段:

yaml 复制代码
# java-saas-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-saas-deployment
  namespace: production
  labels:
    app: java-saas
  annotations:
    # 发布说明,便于 kubectl rollout history 查看
    kubernetes.io/change-cause: "v1.2.0: 新增 AI 摘要功能,优化 JVM GC 参数"
spec:
  replicas: 3                    # 期望副本数
  selector:
    matchLabels:
      app: java-saas             # Deployment 通过 Label 找到它管理的 Pod
  strategy:
    type: RollingUpdate          # 滚动更新策略(默认值)
    rollingUpdate:
      maxSurge: 1                # 更新期间最多多出 1 个 Pod(超出 replicas 数)
      maxUnavailable: 0          # 更新期间最多 0 个 Pod 不可用(零停机的关键!)
  template:                      # Pod 模板(Deployment 根据此创建 Pod)
    metadata:
      labels:
        app: java-saas
        version: "1.2.0"
    spec:
      # 优雅终止:给 Java 应用 60 秒处理完当前请求再关闭
      terminationGracePeriodSeconds: 60
      containers:
        - name: spring-boot-app
          image: your-registry/java-saas:1.2.0
          ports:
            - containerPort: 8080
          env:
            - name: JAVA_OPTS
              # JVM 参数:在 K8s 中必须用 UseContainerSupport,
              # 否则 JVM 会读取宿主机内存而非容器 limits
              value: >-
                -XX:+UseContainerSupport
                -XX:MaxRAMPercentage=75.0
                -XX:+UseG1GC
                -Xlog:gc*:file=/var/log/gc.log:time,uptime
          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "1000m"
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 15
            failureThreshold: 3
      # Pod 反亲和性:避免 3 个副本都调度到同一个 Node
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: java-saas
                topologyKey: kubernetes.io/hostname

⚠️ 踩坑记录 #2:不加 -XX:+UseContainerSupport 的灾难

这是 Java 开发者上 K8s 最常见的坑之一。容器的内存 limits 设为 1Gi,但 JVM 按宿主机 64Gi 来计算默认堆大小(约 25% 即 16Gi),JVM 申请的内存远超 limits,触发 Linux OOM Killer,Pod 被杀死且报错仅有 OOMKilled,找起来极为费劲。

Java 8u191+、Java 10+ 均已支持 -XX:+UseContainerSupport(Java 11+ 默认开启),请务必确认你的基础镜像版本。

3.3 常用 Deployment 操作命令

bash 复制代码
# 应用配置(create 或 update,--record 已弃用,改用 annotations 记录原因)
kubectl apply -f java-saas-deployment.yaml

# 查看部署状态(会实时刷新,直到 rollout 完成)
kubectl rollout status deployment/java-saas-deployment -n production

# 查看发布历史(前提是在 annotations 中记录了 change-cause)
kubectl rollout history deployment/java-saas-deployment -n production

# 紧急回滚到上一个版本
kubectl rollout undo deployment/java-saas-deployment -n production

# 回滚到指定版本(通过 history 查到的版本号)
kubectl rollout undo deployment/java-saas-deployment --to-revision=2 -n production

# 手动扩缩容(临时方案,生产建议用 HPA,详见第 04 篇)
kubectl scale deployment/java-saas-deployment --replicas=5 -n production

💡 滚动更新期间会发生什么?replicas=3, maxSurge=1, maxUnavailable=0 为例:

  1. 创建 1 个新版本 Pod → 集群共 4 个 Pod
  2. 新 Pod 通过 readinessProbe → 摘掉 1 个旧 Pod → 集群共 3 个 Pod
  3. 重复步骤直到所有旧 Pod 替换完毕

整个过程始终有 ≥3 个可用实例,实现真正零停机发布。


四、Service:Pod 的稳定"门牌号"

4.1 为什么 Pod IP 不能直接用?

前面提到,每个 Pod 有自己的 IP,但这个 IP 是不稳定的------Pod 重启或重新调度后 IP 会变化。如果你的前端直接记住后端 Pod 的 IP,那每次部署都要更新一遍,完全不可维护。

Service 解决了这个问题。它提供一个固定的虚拟 IP(ClusterIP),底层通过 Label Selector 动态路由到符合条件的健康 Pod 上。

bash 复制代码
           外部/内部请求
                │
                ▼
         ┌─────────────┐
         │   Service   │  ← 稳定的 ClusterIP: 10.96.100.50
         │ (java-saas) │     或 DNS: java-saas-service.production.svc.cluster.local
         └─────────────┘
                │
     ┌──────────┼──────────┐
     ▼          ▼          ▼
  Pod #1     Pod #2     Pod #3      ← Label: app=java-saas
(10.244.1.5)(10.244.2.8)(10.244.3.2)  (IP 可能随时变化)

4.2 四种 Service 类型及使用场景

K8s 提供了四种 Service 类型,搞清楚它们的区别是生产部署的必备知识:

类型 访问范围 典型场景
ClusterIP 集群内部 微服务间通信(默认类型)
NodePort 集群外部,通过 NodeIP:Port 测试环境快速暴露,生产慎用
LoadBalancer 集群外部,通过云厂商 LB 云环境生产暴露(AWS ELB、阿里云 SLB)
ExternalName 集群内访问外部服务 将外部数据库映射为集群内 DNS

4.3 配置 Java SaaS 的 Service

先为后端 API 配置一个集群内部 Service(其他微服务访问用):

yaml 复制代码
# java-saas-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: java-saas-service          # 这个名字就是集群内的 DNS 名
  namespace: production
  labels:
    app: java-saas
spec:
  type: ClusterIP                  # 集群内部访问
  selector:
    app: java-saas                 # 匹配所有带此 Label 的 Pod
  ports:
    - name: http
      protocol: TCP
      port: 80                     # Service 对外暴露的端口
      targetPort: 8080             # 转发到 Pod 的端口

同一命名空间内,其他 Java 服务通过 http://java-saas-service 即可访问。跨命名空间访问则用完整 DNS:http://java-saas-service.production.svc.cluster.local

对于需要对外暴露的场景,配合 Ingress Controller(详见第 03 篇)使用比 NodePort/LoadBalancer 更优雅。但如果你只是需要快速测试:

yaml 复制代码
# 快速测试用 NodePort(不建议生产)
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080      # 固定端口号(30000-32767 范围)

⚠️ 踩坑记录 #3:Service selector 匹配不上导致 502

有次发布后 Service 一直返回 502,排查了半天,发现新的 Deployment 的 Pod label 从 app: java-saas 改成了 app: java-saas-api(命名规范调整),但 Service 的 selector 没有同步更新。Service 找不到任何匹配的 Pod,请求无处可发。

排查命令kubectl get endpoints java-saas-service -n production,如果 ENDPOINTS 一列显示 <none>,说明 selector 匹配不上任何 Pod,立刻检查 Label 是否一致。


五、Namespace:集群内的"隔离舱"

5.1 Namespace 解决什么问题?

假设你们公司有三个团队共用一个 K8s 集群:后端团队、AI 团队、前端团队。没有隔离的话,资源互相抢占,权限难以控制,一个团队的误操作可能影响全局。

Namespace 提供了一个软隔离机制:

  • 资源隔离:不同 Namespace 里的 Service 名称可以重复,互不干扰
  • 权限隔离:通过 RBAC 给不同团队不同 Namespace 的操作权限(详见第 07 篇)
  • 资源配额:给每个 Namespace 设置 CPU/Memory 上限,防止一个团队"吃光"集群
bash 复制代码
┌────────────────────── K8s 集群 ──────────────────────┐
│                                                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │ production  │  │  staging    │  │    ai-team  │ │
│  │             │  │             │  │             │ │
│  │ java-saas   │  │ java-saas   │  │ llm-service │ │
│  │ (v1.2.0)    │  │ (v1.3.0-rc) │  │ (vllm)      │ │
│  │             │  │             │  │             │ │
│  │ mysql-svc   │  │ mysql-svc   │  │ gpu-pool    │ │
│  └─────────────┘  └─────────────┘  └─────────────┘ │
│                                                     │
│  默认内置: kube-system / kube-public / default       │
└─────────────────────────────────────────────────────┘

5.2 Namespace 实战配置

创建 Namespace 并配置资源配额,防止无限制消耗集群资源:

yaml 复制代码
# namespace-production.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    env: production
    team: backend
---
# 为 production namespace 设置资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    # Pod 数量上限
    pods: "50"
    # CPU/Memory 总量限制(所有 Pod 的 requests 之和不超过此值)
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.cpu: "40"
    limits.memory: 80Gi
    # Service/ConfigMap 等对象数量限制
    services: "20"
    configmaps: "50"
    persistentvolumeclaims: "20"
---
# LimitRange:为没有设置 resources 的 Pod 设置默认值
# 避免"忘了写 resources"的 Pod 无限制消耗资源
apiVersion: v1
kind: LimitRange
metadata:
  name: production-limits
  namespace: production
spec:
  limits:
    - type: Container
      default:           # 未指定 limits 时的默认值
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:    # 未指定 requests 时的默认值
        cpu: "100m"
        memory: "128Mi"
      max:               # 单个容器的最大值
        cpu: "4"
        memory: "8Gi"

常用 Namespace 管理命令:

bash 复制代码
# 创建 namespace
kubectl apply -f namespace-production.yaml

# 查看所有 namespace
kubectl get namespaces

# 查看 namespace 的资源配额使用情况
kubectl describe resourcequota production-quota -n production

# 为当前 kubectl 会话设置默认 namespace(避免每次 -n production)
kubectl config set-context --current --namespace=production

💡 最佳实践 :强烈建议用 default Namespace 只做临时测试,所有正式的工作负载都应该在专门命名的 Namespace 下。一个清晰的 Namespace 规划方案:

  • production / staging / development:按环境划分
  • infra:Prometheus、Cert-Manager 等基础设施组件
  • ai-platform:LLM 推理服务(详见第 08 篇)

六、综合实战:部署一个最小化 Java SaaS 系统

现在把前面学到的对象组合起来,部署一个包含「Java API 服务 + MySQL 数据库」的最小化 SaaS 系统。

这段配置展示了真实项目中各对象的协作关系,也是后续篇章所有例子的基础:

yaml 复制代码
# complete-java-saas.yaml
# 1. 命名空间
apiVersion: v1
kind: Namespace
metadata:
  name: my-saas
---
# 2. MySQL 部署(简化版,生产应用 StatefulSet,详见第 02 篇)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: my-saas
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "changeme"     # 生产应使用 Secret,详见第 02 篇
            - name: MYSQL_DATABASE
              value: "saasdb"
          ports:
            - containerPort: 3306
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "1Gi"
              cpu: "500m"
---
# 3. MySQL Service(仅集群内可访问)
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  namespace: my-saas
spec:
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306
---
# 4. Java SaaS API Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-saas-api
  namespace: my-saas
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java-saas-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: java-saas-api
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: api
          image: your-registry/java-saas:latest
          env:
            - name: JAVA_OPTS
              value: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
            - name: SPRING_DATASOURCE_URL
              # 通过 Service 名称访问 MySQL,无需关心具体 Pod IP
              value: "jdbc:mysql://mysql-service:3306/saasdb"
            - name: SPRING_DATASOURCE_PASSWORD
              value: "changeme"     # 生产应使用 Secret!
          ports:
            - containerPort: 8080
          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "1Gi"
              cpu: "1000m"
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 10
---
# 5. Java SaaS API Service
apiVersion: v1
kind: Service
metadata:
  name: java-saas-api-service
  namespace: my-saas
spec:
  type: NodePort                   # 快速测试用,生产替换为 Ingress
  selector:
    app: java-saas-api
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080

一键部署并验证:

bash 复制代码
# 部署所有资源
kubectl apply -f complete-java-saas.yaml

# 观察 Pod 启动状态(-w 参数实时监听变化)
kubectl get pods -n my-saas -w

# 预期输出(等待约 60 秒):
# NAME                              READY   STATUS    RESTARTS   AGE
# mysql-7c9d8f6b4-xk2p1            1/1     Running   0          2m
# java-saas-api-5b8c9f7d6-mn4q7    1/1     Running   0          90s
# java-saas-api-5b8c9f7d6-pz8r3    1/1     Running   0          90s

# 访问 API(替换 NODE_IP 为任意 Worker Node IP)
curl http://<NODE_IP>:30080/actuator/health

# 测试 Pod 间通信(进入 api pod 内部 curl mysql)
kubectl exec -it deployment/java-saas-api -n my-saas -- \
  curl mysql-service:3306

七、K8s 与 AI 大模型:系列后续预览

本文建立了 K8s 的基础认知框架。在后续篇章中,我们会逐步深入:

  • 第 02 篇 :用 ConfigMap 管理 Spring Boot 配置,用 Secret 存储数据库密码和 API Key(包括 OpenAI/通义千问的 Key)
  • 第 08 篇:在 K8s 中调度 GPU 资源,部署 vLLM 推理服务,Java 客户端通过 Service 调用大模型 API

AI 大模型与 K8s 的结合点在于:大模型推理服务本质上是一个 HTTP 服务,只是需要特殊的 GPU 资源调度。通过 K8s,你可以像管理普通 Java 微服务一样管理 LLM 推理实例,享受弹性伸缩、灰度发布、监控告警等一切能力。


八、常见问题 FAQ

Q1:K8s 和 Docker Compose 有什么本质区别?

Docker Compose 是单机多容器编排工具,适合本地开发。K8s 是跨多台机器的容器集群管理系统,提供高可用、弹性伸缩、服务发现等生产级能力。可以理解为:Compose 是"单机版",K8s 是"分布式版"。

Q2:Deployment 和 StatefulSet 选哪个?

Deployment 适合无状态服务(Java API 服务、Web 服务)------每个 Pod 完全等价,可以随意创建/销毁。StatefulSet 适合有状态服务(MySQL、Redis、Kafka)------每个 Pod 有固定的网络标识和持久存储,删除再重建后数据不丢失。第 02 篇会详细讲解 StatefulSet。

Q3:kubectl applykubectl create 有什么区别?

kubectl create 只能创建不存在的资源,资源已存在则报错。kubectl apply 是"声明式"操作,资源不存在则创建,已存在则更新到 YAML 描述的状态。实际工作中几乎只用 apply

Q4:为什么我的 Java Pod 一直 CrashLoopBackOff?

最常见的原因:① 镜像拉取失败(检查镜像名和 registry 凭证);② 应用启动报错(kubectl logs pod-name -n namespace 查看日志);③ 资源不足被 OOM Kill(检查 kubectl describe pod pod-name,看 Events 和 Last State);④ 健康检查超时(readinessProbe 的 initialDelaySeconds 设得太短)。

Q5:一个 Java SaaS 系统最少需要几个 Namespace?

最简配置:production(生产)和 staging(预发)两个就够了。随着团队规模扩大,可按"环境 + 职能"双维度拆分,加入 infra(基础设施)、ai-platform(AI 服务)等。


总结

本文用 2500 字的 YAML + 2500 字的散文讲解,带你理解了 K8s 四大核心对象:

对象 核心职责 Java SaaS 使用场景
Pod 运行容器的最小单元 承载 Spring Boot 应用容器
Deployment 管理 Pod 副本,提供滚动更新/回滚 部署无状态 Java API 服务
Service 为 Pod 提供稳定的访问入口 服务发现、负载均衡
Namespace 集群内软隔离 多环境、多团队资源隔离

💬 一句话总结:K8s 的核心思想是"声明式"------你告诉它想要的状态,它负责达到并维持这个状态。这与 Java 中的响应式编程、数据绑定框架的思想一脉相承。


第02篇:K8s 存储与配置管理:ConfigMap、Secret、PV/PVC 实战------Java SaaS 多租户配置最佳实践

将深入讲解如何优雅地管理 Spring Boot 的外部化配置,以及在 K8s 中安全存储数据库密码、AI API Key 的完整方案。


📝 系列文章持续更新中,欢迎关注、收藏、点赞三连支持!

如有问题欢迎评论区交流,笔者看到必回。

参考资料

相关推荐
一勺菠萝丶2 小时前
Docker Desktop 启动后容器自动启动怎么办?如何关闭容器自启动
运维·docker·容器
小欣加油4 小时前
leetcode3751 范围内总波动值I
java·数据结构·c++·算法·leetcode
闪电悠米4 小时前
黑马点评-Redisson-01_why_redisson
java·服务器·网络·数据库·缓存·wpf
星轨zb4 小时前
LangChain4j 集成 Spring Boot:会话记忆 NPE 的根源与 ChatMemoryProvider 正确配置
java·spring boot·后端·langchain4j
JAVA9654 小时前
JAVA面试-并发篇 05-并发包AQS队列实现原理是什么
java·开发语言·面试
JAVA面经实录9174 小时前
RocketMQ全套学习知识手册
java·kafka·rabbitmq·rocketmq
phltxy4 小时前
Spring AI 从提示词到多模态
java·人工智能·spring
Halo_tjn5 小时前
反射与设计模式1
java·开发语言·算法
神仙别闹5 小时前
基于Python + SQL server 实现(GUI)原神圣遗物管理与角色数值模拟系统
java·数据库·python