---
id: kubernetes-kubectl
title: "kubectl"
track: kubernetes
trackTitle: "Kubernetes"
order: 3
level: core
status: published
estimatedMinutes: 50
prerequisites:
  - kubernetes-manifests
next: kubernetes-rollout
reviewedAgainst: 2026-10-15
sources:
  - title: "KodeKloud Engineer — 100 Days of DevOps"
    url: https://engineer.kodekloud.com/practice
  - title: "kubectl apply"
    url: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/
  - title: "kubectl Cheat Sheet"
    url: https://kubernetes.io/docs/reference/kubectl/quick-reference/
  - title: "kubectl port-forward"
    url: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_port-forward/
  - title: "kubectl exec"
    url: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_exec/
  - title: "Declarative management"
    url: https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/
---

# kubectl

Lệnh ghi lên cluster cần context đúng. `kubectl config current-context` trước `apply`. Sai context là ghi nhầm chỗ.

## Để làm gì

Đưa YAML lên cluster, đọc Pod/Service/event, xem log, `exec` vào container, port-forward tạm, rồi gỡ đúng file đã apply.

## Gồm những gì

- `apply`, `get`, `describe`, `logs`, `exec`, `delete`.
- `port-forward` cho `ClusterIP`.
- Triệu chứng hay gặp: `ImagePullBackOff`, `CrashLoopBackOff`, `Pending`, READY `0/1`.

`kubectl rollout` (update / undo) ở bài sau. `kubectl run` đã có ở bài kiến trúc.

## Dùng khi nào

Manifest đã dry-run, kubeconfig trỏ cluster lab. Cùng lệnh trên production là thay đổi vận hành — đúng file, đúng namespace, đúng quyền.

`apply` so file với object đang có rồi cập nhật. Git là source of truth. `kubectl edit` sửa trên API; quên ghi file thì lần apply sau đè ngược.

## Kiến thức cốt lõi

Object xác định bằng apiVersion, kind, namespace, name. Lab để `default` cho ngắn lệnh. App thật nên có namespace riêng.

`kubectl get pods` là bảng ngắn. `READY 1/1` = số container sẵn sàng / tổng trong Pod. Nhiều container thì `1/2` nghĩa là một cái chưa Ready — `describe` và `logs -c`.

`describe` in Events: pull image fail, probe fail, chưa schedule vì thiếu CPU. `get` không đủ khi Pod không lên.

`kubectl logs` đọc stdout của một container. Deployment nhiều Pod: lấy tên từ `get pods`, hoặc `-l app=web`. Nhiều container: `-c tên`. `--follow` bám dòng; Ctrl+C chỉ thoát lệnh, không dừng Pod.

`kubectl exec POD -- lệnh` chạy process thêm, giống `docker exec`. Option đứng trước tên Pod. Nhiều container: `-c`. Container phải Running. `--` tách lệnh trong container khỏi flag kubectl.

```bash
kubectl exec lab-nginx -- printenv
kubectl exec -it lab-nginx -- sh
kubectl exec web-app-7d9f8 -c nginx -- nginx -v
```

`port-forward service/web-service 8080:80` mở 8080 trên máy bạn, chuyển vào port 80 của Service. Phiên kubectl còn thì đường còn. Không phải cửa public.

`delete -f` xóa đúng object trong file. Xóa một Pod của Deployment thì ReplicaSet tạo Pod khác — đó là cách thấy self-heal. Xóa cả Deployment thì hết replica.

Debug theo thứ tự: `get` → `describe` (Events) → `logs` → `exec` nếu process còn sống. Đừng scale khi chưa biết bản đầu fail vì sao.

| STATUS / cột | Ý thường gặp | Việc làm |
| --- | --- | --- |
| `Pending` | Chưa có node, hoặc PVC chưa bind | `describe pod` — FailedScheduling, volume |
| `ImagePullBackOff` | Sai tag, registry, hoặc secret pull | Events: Failed, ErrImagePull |
| `CrashLoopBackOff` | Process chết, kubelet restart | `logs`, `logs --previous` |
| READY `0/1` | Probe hoặc container chưa ready | `describe` điều kiện Ready |
| `Init:0/1` | Init container chưa xong | `logs POD -c tên-init` |

## Lệnh và code mẫu

```bash
kubectl config current-context
kubectl cluster-info
```

```bash
kubectl apply -f "$HOME/devops-lab/k8s"
kubectl get deploy,svc,pods -l app=web
kubectl rollout status deployment/web-app
```

Pod không Ready:

```bash
kubectl describe pod -l app=web
kubectl logs -l app=web --tail=50
kubectl get events --sort-by='.lastTimestamp'
```

Port-forward, terminal riêng:

```bash
kubectl port-forward service/web-service 8080:80
```

Terminal kia:

```bash
curl.exe -sS -D - http://127.0.0.1:8080 -o /dev/null
```

Gỡ lab:

```bash
kubectl delete -f "$HOME/devops-lab/k8s"
```

## Thực hành

