Skip to content

kubectl 与 YAML

Kubernetes 的日常操作主要围绕 API 对象展开。kubectl 是访问 API Server 的客户端,YAML 是描述资源期望状态的文件格式。命令行负责提交、查询、对比和排错,YAML 负责把资源对象记录成可复用、可审查、可回滚的文本。

资源对象可以近似看成一份结构化记录:apiVersionkind 决定资源类型,metadata 描述身份,spec 写期望状态,status 由控制器回写当前状态。排查时经常就是对比 specstatus:文件里希望有 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@k3s

server 是 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

几个字段的分工:

字段说明
apiVersionAPI 组和版本,决定这个资源由哪个 API 提供
kind资源类型,比如 Pod、Service、Deployment
metadata.name同一 namespace 内的资源名称
metadata.namespace命名空间,不写时通常落到 default
metadata.labels可被 selector 匹配的标签
spec期望状态,由使用者提交
status当前状态,由控制器或 kubelet 回写

源文件里通常不写 status。从集群导出的完整 YAML 会包含 uidresourceVersionmanagedFieldsstatus 等运行期字段,这些字段不适合直接复制回 Git 仓库。

三、API 组和版本

Kubernetes 的资源不全在同一个 API 里。核心资源在 v1,工作负载在 apps/v1,批处理任务在 batch/v1,网络策略在 networking.k8s.io/v1

apiVersion常见 kind
v1Pod、Service、ConfigMap、Secret、PersistentVolumeClaim
apps/v1Deployment、StatefulSet、DaemonSet
batch/v1Job、CronJob
networking.k8s.io/v1Ingress、NetworkPolicy
gateway.networking.k8s.io/v1Gateway、HTTPRoute
storage.k8s.io/v1StorageClass
rbac.authorization.k8s.io/v1Role、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.jobTemplate

CRD 安装后,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 demo

diff 对变更前确认很有用。比如改了镜像版本、环境变量、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=web

describe 会把对象详情、事件和关联状态放在一起:

bash
kubectl describe pod <pod-name> -n demo
kubectl describe deploy web -n demo
kubectl describe svc web -n demo

Events 是 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、外部云资源等对象的回收还受各自策略影响,不能只看命令执行成功。

资源关系和垃圾回收细节见 标签与资源关系