Перейти до вмісту

Модуль 0.2: Налаштування лабораторії безпеки

Hands-On Lab Available
K8s Cluster advanced 45-60 min
Launch Lab ↗

Opens in Killercoda in a new tab

Складність: [СЕРЕДНЯ] — кілька інструментів для встановлення

Час на проходження: 45-60 хвилин

Передумови: Робочий кластер Kubernetes (з курсу CKA), налаштований kubectl


Що ви зможете зробити

Розділ «Що ви зможете зробити»

Після завершення цього модуля ви зможете:

  1. Розгорнути відтворювану лабораторію безпеки CKS з логуванням аудиту, Trivy, Falco, kube-bench, kubesec та навмисно вразливими навчальними цілями.
  2. Налаштувати вузли Kubernetes 1.35+ та параметри API-сервера для логування аудиту, AppArmor та перевірки seccomp.
  3. Діагностувати збої встановлення інструментів безпеки, порівнюючи вибір драйвера, підтримку вузла, вивід логів та очікуваний стан кластера.
  4. Оцінити результати лабораторії від сканерів, сповіщень середовища виконання та перевірок CIS, щоб обрати безпечний шлях для відпрацювання усунення проблем.

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Навчальний сценарій: у вас є робочий кластер Kubernetes після практики CKA, але перша вправа CKS просить вас просканувати образ, переглянути лог аудиту, посилити ризикований Под та пояснити сповіщення середовища виконання під тиском екзамену. Ніщо в цьому робочому процесі не є складним, коли лабораторія підготовлена, проте кожен крок стає повільним, якщо база даних сканера відсутня, в API-сервера немає політики аудиту або Falco не може завантажити потрібний драйвер для ядра вузла. Лабораторія безпеки — це різниця між вивченням екзаменаційної навички та налагодженням навчального середовища.

Екзамен CKS практичний, тож лабораторія має поводитися радше як невелика робоча станція безпеки, ніж як звичайний кластер. Trivy дає вам швидкий цикл зворотного зв’язку для сканування образів і маніфестів, kube-bench перетворює перевірки за бенчмарком CIS на відтворювані докази, kubesec надає статичний зворотний зв’язок щодо маніфестів, а Falco перетворює поведінку середовища виконання на сповіщення, які ви можете читати й осмислювати. Логування аудиту, AppArmor та seccomp тут не є окремими темами для зубріння; це поверхні кластера, які роблять ці інструменти значущими.

Цей модуль будує сфокусовану лабораторію навколо концепцій Kubernetes 1.35+, зберігаючи при цьому легке налаштування, яке робить можливою повторювану практику. Ви оберете між кластером kind та кластером kubeadm, додасте логування аудиту туди, де API-сервер справді може писати логи, встановите інструменти з чіткими точками перевірки та розгорнете навмисно вразливі робочі навантаження в ізольованому просторі імен. Мета — не створити навчальний кластер, відкритий в інтернет; мета — створити контрольоване середовище, де погана безпекова конфігурація є видимою, вимірюваною та оборотною.


Архітектура лабораторії

Розділ «Архітектура лабораторії»

Лабораторія має три рівні, які варто подумки тримати окремо під час роботи. Рівень кластера надає примітиви Kubernetes, такі як API-сервер, kubelet, середовище виконання контейнерів, простори імен та засоби контролю допуску. Рівень спостереження додає інструменти, що перевіряють ці примітиви під різними кутами: Trivy бачить образи й маніфести, Falco бачить події середовища виконання, kube-bench бачить конфігурацію хоста та компонентів, а kubesec бачить статичні специфікації Подів. Рівень практики містить навмисно небезпечні робочі навантаження, які дають інструментам щось корисне для звіту.

┌─────────────────────────────────────────────────────────────┐
│ CKS SECURITY LAB │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Kubernetes Cluster │ │
│ │ │ │
│ │ Security Tools Deployed: │ │
│ │ ┌─────────┐ ┌─────────┐ ┌───────────┐ │ │
│ │ │ Falco │ │ Trivy │ │ kube-bench│ │ │
│ │ │(runtime)│ │(scanner)│ │(CIS audit)│ │ │
│ │ └─────────┘ └─────────┘ └───────────┘ │ │
│ │ │ │
│ │ Security Features Enabled: │ │
│ │ ┌─────────┐ ┌─────────┐ ┌───────────┐ │ │
│ │ │AppArmor │ │ seccomp │ │ Audit │ │ │
│ │ │profiles │ │profiles │ │ Logging │ │ │
│ │ └─────────┘ └─────────┘ └───────────┘ │ │
│ │ │ │
│ │ Vulnerable Apps (for practice): │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Intentionally insecure deployments │ │ │
│ │ │ for scanning and hardening practice │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Діаграма показує єдину межу кластера, тому що перше правило цієї лабораторії — стримування. Вразливі Поди, привілейовані контейнери та старі образи належать до простору імен, який існує лише для навчання, а не до спільного кластера розробки. Ставтеся до простору імен як до робочого верстака: ви можете класти на нього гострі інструменти, бо ви контролюєте кімнату, чітко позначаєте роботу та прибираєте, коли вправу завершено.

Друге правило полягає в тому, що кожен сигнал безпеки має мати відоме джерело. Якщо Trivy повідомляє про вразливі пакети, ви маєте знати, чи сканував він образ з реєстру, файлову систему чи маніфест Kubernetes. Якщо Falco видає сповіщення, ви маєте знати, чи прийшла подія від процесу в контейнері, файлової операції на хості, чи зі шляху збагачення метаданими Kubernetes. Якщо kube-bench повідомляє про невдалий контроль, ви маєте знати, чи належить ця перевірка до API-сервера, kubelet, etcd чи операційної системи вузла.

Третє правило — відтворюваність. Лабораторія, яка спрацьовує один раз, але яку не можна перебудувати, є тягарем під час підготовки до екзамену, бо зламаний стан стає невідрізнимим від навчального стану. Тримайте створення кластера, встановлення інструментів, вразливі робочі навантаження та команди перевірки разом у версіонованих нотатках, щоб ви могли скинути все після експериментів. Для практики CKS швидке перебудування часто цінніше за збереження захаращеного кластера, який накопичив невідомі зміни.

Думайте про лабораторію як про фабрику доказів. Кожна вправа має продукувати один артефакт, який ви можете перевірити: звіт сканера, подію аудиту, сповіщення Falco, результат kube-bench або змінену специфікацію Пода. Коли артефакт відсутній, саме цей відсутній артефакт є дефектом, який треба діагностувати. Така рамка тримає модуль практичним, бо ви не просто встановлюєте інструменти; ви доводите, що кожна частина середовища може породжувати докази, коли відбувається дія, релевантна для безпеки.

Інструменти також відрізняються за часовим горизонтом, що впливає на те, як ви тлумачите їхні результати. Trivy та kubesec найсильніші перед розгортанням, бо вони перевіряють вхідні дані, які можна змінити до того, як робоче навантаження запуститься. Логи аудиту та Falco найсильніші під час та після активності, бо вони фіксують поведінку й запити до площини управління. kube-bench розташований між цими поглядами, перевіряючи конфігурацію кластера за бенчмарком. Досвідчений оператор порівнює часовий горизонт інструмента з часовим горизонтом ризику, перш ніж вирішувати, що виправляти.

Зупиніться й подумайте: Як ви гадаєте, чому логування аудиту не ввімкнене за замовчуванням у Kubernetes? Зважте на використання диска, обсяг подій, чутливі тіла запитів та операційну вартість зберігання логів, перш ніж вирішувати, де мають бути дані аудиту в навчальній лабораторії.


Побудова кластера та сліду аудиту

Розділ «Побудова кластера та сліду аудиту»

Почніть з рішення щодо кластера, бо воно визначає, наскільки близько ваша лабораторія до екзаменаційної механіки. Кластер kind швидкий, одноразовий та чудовий для повторюваної практики сканування, маніфестів та допуску. Кластер kubeadm повільніший у перебудові, але він розкриває статичні маніфести Подів і шляхи рівня вузла так, що це виглядає значно ближче до того, що ви бачите під час вправ CKA та CKS. Обидва варіанти прийнятні, але вони навчають дещо різних режимів збоїв.

