Посилення безпеки Kubernetes за допомогою режиму Istio Ambient Mode у пласких мережах

Як використовувати режим Istio Ambient для захисту вашої локальної мережі.

Jun 20, 2026 | Від Harshwardhan Mehrotra - One2N

Якщо ви перенесли робоче навантаження з AWS на локальну інфраструктуру, ви, ймовірно, стикалися з цим: ізоляції мережі, яку ви отримували безкоштовно в хмарі, на bare metal немає.

В AWS Security Groups та межі VPC мовчки забезпечують межі сервісів. Більшість команд ніколи не замислюються про це. На локальній інфраструктурі мережа зазвичай є пласкою. Ваш платіжний сервіс, внутрішня панель адміністратора, агент логування та API для клієнтів всі знаходяться в одному кластері без нічого між ними на мережевому рівні.

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

Отже, у розгортанні EKS Hybrid, яке ми проводили, ми вирішили розвʼязати це на рівні mesh. У нас уже був Istio в стеку, і він дав нам спосіб забезпечити ізоляцію на рівні робочого навантаження без очікування змін на мережевому рівні. Команда з безпеки переглянула модель і схвалила її, оскільки контрольні механізми, які ми побудували, безпосередньо відповідали тому, що вони вимагали б від брандмауера. Ця доповідь охоплює ширші налаштування EKS Hybrid, якщо вам потрібен цей контекст.

Чому Istio (навіть для невеликих кластерів)

Вам не потрібна масштабна архітектура мікросервісів, щоб отримати користь від Istio. Навіть у невеликому кластері mesh дає вам три речі, які важко отримати будь-яким іншим способом:

Sidecar чи Ambient: чому було обрано Ambient

Існує два способи запуску Istio. Традиційна модель робить інʼєкцію невеликого проксі (який називається sidecar) у кожен pod. Кожен сервіс отримує власний проксі, який обробляє шифрування та застосування політик для цього сервісу.

Ми обрали новіший підхід: Istio Ambient Mode. Замість проксі для кожного podʼа, Ambient запускає один спільний компонент під назвою ztunnel на кожному вузлі. Він виконує ту саму роботу (шифрування трафіку, забезпечення ідентичності), але працює строго на транспортному рівні (Layer 4, L4), на рівні вузла, а не всередині кожного окремого podʼа.

ФункціяРежим SidecarРежим Ambient
РозгортанняОдин проксі всередині кожного podʼаОдин спільний компонент на вузол
Операційне навантаженняВисоке (рестарти, додаткова памʼять на pod)Низьке (прозоро для podʼа)
Шифрування (mTLS)Виконується власним проксі кожного podʼаВиконується ztunnel на вузлі
Розширені HTTP-функції (L7)Завжди доступніПотребує додаткового компонента (Waypoint Proxy)
ПродуктивністьСередняМенше накладних витрат для базової безпеки

Чого ви позбавляєтеся в режимі Ambient

Режим Ambient ще не є повноцінною заміною sidecar. Варто знати про обмеження, перш ніж ви вирішите його використовувати:

Ментальна модель, перш ніж читати далі

З інструментами визначено, ось як варто мислити про те, що ми насправді будуємо, перш ніж переходити до кроків.

Уявіть свій кластер як офісну будівлю, де всі двері стандартно відкриті. Будь-хто, хто потрапляє всередину, може пройти в будь-яку кімнату. Те, що ми робимо тут, це:

  1. Закриймо всі двері — стандартно жодна служба не може отримувати трафік, якщо ми явно не дозволимо це.
  2. Заміна ключ-карт на бейджі співробітників — замість “цей IP-адрес дозволений”, стає “ця конкретна служба, підтверджена сертифікатом, дозволена”. Зловмисник не може підробити сертифікат, просто підробивши IP.
  3. Контроль того, що залишає будівлю — нічого в кластері не може спілкуватися з зовнішнім інтернетом, якщо це не проходить через єдину контрольовану точку виходу.
  4. Додамо фізичний засув зверху — другий рівень мережевих правил на рівні операційної системи, щоб навіть якщо щось обійшло Istio повністю, воно все одно не могло вийти.

Кожен розділ нижче охоплює один із цих чотирьох кроків, по порядку.

Шлях до зміцнення безпеки

Ми не впроваджували це за один раз. Кожен рівень усував прогалину, яку залишив попередній. Принцип залишався незмінним: спочатку все блокувати, а потім відкривати лише те, що можна обґрунтувати.

Рівень 1: глобальна заборона

Перший крок — заблокувати весь вхідний трафік до кожної служби в mesh. Ми зробили це за допомогою однієї політики Istio, застосованої на верхньому рівні:


# Приклад 1: Глобальна політика заборони вхідного трафіку

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all-ingress
  namespace: istio-system
spec:
{}

Порожній spec без правил означає, що нічого не дозволено. Далі ми додаємо явні правила для кожного зʼєднання, яке має бути дозволене.

Рівень 2: ідентичність SPIFFE як периметр

Як тільки все стандартно заблоковано, нам потрібен спосіб відкрити конкретні зʼєднання. Замість використання IP-адрес (які можуть змінюватися при перезапуску podʼів) ми використовуємо ідентичність сервісів.

Кожен сервіс в mesh отримує SPIFFE ID, стандартний спосіб іменування ідентичностей робочих навантажень. SPIFFE розшифровується як Secure Production Identity Framework for Everyone. Це виглядає так:

spiffe://cluster.local/ns/production/sa/frontend-sa

