Danh sách bài viết trong series Học Kubernetes Từ Cơ Bản Đến Chứng Chỉ CKAD
- Lộ Trình Học Kubernetes Từ Cơ Bản Đến Chứng Chỉ CKAD
- Bài 1: Giới Thiệu Kubernetes Và Khái Niệm Cluster Cho CKAD
- Bài 2: Cài Đặt Minikube Và sử dụng kubectl Cơ Bản
- Bài 3: Quản Lý Pod Cơ Bản (Create, Delete, Describe)
- Bài 4: Sử Dụng ConfigMap Và Secret Trong YAML
- Bài 5: Quản Lý Environment Variables Và Command/Args
- Bài 6: Cấu Hình Deployment Và Replica Set
- Bài 7: Thiết Kế Pod Với Nhiều Container
- Bài 8: Sử Dụng Sidecar Và Init Container
- Bài 9: Chia Sẻ Tài Nguyên Giữa Các Container
- Bài 10: Giám Sát Log Và Events Với kubectl logs
- Bài 11: Debug Pod Với kubectl describe Và exec
- Bài 12: Tối Ưu Pod Với Resource Limits Và Requests
- Bài 13: Sử Dụng Liveness Và Readiness Probes
- Bài 14: Tối Ưu Hóa Pod Với HPA (Horizontal Pod Autoscaler)
- Bài 15: Cấu Hình Service (ClusterIP, NodePort)
- Bài 16: Sử Dụng Ingress Và Network Policy
- Bài 17: Quản Lý DNS Và Load Balancing Trong Kubernetes
- Bài 18: Sử Dụng Volume (emptyDir, hostPath)
- Bài 19: Cấu Hình Persistent Volume Và Persistent Volume Claim
- Bài 20: Tổng Kết, Mẹo Thi CKAD, Bài Tập Thực Hành Cuối
Sau khi đã học cách tối ưu Pod với HPA (Horizontal Pod Autoscaler) ở Bài 14, chúng ta chính thức bước sang domain Services & Networking (20%) một trong những phần nặng nhất và hay ra đề nhất trong kỳ thi CKAD.
Bài viết này thuộc đúng domain đó, tập trung vào Service, thành phần cơ bản để kết nối các Pod ổn định và expose ứng dụng ra ngoài. Trong kỳ thi, bạn thường gặp những task như tạo Service kiểu ClusterIP để map cổng 8080 của container ra 80 trong cluster, chuyển một Service từ ClusterIP sang NodePort với cổng cố định 30080, hoặc tạo một Service không có selector rồi tự định nghĩa Endpoints. Những câu này tưởng đơn giản nhưng rất dễ mất điểm nếu bạn nhầm giữa port/targetPort/nodePort hoặc đặt selector lệch nhãn Pod.
Service Là Gì? Tại Sao Cần Nó?
Service là một abstraction layer giúp bạn kết nối đến các Pod một cách ổn định, dù Pod có chết đi sống lại, IP thay đổi liên tục.
| Vấn đề | Giải pháp bằng Service |
|---|---|
| Pod có IP động => Không thể hardcode | Service có IP tĩnh (ClusterIP) |
| Nhiều Pod cùng Service => cần load balance | Service tự động round-robin |
| Cần expose ra ngoài cluster | Dùng NodePort hoặc LoadBalancer |
CKAD Tip: Không bao giờ kết nối trực tiếp bằng Pod IP luôn dùng Service Name (DNS).
Các Loại Service Trong Kubernetes
| Loại | Mục đích | Port mở | Dùng khi |
|---|---|---|---|
| ClusterIP (default) | Giao tiếp trong cluster | Chỉ nội bộ | API backend, DB, microservices |
| NodePort | Expose ra ngoài qua node | 30000–32767 | Dev/test, truy cập tạm thời |
| LoadBalancer | Expose qua cloud LB | Tùy cloud | Production (AWS ELB, GCP, etc.) |
| ExternalName | Map đến DNS bên ngoài | Không mở port | Gọi API bên ngoài |
Trong môi trường thi CKAD, bạn chỉ cần nhớ ClusterIP và NodePort. LoadBalancer thường không khả dụng trong môi trường thi.
Dưới đây là minh họa về các loại Service trong Kubernetes để bạn dễ hình dung:
Cấu Trúc YAML Service Cơ Bản
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
Giải thích nhanh:
port: cổng mà Service expose trong cluster.targetPort: cổng container trong Pod.nodePort: chỉ dùng khitype: NodePort.
CKAD Golden Rule: port là của Service, targetPort là của Pod, nodePort là của Node.
Thực Hành 1: Tạo Deployment + Service ClusterIP
-
Tạo Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-app spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80kubectl apply -f nginx-deployment.yaml -
Expose Deployment bằng lệnh Imperative
kubectl expose deployment nginx-app \ --name=nginx-service \ --port=80 \ --target-port=80 -
Tạo Service YAML (Cách thi yêu cầu)
apiVersion: v1 kind: Service metadata: name: nginx-service-yaml spec: selector: app: nginx ports: - protocol: TCP port: 8080 targetPort: 80 type: ClusterIP -
Test kết nối nội bộ
kubectl run test-pod --image=busybox --rm -it --restart=Never -- sh wget -qO- http://nginx-service-yaml:8080
Mẹo: Kubernetes tự resolve DNS theo ServiceName.Namespace.svc.cluster.local.
Thực Hành 2: Chuyển Sang NodePort Expose Ra Ngoài
Service NodePort YAML:
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
selector:
app: nginx
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
Áp dụng:
kubectl apply -f nginx-nodeport.yaml
Truy cập từ máy host:
minikube service nginx-nodeport --url
curl http://$(minikube ip):30080
Trong CKAD: NodePort thường dùng để xác thực ứng dụng chạy đúng (ví dụ 30080, 30081).
So Sánh ClusterIP vs NodePort
| Tiêu chí | ClusterIP | NodePort |
|---|---|---|
type |
Mặc định | NodePort |
| IP | Nội bộ | IP của Node |
| Port range | Tùy ý | 30000–32767 |
| Sử dụng | Microservices | Test, demo |
Có nodePort? |
Không | Có |
| Lệnh nhanh | kubectl expose |
kubectl expose --type=NodePort |
Service Không Có Selector (Rất Hay Ra Đề)
Đề thi mẫu:
“Tạo Service backend-external trỏ đến IP 203.0.113.10:8080 mà không dùng selector.”
Giải pháp:
apiVersion: v1
kind: Service
metadata:
name: backend-external
spec:
ports:
- port: 80
targetPort: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: backend-external
subsets:
- addresses:
- ip: 203.0.113.10
ports:
- port: 8080
Tip: Service không selector + Endpoints = kết nối tới service ngoài cluster.
Debug Service Không Kết Nối
| Lỗi | Nguyên nhân | Cách fix |
|---|---|---|
Connection refused |
Sai targetPort |
Kiểm tra containerPort |
Service not found |
Sai tên | kubectl get svc |
No endpoints |
Sai selector | kubectl get pod -l app=xxx |
Pending |
Pod chưa ready | kubectl get pod |
Debug nhanh:
kubectl describe svc nginx-service
kubectl get endpoints nginx-service
Bài Tập CKAD
Đề:
Trong namespace exam, tạo:
- Deployment
web(image:httpd, replicas: 2) - Service
web-svc(ClusterIP, port 8080→80) - Service
web-ext(NodePort, port 80→80, nodePort: 30081)
Đáp án:
web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: exam
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: httpd
image: httpd:alpine
ports:
- containerPort: 80
web-services.yaml
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: exam
spec:
selector:
app: web
ports:
- port: 8080
targetPort: 80
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: web-ext
namespace: exam
spec:
selector:
app: web
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30081
Chạy:
kubectl create ns exam
kubectl apply -f web-deployment.yaml
kubectl apply -f web-services.yaml
kubectl -n exam get svc,pod,ep
Liên Hệ Với Chứng Chỉ CKAD
Domain Services & Networking (20%) luôn có 2–3 câu hỏi liên quan đến Service, chiếm số điểm khá lớn vì kiểm tra khả năng hiểu đúng cách expose và định tuyến nội bộ trong Kubernetes. Trong kỳ thi, bạn thường gặp yêu cầu tạo Service ClusterIP để route cổng 8080 của container sang 80 trong cluster, chuyển một Service sang NodePort với cổng cụ thể như 30080, hoặc tạo Service không có selector rồi định nghĩa thủ công Endpoints để trỏ đến IP cố định.
Các lỗi phổ biến khiến thí sinh mất điểm là nhầm lẫn giữa port, targetPort, nodePort; selector không khớp với nhãn Pod nên Service không có endpoints; hoặc quên thêm type: NodePort khi đề bài yêu cầu expose ra ngoài.
Mẹo thi:
- Luôn ghi rõ
type: NodePortkhi đề yêu cầu expose ra ngoài, tránh bị mặc định là ClusterIP. portlà cổng của Service,targetPortlà cổng container trong Pod, vànodePortchỉ có khi Service là NodePort.- Kiểm tra `kubectl get endpoints
` ngay sau khi apply để xác minh selector hoạt động đúng. - Trong bài thi, có thể dùng
kubectl exposeđể tạo nhanh Service, nhưng khi nộp bài nên dùng YAML chuẩn để dễ chỉnh sửa.
Tóm Tắt Kiến Thức Cho CKAD
| Khái niệm | Giá trị cần nhớ |
|---|---|
| Default type | ClusterIP |
| NodePort range | 30000–32767 |
port |
Cổng Service |
targetPort |
Cổng container |
nodePort |
Chỉ khi type: NodePort |
| Lệnh nhanh | kubectl expose deploy X --port=A --target-port=B --type=NodePort |
Kết Luận
Bài này mình đã hướng dẫn chi tiết cách tạo và quản lý Service trong Kubernetes, từ ClusterIP, NodePort đến Service không có selector và cách debug khi Service không hoạt động. Bạn giờ đã có thể kết nối các Pod ổn định, expose ứng dụng ra ngoài, và kiểm tra routing một cách thành thạo trong môi trường thực tế. Tiếp theo, ở Bài 16: Sử Dụng Ingress Và Network Policy, chúng ta sẽ mở rộng sang phần routing nâng cao và bảo mật mạng nội bộ hai kỹ năng quan trọng để hoàn thiện domain Services & Networking (20%).