Для більшості учнів kind є правильною першою лабораторією, бо він прибирає інфраструктурний шум, зберігаючи поведінку Kubernetes достатньо реальною для корисної практики. Наведена нижче конфігурація створює вузол площини управління з політикою аудиту та монтуваннями лога аудиту, а потім додає двох воркерів, щоб поведінка планування не була надто штучною. Зверніть увагу, що прапорці API-сервера посилаються на файли всередині контейнера вузла, тоді як extraMounts зіставляє ці шляхи назад із файлами й каталогами на вашому хості.

Конфігурація kind заслуговує на повільне читання, перш ніж ви її запустите. Секція kubeadmConfigPatches змінює конфігурацію площини управління, що використовується всередині вузла kind, тоді як extraMounts змінює те, які файли з вашої робочої станції з’являються всередині цього вузла. Ці два механізми мають узгоджуватися щодо однакових шляхів. Якщо прапорець API-сервера вказує на /etc/kubernetes/audit-policy.yaml, але файл хоста змонтовано в іншому місці, кластер може не запуститися або запуститися без політики, яку ви мали намір протестувати.

Рівні політики аудиту також заслуговують на свідомий вибір. Metadata записує хто, що, коли й де, не зберігаючи повне тіло об’єкта, чого часто достатньо для Secret і ConfigMap у навчальній лабораторії. Request записує тіло запиту, але не відповідь, що корисно, коли ви хочете побачити деталі створення Пода. RequestResponse записує більше, але може зафіксувати чутливий вміст і створити більший обсяг. Обирайте найлегший рівень, який підтримує вправу, яку ви виконуєте.

Terminal window
# Create kind cluster with audit logging enabled
cat <<EOF > kind-cks.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
apiServer:
extraArgs:
audit-policy-file: /etc/kubernetes/audit-policy.yaml
audit-log-path: /var/log/kubernetes/audit.log
audit-log-maxage: "30"
audit-log-maxbackup: "3"
audit-log-maxsize: "100"
extraVolumes:
- name: audit-policy
hostPath: /etc/kubernetes/audit-policy.yaml
mountPath: /etc/kubernetes/audit-policy.yaml
readOnly: true
pathType: File
- name: audit-logs
hostPath: /var/log/kubernetes
mountPath: /var/log/kubernetes
pathType: DirectoryOrCreate
extraMounts:
- hostPath: ./audit-policy.yaml
containerPath: /etc/kubernetes/audit-policy.yaml
readOnly: true
- hostPath: ./audit-logs
containerPath: /var/log/kubernetes
- role: worker
- role: worker
EOF
# Create the audit log directory on the host
mkdir -p audit-logs
# Create basic audit policy
cat <<EOF > audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: Request
resources:
- group: ""
resources: ["pods"]
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: ""
resources: ["endpoints", "services"]
- level: Metadata
omitStages:
- RequestReceived
EOF
# Create the cluster
kind create cluster --name cks-lab --config kind-cks.yaml
# Prove audit logging before installing security tools
kubectl wait --for=condition=Ready node --all --timeout=120s
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: audit-test
namespace: default
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.10
EOF
kubectl wait --for=condition=Ready pod/audit-test --timeout=60s
sleep 2
# Host-mounted audit log (kind maps /var/log/kubernetes inside the node to ./audit-logs)
grep '"resource":"pods"' audit-logs/audit.log | tail -5
grep '"verb":"create"' audit-logs/audit.log | grep audit-test | tail -3
kubectl delete pod audit-test --wait=false

Політика аудиту навмисно невелика, бо це лабораторія, а не корпоративна архітектура логування. Вона записує метадані для Secret і ConfigMap, тіла запитів для Подів, придушує галасливий watch-трафік kube-proxy та відкидає найраніший етап, щоб зменшити дублювання записів. Це дає вам достатньо сигналу для практики читання виводу аудиту, не заповнюючи каталог хоста кожною watch-подією, що її породжує звичайна робота кластера.

Перш ніж це запустити, спрогнозуйте, де з’явиться перша корисна подія аудиту після того, як ви створите Под. Якщо ви відповіли «лише всередині контейнера API-сервера», подивіться ще раз на зв’язок між монтуванням хоста та шляхом до лога. API-сервер пише до /var/log/kubernetes/audit.log зі свого погляду, але kind зіставляє цей каталог назад із ./audit-logs на вашій робочій станції, що дає вам змогу перевірити файл, не заходячи в контейнер вузла.

Після того як кластер запуститься, створіть один нешкідливий Под, а потім перегляньте найновіші рядки лога аудиту, перш ніж встановлювати будь-які інструменти безпеки. Ця рання перевірка запобігає поширеній навчальній пастці, коли учні успішно встановлюють Trivy, Falco та kube-bench, а потім пізніше виявляють, що докази аудиту так і не було налаштовано. Правильна послідовність — кластер, докази аудиту, встановлення інструментів, вразливі цілі та перевірка. Переставлення цієї послідовності можливе, але воно ускладнює атрибуцію збоїв.

Кластер kubeadm навчає тієї самої концепції через статичні маніфести Подів. API-сервер — це Под, запущений kubelet з /etc/kubernetes/manifests/kube-apiserver.yaml, тож помилка конфігурації часто проявляється як перезапуск Пода площини управління, а не як охайний збій команди. Це корисна підготовка до екзамену, бо вам потрібно під тиском часу пов’язати редагування файлів, узгодження kubelet, змонтовані шляхи хоста та поведінку запуску API-сервера.

Редагуючи маніфест API-сервера kubeadm, робіть один клас зміни за раз. Спочатку додайте файл політики на диск, потім додайте каталог лога, потім додайте записи тома та монтування, і нарешті додайте прапорці аудиту. Такий порядок дає kubelet реальний файл і каталог для монтування до того, як API-сервер запуститься з новими аргументами. Якщо ви додасте спочатку прапорці, а шляхи пізніше, API-сервер може дати збій у спосіб, який виглядає як проблема з аргументами, навіть якщо першопричина — відсутній шлях хоста.

Terminal window
# Enable audit logging on existing cluster
# Edit /etc/kubernetes/manifests/kube-apiserver.yaml on control plane
# Add these flags to the API server:
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-log-maxage=30
# --audit-log-maxbackup=3
# --audit-log-maxsize=100
# You must also add these volumeMounts inside the container spec:
# - mountPath: /etc/kubernetes/audit-policy.yaml
# name: audit-policy
# readOnly: true
# - mountPath: /var/log/kubernetes
# name: audit-logs
# And these volumes at the bottom of the pod spec:
# - hostPath:
# path: /etc/kubernetes/audit-policy.yaml
# type: File
# name: audit-policy
# - hostPath:
# path: /var/log/kubernetes
# type: DirectoryOrCreate
# name: audit-logs
# Create the audit policy file
sudo mkdir -p /etc/kubernetes
sudo tee /etc/kubernetes/audit-policy.yaml <<EOF
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: RequestResponse
resources:
- group: ""
resources: ["pods"]
verbs: ["create", "delete"]
- level: Metadata
omitStages:
- RequestReceived
EOF
# Create log directory
sudo mkdir -p /var/log/kubernetes

Шлях kubeadm має один додатковий ризик: помилка відступу YAML у статичному маніфесті Пода може тимчасово прибрати ваш API-сервер. Це звучить драматично, але kubelet продовжує намагатися узгодити файл, тож виправлення зазвичай зводиться до того, щоб виправити маніфест і зачекати, поки площина управління повернеться. У середовищі екзаменаційного типу завжди тримайте другий термінал доступним на вузлі площини управління, щоб ви могли переглянути логи kubelet або перемістити некоректний маніфест геть зі спостережуваного каталогу за потреби.

