Appearance
kubectl 与 YAML
Kubernetes 的日常操作主要围绕 API 对象展开。kubectl 是访问 API Server 的客户端,YAML 是描述资源期望状态的文件格式。命令行负责提交、查询、对比和排错,YAML 负责把资源对象记录成可复用、可审查、可回滚的文本。
资源对象可以近似看成一份结构化记录:apiVersion 和 kind 决定资源类型,metadata 描述身份,spec 写期望状态,status 由控制器回写当前状态。排查时经常就是对比 spec 和 status:文件里希望有 3 个副本,状态里只有 1 个 Ready;Service 期望选中某组 Pod,EndpointSlice 里却没有后端。
一、kubectl 连接到哪里
kubectl 读取 kubeconfig 文件,里面记录集群地址、用户凭据和当前上下文。默认路径是 ~/.kube/config,也可以通过 KUBECONFIG 指定。
bash
kubectl config current-context
kubectl config get-contexts
kubectl cluster-info常用的 kubeconfig 结构如下:
yaml
apiVersion: v1
kind: Config
clusters:
- name: k3s
cluster:
server: https://192.168.10.11:6443
certificate-authority-data: LS0tLS1CRUdJTi...
users:
- name: admin
user:
client-certificate-data: LS0tLS1CRUdJTi...
client-key-data: LS0tLS1CRUdJTi...
contexts:
- name: admin@k3s
context:
cluster: k3s
user: admin
namespace: default
current-context: admin@k3sserver 是 API Server 地址。证书字段用于客户端身份认证,和 RBAC 权限判断配合使用。生产环境里常见问题不是 kubectl 命令本身坏了,而是 kubeconfig 指向了错误集群、当前 namespace 不对,或者用户没有对应资源的权限。
二、资源对象的基本结构
一个最小 Deployment:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.26
ports:
- containerPort: 80几个字段的分工:
| 字段 | 说明 |
|---|---|
apiVersion | API 组和版本,决定这个资源由哪个 API 提供 |
kind | 资源类型,比如 Pod、Service、Deployment |
metadata.name | 同一 namespace 内的资源名称 |
metadata.namespace | 命名空间,不写时通常落到 default |
metadata.labels | 可被 selector 匹配的标签 |
spec | 期望状态,由使用者提交 |
status | 当前状态,由控制器或 kubelet 回写 |
源文件里通常不写 status。从集群导出的完整 YAML 会包含 uid、resourceVersion、managedFields、status 等运行期字段,这些字段不适合直接复制回 Git 仓库。
三、API 组和版本
Kubernetes 的资源不全在同一个 API 里。核心资源在 v1,工作负载在 apps/v1,批处理任务在 batch/v1,网络策略在 networking.k8s.io/v1。
| apiVersion | 常见 kind |
|---|---|
v1 | Pod、Service、ConfigMap、Secret、PersistentVolumeClaim |
apps/v1 | Deployment、StatefulSet、DaemonSet |
batch/v1 | Job、CronJob |
networking.k8s.io/v1 | Ingress、NetworkPolicy |
gateway.networking.k8s.io/v1 | Gateway、HTTPRoute |
storage.k8s.io/v1 | StorageClass |
rbac.authorization.k8s.io/v1 | Role、ClusterRole、RoleBinding、ClusterRoleBinding |
查看当前集群支持哪些资源:
bash
kubectl api-resources
kubectl api-versions字段不熟时用 kubectl explain 查结构,比照着网上旧示例复制更稳。Kubernetes 版本变化后,某些字段可能已经废弃,explain 能直接反映当前集群支持的 schema。
bash
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template.spec.containers
kubectl explain cronjob.spec.jobTemplateCRD 安装后,kubectl explain 也能看到自定义资源的字段结构。Prometheus Operator 的 ServiceMonitor、Argo Rollouts 的 Rollout、Gateway API 的 HTTPRoute 都属于这类对象。
四、apply、diff 和 dry-run
声明式资源通常用 apply 提交:
bash
# 预览本地文件和集群当前对象之间的差异
kubectl diff -f web.yaml
# 提交声明式配置,让控制器按 spec 调整实际状态
kubectl apply -f web.yaml
# 查看资源是否创建成功
kubectl get deploy,svc -n demodiff 对变更前确认很有用。比如改了镜像版本、环境变量、Service 端口,先看差异能避免把不相关字段一起带进去。
dry-run 常用于生成模板或验证 YAML:
bash
# 只在客户端生成 YAML,不提交到集群
kubectl create deployment web --image=nginx:1.26 \
--dry-run=client -o yaml
# 发送到 API Server 做校验,但不持久化资源
kubectl apply -f web.yaml --dry-run=server--dry-run=server 会走 API Server 的准入校验、默认值填充和 schema 校验。CRD 资源或有准入策略的集群里,server dry-run 更接近真实提交结果。
五、get、describe 和 events
get 适合快速看列表和关键字段:
bash
kubectl get pod -n demo
kubectl get pod -n demo -o wide
kubectl get deploy web -n demo -o yaml
kubectl get pod -n demo -l app=webdescribe 会把对象详情、事件和关联状态放在一起:
bash
kubectl describe pod <pod-name> -n demo
kubectl describe deploy web -n demo
kubectl describe svc web -n demoEvents 是 Kubernetes 排错里非常重要的一层。镜像拉取失败、调度失败、探针失败、挂载失败、Service 后端为空,很多信息都先出现在 Events 里。
bash
# 按时间排序查看 namespace 里的事件
kubectl get events -n demo --sort-by=.lastTimestamp
# 只看某个 Pod 相关事件
kubectl get events -n demo \
--field-selector involvedObject.kind=Pod,involvedObject.name=<pod-name>kubectl logs 看的是容器输出,Events 看的是 Kubernetes 对这个对象做了什么、失败在哪里。Pod 没启动时日志可能为空,此时 Events 往往更有用。
六、namespace 和默认命名空间
namespace 用来隔离同类资源名称和权限范围。Pod、Service、Deployment、ConfigMap、Secret、PVC 都是 namespaced 资源;Node、PV、StorageClass、ClusterRole 是集群级资源。
bash
kubectl get ns
kubectl create ns demo
kubectl config set-context --current --namespace=demo
kubectl get pod排查时经常出现“资源明明创建了却查不到”的情况,本质是 namespace 不一致。命令里显式加 -n 更清楚:
bash
kubectl get deploy -n demo
kubectl get svc -n demo
kubectl get pod -n demo跨 namespace 引用不是所有资源都支持。比如 Pod 引用 ConfigMap 和 Secret 时,默认只能引用同 namespace 下的对象;Ingress、HTTPRoute、Service 之间的跨 namespace 关系也受字段和权限约束。
七、输出格式和常用定位
kubectl 支持多种输出格式:
bash
kubectl get pod -n demo -o wide
kubectl get pod -n demo -o yaml
kubectl get pod -n demo -o jsonpath='{.items[*].metadata.name}'
kubectl get deploy web -n demo -o jsonpath='{.status.availableReplicas}'常用定位方式:
| 场景 | 命令 |
|---|---|
| 按标签找资源 | kubectl get pod -l app=web -n demo |
| 看 Pod 落在哪个节点 | kubectl get pod -o wide -n demo |
| 看 Service 后端 | kubectl get endpointslice -n demo -l kubernetes.io/service-name=web |
| 看镜像和启动命令 | kubectl get pod <pod> -n demo -o yaml |
| 看最近事件 | kubectl get events -n demo --sort-by=.lastTimestamp |
jsonpath 适合脚本里取单个字段,但表达复杂时可读性会下降。日常排查里,-o yaml 加搜索通常更直观。
八、删除和回收
删除资源时要分清“删的是控制器”还是“删的是控制器创建出来的 Pod”。
bash
kubectl delete pod <pod-name> -n demo
kubectl delete deploy web -n demo
kubectl delete -f web.yaml删除 Pod 时,如果它受 Deployment、ReplicaSet、StatefulSet、DaemonSet 管理,控制器会再创建新的 Pod。删除控制器时,子资源通常会跟随 ownerReference 被垃圾回收。PVC、PV、LoadBalancer、外部云资源等对象的回收还受各自策略影响,不能只看命令执行成功。
资源关系和垃圾回收细节见 标签与资源关系。