AWS: VPC Flow Logs, NAT Gateways, та Kubernetes Pods – детальний обзор

Автор |  01/05/2024
 

Маємо відносно великі витрати на AWS NAT Gateway Processed Bytes, і стало цікаво що ж саме процеситься через нього.

Здавалося б, все просто – включи собі VPC Flow Logs, да подивись, що до чого. Але як діло стосується AWS Elasitc Kubernetes Service та NAT Gateways, то все трохи цікавіше.

Отже, про що будемо говорити:

  • що таке NAT Gateway у AWS VPC
  • що таке NAT та Source NAT
  • включимо VPC Flow Logs, і розберемося з тим, що саме в них пишеться
  • і розберемося з тим, як знайти Kubernetes Pod IP у VPC Flow Logs

Схема нетворкінгу досить стандартна:

  • AWS EKS кластер
  • VPC
    • публічні сабнети для Load Balancers та NAT Gateways
    • приватні для Kubernetes Worker Nodes
    • окремі сабнети для баз даних
    • окремі сабнети для Kubernetes Control Plain

Створення VPC для кластеру описано у Terraform: створення EKS, частина 1 – VPC, Subnets та Endpoints.

AWS NAT Gateway Pricing

Документація – Amazon VPC pricing.

Отже, коли ми використовуємо NAT Gateway, то платимо за:

  1. за кожну годину роботи NAT Gateway
  2. за гігабайти, які він оброблює

Година роботи NAT Gateway коштує $0.045, тобто в місяць це буде:

0.045*24*30
32.400

32 долари.

Є варіант з використання NAT Instance замість NAT Gateway, але тоді мусимо мати справу з його менеджментом – і створення інстансу, і його апдейти, і конфігурація.

Амазон предоставляє AMI для цього – але вони давно не оновлюються, і не будуть.

Крім того, Terraform-модуль terraform-aws-modules/vpc/aws працює тільки з NAT Gateway, тому, якщо ви хочете використати NAT Instance – то маєте ще й автоматизацію писати під нього.

Отже – скіпаємо варіант з NAT Instance, і використовуємо NAT Gateway – як рішення, яке повністю підтримується і менеджиться Амазоном та VPC-модулем для Terraform.

Щодо вартості трафіку: платимо ті ж самі $0.045, але вже за кожен гігабайт. При чому рахується весь processed трафік – тобто і outbound (egress, TX – Transmitted), і inbound (ingress, RX – Recieved).

Отже, коли ви відправляєте один гігабайт даних в S3-бакет, а потім завантажуєте його назад на EC2 в приватній мережі – ви платите 0.045 + 0.045 долари.

Що таке NAT?

Давайте згадаємо, що таке NAT взагалі, і як він працює на рівні пакетів і архітектури мережі.

NAT – Network Address Translation – виконує операції над заголовками TCP/IP пакетів, міняючи (translate) адресу відправника або отримувача, дозволяючи мережевий доступ з або до машин, які не мають власного публічного IP.

Знаємо, що є декілька типів NAT:

  • Source NAT: пакет “виходить” з приватної мережі, і NAT перед відправкою в Internet заміняє source IP пакету на власний (SNAT)
  • Destination NAT: пакет “входить” в приватну мережу з Inernet, і NAT перед відправкою всередину мережі заміняє destination IP пакету з власного на приватну IP всередині мережі (DNAT)

Окрім того, є Static NAT, Port Address Translation (PAT), Twice NAT, Multicast NAT.

Нас зараз цікавить саме Source NAT, і далі ми будемо в основному розглядати саме його і те, як пакет потрапляє з VPC до інтернету.