Не перетворюйте логування аудиту на вправу з максимального захоплення даних. Тіла запитів можуть містити чутливий матеріал, обсяг логів швидко зростає, а зберігання аудиту є частиною дизайну. У цій лабораторії політика має бути рівно настільки широкою, щоб продемонструвати події створення, видалення та метаданих для релевантних для безпеки ресурсів. У продакшені політику переглядали б з огляду на вимоги до зберігання, приватності, юридичного утримання та реагування на інциденти.

Є ще одна звичка аудиту, яку варто виробити вже зараз: завжди занотовуйте дію, яка має створити подію. Якщо ви застосовуєте Под, запишіть простір імен, ім’я Пода, дієслово та приблизний час, перш ніж шукати в логах. Записи аудиту структуровані, але їх усе одно легко неправильно прочитати, коли активні кілька контролерів. Пошук конкретної події створення чи видалення привчає вас використовувати логи аудиту як докази, а не як прокручувану стіну JSON.


Встановлення інструментів безпеки як циклів зворотного зв’язку

Розділ «Встановлення інструментів безпеки як циклів зворотного зв’язку»

Встановлюйте інструменти з чіткою ментальною моделлю, а не як список покупок. Trivy відповідає на питання «які відомі слабкі місця присутні перед розгортанням або під час нього», Falco відповідає «яка підозріла поведінка відбувається під час виконання», kube-bench відповідає «як цей кластер порівнюється з перевірками бенчмарка CIS», а kubesec відповідає «які ризиковані поля видно в маніфесті». Коли ви знаєте, на яке питання відповідає кожен інструмент, ви можете швидше діагностувати хибний вивід.

Trivy є першим інструментом, бо він дає швидкий зворотний зв’язок із дуже малою залежністю від кластера. Наведена нижче команда зберігає звичне встановлення з репозиторію Debian, шлях macOS через Homebrew, перевірку версії та тестове сканування образу nginx:latest. У реальній роботі вам слід закріплювати образи й уникати покладання на latest, але сканування поширеного тега під час налаштування корисне, бо швидко доводить, що сканер може завантажити свою базу даних вразливостей і прочитати метадані образу.

Налаштування сканера має дві окремі умови успіху. Двійковий файл має запускатися, а база даних вразливостей має бути доступною. Команда версії доводить лише першу умову. Реальне сканування образу доводить другу, бо Trivy має розв’язати шари образу, завантажити чи прочитати свою базу даних і зіставити пакети з відомими записами про вразливості. Якщо сканування дає збій через проблеми з мережею чи кешем, виправте це, перш ніж вводити в тест маніфести Kubernetes.

Terminal window
# Install Trivy CLI
# On Ubuntu/Debian
sudo apt-get install wget apt-transport-https gnupg lsb-release -y
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy -y
# On macOS
brew install trivy
# Verify installation
trivy --version
# Test scan
trivy image nginx:latest

Сирі підрахунки вразливостей є поганою метрикою для прийняття рішень. Образ може показувати багато знахідок низької серйозності, бо містить шар операційної системи загального призначення, тоді як менший образ усе ще може містити одну критичну вразливість, що має значення негайно. Під час практики спочатку запустіть широке сканування, щоб підтвердити роботу інструмента, потім повторіть із фільтрами серйозності, перевірками виправлених версій та скануванням маніфестів, щоб навчитися перетворювати галасливі знахідки на план дій.

Для практики до екзамену важливий хід із Trivy — проговорити вашу триаж-логіку. Скажіть, який образ ви сканували, за якими рівнями серйозності ви фільтрували, чи існують виправлені версії та яке робоче навантаження споживало б образ. Таке проговорювання запобігає поверхневій відповіді на кшталт «використовуйте менший образ», коли реальним виправленням може бути оновлення одного пакета, вибір супроводжуваного тега або блокування розгортання, доки не стане доступним оновлений базовий образ. Команда проста; навичкою є рішення.

Falco — інструмент іншого класу, бо він має спостерігати за подіями рівня ядра з вузлів, що запускають ваші контейнери. Це означає, що вибір драйвера важить більше, ніж успіх встановлення чарта. Сучасний драйвер eBPF є кращим шляхом на підтримуваних ядрах, тоді як деякі локальні кластери потребують драйвера модуля ядра чи іншого запасного варіанта. Реліз Helm може бути розгорнутий чисто й усе одно дати збій під час виконання, якщо вузол не може завантажити потрібний зонд.

Ставтеся до встановлення Falco як до перемовин між чартом, ядром вузла та середовищем виконання контейнерів. Чарт обирає, як Falco намагається спостерігати за подіями, ядро вирішує, які механізми доступні, а середовище виконання формує, які метадані контейнера Falco може збагатити у сповіщення. Простору імен, повного на вигляд справних об’єктів Kubernetes, недостатньо. Вам потрібен робочий Под Falco та логи, які показують, що драйвер успішно ініціалізувався.

Terminal window
# Install Falco using Helm
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
# Install Falco with modern eBPF driver
helm install falco falcosecurity/falco \
--namespace falco \
--create-namespace \
--set driver.kind=modern_ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true
# For kind clusters, use kernel module driver instead
# helm install falco falcosecurity/falco \
# --namespace falco \
# --create-namespace \
# --set driver.kind=kmod
# Verify Falco is running
kubectl get pods -n falco
# Check Falco logs
kubectl logs -n falco -l app.kubernetes.io/name=falco

Зробіть паузу й спрогнозуйте: якщо Поди Falco показують CrashLoopBackOff, які докази дали б вам змогу відрізнити погане значення Helm від непідтримуваного драйвера ядра? Почніть з подій Пода й логів Falco, потім пов’яжіть помилку з можливостями ядра вузла. Якщо логи згадують непідтримувані функції eBPF, оновлення чарта не виправить вузол; вам потрібен сумісний драйвер, інший кластер або ядро хоста, яке підтримує потрібну поведінку eBPF.

FalcoSidekick та його вебінтерфейс включено, бо вони полегшують перегляд сповіщень під час практики, а не тому, що кожне екзаменаційне завдання потребує дашборду. Суттєвою навичкою є читання полів сповіщення та пов’язування їх із робочим навантаженням, що породило цю поведінку. Якщо ви згодом приберете інтерфейс заради легшої лабораторії, тримайте основні логи Falco доступними, бо саме ці логи є доказами, які ви використовуватимете, коли дашборду немає.

Щойно Falco запрацює, згенеруйте нешкідливу тестову подію та прочитайте сповіщення, перш ніж рухатися далі. Поширена практика — виконати інтерактивну оболонку в тестовому контейнері або запустити команду, що спрацьовує одне зі стандартних правил Falco. Робіть це лише в просторі імен лабораторії, потім зіставте поля сповіщення назад із Подом, контейнером, процесом та іменем правила. Ця вправа доводить, що шлях середовища виконання функціонує, і навчає вас, як виглядають нормальні докази Falco.

kube-bench працює найкраще, коли ви розглядаєте його як інтерпретатор бенчмарка, а не як магічний генератор оцінок. Він зіставляє конфігурацію кластера з контролями бенчмарка CIS Kubernetes, потім повідомляє про перевірки pass, fail, warn чи manual. У кластері kind деякі перевірки очікувано виглядатимуть незвично, бо площина управління працює всередині контейнерів; у кластері kubeadm вивід ближчий до шляхів хоста та статичних маніфестів, які охоплює практика CKA.

Мова бенчмарка має значення, бо невдала перевірка не завжди є командою негайно змінити кластер. Деякі контролі не застосовні до конкретного дистрибутива, деякими керує провайдер, а деякі навмисно інші в локальній лабораторії. Під час підготовки до CKS практикуйте пояснення ланцюжка доказів: ID контролю, перевірений файл чи прапорець, поточне значення, очікуване значення та чи робить середовище лабораторії усунення доречним.

Terminal window
# Run kube-bench as a job
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
# Wait for completion
kubectl wait --for=condition=complete job/kube-bench --timeout=120s
# View results
kubectl logs job/kube-bench
# For detailed output on a kubeadm control-plane node (Linux amd64 shell — not a macOS laptop)
curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.15.5/kube-bench_0.15.5_linux_amd64.tar.gz -o kube-bench.tar.gz
tar -xvf kube-bench.tar.gz
./kube-bench run --targets=master

