# 🖥️ Thiết lập môi trường lab và tài khoản thi

> Sign in to view the full content of this lesson.

Mình nhớ lần đầu đăng ký thi CKA, mình mất gần một buổi tối chỉ để loay hoay xem nên dựng lab bằng gì, và đúng một tuần trước ngày thi mới phát hiện webcam của mình không qua được bước kiểm tra hệ thống. Bài này để bạn không lặp lại lỗi đó: dựng lab trong khoảng 15 phút, và chuẩn bị tài khoản thi đúng cách ngay từ đầu.

**Ôn lại nhanh:** bài trước đã chốt rằng CKA là bài thi thực hành, chấm điểm dựa trên trạng thái cluster thật sau khi bạn làm, không phải trắc nghiệm. Vì vậy mọi thứ trong bài này đều phục vụ một mục tiêu: tay bạn phải quen với terminal và cluster giống môi trường thi.

## Mục tiêu bài học

Sau bài này, bạn có thể:

- Dựng được một cluster lab cục bộ (minikube, kind hoặc kubeadm trên VM) và biết khi nào dùng công cụ nào.
- Dùng thành thạo các lệnh kiểm tra cơ bản: `kubectl cluster-info`, `kubectl get nodes -o wide`, `kubectl config get-contexts`.
- Vào được bên trong node để xem static pod và các file cấu hình, đúng kiểu bạn sẽ phải làm khi thi.
- Hoàn tất phần tài khoản thi: đăng ký lịch, chạy kiểm tra hệ thống, chuẩn bị phòng thi.

> [!NOTE]
> Mọi chi tiết về môi trường thi (domain tài liệu được phép mở, giờ check-in, yêu cầu thiết bị) đều có thể thay đổi. Luôn đọc lại Candidate Handbook trong portal của bạn trước khi thi. Bài này dạy bạn cách chuẩn bị, không thay thế tài liệu chính thức.

## Ví dụ minh hoạ: dựng cluster 3 node bằng kind

Mình chọn kind cho ví dụ này vì nó tạo được nhiều node (control plane và worker) ngay trên một máy, đủ để luyện `drain`, `nodeSelector`, `taint`, và vào node xem static pod. Đây là những thứ module 2 và module 3 sẽ dùng liên tục.

**Bước 1: kiểm tra công cụ đã có**

```bash
docker version --format '{{.Server.Version}}'
kubectl version --client
kind version
```

Nếu thiếu `kind`, cài bằng package manager hoặc tải binary từ trang chính thức của kind. Nếu `docker version` báo lỗi kết nối, bật Docker daemon trước.

**Bước 2: tạo file cấu hình cluster**

```yaml
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
```

**Bước 3: tạo cluster**

```bash
kind create cluster --name cka --config kind-config.yaml
```

kind sẽ tải node image, khởi tạo control plane, cài CNI mặc định và join hai worker. Lần đầu có thể mất 2 đến 3 phút vì phải pull image.

**Bước 4: kiểm tra**

```bash
kubectl config current-context      # kind-cka
kubectl cluster-info
kubectl get nodes -o wide
```

Bạn cần thấy đúng 3 node ở trạng thái `Ready`. Nếu có node `NotReady`, chờ thêm 30 đến 60 giây rồi xem lại, thường chỉ là CNI chưa khởi động xong.

**Bước 5: vào bên trong node**

```bash
docker exec -it cka-control-plane bash
ls /etc/kubernetes/manifests
exit
```

Bạn sẽ thấy `etcd.yaml`, `kube-apiserver.yaml`, `kube-controller-manager.yaml`, `kube-scheduler.yaml`. Đây chính là các static pod, và kỹ năng sửa file trong thư mục này là một dạng bài rất hay gặp.

**Bước 6: dọn dẹp khi cần làm lại**

```bash
kind delete cluster --name cka
```

Sơ đồ chọn công cụ lab:

```mermaid
flowchart TD
    Start["🎯 Cần cluster lab"] --> Q{"Cần nhiều node<br/>và luyện kubeadm?"}
    Q -->|"Chỉ luyện kubectl"| Mini["💻 minikube"]
    Q -->|"Có, muốn nhanh"| Kind["📦 kind"]
    Q -->|"Muốn giống thi nhất"| VM["🖥️ VM + kubeadm"]
    Mini --> Done["✅ kubectl get nodes Ready"]
    Kind --> Done
    VM --> Done
```

