@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.
- package/content/pages/xoa-du-lieu-nguoi-dung.md +68 -0
- 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
- 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
- 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
- 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
- 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
- package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/chapters/02-phan-2-modeling/lessons/06-bai-6-model-evaluation.md +169 -0
- 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
- 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
- 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
- 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
- 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
- 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
- package/content/series/luyen-thi/luyen-thi-aws-ml-specialty/index.md +1 -1
- 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 +217 -0
- 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 +199 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/content/series/luyen-thi/luyen-thi-gcp-ml-engineer/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 +168 -0
- package/data/quizzes.json +1059 -0
- 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 <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>
|