Якщо відобразити це схемою, то вона буде виглядати так:

  1. Ініціація запиту з EC2: сервіс на EC2 з Private IP 10.0.1.5 генерує запит до External Server з IP 203.0.113.5
    1. ядро операційної системи EC2 створює пакет
      • source IP: 10.0.1.5
      • packet source IP: 10.0.1.5
      • destintation IP: 203.0.113.5
      • packet destination IP: 203.0.113.5
  2. Маршрутизація пакета: мережевий інтерфейс на EC2 включений в Private Subnet, і має Route Table, яка підключена до цього сабнету
    1. ядро операційної системи визначає, що destintation IP не належить до VPC, і переадресує пакет до NAT GW Private IP 10.0.0.220
      • source IP: 10.0.1.5
      • packet source IP: 10.0.1.5
      • destination IP: 10.0.0.220
      • packet destination IP: 203.0.113.5
  3. Обробка пакета NAT Gateway: пакет приходить на мережевий інтерфейс NAT GW, який має адресу 10.0.0.220
    1. NAT Gateway зберігає запис про походження пакету з IP 10.0.1.5:10099 => 203.0.11.443 у своїй NAT-таблиці
    2. NAT GW змінює source IP з 10.0.1.5 на адресу свого інтерфейсу у публічній мережі з IP 77.70.07.200 (власне, сама операція SNAT), і пакет відправляється в Інтернет
      • source IP: 77.70.07.200
      • packet source IP: 10.0.1.5
      • destination IP: 203.0.113.5
      • packet destination IP: 203.0.113.5

Що таке NAT Table?

NAT-таблиця зберігається в пам’яті NAT Gateway та використовується, аби прийняти пакет від External Server до нашої EC2, коли він буде слати відповідь, і переадресувати його до відповідного серверу в приватній мережі.

Схематично його можна відобразити так:

Отримуючи відповідь від 203.0.113.5 до себе на 77.70.07.200 і порт 20588, NAT Gateway по таблиці знаходить відповідного адресата – IP 10.0.1.5 і порт 10099.

Добре. Тепер, як згадали що таке NAT – давайте включимо VPC Flow Logs, і розберемося з записами, які він створює.

Див. The Network Address Translation Table.

Налаштування AWS VPC Flow Logs

Див. також AWS: VPC Flow Logs – знайомство та аналітика з CloudWatch Logs Insights.

VPC Flow Logs можна налаштувати вручну в панелі AWS:

Або, якщо використовуєте Terraform модуль terraform-aws-modules/vpc, то задати параметри в ньому:

...
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.5.2"

  name = local.env_name
  cidr = var.vpc_params.vpc_cidr

  ...

  enable_flow_log = var.vpc_params.enable_flow_log

  create_flow_log_cloudwatch_log_group = true
  create_flow_log_cloudwatch_iam_role  = true

  flow_log_max_aggregation_interval         = 60
  flow_log_cloudwatch_log_group_name_prefix = "/aws/${local.env_name}-flow-logs/"
  flow_log_log_format = "$${region} $${vpc-id} $${az-id} $${subnet-id} $${instance-id} $${interface-id} $${flow-direction} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${pkt-srcaddr} $${pkt-dstaddr} $${pkt-src-aws-service} $${pkt-dst-aws-service} $${traffic-path} $${packets} $${bytes} $${action}"
  #flow_log_cloudwatch_log_group_class       = "INFREQUENT_ACCESS"

}
...

Виконуємо terraform apply, і маємо логи у VPC з власним форматом:

VPC Flow Logs – формат

У flow_log_log_format описується формат того, як лог буде записаний, а саме – які поля в ньому будуть.

Я завжди використовую custom format з додатковою інформацією, бо дефолтний формат може бути недостатньо інформативним, особливо про роботі через NAT Gateways.

Всі поля є у документації Logging IP traffic using VPC Flow Logs.

Для Terraform, екрануємо записи з ${...} через додатковий $.

Вартість VPC Flow Logs в CloudWatch Logs

flow_log_cloudwatch_log_group_class дозволяє задати клас Standard або Infrequent Access, і Infrequent Access буде дешевшим, але він має обмеження – див. Log classes.

В моєму випадку, я планую збирати логи до Grafana Loki через CloudWatch Log Subscription Filter – тому потрібен Standard. Але подивимось – може налаштую через S3 бакет, і тоді, мабуть, можна буде використати Infrequent Access.

Бо насправді витрати на логування трафіку досить помітні.