| Công cụ | Thời gian dựng | Số node | Phù hợp với |
| --- | --- | --- | --- |
| minikube | 2 đến 5 phút | 1 (có thể thêm) | Luyện kubectl, workload cơ bản |
| kind | 2 đến 3 phút | 1 đến nhiều | Luyện drain, static pod, đa node |
| VM + kubeadm | 30 đến 45 phút | 2 trở lên | Luyện init, join, upgrade, etcd backup |

Mẹo của mình: dựng kind trước để luyện hằng ngày, và dựng một cụm VM kubeadm riêng cho module 2. Đừng cố dùng một môi trường cho tất cả.

## Luyện tập có hướng dẫn

Phần này bạn tự làm, mỗi bài đều bấm giờ. Mục tiêu không phải làm đúng, mà là làm nhanh và không cần nhìn tài liệu.

### Bài tập 1: Dựng lại cluster mà không nhìn hướng dẫn (5 phút)

Xóa cluster cũ, dựng lại cluster tên `cka` với 1 control plane và 2 worker, sau đó xác nhận cả 3 node `Ready`.

<details><summary>Gợi ý nếu bị kẹt</summary>

```bash
kind delete cluster --name cka
kind create cluster --name cka --config kind-config.yaml
kubectl get nodes -o wide
```

Nếu lệnh create báo file config không tồn tại, kiểm tra bạn đang đứng đúng thư mục chứa `kind-config.yaml`.

</details>

### Bài tập 2: Luyện phản xạ context (3 phút)

Chạy lần lượt và đọc kỹ output:

```bash
kubectl config get-contexts
kubectl config current-context
kubectl config use-context kind-cka
kubectl config view --minify -o jsonpath='{.contexts[0].context.namespace}'
```

Câu hỏi tự kiểm tra: nếu đề thi ghi "on cluster X, in namespace Y", bạn cần mấy lệnh để chắc chắn mình đang ở đúng chỗ? Câu trả lời mình hay dùng là hai: `use-context` và thêm `-n <namespace>` trong từng lệnh.

### Bài tập 3: Ba task kiểu đề thi, chỉ dùng terminal (8 phút)

Làm cả ba task, bấm giờ, không mở trình duyệt.

1. Tạo namespace `web` và Deployment tên `nginx` dùng image `nginx:1.27`, 3 replicas, container port 80. Kiểm tra có đủ 3 pod `Running`.
2. Vào control plane node, liệt kê thư mục manifest static pod và cho biết pod nào trong `kube-system` là static pod.
3. Liệt kê các node kèm IP nội bộ và phiên bản kubelet.

<details><summary>Gợi ý cho task 1</summary>

```bash
kubectl create namespace web
kubectl create deployment nginx -n web --image=nginx:1.27 --replicas=3
kubectl get pods -n web
```

Bài sau sẽ dạy cách thêm container port bằng `--dry-run=client -o yaml`, nên bây giờ chỉ cần Deployment chạy được là đủ.

</details>

<details><summary>Gợi ý cho task 2</summary>

```bash
docker exec -it cka-control-plane ls /etc/kubernetes/manifests
kubectl get pods -n kube-system -o wide
```

Static pod có tên kết thúc bằng tên node, ví dụ `kube-apiserver-cka-control-plane`.

</details>

<details><summary>Gợi ý cho task 3</summary>

```bash
kubectl get nodes -o wide
```

Cột `INTERNAL-IP` và `KUBELET-VERSION` là thứ đề hay hỏi gián tiếp.

</details>

### Bài tập 4: Hoàn tất tài khoản thi và kiểm tra hệ thống (10 phút)

Đây là phần không nằm trong terminal nhưng ảnh hưởng trực tiếp đến kết quả thi.

```steps
1. Đăng nhập portal của nhà cung cấp chứng chỉ, xác nhận gói thi của bạn đã active và tìm access code.
2. Đăng ký lịch thi qua PSI: chọn múi giờ, ngôn ngữ thi và khung giờ bạn tỉnh táo nhất.
3. Tải và chạy PSI Secure Browser trên đúng chiếc máy bạn sẽ dùng để thi, chạy mục kiểm tra hệ thống.
4. Kiểm tra webcam, micro, loa và băng thông mạng. Nên dùng cáp mạng thay vì Wi-Fi.
5. Tắt màn hình phụ, tắt notification, đặt máy ở phòng riêng, bàn sạch.
6. Chuẩn bị giấy tờ tùy thân có ảnh còn hiệu lực, đúng tên đã đăng ký.
7. Đọc lại Candidate Handbook một lần, ghi chú giờ check-in và danh sách tài liệu được phép mở.
8. Tìm link killer.sh trong portal học viên, đây là 2 buổi lab mô phỏng sát môi trường thi, đừng để đến sát ngày mới dùng.
```