Запуск на основі Job зручний, бо тримає робочий процес усередині Kubernetes, але прямий запуск на вузлі часто інформативніший. Деякі перевірки бенчмарка потребують доступу до файлів хоста, таких як конфігурація kubelet, статичні маніфести Подів та шляхи до сертифікатів. Якщо Job не може побачити релевантний шлях хоста, результат може сказати вам більше про середовище контейнера, ніж про конфігурацію вузла. Саме тому модуль зберігає обидва підходи.

kubesec дає вам легкий прохід статичного аналізу маніфестів. Він не знає вашої повної моделі загроз, але швидко підсвічує поля на кшталт runAsUser: 0, відсутнього контексту безпеки, широких можливостей (capabilities), привілейованого режиму та відсутніх засобів контролю ресурсів. Це робить його корисним перед застосуванням маніфесту, особливо коли ви вчитеся розпізнавати ризиковані налаштування Пода на око.

kubesec також корисний як навчальне дзеркало. Коли він позначає ризиковане поле, відкрийте маніфест і спитайте, який контроль Kubernetes запобіг би цьому ризику або пом’якшив би його. Привілейований контейнер може блокуватися через Pod Security Admission, кореневий процес можна змінити за допомогою runAsNonRoot, а відсутні налаштування ресурсів можна врегулювати через значення за замовчуванням LimitRange чи політику перегляду. Це перетворює одну статичну знахідку на карту можливих контролів.

Terminal window
# Scan a manifest with Docker (primary on macOS/arm64 and when no local binary is installed)
docker run --rm -i kubesec/kubesec:v2.14.0 scan /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: nginx
securityContext:
runAsUser: 0
EOF
# Optional binary install — match host OS and architecture (uname -m)
ARCH=$(uname -m)
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
case "${OS}-${ARCH}" in
linux-x86_64|linux-amd64)
KUBESEC_URL=https://github.com/controlplaneio/kubesec/releases/download/v2.14.0/kubesec_linux_amd64.tar.gz ;;
linux-aarch64|linux-arm64)
KUBESEC_URL=https://github.com/controlplaneio/kubesec/releases/download/v2.14.0/kubesec_linux_arm64.tar.gz ;;
darwin-x86_64|darwin-amd64)
KUBESEC_URL=https://github.com/controlplaneio/kubesec/releases/download/v2.14.0/kubesec_darwin_amd64.tar.gz ;;
darwin-arm64|darwin-aarch64)
KUBESEC_URL=https://github.com/controlplaneio/kubesec/releases/download/v2.14.0/kubesec_darwin_arm64.tar.gz ;;
*)
echo "No binary for ${OS}-${ARCH}; use the Docker one-liner above" >&2; exit 1 ;;
esac
curl -L "$KUBESEC_URL" -o kubesec.tar.gz
tar -xvf kubesec.tar.gz kubesec
sudo mv kubesec /usr/local/bin/

Статичний аналіз не є заміною політики допуску чи моніторингу середовища виконання. Він бачить документ, який ви йому даєте, а не кожну мутацію, що може статися до допуску Пода, і не поведінку, що відбувається після запуску контейнера. Використовуйте kubesec, щоб тренувати око, використовуйте контролі допуску та політики, щоб блокувати погані маніфести, і використовуйте інструменти середовища виконання, щоб ловити поведінку, яка не була очевидною з YAML.

Чотири інструменти тепер утворюють багаторівневий цикл зворотного зв’язку. Trivy перевіряє ризик ланцюга постачання ПЗ, kubesec перевіряє стан маніфесту, kube-bench перевіряє конфігурацію кластера, а Falco перевіряє поведінку середовища виконання. Жоден із цих поглядів не є повним, але разом вони дають вам практичний спосіб відповісти: «звідки прийшов цей ризик, де його мали заблокувати та де ми його спостерігали?». Саме це питання стоїть за багатьма завданнями CKS на усунення проблем.


Перевірка примітивів безпеки рівня вузла

Розділ «Перевірка примітивів безпеки рівня вузла»

AppArmor та seccomp є механізмами рівня вузла, тож самої лише перевірки через API Kubernetes недостатньо. API може прийняти специфікацію Пода, яка посилається на профіль, але kubelet і середовище виконання контейнерів усе одно потребують відповідної підтримки на вузлі, куди приземлиться Под. Ця деталь планування має значення: користувацький профіль на одному вузлі не з’являється магічним чином на кожному іншому вузлі, якщо ви не розмістите його там або не автоматизуєте розповсюдження.

У кластері kind, що хоститься з macOS чи Windows, шляхи вузла на кшталт /sys/module/apparmor та /boot/config-$(uname -r) живуть усередині контейнера вузла kind, а не на ядрі вашого ноутбука. Запускайте наведені нижче перевірки через docker exec проти вузла kind, або підключіться через SSH до вузла kubeadm/Linux і запустіть гілку kubeadm там.

Terminal window
# kind: check AppArmor inside the control-plane node (not on the macOS host)
CP_NODE=$(kind get nodes --name cks-lab 2>/dev/null | head -1)
if [ -n "$CP_NODE" ]; then
docker exec "$CP_NODE" cat /sys/module/apparmor/parameters/enabled # Should output: Y
docker exec "$CP_NODE" aa-status 2>/dev/null | head -20 || true
else
# kubeadm/Linux node shell only
cat /sys/module/apparmor/parameters/enabled
sudo aa-status
fi
# containerd enables AppArmor support by default when the node kernel provides it

AppArmor найлегше зрозуміти як іменований набір правил, завантажений у ядро Linux і потім прикріплений до процесу. Kubernetes дає вам змогу запитувати поведінку AppArmor для контейнера, але вузол має мати завантажений профіль, перш ніж робоче навантаження зможе його використати. У лабораторії це означає, що вам слід перевірити підтримку на самому вузлі, а потім запустити невеликий експеримент із Подом після того, як ви впевнитеся, що шар операційної системи готовий.

Не плутайте доступність профілю з наміром політики. Вузол може мати ввімкнений AppArmor і все одно запускати контейнери під дозвільним чи стандартним профілем, що не демонструє обмеження, яке ви хотіли протестувати. Для значущої лабораторії запишіть ім’я профілю, вузол, де його завантажено, поле чи анотацію Пода, що його запитує, та поведінку, яку він має блокувати. Без цього ланцюжка успішний запуск Пода каже вам дуже мало.

Seccomp подібний за духом, але відрізняється тим, що обмежує. Замість іменування правил для файлів і можливостей, як AppArmor, seccomp фільтрує системні виклики, які є низькорівневими запитами процесу до ядра. Kubernetes підтримує профіль RuntimeDefault та користувацькі localhost-профілі, але користувацький профіль має бути присутнім під коренем seccomp kubelet на вузлі, що запускає Под.

Профіль RuntimeDefault є корисною базовою лінією, бо дає вам безпечніше значення за замовчуванням без керування користувацьким файлом JSON для кожної вправи. Користувацькі профілі все одно варто практикувати, бо вони навчають правилу локальності та режиму збою, коли профіль не вдається знайти. Починайте з RuntimeDefault, коли навчальна мета — загальне посилення безпеки, потім використовуйте localhost-профіль, коли навчальна мета — розміщення шляхів та усунення проблем, специфічних для вузла.

Terminal window
# kind: check seccomp support inside the node (host /boot/config on macOS is the wrong kernel)
CP_NODE=$(kind get nodes --name cks-lab 2>/dev/null | head -1)
if [ -n "$CP_NODE" ]; then
docker exec "$CP_NODE" sh -c 'grep CONFIG_SECCOMP /boot/config-$(uname -r) 2>/dev/null || zgrep CONFIG_SECCOMP /proc/config.gz 2>/dev/null'
docker exec "$CP_NODE" ls /var/lib/kubelet/seccomp/ 2>/dev/null || true
else
# kubeadm/Linux node shell only
grep CONFIG_SECCOMP /boot/config-$(uname -r) # Should see: CONFIG_SECCOMP=y
ls /var/lib/kubelet/seccomp/
sudo mkdir -p /var/lib/kubelet/seccomp/profiles
fi

