k8s八股分析

K8S

1.k8s 基础组件有哪些,什么功能?

Kubernetes 遵循典型的 C/S(客户端/服务器)架构,由控制平面(Control Plane / Master)数据平面(Data Plane / Node)组成。

控制平面组件 (Master Components):

  • kube-apiserver:
    • 功能: 集群的统一入口和大脑中枢。所有组件之间的通信都通过它进行。它以 RESTful API 的形式暴露了 Kubernetes 的所有功能,并负责处理请求的认证、授权、准入控制,然后将有效资源对象的状态持久化到 etcd。
  • etcd:
    • 功能: 集群的分布式键值存储系统。它负责存储集群的所有状态数据,如 Pod、Service、Deployment 的定义和状态等。etcd 的高可用性和数据一致性是整个 K8s 集群可靠性的基石。
  • kube-scheduler:
    • 功能: 专职的“调度员”。它持续监听(Watch)apiserver,发现新创建的、尚未分配节点的 Pod。然后根据一系列预设的调度策略(如资源需求、亲和性、污点容忍等)为 Pod 选择一个最合适的 Node,并将绑定信息写回 apiserver。
  • kube-controller-manager:
    • 功能: 集群状态的“维护者”。它由一系列独立的控制器组成(如 Deployment Controller, Node Controller, Endpoint Controller 等)。每个控制器负责一种特定资源的管理,通过 apiserver 监控资源对象的当前状态(Actual State),并努力使其达到期望状态(Desired State)。这是一个持续运行的“调谐循环”(Reconciliation Loop)。

数据平面组件 (Node Components):

  • kubelet:
    • 功能: 每个 Node 上的“大管家”和代理。它直接与 apiserver 通信,接收分配到本节点的 Pod 的创建指令。然后,它调用容器运行时(如 containerd 或 Docker)来真正地启动、监控和管理容器的生命周期。同时,它还负责上报本节点的健康状况和资源使用情况。
  • kube-proxy:
    • 功能: 网络规则的“实施者”。它负责实现 Kubernetes Service 的概念。它会监听 apiserver 中 Service 和 Endpoint 的变化,并通过 iptablesIPVS 等模式在 Node 上创建和维护网络规则,从而实现服务发现和负载均衡。
  • 容器运行时 (Container Runtime):
    • 功能: 容器的“发动机”。负责镜像管理以及容器的真正运行,如 Docker, containerd, CRI-O 等。

2.一个 Pod 的创建流程是怎样的?

一个 Pod 的创建是多个组件协作的结果,其流程可以精炼为以下几个关键步骤:

  1. 用户请求: 用户通过 kubectl 或其他客户端,向 kube-apiserver 发送一个创建 Pod 的请求(通常是提交一个 YAML 文件)。
  2. API Server 处理: apiserver 收到请求后,会进行一系列处理,包括认证、授权和准入控制。验证通过后,它会将 Pod 的定义信息(一个期望状态的对象)存入 etcd,此时 Pod 的状态为 Pending,且 nodeName 字段为空。
  3. Scheduler 调度: kube-scheduler 通过 Watch 机制监听到有一个 nodeName 为空的 Pending 状态 Pod。它会启动调度流程,通过“预选”(Predicates)和“优选”(Priorities)两个阶段,为 Pod 筛选出最合适的 Node。
  4. 绑定节点: 调度成功后,scheduler 会通过 apiserver 更新 Pod 对象,将选定的 nodeName 写入 Pod 的定义中,并将这个“绑定”事件记录到 etcd
  5. Kubelet 执行: 目标 Node 上的 kubelet 通过 Watch 机制监听到有一个新的 Pod 被调度到了自己身上。
  6. 创建容器: kubelet 读取 Pod 的详细定义,然后调用容器运行时接口 (CRI) 来创建容器。这个过程通常是:
    • 调用容器网络接口 (CNI) 分配网络。
    • 创建并启动 pause 容器。
    • 依次创建并启动 Pod 中定义的业务容器。
    • 挂载 Pod 所需的 Volume。
  7. 状态上报: kubelet 会持续监控 Pod 中容器的状态,并定期将 Pod 的最新状态(如 IP 地址、运行状况)上报给 apiserverapiserver 再将这些信息更新到 etcd 中。
  8. Controller 更新 Endpoint: 当 Pod 成功运行并准备就绪(通过健康检查),endpoint-controller 会监听到这个变化,如果该 Pod 属于某个 Service,则会更新相应的 Endpoint 对象,将 Pod 的 IP 地址加入其中。至此,Pod 才能真正被 Service 发现并接收流量。

3.为什么 k8s 要用声明式 API?