> [!TIP]
> Hãy làm bước 3 và bước 4 ít nhất một tuần trước ngày thi. Nếu webcam hoặc màn hình không đạt, bạn vẫn còn thời gian đổi thiết bị hoặc đổi lịch.

### Bài tập 5: Tạo thói quen reset nhanh (2 phút)

Ghi lại đúng một lệnh dựng lại môi trường lab của bạn (với kind là `kind delete cluster --name cka` rồi `kind create cluster ...`) vào một file `reset-lab.sh`. Trong lúc luyện, bạn sẽ phá cluster rất nhiều lần, có script này thì không bao giờ ngại thử.

## Lỗi thường gặp và cách xử lý

| Triệu chứng | Nguyên nhân thường gặp | Cách xử lý |
| --- | --- | --- |
| `Cannot connect to the Docker daemon` | Docker chưa chạy hoặc user chưa thuộc group `docker` | `sudo systemctl start docker`, thêm user vào group rồi đăng nhập lại |
| `The connection to the server localhost:8080 was refused` | Chưa có kubeconfig hoặc cluster chưa chạy | `kubectl config get-contexts`, `kubectl cluster-info` |
| Node `NotReady` ngay sau khi tạo | CNI chưa khởi động xong | Chờ 30 đến 60 giây, xem `kubectl get pods -n kube-system` |
| `ssh` vào node kind bị từ chối | Node kind là container, không chạy sshd | Dùng `docker exec -it <tên-node> bash` |
| `permission denied` khi sửa file trên node | Chưa có quyền root | `sudo -i` hoặc dùng `sudo` trước từng lệnh |
| Kiểm tra hệ thống PSI thất bại | Còn màn hình phụ, thiếu webcam, hoặc trình duyệt chưa đúng | Ngắt màn hình phụ, kiểm tra lại thiết bị, chạy lại công cụ kiểm tra |
| Làm đúng nhưng không thấy kết quả | Sai context hoặc sai namespace | Luôn chạy `kubectl config use-context` trước, thêm `-n` rõ ràng |

Lỗi cuối cùng là lỗi đắt nhất trong phòng thi. Mình từng làm xong một task, verify không thấy pod, hoảng lên, thì ra đang ở context của cluster khác. Từ đó mình có phản xạ: câu nào cũng bắt đầu bằng việc đọc context và namespace trong đề, và kết thúc bằng một lệnh verify.

## Góc chuyên gia

- **Dựng lab đúng phiên bản Kubernetes mà handbook ghi.** Lệch một vài minor version có thể khiến flag của `kubeadm` hoặc output của `kubectl` khác đi, và bạn sẽ bối rối không cần thiết.
- **Luôn có một snapshot trước khi phá.** Với VM, tạo snapshot. Với kind, chỉ cần nhớ lệnh dựng lại. Thời gian tiết kiệm được khi luyện tập là rất lớn.
- **Đặt độ phân giải 1920x1080 và font terminal cỡ vừa.** Trong bài thi bạn phải đọc nhiều output dài, màn hình nhỏ làm bạn cuộn nhiều và mất thời gian.
- **Học copy/paste bằng bàn phím.** Trong terminal của môi trường thi thường là `Ctrl+Shift+C` và `Ctrl+Shift+V`. Luyện ngay trên máy mình để không phải nghĩ trong lúc thi.
- **Nhập YAML nhanh bằng heredoc**, tránh mở editor nếu không cần:

  ```bash
  cat <<EOF | kubectl apply -f -
  apiVersion: v1
  kind: Namespace
  metadata:
    name: web
  EOF
  ```