Наприклад, у невеликій VPC, де в Kubernetes крутиться наш Backend API, моніторинг (див. VictoriaMetrics: створення Kubernetes monitoring stack з власним Helm-чартом) та кілька інших сервісів, після включення VPC Flow Logs вартість CloudWatch почала виглядати так:

Тож майте це на увазі.

VPC Flow Logs в CloudWatch Logs vs AWS S3

Зберігання логів в CloudWatch Logs буде дорожчим – але дає можливість виконувати запити у CloudWatch Logs Insights.

Крім того, як на мене, то налаштування збору логів до Grafana Loki простіше через CloudWatch Subscription Filters, аніж робити через S3 – просто менше головної болі з IAM.

Про Loki та S3 – див. Grafana Loki: збираємо логи AWS LoadBalancer з S3 за допомогою Promtail Lambda.

Про Loki та CloudWatch – див. Loki: збір логів з CloudWatch Logs з використанням Lambda Promtail.

Втім, поки що тримаю Flow Logs в CloudWatch Logs, а як закінчу розбиратись з тим, звідки йде трафік – то подумаю про використання S3, і звідти вже буду збирати до Grafana Loki.

VPC Flow Logs та Log Insights

Окей – отже, маємо налаштовані VPC Flow Logs в CloudWatch Logs.

Що нас особливо цікавить – це трафік через NAT Gateway.

Використовуючи кастомний формат логів – в Logs Insights можемо зробити такий запит:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| filter (dstaddr like "10.0.5.175") | stats sum(bytes) as bytesTransferred by interface_id, flow_direction, srcaddr, srcport, dstaddr, dstport, pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, bytes
| sort bytesTransferred desc
| limit 10

Тут ми робимо фільтр по запитам, які у dstaddr мають Private IP нашого NAT Gateway:

Іноді pkt_src_aws_service або pkt_dst_aws_service не вказані, і тоді не дуже зрозуміло що за трафік.

Можна перевірити на сайті https://ipinfo.io – там може бути вказане ім’я хоста, і тоді ясно, що це, наприклад, S3-ендпоінт:

Flow Logs ingress vs egress

Ми знаємо, що це ingress – це вхідний трафік (RX, Received), а egress – вихідний трафік (TX, Transmitted).

Але вхідний та вихідний до чого? VPC, Subnet або ENI – Elastic Network Interface?

Читаємо документацію Logging IP traffic using VPC Flow Logs:

  • flow-direction: The direction of the flow with respect to the interface where traffic is captured. The possible values are: ingress | egress.

Тобто, відносно до мережевого інтерфейсу: якщо на інтерфейс EC2 або NAT Gateway (який під капотом є звичайним EC2) приходить трафік – то це ingress, якщо виходить з інтерфейсу – то egress.

Різниця srcaddr vs pkt-srcaddr та dstaddr vs pkt-dstaddr

У нас є чотири поля, які вказують на адресатів.

При цьому для source та destination у нас є два різних типи полів – з pkt-, або без.

В чому різниця:

  • srcaddr – “поточна” маршрутизація:
    • адреса вхідного трафіку – звідки прийшов пакет, або:
    • адреса інтерфейсу, який відправляє трафік
  • dstaddr – “поточна” маршрутизація:
    • адреса “пункту призначення” пакета у вихідному трафіку, або
    • адреса мережевого інтерфейсу для вхідного трафіку
  • pkt-srcaddr: “оригінальна” адреса появи пакету
  • pkt-dstaddr: “оригінальна” адреса “пункту призначення” пакету

Аби краще зрозуміти ці поля і взагалі структуру записів у Flow Logs – давайте розглянемо кілька прикладів з документації.

Flow Logs та приклади записів

Отже, маємо EC2 інстанс в приватній мережі, який робить запити до якогось зовнішнього сервісу через NAT Gateway.

Що ми побачимо в логах?

Приклади взяті з документації Traffic through a NAT gateway, і додав трохи схем, аби візуально було простіше зрозуміти.

Дивитись будемо на реальні дані:

  • маємо EC2 інстанс в приватному сабнеті:
    • Elastic Network Interface: eni-0467f85cabee7c295
    • Private IP: 10.0.36.132
  • маємо NAT Gateway:
    • Elastic Network Interface: eni-0352f8c82da6aa229
    • Private IP: 10.0.5.175
    • Public IP: 52.54.3.183

