jvinhit//lab

Search posts

Type to search across journal entries.

↑ ↓ navigate ↵ open esc close

Kubernetes cho Frontend Developer · Phần 1 — Vì sao FE dev nên học K8s, bức tranh tổng thể và lộ trình 19 phần

Mở đầu series: FE dev học Kubernetes để làm gì và học tới đâu là đủ, hành trình từ npm run build tới URL production qua 9 chặng, từ điển thuật ngữ cấp tốc, cách học và lộ trình 19 phần.

Là frontend developer, vòng đời công việc của bạn thường dừng ở git push. Sau đó là một “vùng tối”: trang trắng trên production nhưng chạy tốt ở local, VITE_API_URL trỏ sai mà không biết vì sao, F5 ở route /users/123 thì ra 404 trong khi bấm link nội bộ thì chạy. Những câu hỏi đó không phải câu hỏi frontend. Chúng là câu hỏi hạ tầng, và trong đa số công ty hiện đại, hạ tầng đó chính là Kubernetes.

Series này viết cho React / Vue / Angular / Next.js developer chưa từng làm việc với server, Docker hay Linux chuyên sâu. Mọi khái niệm hạ tầng được giải thích lại từ đầu, kèm phép so sánh với thứ bạn đã quen: npm, webpack, package.json, localhost:3000. Phần 1 lo phần định vị: bạn đang học cái gì, vì sao, học tới đâu là đủ, và toàn cảnh hành trình của code từ npm run build tới URL production. Từ phần 2 trở đi ta mới gõ lệnh.

Thuật ngữ kỹ thuật giữ nguyên tiếng Anh (Pod, Deployment, Service, Ingress, probe, rollout, registry, reconciliation) vì đó là từ bạn sẽ gõ trong terminal, đọc trong manifest và nghe đồng nghiệp DevOps nói. Phần dịch là phần giải thích.

Lộ trình 19 phần

PhầnChủ đềNguồn gốc
1Vì sao FE dev nên học K8s, bức tranh tổng thể, từ điển và lộ trìnhHướng dẫn + Bài 0.1–0.3
2Linux, terminal và mạng máy tính cho FEBài 1.1–1.2
3YAML trong 20 phút và container là gìBài 1.3–1.4
4Dockerfile chuẩn cho frontend, registry và Docker ComposeBài 1.5–1.7
5K8s là gì, kiến trúc cluster, cluster local và kubectlBài 2.1–2.4
6Pod, ReplicaSet, Deployment, label và namespaceBài 2.5–2.7
7Service và IngressBài 2.8–2.9
8ConfigMap, Secret và health check probeBài 2.10–2.11
9Resources, QoS, storage và vòng đời PodBài 2.12–2.14
10Biến môi trường build-time vs runtime và deploy React SPA từ A đến ZBài 3.1–3.2
11Deploy Next.js SSR, nhiều app trên một domain và micro-frontendBài 3.3–3.4
12Cache, nén, CDN đứng trước cluster và zero-downtime deployBài 3.5–3.6
13Sổ tay debug: 12 lỗi thường gặpBài 3.7
14Chiến lược rollout và autoscalingBài 4.1–4.2
15Helm và KustomizeBài 4.3–4.4
16CI/CD với GitHub Actions và GitOps với ArgoCDBài 4.5–4.6
17HTTPS tự động với cert-manager và observabilityBài 4.7–4.8
18Bảo mật cơ bản, chi phí và khi nào không nên dùng K8sBài 4.9–4.10
19Thời khoá biểu 6 tuần, checklist, đồ án và cheat sheetPhần 5

Cách đọc series này:

  • Phần 1–4 là nền tảng bắt buộc, đọc tuần tự và đừng bỏ. 80% người học K8s thất bại không phải vì K8s khó, mà vì không hiểu container, port và DNS. Nếu bạn chưa từng viết Dockerfile, tuyệt đối đừng nhảy sang phần 5.
  • Phần 5–9 là Kubernetes core, mỗi phần xây trên phần trước: kiến trúc → Pod và Deployment → Service và Ingress → ConfigMap và probe → resources và vòng đời Pod. Đọc theo thứ tự.
  • Phần 10–13 là chặng deploy thực tế. Phần 10 (biến môi trường build-time vs runtime) là bài quan trọng nhất của cả series đối với FE dev; phần 13 (sổ tay debug) là bài bạn sẽ mở lại nhiều nhất.
  • Phần 14–18 là nâng cao, nhảy cóc theo nhu cầu: cần đóng gói nhiều môi trường thì đọc 15, cần pipeline thì đọc 16, cần HTTPS thật thì đọc 17.
  • Phần 19 là thời khoá biểu, checklist tự đánh giá và đồ án. Đọc lướt nó ngay từ đầu để biết đích đến trông thế nào.

