@xdev-asia/xdev-knowledge-mcp 1.0.44 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/01-kien-truc-cka-kubeadm.md +133 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/02-cluster-upgrade-kubeadm.md +147 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/03-rbac-cka.md +152 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/02-workloads-scheduling/lessons/04-deployments-daemonsets-statefulsets.md +186 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/02-workloads-scheduling/lessons/05-scheduling-taints-affinity.md +163 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/03-services-networking/lessons/06-services-endpoints-coredns.md +145 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/03-services-networking/lessons/07-ingress-networkpolicies-cni.md +172 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/04-storage/lessons/08-persistent-volumes-storageclass.md +159 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/09-etcd-backup-restore.md +149 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/10-troubleshooting-nodes.md +153 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/11-troubleshooting-workloads.md +146 -0
- package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/12-troubleshooting-networking-exam.md +170 -0
- package/content/series/luyen-thi/luyen-thi-cka/index.md +1 -1
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/01-app-design-build/lessons/01-multi-container-pods.md +146 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/01-app-design-build/lessons/02-jobs-cronjobs-resources.md +174 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/02-app-deployment/lessons/03-rolling-updates-rollbacks.md +148 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/02-app-deployment/lessons/04-helm-kustomize.md +181 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/03-app-observability/lessons/05-probes-logging-debugging.md +183 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/06-configmaps-secrets.md +182 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/07-securitycontext-pod-security.md +168 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/08-resources-qos.md +168 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/05-services-networking/lessons/09-services-ingress.md +182 -0
- package/content/series/luyen-thi/luyen-thi-ckad/chapters/05-services-networking/lessons/10-networkpolicies-exam-strategy.md +236 -0
- package/content/series/luyen-thi/luyen-thi-ckad/index.md +1 -1
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/01-kien-truc-kubernetes.md +137 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/02-pods-workloads-controllers.md +142 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/03-services-networking-storage.md +155 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/04-rbac-security.md +137 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/02-container-orchestration/lessons/05-container-runtimes-oci.md +137 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/02-container-orchestration/lessons/06-orchestration-patterns.md +147 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/03-cloud-native-architecture/lessons/07-cloud-native-architecture.md +143 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/04-observability-delivery/lessons/08-observability.md +143 -0
- package/content/series/luyen-thi/luyen-thi-kcna/chapters/04-observability-delivery/lessons/09-helm-gitops-cicd.md +162 -0
- package/content/series/luyen-thi/luyen-thi-kcna/index.md +1 -1
- package/data/quizzes.json +1059 -0
- package/package.json +1 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ckad-d4-l08
|
|
3
|
+
title: 'Bài 8: Resource Requests, Limits & QoS'
|
|
4
|
+
slug: 08-resources-qos
|
|
5
|
+
description: >-
|
|
6
|
+
Resource requests vs limits (CPU, Memory). QoS classes: Guaranteed, Burstable,
|
|
7
|
+
BestEffort. LimitRange defaults và ResourceQuota namespace limits.
|
|
8
|
+
duration_minutes: 50
|
|
9
|
+
is_free: true
|
|
10
|
+
video_url: null
|
|
11
|
+
sort_order: 8
|
|
12
|
+
section_title: "Domain 4: Application Environment, Configuration and Security (25%)"
|
|
13
|
+
course:
|
|
14
|
+
id: lt-ckad-series-001
|
|
15
|
+
title: 'Luyện thi CKAD — Certified Kubernetes Application Developer'
|
|
16
|
+
slug: luyen-thi-ckad
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<img src="/storage/uploads/2026/04/k8s-cert-ckad-bai8-qos-classes.png" alt="Resource Requests, Limits và QoS Classes — Guaranteed, Burstable, BestEffort" style="max-width: 800px; width: 100%; border-radius: 12px;" />
|
|
20
|
+
|
|
21
|
+
<h2 id="requests-limits">1. Requests vs Limits</h2>
|
|
22
|
+
|
|
23
|
+
<pre><code class="language-text">resources:
|
|
24
|
+
requests:
|
|
25
|
+
cpu: "250m" # 250 millicores = 0.25 CPU (scheduling)
|
|
26
|
+
memory: "128Mi" # Minimum guaranteed memory
|
|
27
|
+
limits:
|
|
28
|
+
cpu: "500m" # Max CPU (throttled but not killed)
|
|
29
|
+
memory: "256Mi" # Max memory (killed if exceeded → OOMKilled)</code></pre>
|
|
30
|
+
|
|
31
|
+
<table>
|
|
32
|
+
<thead><tr><th>Resource</th><th>Khi vượt requests</th><th>Khi vượt limits</th></tr></thead>
|
|
33
|
+
<tbody>
|
|
34
|
+
<tr><td><strong>CPU</strong></td><td>Chạy bình thường (burst)</td><td>Bị throttled (chậm lại, không kill)</td></tr>
|
|
35
|
+
<tr><td><strong>Memory</strong></td><td>Chạy bình thường</td><td>Container bị kill → OOMKilled</td></tr>
|
|
36
|
+
</tbody>
|
|
37
|
+
</table>
|
|
38
|
+
|
|
39
|
+
<pre><code class="language-text">CPU units:
|
|
40
|
+
1 CPU = 1000m (millicores)
|
|
41
|
+
0.5 CPU = 500m
|
|
42
|
+
100m = 0.1 CPU
|
|
43
|
+
|
|
44
|
+
Memory units:
|
|
45
|
+
Ki (Kibibyte) = 1024 bytes
|
|
46
|
+
Mi (Mebibyte) = 1024 Ki
|
|
47
|
+
Gi (Gibibyte) = 1024 Mi
|
|
48
|
+
(NOT KB/MB/GB which are decimal)</code></pre>
|
|
49
|
+
|
|
50
|
+
<h2 id="qos">2. QoS Classes</h2>
|
|
51
|
+
|
|
52
|
+
<pre><code class="language-text">QoS = Quality of Service (kiểm soát eviction priority)
|
|
53
|
+
|
|
54
|
+
┌─────────────────────────────────────────────────────────┐
|
|
55
|
+
│ GUARANTEED — Last to evict │
|
|
56
|
+
│ ✓ CPU requests == CPU limits │
|
|
57
|
+
│ ✓ Memory requests == Memory limits │
|
|
58
|
+
│ ✓ ALL containers in pod must satisfy │
|
|
59
|
+
├─────────────────────────────────────────────────────────┤
|
|
60
|
+
│ BURSTABLE — Middle priority │
|
|
61
|
+
│ ✓ At least one container has requests OR limits │
|
|
62
|
+
│ ✗ Doesn't meet Guaranteed criteria │
|
|
63
|
+
├─────────────────────────────────────────────────────────┤
|
|
64
|
+
│ BESTEFFORT — First to evict │
|
|
65
|
+
│ ✗ NO requests, NO limits set at all │
|
|
66
|
+
└─────────────────────────────────────────────────────────┘</code></pre>
|
|
67
|
+
|
|
68
|
+
<table>
|
|
69
|
+
<thead><tr><th>QoS Class</th><th>Điều kiện</th><th>Eviction priority</th></tr></thead>
|
|
70
|
+
<tbody>
|
|
71
|
+
<tr><td><strong>Guaranteed</strong></td><td>requests == limits cho CPU và Memory (tất cả containers)</td><td>Thấp nhất (last evicted)</td></tr>
|
|
72
|
+
<tr><td><strong>Burstable</strong></td><td>Ít nhất một container có request/limit, không đủ Guaranteed</td><td>Trung bình</td></tr>
|
|
73
|
+
<tr><td><strong>BestEffort</strong></td><td>Không có bất kỳ request/limit nào</td><td>Cao nhất (first evicted)</td></tr>
|
|
74
|
+
</tbody>
|
|
75
|
+
</table>
|
|
76
|
+
|
|
77
|
+
<blockquote><p><strong>Exam tip:</strong> Kiểm tra QoS class của pod: <code>kubectl describe pod <name> | grep -i qos</code> hoặc <code>kubectl get pod <name> -o jsonpath='{.status.qosClass}'</code>. Để đạt Guaranteed: set requests = limits cho CẢ CPU lẫn memory, trong CẢ containers (kể cả init containers).</p></blockquote>
|
|
78
|
+
|
|
79
|
+
<h2 id="limitrange">3. LimitRange</h2>
|
|
80
|
+
|
|
81
|
+
<p>LimitRange đặt default requests/limits cho Pods trong namespace — áp dụng khi Pod không tự set.</p>
|
|
82
|
+
|
|
83
|
+
<pre><code class="language-text">apiVersion: v1
|
|
84
|
+
kind: LimitRange
|
|
85
|
+
metadata:
|
|
86
|
+
name: mem-limit-range
|
|
87
|
+
namespace: development
|
|
88
|
+
spec:
|
|
89
|
+
limits:
|
|
90
|
+
- type: Container
|
|
91
|
+
default: # Default limits (khi container không set limits)
|
|
92
|
+
memory: 512Mi
|
|
93
|
+
cpu: 500m
|
|
94
|
+
defaultRequest: # Default requests (khi container không set requests)
|
|
95
|
+
memory: 256Mi
|
|
96
|
+
cpu: 250m
|
|
97
|
+
max: # Maximum allowed limits
|
|
98
|
+
memory: 1Gi
|
|
99
|
+
cpu: "1"
|
|
100
|
+
min: # Minimum required requests
|
|
101
|
+
memory: 64Mi
|
|
102
|
+
cpu: 50m</code></pre>
|
|
103
|
+
|
|
104
|
+
<h2 id="resourcequota">4. ResourceQuota</h2>
|
|
105
|
+
|
|
106
|
+
<pre><code class="language-text">apiVersion: v1
|
|
107
|
+
kind: ResourceQuota
|
|
108
|
+
metadata:
|
|
109
|
+
name: production-quota
|
|
110
|
+
namespace: production
|
|
111
|
+
spec:
|
|
112
|
+
hard:
|
|
113
|
+
# Compute resources
|
|
114
|
+
requests.cpu: "10"
|
|
115
|
+
requests.memory: 20Gi
|
|
116
|
+
limits.cpu: "20"
|
|
117
|
+
limits.memory: 40Gi
|
|
118
|
+
# Object counts
|
|
119
|
+
pods: "50"
|
|
120
|
+
services: "20"
|
|
121
|
+
persistentvolumeclaims: "10"
|
|
122
|
+
secrets: "30"
|
|
123
|
+
configmaps: "30"</code></pre>
|
|
124
|
+
|
|
125
|
+
<blockquote><p><strong>Exam tip:</strong> Nếu namespace có ResourceQuota yêu cầu resource limits, thì <strong>tất cả Pods</strong> trong namespace đó PHẢI set resource requests và limits — hoặc phải có LimitRange cung cấp defaults. Nếu không set, API server sẽ reject Pod creation.</p></blockquote>
|
|
126
|
+
|
|
127
|
+
<h2 id="cheatsheet">5. Cheat Sheet</h2>
|
|
128
|
+
|
|
129
|
+
<table>
|
|
130
|
+
<thead><tr><th>Tình huống</th><th>Giải pháp</th></tr></thead>
|
|
131
|
+
<tbody>
|
|
132
|
+
<tr><td>Container bị OOMKilled</td><td>Tăng <code>limits.memory</code></td></tr>
|
|
133
|
+
<tr><td>Container bị throttled (chậm)</td><td>Tăng <code>limits.cpu</code></td></tr>
|
|
134
|
+
<tr><td>Pod không schedule được</td><td>Giảm <code>requests</code> hoặc scale cluster</td></tr>
|
|
135
|
+
<tr><td>QoS là Guaranteed</td><td><code>requests == limits</code> cho CPU và Memory</td></tr>
|
|
136
|
+
<tr><td>Set default limits cho namespace</td><td><strong>LimitRange</strong></td></tr>
|
|
137
|
+
<tr><td>Giới hạn tổng resource của namespace</td><td><strong>ResourceQuota</strong></td></tr>
|
|
138
|
+
</tbody>
|
|
139
|
+
</table>
|
|
140
|
+
|
|
141
|
+
<h2 id="practice">6. Practice Questions</h2>
|
|
142
|
+
|
|
143
|
+
<p><strong>Q1:</strong> A container has cpu requests=200m, cpu limits=500m, memory requests=256Mi, memory limits=256Mi. What is the QoS class of this Pod (assuming it's the only container)?</p>
|
|
144
|
+
<ul>
|
|
145
|
+
<li>A) Guaranteed</li>
|
|
146
|
+
<li>B) Burstable ✓</li>
|
|
147
|
+
<li>C) BestEffort</li>
|
|
148
|
+
<li>D) Critical</li>
|
|
149
|
+
</ul>
|
|
150
|
+
<p><em>Explanation: For Guaranteed, all requests must equal limits. Here cpu requests (200m) ≠ cpu limits (500m). Memory requests do equal limits (256Mi). Since the criteria for Guaranteed is not fully met, but resources are set, the class is Burstable.</em></p>
|
|
151
|
+
|
|
152
|
+
<p><strong>Q2:</strong> A container's memory usage exceeds its memory limit. What happens?</p>
|
|
153
|
+
<ul>
|
|
154
|
+
<li>A) The container is throttled (slowed down)</li>
|
|
155
|
+
<li>B) The container is terminated and restarted (OOMKilled) ✓</li>
|
|
156
|
+
<li>C) The container is evicted from the node</li>
|
|
157
|
+
<li>D) The Pod is rescheduled to a different node</li>
|
|
158
|
+
</ul>
|
|
159
|
+
<p><em>Explanation: Unlike CPU (which is compressible — throttled but not killed), memory is incompressible. When a container exceeds its memory limit, it receives an OOMKilled exit code and is restarted by the container runtime. Repeated OOMKills lead to CrashLoopBackOff.</em></p>
|
|
160
|
+
|
|
161
|
+
<p><strong>Q3:</strong> A namespace has a ResourceQuota requiring limits.memory to be set on all Pods. A new Pod is created without any resource limits. What happens?</p>
|
|
162
|
+
<ul>
|
|
163
|
+
<li>A) The Pod starts with no limits (ResourceQuota applies only to running Pods)</li>
|
|
164
|
+
<li>B) The Pod is rejected by the API server unless a LimitRange provides defaults ✓</li>
|
|
165
|
+
<li>C) The Pod starts with default limits of 512Mi</li>
|
|
166
|
+
<li>D) The ResourceQuota is automatically updated to exclude this Pod</li>
|
|
167
|
+
</ul>
|
|
168
|
+
<p><em>Explanation: When a ResourceQuota exists in a namespace that covers memory limits, ALL Pods must specify memory limits. If no LimitRange provides defaults, the API server rejects the Pod. Solution: either set limits on the Pod, or create a LimitRange with defaultRequest/default values for the namespace.</em></p>
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ckad-d5-l09
|
|
3
|
+
title: 'Bài 9: Services & Ingress'
|
|
4
|
+
slug: 09-services-ingress
|
|
5
|
+
description: >-
|
|
6
|
+
Service types: ClusterIP, NodePort, LoadBalancer, ExternalName. kubectl expose.
|
|
7
|
+
Ingress resources, IngressClass, TLS termination và path-based routing.
|
|
8
|
+
duration_minutes: 60
|
|
9
|
+
is_free: true
|
|
10
|
+
video_url: null
|
|
11
|
+
sort_order: 9
|
|
12
|
+
section_title: "Domain 5: Services and Networking (20%)"
|
|
13
|
+
course:
|
|
14
|
+
id: lt-ckad-series-001
|
|
15
|
+
title: 'Luyện thi CKAD — Certified Kubernetes Application Developer'
|
|
16
|
+
slug: luyen-thi-ckad
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<img src="/storage/uploads/2026/04/k8s-cert-ckad-bai9-services-ingress.png" alt="Service Types và Ingress Routing — ClusterIP, NodePort, LoadBalancer" style="max-width: 800px; width: 100%; border-radius: 12px;" />
|
|
20
|
+
|
|
21
|
+
<h2 id="service-types">1. Service Types</h2>
|
|
22
|
+
|
|
23
|
+
<table>
|
|
24
|
+
<thead><tr><th>Type</th><th>Access</th><th>Dùng khi nào</th></tr></thead>
|
|
25
|
+
<tbody>
|
|
26
|
+
<tr><td><strong>ClusterIP</strong></td><td>Internal only (cluster DNS)</td><td>Service-to-service communication (default)</td></tr>
|
|
27
|
+
<tr><td><strong>NodePort</strong></td><td>NodeIP:30000-32767</td><td>Dev/test external access</td></tr>
|
|
28
|
+
<tr><td><strong>LoadBalancer</strong></td><td>Cloud LB external IP</td><td>Production external access (cloud)</td></tr>
|
|
29
|
+
<tr><td><strong>ExternalName</strong></td><td>CNAME DNS alias</td><td>Route to external DNS name</td></tr>
|
|
30
|
+
</tbody>
|
|
31
|
+
</table>
|
|
32
|
+
|
|
33
|
+
<pre><code class="language-text">ClusterIP (default):
|
|
34
|
+
apiVersion: v1
|
|
35
|
+
kind: Service
|
|
36
|
+
metadata:
|
|
37
|
+
name: myapp-svc
|
|
38
|
+
spec:
|
|
39
|
+
type: ClusterIP # Can omit — default
|
|
40
|
+
selector:
|
|
41
|
+
app: myapp
|
|
42
|
+
ports:
|
|
43
|
+
- port: 80 # Service port (what clients connect to)
|
|
44
|
+
targetPort: 8080 # Container port (where app listens)
|
|
45
|
+
|
|
46
|
+
NodePort:
|
|
47
|
+
spec:
|
|
48
|
+
type: NodePort
|
|
49
|
+
ports:
|
|
50
|
+
- port: 80
|
|
51
|
+
targetPort: 8080
|
|
52
|
+
nodePort: 30080 # Optional: 30000-32767 range (auto-assigned if omitted)</code></pre>
|
|
53
|
+
|
|
54
|
+
<h2 id="kubectl-expose">2. kubectl expose</h2>
|
|
55
|
+
|
|
56
|
+
<pre><code class="language-text"># Expose Deployment as ClusterIP (default)
|
|
57
|
+
kubectl expose deployment myapp --port=80 --target-port=8080
|
|
58
|
+
|
|
59
|
+
# Expose as NodePort
|
|
60
|
+
kubectl expose deployment myapp --port=80 --target-port=8080 --type=NodePort
|
|
61
|
+
|
|
62
|
+
# Expose a Pod
|
|
63
|
+
kubectl expose pod mypod --port=80 --name=mypod-svc
|
|
64
|
+
|
|
65
|
+
# Expose existing service quickly and redirect traffic
|
|
66
|
+
kubectl run nginx --image=nginx --port=80 --expose
|
|
67
|
+
# This creates both the Pod AND the ClusterIP Service</code></pre>
|
|
68
|
+
|
|
69
|
+
<blockquote><p><strong>Exam tip:</strong> <code>kubectl expose</code> cần selector match với Pod labels. Nếu Deployment đang dùng <code>app: myapp</code>, Service selector phải là <code>app: myapp</code>. Flag <code>--expose</code> khi dùng với <code>kubectl run</code> tạo cả Pod lẫn Service cùng lúc — rất nhanh trong exam.</p></blockquote>
|
|
70
|
+
|
|
71
|
+
<h2 id="ingress">3. Ingress</h2>
|
|
72
|
+
|
|
73
|
+
<p>Ingress là L7 HTTP/HTTPS routing — một điểm vào, route đến nhiều Services dựa trên host/path.</p>
|
|
74
|
+
|
|
75
|
+
<pre><code class="language-text"> ┌─────────────────────────────────┐
|
|
76
|
+
Internet ──────────►│ Ingress Controller (nginx) │
|
|
77
|
+
│ │
|
|
78
|
+
│ /api ──────────► api-service │
|
|
79
|
+
│ /web ──────────► web-service │
|
|
80
|
+
│ blog.example.com → blog-service │
|
|
81
|
+
└─────────────────────────────────┘</code></pre>
|
|
82
|
+
|
|
83
|
+
<pre><code class="language-text">apiVersion: networking.k8s.io/v1
|
|
84
|
+
kind: Ingress
|
|
85
|
+
metadata:
|
|
86
|
+
name: myapp-ingress
|
|
87
|
+
annotations:
|
|
88
|
+
nginx.ingress.kubernetes.io/rewrite-target: /
|
|
89
|
+
spec:
|
|
90
|
+
ingressClassName: nginx # Which IngressClass to use
|
|
91
|
+
tls:
|
|
92
|
+
- hosts:
|
|
93
|
+
- myapp.example.com
|
|
94
|
+
secretName: myapp-tls # TLS cert stored as Secret
|
|
95
|
+
rules:
|
|
96
|
+
- host: myapp.example.com
|
|
97
|
+
http:
|
|
98
|
+
paths:
|
|
99
|
+
- path: /api
|
|
100
|
+
pathType: Prefix # Prefix or Exact
|
|
101
|
+
backend:
|
|
102
|
+
service:
|
|
103
|
+
name: api-service
|
|
104
|
+
port:
|
|
105
|
+
number: 80
|
|
106
|
+
- path: /web
|
|
107
|
+
pathType: Prefix
|
|
108
|
+
backend:
|
|
109
|
+
service:
|
|
110
|
+
name: web-service
|
|
111
|
+
port:
|
|
112
|
+
number: 80</code></pre>
|
|
113
|
+
|
|
114
|
+
<table>
|
|
115
|
+
<thead><tr><th>pathType</th><th>Hành vi</th><th>Ví dụ</th></tr></thead>
|
|
116
|
+
<tbody>
|
|
117
|
+
<tr><td><strong>Exact</strong></td><td>Match chính xác path</td><td><code>/api</code> chỉ match <code>/api</code></td></tr>
|
|
118
|
+
<tr><td><strong>Prefix</strong></td><td>Match path prefix</td><td><code>/api</code> match <code>/api</code>, <code>/api/v1</code>, <code>/api/users</code></td></tr>
|
|
119
|
+
<tr><td><strong>ImplementationSpecific</strong></td><td>Tùy IngressClass</td><td>Depends on controller</td></tr>
|
|
120
|
+
</tbody>
|
|
121
|
+
</table>
|
|
122
|
+
|
|
123
|
+
<blockquote><p><strong>Exam tip:</strong> Ingress cần <strong>Ingress Controller</strong> (như nginx, traefik) mới hoạt động — Ingress resource chỉ là config. IngressClass chỉ định controller nào xử lý. Trong exam, IngressClass thường đã được setup sẵn. Nhớ check <code>kubectl get ingressclass</code> để biết tên.</p></blockquote>
|
|
124
|
+
|
|
125
|
+
<h2 id="debug-service">4. Debug Service Connectivity</h2>
|
|
126
|
+
|
|
127
|
+
<pre><code class="language-text"># Check service exists và endpoints
|
|
128
|
+
kubectl get services
|
|
129
|
+
kubectl get endpoints myapp-svc
|
|
130
|
+
|
|
131
|
+
# Test connectivity từ trong cluster (create temp pod)
|
|
132
|
+
kubectl run test --image=busybox --rm -it -- wget -qO- http://myapp-svc
|
|
133
|
+
kubectl run test --image=curlimages/curl --rm -it -- curl http://myapp-svc:80
|
|
134
|
+
|
|
135
|
+
# Check if selector matches pods
|
|
136
|
+
kubectl get pods -l app=myapp # Should match service selector
|
|
137
|
+
kubectl describe service myapp-svc # Shows Endpoints section
|
|
138
|
+
|
|
139
|
+
# If Endpoints is empty: selector mismatch!
|
|
140
|
+
# Check: kubectl get pods --show-labels</code></pre>
|
|
141
|
+
|
|
142
|
+
<h2 id="cheatsheet">5. Cheat Sheet</h2>
|
|
143
|
+
|
|
144
|
+
<table>
|
|
145
|
+
<thead><tr><th>Task</th><th>Command</th></tr></thead>
|
|
146
|
+
<tbody>
|
|
147
|
+
<tr><td>Expose Deployment</td><td><code>kubectl expose deploy/app --port=80 --type=NodePort</code></td></tr>
|
|
148
|
+
<tr><td>Create Pod + Service</td><td><code>kubectl run nginx --image=nginx --port=80 --expose</code></td></tr>
|
|
149
|
+
<tr><td>Check service endpoints</td><td><code>kubectl get endpoints svc-name</code></td></tr>
|
|
150
|
+
<tr><td>Test service từ trong cluster</td><td><code>kubectl run tmp --image=busybox --rm -it -- wget -O- http://svc</code></td></tr>
|
|
151
|
+
<tr><td>Ingress với TLS</td><td>tls: secretName + hosts trong rules</td></tr>
|
|
152
|
+
</tbody>
|
|
153
|
+
</table>
|
|
154
|
+
|
|
155
|
+
<h2 id="practice">6. Practice Questions</h2>
|
|
156
|
+
|
|
157
|
+
<p><strong>Q1:</strong> A Deployment named "webapp" with selector app=webapp runs on port 8080. You need to create a Service that makes it accessible within the cluster on port 80. Which command creates this correctly?</p>
|
|
158
|
+
<ul>
|
|
159
|
+
<li>A) <code>kubectl expose deployment webapp --port=8080</code></li>
|
|
160
|
+
<li>B) <code>kubectl expose deployment webapp --port=80 --target-port=8080</code> ✓</li>
|
|
161
|
+
<li>C) <code>kubectl create service clusterip webapp --port=8080:80</code></li>
|
|
162
|
+
<li>D) <code>kubectl expose deployment webapp --type=ClusterIP --port=80</code></li>
|
|
163
|
+
</ul>
|
|
164
|
+
<p><em>Explanation: --port=80 is the Service port (what clients use), --target-port=8080 is the container port (where the app listens). Without --target-port, Kubernetes assumes target-port equals port. Option D would work but uses same port 80 for both.</em></p>
|
|
165
|
+
|
|
166
|
+
<p><strong>Q2:</strong> An Ingress resource exists but traffic doesn't reach the backend Services. kubectl get endpoints shows the correct Pod IPs. What is the most likely cause?</p>
|
|
167
|
+
<ul>
|
|
168
|
+
<li>A) The Service type should be LoadBalancer instead of ClusterIP</li>
|
|
169
|
+
<li>B) No Ingress Controller is installed or the ingressClassName is wrong ✓</li>
|
|
170
|
+
<li>C) The Ingress needs TLS configured</li>
|
|
171
|
+
<li>D) The pathType should be Exact instead of Prefix</li>
|
|
172
|
+
</ul>
|
|
173
|
+
<p><em>Explanation: Ingress resources are just configuration objects. Without an Ingress Controller, nothing processes the rules. If the ingressClassName doesn't match an IngressClass connected to a running controller, the Ingress is effectively ignored. Always verify kubectl get ingressclass and that the controller Pod is running.</em></p>
|
|
174
|
+
|
|
175
|
+
<p><strong>Q3:</strong> Which Service type provides external access using a port in the range 30000-32767 on every cluster node?</p>
|
|
176
|
+
<ul>
|
|
177
|
+
<li>A) ClusterIP</li>
|
|
178
|
+
<li>B) ExternalName</li>
|
|
179
|
+
<li>C) NodePort ✓</li>
|
|
180
|
+
<li>D) LoadBalancer</li>
|
|
181
|
+
</ul>
|
|
182
|
+
<p><em>Explanation: NodePort opens a port in the 30000-32767 range on every Node in the cluster. External traffic can reach the Service via NodeIP:NodePort. This is typically used for development and testing. LoadBalancer provides a cloud load balancer with a stable external IP, which is preferred for production.</em></p>
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ckad-d5-l10
|
|
3
|
+
title: 'Bài 10: NetworkPolicies & CKAD Exam Strategy'
|
|
4
|
+
slug: 10-networkpolicies-exam-strategy
|
|
5
|
+
description: >-
|
|
6
|
+
NetworkPolicy ingress/egress rules, default-deny patterns và pod selector.
|
|
7
|
+
CKAD exam strategy: kubectl shortcuts, --dry-run pattern và time management.
|
|
8
|
+
duration_minutes: 60
|
|
9
|
+
is_free: true
|
|
10
|
+
video_url: null
|
|
11
|
+
sort_order: 10
|
|
12
|
+
section_title: "Domain 5: Services and Networking (20%)"
|
|
13
|
+
course:
|
|
14
|
+
id: lt-ckad-series-001
|
|
15
|
+
title: 'Luyện thi CKAD — Certified Kubernetes Application Developer'
|
|
16
|
+
slug: luyen-thi-ckad
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<img src="/storage/uploads/2026/04/k8s-cert-ckad-bai10-networkpolicy.png" alt="NetworkPolicy — ingress/egress rules, default-deny và AND/OR logic" style="max-width: 800px; width: 100%; border-radius: 12px;" />
|
|
20
|
+
|
|
21
|
+
<h2 id="networkpolicy">1. NetworkPolicy</h2>
|
|
22
|
+
|
|
23
|
+
<p>Mặc định, tất cả Pods trong cluster có thể communicate với nhau. NetworkPolicy giới hạn traffic dựa trên labels.</p>
|
|
24
|
+
|
|
25
|
+
<pre><code class="language-text">Default: All pods can talk to all pods (no restriction)
|
|
26
|
+
|
|
27
|
+
After applying default-deny-all:
|
|
28
|
+
Pod A ──✗──► Pod B (blocked)
|
|
29
|
+
Pod A ──✗──► Pod C (blocked)
|
|
30
|
+
|
|
31
|
+
After applying allow policy:
|
|
32
|
+
Pod A (app=frontend) ──✓──► Pod B (app=backend, port 3000)
|
|
33
|
+
Pod A ──✗──► Pod C (app=database) (still blocked)</code></pre>
|
|
34
|
+
|
|
35
|
+
<h2 id="policy-syntax">2. NetworkPolicy Syntax</h2>
|
|
36
|
+
|
|
37
|
+
<pre><code class="language-text">apiVersion: networking.k8s.io/v1
|
|
38
|
+
kind: NetworkPolicy
|
|
39
|
+
metadata:
|
|
40
|
+
name: backend-policy
|
|
41
|
+
namespace: production
|
|
42
|
+
spec:
|
|
43
|
+
podSelector: # Applies to these pods (empty = all pods in ns)
|
|
44
|
+
matchLabels:
|
|
45
|
+
app: backend
|
|
46
|
+
policyTypes:
|
|
47
|
+
- Ingress # Controls inbound traffic
|
|
48
|
+
- Egress # Controls outbound traffic
|
|
49
|
+
ingress:
|
|
50
|
+
- from:
|
|
51
|
+
- podSelector: # Allow from pods with this label
|
|
52
|
+
matchLabels:
|
|
53
|
+
app: frontend
|
|
54
|
+
- namespaceSelector: # Allow from pods in these namespaces
|
|
55
|
+
matchLabels:
|
|
56
|
+
name: production
|
|
57
|
+
ports:
|
|
58
|
+
- protocol: TCP
|
|
59
|
+
port: 3000
|
|
60
|
+
egress:
|
|
61
|
+
- to:
|
|
62
|
+
- podSelector:
|
|
63
|
+
matchLabels:
|
|
64
|
+
app: database
|
|
65
|
+
ports:
|
|
66
|
+
- protocol: TCP
|
|
67
|
+
port: 5432</code></pre>
|
|
68
|
+
|
|
69
|
+
<blockquote><p><strong>Exam tip — AND vs OR trong NetworkPolicy:</strong><br/>
|
|
70
|
+
<code>from: [{podSelector}, {namespaceSelector}]</code> = OR (pod from either selector)<br/>
|
|
71
|
+
<code>from: [{podSelector + namespaceSelector}]</code> in SAME item = AND (pod matching both)<br/>
|
|
72
|
+
Đây là một trong những câu hỏi trap nhất của CKAD.</p></blockquote>
|
|
73
|
+
|
|
74
|
+
<h2 id="common-patterns">3. Common Patterns</h2>
|
|
75
|
+
|
|
76
|
+
<pre><code class="language-text">Pattern 1: Default deny all ingress
|
|
77
|
+
---
|
|
78
|
+
apiVersion: networking.k8s.io/v1
|
|
79
|
+
kind: NetworkPolicy
|
|
80
|
+
metadata:
|
|
81
|
+
name: default-deny-ingress
|
|
82
|
+
spec:
|
|
83
|
+
podSelector: {} # Empty = match ALL pods
|
|
84
|
+
policyTypes:
|
|
85
|
+
- Ingress
|
|
86
|
+
# No ingress rules = deny all ingress
|
|
87
|
+
|
|
88
|
+
Pattern 2: Default deny all (both ingress + egress)
|
|
89
|
+
---
|
|
90
|
+
spec:
|
|
91
|
+
podSelector: {}
|
|
92
|
+
policyTypes:
|
|
93
|
+
- Ingress
|
|
94
|
+
- Egress
|
|
95
|
+
# No rules = deny all
|
|
96
|
+
|
|
97
|
+
Pattern 3: Allow all ingress (override deny)
|
|
98
|
+
---
|
|
99
|
+
spec:
|
|
100
|
+
podSelector: {}
|
|
101
|
+
policyTypes:
|
|
102
|
+
- Ingress
|
|
103
|
+
ingress:
|
|
104
|
+
- {} # Empty rule = allow all ingress</code></pre>
|
|
105
|
+
|
|
106
|
+
<table>
|
|
107
|
+
<thead><tr><th>Pattern</th><th>policyTypes</th><th>Rules</th><th>Effect</th></tr></thead>
|
|
108
|
+
<tbody>
|
|
109
|
+
<tr><td>Deny all ingress</td><td>[Ingress]</td><td>Không có ingress rules</td><td>Block all inbound</td></tr>
|
|
110
|
+
<tr><td>Deny all egress</td><td>[Egress]</td><td>Không có egress rules</td><td>Block all outbound</td></tr>
|
|
111
|
+
<tr><td>Allow specific</td><td>[Ingress]</td><td>ingress rules listed</td><td>Allow matching only</td></tr>
|
|
112
|
+
<tr><td>Allow DNS egress</td><td>[Egress]</td><td>to port 53 (UDP+TCP)</td><td>Allow DNS queries</td></tr>
|
|
113
|
+
</tbody>
|
|
114
|
+
</table>
|
|
115
|
+
|
|
116
|
+
<blockquote><p><strong>Exam tip:</strong> NetworkPolicy chỉ hoạt động nếu CNI plugin hỗ trợ (Calico, Cilium, Weave). <strong>Flannel không hỗ trợ NetworkPolicy!</strong> Ingress/Egress rules là additive — nếu nhiều policies apply đến cùng Pod, Kubernetes OR tất cả rules lại.</p></blockquote>
|
|
117
|
+
|
|
118
|
+
<h2 id="exam-strategy">4. CKAD Exam Strategy</h2>
|
|
119
|
+
|
|
120
|
+
<pre><code class="language-text">Thông tin exam:
|
|
121
|
+
- 2 giờ, ~15-20 tasks thực hành (performance-based)
|
|
122
|
+
- Mỗi task có value % khác nhau (ưu tiên task cao điểm trước)
|
|
123
|
+
- Pass score: 66%
|
|
124
|
+
- Được dùng docs: kubernetes.io/docs + helm.sh/docs
|
|
125
|
+
|
|
126
|
+
Keyboard shortcuts quan trọng:
|
|
127
|
+
k = kubectl (export alias k=kubectl trong exam, đã set sẵn)
|
|
128
|
+
CTRL+R = search command history
|
|
129
|
+
CTRL+A = go to beginning of line</code></pre>
|
|
130
|
+
|
|
131
|
+
<pre><code class="language-text">Workflow cho mỗi task:
|
|
132
|
+
|
|
133
|
+
1. ĐỌC KỸ task description (đặc biệt để ý namespace!)
|
|
134
|
+
2. Switch context nếu cần:
|
|
135
|
+
kubectl config use-context cluster-name
|
|
136
|
+
3. Set namespace shortcut:
|
|
137
|
+
export ns=target-namespace
|
|
138
|
+
alias kn="kubectl -n $ns"
|
|
139
|
+
4. Dùng --dry-run=client -o yaml để generate YAML:
|
|
140
|
+
kubectl run pod --image=nginx --dry-run=client -o yaml > pod.yaml
|
|
141
|
+
5. Edit YAML, apply, verify:
|
|
142
|
+
kubectl apply -f pod.yaml
|
|
143
|
+
kubectl get pods -n $ns</code></pre>
|
|
144
|
+
|
|
145
|
+
<h2 id="dry-run-pattern">5. --dry-run Pattern</h2>
|
|
146
|
+
|
|
147
|
+
<pre><code class="language-text"># Generate YAML templates nhanh hơn viết tay:
|
|
148
|
+
|
|
149
|
+
Pod:
|
|
150
|
+
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
|
|
151
|
+
|
|
152
|
+
Deployment:
|
|
153
|
+
kubectl create deployment myapp --image=nginx --replicas=3 \
|
|
154
|
+
--dry-run=client -o yaml > deploy.yaml
|
|
155
|
+
|
|
156
|
+
Service (ClusterIP):
|
|
157
|
+
kubectl create service clusterip myapp --tcp=80:8080 \
|
|
158
|
+
--dry-run=client -o yaml > svc.yaml
|
|
159
|
+
|
|
160
|
+
ConfigMap:
|
|
161
|
+
kubectl create configmap myconfig --from-literal=k=v \
|
|
162
|
+
--dry-run=client -o yaml > cm.yaml
|
|
163
|
+
|
|
164
|
+
Secret:
|
|
165
|
+
kubectl create secret generic mysecret --from-literal=pass=secret \
|
|
166
|
+
--dry-run=client -o yaml > secret.yaml
|
|
167
|
+
|
|
168
|
+
Job:
|
|
169
|
+
kubectl create job myjob --image=busybox -- echo hello \
|
|
170
|
+
--dry-run=client -o yaml > job.yaml
|
|
171
|
+
|
|
172
|
+
CronJob:
|
|
173
|
+
kubectl create cronjob mycron --image=busybox --schedule="*/1 * * * *" \
|
|
174
|
+
-- echo hello --dry-run=client -o yaml > cron.yaml</code></pre>
|
|
175
|
+
|
|
176
|
+
<h2 id="kubectl-shortcuts">6. Essential kubectl Shortcuts</h2>
|
|
177
|
+
|
|
178
|
+
<table>
|
|
179
|
+
<thead><tr><th>Lệnh đầy đủ</th><th>Short form</th></tr></thead>
|
|
180
|
+
<tbody>
|
|
181
|
+
<tr><td><code>kubectl get pods</code></td><td><code>k get po</code></td></tr>
|
|
182
|
+
<tr><td><code>kubectl get deployments</code></td><td><code>k get deploy</code></td></tr>
|
|
183
|
+
<tr><td><code>kubectl get services</code></td><td><code>k get svc</code></td></tr>
|
|
184
|
+
<tr><td><code>kubectl get namespaces</code></td><td><code>k get ns</code></td></tr>
|
|
185
|
+
<tr><td><code>kubectl get persistentvolumeclaims</code></td><td><code>k get pvc</code></td></tr>
|
|
186
|
+
<tr><td><code>kubectl get configmaps</code></td><td><code>k get cm</code></td></tr>
|
|
187
|
+
<tr><td><code>kubectl get serviceaccounts</code></td><td><code>k get sa</code></td></tr>
|
|
188
|
+
<tr><td><code>kubectl get networkpolicies</code></td><td><code>k get netpol</code></td></tr>
|
|
189
|
+
<tr><td><code>kubectl describe pod mypod</code></td><td><code>k describe po mypod</code></td></tr>
|
|
190
|
+
<tr><td><code>kubectl delete pod mypod --force</code></td><td><code>k delete po mypod --force</code></td></tr>
|
|
191
|
+
</tbody>
|
|
192
|
+
</table>
|
|
193
|
+
|
|
194
|
+
<h2 id="cheatsheet">7. Final CKAD Cheat Sheet</h2>
|
|
195
|
+
|
|
196
|
+
<table>
|
|
197
|
+
<thead><tr><th>Domain</th><th>Key Topics</th><th>% Weight</th></tr></thead>
|
|
198
|
+
<tbody>
|
|
199
|
+
<tr><td>App Design & Build</td><td>Multi-container, Init Containers, Jobs, CronJobs, volumes</td><td>20%</td></tr>
|
|
200
|
+
<tr><td>App Deployment</td><td>Rolling updates, rollbacks, Helm, Kustomize</td><td>20%</td></tr>
|
|
201
|
+
<tr><td>App Observability</td><td>Probes (liveness/readiness/startup), logs, debug</td><td>15%</td></tr>
|
|
202
|
+
<tr><td>App Env/Config/Security</td><td>ConfigMaps, Secrets, SecurityContext, SA, Resources, QoS</td><td>25%</td></tr>
|
|
203
|
+
<tr><td>Services & Networking</td><td>Services, Ingress, NetworkPolicies</td><td>20%</td></tr>
|
|
204
|
+
</tbody>
|
|
205
|
+
</table>
|
|
206
|
+
|
|
207
|
+
<h2 id="practice">8. Practice Questions</h2>
|
|
208
|
+
|
|
209
|
+
<p><strong>Q1:</strong> You apply a NetworkPolicy with podSelector: {} and policyTypes: [Ingress] but no ingress rules. What happens?</p>
|
|
210
|
+
<ul>
|
|
211
|
+
<li>A) All ingress traffic is allowed (no rules = no restriction)</li>
|
|
212
|
+
<li>B) All ingress traffic to ALL pods in the namespace is denied ✓</li>
|
|
213
|
+
<li>C) All pods are deleted</li>
|
|
214
|
+
<li>D) Only external ingress is denied; internal pod-to-pod traffic is allowed</li>
|
|
215
|
+
</ul>
|
|
216
|
+
<p><em>Explanation: podSelector: {} matches ALL pods in the namespace. policyTypes: [Ingress] says this policy controls ingress. Having no ingress rules means zero traffic is allowed. This is the "default deny all ingress" pattern. Pod-to-pod traffic within the cluster is also denied because NetworkPolicy controls all ingress, regardless of source.</em></p>
|
|
217
|
+
|
|
218
|
+
<p><strong>Q2:</strong> In a NetworkPolicy, what is the difference between these two from clauses?<br/>
|
|
219
|
+
Clause A: from: [{podSelector: {app: web}}, {namespaceSelector: {env: prod}}]<br/>
|
|
220
|
+
Clause B: from: [{podSelector: {app: web}, namespaceSelector: {env: prod}}]</p>
|
|
221
|
+
<ul>
|
|
222
|
+
<li>A) They are identical</li>
|
|
223
|
+
<li>B) Clause A: allow from pods with app=web OR from any pod in env=prod namespace. Clause B: allow only from pods with app=web AND in env=prod namespace ✓</li>
|
|
224
|
+
<li>C) Clause A uses AND logic, Clause B uses OR logic</li>
|
|
225
|
+
<li>D) Clause B is invalid YAML syntax</li>
|
|
226
|
+
</ul>
|
|
227
|
+
<p><em>Explanation: In NetworkPolicy, when podSelector and namespaceSelector are in SEPARATE list items (separated by -), they use OR logic. When they are in the SAME list item (same indentation level, no -), they use AND logic. This is a critical distinction and a common exam trap.</em></p>
|
|
228
|
+
|
|
229
|
+
<p><strong>Q3:</strong> During the CKAD exam, you need to create a Deployment with a specific Pod spec. What is the fastest approach?</p>
|
|
230
|
+
<ul>
|
|
231
|
+
<li>A) Write the entire YAML from memory</li>
|
|
232
|
+
<li>B) Search kubernetes.io docs and copy-paste example YAML</li>
|
|
233
|
+
<li>C) Use kubectl create deployment --dry-run=client -o yaml to generate a template, then edit ✓</li>
|
|
234
|
+
<li>D) Use helm to deploy a chart with default values</li>
|
|
235
|
+
</ul>
|
|
236
|
+
<p><em>Explanation: The --dry-run=client -o yaml pattern generates valid YAML without creating resources. You redirect to a file, edit only the fields that differ, then apply. This is faster than manual YAML authoring and less likely to have syntax errors. Combining with > file.yaml lets you make precise edits.</em></p>
|
|
@@ -8,7 +8,7 @@ description: >-
|
|
|
8
8
|
App Deployment (20%), Services & Networking (20%), App Observability (15%).
|
|
9
9
|
10 bài học kèm bài tập thực hành terminal.
|
|
10
10
|
|
|
11
|
-
featured_image:
|
|
11
|
+
featured_image: images/blog/luyen-thi-ckad-banner.png
|
|
12
12
|
level: intermediate
|
|
13
13
|
duration_hours: 28
|
|
14
14
|
lesson_count: 10
|