[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6WXFQWX080RWHGA2B1QCTEP":3,"skill-same:01M6WXFQWX080RWHGA2B1QCTEP":91},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":14,"repositoryHtmlUrl":59,"repositoryHomepageUrl":60,"ownerHtmlUrl":61,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":62,"install":63,"resources":76},"01M6WXFQWX080RWHGA2B1QCTEP","kubernetes-basics",null,"Kubernetes cluster management — resources, networking, storage, Helm, troubleshooting. Use when writing Kubernetes manifests, running kubectl or helm, debugging pods and services, or configuring ingress, DNS, storage, or network policies.","projectious-work\u002Fprocesskit","projectious-work","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F263889726?v=4","01M6N97TJJ118WQ35CHRV8RD0E","projectious.work","01M6N97TPWJPF0BMKYQ4PBY5W8",0,"MIT","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"kubernetes","kubernetes basics","basics","running","writing","when","v1","manifests","cluster management","cluster","resources","devops","use","work","helm","network","dns","services","debugging","storage","2026-11-10 10:12:30",false,"---\nname: kubernetes-basics\ndescription: |\n  Kubernetes cluster management — resources, networking, storage, Helm, troubleshooting. Use when writing Kubernetes manifests, running kubectl or helm, debugging pods and services, or configuring ingress, DNS, storage, or network policies.\nmetadata:\n  processkit:\n    apiVersion: processkit.projectious.work\u002Fv1\n    id: SKILL-kubernetes-basics\n    version: \"1.1.0\"\n    created: 2026-04-06T00:00:00Z\n    category: devops\n---\n\n# Kubernetes Basics\n\n## Intro\n\nKubernetes is a declarative system: you write manifests, the API\nserver stores them in etcd, and controllers reconcile reality toward\nthat desired state. Confirm the active context, prefer declarative\n`apply` over imperative commands, and always check events and logs\nbefore poking at YAML.\n\n## Overview\n\n### Cluster context\n\nAlways confirm the active cluster and namespace before making changes:\n\n```bash\nkubectl config current-context\nkubectl config get-contexts\nkubectl get ns\n```\n\nSwitch context\u002Fnamespace explicitly rather than relying on defaults:\n\n```bash\nkubectl config use-context \u003Cname>\nkubectl config set-context --current --namespace=\u003Cns>\n```\n\n### Core resources\n\nUse Deployments for stateless workloads and StatefulSets for stateful\nones. Never create bare Pods in production — they are not rescheduled\non failure.\n\n- **Pod** — smallest deployable unit, one or more containers\n- **Deployment** — manages ReplicaSets, handles rolling updates\n- **StatefulSet** — stable network identity and persistent storage\n  per replica\n- **DaemonSet** — one pod per node (logging, monitoring agents)\n- **Job \u002F CronJob** — run-to-completion and scheduled tasks\n\n### Networking\n\nServices expose pods internally or externally:\n\n- **ClusterIP** (default) — internal only\n- **NodePort** — exposes on each node's IP at a static port\n- **LoadBalancer** — provisions an external LB (cloud providers)\n\nIngress routes external HTTP\u002FHTTPS to services by host\u002Fpath. Always\nset `ingressClassName`. Pods resolve services via DNS at\n`\u003Csvc>.\u003Cns>.svc.cluster.local`.\n\nNetwork policies default to allow-all. Define explicit ingress\u002Fegress\nrules to restrict traffic between namespaces or pods.\n\n### Storage\n\n- **PersistentVolume (PV)** — cluster-level storage resource\n- **PersistentVolumeClaim (PVC)** — namespace-scoped request for\n  storage\n- **StorageClass** — dynamic provisioning template\n\nUse `storageClassName` in PVCs. For StatefulSets, use\n`volumeClaimTemplates` to create per-replica PVCs automatically.\nAlways set `accessModes` and `resources.requests.storage`.\n\n### Configuration\n\n- **ConfigMap** — non-sensitive key-value config; mount as files or\n  env vars\n- **Secret** — base64-encoded sensitive data; same mount options\n\nPrefer mounting as volumes over env vars for config files. Use\n`kubectl create secret generic` for quick creation. In production, use\nan external secrets operator or sealed-secrets.\n\n### Helm\n\nHelm manages templated releases:\n\n```bash\nhelm repo add \u003Cname> \u003Curl>\nhelm repo update\nhelm search repo \u003Cchart>\nhelm install \u003Crelease> \u003Cchart> -n \u003Cns> --create-namespace -f values.yaml\nhelm upgrade \u003Crelease> \u003Cchart> -n \u003Cns> -f values.yaml\nhelm rollback \u003Crelease> \u003Crevision> -n \u003Cns>\nhelm list -n \u003Cns>\nhelm uninstall \u003Crelease> -n \u003Cns>\n```\n\nInspect before installing: `helm template` to render, `helm show\nvalues` for defaults. Pin chart versions in CI with `--version`.\n\n### Troubleshooting order\n\nWhen debugging, start broad and narrow down:\n\n1. `kubectl get events --sort-by=.lastTimestamp` — cluster events\n2. `kubectl describe pod \u003Cpod>` — scheduling, image pull, probes\n3. `kubectl logs \u003Cpod> [-c container] [--previous]` — app logs\n4. `kubectl exec -it \u003Cpod> -- sh` — interactive shell\n5. `kubectl top pod` \u002F `kubectl top node` — resource usage\n\n### Applying changes safely\n\nAlways `kubectl diff` before `kubectl apply` to preview changes.\nPrefer declarative `apply` over imperative `create`\u002F`edit`. Use\n`--dry-run=client -o yaml` to validate without submitting. For\nproduction rollouts, watch with `kubectl rollout status` and reach\nfor `kubectl rollout undo` if something goes wrong.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Not confirming the active context before making changes.** `kubectl apply -f` operates against whichever cluster context is currently active. Running a destructive operation in production because the context was left pointing at prod from a previous debugging session is among the most common Kubernetes incidents. Always run `kubectl config current-context` before any write operation, and use a tool or alias that shows the context in the prompt.\n- **Bare Pods in production instead of Deployments.** A bare Pod that crashes is not rescheduled — it stays in `Error` or `CrashLoopBackOff` until manually deleted and recreated. A Deployment's ReplicaSet controller reschedules it automatically and supports rolling updates and rollbacks. Never create bare Pods for any workload that must stay up.\n- **Missing readiness probes on Services.** A Service will send traffic to all pods that match its selector, including pods that are starting, initializing, or currently unhealthy but have not yet been killed by the liveness probe. Without a readiness probe, traffic hits unready pods and users see errors. The liveness probe kills bad pods; the readiness probe keeps traffic away from them until they are ready.\n- **No resource requests or limits.** Without `resources.requests`, the scheduler has no signal for node placement and a noisy pod can be scheduled on an already-overloaded node. Without `resources.limits`, a memory-leaking pod can OOMKill neighboring pods on the same node. Set both on every container; start with generous values, observe with `kubectl top`, then tighten.\n- **`latest` image tags in Deployment manifests.** A Deployment with `image: myapp:latest` will pull whatever `latest` resolves to at each restart — silently deploying a different version than the one you tested. Always pin to a specific immutable tag (typically a Git SHA or build number) so rollouts are deterministic and `kubectl rollout undo` restores the exact previous version.\n- **Blind `kubectl apply` without reviewing `kubectl diff` first.** `kubectl apply` without a preceding `kubectl diff` is a production change made without preview. Fields set out-of-band (via `kubectl edit`, autoscalers, or admission webhooks) may be silently overwritten. Always `kubectl diff -f manifest.yaml` before `kubectl apply -f manifest.yaml` in production.\n- **Using `-target` or imperative `kubectl edit` as a normal workflow.** Imperative edits (`kubectl edit`, `kubectl scale`) and `-target` applies produce configuration that diverges from the version-controlled manifests. The next declarative apply will overwrite the change without warning. All production changes must go through version-controlled manifests applied via CI\u002FCD.\n\n## Full reference\n\n### Control plane architecture\n\n```\nkubectl apply -f deployment.yaml\n    |\n    v\nAPI Server: validates, stores in etcd\n    |\n    v\nDeployment controller -> ReplicaSet -> Pod objects (Pending)\n    |\n    v\nScheduler: assigns Pods to nodes (filtering + scoring)\n    |\n    v\nkubelet: pulls image, starts containers on the node\n    |\n    v\nkube-proxy: updates iptables\u002FIPVS rules for Service endpoints\n```\n\nComponents:\n\n- **API server** — front door; validates and persists to etcd\n- **etcd** — distributed KV store holding all cluster state; HA with\n  3 or 5 members; back up with `etcdctl snapshot save`\n- **Scheduler** — filters then scores nodes for unscheduled pods\n- **Controller manager** — runs reconcile loops (ReplicaSet,\n  Deployment, Node, Job, Endpoint, ServiceAccount controllers)\n- **kubelet** — node agent; manages Pod lifecycle via the CRI\n- **kube-proxy** — programs iptables\u002FIPVS\u002Fnftables for Services\n- **Container runtime** — containerd or CRI-O; Docker Engine was\n  removed as a direct runtime in v1.24\n\n### Resource YAML cheatsheet\n\n**Deployment with resources, probes, config, storage:**\n\n```yaml\napiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: myapp\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: myapp\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxSurge: 1\n      maxUnavailable: 0\n  template:\n    metadata:\n      labels:\n        app: myapp\n    spec:\n      containers:\n        - name: app\n          image: myapp:1.0.0\n          ports:\n            - containerPort: 8080\n          resources:\n            requests:\n              cpu: 100m\n              memory: 128Mi\n            limits:\n              cpu: 500m\n              memory: 256Mi\n          livenessProbe:\n            httpGet:\n              path: \u002Fhealthz\n              port: 8080\n            initialDelaySeconds: 5\n            periodSeconds: 10\n          readinessProbe:\n            httpGet:\n              path: \u002Fready\n              port: 8080\n            initialDelaySeconds: 3\n            periodSeconds: 5\n          envFrom:\n            - configMapRef:\n                name: myapp-config\n          volumeMounts:\n            - name: data\n              mountPath: \u002Fdata\n      volumes:\n        - name: data\n          persistentVolumeClaim:\n            claimName: myapp-data\n```\n\n**Service types:**\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: myapp\nspec:\n  selector:\n    app: myapp\n  ports:\n    - port: 80\n      targetPort: 8080\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: myapp-lb\nspec:\n  type: LoadBalancer\n  selector:\n    app: myapp\n  ports:\n    - port: 443\n      targetPort: 8080\n```\n\n**Ingress with TLS:**\n\n```yaml\napiVersion: networking.k8s.io\u002Fv1\nkind: Ingress\nmetadata:\n  name: myapp\nspec:\n  ingressClassName: nginx\n  tls:\n    - hosts: [myapp.example.com]\n      secretName: myapp-tls\n  rules:\n    - host: myapp.example.com\n      http:\n        paths:\n          - path: \u002F\n            pathType: Prefix\n            backend:\n              service:\n                name: myapp\n                port:\n                  number: 80\n```\n\n**ConfigMap, Secret, PVC:**\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: myapp-config\ndata:\n  APP_ENV: production\n  LOG_LEVEL: info\n---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: myapp-secret\ntype: Opaque\nstringData:\n  DB_PASSWORD: s3cret\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: myapp-data\nspec:\n  accessModes: [ReadWriteOnce]\n  storageClassName: standard\n  resources:\n    requests:\n      storage: 10Gi\n```\n\n**Job and CronJob:**\n\n```yaml\napiVersion: batch\u002Fv1\nkind: CronJob\nmetadata:\n  name: nightly-backup\nspec:\n  schedule: \"0 2 * * *\"\n  concurrencyPolicy: Forbid\n  successfulJobsHistoryLimit: 3\n  failedJobsHistoryLimit: 3\n  jobTemplate:\n    spec:\n      template:\n        spec:\n          restartPolicy: OnFailure\n          containers:\n            - name: backup\n              image: myapp:1.0.0\n              command: [\".\u002Fbackup.sh\"]\n```\n\n### kubectl cheatsheet\n\n```bash\n# Viewing\nkubectl get pods -n \u003Cns> -o wide\nkubectl get all -n \u003Cns>\nkubectl describe pod \u003Cpod> -n \u003Cns>\nkubectl get events --sort-by=.lastTimestamp\n\n# Applying\nkubectl apply -f manifest.yaml\nkubectl apply -f .\u002Fmanifests\u002F -R\nkubectl diff -f manifest.yaml\nkubectl create secret generic db \\\n  --from-literal=password=s3cret -n \u003Cns>\n\n# Debugging\nkubectl logs \u003Cpod> -n \u003Cns>\nkubectl logs \u003Cpod> -c \u003Ccontainer> --previous\nkubectl logs -l app=myapp -n \u003Cns> --tail=100\nkubectl exec -it \u003Cpod> -n \u003Cns> -- sh\nkubectl port-forward svc\u002Fmyapp 8080:80 -n \u003Cns>\nkubectl top pod -n \u003Cns>\nkubectl top node\n\n# Rollouts\nkubectl scale deploy myapp --replicas=5 -n \u003Cns>\nkubectl rollout status deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout history deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout undo deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout restart deploy\u002Fmyapp -n \u003Cns>\n\n# Deleting\nkubectl delete -f manifest.yaml\nkubectl delete pod \u003Cpod> --grace-period=0 --force\n```\n\n### Troubleshooting patterns\n\n**Pod Pending (not scheduled).** Read the events:\n\n```bash\nkubectl describe pod \u003Cpod> -n \u003Cns>   # look at Events section\n```\n\n| Event message | Cause | Fix |\n|---|---|---|\n| `Insufficient cpu\u002Fmemory` | Node full | Scale cluster, reduce requests |\n| `node(s) had taint` | Taint\u002Ftoleration mismatch | Add toleration or remove taint |\n| `no persistent volumes available` | PVC cannot bind | Check PV, StorageClass, access modes |\n| `didn't match Pod's node affinity\u002Fselector` | Scheduling constraint | Fix selector or label nodes |\n\n**CrashLoopBackOff.** Get logs from the crashed container:\n\n```bash\nkubectl logs \u003Cpod> -n \u003Cns> --previous\nkubectl get pod \u003Cpod> -n \u003Cns> \\\n  -o jsonpath='{.status.containerStatuses[0].lastState.terminated}'\n```\n\nExit code 137 is OOMKilled — raise the memory limit. Exit code 1 with\nno logs usually means a bad `command`\u002F`args`. A failing liveness\nprobe restarts the container on a loop.\n\n**ImagePullBackOff.** Almost always a wrong tag, a private registry\nwithout `imagePullSecrets`, or Docker Hub rate limiting:\n\n```bash\nkubectl create secret docker-registry regcred \\\n  --docker-server=ghcr.io \\\n  --docker-username=\u003Cuser> \\\n  --docker-password=\u003Ctoken> \\\n  -n \u003Cns>\n```\n\nReference it in the pod spec via `spec.imagePullSecrets`.\n\n**Service not reachable.** Endpoints tell you if the selector matches\nany pods:\n\n```bash\nkubectl get svc \u003Csvc> -n \u003Cns>\nkubectl get endpoints \u003Csvc> -n \u003Cns>\n# Empty endpoints = selector mismatch OR no pods are Ready\nkubectl get pods -n \u003Cns> --show-labels\nkubectl run curl --image=curlimages\u002Fcurl --restart=Never --rm -it -- \\\n  curl -v http:\u002F\u002F\u003Csvc>.\u003Cns>.svc.cluster.local:\u003Cport>\n```\n\nCheck: selector labels match pod labels exactly, `targetPort` matches\nthe container's listening port, readiness probe is passing,\nNetworkPolicy is not blocking.\n\n**DNS issues inside the cluster.**\n\n```bash\nkubectl run dnstest --image=busybox:1.36 --restart=Never --rm -it -- \\\n  nslookup \u003Csvc>.\u003Cns>.svc.cluster.local\nkubectl get pods -n kube-system -l k8s-app=kube-dns\nkubectl logs -n kube-system -l k8s-app=kube-dns --tail=50\n```\n\n`ndots:5` can cause slow external lookups — use a fully-qualified name\nwith a trailing dot to force a direct lookup.\n\n**Resource limits and OOM.**\n\n- `requests` = typical usage, used for scheduling\n- `limits` = maximum allowed; memory overrun is OOMKill, CPU overrun\n  is throttling\n- Start with generous limits, monitor with `kubectl top`, then tighten\n- CPU limits are often best omitted — throttling is less harmful than\n  OOMKill\n\n```bash\nkubectl top pod -n \u003Cns> --containers\nkubectl get pods -n \u003Cns> -o json | \\\n  jq '.items[] | select(.status.containerStatuses[]?.lastState.terminated.reason==\"OOMKilled\") | .metadata.name'\n```\n\n**Node pressure and eviction.**\n\n```bash\nkubectl describe node \u003Cnode> | grep -A 5 Conditions\n# Common: MemoryPressure, DiskPressure, PIDPressure\nkubectl get pods -n \u003Cns> --field-selector=status.phase=Failed | grep Evicted\n```\n\n### Helm upgrade with rollback safety\n\n```bash\nhelm upgrade myrelease mychart\u002Fapp -n prod -f prod-values.yaml \\\n  --atomic --timeout 5m\n# --atomic auto-rolls back on failure\nhelm history myrelease -n prod\n```\n\n### Debug containers and RBAC checks\n\n```bash\n# Ephemeral debug container (K8s 1.23+)\nkubectl debug -it \u003Cpod> -n \u003Cns> --image=busybox:1.36 --target=\u003Ccontainer>\n\n# Copy a running pod\nkubectl debug \u003Cpod> -n \u003Cns> --copy-to=debug-pod --container=app -- sh\n\n# RBAC checks\nkubectl auth can-i create deployments -n \u003Cns>\nkubectl auth can-i '*' '*' --all-namespaces\nkubectl auth can-i get pods --as=system:serviceaccount:\u003Cns>:\u003Csa>\n```\n\n### Anti-patterns\n\n- **Bare Pods in production** — use Deployments or StatefulSets\n- **Missing readiness probes** — Services will send traffic to pods\n  that aren't ready\n- **No resource requests\u002Flimits** — scheduler has nothing to go on,\n  noisy neighbors can starve you\n- **Hardcoded namespace in manifests** — pass via `-n` or kustomize\n- **`latest` image tags** — rollouts become non-deterministic\n- **Ignoring `kubectl diff`** — blind `apply` can silently remove\n  fields that were set out-of-band\n","# Kubernetes Basics\n\n## Intro\n\nKubernetes is a declarative system: you write manifests, the API\nserver stores them in etcd, and controllers reconcile reality toward\nthat desired state. Confirm the active context, prefer declarative\n`apply` over imperative commands, and always check events and logs\nbefore poking at YAML.\n\n## Overview\n\n### Cluster context\n\nAlways confirm the active cluster and namespace before making changes:\n\n```bash\nkubectl config current-context\nkubectl config get-contexts\nkubectl get ns\n```\n\nSwitch context\u002Fnamespace explicitly rather than relying on defaults:\n\n```bash\nkubectl config use-context \u003Cname>\nkubectl config set-context --current --namespace=\u003Cns>\n```\n\n### Core resources\n\nUse Deployments for stateless workloads and StatefulSets for stateful\nones. Never create bare Pods in production — they are not rescheduled\non failure.\n\n- **Pod** — smallest deployable unit, one or more containers\n- **Deployment** — manages ReplicaSets, handles rolling updates\n- **StatefulSet** — stable network identity and persistent storage\n  per replica\n- **DaemonSet** — one pod per node (logging, monitoring agents)\n- **Job \u002F CronJob** — run-to-completion and scheduled tasks\n\n### Networking\n\nServices expose pods internally or externally:\n\n- **ClusterIP** (default) — internal only\n- **NodePort** — exposes on each node's IP at a static port\n- **LoadBalancer** — provisions an external LB (cloud providers)\n\nIngress routes external HTTP\u002FHTTPS to services by host\u002Fpath. Always\nset `ingressClassName`. Pods resolve services via DNS at\n`\u003Csvc>.\u003Cns>.svc.cluster.local`.\n\nNetwork policies default to allow-all. Define explicit ingress\u002Fegress\nrules to restrict traffic between namespaces or pods.\n\n### Storage\n\n- **PersistentVolume (PV)** — cluster-level storage resource\n- **PersistentVolumeClaim (PVC)** — namespace-scoped request for\n  storage\n- **StorageClass** — dynamic provisioning template\n\nUse `storageClassName` in PVCs. For StatefulSets, use\n`volumeClaimTemplates` to create per-replica PVCs automatically.\nAlways set `accessModes` and `resources.requests.storage`.\n\n### Configuration\n\n- **ConfigMap** — non-sensitive key-value config; mount as files or\n  env vars\n- **Secret** — base64-encoded sensitive data; same mount options\n\nPrefer mounting as volumes over env vars for config files. Use\n`kubectl create secret generic` for quick creation. In production, use\nan external secrets operator or sealed-secrets.\n\n### Helm\n\nHelm manages templated releases:\n\n```bash\nhelm repo add \u003Cname> \u003Curl>\nhelm repo update\nhelm search repo \u003Cchart>\nhelm install \u003Crelease> \u003Cchart> -n \u003Cns> --create-namespace -f values.yaml\nhelm upgrade \u003Crelease> \u003Cchart> -n \u003Cns> -f values.yaml\nhelm rollback \u003Crelease> \u003Crevision> -n \u003Cns>\nhelm list -n \u003Cns>\nhelm uninstall \u003Crelease> -n \u003Cns>\n```\n\nInspect before installing: `helm template` to render, `helm show\nvalues` for defaults. Pin chart versions in CI with `--version`.\n\n### Troubleshooting order\n\nWhen debugging, start broad and narrow down:\n\n1. `kubectl get events --sort-by=.lastTimestamp` — cluster events\n2. `kubectl describe pod \u003Cpod>` — scheduling, image pull, probes\n3. `kubectl logs \u003Cpod> [-c container] [--previous]` — app logs\n4. `kubectl exec -it \u003Cpod> -- sh` — interactive shell\n5. `kubectl top pod` \u002F `kubectl top node` — resource usage\n\n### Applying changes safely\n\nAlways `kubectl diff` before `kubectl apply` to preview changes.\nPrefer declarative `apply` over imperative `create`\u002F`edit`. Use\n`--dry-run=client -o yaml` to validate without submitting. For\nproduction rollouts, watch with `kubectl rollout status` and reach\nfor `kubectl rollout undo` if something goes wrong.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **Not confirming the active context before making changes.** `kubectl apply -f` operates against whichever cluster context is currently active. Running a destructive operation in production because the context was left pointing at prod from a previous debugging session is among the most common Kubernetes incidents. Always run `kubectl config current-context` before any write operation, and use a tool or alias that shows the context in the prompt.\n- **Bare Pods in production instead of Deployments.** A bare Pod that crashes is not rescheduled — it stays in `Error` or `CrashLoopBackOff` until manually deleted and recreated. A Deployment's ReplicaSet controller reschedules it automatically and supports rolling updates and rollbacks. Never create bare Pods for any workload that must stay up.\n- **Missing readiness probes on Services.** A Service will send traffic to all pods that match its selector, including pods that are starting, initializing, or currently unhealthy but have not yet been killed by the liveness probe. Without a readiness probe, traffic hits unready pods and users see errors. The liveness probe kills bad pods; the readiness probe keeps traffic away from them until they are ready.\n- **No resource requests or limits.** Without `resources.requests`, the scheduler has no signal for node placement and a noisy pod can be scheduled on an already-overloaded node. Without `resources.limits`, a memory-leaking pod can OOMKill neighboring pods on the same node. Set both on every container; start with generous values, observe with `kubectl top`, then tighten.\n- **`latest` image tags in Deployment manifests.** A Deployment with `image: myapp:latest` will pull whatever `latest` resolves to at each restart — silently deploying a different version than the one you tested. Always pin to a specific immutable tag (typically a Git SHA or build number) so rollouts are deterministic and `kubectl rollout undo` restores the exact previous version.\n- **Blind `kubectl apply` without reviewing `kubectl diff` first.** `kubectl apply` without a preceding `kubectl diff` is a production change made without preview. Fields set out-of-band (via `kubectl edit`, autoscalers, or admission webhooks) may be silently overwritten. Always `kubectl diff -f manifest.yaml` before `kubectl apply -f manifest.yaml` in production.\n- **Using `-target` or imperative `kubectl edit` as a normal workflow.** Imperative edits (`kubectl edit`, `kubectl scale`) and `-target` applies produce configuration that diverges from the version-controlled manifests. The next declarative apply will overwrite the change without warning. All production changes must go through version-controlled manifests applied via CI\u002FCD.\n\n## Full reference\n\n### Control plane architecture\n\n```\nkubectl apply -f deployment.yaml\n    |\n    v\nAPI Server: validates, stores in etcd\n    |\n    v\nDeployment controller -> ReplicaSet -> Pod objects (Pending)\n    |\n    v\nScheduler: assigns Pods to nodes (filtering + scoring)\n    |\n    v\nkubelet: pulls image, starts containers on the node\n    |\n    v\nkube-proxy: updates iptables\u002FIPVS rules for Service endpoints\n```\n\nComponents:\n\n- **API server** — front door; validates and persists to etcd\n- **etcd** — distributed KV store holding all cluster state; HA with\n  3 or 5 members; back up with `etcdctl snapshot save`\n- **Scheduler** — filters then scores nodes for unscheduled pods\n- **Controller manager** — runs reconcile loops (ReplicaSet,\n  Deployment, Node, Job, Endpoint, ServiceAccount controllers)\n- **kubelet** — node agent; manages Pod lifecycle via the CRI\n- **kube-proxy** — programs iptables\u002FIPVS\u002Fnftables for Services\n- **Container runtime** — containerd or CRI-O; Docker Engine was\n  removed as a direct runtime in v1.24\n\n### Resource YAML cheatsheet\n\n**Deployment with resources, probes, config, storage:**\n\n```yaml\napiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: myapp\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: myapp\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxSurge: 1\n      maxUnavailable: 0\n  template:\n    metadata:\n      labels:\n        app: myapp\n    spec:\n      containers:\n        - name: app\n          image: myapp:1.0.0\n          ports:\n            - containerPort: 8080\n          resources:\n            requests:\n              cpu: 100m\n              memory: 128Mi\n            limits:\n              cpu: 500m\n              memory: 256Mi\n          livenessProbe:\n            httpGet:\n              path: \u002Fhealthz\n              port: 8080\n            initialDelaySeconds: 5\n            periodSeconds: 10\n          readinessProbe:\n            httpGet:\n              path: \u002Fready\n              port: 8080\n            initialDelaySeconds: 3\n            periodSeconds: 5\n          envFrom:\n            - configMapRef:\n                name: myapp-config\n          volumeMounts:\n            - name: data\n              mountPath: \u002Fdata\n      volumes:\n        - name: data\n          persistentVolumeClaim:\n            claimName: myapp-data\n```\n\n**Service types:**\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: myapp\nspec:\n  selector:\n    app: myapp\n  ports:\n    - port: 80\n      targetPort: 8080\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: myapp-lb\nspec:\n  type: LoadBalancer\n  selector:\n    app: myapp\n  ports:\n    - port: 443\n      targetPort: 8080\n```\n\n**Ingress with TLS:**\n\n```yaml\napiVersion: networking.k8s.io\u002Fv1\nkind: Ingress\nmetadata:\n  name: myapp\nspec:\n  ingressClassName: nginx\n  tls:\n    - hosts: [myapp.example.com]\n      secretName: myapp-tls\n  rules:\n    - host: myapp.example.com\n      http:\n        paths:\n          - path: \u002F\n            pathType: Prefix\n            backend:\n              service:\n                name: myapp\n                port:\n                  number: 80\n```\n\n**ConfigMap, Secret, PVC:**\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: myapp-config\ndata:\n  APP_ENV: production\n  LOG_LEVEL: info\n---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: myapp-secret\ntype: Opaque\nstringData:\n  DB_PASSWORD: s3cret\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: myapp-data\nspec:\n  accessModes: [ReadWriteOnce]\n  storageClassName: standard\n  resources:\n    requests:\n      storage: 10Gi\n```\n\n**Job and CronJob:**\n\n```yaml\napiVersion: batch\u002Fv1\nkind: CronJob\nmetadata:\n  name: nightly-backup\nspec:\n  schedule: \"0 2 * * *\"\n  concurrencyPolicy: Forbid\n  successfulJobsHistoryLimit: 3\n  failedJobsHistoryLimit: 3\n  jobTemplate:\n    spec:\n      template:\n        spec:\n          restartPolicy: OnFailure\n          containers:\n            - name: backup\n              image: myapp:1.0.0\n              command: [\".\u002Fbackup.sh\"]\n```\n\n### kubectl cheatsheet\n\n```bash\n# Viewing\nkubectl get pods -n \u003Cns> -o wide\nkubectl get all -n \u003Cns>\nkubectl describe pod \u003Cpod> -n \u003Cns>\nkubectl get events --sort-by=.lastTimestamp\n\n# Applying\nkubectl apply -f manifest.yaml\nkubectl apply -f .\u002Fmanifests\u002F -R\nkubectl diff -f manifest.yaml\nkubectl create secret generic db \\\n  --from-literal=password=s3cret -n \u003Cns>\n\n# Debugging\nkubectl logs \u003Cpod> -n \u003Cns>\nkubectl logs \u003Cpod> -c \u003Ccontainer> --previous\nkubectl logs -l app=myapp -n \u003Cns> --tail=100\nkubectl exec -it \u003Cpod> -n \u003Cns> -- sh\nkubectl port-forward svc\u002Fmyapp 8080:80 -n \u003Cns>\nkubectl top pod -n \u003Cns>\nkubectl top node\n\n# Rollouts\nkubectl scale deploy myapp --replicas=5 -n \u003Cns>\nkubectl rollout status deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout history deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout undo deploy\u002Fmyapp -n \u003Cns>\nkubectl rollout restart deploy\u002Fmyapp -n \u003Cns>\n\n# Deleting\nkubectl delete -f manifest.yaml\nkubectl delete pod \u003Cpod> --grace-period=0 --force\n```\n\n### Troubleshooting patterns\n\n**Pod Pending (not scheduled).** Read the events:\n\n```bash\nkubectl describe pod \u003Cpod> -n \u003Cns>   # look at Events section\n```\n\n| Event message | Cause | Fix |\n|---|---|---|\n| `Insufficient cpu\u002Fmemory` | Node full | Scale cluster, reduce requests |\n| `node(s) had taint` | Taint\u002Ftoleration mismatch | Add toleration or remove taint |\n| `no persistent volumes available` | PVC cannot bind | Check PV, StorageClass, access modes |\n| `didn't match Pod's node affinity\u002Fselector` | Scheduling constraint | Fix selector or label nodes |\n\n**CrashLoopBackOff.** Get logs from the crashed container:\n\n```bash\nkubectl logs \u003Cpod> -n \u003Cns> --previous\nkubectl get pod \u003Cpod> -n \u003Cns> \\\n  -o jsonpath='{.status.containerStatuses[0].lastState.terminated}'\n```\n\nExit code 137 is OOMKilled — raise the memory limit. Exit code 1 with\nno logs usually means a bad `command`\u002F`args`. A failing liveness\nprobe restarts the container on a loop.\n\n**ImagePullBackOff.** Almost always a wrong tag, a private registry\nwithout `imagePullSecrets`, or Docker Hub rate limiting:\n\n```bash\nkubectl create secret docker-registry regcred \\\n  --docker-server=ghcr.io \\\n  --docker-username=\u003Cuser> \\\n  --docker-password=\u003Ctoken> \\\n  -n \u003Cns>\n```\n\nReference it in the pod spec via `spec.imagePullSecrets`.\n\n**Service not reachable.** Endpoints tell you if the selector matches\nany pods:\n\n```bash\nkubectl get svc \u003Csvc> -n \u003Cns>\nkubectl get endpoints \u003Csvc> -n \u003Cns>\n# Empty endpoints = selector mismatch OR no pods are Ready\nkubectl get pods -n \u003Cns> --show-labels\nkubectl run curl --image=curlimages\u002Fcurl --restart=Never --rm -it -- \\\n  curl -v http:\u002F\u002F\u003Csvc>.\u003Cns>.svc.cluster.local:\u003Cport>\n```\n\nCheck: selector labels match pod labels exactly, `targetPort` matches\nthe container's listening port, readiness probe is passing,\nNetworkPolicy is not blocking.\n\n**DNS issues inside the cluster.**\n\n```bash\nkubectl run dnstest --image=busybox:1.36 --restart=Never --rm -it -- \\\n  nslookup \u003Csvc>.\u003Cns>.svc.cluster.local\nkubectl get pods -n kube-system -l k8s-app=kube-dns\nkubectl logs -n kube-system -l k8s-app=kube-dns --tail=50\n```\n\n`ndots:5` can cause slow external lookups — use a fully-qualified name\nwith a trailing dot to force a direct lookup.\n\n**Resource limits and OOM.**\n\n- `requests` = typical usage, used for scheduling\n- `limits` = maximum allowed; memory overrun is OOMKill, CPU overrun\n  is throttling\n- Start with generous limits, monitor with `kubectl top`, then tighten\n- CPU limits are often best omitted — throttling is less harmful than\n  OOMKill\n\n```bash\nkubectl top pod -n \u003Cns> --containers\nkubectl get pods -n \u003Cns> -o json | \\\n  jq '.items[] | select(.status.containerStatuses[]?.lastState.terminated.reason==\"OOMKilled\") | .metadata.name'\n```\n\n**Node pressure and eviction.**\n\n```bash\nkubectl describe node \u003Cnode> | grep -A 5 Conditions\n# Common: MemoryPressure, DiskPressure, PIDPressure\nkubectl get pods -n \u003Cns> --field-selector=status.phase=Failed | grep Evicted\n```\n\n### Helm upgrade with rollback safety\n\n```bash\nhelm upgrade myrelease mychart\u002Fapp -n prod -f prod-values.yaml \\\n  --atomic --timeout 5m\n# --atomic auto-rolls back on failure\nhelm history myrelease -n prod\n```\n\n### Debug containers and RBAC checks\n\n```bash\n# Ephemeral debug container (K8s 1.23+)\nkubectl debug -it \u003Cpod> -n \u003Cns> --image=busybox:1.36 --target=\u003Ccontainer>\n\n# Copy a running pod\nkubectl debug \u003Cpod> -n \u003Cns> --copy-to=debug-pod --container=app -- sh\n\n# RBAC checks\nkubectl auth can-i create deployments -n \u003Cns>\nkubectl auth can-i '*' '*' --all-namespaces\nkubectl auth can-i get pods --as=system:serviceaccount:\u003Cns>:\u003Csa>\n```\n\n### Anti-patterns\n\n- **Bare Pods in production** — use Deployments or StatefulSets\n- **Missing readiness probes** — Services will send traffic to pods\n  that aren't ready\n- **No resource requests\u002Flimits** — scheduler has nothing to go on,\n  noisy neighbors can starve you\n- **Hardcoded namespace in manifests** — pass via `-n` or kustomize\n- **`latest` image tags** — rollouts become non-deterministic\n- **Ignoring `kubectl diff`** — blind `apply` can silently remove\n  fields that were set out-of-band\n",{"name":5,"metadata":49,"description":55},{"processkit":50},{"id":51,"created":52,"version":53,"category":35,"apiVersion":54},"SKILL-kubernetes-basics",1775433600000,"1.1.0","processkit.projectious.work\u002Fv1","Kubernetes cluster management — resources, networking, storage, Helm, troubleshooting. Use when writing Kubernetes manifests, running kubectl or helm, debugging pods and services, or configuring ingress, DNS, storage, or network policies.\n","main","4876a92620ee792aac2ac9a1a806322d8a572367","archive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit","https:\u002F\u002Fprojectious-work.github.io\u002Fprocesskit\u002F","https:\u002F\u002Fgithub.com\u002Fprojectious-work","2026-11-11 23:24:18",{"source":8,"skillName":5,"commands":64,"prompt":74,"zipAvailable":75},[65,68,71],{"tool":66,"command":67},"npx","npx skills add projectious-work\u002Fprocesskit --skill kubernetes-basics",{"tool":69,"command":70},"bunx","bunx skills add projectious-work\u002Fprocesskit --skill kubernetes-basics",{"tool":72,"command":73},"pnpm","pnpm dlx skills add projectious-work\u002Fprocesskit --skill kubernetes-basics","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics\u002FSKILL.md",true,[77,83,87],{"path":78,"resourceType":79,"resourceTypeDesc":80,"sizeBytes":81,"sourceHtmlUrl":82},"references\u002Fcluster-architecture.md","REFERENCE","参考文档",4877,"https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics\u002Freferences\u002Fcluster-architecture.md",{"path":84,"resourceType":79,"resourceTypeDesc":80,"sizeBytes":85,"sourceHtmlUrl":86},"references\u002Fresource-cheatsheet.md",6290,"https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics\u002Freferences\u002Fresource-cheatsheet.md",{"path":88,"resourceType":79,"resourceTypeDesc":80,"sizeBytes":89,"sourceHtmlUrl":90},"references\u002Ftroubleshooting.md",6770,"https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.11.1\u002Fcontext\u002Fskills\u002Fdevops\u002Fkubernetes-basics\u002Freferences\u002Ftroubleshooting.md",[92,115,135,156,173,191],{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":101,"publishedAt":44},"01M6X5MTC89B4ZGXW3JVSQCPF8","skill-management","Manage Skill package manifests as v1 ontology entities.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fskill-management\u002FSKILL.md",[98],{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[102,103,104,105,106,107,37,108,109,110,94,111,112,31,30,113,114],"management","skill management","create","update","package","alpha","list","manage","ontology","get","as","skill package","transition",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":122,"publishedAt":44},"01M6X5MCV74NHW5MEDNHZRF2C8","schema-management","Manage generated processkit schema contracts through deterministic MCP rebuild and inspection workflows.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fschema-management\u002FSKILL.md",[121],{"categoryNo":99,"categoryName":100,"taxonomyType":21,"taxonomyTypeDesc":22},[102,123,124,125,126,127,107,37,128,129,109,130,131,132,111,133,134],"schema","schema management","MCP","workflows","validation","generated","rebuild","contracts","wed","deterministic","contract","mode",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":141,"publishedAt":44},"01M6X5M5G6YJ96AMZGSCZJ1D13","proposition-management","Record claims, risks, beliefs, world facts, WSJF estimates, and assumptions through the Proposition interface.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fproposition-management\u002FSKILL.md",[],[102,142,143,104,105,144,107,37,145,146,147,148,111,149,150,151,152,153,154,155],"proposition","proposition management","index","log","world","record","query","creation","event","interface","updates","facts","claims","WSJF",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":44},"01M6X5KMQ83QN9M6MPWZM7344F","ontology-management","Manage generated v1 ontology entities that do not require a dedicated domain server.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fontology-management\u002FSKILL.md",[],[102,110,163,104,107,164,165,128,166,145,109,167,168,111,169,170,150,171,30,172],"ontology management","lifecycle","archive","roadmap","do","domain","iteration","keep","measurement","generic",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":179,"publishedAt":44},"01M6X5KCY2DN3SM21RERSFNEBT","okf-compatibility","Import, export, and validate conformant Open Knowledge Format bundles.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fokf-compatibility\u002FSKILL.md",[],[180,181,182,183,107,184,185,186,37,187,188,189,190],"okf","compatibility","okf compatibility","validate","open","knowledge","format","export","bundles","bundle","import",{"skillNo":192,"name":193,"nameZh":6,"description":194,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":195,"categories":196,"keywords":197,"publishedAt":44},"01M6X5JA8S5PNGJVFW4EQY8T83","capability-management","Manage versioned Capability entities and their governed lifecycle.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fcapability-management\u002FSKILL.md",[],[102,198,199,104,105,144,107,164,37,108,145,200,109,147,111,170,150,151,201,114],"capability","capability management","queries","changes"]