声明式(Declarative)API 是 Kubernetes 的基石。与之相对的是命令式(Imperative)API。

  • 命令式: 你告诉系统“做什么”,一步一步地下达指令。例如:“运行一个容器”、“停止那个容器”、“替换这个容器”。
  • 声明式: 你告诉系统“我想要什么”,只描述最终的期望状态。例如:“我需要有 3 个副本的 Nginx v1.2 应用在运行”。

采用声明式 API 的核心优势在于:

  1. 自动化和自愈能力: 用户只需声明期望状态,Kubernetes 内部的各个控制器(Controller)会不断地检查当前状态,并自动地、持续地采取行动(创建、删除、修改资源),使当前状态趋向于期望状态。如果节点宕机或 Pod 意外死亡,控制器会自动在其他地方重建,以维持声明的数量,这是自愈能力的基础。
  2. 容错性和幂等性: 无论你执行多少次 kubectl apply -f app.yaml,只要 YAML 文件内容不变,集群的最终状态都是一样的。这使得自动化部署和配置管理变得极其简单和可靠。你不必担心重复执行命令会产生副作用。
  3. 简化管理,关注业务: 用户和管理员可以将精力集中在“业务应该是什么样”上,而不是“如何一步步达到那个状态”。这极大地降低了复杂分布式系统的管理心智负担。
  4. 易于版本控制和审计: 所有的期望状态都以 YAML/JSON 文件的形式存在,可以像代码一样被存储在 Git 等版本控制系统中,实现了基础设施即代码 (Infrastructure as Code)。每一次变更都有迹可循,便于审计和回滚。

4.kubernetes 发布策略(4种)

Recreate (重建发布):

  • 方式: 先完全删除所有旧版本的 Pod,然后再创建所有新版本的 Pod。
  • 优点: 简单直接,应用状态不会出现新旧版本共存的中间态。
  • 缺点: 会导致服务中断一段时间。适用于对服务可用性要求不高的应用。

RollingUpdate (滚动更新):

  • 方式: 这是 Deployment 的默认策略。逐步用新版本的 Pod 替换旧版本的 Pod。可以精细控制更新过程中“最多有多少个 Pod 不可用”(maxUnavailable)和“最多可以额外创建多少个 Pod”(maxSurge)。
  • 优点: 实现零停机更新,发布过程平滑。
  • 缺点: 发布周期较长,在更新过程中新旧版本并存,可能存在兼容性问题。

蓝绿发布 (Blue-Green Deployment):

  • 方式: 同时部署新旧两个版本的应用(蓝组和绿组),但只有其中一个版本(如蓝组)对外提供服务。当新版本(绿组)经过充分测试后,通过修改 Serviceselector 或负载均衡器的配置,一次性将所有流量从蓝组切换到绿组。
  • 优点: 切换速度极快,回滚几乎是瞬时的(只需将流量切回蓝组)。
  • 缺点: 需要双倍的硬件资源。

灰度发布 (Canary Release / 金丝雀发布):

  • 方式: 引入一小部分新版本的 Pod,并将少量真实流量(例如 1%)导入到新版本。通过监控新版本的表现(错误率、延迟等),如果没有问题,则逐步增加新版本 Pod 的数量和流量比例,直到完全替代旧版本。
  • 优点: 风险最低,可以基于真实流量验证新版本的稳定性。
  • 缺点: 自动化和流量控制相对复杂,通常需要结合 Service Mesh (如 Istio) 或 Ingress Controller (如 Nginx Ingress) 的高级流量管理功能来实现。

5.如果利用 k8s 实现滚动更新,我说的配置文件机制

Deployment 的 YAML 配置文件中,通过 spec.strategy 字段来定义更新策略。实现滚动更新的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 10
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app:v1.0 # 初始版本
# 关键配置在这里
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25% # 更新期间,最多允许 25% 的 Pod 不可用
maxSurge: 25% # 更新期间,最多允许额外创建 25% 的 Pod

当你想更新时,只需修改 spec.template.spec.containers[0].imagemy-app:v2.0

然后执行 kubectl apply -f deployment.yaml

Kubernetes 的 deployment-controller 会检测到 template 的变化,并启动滚动更新流程:

  • 根据 maxSurge (10 * 25% = 2.5,向上取整为 3),它最多可以创建 3 个新版 Pod,使总 Pod 数达到 13。
  • 根据 maxUnavailable (10 * 25% = 2.5,向上取整为 3),它必须保证任何时候都至少有 10 - 3 = 7 个 Pod 在运行。
  • 控制器会交替地创建新 Pod 和删除旧 Pod,直到所有 10 个副本都更新为 v2.0 版本。