Nếu bạn chỉ có 2 tuần: đọc phần 2–4 (bỏ mục Docker Compose), phần 5–8, phần 10 và phần 13. Bỏ qua chặng nâng cao, quay lại sau khi đã dùng K8s thực tế vài tuần.


Hướng dẫn sử dụng tài liệu

Cách học hiệu quả nhất

  1. Đọc, gõ, phá, sửa. Đừng copy/paste. Hãy gõ tay từng lệnh. Sau khi chạy được, cố tình làm sai (đổi tên image, xoá Service, bỏ một dòng trong nginx.conf) để xem lỗi trông như thế nào. Kinh nghiệm debug đến từ việc đã nhìn thấy lỗi đó một lần; lần thứ hai gặp lại trên production, bạn nhận ra nó trong 10 giây thay vì 2 giờ.
  2. Mỗi phần đều có mục Thực hành. Không làm thực hành thì coi như chưa học phần đó. Kiến thức K8s không nằm ở việc nhớ cú pháp YAML, mà ở phản xạ khi thấy CrashLoopBackOff là gõ ngay kubectl logs --previous.
  3. Không nhảy cóc chặng nền tảng. Kubernetes chỉ là công cụ điều phối container. Không hiểu container thì không hiểu K8s, và mọi lỗi “lạ” về sau thực ra là lỗi về port, DNS hoặc filesystem của container.
  4. Chấp nhận không hiểu hết. Kubernetes có hơn 60 loại tài nguyên. Frontend dev thực tế chỉ dùng khoảng 10 loại: Namespace, Pod, Deployment, Service, Ingress, ConfigMap, Secret, HorizontalPodAutoscaler, PodDisruptionBudget và vài thứ quanh chúng. Series này tập trung vào đúng 10 loại đó.

Ký hiệu trong series

Nguồn gốc của series là một tài liệu 52 trang dùng năm loại ký hiệu. Trong bài viết, chúng trở thành các khối sau:

Ký hiệuNghĩa
Ghi chúGiải thích thêm, mẹo, liên hệ với kiến thức frontend bạn đã biết.
Thực hành (mục riêng)Bắt buộc gõ tay. Đây là phần tạo ra kỹ năng thật.
Cạm bẫyLỗi mà gần như 100% người mới đều mắc phải.
Nguy hiểmCó thể gây downtime hoặc lộ bảo mật trên production.
Kết quả mong đợiSau bước này bạn phải thấy đúng cái này; nếu không thì dừng lại debug, đừng đi tiếp.

Ví dụ, đây là dạng bạn sẽ gặp:

Cạm bẫy: cú pháp -p 8080:80 là cổng-máy-thật : cổng-trong-container. Nhớ sai thứ tự là lỗi phổ biến nhất của người mới.

Cần chuẩn bị gì

  • Máy tính có ít nhất 8GB RAM (16GB thì thoải mái), còn trống khoảng 20GB ổ cứng. Một cluster kind 3 node cộng Docker Desktop ăn khoảng 3–4GB RAM khi rảnh; nếu máy 8GB, hãy đóng bớt tab trình duyệt và tăng RAM cấp cho Docker Desktop trong Settings → Resources.
  • macOS, Linux hoặc Windows kèm WSL2. Windows thuần rất khổ (đường dẫn, quyền file, script shell), hãy cài WSL2 và làm toàn bộ series bên trong Ubuntu của WSL.
  • Đã cài Node.js và biết chạy npm run build. Bạn sẽ dùng chính app của mình làm vật thí nghiệm, nên hãy chọn một app Vite hoặc Next.js nhỏ, build được sạch.
  • Một tài khoản GitHub. Nó dùng cho GitHub Container Registry (nơi cất image, phần 4) và GitHub Actions (CI/CD, phần 16).
  • Tuỳ chọn: 5–10 USD để thuê VPS hoặc cluster thật ở tuần cuối. Không bắt buộc.

Ghi chú: toàn bộ phần 2 đến phần 18 học hoàn toàn miễn phí trên máy local bằng kind. Bạn không cần thuê cloud để học. Cluster thật chỉ khác ở chỗ có IP public và LoadBalancer do cloud cấp; mọi khái niệm còn lại giống hệt.


Vì sao FE dev nên học K8s và học tới đâu là đủ

Vấn đề thực tế bạn đang gặp