На EC2 запущено curl в циклі з запитом на 1.1.1.1:

root@ip-10-0-36-132:/home/ubuntu# watch -n 1 curl https://1.1.1.1

Формат VPC Flow Log той самий, що був вище, а для перевірки в CloudWatch Logs Insights будемо використовувати такий запит:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| filter (interface_id = "eni-0352f8c82da6aa229" AND srcaddr = "10.0.36.132") | stats sum(bytes) as bytesTransferred by instance_id, interface_id, flow_direction, srcaddr, dstaddr, pkt_srcaddr, pkt_dstaddr
| sort bytesTransferred desc

Тут робимо виборку по записам з мережевого інтерфейсу NAT Gateway та Private IP нашого EC2:

Отже, в результатах у нас буде “instance_id, interface_id, flow_direction, srcaddr, dstaddr, pkt_srcaddr, pkt_dstaddr

NAT Gateway Elastic Network Interface records

Спочатку глянемо записи, які стосуються мережевого інтерфейсу NAT Gateway.

Від EC2 через NAT GW до Remote server

Перший приклад запису в Flow Logs відображає інформацію з мережевого інтерфейсу NAT Gateway, де записано проходження пакету від EC2 в приватній мережі до зовнішнього серверу:

При роботі з VPC Flow Logs головне пам’ятати, що записи робляться для кожного інтерфейсу.

Тобто, якщо ми робимо curl 1.1.1.1 з EC2-інстансу – то отримаємо два записи у Flow Log:

  1. з Elastic Network Interface на самому EC2
  2. з Elastic Network Interface на NAT Gateway

В цьому прикладі ми бачимо запис з інтерфейсу NAT Gateway, бо:

  • поле instace-id пусте (NAT GW хоч і є EC2, але це все ж Amazon-managed сервіс)
  • flow-directioningress, пакет прийшов на інтерфейс NAT Gateway
  • в полі dstaddr бачимо Private IP нашого NAT GW
  • і поле pkt-dstaddr не співпадає з dstaddr – в pkt-dstaddr у нас адреса “кінцевого отримувача”, а пакет прийшов на dstaddr – NAT Gateway

Від NAT Gateway до Remote Server

В другому прикладі бачимо запис про пакет, який було відправлено з NAT Gateway до Remote Server:

  • flow-directionegress, пакет відправлено з інтерфейсу NAT Gateway
  • srcaddr та pkt-srcaddr однакові
  • dstaddr та pkt-dstaddr однакові

Від Remote Server до NAT Gateway

Далі – наш Remote Server відправляє відповідь до нашого NAT Gateway:

  • flow-directioningress, пакет прийшов на інтерфейс NAT Gateway
  • srcaddr та pkt-srcaddr однакові
  • dstaddr та pkt-dstaddr однакові

Від Remote Server через NAT Gateway до EC2

Запис про пакет від Remote Server до нашого EC2 через NAT Gateway:

  • flow-directionegress, пакет відправлено з інтерфейсу NAT Gateway
  • srcaddr та pkt-srcaddr різні – в srcaddr маємо NAT GW IP, а в pkt-srcaddr – Remote Server
  • dstaddr та pkt-dstaddr однакові, з IP нашого EC2

EC2 Network Interface records

І пара прикладів записів у Flow Logs, які відносяться до EC2 Elastic Network Interface.

Від EC2 до Remote Server

Відправка пакета з EC2 до Remote Server:

  • instance_id не пустий
  • flow-directionegress, бо запис с інтерфейсу EC2, який відправляє пакет до Remote Server
  • srcaddr та pkt-srcaddr однакові, з Private IP цього EC2
  • поля dstaddr та pkt-dstaddr – теж однакові, з адресою Remote Server

Від Remote Server до EC2