Зробіть паузу й спрогнозуйте: ви створюєте profiles/audit-only.json на вузлі площини управління, потім плануєте Под на воркер, що посилається на localhost/profiles/audit-only.json. Який шлях помилки ви очікуєте і де б ви шукали першим? Корисна відповідь — не просто «Под дає збій»; вона полягає в тому, що kubelet на обраному воркері просить у середовища виконання шлях до локального профілю, якого на цьому воркері не існує.

Саме тут окупається дисципліна лабораторії. Маркуйте вузли, використовуйте явне планування, коли профіль існує лише на одному вузлі, та занотовуйте, які функції безпеки є вимогами хоста, а не загальнокластерними об’єктами. Для практики з Kubernetes 1.35+ поверхня API може виглядати чистою, але екзаменаційна навичка часто полягає в розпізнаванні того, чи належить збій до допуску, kubelet, середовища виконання контейнерів чи ядра хоста.

Один практичний діагностичний патерн — читати статус Пода ззовні всередину. Почніть з kubectl describe pod, щоб побачити події планування та створення контейнера, потім перегляньте логи kubelet чи середовища виконання на обраному вузлі, якщо подія вказує нижче рівня API. Якщо збій згадує відсутній профіль, не редагуйте RBAC чи NetworkPolicy. Перейдіть до шляху вузла, підтвердьте, що файл існує, підтвердьте, що ім’я профілю збігається з посиланням Пода, і потім повторіть спробу з контрольованим плануванням.


Розгортання навчальних цілей та перевірка лабораторії

Розділ «Розгортання навчальних цілей та перевірка лабораторії»

Навмисно небезпечні робочі навантаження корисні лише тоді, коли вони ізольовані, позначені та одноразові. Простір імен у наведеній нижче команді є межею практики, а не межею дозволів сам по собі. Вам усе одно слід уникати відкривати ці Поди за межами вашої машини, уникати підключення їх до спільних облікових даних та видаляти простір імен, коли вправу завершено. Суть — створити передбачувані погані приклади, проти яких сканери та інструменти посилення безпеки можуть звітувати.

Простір імен слід назвати просто, бо майбутній ви забуде, чому існує привілейований Под. Мітки та імена на кшталт insecure-apps, privileged-pod та vulnerable-image роблять намір очевидним, коли ви згодом переглядаєте логи аудиту чи вивід сканера. Уникайте хитромудрих імен у лабораторії безпеки. Чіткі імена зменшують ймовірність того, що навмисно поганий ресурс сприймуть за випадкове, схоже на продакшен робоче навантаження.

Terminal window
# Create namespace for practice
kubectl create namespace insecure-apps
# Deploy vulnerable app 1: Privileged container
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
namespace: insecure-apps
spec:
containers:
- name: nginx
image: nginx:1.25
securityContext:
privileged: true
EOF
# Deploy vulnerable app 2: Root user
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: root-pod
namespace: insecure-apps
spec:
containers:
- name: nginx
image: nginx:1.25
securityContext:
runAsUser: 0
EOF
# Deploy vulnerable app 3: No resource limits
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: unlimited-pod
namespace: insecure-apps
spec:
containers:
- name: nginx
image: nginx:1.25
# No resources specified = unlimited
EOF
# Deploy vulnerable app 4: Vulnerable image
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: vulnerable-image
namespace: insecure-apps
spec:
containers:
- name: app
image: vulnerables/web-dvwa # Known vulnerable image
EOF

Перш ніж застосовувати ці Поди, спитайте, які контролі заблокували б кожен із них у посиленому кластері. Pod Security Admission в обмеженому просторі імен має відхиляти привілейовані контейнери та сприятливі для кореня налаштування. Політика образів чи контролер допуску могли б заблокувати відомі вразливі образи до планування. Об’єкти ResourceQuota та LimitRange могли б змусити вказувати запити та ліміти ресурсів, тоді як контролі RBAC вирішували б, кому взагалі дозволено створювати простір імен і Поди.

Список навчальних цілей навмисно простий, бо кожен Под навчає одному діагностичному виміру. Привілейований Под привчає вас помічати небезпечні привілеї контейнера. Кореневий Под привчає вас перевіряти налаштування ідентифікації. Необмежений Под привчає вас пов’язувати гігієну ресурсів із надійністю та ризиком відмови в обслуговуванні. Вразливий образ привчає вас відокремлювати знахідки образу від поведінки середовища виконання та посилення маніфесту.

Це також гарне місце, щоб попрактикувати порядок контролів. Вразливий образ можна виявити перед розгортанням сканером, заблокувати на допуску політикою, спостерігати під час виконання у разі експлуатації та пізніше дослідити через логи. Привілейований Под проходить подібним шляхом через статичний аналіз, Pod Security Admission, допуск kubelet та виявлення під час виконання. Коли ви можете описати той самий поганий ресурс на всіх цих етапах, ви вивчаєте модель безпеки, а не запам’ятовуєте команду.

Перевірка замикає цикл, доводячи, що в лабораторії є сигнали, на які ви очікуєте. Хороший скрипт перевірки не стверджує, що кожна знахідка чиста; у лабораторії безпеки деякі знахідки мають бути навмисно поганими. Натомість він підтверджує, що кластер відповідає, сканери запускаються, Falco присутній, якщо встановлений, kube-bench може видати вивід, функції хоста можна перевірити, а логування аудиту принаймні видно в конфігурації API-сервера.

Скрипт перевірки навмисно консервативний. Він уникає зміни політики кластера, не припускає, що Falco є обов’язковим для кожного локального середовища, та повідомляє про відсутні інструменти, не приховуючи решту перевірок. Це робить його корисним під час поетапного налаштування. Ви можете запускати його після створення кластера, знову після встановлення сканера та знову після розгортання вразливих цілей, потім порівняти вивід, щоб побачити, який рівень змінився.

#!/bin/bash
echo "=== CKS Lab Validation ==="
echo ""
# Check cluster
echo "1. Cluster Status:"
kubectl cluster-info | head -2
echo ""
# Check Trivy
echo "2. Trivy:"
if command -v trivy &> /dev/null; then
trivy --version
else
echo " NOT INSTALLED"
fi
echo ""
# Check Falco
echo "3. Falco:"
kubectl get pods -n falco -l app.kubernetes.io/name=falco --no-headers 2>/dev/null | head -1 || echo " NOT RUNNING"
echo ""
# Check kube-bench
echo "4. kube-bench:"
if command -v kube-bench &> /dev/null; then
echo " Installed"
else
echo " Available as Job"
fi
echo ""
# Check AppArmor
echo "5. AppArmor:"
CP_NODE=$(kind get nodes --name cks-lab 2>/dev/null | head -1)
if [ -n "$CP_NODE" ] && docker exec "$CP_NODE" test -f /sys/module/apparmor/parameters/enabled 2>/dev/null; then
docker exec "$CP_NODE" cat /sys/module/apparmor/parameters/enabled
elif [ -f /sys/module/apparmor/parameters/enabled ]; then
cat /sys/module/apparmor/parameters/enabled
else
echo " Check inside cluster nodes (kind: docker exec; kubeadm: SSH to node)"
fi
echo ""
# Check Audit Logging
echo "6. Audit Logging:"
if kubectl get pods -n kube-system -l component=kube-apiserver -o yaml 2>/dev/null | grep -q "audit-log-path"; then
echo " API server flags: Enabled"
if [ -f audit-logs/audit.log ]; then
echo " Host log lines: $(wc -l < audit-logs/audit.log)"
grep '"resource":"pods"' audit-logs/audit.log | tail -1 || echo " No pod events yet — create a test pod"
fi
else
echo " Check API server config"
fi
echo ""
echo "=== Validation Complete ==="