Hãy nhớ lại lần gần nhất bạn deploy xong và có người báo lỗi:

  • “Trang trắng trên production, ở local chạy bình thường.” Bạn mở console thấy 404 cho main-a1b2c3.js. Ai đó nói “chắc do cache”. Bạn không biết cache ở đâu, của ai, xoá thế nào.
  • “App gọi API staging trên production.” Bạn chắc chắn đã set VITE_API_URL đúng trong ConfigMap. Nhưng bundle vẫn gọi staging. Hoá ra biến Vite được nhúng lúc build, và ConfigMap chỉ tác động tới tiến trình nginx.
  • “F5 ở /users/123 ra 404, bấm link nội bộ thì vào được.” Đây là lỗi cấu hình reverse proxy, không phải lỗi React Router.
  • “Probe đang fail nên Pod không nhận traffic.” Bạn gật đầu nhưng không hiểu probe là gì và vì sao nó liên quan tới trang của bạn.

Bốn tình huống này lặp lại ở gần như mọi team. Điểm chung: FE dev là người thấy triệu chứng đầu tiên, nhưng không có ngôn ngữ để mô tả và không có quyền để tự kiểm tra. Học K8s là học ngôn ngữ đó.

Học K8s mang lại gì cho một FE dev

Khả năngÝ nghĩa thực tế
Tự deploy app của mìnhKhông phải chờ DevOps rảnh. Tự tạo môi trường staging cho QA test, tự dựng preview cho một branch.
Tự debug lỗi productionĐọc log, vào trong container, kiểm tra biến môi trường mà không cần nhờ ai.
Hiểu kiến trúc hệ thốngBiết request đi từ trình duyệt qua những lớp nào tới code của mình, và mỗi lớp có thể hỏng ra sao.
Nói chuyện được với backend/DevOpsHiểu “Service đó là ClusterIP” hay “probe đang fail” nghĩa là gì, và hỏi đúng câu hỏi.
Mở đường lên Senior / FullstackĐây là khác biệt rõ nhất giữa mid-level và senior FE trong JD tuyển dụng.

Ranh giới: học tới đâu là đủ

Bạn không cần trở thành SRE. Hãy phân biệt rõ hai cột này và đừng cảm thấy có lỗi khi không biết cột bên phải:

FE dev CẦN thành thạoFE dev KHÔNG cần (để DevOps lo)
Pod, Deployment, Service, Ingressetcd backup, cluster upgrade
ConfigMap, SecretCNI plugin (Calico, Cilium) nội bộ
Probes, resources, HPAThiết kế network policy toàn cluster
Đọc log, exec vào Pod, debugVận hành StatefulSet cho database
Viết Dockerfile tối ưuTuning kernel, storage class, CSI driver
Helm/Kustomize ở mức sử dụngViết Operator, CRD, controller

Ghi chú: series này dạy đúng cột bên trái, cộng thêm vừa đủ cột bên phải để bạn hiểu đồng nghiệp đang nói gì. Khi thấy một từ lạ trong cuộc họp (taint, CNI, CSI), bạn chỉ cần biết nó thuộc cột nào để quyết định có cần tìm hiểu thêm hay không.

Một cách kiểm tra đơn giản xem bạn đã “đủ” chưa: mở file Deployment mà team DevOps viết cho app của bạn. Nếu bạn đọc hiểu từng dòng, biết vì sao có readinessProbe, biết targetPort phải khớp cái gì, và tự trả lời được câu “vì sao cột READY là 0/1”, bạn đã ở mức đủ. Đó là đích của phần 5–9.


Bức tranh tổng thể: từ npm run build đến URL production

Trước khi đi vào chi tiết, hãy nắm toàn cảnh. Đây là hành trình của code frontend, chín chặng, từ file .tsx tới trình duyệt người dùng:

[1] Code của bạn            src/App.tsx, package.json
        |
        v  npm run build
[2] Static files            dist/index.html, dist/assets/main-a1b2c3.js
        |
        v  docker build
[3] Docker image            my-app:v1.2.0 (nginx + dist bên trong)
        |
        v  docker push
[4] Registry                ghcr.io/cong-ty/my-app:v1.2.0
        |
        v  kubectl apply -f deployment.yaml
[5] Kubernetes Deployment   "Tôi muốn 3 bản sao của image này luôn chạy"
        |
        v  K8s tự tạo
[6] Pod x3                  3 container nginx đang chạy, mỗi cái 1 IP riêng
        |
        v  Service gom lại
[7] Service                 1 địa chỉ nội bộ ổn định: my-app-svc:80
        |
        v  Ingress route
[8] Ingress                 app.congty.com -> my-app-svc:80
        |
        v
[9] Trình duyệt người dùng