Відправка пакета з Remote Server до EC2:

  • instance_id не пустий
  • flow-directioningress, бо запис с інтерфейсу EC2, який отримує пакет від Remote Server
  • srcaddr та pkt-srcaddr однакові, з адресою Remote Server
  • поля dstaddr та pkt-dstaddr – теж однакові, з Private IP цього EC2

VPC Flow Logs, NAT, Elastic Kubernetes Service та Kubernetes Pods

Окей – ми побачили, як знайти інформацію по трафіку через NAT Gateway з EC2-інстансів.

А як щодо Kubernetes Pods?

Тут ситуація ще цікавіша, бо маємо різні типи мережевої комунікації:

  • Worker Node to Pod
  • Worker Node to ClusterIP
  • Pod to ClusterIP Service
  • Pod to Pod на одній Worker Node
  • Pod to Pod на різних Worker Node
  • Pod to External Server

Поди мають IP адреси з пулу VPC CIDR, і ці IP підключаються до WorkerNode як Secondary Private IP (або беруться з підключених префіксів /28 у випадку з VPC CNI Prefix Assignment Mode – див. AWS: VPC Prefix та максимальна кількість подів на Kubernetes WorkerNodes).

При комунікації Pod to Pod, якщо вони в одній VPC, то використовуються їхні IP/WorkerNode Secondary Private IP. Але якщо вони знаходяться на одній WorkerNode – то пакет піде через віртуальні мережеві інтерфейси, а не через “фізичний” інтерфейс на WorkerNode/EC2, і, відповідно, ми цей трафік у Flow Logs не побачимо взагалі.

А от коли Pod відправляє трафік до зовнішнього ресурсу – то по дефолту плагін VPC CNI транслює (міняє) Pod IP на WorkerNode Primary Private IP, і, відповідно, у Flow Logs ми не побачимо IP поду, який шле трафік через NAT Gateway.

Тобто, у нас на рівні ядра операційної системи WorkerNode/EC2 виконується один SNAT, а потім на NAT Gateway – ще один.

Виключення – якщо под запускається з hostNetwork: true.

Документація – SNAT for Pods.

Давайте перевіримо.

Трафік з Pod до Pod, та VPC Flow Logs

Запустимо два поди. Додамо їм antiAffinity та topologyKey (див. Kubernetes: Pods та WorkerNodes – контроль розміщення подів на нодах), аби вони запустились на двох різних WorkerNodes:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-pod1
  labels:
    app: ubuntu-app
    pod: one
spec:
  containers:
  - name: ubuntu-container1
    image: ubuntu
    command: ["sleep"]
    args: ["infinity"]
    ports:
    - containerPort: 80
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: ubuntu-app
        topologyKey: "kubernetes.io/hostname"
---
apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-pod2
  labels:
    app: ubuntu-app
    pod: two
spec:
  containers:
  - name: ubuntu-container2
    image: ubuntu
    command: ["sleep"]
    args: ["infinity"]
    ports:
    - containerPort: 80
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: ubuntu-app
        topologyKey: "kubernetes.io/hostname"

Деплоїмо, і на першому встановлюємо curl, а на другому – NGINX.

Тепер маємо:

  • ubuntu-pod1:
    • Pod IP: 10.0.46.182
    • WorkerNode IP: 10.0.42.244
  • ubuntu-pod2:
    • Pod IP: 10.0.46.127
    • WorkerNode IP: 10.0.39.75

На другому стартуємо NGINX, і з першого поду запускаємо curl в циклі на IP другого поду:

root@ubuntu-pod1:/# watch -n 1 curl 10.0.46.127

І за хвилину перевіряємо Flow Logs с запитом:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| filter (dstaddr = "10.0.46.127" AND dstport = 80) | stats sum(bytes) as bytesTransferred by instance_id, interface_id, flow_direction, srcaddr, dstaddr, dstport, pkt_srcaddr, pkt_dstaddr
| sort bytesTransferred desc

В srcaddr у нас Primary Private IP з WorkerNode, на якій запущено ubuntu-pod-1, а в pkt_srcaddr – IP самого Pod, який робить запити.

Трафік з Pod до External Server через NAT Gateway, та VPC Flow Logs