Читайте вивід перевірки як таблицю маршрутизації для вашої наступної дії. Якщо kubectl cluster-info дає збій, жодна діагностика інструмента безпеки ще не має значення, бо з’єднання з кластером розірване. Якщо Trivy відсутній, виправте шлях пакета локальної робочої станції, перш ніж торкатися Kubernetes. Якщо Falco відсутній чи в циклі збоїв, перевірте реліз Helm та логи драйвера. Якщо логування аудиту не видно, поверніться до конфігурації API-сервера, перш ніж очікувати значущих вправ з аудитом.

Найважливіша звичка — фіксувати очікувані збої окремо від неочікуваних. Вразливий образ, що видає страшний результат сканування, очікуваний. Попередження kube-bench, спричинене відомим обмеженням kind, може бути очікуваним. Відсутній файл лога аудиту після того, як ви навмисно створили Поди, не є очікуваним, бо лабораторію було налаштовано саме для спостереження за цією поведінкою. Це розрізнення тримає практику продуктивною, замість того щоб перетворювати кожне попередження на паніку.

Ведіть невеликий журнал лабораторії, поки перевіряєте. Для кожного інструмента запишіть команду, яку ви запустили, ресурс, який він перевірив, очікуваний сигнал та фактичний сигнал. Це може бути коротка нотатка, але вона має бути достатньо конкретною, щоб ви могли перебудувати лабораторію через тиждень і знати, що означало «готово». Практика безпеки покращується найшвидше, коли ви порівнюєте докази в часі, а не покладаєтеся на пам’ять про вдале налаштування.


Патерни та антипатерни

Розділ «Патерни та антипатерни»

Найсильніший патерн лабораторії — будувати цикли зворотного зв’язку навколо одного питання за раз. Якщо ви скануєте образи, оцініть знахідки образу й потім змініть шар образу чи пакета. Якщо ви тестуєте виявлення під час виконання, спричиніть поведінку й потім прочитайте поля сповіщення Falco. Якщо ви запускаєте kube-bench, оберіть один невдалий контроль і простежте його до файлу, прапорця чи налаштування kubelet. Малі цикли створюють стійку екзаменаційну навичку, бо ви можете пояснити кожен результат.

Найслабший патерн — встановити кожен інструмент і сприйняти перший вивід за урок. Інструменти безпеки продукують дані, але навичка CKS — перетворення цих даних на безпечну дію. Це означає, що вам слід на мить зберегти вивід команди, визначити залучений ресурс чи вузол, вирішити, чи є знахідка очікуваною в лабораторії, і потім застосувати одне усунення. Якщо усунення змінює одразу кілька змінних, ви втрачаєте слід доказів.

Ще один корисний патерн — підтримувати одну чисту базову лінію та один навмисно зламаний стан. Чиста базова лінія доводить, що сама лабораторія справна. Зламаний стан доводить, що інструмент може побачити проблему. Переходьте між цими станами свідомо, застосовуючи й видаляючи невеликий маніфест, змінюючи одне значення чарта або перебудовуючи одноразовий кластер. Якщо лабораторія завжди частково зламана, ви перестаєте вчитися, яка зміна породила який результат.

Патерн або антипатернКоли з’являєтьсяОпераційний наслідокКращий хід
Патерн: одноразова лабораторія kindВам потрібна швидка практика сканера й маніфестівПеребудови швидкі, але реалізм рівня хоста обмеженийСпочатку використовуйте kind, потім повторіть вправи зі шляхами вузла на kubeadm
Патерн: реалізм kubeadmВам потрібна практика статичних Подів, kubelet та шляхів вузлаЗбої нагадують екзаменаційні завдання, але перебудови довшіЗробіть знімок нотаток перед редагуванням маніфестів площини управління
Патерн: ізольований небезпечний простір іменВам потрібні навчальні цілі з відомим поганим станомЗнахідки навмисні й легко прибираютьсяПромаркуйте простір імен і видаляйте його після кожної вправи
Антипатерн: гонитва за сирими сумами вразливостейСканування повідомляє великий підрахунокУчні оптимізують за меншу кількість рядків замість ризикуФільтруйте за серйозністю, виправленими версіями, можливістю експлуатації та контекстом робочого навантаження
Антипатерн: ігнорування сумісності драйвераFalco встановлюється, але дає збійЧарт виглядає правильним, тоді як вузол не може підтримати зондПеревірте логи Falco та оберіть сумісний драйвер
Антипатерн: припущення, що профілі є об’єктами кластераПод з seccomp чи AppArmor дає збій на одному вузліПрофілі існують на одному хості, але не там, де працює ПодПеревірте розміщення вузла та розповсюджуйте профілі свідомо

Патерни — не закони; це значення за замовчуванням, які тримають лабораторію чесною. Кластер kind чудовий для повторень, але він може приховувати деталі хоста. Кластер kubeadm чудовий для реалізму вузла, але він може марнувати час, якщо кожен невдалий Под перетворюється на ремонт інфраструктури. Використовуйте патерн, який навчає поточної навички, потім перемикайтеся, коли обмеження стає уроком.

Зріла лабораторія також має умову виходу. Коли вправу завершено, ви маєте знати, чи видалити простір імен, видалити реліз Helm, прибрати Job бенчмарка чи перебудувати кластер. Прибирання є частиною практики безпеки, бо застарілі вразливі ресурси створюють хибні сигнали в наступних вправах. Якщо ви не можете пояснити, чому ризикований Под усе ще працює, найбезпечніше припущення — що його слід прибрати.


Рамка для прийняття рішень

Розділ «Рамка для прийняття рішень»

Обирайте шлях лабораторії, питаючи, які докази вам потрібні від середовища. Якщо доказ — це звіт сканера, оцінка маніфесту чи результат допуску, kind зазвичай достатньо. Якщо доказ — це шлях kubelet, статичний маніфест Пода, профіль ядра чи перевірка бенчмарка, що торкається хоста, kubeadm зазвичай кращий. Якщо доказ — це поведінка середовища виконання, може спрацювати будь-який кластер, але вирішальним фактором стає підтримка драйвера Falco.

Точка рішенняОберіть Kind, колиОберіть Kubeadm, колиРизик, за яким стежити
Логування аудитуВи хочете швидку практику аудиту API-сервера з логами, змонтованими з хостаВи хочете практику зі статичним маніфестом Пода та реальними шляхами площини управлінняПогані редагування маніфесту можуть перервати API-сервер
Trivy та kubesecВам переважно потрібні цикли зворотного зв’язку для образів і YAMLВам потрібен той самий робочий процес сканера проти довговічнішої лабораторіїВивід сканера може стати галасливим без триажу за серйозністю
FalcoВаше ядро хоста та вибір драйвера, як відомо, працюютьВам потрібна реалістичніша інспекція середовища виконання рівня вузлаНевідповідність драйвера може виглядати як збій Helm
kube-benchВам потрібен швидкий звіт для практики тлумаченняВам потрібні перевірки бенчмарка рівня хоста, близькі до форми екзаменуКонтейнеризовані Job можуть не бачити кожного шляху хоста
AppArmor та seccompВам потрібні лише посилання рівня API та прості експериментиВам потрібно розмістити й перевірити профілі на реальних вузлахРозташування профілю має збігатися із запланованим вузлом

Використовуйте двопрохідний підхід, якщо маєте час. Спочатку побудуйте лабораторію kind і відрепетируйте робочий процес інструмента, доки команди, простори імен та прибирання не стануть звичними. Потім повторіть завдання аудиту, kube-bench, AppArmor та seccomp на kubeadm, щоб ви вивчили шляхи вузла та поведінку статичних Подів. Така послідовність тримає перший прохід швидким, водночас розкриваючи операційну механіку, яка має значення на схожих на екзамен системах.