- **Đặt lịch thi vào buổi sáng, sau khi lab đã ổn định 2 đến 3 tuần.** Đừng đặt lịch trước khi dựng xong môi trường, vì đó là lúc bạn còn đang loay hoay với công cụ chứ chưa luyện được dạng bài.
- **Dùng killer.sh đúng hai lượt.** Lượt một làm full 2 giờ như thi thật, ghi lại mọi chỗ bí. Lượt hai sau khoảng 3 ngày, sau khi đã ôn lại các phần yếu.

## Tóm tắt và bước tiếp theo

Tóm lại những gì cần nhớ:

- Có cluster lab là điều kiện bắt buộc để luyện CKA. kind là lựa chọn nhanh nhất cho đa node, VM cộng kubeadm là bản giống thi nhất.
- Bốn lệnh kiểm tra nền tảng: {{c1::kubectl config get-contexts}}, {{c2::kubectl config use-context}}, `kubectl cluster-info`, `kubectl get nodes -o wide`.
- Vào node bằng `docker exec` với kind, bằng `ssh` rồi `sudo -i` với VM hoặc môi trường thi. Manifest static pod nằm ở {{c3::/etc/kubernetes/manifests}}.
- Tài khoản thi cần được chuẩn bị trước: đăng ký lịch, chạy kiểm tra hệ thống PSI, chuẩn bị giấy tờ và phòng thi.

**Bài tiếp theo:** bạn đã có cluster, giờ là lúc làm tay nhanh hơn. Bài sau đi vào `kubectl` tốc độ: alias, `--dry-run=client -o yaml`, `jsonpath` và `kubectl explain`, đúng những thứ giúp bạn tiết kiệm 10 đến 15 phút trong phòng thi.

```flashcard
[
  { "front": "Bài thi CKA được làm trên môi trường nào?", "back": "Remote desktop qua PSI Secure Browser, thao tác hoàn toàn bằng terminal." },
  { "front": "Việc đầu tiên cần làm với mỗi câu hỏi trong đề thi là gì?", "back": "Chạy kubectl config use-context đúng context mà đề chỉ định." },
  { "front": "Lệnh liệt kê tất cả context và lệnh đổi context?", "back": "kubectl config get-contexts và kubectl config use-context <tên-context>." },
  { "front": "Hai lệnh kiểm tra cluster và node đang chạy?", "back": "kubectl cluster-info và kubectl get nodes -o wide." },
  { "front": "kind chạy node dưới dạng gì và vào node bằng lệnh nào?", "back": "Container Docker, vào bằng docker exec -it <tên-node> bash." },
  { "front": "Manifest của static pod nằm ở thư mục nào?", "back": "/etc/kubernetes/manifests." },
  { "front": "Lệnh tạo cluster kind 3 node từ file cấu hình?", "back": "kind create cluster --name cka --config kind-config.yaml, với 1 control-plane và 2 worker." },
  { "front": "Lệnh dựng nhanh cluster một node bằng minikube?", "back": "minikube start --cpus=2 --memory=4096." },
  { "front": "Vì sao nên dựng lab nhiều node thay vì một node?", "back": "Để luyện drain, taint/toleration, nodeSelector và troubleshoot node NotReady." },
  { "front": "Lấy quyền root trên node trong môi trường thi như thế nào?", "back": "ssh vào node rồi chạy sudo -i." },
  { "front": "killer.sh là gì và có mấy buổi?", "back": "Lab mô phỏng sát môi trường thi, thường kèm 2 buổi trong gói mua CKA." },
  { "front": "Cần chạy gì trên máy thi trước ngày thi?", "back": "PSI Secure Browser compatibility check, kèm kiểm tra webcam, micro và màn hình." },
  { "front": "Hậu quả của việc làm đúng nhưng sai context?", "back": "Cluster hoặc namespace không thay đổi, câu đó thường bị 0 điểm." }
]
```

```cloze
Trong bài thi CKA, bước đầu tiên của mỗi câu là chạy {{c1::kubectl config use-context}} với context mà đề chỉ định.
Cluster kind chạy mỗi node như một {{c2::container Docker}}, nên muốn vào node phải dùng {{c3::docker exec}}.
Manifest của static pod nằm trong thư mục {{c4::/etc/kubernetes/manifests}}.
Sau khi ssh vào node, lệnh {{c5::sudo -i}} giúp lấy quyền root để sửa file cấu hình.
Lệnh {{c6::kubectl get nodes -o wide}} cho biết node nào chưa Ready, IP nội bộ và phiên bản kubelet của từng node.
```
