Модуль 1.1: Поглиблене вивчення Network Policies
Складність:
[СЕРЕДНЯ]— Ключова навичка CKSЧас на виконання: 45-50 хвилин
Передумови: Знання мережі з CKA, базовий досвід з NetworkPolicy
Що ви зможете робити
Розділ «Що ви зможете робити»Після завершення цього модуля ви зможете:
- Створити ingress та egress NetworkPolicies, що забезпечують комунікацію Pod за принципом найменших привілеїв
- Діагностувати збої з’єднань, спричинені відсутніми або надмірно обмежувальними політиками
- Реалізувати політики default-deny та вибірково дозволити необхідні потоки трафіку
- Аудитувати існуючі NetworkPolicies для виявлення прогалин, що дозволяють латеральний рух
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»NetworkPolicies — це фаєрвол Kubernetes. За замовчуванням усі Pod можуть спілкуватися з усіма іншими Pod — кошмар безпеки. NetworkPolicies дозволяють точно визначити, які Pod можуть спілкуватися з якими, блокуючи латеральний рух у разі компрометації.
CKS серйозно тестує NetworkPolicies. Ви повинні писати їх швидко та правильно під тиском іспиту.
Проблема за замовчуванням
Розділ «Проблема за замовчуванням»┌─────────────────────────────────────────────────────────────┐│ МЕРЕЖА KUBERNETES ЗА ЗАМОВЧУВАННЯМ │├─────────────────────────────────────────────────────────────┤│ ││ Без NetworkPolicies: ││ ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ Web Pod │◄───►│ API Pod │◄───►│ DB Pod │ ││ └────┬────┘ └────┬────┘ └────┬────┘ ││ │ │ │ ││ └───────────────┼───────────────┘ ││ │ ││ ┌───────────────┼───────────────┐ ││ │ │ │ ││ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ││ │Зловмис- │◄───►│Будь-який│◄───►│ Secrets │ ││ │ник Pod │ │ Pod │ │ Pod │ ││ └─────────┘ └─────────┘ └─────────┘ ││ ││ ❌ Кожен Pod може дістатися до кожного іншого Pod ││ ❌ Скомпрометований Pod = доступ до всього ││ ❌ Немає мережевої сегментації ││ │└─────────────────────────────────────────────────────────────┘Основи NetworkPolicy
Розділ «Основи NetworkPolicy»Як вони працюють
Розділ «Як вони працюють»apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: example namespace: defaultspec: # Which pods this policy applies to podSelector: matchLabels: app: web
# Which directions to control policyTypes: - Ingress # Incoming traffic - Egress # Outgoing traffic
# What's allowed IN ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 80
# What's allowed OUT egress: - to: - podSelector: matchLabels: app: database ports: - port: 5432Ключові концепції
Розділ «Ключові концепції»┌─────────────────────────────────────────────────────────────┐│ МЕНТАЛЬНА МОДЕЛЬ NETWORKPOLICY │├─────────────────────────────────────────────────────────────┤│ ││ podSelector: ДО КОГО застосовується ця політика? ││ (Порожній = усі Pod у просторі імен) ││ ││ policyTypes: ЯКІ напрямки трафіку контролювати? ││ - Лише Ingress ││ - Лише Egress ││ - Обидва ││ ││ ingress.from: ХТО може надсилати трафік ДО обраних Pod? ││ ││ egress.to: КУДИ обрані Pod можуть надсилати трафік? ││ ││ ports: ЯКІ порти дозволені? ││ (Пропущено = усі порти) ││ ││ КРИТИЧНО: Немає правил ingress/egress = ЗАБОРОНИТИ ВСЕ ││ (якщо вказано policyType) ││ │└─────────────────────────────────────────────────────────────┘Основні патерни
Розділ «Основні патерни»Патерн 1: Заборонити все за замовчуванням
Розділ «Патерн 1: Заборонити все за замовчуванням»# Deny all ingress traffic to namespaceapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-ingress namespace: securespec: podSelector: {} # All pods policyTypes: - Ingress # No ingress rules = deny all ingress---# Deny all egress traffic from namespaceapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-egress namespace: securespec: podSelector: {} policyTypes: - Egress # No egress rules = deny all egress---# Deny BOTH ingress and egressapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-all namespace: securespec: podSelector: {} policyTypes: - Ingress - EgressПатерн 2: Дозволити конкретний Pod-to-Pod
Розділ «Патерн 2: Дозволити конкретний Pod-to-Pod»# Allow frontend pods to access api pods on port 8080apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-frontend-to-api namespace: productionspec: podSelector: matchLabels: app: api policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080Патерн 3: Дозволити з простору імен
Розділ «Патерн 3: Дозволити з простору імен»# Allow any pod from 'monitoring' namespaceapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-from-monitoring namespace: productionspec: podSelector: matchLabels: app: web policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: monitoringПатерн 4: Дозволити до зовнішнього CIDR
Розділ «Патерн 4: Дозволити до зовнішнього CIDR»# Allow egress to specific IP rangeapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-external-api namespace: productionspec: podSelector: matchLabels: app: backend policyTypes: - Egress egress: - to: - ipBlock: cidr: 10.0.0.0/8 except: - 10.0.1.0/24 # Except this subnet ports: - port: 443Патерн 5: Дозволити DNS (Критично!)
Розділ «Патерн 5: Дозволити DNS (Критично!)»# Allow DNS - ALWAYS needed for egress policiesapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-dns namespace: productionspec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: {} podSelector: matchLabels: k8s-app: kube-dns ports: - port: 53 protocol: UDP - port: 53 protocol: TCPКомбінування селекторів
Розділ «Комбінування селекторів»Логіка AND проти OR
Розділ «Логіка AND проти OR»# OR: Allow from EITHER namespace OR pods with labelingress:- from: - namespaceSelector: matchLabels: env: prod - podSelector: matchLabels: role: frontend
# AND: Allow from pods with label IN namespace with labelingress:- from: - namespaceSelector: matchLabels: env: prod podSelector: matchLabels: role: frontend┌─────────────────────────────────────────────────────────────┐│ ПРАВИЛА КОМБІНУВАННЯ СЕЛЕКТОРІВ │├─────────────────────────────────────────────────────────────┤│ ││ Два елементи списку = OR ││ - from: ││ - namespaceSelector: ... # АБО ││ - podSelector: ... # Збіг з будь-яким ││ ││ Один елемент, кілька селекторів = AND ││ - from: ││ - namespaceSelector: ... # І ││ podSelector: ... # Обидва повинні збігатися ││ ││ ⚠️ Це поширена пастка на іспиті! ││ │└─────────────────────────────────────────────────────────────┘Реальні сценарії іспиту
Розділ «Реальні сценарії іспиту»Сценарій 1: Ізоляція бази даних
Розділ «Сценарій 1: Ізоляція бази даних»# Only API pods can reach database on port 5432apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: db-isolation namespace: productionspec: podSelector: matchLabels: app: database policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: api ports: - port: 5432 egress: [] # No egress allowedСценарій 2: Багаторівневий застосунок
Розділ «Сценарій 2: Багаторівневий застосунок»# Web tier: only from ingress controller---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: web-policy namespace: appspec: podSelector: matchLabels: tier: web policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: name: ingress-nginx ports: - port: 80
# API tier: only from web tier---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: api-policy namespace: appspec: podSelector: matchLabels: tier: api policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: tier: web ports: - port: 8080
# DB tier: only from API tier---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: db-policy namespace: appspec: podSelector: matchLabels: tier: db policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: tier: api ports: - port: 5432Сценарій 3: Блокування сервісу метаданих
Розділ «Сценарій 3: Блокування сервісу метаданих»# Block access to cloud metadata (169.254.169.254)apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: block-metadata namespace: defaultspec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 0.0.0.0/0 except: - 169.254.169.254/32Налагодження NetworkPolicies
Розділ «Налагодження NetworkPolicies»# List policies in namespacekubectl get networkpolicies -n production
# Describe policy detailskubectl describe networkpolicy db-isolation -n production
# Check if CNI supports NetworkPolicies# (Calico, Cilium, Weave support them; Flannel doesn't!)kubectl get pods -n kube-system | grep -E "calico|cilium|weave"
# Test connectivitykubectl exec -it frontend-pod -- nc -zv api-pod 8080kubectl exec -it frontend-pod -- curl -s api-pod:8080
# Check pod labels (policies match on labels!)kubectl get pod -n production --show-labelsЧи знали ви?
Розділ «Чи знали ви?»-
NetworkPolicies є адитивними. Якщо кілька політик обирають Pod, застосовується об’єднання всіх правил. Ви не можете використати одну політику для перевизначення іншої.
-
Поведінка за замовчуванням — дозволити все. NetworkPolicies лише обмежують — вони не дозволяють явно. Pod без політик, що його обирають, дозволяє весь трафік.
-
DNS часто забувають. Коли ви додаєте політики egress, Pod не можуть вирішувати DNS, якщо ви явно не дозволите UDP/TCP 53 до kube-dns.
-
Не всі CNI підтримують NetworkPolicies. Flannel не підтримує. Calico, Cilium та Weave підтримують. Перевірте свій кластер!
-
Cilium виходить за межі NetworkPolicies. Cilium підтримує стандартні Kubernetes NetworkPolicies плюс власний CRD
CiliumNetworkPolicyдля фільтрації L7 (HTTP/gRPC), DNS-обізнаних політик та прозорого Pod-to-Pod шифрування (WireGuard або IPsec) без будь-яких змін у застосунку. Якщо ваше середовище іспиту CKS використовує Cilium, ви отримуєте мережеве шифрування фактично безкоштовно:
# Enable Cilium transparent encryption (cluster-level)# In Cilium Helm values or ConfigMap:encryption: enabled: true type: wireguard # or ipsecПоширені помилки
Розділ «Поширені помилки»| Помилка | Чому це шкодить | Рішення |
|---|---|---|
| Забути DNS egress | Pod не можуть вирішувати імена | Завжди дозволяйте DNS з політиками egress |
| Неправильна логіка селектора | Політика не відповідає потрібним Pod | AND = один елемент, OR = окремі елементи |
| Відсутні мітки простору імен | namespaceSelector не збігається | Позначте простори імен мітками |
| Тестування з неправильного Pod | Думає, що політика не працює | Перевірте, що мітки вихідного Pod збігаються |
| CNI не підтримує NP | Політика існує, але не застосовується | Використовуйте Calico, Cilium або Weave |
Тест
Розділ «Тест»-
Що станеться, якщо NetworkPolicy вказує
policyTypes: [Ingress], але не має правилingress?Відповідь
Весь вхідний трафік до обраних Pod заборонений. Вказання policyType без правил означає "заборонити все для цього типу". -
Як дозволити трафік від будь-якого Pod у конкретному просторі імен?
Відповідь
Використовуйте `namespaceSelector` з мітками, що відповідають цьому простору імен. Простір імен повинен мати мітку для вибору, наприклад, `namespaceSelector: {matchLabels: {name: monitoring}}`. -
Яка різниця між двома елементами
fromта двома селекторами в одному елементіfrom?Відповідь
Два елементи `from` = OR (збіг з будь-яким). Два селектори в одному елементі = AND (збіг з обома). Це критично для складних політик. -
Чому політики egress часто ламають вирішення DNS?
Відповідь
DNS використовує UDP порт 53 до Pod kube-dns. Політики egress, які явно не дозволяють це, блокують DNS, ламаючи вирішення імен для уражених Pod.
Практична вправа
Розділ «Практична вправа»Завдання: Створіть NetworkPolicies для трирівневого застосунку.
# Setupkubectl create namespace exercisekubectl label namespace exercise name=exercise
# Create podskubectl run web --image=nginx -n exercise -l tier=webkubectl run api --image=nginx -n exercise -l tier=apikubectl run db --image=nginx -n exercise -l tier=db
# Wait for podskubectl wait --for=condition=Ready pod --all -n exercise
# Task 1: Create default deny all ingresscat <<EOF | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny namespace: exercisespec: podSelector: {} policyTypes: - IngressEOF
# Verify: api can't reach db anymorekubectl exec -n exercise web -- curl -s --connect-timeout 2 db || echo "Blocked (expected)"
# Task 2: Allow web -> api on port 80cat <<EOF | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-web-to-api namespace: exercisespec: podSelector: matchLabels: tier: api policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: tier: web ports: - port: 80EOF
# Task 3: Allow api -> db on port 80cat <<EOF | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-api-to-db namespace: exercisespec: podSelector: matchLabels: tier: db policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: tier: api ports: - port: 80EOF
# Verifykubectl exec -n exercise web -- curl -s --connect-timeout 2 api # Should workkubectl exec -n exercise api -- curl -s --connect-timeout 2 db # Should workkubectl exec -n exercise web -- curl -s --connect-timeout 2 db # Should fail
# Cleanupkubectl delete namespace exerciseКритерії успіху: Web може дістатися до API, API може дістатися до DB, Web не може безпосередньо дістатися до DB.
Підсумок
Розділ «Підсумок»Основи NetworkPolicy:
podSelector: До яких Pod застосовується політикаpolicyTypes: Ingress, Egress або обидваingress/egress: Який трафік дозволений
Критичні патерни:
- Заборона за замовчуванням:
podSelector: {}без правил - Завжди дозволяйте DNS з політиками egress
- AND проти OR: Один елемент = AND, окремі елементи = OR
Поради для іспиту:
- Правильно позначайте Pod та простори імен
- Тестуйте з’єднання після застосування політик
- Пам’ятайте: немає політики = дозволити все
Наступний модуль
Розділ «Наступний модуль»Модуль 1.2: CIS Benchmarks — Аудит безпеки кластера з kube-bench.