Коли крок перевірки дає збій, класифікуйте збій, перш ніж його виправляти. Збої робочої станції включають відсутні двійкові файли, недосяжні репозиторії пакетів та проблеми із завантаженням бази даних сканера. Збої кластера включають зламаний kubeconfig, невдалі Поди, відсутні простори імен та відсутні прапорці API-сервера. Збої вузла включають непідтримувані функції ядра, відсутні профілі та недоступні шляхи хоста. Правильна класифікація запобігає випадковим змінам, що ускладнюють осмислення лабораторії.

Використовуйте ту саму класифікацію для планування усунення. Збої робочої станції зазвичай потребують виправлень пакета, кешу, облікових даних чи мережі. Збої кластера зазвичай потребують інспекції об’єктів Kubernetes, змін релізу Helm чи конфігурації API-сервера. Збої вузла зазвичай потребують доступу до оболонки, перевірок файлів хоста, перевірок можливостей ядра чи перепланування робочого навантаження. Якщо ваше запропоноване виправлення належить до іншого рівня, ніж доказ, зробіть паузу, перш ніж його застосовувати.

Рамка для прийняття рішень також має враховувати час. Перед сеансом практики з таймером віддавайте перевагу шляху з меншою кількістю рухомих частин, щоб ви могли зосередитися на екзаменаційній навичці. Під час глибшого навчального блоку обирайте шлях, що розкриває базовий механізм, навіть якщо налаштування повільніше. Лабораторія — це не одне середовище назавжди; це набір компромісів, які ви обираєте на основі поведінки, яку вам потрібно спостерігати.


Ці факти варто запам’ятати, бо вони пояснюють, чому лабораторія має кілька інструментів замість одного універсального сканера.

  • Falco було спочатку створено у 2016 році (анонс релізу Sysdig, травень 2016) і пізніше він став проєктом CNCF, зосередженим на виявленні загроз середовища виконання для хмарних робочих навантажень.

  • Trivy сканує більше, ніж образи контейнерів; він може перевіряти файлові системи, репозиторії, ресурси Kubernetes та вхідні дані інфраструктури як коду, що робить його корисним до й після розгортання.

  • Бенчмарк CIS Kubernetes включає понад 200 перевірок для площини управління, etcd, вузла, політик та областей керованих сервісів (kube-bench реалізує ці перевірки), тож вивід kube-bench потребує триажу, а не сліпої гонитви за оцінкою.

  • AppArmor та SELinux вирішують подібну проблему стримування по-різному; системи родини Ubuntu зазвичай використовують AppArmor, тоді як системи родини RHEL зазвичай використовують SELinux, а практика CKS часто наголошує на механіці AppArmor.


Більшість збоїв лабораторії — це звичайні помилки налаштування, замасковані під безпекову складність. Використовуйте таблицю як діагностичний контрольний список, перш ніж перебудовувати весь кластер.

ПомилкаЧому вона стаєтьсяЯк її виправити
Логування аудиту не ввімкненеКластер чудово запускається без прапорців аудиту, тож відсутність доказів помічають лише під час вправиНалаштуйте політику аудиту API-сервера, шлях до лога, прапорці зберігання та потрібні томи хоста, перш ніж запускати вправи з аудиту
Falco не працюєВстановлення Helm успішне, але обраний драйвер не може завантажитися на ядрі вузлаПеревірте логи Пода Falco, підтвердьте помилку драйвера та встановіть із драйвером, сумісним із хостом лабораторії
Сканування образів лише один разПерший звіт Trivy відчувається як завершення, хоча робочий процес усунення не відпрацьованоПересканіруйте після зміни тегів образу, фільтрів серйозності, версій пакетів чи налаштувань маніфесту
Пропуск налаштування вразливого застосункуВ інструментів немає реалістичних цілей, тож кожна вправа стає абстрактним читанням виводуРозгорніть ізольовані навмисно небезпечні Поди та задокументуйте, яку знахідку має спричинити кожен Под
Неперевірка інструментів рівня вузлаAppArmor та seccomp розглядають як об’єкти API, хоча профілі та підтримка ядра живуть на вузлахПідключіться через SSH або зайдіть на вузол, перевірте підтримку ядра, шляхи профілів та розміщення планування
Ставлення до kube-bench як до значка pass/failВивід бенчмарка легше процитувати, ніж простежити до конкретної конфігураціїОберіть одну невдалу перевірку, знайдіть пов’язаний файл чи прапорець і вирішіть, чи робить середовище лабораторії її очікуваною
Залишання навчальних навантажень позадуНебезпечні Поди залишаються після вправи й заплутують пізніший вивід перевіркиВидаляйте простір імен insecure-apps або перебудовуйте одноразовий кластер після кожного сеансу практики

Використовуйте ці сценарії, щоб перевірити, чи можете ви спрямувати проблему лабораторії до правильного рівня, перш ніж змінювати команди.

1. Навчальний сценарій: Ви запускаєте `trivy image nginx:latest` і отримуєте понад 140 вразливостей. Колега хоче негайно перевести всі робочі навантаження на образи на основі Alpine. Чи це правильна реакція і що б ви зробили спершу?

Перехід на інші базові образи може зменшити кількість пакетів, але він не є автоматично правильною реакцією. Спершу відфільтруйте звіт за серйозністю, доступністю виправленої версії, розташуванням пакета та тим, чи досяжний вразливий компонент у робочому навантаженні. Образи Alpine, distroless та slim мають свої компроміси, тож безпечніша дія — оцінити знахідки, оновити чи замінити базовий образ свідомо та пересканувати, щоб довести, що усунення змінило ризик, а не просто змінило підрахунок.

2. Навчальний сценарій: Ви створюєте користувацький профіль seccomp під `/etc/seccomp/profiles/`, посилаєтеся на нього з Пода, і Под дає збій під час створення контейнера. Що пішло не так?

Localhost-профілі seccomp у Kubernetes розв’язуються відносно каталогу seccomp kubelet, зазвичай /var/lib/kubelet/seccomp/, на вузлі, що запускає Под. Розміщення файлу під загальним шляхом операційної системи не робить його доступним для kubelet чи середовища виконання контейнерів. Перемістіть профіль під шлях kubelet, посилайтеся на нього з правильним іменем localhost-профілю та переконайтеся, що Под планується на вузол, де файл справді існує.

3. Навчальний сценарій: Рецензент помічає `vulnerables/web-dvwa` у просторі імен `insecure-apps` і питає, чому лабораторія розгортає навмисно вразливий образ. Як ви виправдаєте це безпечно?

Образ є контрольованою навчальною ціллю, а не виробничою залежністю. Він дає Trivy реальні знахідки для звіту й дає учневі конкретне робоче навантаження, яке треба посилити контекстом безпеки, політикою допуску та мережевими контролями. Безпечне виправдання залежить від ізоляції: простір імен має бути чітко призначений для лабораторного використання, кластер не має зберігати реальних облікових даних, зовнішнього відкриття слід уникати, а прибирання має бути частиною вправи.

4. Навчальний сценарій: Falco встановлено з `driver.kind=modern_ebpf`, але кожен Под Falco входить у `CrashLoopBackOff`, а логи згадують непідтримувані функції ядра. Як ви це діагностуєте та виправите?

Почніть із логів і подій Пода, бо реліз Helm може існувати навіть тоді, коли драйвер не може завантажитися. Помилка вказує на можливості вузла, тож оновлення випадкових значень чарта навряд чи допоможе. Оберіть драйвер, що відповідає хосту лабораторії, наприклад шлях модуля ядра, коли це доречно, або перемістіть лабораторію на ядро хоста, що підтримує вимоги сучасного eBPF. Після зміни драйвера перевірте статусом Пода та простою подією середовища виконання.

5. Навчальний сценарій: kube-bench повідомляє про кілька невдалих контролів, коли запущений як Kubernetes Job у kind. Чи слід вам негайно редагувати кожне повідомлене налаштування?

Ні. Спершу вирішіть, чи відображає кожна знахідка ціль бенчмарка, середовище kind чи реальну проблему конфігурації, яку ви маєте намір відпрацювати. Контейнеризовані Job бенчмарка можуть не бачити кожного шляху хоста так само, як прямий запуск на вузлі, а kind має інше пакування площини управління, ніж kubeadm. Оберіть одну перевірку, простежте її до релевантного файлу чи прапорця і лише тоді вирішіть, чи має усунення сенс у цій лабораторії.

