Kubernetes 基础
Kubernetes 集群由两类节点组成:Control Plane(控制平面)和 Worker Node(工作节点)。 Control Plane 组件 Worker Node 组件 生产环境推荐声明式,便于版本控制和 GitOps 工作流。 列出资源对象。 查看资源详情及事件(排查问题的首选命令)。 将 YAML/JSON 清单应用到集群(声明式更新)。 删除资源对象。 查看 Pod 中容器的日志。 在运行中的容器内执行命令。 将本地端口转发到 Pod 端口,常用于本地调试。 调整 Deployment/StatefulSet/ReplicaSet
官方文档:https://kubernetes.io/zh-cn/docs/home/
适用版本:Kubernetes 1.29+(2026-05-07 核实)
核心概念
集群架构
Kubernetes 集群由两类节点组成:Control Plane(控制平面)和 Worker Node(工作节点)。
Control Plane 组件
| 组件 | 职责 |
|---|---|
| API Server | 集群的统一入口,所有操作(kubectl、内部组件通信)均通过 REST API 与它交互 |
| etcd | 分布式键值存储,保存集群所有状态数据(配置、资源对象) |
| Scheduler | 监听未调度的 Pod,根据资源需求、亲和性等规则将其分配到合适的 Node |
| Controller Manager | 运行各类控制器(Deployment Controller、ReplicaSet Controller 等),持续将实际状态收敛到期望状态 |
Worker Node 组件
| 组件 | 职责 |
|---|---|
| kubelet | 运行在每个 Node 上的代理,负责接收 Pod 规格并驱动容器运行时启动/维护容器 |
| kube-proxy | 维护节点上的 iptables/ipvs 规则,实现 Service 的负载均衡和流量转发 |
| Container Runtime | 实际运行容器的引擎,常见实现为 containerd、CRI-O(旧版为 Docker) |
Pod、Node、Namespace 的关系
- Node 是物理或虚拟机器,是运行 Pod 的宿主机。
- Pod 是 Kubernetes 最小调度单元,运行在某个 Node 上,包含一个或多个容器,共享网络栈和存储卷。
- Namespace 是逻辑隔离单位,用于将同一集群的资源划分为不同的虚拟空间(如
dev、staging、prod)。Node 本身不属于 Namespace,Pod 和 Service 等资源属于某个 Namespace。
声明式 vs 命令式
| 方式 | 描述 | 典型用法 |
|---|---|---|
| 命令式(Imperative) | 直接告诉集群"做什么动作" | kubectl run、kubectl scale |
| 声明式(Declarative) | 描述"期望状态",集群自动收敛 | kubectl apply -f manifest.yaml |
生产环境推荐声明式,便于版本控制和 GitOps 工作流。
kubectl 常用命令
kubectl get
列出资源对象。
kubectl get <resource> [-n namespace] [-o wide|yaml|json]
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<resource> |
字符串 | 必填 | 资源类型,如 pods、deployments、services、nodes |
-n / --namespace |
字符串 | default |
指定命名空间;-A 表示所有命名空间 |
-o / --output |
字符串 | 表格 | 输出格式:wide(更多列)、yaml、json、name |
-l / --selector |
字符串 | 无 | 按标签筛选,如 -l app=nginx |
--field-selector |
字符串 | 无 | 按字段筛选,如 --field-selector status.phase=Running |
-w / --watch |
bool | false | 监听资源变化,实时输出 |
kubectl get pods -n kube-system -o wide
kubectl get all -A
kubectl get pods -l app=nginx
kubectl describe
查看资源详情及事件(排查问题的首选命令)。
kubectl describe <resource> <name> [-n namespace]
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<resource> |
字符串 | 必填 | 资源类型 |
<name> |
字符串 | 必填 | 资源名称 |
-n / --namespace |
字符串 | default |
命名空间 |
kubectl describe pod my-pod -n default
kubectl describe node worker-1
kubectl apply
将 YAML/JSON 清单应用到集群(声明式更新)。
kubectl apply -f <file.yaml>
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
-f / --filename |
字符串/目录 | 必填 | 文件路径、目录或 URL;-f . 应用当前目录所有 YAML |
-R / --recursive |
bool | false | 递归处理目录 |
--dry-run=client |
字符串 | 无 | 模拟执行,不实际变更集群 |
--prune |
bool | false | 删除集群中存在但本地清单中已移除的资源 |
kubectl apply -f deployment.yaml
kubectl apply -f ./manifests/ -R
kubectl apply -f deployment.yaml --dry-run=client
kubectl delete
删除资源对象。
kubectl delete <resource> <name> [-n namespace]
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<resource> |
字符串 | 必填 | 资源类型 |
<name> |
字符串 | 必填(或用 -f) | 资源名称 |
-f |
字符串 | 无 | 通过文件删除 |
--grace-period |
整数 | 30 | 优雅终止等待秒数;0 强制立即删除 |
--force |
bool | false | 强制删除,跳过优雅终止 |
kubectl delete pod my-pod
kubectl delete -f deployment.yaml
kubectl delete pod my-pod --grace-period=0 --force
kubectl logs
查看 Pod 中容器的日志。
kubectl logs <pod> [-c container] [-f] [--previous]
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<pod> |
字符串 | 必填 | Pod 名称 |
-c / --container |
字符串 | 无 | 多容器 Pod 时指定容器名 |
-f / --follow |
bool | false | 持续跟踪输出(类似 tail -f) |
--previous |
bool | false | 查看上一个已终止容器的日志(容器崩溃重启后排查) |
--tail |
整数 | 无 | 只输出最后 N 行 |
--since |
时间段 | 无 | 只输出指定时间段内的日志,如 --since=1h |
kubectl logs my-pod -c sidecar -f
kubectl logs my-pod --previous --tail=100
kubectl exec
在运行中的容器内执行命令。
kubectl exec -it <pod> [-c container] -- /bin/sh
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<pod> |
字符串 | 必填 | Pod 名称 |
-i / --stdin |
bool | false | 保持标准输入打开 |
-t / --tty |
bool | false | 分配伪终端 |
-c / --container |
字符串 | 无 | 多容器 Pod 时指定容器 |
-- |
分隔符 | 无 | 之后为传入容器的命令 |
kubectl exec -it my-pod -- /bin/bash
kubectl exec -it my-pod -c init-container -- /bin/sh
kubectl port-forward
将本地端口转发到 Pod 端口,常用于本地调试。
kubectl port-forward <pod> <local>:<remote>
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<pod> |
字符串 | 必填 | Pod 名称;也可用 svc/<name> 或 deploy/<name> |
<local>:<remote> |
端口映射 | 必填 | 本地端口:容器端口 |
-n |
字符串 | default |
命名空间 |
kubectl port-forward my-pod 8080:80
kubectl port-forward svc/my-service 9090:9090 -n staging
kubectl scale
调整 Deployment/StatefulSet/ReplicaSet 的副本数。
kubectl scale deployment <name> --replicas=N
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
<name> |
字符串 | 必填 | 资源名称 |
--replicas |
整数 | 必填 | 目标副本数 |
-n |
字符串 | default |
命名空间 |
kubectl scale deployment my-app --replicas=3
kubectl rollout
管理 Deployment 的发布过程。
kubectl rollout status|history|undo deployment/<name>
| 子命令 | 说明 |
|---|---|
status |
查看当前滚动更新进度 |
history |
查看历史版本列表(需要 --record 或设置 change-cause) |
undo |
回滚到上一版本;--to-revision=N 回滚到指定版本 |
pause |
暂停滚动更新 |
resume |
恢复已暂停的滚动更新 |
kubectl rollout status deployment/my-app
kubectl rollout history deployment/my-app
kubectl rollout undo deployment/my-app
kubectl rollout undo deployment/my-app --to-revision=2
核心资源对象
Pod
Pod 是 Kubernetes 的最小调度单元,封装一个或多个容器。
基本 YAML 结构
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: default
labels:
app: my-app
spec:
containers:
- name: main
image: nginx:1.25
ports:
- containerPort: 80
env:
- name: ENV_VAR
value: "hello"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
volumeMounts:
- name: config-vol
mountPath: /etc/config
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 3
volumes:
- name: config-vol
configMap:
name: my-config
spec.containers 核心字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
字符串 | 必填 | 容器名称,同一 Pod 内唯一 |
image |
字符串 | 必填 | 镜像地址,建议指定具体 tag,避免使用 latest |
ports |
列表 | 无 | 声明容器监听的端口(仅文档作用,不影响实际网络) |
env |
列表 | 无 | 环境变量,支持直接赋值或引用 ConfigMap/Secret |
resources |
对象 | 无 | CPU/内存的 requests 和 limits |
volumeMounts |
列表 | 无 | 挂载卷到容器内的路径 |
livenessProbe |
对象 | 无 | 存活探针,失败则重启容器 |
readinessProbe |
对象 | 无 | 就绪探针,失败则从 Service 摘除流量 |
startupProbe |
对象 | 无 | 启动探针,用于慢启动容器,成功后才开始执行其他探针 |
command |
列表 | 无 | 覆盖镜像的 ENTRYPOINT |
args |
列表 | 无 | 覆盖镜像的 CMD |
imagePullPolicy |
字符串 | IfNotPresent |
拉取策略:Always、IfNotPresent、Never |
resources.requests vs resources.limits
| 字段 | 作用 | 调度影响 |
|---|---|---|
requests |
Scheduler 用于选择节点的依据,保证容器能获得此资源量 | 影响调度 |
limits |
容器能使用的资源上限,超出 CPU limit 会被限流,超出 Memory limit 会被 OOM Kill | 不影响调度 |
建议始终设置 requests,在资源紧张的生产环境也应设置 limits。
多容器 Pod(Sidecar 模式)
同一 Pod 内的容器共享网络(localhost 互通)和存储卷,适合以下模式:
- Sidecar:辅助主容器,如日志收集(Fluentd)、配置同步
- Ambassador:代理主容器对外通信
- Adapter:转换主容器的输出格式
spec:
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: log-vol
mountPath: /var/log/app
- name: log-collector
image: fluentd:latest
volumeMounts:
- name: log-vol
mountPath: /var/log/app
volumes:
- name: log-vol
emptyDir: {}
Deployment
Deployment 管理无状态应用的副本集,提供滚动更新和回滚能力。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:1.0
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
spec 核心字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
replicas |
整数 | 1 |
期望的 Pod 副本数 |
selector |
对象 | 必填 | 选择受管 Pod 的标签选择器,必须与 template.metadata.labels 匹配 |
template |
对象 | 必填 | Pod 模板,定义创建 Pod 时使用的规格 |
strategy |
对象 | RollingUpdate |
更新策略,支持 RollingUpdate 和 Recreate |
minReadySeconds |
整数 | 0 |
Pod 就绪后额外等待的秒数,再认为该 Pod 可用 |
revisionHistoryLimit |
整数 | 10 |
保留的历史 ReplicaSet 数量,用于回滚 |
paused |
bool | false | 暂停发布,配合 kubectl rollout pause 使用 |
滚动更新策略参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
maxSurge |
整数或百分比 | 25% |
更新期间允许超出期望副本数的最大 Pod 数量 |
maxUnavailable |
整数或百分比 | 25% |
更新期间允许不可用的最大 Pod 数量 |
零停机发布建议:maxSurge: 1,maxUnavailable: 0。
Service
Service 为一组 Pod 提供稳定的访问入口(虚拟 IP + DNS 名称)。
Service 类型对比
| 类型 | 访问范围 | 说明 |
|---|---|---|
ClusterIP |
集群内部 | 默认类型,分配集群内虚拟 IP,仅集群内可访问 |
NodePort |
集群外部 | 在每个 Node 上开放一个静态端口(30000-32767),外部通过 NodeIP:NodePort 访问 |
LoadBalancer |
集群外部 | 需要云平台支持,自动创建外部负载均衡器,分配公网 IP |
ExternalName |
集群内部 | 将 Service 映射到外部 DNS 名称(CNAME),用于访问集群外部服务 |
spec.selector 工作方式
Service 通过标签选择器动态发现后端 Pod。只要 Pod 带有匹配的标签且处于 Ready 状态,就会加入 Endpoints 列表。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app # 匹配带有此标签的 Pod
ports:
- port: 80 # Service 暴露的端口
targetPort: 8080 # 转发到 Pod 的端口
type: ClusterIP
Headless Service
将 clusterIP 设为 None,不分配虚拟 IP,DNS 查询直接返回 Pod IP 列表。StatefulSet 场景下常用,客户端可以直接连接到特定 Pod。
spec:
clusterIP: None
selector:
app: my-statefulset
ConfigMap 与 Secret
创建方式
# 命令行字面量
kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2
# 从文件创建
kubectl create configmap my-config --from-file=config.properties
# 从目录创建(目录下每个文件成为一个键)
kubectl create configmap my-config --from-file=./configs/
# YAML 方式
kubectl apply -f configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
APP_ENV: production
config.yaml: |
server:
port: 8080
Secret 创建方式相同,但内容会经 Base64 编码存储:
kubectl create secret generic my-secret \
--from-literal=db-password=s3cr3t \
--from-file=tls.crt=./certs/tls.crt
注入方式对比
| 方式 | 使用场景 | 特点 |
|---|---|---|
| 环境变量 | 简单键值对 | 容器启动时注入,ConfigMap 更新后不自动刷新,需重启 Pod |
| volumeMount | 配置文件、多行内容 | 以文件形式挂载,ConfigMap 更新后文件会自动同步(有延迟) |
# 环境变量注入
env:
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: my-config
key: APP_ENV
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: db-password
# 全量注入为环境变量
envFrom:
- configMapRef:
name: my-config
# volumeMount 注入
volumeMounts:
- name: config-vol
mountPath: /etc/app
volumes:
- name: config-vol
configMap:
name: my-config
Health Check(健康检查)
三种探针的区别
| 探针 | 失败后行为 | 典型使用场景 |
|---|---|---|
livenessProbe |
重启容器 | 检测应用是否陷入死锁、无响应状态 |
readinessProbe |
从 Service Endpoints 中摘除该 Pod(不重启) | 检测应用是否已准备好接收流量 |
startupProbe |
在成功前,liveness/readiness 探针不会执行;失败超限则重启 | 启动慢的应用(如 JVM 应用),避免被 liveness 误杀 |
探针类型参数
httpGet
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path |
字符串 | 必填 | 请求路径 |
port |
整数/字符串 | 必填 | 端口号或容器端口名 |
scheme |
字符串 | HTTP |
协议:HTTP 或 HTTPS |
httpHeaders |
列表 | 无 | 自定义请求头 |
exec
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
command |
列表 | 必填 | 在容器内执行的命令,退出码为 0 表示成功 |
tcpSocket
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
port |
整数/字符串 | 必填 | TCP 端口号,能建立连接则成功 |
探针通用配置参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
initialDelaySeconds |
整数 | 0 |
容器启动后等待多少秒才开始探测 |
periodSeconds |
整数 | 10 |
探测间隔秒数 |
timeoutSeconds |
整数 | 1 |
探测超时秒数 |
successThreshold |
整数 | 1 |
连续成功多少次才认为健康(liveness 只能为 1) |
failureThreshold |
整数 | 3 |
连续失败多少次才采取行动 |
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
tcpSocket:
port: 8080
failureThreshold: 30 # 最多等待 30 * 10 = 300 秒
periodSeconds: 10
踩坑与注意事项
Pod 一直处于 Pending 状态
排查思路:kubectl describe pod <name> 查看 Events 字段。
| 常见原因 | 表现 | 解决方法 |
|---|---|---|
| 节点资源不足 | Insufficient cpu / Insufficient memory |
调整 resources.requests,或扩容节点 |
| 镜像拉取失败 | Failed to pull image / ImagePullBackOff |
检查镜像名称、tag、仓库权限,配置 imagePullSecrets |
| NodeSelector 无匹配 | 0/N nodes are available: N node(s) didn't match node selector |
检查 nodeSelector 标签是否存在于节点 |
| PVC 未绑定 | pod has unbound immediate PersistentVolumeClaims |
检查 PV/StorageClass 是否正确配置 |
| Taint 未容忍 | N node(s) had taints that the pod didn't tolerate |
为 Pod 添加对应 tolerations |
ImagePullBackOff 排查步骤
kubectl describe pod <name>查看具体错误信息- 确认镜像地址和 tag 正确:
docker pull <image>在本地验证 - 私有仓库需创建 Secret 并配置
imagePullSecrets:kubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=user \ --docker-password=passwordspec: imagePullSecrets: - name: regcred - 检查节点网络是否能访问镜像仓库
其他常见坑
- 环境变量中引用 Secret:Secret 的 value 已经是明文,不需要 Base64 解码,Kubernetes 会自动处理。
- ConfigMap 大小限制:单个 ConfigMap 数据上限为 1MB,超大配置文件建议用 Volume 挂载外部存储。
- Service 和 Pod 标签必须严格匹配:selector 中的每个标签键值对都必须出现在 Pod 的 labels 中。
kubectl apply与kubectl create的区别:create用于首次创建,资源已存在则报错;apply创建或更新,推荐生产使用。
最佳实践
始终设置 resources.requests 和 resources.limits:没有 requests 的 Pod 会被调度到资源不足的节点,没有 limits 的 Pod 可能耗尽节点资源导致其他 Pod 被驱逐。
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
用 livenessProbe 和 readinessProbe 保障流量切换:livenessProbe 失败时 kubelet 重启容器,readinessProbe 失败时 Service 摘除该 Pod 的流量,两者配合实现零停机滚动更新。
命名空间隔离不同环境:用 dev/staging/prod 命名空间隔离资源,配合 RBAC 限制各命名空间的操作权限,避免误操作生产资源。
kubectl apply 优于 kubectl create:apply 是声明式更新,支持 GitOps 工作流;create 只能用于首次创建,资源已存在时报错。所有资源文件纳入 Git 版本控制。
使用 Deployment 而非直接管理 Pod:裸 Pod 在节点故障后不会自动重建,Deployment 通过 ReplicaSet 保证副本数,并提供滚动更新和回滚能力。
常见陷阱
陷阱:Pod 一直处于 Pending 状态
现象: kubectl get pods 显示 Pod 长时间 Pending,无法调度到节点。
原因: 常见原因:节点资源不足(CPU/内存)、节点 taint 与 Pod 无匹配 toleration、PVC 未绑定、nodeSelector 无匹配节点。
解决: kubectl describe pod <name> 查看 Events 字段,根据 Insufficient cpu、no nodes are available 等提示定位原因。
陷阱:ConfigMap / Secret 更新后 Pod 内不生效
现象: 更新了 ConfigMap,但 Pod 内挂载的文件仍是旧值。
原因: 以 subPath 挂载的 Volume 不会自动同步更新;环境变量注入的值在 Pod 启动时已固化。
解决: 避免 subPath;使用环境变量时需滚动重启 Pod(kubectl rollout restart deployment/<name>)使新配置生效。
陷阱:Service 无法访问 Pod
现象: Service ClusterIP 可达但请求超时,或返回 connection refused。
原因: Service 的 selector 标签与 Pod 的 labels 不匹配,导致 Endpoints 列表为空。
解决: kubectl get endpoints <service-name> 检查 Endpoints,若为空则检查 selector 与 Pod labels 是否一致(区分大小写)。