简介

Kubernetes(简称 K8s)是一个 开源的容器编排平台,用于自动化 部署、扩展、管理容器化应用 的工具。

假设你有很多个应用(比如用 Docker 打包的服务),Kubernetes 能帮你:

  • 自动部署:像安装软件一样部署多个容器。
  • 📦 管理资源:统一分配 CPU、内存等资源。
  • 🔁 自动重启:服务挂了自动重启。
  • ⬆️ 滚动升级:不中断服务的情况下发布新版本。
  • 💻 负载均衡:用户访问自动分配到不同容器上。
  • 📈 自动扩容缩容:根据流量自动增加或减少容器数量。

Kubernetes 通常运行在一个集群中,包括:

  • 一个或多个 控制节点(Master)
  • 多个 工作节点(Node)
  • 节点上运行的是容器,比如用 Docker、containerd 等。Docker用来“打包”应用(像造车)。Kubernetes用来“调度管理”这些容器(像管车队)。Docker 管一个容器,Kubernetes 管一堆容器。

Kubernetes 架构采用了 主从(Master-Node) 模式,具有高度的可扩展性和模块化。

+---------------------------------------------------------------+
|                        Kubernetes 集群                        |
|                                                               |
|  +----------------+            +---------------------------+  |
|  |   Master 节点   | <------->   |       Node 节点(工作节点)     |  |
|  +----------------+            +---------------------------+  |
|     控制面(Control Plane)       每个节点上运行 Pod、容器等资源      |
+---------------------------------------------------------------+

Master 控制面组件
kube-apiserver

  • 对外暴露的统一接口,所有操作都要通过它进行。
  • 是 Kubernetes 的“前门”。

etcd

  • 高可用的键值存储系统。
  • 用于保存所有集群状态(如节点信息、Pod 状态、配置等)。

kube-scheduler:调度器,负责将 Pod 分配到合适的节点上。

kube-controller-manager 管理集群中的各种控制器,例如:

  • 节点控制器
  • 副本控制器(ReplicaSet)
  • 端点控制器(Endpoints)
  • 服务账户控制器

cloud-controller-manager(可选) 用于和云平台交互(如创建负载均衡器、磁盘等)。

Node 工作节点组件
kubelet

  • 与 API Server 通信,确保容器按照 Pod 规范运行。
  • 监控 Pod 和容器状态。

kube-proxy

  • 管理服务的网络通信(Service -> Pod)。
  • 实现 Kubernetes 的服务发现与负载均衡。

容器运行时(Container Runtime)

  • 比如 Docker、containerd、CRI-O。
  • 负责真正拉取镜像并运行容器。

其他关键概念

  • Pod:K8s 最小的调度单位,一个或多个容器的集合。
  • Service:提供稳定的访问入口,负责负载均衡。
  • Deployment:控制 Pod 的副本数量,实现滚动更新等。
  • Namespace:多租户隔离机制。

🧭 总结图示(简化)

用户 -> kubectl -> kube-apiserver -> etcd
                           |
            +--------------+--------------+
            |              |              |
      scheduler     controller-manager   ...
                           |
               控制 Pod 部署 / 更新 / 状态
                           |
                     各 Node 节点
               +----------------------+
               | kubelet + kube-proxy |
               |    + 容器运行时       |
               +----------------------+

Pod 是 Kubernetes 中最小的调度单元。 它是运行一个或多个紧密关联容器的封装体**,比如:

docker run nginx

在 Kubernetes 里,它不会直接运行容器,而是运行一个 Pod,Pod 里面装着这个容器。

一个 Pod 可能包含一个容器(最常见);多个容器(共享网络 & 存储,用于协作,比如主服务 + 辅助 sidecar)

📦 Pod 特性:

特性 说明
共享网络 Pod 里的容器用同一个 IP,localhost 之间可以通信
共享存储 可挂载同一个 Volume(持久化数据)
生命周期一致 一个 Pod 里的容器是一起创建、一起销毁的
短暂性 Pod 本身是“易失”的,挂了就没了,通常通过 Deployment 来控制它们重建

