@xdev-asia/xdev-knowledge-mcp 1.0.43 → 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.
Files changed (61) hide show
  1. package/content/pages/xoa-du-lieu-nguoi-dung.md +68 -0
  2. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/01-phan-1-data-engineering/lessons/01-bai-1-data-repositories-ingestion.md +5 -0
  3. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/01-phan-1-data-engineering/lessons/02-bai-2-data-transformation.md +5 -0
  4. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/01-phan-1-data-engineering/lessons/03-bai-3-data-analysis.md +159 -0
  5. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/02-phan-2-modeling/lessons/04-bai-4-sagemaker-built-in-algorithms.md +186 -0
  6. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/02-phan-2-modeling/lessons/05-bai-5-training-hyperparameter-tuning.md +159 -0
  7. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/02-phan-2-modeling/lessons/06-bai-6-model-evaluation.md +169 -0
  8. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/03-phan-3-implementation-operations/lessons/07-bai-7-model-deployment.md +193 -0
  9. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/03-phan-3-implementation-operations/lessons/08-bai-8-model-monitoring-mlops.md +184 -0
  10. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/03-phan-3-implementation-operations/lessons/09-bai-9-security-cost.md +166 -0
  11. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/04-phan-4-on-tap/lessons/10-bai-10-bai-toan-thuong-gap.md +181 -0
  12. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/04-phan-4-on-tap/lessons/11-bai-11-cheat-sheet.md +110 -0
  13. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/04-phan-4-on-tap/lessons/12-bai-12-chien-luoc-thi.md +113 -0
  14. package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/index.md +1 -1
  15. package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/01-kien-truc-cka-kubeadm.md +133 -0
  16. package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/02-cluster-upgrade-kubeadm.md +147 -0
  17. package/content/series/luyen-thi/luyen-thi-cka/chapters/01-cluster-architecture/lessons/03-rbac-cka.md +152 -0
  18. package/content/series/luyen-thi/luyen-thi-cka/chapters/02-workloads-scheduling/lessons/04-deployments-daemonsets-statefulsets.md +186 -0
  19. package/content/series/luyen-thi/luyen-thi-cka/chapters/02-workloads-scheduling/lessons/05-scheduling-taints-affinity.md +163 -0
  20. package/content/series/luyen-thi/luyen-thi-cka/chapters/03-services-networking/lessons/06-services-endpoints-coredns.md +145 -0
  21. package/content/series/luyen-thi/luyen-thi-cka/chapters/03-services-networking/lessons/07-ingress-networkpolicies-cni.md +172 -0
  22. package/content/series/luyen-thi/luyen-thi-cka/chapters/04-storage/lessons/08-persistent-volumes-storageclass.md +159 -0
  23. package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/09-etcd-backup-restore.md +149 -0
  24. package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/10-troubleshooting-nodes.md +153 -0
  25. package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/11-troubleshooting-workloads.md +146 -0
  26. package/content/series/luyen-thi/luyen-thi-cka/chapters/05-troubleshooting/lessons/12-troubleshooting-networking-exam.md +170 -0
  27. package/content/series/luyen-thi/luyen-thi-cka/index.md +217 -0
  28. package/content/series/luyen-thi/luyen-thi-ckad/chapters/01-app-design-build/lessons/01-multi-container-pods.md +146 -0
  29. package/content/series/luyen-thi/luyen-thi-ckad/chapters/01-app-design-build/lessons/02-jobs-cronjobs-resources.md +174 -0
  30. package/content/series/luyen-thi/luyen-thi-ckad/chapters/02-app-deployment/lessons/03-rolling-updates-rollbacks.md +148 -0
  31. package/content/series/luyen-thi/luyen-thi-ckad/chapters/02-app-deployment/lessons/04-helm-kustomize.md +181 -0
  32. package/content/series/luyen-thi/luyen-thi-ckad/chapters/03-app-observability/lessons/05-probes-logging-debugging.md +183 -0
  33. package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/06-configmaps-secrets.md +182 -0
  34. package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/07-securitycontext-pod-security.md +168 -0
  35. package/content/series/luyen-thi/luyen-thi-ckad/chapters/04-app-environment-config/lessons/08-resources-qos.md +168 -0
  36. package/content/series/luyen-thi/luyen-thi-ckad/chapters/05-services-networking/lessons/09-services-ingress.md +182 -0
  37. package/content/series/luyen-thi/luyen-thi-ckad/chapters/05-services-networking/lessons/10-networkpolicies-exam-strategy.md +236 -0
  38. package/content/series/luyen-thi/luyen-thi-ckad/index.md +199 -0
  39. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/01-phan-1-problem-framing/lessons/01-bai-1-framing-ml-problems.md +136 -0
  40. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/01-phan-1-problem-framing/lessons/02-bai-2-gcp-ai-ml-ecosystem.md +160 -0
  41. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/02-phan-2-data-engineering/lessons/03-bai-3-data-pipeline.md +174 -0
  42. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/02-phan-2-data-engineering/lessons/04-bai-4-feature-engineering.md +156 -0
  43. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/03-phan-3-model-development/lessons/05-bai-5-vertex-ai-training.md +155 -0
  44. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/03-phan-3-model-development/lessons/06-bai-6-bigquery-ml-tensorflow.md +141 -0
  45. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/04-phan-4-deployment-mlops/lessons/07-bai-7-model-deployment.md +134 -0
  46. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/04-phan-4-deployment-mlops/lessons/08-bai-8-vertex-ai-pipelines-mlops.md +149 -0
  47. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/05-phan-5-responsible-ai/lessons/09-bai-9-responsible-ai.md +128 -0
  48. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/chapters/05-phan-5-responsible-ai/lessons/10-bai-10-cheat-sheet-chien-luoc-thi.md +108 -0
  49. package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/index.md +1 -1
  50. package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/01-kien-truc-kubernetes.md +137 -0
  51. package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/02-pods-workloads-controllers.md +142 -0
  52. package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/03-services-networking-storage.md +155 -0
  53. package/content/series/luyen-thi/luyen-thi-kcna/chapters/01-kubernetes-fundamentals/lessons/04-rbac-security.md +137 -0
  54. package/content/series/luyen-thi/luyen-thi-kcna/chapters/02-container-orchestration/lessons/05-container-runtimes-oci.md +137 -0
  55. package/content/series/luyen-thi/luyen-thi-kcna/chapters/02-container-orchestration/lessons/06-orchestration-patterns.md +147 -0
  56. package/content/series/luyen-thi/luyen-thi-kcna/chapters/03-cloud-native-architecture/lessons/07-cloud-native-architecture.md +143 -0
  57. package/content/series/luyen-thi/luyen-thi-kcna/chapters/04-observability-delivery/lessons/08-observability.md +143 -0
  58. package/content/series/luyen-thi/luyen-thi-kcna/chapters/04-observability-delivery/lessons/09-helm-gitops-cicd.md +162 -0
  59. package/content/series/luyen-thi/luyen-thi-kcna/index.md +168 -0
  60. package/data/quizzes.json +1059 -0
  61. package/package.json +1 -1