Chặng 1–2 bạn đã làm hằng ngày. Chặng 3–4 là Docker (phần 3–4 của series). Chặng 5–8 là Kubernetes (phần 5–9). Mọi lỗi “vùng tối” ở đầu bài đều nằm ở một chặng cụ thể: cache index.html là chuyện của chặng 8 và CDN đứng trước nó; VITE_API_URL sai là chuyện của chặng 2 (giá trị bị đóng băng lúc build); 404 khi F5 là chuyện của nginx bên trong chặng 3.

Deployment replicas: 3 ReplicaSet keeps 3 alive Pod 1 Pod 2 Pod 3 Service stable VIP · LB traffic in →
Chặng 5–6: Deployment quản lý ReplicaSet, ReplicaSet quản lý Pod. Bạn chỉ viết Deployment, hai tầng dưới K8s tự tạo.

Giải thích từng chặng bằng ngôn ngữ frontend

ChặngVí von với thứ bạn đã biết
ImageGiống một file .zip chứa cả hệ điều hành mini + nginx + thư mục dist. Bất biến, có version.
RegistryGiống npm registry, nhưng chứa image thay vì package. docker push tương đương npm publish.
ContainerGiống khi bạn npm start: biến file tĩnh thành tiến trình đang chạy.
PodMột “hộp” chứa 1 (hoặc vài) container, có IP riêng. Đơn vị mà K8s quản lý.
DeploymentGiống package.json khai báo phiên bản mong muốn. Bạn nói “tôi muốn 3 bản”, K8s lo phần còn lại.
ServiceGiống một biến DNS nội bộ. Pod chết/sinh liên tục, IP đổi liên tục; Service cho bạn một tên cố định.
IngressGiống cấu hình server.proxy trong vite.config.ts nhưng ở tầng production: ánh xạ domain/path vào Service.

Nếu bạn từng viết đoạn này trong vite.config.ts để tránh CORS lúc dev:

export default defineConfig({
  server: {
    proxy: {
      '/api': 'http://localhost:3000',
    },
  },
});

thì bạn đã hiểu Ingress ở mức ý tưởng. Ingress làm đúng việc đó cho app.congty.com/api → backend-svc:3000 trên production, bằng YAML thay vì TypeScript. Phần 7 đi vào chi tiết.

Triết lý cốt lõi cần nhớ suốt series

Kubernetes hoạt động theo mô hình declarative (khai báo). Bạn mô tả trạng thái mong muốn (“3 bản sao của image v1.2.0”), K8s liên tục so sánh với thực tế và tự sửa cho khớp. Bạn không ra lệnh “hãy khởi động server”, đó là imperative, tư duy cũ.

Hãy nghĩ như React. Bạn không gọi document.createElement rồi appendChild; bạn khai báo UI mong muốn theo state, React tự diff và patch DOM. K8s cũng vậy: bạn khai báo spec, controller tự diff với status và patch cluster.

ReactKubernetes
state là nguồn sự thậtspec trong manifest là nguồn sự thật
Virtual DOM diff với DOM thậtController diff spec với status thật
Render lại khi state đổiReconcile lại khi spec đổi hoặc thực tế lệch
Bạn không đụng DOM trực tiếpBạn không docker run trực tiếp trên node
setState rồi để React lokubectl apply rồi để controller lo

Hệ quả thực tế của mô hình này, thứ bạn sẽ thấy tận mắt ở phần 5: xoá một Pod bằng tay, vài giây sau K8s tạo lại Pod mới, vì thực tế (2 Pod) lệch với khai báo (3 Pod). Bạn không làm gì cả. Đây là khác biệt cơ bản giữa K8s và docker run, và cũng là lý do kubectl edit trực tiếp trên production là ý tưởng tồi: lần kubectl apply sau từ Git sẽ âm thầm ghi đè thay đổi tay của bạn.


Từ điển thuật ngữ cấp tốc

Đọc lướt bảng này một lần, không cần nhớ. Bạn sẽ quay lại tra khi gặp từ lạ ở các phần sau.

