k8s
1 · k8s#
1.1 · 0. 为什么需要 k8s#
S: 写代码 → Docker 打包(环境一致性)→ Docker Compose(管理多容器,但单机) C: 多机器部署?自动扩容缩容?容器挂了谁来重启? Q: 需要一个”跨多机器的容器编排系统” A: Kubernetes — 你声明期望状态,k8s 自动驱动现实去逼近它
1.2 · 1. 核心范式:声明式 + 控制循环#
S: k8s 要管成百上千个容器 C: 命令式逐个操作不现实,手动管状态必然漂移 Q: 如何让系统自动维护期望状态? A: 声明式 + 控制循环 — 理解了这一点,所有资源都是”这个循环的不同实例”
你写 spec(期望状态)
→ Controller watch 实际状态
→ 发现 diff
→ 执行动作
→ 趋近期望
→ 循环(Reconcile Loop)
- Deployment Controller:期望 3 个副本,实际 2 个 → 创建 1 个 Pod
- Service Controller:期望 Pod 有稳定入口 → 维护 Endpoints 列表
- Node Controller:节点心跳超时 → 标记 NotReady → 驱逐 Pod
最终一致性(Eventual Consistency):不保证瞬时到位,但保证最终收敛。
1.3 · 2. 架构:谁在跑这些控制循环?#
S: 控制循环需要有人来跑 C: 调度、状态存储、执行容器是不同职责 Q: 集群内部怎么分工? A: 控制面(决策)+ 数据面(执行)
控制面(master node):
- apiserver: 唯一入口,所有组件/用户通过 RESTful API 与它交互
- etcd: 存储所有资源的期望状态和实际状态(唯一持久化存储)
- scheduler: 新 Pod 该放哪个 Node?按资源/亲和性/污点打分选择
- controller-manager: 运行所有内置 Controller(Deployment/ReplicaSet/Node/…)
数据面(worker node):
- kubelet: 唯一能和 apiserver 通信的 agent,负责管理本节点上的 Pod
- kube-proxy: 维护 iptables/IPVS 规则,实现 Service 的流量转发
- container-runtime: 真正跑容器的(containerd/CRI-O/…)
一个请求的路径:kubectl apply → apiserver → etcd 存储 → scheduler 分配 Node → kubelet 拉镜像启动容器
1.4 · 3. 工作负载:不同类型的应用怎么管?#
S: 集群跑起来了,要部署应用 C: 有的应用无状态可以随便扩,有的有状态不能乱来,有的只跑一次,有的要定时跑 Q: 不同类型的应用该用什么资源管理? A: Pod 是最小单位,上层 Controller 按应用特性管理 Pod 的生命周期
1.4.1 · Pod — 最小调度单位#
里面运行一个或多个容器。所有 k8s 资源都直接或间接依附在 Pod 之上。
- 可以挂载多个 Volume,以 Volume 方式使用 ConfigMap/Secret
- 域名:
IP地址.名字空间.pod.cluster.local(IP 中.改-) - 同一 Pod 内的容器共享网络和存储(适合 sidecar 模式:业务 + 日志采集)
1.4.2 · Deployment — 无状态应用(最常用)#
问题:Web/API 服务要保证副本数、支持滚动更新和回滚 方案:template 嵌入 Pod 定义,replicas 声明期望副本数
Deployment → 创建 ReplicaSet → ReplicaSet 创建/维护 Pod 数量(两层控制循环)
1.4.3 · StatefulSet — 有状态应用#
问题:MySQL/Redis/Kafka 需要稳定的网络标识、有序启停、持久化存储
方案:Pod 有固定名称(mysql-0, mysql-1),绑定独立 PersistentVolume
1.4.4 · DaemonSet — 每节点一个#
问题:日志采集/监控 Agent 需要在每个节点上跑一份 方案:保证每个 Node 上运行且仅运行一个 Pod
污点(taint)+ 容忍度(toleration):控制哪些 DaemonSet 可以调度到特殊节点(如 GPU 节点)
1.4.5 · Job / CronJob — 一次性 / 定时任务#
问题:数据库迁移只跑一次,日志清理每天跑 方案:Job 完成即结束;CronJob → 按 cron 表达式创建 Job → Job 创建 Pod
1.5 · 4. 网络:Pod 跑起来了,怎么访问?#
S: Pod 已经在运行 C: Pod IP 是动态的(重启/扩容就变),集群外部无法直接访问 Pod Q: 如何给 Pod 一个稳定的访问入口? A: Service(集群内四层 LB)→ Ingress(对外七层路由)
1.5.1 · Service — 稳定入口#
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/
Kubernetes 分配一个静态 ClusterIP,kube-proxy 用 iptables 将流量转发到后面动态变化的 Pod。
- ClusterIP:集群内部访问(默认)
- NodePort:在每个 Node 开一个端口暴露服务
- LoadBalancer:云厂商提供外部负载均衡器
域名:service名.namespace.svc.cluster.local
Service 本身不管理 Pod,通过 label selector 找到 Pod(和 Deployment 解耦)。
1.5.2 · Ingress — 外部流量入口#
问题:有 10 个 Service,不可能开 10 个 LoadBalancer 方案:Ingress 按域名/路径规则把流量路由到不同 Service(七层,HTTP/HTTPS)
Ingress Controller(实际干活的):
Ingress Class:解耦 Ingress 规则和 Ingress Controller 实现。
1.5.3 · 一个请求的完整路径
用户浏览器 → DNS → Ingress(七层路由,按域名/路径分发)
→ Service(四层 LB,iptables 选一个 Pod IP)
→ Pod(容器处理请求)
1.6 · 5. 配置与存储:应用运行需要什么?#
S: 应用跑起来了 C: 配置写死在镜像里改不了,密码明文不安全,容器重启数据丢失 Q: 如何管理配置、敏感信息和持久化数据? A: ConfigMap(配置)/ Secret(敏感信息)/ PersistentVolume(持久存储)
1.6.1 · ConfigMap — 配置外置#
服务地址、端口、功能开关等配置从镜像中分离出来,通过环境变量或 Volume 注入 Pod。
1.6.2 · Secret — 敏感信息#
数据库密码、API Key、TLS 证书。Base64 编码(不是加密!),生产环境需配合加密方案。
1.6.3 · PersistentVolume(PV)— 持久存储#
Pod 销毁数据不丢。PV 是集群级别的存储资源,PVC 是 Pod 对存储的申请。 StatefulSet 通常搭配 PVC 模板使用。
1.7 · 6. 生产实践:发版和运维#
S: 应用部署完毕 C: 要发新版本、要扩容、要防止容器 OOM Q: 生产环境怎么安全地运维? A: 滚动更新 + 资源配额 + 探针
- 滚动更新:修改 Deployment 的镜像 →
kubectl apply→ 自动逐步替换 Pod - 回滚:
kubectl rollout undo deployment/xxx - 水平扩缩容:
kubectl scale或 HPA(根据 CPU/内存自动扩缩) - 资源限制:
resources.requests/limits防止容器吃掉整个节点 - 探针:liveness(是否活着)/ readiness(是否准备好接流量)/ startup(是否启动完毕)
- 集群级资源配额:ResourceQuota
1.8 · 7. Operator:当内置 Controller 不够用#
S: 内置 Controller 覆盖了通用场景 C: 业务有特殊的运维逻辑(如数据库主从切换、证书自动续期) Q: 如何让 k8s 理解并自动管理自定义的业务资源? A: CRD(自定义资源)+ Controller(自定义控制循环)= Operator
本质还是声明式 + 控制循环,只是你自己定义了”期望状态”长什么样、“如何趋近”的逻辑。
1.9 · kubectl 常用命令#
minikube — 单节点集群,最主流,minikube start 即可 kind (Kubernetes in Docker) — 用 Docker 容器模拟多节点,适合测试多节点场景 k3s/k3d — 轻量发行版,资源占用最小
kubectl 管理集群资源
# 探索
kubectl api-resources # 列出所有资源类型
kubectl explain $RESOURCE # 查看资源字段说明
# 查看
kubectl get $RESOURCE # 列出实例
kubectl describe $RESOURCE # 详细信息(事件、状态)
# 部署
kubectl create deployment my-nginx --image=nginx --dry-run=client -o yaml # 生成 YAML
kubectl apply -f manifest.yaml # 声明式创建/更新(推荐)
# 运维
kubectl rollout status/undo # 发版状态/回滚
kubectl scale # 手动扩缩容
kubectl logs / exec / port-forward # 调试