6. Навчальний сценарій: Ваша політика аудиту присутня, Под API-сервера працює, але жодних очікуваних подій створення Пода не з'являється після того, як ви розгорнули тестовий Под. Що ви перевіряєте далі?

Перевірте зв’язок між прапорцями API-сервера, змонтованим файлом політики, змонтованим каталогом лога та шляхом хоста, де ви очікуєте читати логи. API-сервер може писати всередині шляху свого контейнера, тоді як каталог хоста, який ви перевіряєте, насправді не змонтований. Також підтвердьте, що правило політики включає події створення Пода на рівні, який записує те, на що ви очікуєте. Щойно шлях і правило збігаються, повторіть нову дію створення Пода замість пошуку події, яка сталася до того, як завантажилася виправлена конфігурація.

7. Навчальний сценарій: kubesec позначає Под за `runAsUser: 0`, але Под уже працює у вашій лабораторії. У чому урок безпеки і яку дію ви б відпрацювали?

kubesec — це статичний аналіз, тож він каже вам, що маніфест ризикований; він не запобігає заднім числом активному Поду. Урок — відокремлювати виявлення від примусового виконання. Відпрацюйте оновлення маніфесту, щоб запускати від некореневого користувача, додайте сильніший контекст безпеки, а потім поміркуйте, який контроль допуску заблокував би ризиковану форму, перш ніж вона досягне кластера. Перезапустіть статичне сканування та перевірте специфікацію Пода після повторного розгортання, щоб підтвердити зміну.


Вправа перетворює модуль на повторювану перевірку готовності. Виконуйте завдання по порядку, бо кожне наступне звужує можливу область збою для наступного. Якщо завдання дає збій, зупиніться й виправте цей рівень, перш ніж продовжувати; зламане з’єднання з кластером робить встановлення сканера нерелевантним, а відсутній сканер робить знахідки вразливих навантажень менш корисними.

Виконуйте вправу з таймером лише після того, як ви один раз пройшли її повільно. Перший прохід — для побудови ментальної карти: який файл належить API-серверу, який вивід доводить, що Trivy функціонує, яка помилка Falco вказує на драйвер та який шлях вузла має значення для seccomp. Прохід із таймером — для екзаменаційної швидкості. Змішування цих цілей надто рано заохочує запам’ятовування команд без діагностичної розсудливості, якої вимагають завдання CKS.

Terminal window
# 1. Verify cluster is running
kubectl get nodes
# 2. Prove audit logging records pod events (kind: host-mounted ./audit-logs)
kubectl wait --for=condition=Ready node --all --timeout=120s
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: audit-test
namespace: default
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.10
EOF
kubectl wait --for=condition=Ready pod/audit-test --timeout=60s
sleep 2
grep '"verb":"create"' audit-logs/audit.log | grep audit-test | tail -3
kubectl delete pod audit-test --wait=false
# 3. Install Trivy and scan an image
trivy image nginx:latest | head -50
# 4. Check Falco is running (if installed)
kubectl get pods -n falco
# 5. Run kube-bench
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl wait --for=condition=complete job/kube-bench --timeout=120s
kubectl logs job/kube-bench | head -100
# 6. Create a test pod and scan the image (apply avoids default SA race on fresh kind 1.35)
until kubectl get sa default -n default >/dev/null 2>&1; do sleep 1; done
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
spec:
containers:
- name: nginx
image: nginx:1.25
EOF
kubectl wait --for=condition=Ready pod/test-pod --timeout=60s
trivy image nginx:1.25
# 7. Cleanup
kubectl delete pod test-pod
kubectl delete job kube-bench
  • Завдання 1: Розгорніть або оберіть кластер лабораторії. Використовуйте конфігурацію kind, коли хочете швидкі перебудови, або використовуйте кластер kubeadm, коли хочете реалізм статичних Подів та шляхів вузла.
Підказка до розв'язання

Підтвердьте, що kubectl get nodes повертає принаймні один вузол у стані Ready, перш ніж встановлювати інструменти безпеки. Якщо ви використовуєте kind, перевірте локальний каталог лога аудиту після створення невеликого Пода. Якщо ви використовуєте kubeadm, переконайтеся, що статичний Под API-сервера залишається справним після додавання прапорців аудиту та томів.

  • Завдання 2: Налаштуйте логування аудиту й доведіть, що воно записує дію Пода. Створіть Под, видаліть його та знайдіть відповідну подію аудиту через налаштований шлях лога.
Підказка до розв'язання

Для kind перевірте змонтований із хоста каталог audit-logs. Для kubeadm перевірте налаштований шлях лога площини управління. Якщо подія не з’являється, перегляньте прапорці API-сервера, правила політики та те, чи сталася дія після того, як API-сервер перезавантажив конфігурацію.

  • Завдання 3: Встановіть і перевірте Trivy, Falco, kube-bench та kubesec. Запишіть одну успішну команду чи перевірку статусу від кожного інструмента, щоб ви могли відрізнити збій встановлення від знахідок безпеки.
Підказка до розв'язання

Використовуйте trivy --version, kubectl get pods -n falco, логи Job kube-bench чи прямий запуск на вузлі та невелике сканування kubesec. Якщо Falco дає збій, класифікуйте помилку як конфігурацію чарта, налаштування простору імен чи сумісність драйвера, перш ніж змінювати значення.

  • Завдання 4: Розгорніть ізольовані вразливі навчальні цілі. Тримайте їх у insecure-apps, скануйте їх і визначте, який інструмент повідомляє про який вид проблеми.
Підказка до розв'язання

Привілейований Под має навчати посиленню маніфесту, кореневий Под має навчати налаштуванням ідентифікації, необмежений Под має навчати керуванню ресурсами, а вразливий образ має навчати триажу сканера. Не відкривайте ці робочі навантаження за межами лабораторії.

  • Завдання 5: Оцініть результати лабораторії та оберіть один шлях усунення. Оберіть одну знахідку, поясніть, чи прийшла вона від сканування образу, виявлення під час виконання, порівняння за бенчмарком чи статичного аналізу, потім застосуйте або опишіть вузьке виправлення.
Підказка до розв'язання

Сильна відповідь називає джерело доказу та рівень, до якого він належить. Приклади включають зміну ризикованого контексту безпеки Пода після виводу kubesec, фільтрування знахідок Trivy перед зміною образу чи коригування налаштувань драйвера Falco після читання логів середовища виконання. Приберіть тестовий Под, Job kube-bench та вразливий простір імен, коли вправу завершено.

Критерії успіху:

  • Кластер досяжний через kubectl get nodes.
  • Логування аудиту налаштоване й продукує подію для дії створення чи видалення Пода.
  • Trivy сканує образ, і ви можете пояснити принаймні одну знахідку високої серйозності або чому вона не потребує дії.
  • Falco або успішно працює, або ви задокументували причину драйвера, чому він не працює в цій лабораторії.
  • kube-bench продукує вивід через Job чи прямий запуск на вузлі.
  • kubesec сканує маніфест і позначає ризикований контекст безпеки.
  • Простір імен insecure-apps видалено або одноразовий кластер перебудовано після практики.

Перевірка для учня

Розділ «Перевірка для учня»

Host-mounted audit log (kind maps /var/log/kubernetes inside the node to ./audit-logs)

Перш ніж рухатися далі, поясніть, чому grep audit-logs/audit.log на вашій робочій станції може показувати події створення Пода, навіть попри те, що процес API-сервера працює всередині контейнера площини управління kind. Ґрунтовна відповідь пов’язує прапорець API-сервера --audit-log-path, внутрішньовузловий каталог /var/log/kubernetes та зіставлення kind extraMounts, яке відкриває цей каталог як ./audit-logs на хості.


Модуль 0.3: Майстерність роботи з інструментами безпеки — Глибоке занурення у використання Trivy, Falco та kube-bench.