🧭 Pod 工作流程:

  1. 创建一个 Pod(直接或通过 Deployment 等)
  2. kube-scheduler 把它调度到某个 Node
  3. kubelet 在 Node 上启动里面的容器
  4. kube-proxy 负责网络连接
  5. Pod 运行、暴露端口、接收流量等

Kubernetes 中导致 pod 重启的原因

应用程序异常

  • 应用进程崩溃:Pod 内部的应用程序由于未处理的异常、内存溢出(OOM)、访问非法地址等原因崩溃,导致容器退出并被 K8s 重新拉起。
  • 主动退出(exit 非 0):如果容器的主进程(PID 1)主动退出并返回非零状态码,K8s 会认为容器异常终止,并可能触发重启。

OOM(Out Of Memory)杀死

  • 内存不足(OOMKilled):当容器内存超出 requestslimits 限制,K8s 可能会触发 OOM 终止容器。
  • Node 级别 OOM:如果 Node 本身内存不足,K8s 可能会触发 OOM 终止某些 Pod(优先终止低优先级的 Pod)。

Liveness Probe 检测失败

  • 存活探针(Liveness Probe)失败:如果 Pod 配置了 livenessProbe,但探测失败(例如健康检查接口未响应或返回错误),K8s 会认为该容器不健康并重启它。

Readiness Probe 失败

  • 就绪探针(Readiness Probe)失败:虽然 Readiness Probe 失败不会直接导致重启,但如果 Pod 一直无法进入就绪状态,可能会被调度器驱逐或被运维人员删除并重新创建。

节点问题

  • Node 故障:如果运行 Pod 的 Node 发生故障(如宕机、网络异常等),K8s 会将该 Node 标记为 NotReady,并可能在其他 Node 上重新调度 Pod。
  • Node 重启:如果 Node 由于系统更新、管理员操作等原因重启,Pod 也会随之重启。

可以使用以下命令查看 Pod 的状态和重启原因:

kubectl get pod <pod_name> -o wide
kubectl describe pod <pod_name>
kubectl logs <pod_name> --previous  # 查看上次退出的日志
kubectl get events --sort-by=.metadata.creationTimestamp  # 查看最近的事件

如果 Pod 处于 CrashLoopBackOff 状态,可以进一步检查:

kubectl get pod <pod_name> -o yaml | grep reason

如果怀疑是 OOMKilled:

kubectl describe pod <pod_name> | grep -i oom

如果 Pod 运行的是 Java 应用,JVM 的堆内存(Heap)和 Kubernetes 分配的内存可能存在不匹配的问题:

  • JVM 默认会基于物理内存计算 -Xmx(最大堆内存),但 K8s 容器中的可用内存是受 limits.memory 限制的。
  • 如果 JVM 误以为它可以使用整个节点的内存,而不是容器的限制,可能导致 堆内存(Heap)+ 其他非堆内存(Metaspace、Stack)总和超出 K8s 限制,最终触发 OOMKilled。

如何避免 OOMKilled?
使用 requests.memorylimits.memory

  • requests.memory:表示Pod 启动时的最小预留内存,用于调度时分配。
  • limits.memory:表示Pod 最大可使用的内存,超出后会触发 OOMKilled。
resources:
  requests:
    memory: "512Mi"   # 申请 512MB
  limits:
    memory: "1Gi"     # 限制最大 1GB

避免 limits.memory 过低,否则 JVM 可能会因 GC 频繁触发 OOM。 如果业务允许,可以不设置 limits.memory,仅使用 requests.memory,这样 Kubernetes 不会强行杀死超限的进程,而是让 JVM 进行 GC 以尝试释放内存。

监控和优化内存使用

  1. 监控 JVM 内存占用
    • 使用 Prometheus + Grafana 监控 Pod 内存使用情况
    • 结合 JVM Metrics(Micrometer、JMX Exporter) 监控 Heap、GC 频率
  2. 优化代码
    • 通过 调优 GC(G1GC、ZGC)减少堆外内存泄露
    • 避免大量对象滞留,减少 OutOfMemoryError: Metaspace

Kubernetes 中 Pod 节点相关问题