@@ -0,0 +1,182 @@
1
+ ---
2
+ id: ckad-d4-l06
3
+ title: 'Bài 6: ConfigMaps & Secrets'
4
+ slug: 06-configmaps-secrets
5
+ description: >-
6
+ Tạo và consume ConfigMaps và Secrets trong Kubernetes. Inject qua env vars
7
+ (envFrom, valueFrom) và volume mounts. Secret types và security considerations.
8
+ duration_minutes: 55
9
+ is_free: true
10
+ video_url: null
11
+ sort_order: 6
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-bai6-configmap-secret.png" alt="ConfigMap và Secret injection — envFrom, valueFrom và Volume Mount" style="max-width: 800px; width: 100%; border-radius: 12px;" />
20
+
21
+ <h2 id="configmap">1. ConfigMap</h2>
22
+
23
+ <p>ConfigMap lưu trữ cặp key-value non-sensitive. Không được mã hóa (plain text).</p>
24
+
25
+ <pre><code class="language-text"># Tạo ConfigMap — Imperative
26
+ kubectl create configmap app-config \
27
+ --from-literal=DB_HOST=mysql \
28
+ --from-literal=DB_PORT=3306
29
+
30
+ kubectl create configmap app-config --from-file=config.properties
31
+ kubectl create configmap app-config --from-env-file=.env
32
+
33
+ # Declarative YAML
34
+ apiVersion: v1
35
+ kind: ConfigMap
36
+ metadata:
37
+ name: app-config
38
+ data:
39
+ DB_HOST: mysql
40
+ DB_PORT: "3306"
41
+ config.properties: |
42
+ server.port=8080
43
+ debug=false</code></pre>
44
+
45
+ <h2 id="secret">2. Secret</h2>
46
+
47
+ <p>Secret lưu trữ sensitive data. Được <strong>base64 encode</strong> (không phải mã hóa — encode thôi!).</p>
48
+
49
+ <pre><code class="language-text"># Tạo Secret — Imperative
50
+ kubectl create secret generic db-secret \
51
+ --from-literal=username=admin \
52
+ --from-literal=password=mypassword
53
+
54
+ kubectl create secret generic db-secret --from-file=credentials.txt
55
+
56
+ # Declarative (base64 encode trước)
57
+ echo -n 'admin' | base64 # YWRtaW4=
58
+ echo -n 'mypassword' | base64 # bXlwYXNzd29yZA==
59
+
60
+ apiVersion: v1
61
+ kind: Secret
62
+ metadata:
63
+ name: db-secret
64
+ type: Opaque
65
+ data:
66
+ username: YWRtaW4=
67
+ password: bXlwYXNzd29yZA==</code></pre>
68
+
69
+ <table>
70
+ <thead><tr><th>Secret Type</th><th>Mục đích</th></tr></thead>
71
+ <tbody>
72
+ <tr><td><code>Opaque</code></td><td>Generic — default type, any key-value data</td></tr>
73
+ <tr><td><code>kubernetes.io/dockerconfigjson</code></td><td>Docker registry credentials</td></tr>
74
+ <tr><td><code>kubernetes.io/tls</code></td><td>TLS certificate và private key</td></tr>
75
+ <tr><td><code>kubernetes.io/service-account-token</code></td><td>ServiceAccount token (auto-created)</td></tr>
76
+ </tbody>
77
+ </table>
78
+
79
+ <blockquote><p><strong>Exam tip:</strong> Secret data là <strong>base64 encoded, không encrypted</strong>. Bất kỳ ai có quyền đọc Secret đều có thể decode: <code>echo 'YWRtaW4=' | base64 -d</code>. Để encrypt at rest, phải enable EncryptionConfiguration — nhưng CKAD không test điều này. Exam thường test: tạo secret và inject vào Pod.</p></blockquote>
80
+
81
+ <h2 id="inject-env">3. Inject qua Environment Variables</h2>
82
+
83
+ <pre><code class="language-text">spec:
84
+ containers:
85
+ - name: app
86
+ image: myapp
87
+
88
+ # Method 1: envFrom — load ALL keys as env vars
89
+ envFrom:
90
+ - configMapRef:
91
+ name: app-config
92
+ - secretRef:
93
+ name: db-secret
94
+
95
+ # Method 2: valueFrom — load SPECIFIC key
96
+ env:
97
+ - name: DATABASE_HOST
98
+ valueFrom:
99
+ configMapKeyRef:
100
+ name: app-config
101
+ key: DB_HOST
102
+ - name: DB_PASSWORD
103
+ valueFrom:
104
+ secretKeyRef:
105
+ name: db-secret
106
+ key: password</code></pre>
107
+
108
+ <h2 id="inject-volume">4. Inject qua Volume Mount</h2>
109
+
110
+ <pre><code class="language-text">spec:
111
+ volumes:
112
+ - name: config-vol
113
+ configMap:
114
+ name: app-config
115
+ - name: secret-vol
116
+ secret:
117
+ secretName: db-secret
118
+
119
+ containers:
120
+ - name: app
121
+ image: myapp
122
+ volumeMounts:
123
+ - name: config-vol
124
+ mountPath: /etc/config # Each key becomes a file
125
+ - name: secret-vol
126
+ mountPath: /etc/secrets
127
+ readOnly: true
128
+
129
+ # Result: /etc/config/DB_HOST contains "mysql"
130
+ # /etc/secrets/password contains "mypassword" (decoded)</code></pre>
131
+
132
+ <table>
133
+ <thead><tr><th>Method</th><th>Khi dùng</th><th>Auto-update khi CM/Secret đổi?</th></tr></thead>
134
+ <tbody>
135
+ <tr><td><code>envFrom</code> / <code>env.valueFrom</code></td><td>App đọc env vars</td><td>Không (cần restart pod)</td></tr>
136
+ <tr><td>Volume mount</td><td>App đọc từ files, hoặc cần auto-reload</td><td>Có (sau ~1-2 phút)</td></tr>
137
+ </tbody>
138
+ </table>
139
+
140
+ <blockquote><p><strong>Exam tip:</strong> Volume-mounted ConfigMaps/Secrets tự động update khi nguồn thay đổi (sau kubelet sync period ~1 phút). Env vars phải restart pod mới reflect changes. CKAD thường test cả 2 methods — nắm rõ syntax của <code>configMapKeyRef</code> vs <code>configMapRef</code> (có chữ "Key" thì là single key).</p></blockquote>
141
+
142
+ <h2 id="cheatsheet">5. Cheat Sheet</h2>
143
+
144
+ <table>
145
+ <thead><tr><th>Task</th><th>Command / YAML</th></tr></thead>
146
+ <tbody>
147
+ <tr><td>Tạo CM từ literals</td><td><code>kubectl create cm name --from-literal=k=v</code></td></tr>
148
+ <tr><td>Tạo Secret từ literals</td><td><code>kubectl create secret generic n --from-literal=k=v</code></td></tr>
149
+ <tr><td>Load all CM keys as env</td><td><code>envFrom: - configMapRef: name: ...</code></td></tr>
150
+ <tr><td>Load specific key</td><td><code>env: - valueFrom: configMapKeyRef: ...</code></td></tr>
151
+ <tr><td>Mount as files</td><td><code>volumes: configMap/secret + volumeMounts</code></td></tr>
152
+ </tbody>
153
+ </table>
154
+
155
+ <h2 id="practice">6. Practice Questions</h2>
156
+
157
+ <p><strong>Q1:</strong> A Pod needs to consume ALL key-value pairs from a ConfigMap named "app-settings" as environment variables. Which configuration is correct?</p>
158
+ <ul>
159
+ <li>A) <code>env: - name: APP_SETTINGS valueFrom: configMapRef: name: app-settings</code></li>
160
+ <li>B) <code>envFrom: - configMapRef: name: app-settings</code> ✓</li>
161
+ <li>C) <code>volumes: - configMap: name: app-settings</code></li>
162
+ <li>D) <code>env: - configMapKeyRef: name: app-settings key: "*"</code></li>
163
+ </ul>
164
+ <p><em>Explanation: envFrom with configMapRef loads ALL keys from the ConfigMap as environment variables. env with valueFrom configMapKeyRef only loads ONE specific key. The wildcard "*" syntax does not exist.</em></p>
165
+
166
+ <p><strong>Q2:</strong> You create a Secret with the command: kubectl create secret generic mysecret --from-literal=password=secret123. How is the data stored in etcd?</p>
167
+ <ul>
168
+ <li>A) Plain text: "password=secret123"</li>
169
+ <li>B) AES-256 encrypted</li>
170
+ <li>C) Base64 encoded ✓</li>
171
+ <li>D) SHA-256 hashed</li>
172
+ </ul>
173
+ <p><em>Explanation: By default, Kubernetes stores Secret data as base64 encoded values in etcd — NOT encrypted. Base64 is encoding, not encryption. Anyone with etcd access can decode it. To encrypt at rest, an EncryptionConfiguration must be configured separately.</em></p>
174
+
175
+ <p><strong>Q3:</strong> A ConfigMap is updated with new values. A Pod is using this ConfigMap mounted as a volume at /etc/config. What happens?</p>
176
+ <ul>
177
+ <li>A) The Pod fails immediately because the config changed</li>
178
+ <li>B) The files in /etc/config are automatically updated (with a short delay) ✓</li>
179
+ <li>C) Nothing happens — the Pod must be restarted to see changes</li>
180
+ <li>D) The Pod is restarted automatically by Kubernetes</li>
181
+ </ul>
182
+ <p><em>Explanation: Volume-mounted ConfigMaps are automatically updated when the ConfigMap changes, after the kubelet sync period (typically ~1 minute). Environment variables from ConfigMaps do NOT auto-update — the Pod must be recreated. Applications that watch for file changes can react to these updates without restarts.</em></p>
@@ -0,0 +1,168 @@
1
+ ---
2
+ id: ckad-d4-l07
3
+ title: 'Bài 7: SecurityContext, Capabilities & ServiceAccounts'
4
+ slug: 07-securitycontext-pod-security
5
+ description: >-
6
+ SecurityContext cho Pod và Container: runAsUser, runAsNonRoot, readOnlyRootFilesystem,
7
+ Linux capabilities. ServiceAccount binding và automountServiceAccountToken.
8
+ duration_minutes: 55
9
+ is_free: true
10
+ video_url: null
11
+ sort_order: 7
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-bai7-security-context.png" alt="SecurityContext — Pod-level vs Container-level, Linux capabilities" style="max-width: 800px; width: 100%; border-radius: 12px;" />
20
+
21
+ <h2 id="securitycontext">1. SecurityContext</h2>
22
+
23
+ <p>SecurityContext định nghĩa các privilege và access control settings cho Pod hoặc Container.</p>
24
+
25
+ <pre><code class="language-text">apiVersion: v1
26
+ kind: Pod
27
+ spec:
28
+ securityContext: # Pod-level: applies to ALL containers
29
+ runAsUser: 1000 # UID để chạy containers
30
+ runAsGroup: 3000 # GID primary group
31
+ fsGroup: 2000 # GID cho mounted volumes
32
+ runAsNonRoot: true # Reject containers that run as root
33
+
34
+ containers:
35
+ - name: app
36
+ image: myapp
37
+ securityContext: # Container-level: overrides pod-level
38
+ allowPrivilegeEscalation: false
39
+ readOnlyRootFilesystem: true # Filesystem là read-only
40
+ capabilities:
41
+ add: ["NET_BIND_SERVICE"] # Add capability
42
+ drop: ["ALL"] # Drop all, add only what needed</code></pre>
43
+
44
+ <table>
45
+ <thead><tr><th>Setting</th><th>Level</th><th>Tác dụng</th></tr></thead>
46
+ <tbody>
47
+ <tr><td><code>runAsUser</code></td><td>Pod/Container</td><td>Chạy process với UID cụ thể</td></tr>
48
+ <tr><td><code>runAsNonRoot</code></td><td>Pod/Container</td><td>Từ chối chạy nếu UID = 0 (root)</td></tr>
49
+ <tr><td><code>readOnlyRootFilesystem</code></td><td>Container</td><td>Mount root filesystem read-only</td></tr>
50
+ <tr><td><code>allowPrivilegeEscalation</code></td><td>Container</td><td>Chặn privilege escalation (sudo etc.)</td></tr>
51
+ <tr><td><code>privileged</code></td><td>Container</td><td>Run as privileged (như root trên host)</td></tr>
52
+ <tr><td><code>fsGroup</code></td><td>Pod</td><td>GID cho volume files (shared volume access)</td></tr>
53
+ </tbody>
54
+ </table>
55
+
56
+ <blockquote><p><strong>Exam tip:</strong> Container-level <code>securityContext</code> <strong>override</strong> Pod-level settings. Nếu Pod có <code>runAsUser: 1000</code> và container có <code>runAsUser: 2000</code>, container đó chạy với UID 2000. Hay bị test: verify user bằng <code>kubectl exec pod -- id</code> hoặc <code>whoami</code>.</p></blockquote>
57
+
58
+ <h2 id="capabilities">2. Linux Capabilities</h2>
59
+
60
+ <pre><code class="language-text">Capabilities cho phép grant specific privileges mà không cần full root.
61
+
62
+ # Ví dụ thường gặp:
63
+ NET_BIND_SERVICE — Bind to port < 1024 (e.g., port 80)
64
+ NET_ADMIN — Network administration (ifconfig etc.)
65
+ SYS_TIME — Modify system clock
66
+ CHOWN — Change file ownership
67
+ SETUID/SETGID — Change user/group ID
68
+
69
+ securityContext:
70
+ capabilities:
71
+ drop: ["ALL"] # Best practice: drop all first
72
+ add: ["NET_BIND_SERVICE"] # Then re-add only what's needed</code></pre>
73
+
74
+ <h2 id="serviceaccount">3. ServiceAccounts</h2>
75
+
76
+ <p>Pod dùng <strong>ServiceAccount</strong> để authenticate với Kubernetes API.</p>
77
+
78
+ <pre><code class="language-text"># Tạo ServiceAccount
79
+ kubectl create serviceaccount my-sa
80
+
81
+ # Bind vào Role
82
+ kubectl create rolebinding my-binding \
83
+ --role=pod-reader \
84
+ --serviceaccount=default:my-sa
85
+
86
+ # Assign SA cho Pod
87
+ spec:
88
+ serviceAccountName: my-sa # Use specific SA
89
+ automountServiceAccountToken: false # Don't auto-mount SA token
90
+
91
+ # Mặc định: default SA được mount tại /var/run/secrets/kubernetes.io/serviceaccount/
92
+ # Token file có thể gọi K8s API từ container</code></pre>
93
+
94
+ <table>
95
+ <thead><tr><th>Concept</th><th>Mô tả</th></tr></thead>
96
+ <tbody>
97
+ <tr><td>Default SA</td><td>Mỗi namespace có sẵn <code>default</code> SA (ít quyền)</td></tr>
98
+ <tr><td>Token mount</td><td>Token tự động mount vào pod nếu không tắt</td></tr>
99
+ <tr><td><code>automountServiceAccountToken: false</code></td><td>Tắt việc mount token (best security practice)</td></tr>
100
+ </tbody>
101
+ </table>
102
+
103
+ <blockquote><p><strong>Exam tip:</strong> Khi Pod cần gọi Kubernetes API (ví dụ: operator pattern), cần ServiceAccount có quyền phù hợp. Nếu Pod không cần gọi API, best practice là set <code>automountServiceAccountToken: false</code>. CKAD thường test: tạo SA, bind role, và set SA trong Pod spec.</p></blockquote>
104
+
105
+ <h2 id="readonly-volume">4. readOnlyRootFilesystem với emptyDir</h2>
106
+
107
+ <pre><code class="language-text"># Khi dùng readOnlyRootFilesystem: true, app KHÔNG ghi vào root FS.
108
+ # Nhưng app vẫn cần ghi temp files → dùng emptyDir volume:
109
+
110
+ spec:
111
+ containers:
112
+ - name: app
113
+ image: myapp
114
+ securityContext:
115
+ readOnlyRootFilesystem: true
116
+ volumeMounts:
117
+ - name: tmp
118
+ mountPath: /tmp # App ghi temp files vào đây
119
+ - name: cache
120
+ mountPath: /app/cache
121
+ volumes:
122
+ - name: tmp
123
+ emptyDir: {}
124
+ - name: cache
125
+ emptyDir: {}</code></pre>
126
+
127
+ <h2 id="cheatsheet">5. Cheat Sheet</h2>
128
+
129
+ <table>
130
+ <thead><tr><th>Task</th><th>YAML / Command</th></tr></thead>
131
+ <tbody>
132
+ <tr><td>Run container as non-root</td><td><code>securityContext: runAsNonRoot: true</code></td></tr>
133
+ <tr><td>Run với specific UID</td><td><code>securityContext: runAsUser: 1000</code></td></tr>
134
+ <tr><td>Read-only filesystem</td><td><code>securityContext: readOnlyRootFilesystem: true</code></td></tr>
135
+ <tr><td>Drop all capabilities</td><td><code>capabilities: drop: ["ALL"]</code></td></tr>
136
+ <tr><td>Gán ServiceAccount</td><td><code>spec: serviceAccountName: my-sa</code></td></tr>
137
+ <tr><td>Verify user trong container</td><td><code>kubectl exec pod -- whoami</code></td></tr>
138
+ </tbody>
139
+ </table>
140
+
141
+ <h2 id="practice">6. Practice Questions</h2>
142
+
143
+ <p><strong>Q1:</strong> A Pod spec has securityContext.runAsUser: 1000 at the Pod level. One container within the Pod has securityContext.runAsUser: 2000. What UID does that container run with?</p>
144
+ <ul>
145
+ <li>A) 0 (root, because Pod-level overrides)</li>
146
+ <li>B) 1000 (Pod-level takes priority)</li>
147
+ <li>C) 2000 (Container-level overrides Pod-level) ✓</li>
148
+ <li>D) Both UIDs simultaneously</li>
149
+ </ul>
150
+ <p><em>Explanation: Container-level securityContext settings override Pod-level settings. The container runs with UID 2000. Other containers in the same Pod without a container-level securityContext.runAsUser would inherit the Pod-level UID of 1000.</em></p>
151
+
152
+ <p><strong>Q2:</strong> An application container needs to bind to port 80 (a privileged port below 1024) but should NOT run as root. How do you configure this?</p>
153
+ <ul>
154
+ <li>A) Set securityContext.privileged: true</li>
155
+ <li>B) Set securityContext.runAsUser: 0</li>
156
+ <li>C) Add NET_BIND_SERVICE capability while dropping ALL others ✓</li>
157
+ <li>D) Use a NodePort Service instead of port 80</li>
158
+ </ul>
159
+ <p><em>Explanation: Linux capabilities allow granular privilege grants. NET_BIND_SERVICE allows binding to ports below 1024 without full root. Best practice is to drop ALL capabilities first, then add only what's needed: capabilities: { drop: ["ALL"], add: ["NET_BIND_SERVICE"] }.</em></p>
160
+
161
+ <p><strong>Q3:</strong> A Pod is running with readOnlyRootFilesystem: true, but the application tries to write to /tmp and fails. What is the best solution?</p>
162
+ <ul>
163
+ <li>A) Remove readOnlyRootFilesystem: true</li>
164
+ <li>B) Set securityContext.privileged: true</li>
165
+ <li>C) Mount an emptyDir volume at /tmp ✓</li>
166
+ <li>D) Use a ConfigMap mounted at /tmp</li>
167
+ </ul>
168
+ <p><em>Explanation: readOnlyRootFilesystem prevents writes to the container's filesystem, but emptyDir volumes are separate writable mounts. By mounting an emptyDir at /tmp, the application can write temp files there while the root filesystem remains read-only — maintaining the security benefit.</em></p>
@@ -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 &lt;name&gt; | grep -i qos</code> hoặc <code>kubectl get pod &lt;name&gt; -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>