1. Đọc `current-context`. Ghi tên cluster.
2. Apply thư mục lab.
3. Đợi `rollout status` xong.
4. `port-forward` và `curl`.
5. `kubectl delete pod` một replica. `get pods -l app=web` — vẫn đủ số vì Deployment.
6. `describe` một Pod, đọc Events một lần dù đang Running.
7. `delete -f` khi xong.

## Kết quả mong đợi

- Ba Pod `Running`, READY `1/1`.
- Service `ClusterIP`.
- `curl` qua port-forward ra `200`.
- Xóa một Pod, Deployment bù đủ 3.
- Sau `delete -f`, không còn `web-app` / `web-service`.

## Checklist

- [ ] Đọc context trước apply.
- [ ] `describe` khi không Ready, đừng chỉ `get` lại.
- [ ] `logs -c` khi Pod nhiều container.
- [ ] `exec`: option trước tên Pod, lệnh sau `--`.
- [ ] Gỡ bằng đúng file đã apply.

## Thẻ ôn

### kubernetes-kubectl-context
kind: trap
cue: `kubectl apply` ghi đúng context đang chọn. Namespace trùng tên không chặn nhầm cluster.

Q: Bạn apply manifest lab. `get pods` ra Pod production. Bước nào bị bỏ, và làm gì trước lần apply sau?

A: Chưa đọc `kubectl config current-context`. Kubeconfig có thể đang trỏ cluster khác, cùng namespace `default`. Đọc context, đúng lab rồi mới `apply`. `get` trước cũng thấy object lạ thì dừng.

### kubernetes-kubectl-describe
kind: decide
cue: `get` chỉ bảng. Không Ready thì `describe` đọc Events: pull, probe, schedule.

Q: `get pods` in `ImagePullBackOff`. `get` thêm năm lần không đổi. Lệnh nào nói lý do, và hay gặp chữ nào trong Events?

A: `kubectl describe pod <tên>`. Events kiểu `Failed`, `ErrImagePull`, `Back-off pulling image`. Sai tag, registry không tới, hoặc thiếu imagePullSecret. Sửa image/secret rồi xóa Pod (Deployment tạo lại) hoặc chờ kubelet thử lại. Đừng tăng replica.

### kubernetes-kubectl-exec
kind: command
cue: `kubectl exec POD -- lệnh`. Nhiều container thêm `-c`. Option đứng trước tên Pod.

Q: Pod `web-xxxx` có container `nginx` và `logshipper`. In biến môi trường trong `nginx`. Lệnh viết thế nào?

A: `kubectl exec web-xxxx -c nginx -- printenv`. `-c` trước hoặc sau tên Pod vẫn được miễn là trước `--`. Thiếu `-c` mà Pod nhiều container thì kubectl bắt chọn. `printenv` sau `--` là lệnh trong container, không phải flag kubectl.

### kubernetes-kubectl-delete-pod
kind: distinguish
cue: Xóa Pod của Deployment thì ReplicaSet tạo cái khác. Xóa Deployment thì hết replica.

Q: Lab bảo chứng minh self-heal. Xóa object nào, và xóa nhầm Deployment thì sao?

A: `kubectl delete pod <tên-một-replica>`. Deployment giữ `replicas`, tạo Pod mới. `delete -f` cả Deployment thì Service/Deployment biến, không còn ai tạo Pod. Self-heal là controller, không phải Pod tự sống.

### kubernetes-kubectl-port-forward
kind: trap
cue: port-forward gắn phiên kubectl. Không phải đường public.

Q: Bạn gửi đồng nghiệp URL `http://127.0.0.1:8080` sau `port-forward`. Họ vào được không, và điểm vào dùng chung là gì?

A: Không. `127.0.0.1` là máy bạn. Hết phiên kubectl là đứt. Điểm vào chung: Ingress hoặc LoadBalancer khi đã chủ ý publish. Lab một mình thì port-forward đủ.

## Lỗi thường gặp

**Apply nhầm context.** Đọc `current-context` như một bước của lệnh.

**`ImagePullBackOff` rồi sửa YAML nhưng không apply.** Cluster vẫn image cũ. `apply` lại, xem ReplicaSet mới.

**`CrashLoopBackOff` mà chỉ `get`.** `logs` và `logs --previous` — lần chết trước.

**`exec` khi container chưa Running.** Daemon từ chối. Đợi, hoặc `describe` xem init còn chạy.

**Đưa URL port-forward cho người khác.** Đường gắn máy và phiên của bạn.

## Nguồn

1. [KodeKloud Engineer — 100 Days of DevOps](https://engineer.kodekloud.com/practice) — đề cương ngày Troubleshoot Deployment issues, và các ngày dùng `apply`/`get`/`exec`. Trang practice cần đăng nhập. Bài này viết lại lệnh, không chép lab.
2. [kubectl apply](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/) — đưa khai báo lên cluster.
3. [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/quick-reference/) — `get`, `describe`, `logs`.
4. [kubectl exec](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_exec/) — `-c`, `--`.
5. [kubectl port-forward](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_port-forward/) — cổng tạm.
6. [Declarative management](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/) — quản lý bằng file.

## Tiếp theo

[Rolling update và rollback](./10-rollout.md)