Ця ідентичність вбудована в TLS-сертифікат, який використовує сервіс. Оскільки Istio контролює ці сертифікати, сервіс не може претендувати на іншу ідентичність, просто змінивши мітку або конфігураційний файл.

Дозвіл сервісу frontend викликати backend виглядає так:


# Приклад 2: Дозвіл frontend викликати backend на основі ідентичності SPIFFE

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend-api
  action: ALLOW
  rules:
    - from:
        - source:
            principals: ["cluster.local/ns/production/sa/frontend-sa"]

Рівень 3: блокування egress та перехоплення DNS

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

Ми вирішили цю проблему, маршрутизуючи весь вихідний трафік через спеціальну точку виходу (Egress Gateway) для кожного namespace і блокуючи все інше на рівні мережі.

Як працює перехоплення DNS

Коли сервіс намагається підключитися до зовнішньої адреси, наприклад api.external.com, відбувається наступне:

  1. ztunnel перехоплює DNS-запит до того, як він буде надісланий.
  2. Якщо ми оголосили api.external.com як дозволений зовнішній сервіс (через ServiceEntry), ztunnel повертає заповнювач IP-адреси. Сервіс підключається до нього, а ztunnel маршрутизує реальне підключення через Egress Gateway для перевірки.
  3. Якщо ми не оголосили цю адресу, ztunnel пропускає DNS-запит, але фактичне підключення блокується мережевими правилами на рівні ядра (розглянуто на наступному рівні).

Потік вихідного трафіку з перехопленням DNS

Рис. 1: Потік вихідного трафіку з перехопленням DNS

Для реєстрації дозволеного зовнішнього сервісу та маршрутизації його через шлюз:


# Приклад 3: Реєстрація зовнішнього сервісу та привʼязка до Egress Gateway

apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata:
  name: external-api
  namespace: production
  labels:
    istio.io/use-waypoint: production-egress-gateway # Explicitly binds SE to our gateway
spec:
  hosts:
    - api.external.com
  ports:
    - number: 443
      name: https
      protocol: HTTPS
  location: MESH_EXTERNAL
  resolution: DNS

Мітка istio.io/use-waypoint повідомляє ztunnel, що цей вихідний трафік слід маршрутизувати через наш Egress Waypoint, який є стандартним Waypoint Proxy, що діє як egress-шлюз, замість того щоб дозволяти йому виходити безпосередньо в інтернет.

Layer 4: контроль на рівні ядра

Istio потужний, але ми хотіли мати страховку під ним. Якщо щось обійде mesh повністю, мережа сама повинна це перехопити.

Kubernetes має власні мережеві правила (NetworkPolicies), які працюють на нижчому рівні, ніж Istio, і застосовуються ядром Linux на кожному вузлі. Ми встановили два правила для кожного namespace:

  1. Блокувати весь вихідний трафік, крім DNS-запитів та внутрішнього порту для комунікації Istio (15008). Звичайні сервіси не можуть виходити в інтернет.
  2. Дозволити Egress Gateway виходити в інтернет. Це єдиний компонент, який може це робити.

# Приклад 4: Обмеження вихідного трафіку подів лише mesh та DNS

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress-except-mesh
  namespace: production
spec:
  podSelector: {} # Applies to all pods in the namespace
  policyTypes:
    - Egress
  egress:
    - to: # Allow DNS
        - namespaceSelector: {} # any namespace
      ports:
        - protocol: UDP
          port: 53
    - to: # Allow traffic to istio-system (for control plane/discovery)
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: istio-system
      ports: # Allow HBONE tunnel to Egress Gateway/Waypoint
        - protocol: TCP
          port: 15008
---

# Приклад 5: Дозвіл Egress Gateway виходити в інтернет

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-gateway-to-internet
  namespace: production
spec:
  podSelector:
    matchLabels:
      gateway.networking.k8s.io/gateway-name: production-egress-gateway
  policyTypes: ["Egress"]
  egress:
    - {} # Unrestricted egress for the gateway itself

Що ми дізналися

  1. Потрібно зосередитися на бізнес-проблемі, а не на технології: Ми впровадили Istio не тому, що це цікава технологія, а тому, що інфраструктура не могла забезпечити нам необхідну ізоляцію без місяців узгоджень. Це важливо, коли ви пояснюєте своє рішення команді з безпеки.
  2. Ambient mode вартий уваги, але йдіть з відкритими очима: Він знімає багато операційного навантаження, але вам знадобиться Waypoint Proxy для всього, що виходить за межі базового шифрування трафіку, а віртуальні машини поки що не підтримуються.
  3. Istio та мережеві правила Kubernetes — це не одне й те саме: Istio захищає трафік на основі ідентичності робочого навантаження на транспортному та прикладному рівнях. Мережеві правила Kubernetes (NetworkPolicies) працюють на мережевому рівні. Потрібні обидва. Кожен ловить те, що інший не може.

Жорстке зміцнення мережі на пласкій інфраструктурі рідко буває чистим процесом. Все починається з хаотичної реальності, коли сервіси вільно спілкуються один з одним, і включає багато ретельного тестування зі стандартними правилами “deny” перед тим, як ви зможете довіряти тому, що побудували. Але, перейшовши від “довіряй цьому IP” до “довіряй цій перевіреній ідентичності”, ми перетворили високоризикове on-premises середовище на те, що ми могли реально захистити, не подаючи жодного інфраструктурного запиту.

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

Share this post