Тепер, нічого не міняючи, запустимо з того ж ubuntu-pod1 curl на 1.1.1.1, і подивимось логи:

В першому записі бачимо:

  • eni-0352f8c82da6aa229 – інтерфейс NAT Gateway
  • flow-directioningress, інтерфейс отримав пакет
  • srcaddr 10.0.42.244 – адреса WorkerNode, де запущений ubuntu-pod1
  • dstaddr 10.0.5.175 – пакет для NAT Gateway
  • pkt_dstaddr 1.1.1.1 – і пакет призначається для Remote Server

Далі, у другому записі:

  • той же мережевий інтерфейс, NAT GW
  • але вже egress – пакет вийшов з інтерфейсу
  • srcaddr 10.0.5.175 – пакет з NAT GW

І третій запис:

  • інстанс i-023f37c7aad6fc69d – там, де наш Pod
  • трафік egress – пакет вийшов з інтерфейсу
  • srcaddr 10.0.42.244 – пакет з Private IP цієї WorkerNode
  • і dstaddr 1.1.1.1 – пакет для Remote Server

Але ми ніде не бачимо IP самого Kubernetes Pod.

Kubernetes Pod, hostNetwork: true та VPC Flow Logs

Давайте передеплоїмо ubuntu-pod1 з hostNetwork: true:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-pod1
  labels:
    app: ubuntu-app
    pod: one
spec:
  hostNetwork: true
  containers:
  - name: ubuntu-container1
    image: ubuntu
    command: ["sleep"]
    args: ["infinity"]
    ports:
    - containerPort: 80
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: ubuntu-app
        topologyKey: "kubernetes.io/hostname"

Деплоїмо, і перевіряємо IP самого Pod та IP його WorkerNode:

$ kubectl describe pod ubuntu-pod1
Name:             ubuntu-pod1
...
Node:             ip-10-0-44-207.ec2.internal/10.0.44.207
...
Status:           Running
IP:               10.0.44.207
...

Обидва IP однакові, відповідно, якщо зробимо з цього поду curl 1.1.1.1 – то у Flow Logs будемо бачити IP пода (а фактично – IP тієї Worker Node, на якій запущено цей Pod).

Але використання hostNetwork: true ідея погана (безпека, можливі проблеми з TCP-портами тощо), тому можемо зробити інакше.

AWS EKS та Source NAT for Pods

Якщо ми відключимо SNAT for Pods у VPC CNI нашого кластеру, то SNAT буде виконуватись тільки на NAT Gateway у VPC, а не двічі – спочатку на WorkerNode, а потім на NAT Gateway.

Див. AWS_VPC_K8S_CNI_EXTERNALSNAT та AWS_VPC_K8S_CNI_EXCLUDE_SNAT_CIDRS.

І, відповідно, в логах ми будемо бачити реальні IP наших подів.

Оновлюємо конфігурацію VPC CNI:

$ kubectl set env daemonset -n kube-system aws-node AWS_VPC_K8S_CNI_EXTERNALSNAT=true

Повертаємо конфіг для ubuntu-pod-1 без hostNetwork: true, передеплоїмо, і глянемо логи з таким запитом:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| filter (srcaddr = "10.0.37.171" OR pkt_srcaddr = "10.0.37.171") | stats sum(bytes) as bytesTransferred by instance_id, interface_id, flow_direction, srcaddr, dstaddr, pkt_srcaddr, pkt_dstaddr
| sort bytesTransferred desc

Маємо два записи:

Перший запис – з інтерфейсу NAT Gateway, який отримав пакет від Pod з IP 10.0.37.171 для Remote Server 1.1.1.1:

Другий запис – з інтерфейсу EC2, який робить запит до Remote Server, тільки тепер у нас pkt_srcaddr не такий же, як srcadd (як було на схемі “З EC2 до Remote Server” вище), а має запис про IP нашого Kubernetes Pod:

І ось тепер ми зможемо відслідкувати який саме Kubernetes Pod шле або отримує трафік через NAT Gateway з таблиць DynamoDB або S3-корзин.

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

Корисні посилання

(ох, цей кайф, коли закриваєш купу вкладок в браузері…)