Thuật ngữNghĩa ngắn gọn
ClusterToàn bộ hệ thống K8s: gồm nhiều máy chủ hoạt động như một.
NodeMột máy chủ (vật lý hoặc ảo) trong cluster.
Control Plane”Bộ não” điều phối cluster: nhận lệnh, lưu trạng thái, quyết định Pod chạy ở đâu.
PodĐơn vị chạy nhỏ nhất, bọc 1 hay nhiều container.
WorkloadTên gọi chung cho ứng dụng đang chạy (Deployment, Job, DaemonSet…).
ManifestFile YAML mô tả tài nguyên K8s.
kubectlCông cụ dòng lệnh để nói chuyện với cluster.
NamespaceThư mục logic chia tách tài nguyên (dev / staging / prod).
LabelCặp key=value gắn lên tài nguyên để nhóm và chọn lọc.
SelectorĐiều kiện lọc theo label. Cơ chế “kết nối” các tài nguyên với nhau.
ReplicaSố bản sao của Pod.
RolloutQuá trình cập nhật dần các Pod sang phiên bản mới.
ReconciliationVòng lặp K8s liên tục sửa thực tế cho khớp khai báo.
RegistryKho chứa Docker image.
Helm ChartGói template hoá các manifest, có biến và version.
CRDCustom Resource Definition: loại tài nguyên do bên thứ ba thêm vào (cert-manager, ArgoCD dùng cách này).

Ba từ nữa bạn sẽ gặp ngay từ phần 2–4: image (sản phẩm đã build, bất biến, có tag), container (một phiên bản image đang chạy) và reverse proxy (phần mềm đứng trước server, nhận mọi request rồi chuyển tiếp cho đúng service). Phần 3 giải thích hai từ đầu, phần 2 giải thích từ cuối.


Thực hành

Chặng định vị không có lệnh K8s nào để gõ, nhưng có một bài tập đáng làm trước khi sang phần 2: lần theo chín chặng ở trên với chính app của bạn.

  1. Chạy npm run build trong app của bạn. Mở thư mục dist/ (Vite) hoặc .next/ (Next.js). Ghi lại: file index.html nằm ở đâu, file JS chính tên gì, phần hash trong tên file trông thế nào.
  2. Mở index.html vừa build bằng editor. Tìm dòng <script> trỏ tới bundle. Đây là điểm vào mà mọi chiến lược cache ở phần 12 xoay quanh.
  3. Tìm xem app của bạn đang được deploy ở đâu. Hỏi đồng nghiệp DevOps xin file Deployment, hoặc tìm thư mục k8s/, helm/, deploy/ trong repo. Chưa cần hiểu, chỉ cần biết nó tồn tại.
  4. Nếu có file đó, đếm xem có bao nhiêu khối bắt đầu bằng kind:. Ghi lại tên các kind. Bạn sẽ gặp lại từng cái trong phần 5–9.
  5. Nếu công ty chưa dùng K8s: ghi lại cách app hiện được deploy (Vercel, S3, VPS chạy nginx). Phần 18 sẽ giúp bạn quyết định K8s có đáng cho trường hợp đó không.

Kết quả mong đợi: bạn có một ghi chú ngắn gồm tên file bundle có hash, vị trí index.html, và danh sách kind trong manifest (hoặc tên nền tảng deploy hiện tại). Không cần hiểu gì thêm ở bước này.


Tóm tắt

  • Vùng tối sau git push (trang trắng, biến môi trường sai, 404 khi F5) là câu hỏi hạ tầng, và hạ tầng đó thường là Kubernetes.
  • FE dev cần thành thạo khoảng 10 loại tài nguyên: Pod, Deployment, Service, Ingress, ConfigMap, Secret, probe, resources, HPA, cùng Dockerfile và Helm/Kustomize ở mức sử dụng. Phần còn lại để DevOps lo.
  • Hành trình code frontend có chín chặng: code → static files → image → registry → Deployment → Pod → Service → Ingress → trình duyệt. Mỗi lỗi quen thuộc nằm ở một chặng cụ thể.
  • K8s là declarative: bạn khai báo spec, controller tự reconcile thực tế cho khớp. Giống hệt cách React diff state với DOM.
  • Cách học duy nhất có tác dụng: gõ tay, cố tình làm hỏng, đọc lỗi, tự sửa. Mỗi phần đều có mục Thực hành và Kết quả mong đợi.
  • Phần 2–4 là nền tảng bắt buộc (Linux, mạng, YAML, Docker). Đừng nhảy cóc: đa số người thất bại với K8s là vì thiếu nền này chứ không phải vì K8s khó.
  • Toàn bộ series học miễn phí trên máy local bằng kind; máy 8GB RAM và WSL2 (nếu Windows) là đủ.

Đọc thêm

  • Kubernetes Concepts — mục Overview và Kubernetes Objects là bản gốc của triết lý declarative ở trên.
  • Deployment — tài nguyên bạn sẽ viết nhiều nhất.
  • kind — công cụ dựng cluster local dùng xuyên suốt series.
  • Nếu bạn muốn đi sâu hơn về Docker trước khi vào K8s, series Docker for Developers trên blog này đi chậm hơn và kỹ hơn phần 3–4 của series này.