重启是否导致 Pod 名称发生变化
在 Kubernetes 中,Pod 的名称是否变化取决于它是如何创建的。

手动创建的 Pod(裸 Pod)
如果你是用 kubectl apply -f pod.yaml 创建的 裸 Pod,那么:

  • Pod 重启(节点重启)后不会自动恢复
  • 如果节点崩溃了,Pod 会直接消失(不会自动迁移到其他节点);
  • 如果你自己重新创建 Pod,名称可能会改变,取决于你是否指定相同名称;
  • Pod 是不可恢复的资源 —— 不推荐在生产中使用裸 Pod。

由控制器管理的 Pod(如 Deployment、StatefulSet)

  1. Deployment / ReplicaSet 管理的 Pod
    • 如果节点重启、Pod 宕机,Deployment 会重建一个新的 Pod;
    • 新的 Pod 名称会变化,因为它们是动态生成的,比如:
      my-app-7cc7b569b6-lmwvh → my-app-7cc7b569b6-k9zdf
      
  2. StatefulSet 管理的 Pod
    • StatefulSet 会保留 Pod 名称(有状态);
    • 名称不会变,例如:
      my-db-0、my-db-1 这种格式;
      
    • 即使节点重启、Pod 被重新调度,名称还是 my-db-0

在现代生产环境中,使用最多的是 Deployment + ReplicaSet 管理的 Pod,原因如下:

Deployment 是默认的无状态服务部署方式

  • 适合大多数业务场景(如 Web 服务、API 服务、Worker 等);
  • 支持 滚动更新、回滚、扩缩容、健康检查
  • 简单易用,社区支持广泛;
  • 与 HPA(水平自动扩展)无缝配合。

StatefulSet 用于有状态服务,使用相对少一些

  • 适用于数据库、Kafka、ZooKeeper 这类 有状态服务
  • 支持固定 Pod 名称和稳定持久化存储(如 my-app-0, my-app-1);
  • 支持有序部署、扩容、缩容;
  • 配置和管理更复杂,不适合大规模无状态服务。

DaemonSet 适合做守护进程

  • 用于每个节点运行一个 Pod,比如日志采集(Fluentd)、监控 Agent(Prometheus Node Exporter)等;
  • 用量少但场景明确。

裸 Pod 几乎不用于生产

  • 不具备自愈能力;
  • 无法自动调度、自动扩缩容;
  • 容易丢失,不安全。

在现代生产环境中,大多数情况下一个 Pod 只运行一个主要容器,但也存在运行多个容器的情况,具体看应用场景。

单容器 Pod(最常见)

  • 绝大多数业务服务(Web 服务器、API 服务、后台任务)都是一个 Pod 只运行一个主容器;
  • 简单、易管理、资源隔离清晰;
  • Kubernetes 的设计理念是“一组紧密相关的容器组成一个 Pod”,但大多数场景一个容器足够了。

多容器 Pod(Sidecar 模式等)

  • 多个容器共享一个 Pod 网络和存储,彼此协作;
  • 常见场景包括:
    • Sidecar 容器
      • 日志采集(如 Fluentd sidecar 跟主容器一起工作);
      • 配置更新(如 Envoy 代理、Istio Sidecar);
      • 监控 Agent;
      • 数据同步;
    • Adapter 容器
      • 对主应用进行辅助处理,例如缓存、代理等。
  • 多容器 Pod 让业务容器和辅助容器能紧密协同,且共享生命周期。

在一个 Pod 里运行多个容器时,Pod 的生命周期是绑定在这些容器上的,所以:

  • 只要 Pod 里任意一个容器崩溃或异常,整个 Pod 都会被认为“异常”
  • Kubernetes 会根据 Pod 的重启策略(restartPolicy)来决定是重启单个容器,还是整个 Pod 重启;
  • 但实际上,Pod 里的容器共享同一个 Pod 生命周期和调度单元,当关键容器挂掉,通常会触发 Pod 重启;
  • Pod 里的所有容器都会被杀死并重新启动,这意味着任何一个容器异常都会导致整个 Pod 重启
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