🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🪟 Windows TippsHeader and Footer not showing in Excel(14.09.2026 um 22:43 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
🪟 Windows TippsKB5129194 Windows 11 26H1 Out of Band Update - Deskmodder.de(14.09.2026 um 19:25 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🪟 Windows TippsHeader and Footer not showing in Excel(14.09.2026 um 22:43 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
🪟 Windows TippsKB5129194 Windows 11 26H1 Out of Band Update - Deskmodder.de(14.09.2026 um 19:25 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 24 Min Lesezeit
0

Part 1 — Container hoá app & chạy trong Kubernetes local

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Bạn sẽ học gì



Sau bài này, bạn sẽ tự tay đưa một app từ số 0 (một thư mục trống) đến chạy được bên trong một cluster Kubernetes chạy trên máy của bạn. Cụ thể:




  • Viết một app Todo API nhỏ bằng Node.js + Express.

  • Đóng gói (container hoá) nó thành một Docker image.

  • Tạo một cluster Kubernetes local bằng kind.

  • Deploy app bằng file YAML "thật" (không dùng lệnh tắt) để hiểu Kubernetes vận hành thế nào.

  • Truy cập app đang chạy trong cluster từ máy của bạn.



Đây là Part 1 trong series "DevOps 101 — Học K8s, Helm, ArgoCD từ số 0". Cả series dùng chung một app tên todo-ops, các part sau sẽ xây tiếp lên nền này (thêm database, config, ingress, Helm, GitOps với ArgoCD).






Điều kiện tiên quyết





  • Docker (hoặc Docker Desktop / OrbStack) — đang chạy.


  • kind — công cụ tạo cluster Kubernetes trong Docker.


  • kubectl — CLI để nói chuyện với Kubernetes.


  • Node.js 20+npm — để chạy thử app local.


  • git — để quản lý mã nguồn.






Cài đặt



Chọn theo hệ điều hành của bạn.



macOS (dùng Homebrew — nếu chưa có, cài trước):




CODE
# Cài Homebrew (bỏ qua nếu đã có)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Docker Desktop (hoặc OrbStack: brew install --cask orbstack)
brew install --cask docker

# Các CLI còn lại
brew install kind kubectl node git






Sau khi cài xong, mở Docker Desktop (hoặc OrbStack) và chờ nó báo Running trước khi chạy tiếp.



Linux (Ubuntu/Debian):




CODE
# Docker Engine
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER" # cho phép chạy docker không cần sudo (đăng xuất/đăng nhập lại để có hiệu lực)

# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -m 0755 kubectl /usr/local/bin/kubectl && rm kubectl

# kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
sudo install -m 0755 kind /usr/local/bin/kind && rm kind

# Node.js 20 (qua NodeSource) + git
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs git







💡 Trên Apple Silicon (M1/M2/M3) đổi amd64arm64 trong hai lệnh kubectlkind. Trên macOS đã dùng brew nên không phải lo.




Kiểm tra nhanh (mỗi lệnh phải in ra một dòng version, không báo command not found):




CODE
docker --version
kind --version
kubectl version --client
node --version
git --version









Thời gian



Khoảng ~40 phút nếu bạn gõ theo từng bước.






Vị trí trong series






CODE
Cốt lõi (làm theo thứ tự)
[Part 1] Container & Kubernetes local ← bạn đang ở đây
Part 2 Config & State (Postgres, ConfigMap, Secret)
Part 3 Networking (Service & Ingress)
Part 4 Helm (đóng gói chart)
Part 5 ArgoCD / GitOps
Part 6 CI với GitHub Actions
Part 7 Observability & Bảo mật
Part 8 Monitoring (Prometheus, Grafana, Alertmanager)
Track nâng cao
Part 9 Autoscaling (HPA)
Part 10 StatefulSet cho DB
Part 11 Nhiều môi trường (dev/stage/prod)
Part 12 Secrets production (Sealed / External Secrets)
Part 13 Logging (Loki)
Part 14 Tracing (Tempo)

Dọn dẹp (làm cuối cùng)
Part 15 Dọn dẹp — xoá cluster + mọi tài nguyên, trả máy về sạch










💡 Hiểu thêm — Vì sao phải "container hoá"?

Cái đau kinh điển của lập trình: "máy tôi chạy được mà!". App của bạn cần Node.js phiên bản đúng, đúng thư viện, đúng biến môi trường... Khi mang sang máy khác hay server, thiếu một thứ là hỏng.

Container giải quyết bằng cách đóng gói app + toàn bộ thứ nó cần để chạy vào một "hộp" chuẩn hoá. Hộp đó chạy giống hệt nhau ở mọi nơi có Docker. Docker image là bản đóng gói tĩnh (như file cài đặt); container là một image đang chạy (như tiến trình).










Bước 1 — Tạo project



Tạo thư mục dự án và khởi tạo git.




CODE
mkdir todo-ops && cd todo-ops && git init








  • mkdir todo-ops tạo thư mục dự án.


  • cd todo-ops bước vào trong đó — từ giờ mọi lệnh chạy trong thư mục này.


  • git init biến thư mục thành một kho git để theo dõi thay đổi (các part sau, đặc biệt Part 6 GitOps, sẽ cần git).



Output mong đợi:




CODE
Initialized empty Git repository in /.../todo-ops/.git/









✅ Checkpoint 1



Chạy pwd — phải thấy đường dẫn kết thúc bằng /todo-ops. Chạy ls -a — phải thấy thư mục .git.




Nếu sai:




  • Lỡ git init ở nhầm thư mục cha → xoá thư mục .git bị tạo nhầm bằng rm -rf .git, rồi cd vào đúng todo-ops và làm lại.










Bước 2 — Viết app Node.js



App của chúng ta là Todo API: một service HTTP đơn giản cho phép xem và thêm todo. Part 1 chưa có database — dữ liệu lưu tạm trong một biến mảng trong bộ nhớ (in-memory). Nghĩa là restart app thì todo mất; đó là chủ ý, Part 2 sẽ thay bằng Postgres.



Tạo hai file: package.json (khai báo dự án & thư viện) và server.js (mã app).






2a. package.json



Tạo file package.json với nội dung:




CODE
{
"name": "todo-api",
"version": "1.0.0",
"description": "Todo API - DevOps 101",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.19.2"
}
}






Giải thích các field:





  • name, version, description — thông tin mô tả dự án.


  • main — file khởi động chính.


  • scripts.start — định nghĩa lệnh npm start = chạy node server.js. Đây là cách chuẩn để "khởi động app" mà không cần nhớ tên file.


  • dependencies.express — khai báo app cần thư viện Express (framework web cho Node.js). ^4.19.2 nghĩa là "phiên bản 4.19.2 trở lên nhưng vẫn trong dòng 4.x".






2b. server.js



Tạo file server.js với nội dung:




CODE
const express = require("express");

const app = express();
const PORT = 3000;

// Cho phép Express đọc JSON trong body của request (dùng cho POST).
app.use(express.json());

// "Database" tạm thời: một mảng trong bộ nhớ.
// Restart app là mất — Part 2 sẽ thay bằng Postgres.
let todos = [
{ id: 1, title: "Đọc DevOps 101 Part 1", done: false },
];
let nextId = 2;

// GET /todos → trả về toàn bộ danh sách todo dưới dạng JSON.
app.get("/todos", (req, res) => {
res.json(todos);
});

// POST /todos → thêm một todo mới. Body cần có { "title": "..." }.
app.post("/todos", (req, res) => {
const title = req.body && req.body.title;
if (!title) {
return res.status(400).json({ error: "title is required" });
}
const todo = { id: nextId++, title, done: false };
todos.push(todo);
res.status(201).json(todo);
});

// GET /healthz → probe kiểm tra sức khoẻ. Luôn trả 200 nếu app còn sống.
app.get("/healthz", (req, res) => {
res.status(200).send("OK");
});

// Lắng nghe trên port 3000, mọi địa chỉ (0.0.0.0) — quan trọng khi chạy trong container.
app.listen(PORT, () => {
console.log(`Todo API listening on port ${PORT}`);
});






Giải thích những chỗ quan trọng:





  • express.json()middleware — nó chạy trước mỗi request và biến JSON trong body thành req.body. Không có dòng này thì POST không đọc được title.


  • todos / nextIdstate in-memory. Đơn giản để học; dữ liệu không bền.

  • Ba route ứng với ba endpoint trong spec: GET /todos, POST /todos, GET /healthz.


  • /healthz trả 200 OK — Part 4 sẽ dùng endpoint này làm health probe cho Kubernetes. Đặt sẵn từ giờ để nhất quán.


  • app.listen(PORT) — mở cổng và chờ request. console.log giúp ta biết app đã lên.






✅ Checkpoint 2



Chạy ls — phải thấy đủ package.jsonserver.js. Chạy node -c server.js (kiểm tra cú pháp) — không in gì là đúng.




Nếu sai:





  • node -c server.js báo SyntaxError → có ký tự gõ thiếu (dấu ngoặc, dấu phẩy). Đọc số dòng trong lỗi và sửa.










Bước 3 — Chạy thử local



Trước khi container hoá, hãy chắc app chạy được trên máy trần đã. Đây là thói quen tốt: cô lập lỗi — nếu app hỏng ngay ở đây thì không phải lỗi Docker/K8s.



Cài thư viện rồi khởi động:




CODE
npm install
node server.js








  • npm install đọc package.json, tải Express về thư mục node_modules/.


  • node server.js khởi động app. Terminal sẽ "treo" lại (app đang chạy) và in dòng log.



Output mong đợi (ở terminal chạy app):




CODE
Todo API listening on port 3000






Mở một terminal thứ hai (cửa sổ/tab mới, vẫn ở thư mục todo-ops) và thử gọi API:




CODE
curl localhost:3000/todos






Output mong đợi:




CODE
[{"id":1,"title":"Đọc DevOps 101 Part 1","done":false}]






Thêm một todo mới:




CODE
curl -X POST -H 'Content-Type: application/json' -d '{"title":"học K8s"}' localhost:3000/todos








  • -X POST — dùng phương thức POST.


  • -H 'Content-Type: application/json' — báo cho server biết body là JSON.


  • -d '{...}' — dữ liệu gửi lên.



Output mong đợi:




CODE
{"id":2,"title":"học K8s","done":false}






Gọi lại curl localhost:3000/todos sẽ thấy cả hai todo. Xong thì quay lại terminal thứ nhất, nhấn Ctrl+C để dừng app.






✅ Checkpoint 3



GET /todos trả JSON mảng, POST trả về todo vừa tạo với id tăng dần.




Nếu sai:





  • curl báo Connection refused → app chưa chạy hoặc đã bị Ctrl+C. Kiểm tra terminal thứ nhất có dòng listening on port 3000 không.


  • POST trả {"error":"title is required"} → thiếu header -H 'Content-Type: application/json', nên Express không parse được body.


  • Cannot find module 'express' → quên chạy npm install.








💡 Hiểu thêm — Dockerfile là gì?

Dockerfilecông thức để Docker xây image. Mỗi dòng là một bước, và Docker chạy chúng theo thứ tự trên xuống. Docker cache lại từng bước, nên ta cố tình sắp xếp: thứ ít đổi (cài thư viện) đặt trên, thứ hay đổi (mã nguồn) đặt dưới — để build lần sau nhanh hơn.










Bước 4 — Đóng gói thành container



Tạo file Dockerfile (không có đuôi mở rộng) trong thư mục todo-ops:




CODE
# Bắt đầu từ một image có sẵn Node.js 20 trên nền Alpine Linux (nhẹ).
FROM node:20-alpine

# Đặt thư mục làm việc bên trong container. Các lệnh sau chạy trong đây.
WORKDIR /app

# Chỉ copy package.json (và package-lock nếu có) trước.
COPY package*.json ./

# Cài thư viện. Nhờ copy trước, bước này được cache lại khi mã nguồn đổi.
RUN npm install

# Bây giờ mới copy toàn bộ mã nguồn còn lại vào /app.
COPY . .

# Ghi chú rằng container mở port 3000 (tài liệu hoá, không tự mở cổng).
EXPOSE 3000

# Lệnh chạy khi container khởi động.
CMD ["node", "server.js"]






Giải thích từng dòng:





  • FROM node:20-alpine — nền tảng. Không cần tự cài Node; image này đã có sẵn.


  • WORKDIR /app — tạo & vào thư mục /app trong container.


  • COPY package*.json ./ — copy trước file khai báo thư viện. Đây là mẹo tận dụng cache (xem 💡 ở trên).


  • RUN npm install — cài Express bên trong image.


  • COPY . . — copy mọi thứ còn lại (gồm server.js) vào /app.


  • EXPOSE 3000 — khai báo cổng (mang tính tài liệu).


  • CMD ["node", "server.js"] — lệnh chạy app khi container start.




💡 Nên có .dockerignore: để tránh copy node_modules/ local (có thể build cho HĐH khác) và .git vào image, tạo file .dockerignore:




CODE
node_modules
.git




Bây giờ build image:




CODE
docker build -t todo-api:v1 .








  • -t todo-api:v1 — đặt tên:tag cho image. Ta dùng đúng todo-api:v1 như spec của series.


  • . (dấu chấm cuối) — "build context" là thư mục hiện tại; Docker gửi các file ở đây cho quá trình build.



Output mong đợi (rút gọn, kết thúc bằng dòng thành công):




CODE
 => [1/5] FROM docker.io/library/node:20-alpine ...
=> [4/5] RUN npm install ...
=> [5/5] COPY . . ...
=> => naming to docker.io/library/todo-api:v1









✅ Checkpoint 4



Chạy docker images | grep todo-api — phải thấy một dòng có todo-api và tag v1.




Nếu sai:





  • Cannot connect to the Docker daemon → Docker chưa chạy. Mở Docker Desktop / OrbStack rồi build lại.

  • Build dừng ở RUN npm install → thường do mạng, hoặc package.json sai cú pháp JSON. Chạy node -c không giúp cho JSON; kiểm tra dấu phẩy/ngoặc trong package.json.

  • Muốn chắc image chạy được, thử luôn: docker run --rm -p 3000:3000 todo-api:v1, rồi ở terminal khác curl localhost:3000/todos. Ctrl+C để dừng.








💡 Hiểu thêm — Kubernetes, cluster, node là gì?

Kubernetes (K8s) là hệ điều phối container: bạn khai báo "tôi muốn chạy app này, 1 bản, luôn sống" và K8s lo phần còn lại (khởi động lại khi chết, phân bổ tài nguyên...).





  • Cluster = cả dàn máy do K8s quản lý.


  • Node = một máy (thật hoặc ảo) trong cluster, nơi container thực sự chạy.


  • kind ("Kubernetes IN Docker") giả lập cả một cluster bên trong Docker trên máy bạn — hoàn hảo để học mà không tốn tiền cloud.










Bước 5 — Tạo cluster Kubernetes local bằng kind



Tạo file kind-config.yaml:




CODE
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP






Giải thích:





  • kind: Cluster / apiVersion — đây là file cấu hình cho công cụ kind (không phải manifest K8s thường).


  • nodes — danh sách máy trong cluster. Ta chỉ cần một node.


  • role: control-plane — node này vừa là "bộ não" (điều khiển cluster) vừa chạy app luôn (đủ cho môi trường học).


  • extraPortMappings — nối port 80 của máy bạn vào port 80 của node. Part 1 chưa dùng cổng này; ta đặt sẵn để Part 3 (Ingress) có thể mở app ra ngoài qua http://localhost. Đặt từ giờ để không phải tạo lại cluster sau.



Tạo cluster:




CODE
kind create cluster --name todo-ops --config kind-config.yaml






Output mong đợi (rút gọn):




CODE
Creating cluster "todo-ops" ...
✓ Ensuring node image ...
✓ Preparing nodes ...
✓ Starting control-plane ...
Set kubectl context to "kind-todo-ops"






Kiểm tra kubectl đã kết nối được cluster:




CODE
kubectl get nodes






Output mong đợi:




CODE
NAME                      STATUS   ROLES           AGE   VERSION
todo-ops-control-plane Ready control-plane 1m v1.3x.x






Tạo namespace todo để nhóm tài nguyên của app lại:




CODE
kubectl create namespace todo






Output mong đợi: namespace/todo created




💡 Hiểu thêm — Namespace: namespace là "ngăn kéo" logic trong cluster để tách biệt tài nguyên (theo team, theo app, theo môi trường). Ta để mọi thứ của app trong namespace todo cho gọn, thay vì trộn vào default.







✅ Checkpoint 5



kubectl get nodes → node STATUS = Ready. kubectl get ns → có dòng todo.




Nếu sai:




  • Node kẹt ở NotReady vài phút → chờ thêm; nếu quá lâu, Docker có thể thiếu RAM (cấp ≥4GB cho Docker Desktop).


  • port is already allocated khi tạo cluster → có gì đó đang chiếm port 80 trên máy. Tắt tiến trình đó, hoặc tạm bỏ khối extraPortMappings (sẽ xử lý ở Part 3).

  • Tạo lỗi và muốn làm lại sạch: kind delete cluster --name todo-ops rồi tạo lại.








💡 Hiểu thêm — Vì sao phải kind load image thủ công?

Cluster kind chạy bên trong Docker riêng của nó. Image todo-api:v1 bạn vừa build nằm ở Docker của máy host — kind không tự nhìn thấy nó, và ta cũng chưa đẩy image lên registry nào (như Docker Hub). Vì vậy phải "nạp" image từ host vào trong cluster kind bằng tay.










Bước 6 — Nạp image vào cluster kind






CODE
kind load docker-image todo-api:v1 --name todo-ops







  • Lệnh này copy image todo-api:v1 từ Docker host vào trong node của cluster todo-ops.



Output mong đợi:




CODE
Image: "todo-api:v1" with ID "sha256:..." not yet present on node "todo-ops-control-plane", loading...









✅ Checkpoint 6



Không có lỗi đỏ. (Nếu lệnh chạy xong im lặng hoặc in dòng loading... là ổn.)




Nếu sai:





  • image: "todo-api:v1" not present locally → chưa build image, hoặc gõ sai tên/tag. Quay lại Bước 4 chạy docker build lại.


  • Đây là lỗi hay gặp nhất về sau: nếu ở Bước 7 pod báo ErrImagePull / ImagePullBackOff, gần như chắc chắn là quên bước load này hoặc load xong nhưng sau đó build lại image mà chưa load lần nữa. Mỗi lần build image mới, phải kind load lại.








💡 Hiểu thêm — Pod, Deployment, Service khác nhau thế nào?





  • Pod: đơn vị chạy nhỏ nhất của K8s — bọc quanh một (hoặc vài) container. Pod dễ chết/bị thay.


  • Deployment: người quản lý Pod. Bạn nói "tôi muốn 1 pod luôn sống" — Deployment đảm bảo điều đó, pod chết thì nó tạo pod mới. Ta luôn tạo Deployment, không tạo Pod trần.


  • Service: địa chỉ mạng ổn định để gọi tới các Pod (vì pod hay đổi). Part 1 chưa cần Service — ta dùng port-forward để truy cập tạm. Part 3 sẽ thêm Service + Ingress.



💡 Hiểu thêm — Vì sao viết YAML thay vì lệnh tắt?

K8s có lệnh nhanh như kubectl create deployment .... Nhưng cách làm chuẩn của DevOps là declarative: mô tả trạng thái mong muốn trong file YAML, lưu vào git, rồi kubectl apply. File YAML là nguồn sự thật, có thể review, tái lập, và Part 6 (GitOps) sẽ tự động apply chúng từ git. Vì thế ngay từ đầu ta học viết YAML.










Bước 7 — Deploy bằng manifest YAML



Tạo thư mục k8s/ và file k8s/deployment.yaml:




CODE
mkdir k8s






Nội dung k8s/deployment.yaml:




CODE
apiVersion: apps/v1
kind: Deployment
metadata:
name: todo-api
labels:
app: todo-api
spec:
replicas: 1
selector:
matchLabels:
app: todo-api
template:
metadata:
labels:
app: todo-api
spec:
containers:
- name: todo-api
image: todo-api:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000






Giải thích các field quan trọng:





  • apiVersion: apps/v1 — nhóm & phiên bản API cho Deployment. K8s dùng cái này để biết cách hiểu file.


  • kind: Deployment — loại tài nguyên: một Deployment.


  • metadata.name — tên tài nguyên (todo-api). labels — nhãn để phân loại/tìm kiếm.


  • spec — mô tả trạng thái mong muốn:



    • replicas: 1 — muốn có 1 pod chạy.


    • selector.matchLabels — Deployment quản lý các pod có nhãn app: todo-api. Phải khớp với template.metadata.labels bên dưới, nếu không K8s báo lỗi.


    • template — "khuôn" để tạo pod:


    • template.metadata.labels — nhãn dán lên pod (khớp với selector).


    • template.spec.containers — danh sách container trong pod:



      • name — tên container.


      • image: todo-api:v1 — dùng đúng image ta đã build & load.


      • imagePullPolicy: IfNotPresentquan trọng cho kind: chỉ kéo image nếu chưa có sẵn trên node. Vì ta đã kind load, K8s dùng image local thay vì đi tìm trên internet (và fail).


      • ports.containerPort: 3000 — báo container lắng nghe port 3000.







Apply manifest vào namespace todo:




CODE
kubectl apply -f k8s/deployment.yaml -n todo






Output mong đợi: deployment.apps/todo-api created



Xem pod:




CODE
kubectl get pods -n todo






Output mong đợi (chờ ~10-30 giây cho tới khi Running):




CODE
NAME                        READY   STATUS    RESTARTS   AGE
todo-api-xxxxxxxxxx-yyyyy 1/1 Running 0 20s









✅ Checkpoint 7



Pod ở trạng thái Running và cột READY1/1.




Nếu sai:





  • STATUS = ErrImagePull hoặc ImagePullBackOff → K8s không tìm thấy image. Nguyên nhân số 1: quên kind load (Bước 6), hoặc thiếu imagePullPolicy: IfNotPresent. Chạy lại kind load docker-image todo-api:v1 --name todo-ops, rồi kubectl delete pod -n todo -l app=todo-api để pod được tạo lại.


  • STATUS = CrashLoopBackOff → container khởi động rồi chết liên tục, thường do lỗi trong server.js. Xem log để biết lý do:




CODE
  kubectl logs -n todo -l app=todo-api



Log sẽ in đúng lỗi Node.js (ví dụ SyntaxError, Cannot find module). Sửa server.js, build lại image, kind load lại, rồi kubectl rollout restart deploy/todo-api -n todo.





  • error validating data khi apply → YAML sai thụt lề (YAML cực nhạy với dấu cách; chỉ dùng space, không dùng tab) hoặc selector không khớp template.labels.








💡 Hiểu thêm — port-forward: app đang chạy bên trong cluster, máy bạn chưa có đường vào. kubectl port-forward mở một "đường hầm" tạm: request tới localhost:3000 trên máy bạn được chuyển thẳng vào pod. Đây là cách nhanh để debug/test, không phải cách mở app cho người dùng thật (việc đó là Service + Ingress ở Part 3).










Bước 8 — Truy cập app đang chạy trong cluster



Mở đường hầm tới Deployment (chạy nền với &):




CODE
kubectl port-forward -n todo deploy/todo-api 3000:3000 &








  • deploy/todo-api — forward tới Deployment todo-api.


  • 3000:3000 — port máy bạn : port trong pod.


  • & — chạy nền để bạn gõ lệnh tiếp trong cùng terminal.



Output mong đợi:




CODE
Forwarding from 127.0.0.1:3000 -> 3000






Gọi API (giờ là gọi vào app trong cluster):




CODE
curl localhost:3000/todos






Output mong đợi:




CODE
[{"id":1,"title":"Đọc DevOps 101 Part 1","done":false}]






Xong thì tắt đường hầm nền:




CODE
kill %1








  • %1 — job chạy nền số 1 (chính là port-forward). Lệnh này dừng nó.






✅ Checkpoint 8



curl localhost:3000/todos trả JSON mảng todo — từ app chạy trong Kubernetes. Bạn vừa hoàn thành vòng đời: code → image → cluster → truy cập.




Nếu sai:





  • curl báo Connection refused → đường hầm chưa mở hoặc đã bị kill. Xem lại có dòng Forwarding from ... không; nếu terminal đã chạy nền, gõ jobs để xem job còn sống.


  • unable to forward ... pod is not running → pod chưa Running. Quay lại Checkpoint 7.

  • Nhớ kill %1 sau khi xong; nếu quên, port 3000 vẫn bị chiếm cho lần sau. Có thể tắt bằng kill %1 hoặc đóng terminal.










Bạn đã hiểu gì



Tóm lại, bạn vừa đi trọn con đường từ số 0:





  • App → image: viết Todo API Node.js, đóng gói bằng Dockerfile thành image todo-api:v1.


  • Cluster local: dùng kind tạo cluster todo-ops chạy trong Docker, tạo namespace todo.


  • Nạp image: hiểu vì sao phải kind load (cluster không thấy Docker host).


  • Deploy declarative: viết k8s/deployment.yaml thật, hiểu apiVersion / kind / metadata / spec / selector / template / containers, và vì sao imagePullPolicy: IfNotPresent quan trọng với kind.


  • Khái niệm nền: container vs image, Pod vs Deployment vs Service, namespace, port-forward.


  • Cách tự sửa lỗi: đọc kubectl get pods (trạng thái) và kubectl logs (nguyên nhân), phân biệt ImagePullBackOff với CrashLoopBackOff.



Cluster của bạn vẫn đang chạy — giữ nguyên, Part 2 sẽ dùng tiếp. (Nếu cần dọn hẳn: kind delete cluster --name todo-ops.)






Tiếp theo



Trong Part 2 → Config & State, ta sẽ:




  • Thêm PostgreSQL để todo không mất khi restart (thay mảng in-memory).

  • Tách cấu hình ra khỏi code bằng ConfigMapSecret (chuỗi kết nối DB, mật khẩu).

  • Cập nhật app đọc config từ biến môi trường thay vì hard-code.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
Header and Footer not showing in Excel
1 Quelle
Burn Out, Or Fade Away
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Part 1 — Container hoá app & chạy trong Kubernetes local

Thematisch verwandte Begriffe: Part, Container, chạy, trong · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...