В продовження теми AWS: VPC Flow Logs, NAT Gateways, та Kubernetes Pods – детальний обзор.
Там ми розбирали роботу з VPC Flow Logs в цілому, і дізнались, як ми можемо отримувати інформацію про трафік з/до Kubernetes Pods.
Але при використанні Flow Logs з CloudWatch Logs є одна проблема – це вартість.
Наприклад, коли ми включаємо Flow Logs і вони пишуться до CloudWatch Logs, то навіть у невеликому проекті з невеликим трафіком кости на CloudWatch Logs виглядають так – 23-го жовтня включив, 8 листопада відключив:
Тому замість використання CloudWatch Logs ми можемо зробити інакше: Flow Logs писати до AWS S3 бакета, а звідти забирати з Promtail і писати в Grafana Loki, див. Grafana Loki: збираємо логи AWS LoadBalancer з S3 за допомогою Promtail Lambda. А вже маючи логи в Loki – мати і алерти з VMAlert/Alertmanager, і дашборди в Grafana.
Головна проблема, яку ми зараз хочемо вирішити за допомогою VPC Flow Logs – це визначити, хто шле багато трафіку через NAT Gateway, бо це теж з’їдає наші гроші.
Друга задача – це надалі мати загальну картину і якісь алерти по трафіку.
Отже, що будемо робити:
- створимо AWS S3 для логів
- створимо Lambda-функцію з інстансом Promtail, який буде писати логи з бакета до Grafana Loki
- подивимось що ми маємо в логах цікавого, і що корисного там може бути для нас по трафіку
- створимо Grafana Dashboard
Зміст
Наша інфраструктура
Спочатку трохи подивимось на наш проект.
Маємо:
- VPC з 8 сабнетами – 2 публічних, 2 приватних – для Kubernetes Pods, 2 intra – для Kubernetes Control Plane, і 2 для databases – RDS інстанси (див. Terraform: створення EKS, частина 1 – VPC, Subnets та Endpoints)
- 1 NAT Gateway для трафіку з приватних мереж
- 1 Internet Gateway для трафіку з/до публічних мереж
- AWS Elastic Kubernetes Cluster з Karpenter
- Karpenter створює WorkerNodes в VPC Private Subnets (див. Terraform: створення EKS, частина 3 – установка Karpenter)
- VictoriaMetrics стек для моніторингу і Grafana для дашборд (див. VictoriaMetrics: створення Kubernetes monitoring stack з власним Helm-чартом)
Terraform та VPC Flow Logs до S3
Створення самих корзин та Lambda-функції описано в Terraform: створення модулю для збору логів AWS ALB в Grafana Loki, тому тут детально зупинятись не буду.
Взагалі модуль створювався для збору логів AWS Load Balancers, тому в іменах буде зустрічатись “alb” – потім треба буде його переписати аби імена бакетів та функцій передавати параметром.
Єдиний момент, який треба мати на увазі: VPC Flow Logs пише багато даних, тому варто додати більший таймаут для Lambda, бо частина записів втрачалась через помилку Lambda “Task timed out after 3.05 seconds“.
... module "promtail_lambda" { source = "terraform-aws-modules/lambda/aws" version = "~> 7.8.0" # key: dev # value: ops-1-28-backend-api-dev-alb-logs for_each = aws_s3_bucket.alb_s3_logs # <aws_env>-<eks_version>-<component>-<application>-<app_env>-alb-logs-logger # bucket name: ops-1-28-backend-api-dev-alb-logs # lambda name: ops-1-28-backend-api-dev-alb-logs-loki-logger function_name = "${each.value.id}-loki-logger" description = "Promtail instance to collect logs from ALB Logs in S3" create_package = false # https://github.com/terraform-aws-modules/terraform-aws-lambda/issues/36 publish = true # an error when sending logs from Flow Logs S3: # 'Task timed out after 3.05 seconds' timeout = 60 ...
Отже, ми маємо AWS S3 бакет, маємо Lambda, яка з цього бакету бути отримувати повідомлення про появу нових об’єктів, а потім Promtail з цієї Lambda-функції відправляє логи до інстансу Loki через Internal LoadBalancer:
При передачі логів до Loki Promtail додає кілька нових лейбл – component=vpc-flow-logs
, logtype=alb
, environment=ops
. Далі ми зможемо їх використовувати в метриках та Grafana dashboards.
logtype=alb
то знов-таки модуль писався під логи ALB, і це треба буде змінити
Тепер нам треба налаштувати Flow Logs для нашої VPC.
В модулі terraform-aws-modules/vpc/aws
для цього є кілька параметрів:
... enable_flow_log = var.vpc_params.enable_flow_log # Default: "cloud-watch-logs" flow_log_destination_type = "s3" # disalbe to use S3 create_flow_log_cloudwatch_log_group = false create_flow_log_cloudwatch_iam_role = false # ARN of the a CloudWatch log group or an S3 bucket # disable if use 'create_flow_log_cloudwatch_log_group' and the default 'flow_log_destination_type' value (cloud-watch-logs) flow_log_destination_arn = "arn:aws:s3:::ops-1-30-vpc-flow-logs-devops-ops-alb-logs" # set 60 to use more detailed recoring flow_log_max_aggregation_interval = 600 # when use CloudWatch Logs, set this prefix flow_log_cloudwatch_log_group_name_prefix = "/aws/${local.env_name}-flow-logs/" # set custom log format for more detailed information 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_destination_type
: замість дефолтногоcloud-watch-logs
задаємоs3
create_flow_log_cloudwatch_log_group
таcreate_flow_log_cloudwatch_iam_role
: відключаємо створення ресурсів для CloudWatch Logsflow_log_destination_arn
: задаємо ARN корзини, в яку будуть писатись логиflow_log_log_format
: створюємо власний формат, аби мати більше інформації, в тому числі з IP подів в Kubernetes, див. VPC Flow Log – Custom format
Виконуємо terraform apply
, перевіряємо нашу VPC:
І через 10 хвилин перевіряємо логи в Grafana Loki:
Чудово – логи пішли.
Далі до запиту в Loki додаємо парсер pattern
, аби сформувати поля в записах:
{logtype="alb", component="vpc-flow-logs"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>`
Окей. Тепер, маючи логи і поля, можемо подумати про метрики з Loki Recording Rules, Grafana dashboard та алерти в Alertmanager.
Аналіз запису VPC Flow Logs з NAT Gateway
Спочатку давайте глянемо весь трафік через NAT Gateway – додаємо фільтр по interface_id="eni-0352f8c82da6aa229"
:
{logtype="alb", component="vpc-flow-logs"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229"
Що ми тут бачимо?
Наприклад, в першому записі:
Тут:
- ingress: пакет вийшов до інтерфейсу NAT Gateway
- 52.46.154.111: це
src_addr
– якийсь remote server - 10.0.5.175: це
dst_addr
– приватний IP нашого NAT Gateway - 443: це
src_port
– звідки прийшов пакет - 18779: це
dst_port
– куди прийшов пакет - 52.46.154.111 та 10.0.5.175: це
pkt_src_addr
таpkt_dst_addr
відповідно, значення такі ж, як і в5432src_addr
таdst_addr
– тобто трафік явно “чисто NAT”, як розбирали в Від Remote Server до NAT Gateway - AMAZON: сервіс, від якого пакет отримано (але про це трохи далі)
pkt_dst_aws_service
таtraffic_path
: пусті- 105: кількість пакетів
- 113390: кількість байт
- ACCEPT: пакет пройшов через Security Group/WAF
А в наступному запису бачимо dst_port
5432 – тут трафік явно до PostgreSQL RDS.
NAT Gateway та traffic_path
З цікавих моментів, які можна побачити в логах.
По-перше – це traffic_path
. Іноді в логах, які пов’язані в NAT Gateway можна побачити “8”, тобто “Through an internet gateway” – див. Available fields.
Чому Internet Gateway? Бо трафік приходить з приватної мережі на NAT Gateway, але далі в інтернет він йде вже через Internet Gateway – див. One to Many: Evolving VPC Design.
pkt_src_aws_service
, pkt_dst_aws_service
та визначення сервісу
Щодо адрес не з нашої мережі, тобто якихось зовнішніх сервісів. В полях pkt_src_aws_service
та pkt_dst_aws_service
часто можна побачити запис типу “EC2” або “AMAZON” – але нам це нічого не каже.
Навіть більше – технічна підтримка самого AWS не змогла сказати що ж то за сервіси, на які йдуть пакети.
Але тут є хак: якщо в src_port
/dst_port
ми бачимо порт 443 – то можна просто відкрити IP в браузері, де ми отримаємо помилку SSL, і в помилці буде ім’я сервісу, на який це сертифікат видано.
Наприклад, вище ми бачили, що pkt_src_aws_service
== AMAZON. Якщо відкрити https://52.46.154.111 – то побачимо що саме на цьому IP:
Аналогічно будуть записи типу monitoring.us-east-1.amazonaws.com для AWS CloudWatch або athena.us-east-1.amazonaws.com для AWS Athena.
Створення Grafana dashboard
Тепер давайте пробувати створити Grafana dashboard.
Планування
Отже, головна мета – це мати уяву про трафік, який проходить через AWS NAT Gateway.
Що ми знаємо та маємо?
- знаємо CIDR приватних сабнетів для Kubernetes Pods
- знаємо Elastic Network Interface ID, Public IP та Private IP для NAT Gateway – він у нас один, тому тут все просто
- в логах маємо IP подів Kubernetes та якихось зовнішніх ресурсів
- в логах маємо напрямок трафіку через інтерфейс NAT Gateway – IN/OUT (ingress/egress, або RX/TX – Recieved та Transmitted)
Що ми б хотіли бачити на дашборді?
- загальний об’єм трафіку, який пройшов через NAT Gateway і за який ми заплатити
- загальний об’єм трафіку NAT Gateway за напрямком – ingress/egress
- сервіси в Kubernetes, які генерують найбільший трафік
- AWS сервіси та зовнішні ресурси, які генерують трафік – для цього маємо поля
pkt-src-aws-service
таpkt-dst-aws-service
- дія з пакетами
ACCEPT
таREJECT
– може бути корисним, якщо є AWS Web Application Firewall, або вам цікаві спрацювання VPC Network Access List - Availability Zones для визначення cross-AZ трафіку – але це наразі не в нашому випадку, бо у нас все в одній зоні
traffic-path
– може бути корисним для визначення якого типу трафік йде – всередині VPC, через VPC Endpoint тощо (хоча особисто я не став це використовувати в дашборді)
NAT Gateway total traffic processed
Отримати суму всього трафіку за період часу ми можемо таким запитом:
sum ( sum_over_time( ({logtype="alb", component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | unwrap bytes | __error__="" )[$__range] ) )
Використовуємо [$__range]
, аби взяти проміжок часу, який задано в Grafana dashboard. В sum_over_time
рахуємо всі bytes
за цей час, і “загортаємо” все в sum()
, аби мати просто цифру.
Для панелі “Total traffic processed” можна взяти тип візуалізації Stat, використати Unit з Bytes(IEC), і виглядати це буде так:
Маємо тут 5.8 GB за 15 хвилин.
Зараз маю для перевірки Flow Logs в CloudWatch, де можемо зробити такий запит для порівняння:
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 like "eni-0352f8c82da6aa229") | stats sum(bytes) as bytesTransferred | sort bytesTransferred desc | limit 10
Тут у нас за ті ж 15 хвилин 4835737572 байт, тобто такі ж 4.8 гігабайта.
Окей – загальний трафік маємо.
Давайте додамо відображення Egress та Ingress.
NAT Gateway Egress та Ingress traffic processed – Stat
Тут все аналогічно, тільки додаємо фільтр | flow_direction="egress"
або “ingress” відповідно:
sum ( sum_over_time( ({logtype="alb", component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | flow_direction="egress" | unwrap bytes | __error__="" )[$__range] ) )
Так як панель у нас з типом Stat, де просто відображається цифра – то задля зменшення навантаження на Grafana та Loki в Options є сенс поставити Type == Instant.
Змінні дашборди – $kubernetes_pod_ip
та $remote_svc_ip
По-перше – нам цікавий трафік саме з/до Kubernetes Pods, бо майже всі наші сервіси живуть там.
По-друге – хочеться мати можливість вибрати дані тільки по обраним pkt_src_addr
та pkt_dst_addr
– це може бути або Kubernetes Pod, або якийсь зовнішній сервіс – в залежності від ingress/egress трафіку.
Так як ми оперуємо з “сирими” записами в логах, а не метриками з лейблами – то ми не можемо просто взяти значення з полів, тому я додав дві змінні з типом Textbox, в які можна внести IP вручну:
А далі ми можемо ці змінні додати в усі наші запити з регуляркою pkt_src_addr=~"${kubernetes_pod_ip}"
, аби запит спрацьовував, якщо в змінній не задано жодного значення:
sum ( sum_over_time( ({logtype="alb", component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | flow_direction="egress" | pkt_src_addr=~"${kubernetes_pod_ip}" | pkt_dst_addr=~"${remote_svc_ip}" | unwrap bytes | __error__="" )[$__range] ) )
Loki Recording Rules, поля, High Cardinality issue, та performance
Чому ми оперуємо з “сирими” записами в логах, а не метриками з лейблами?
Можна було б створити Recording Rule для Loki по типу такого:
... - record: aws:nat:egress_bytes:sum:15m expr: | sum ( sum_over_time( ({logtype="alb", component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | flow_direction="egress" | pkt_src_addr=ip("10.0.32.0/20") | unwrap bytes | __error__="" )[15m] ) ) ...
Але якщо з даними типу “total processed bytes” це нормальний варіант, то далі, коли ми будемо створювати панелі з інформацією по IP, у нас буде проблема в тому, як ці IP зберігати в метриках.
Якщо ми будемо значення з pkt_src_addr
та pkt_dst_addr
заносити в лейбли метрики – то це призведе до того, що Loki буде створювати окремий набір блоків даних (chunks) на кожний унікальний набір лейбл.
А так як IP в VPC у нас багато, а зовнішніх IP може бути ще більше – то можемо отримати мільйони блоків даних, що вплине і на вартість зберігання даних в AWS S3, і на перформанс самої Loki та VictoriaMetrics або Prometheus, бо їм доведеться всі ці дані завантажувати про виконанні запитів в Grafana. Див. Loki Recording Rules, Prometheus/VictoriaMetrics та High Cardinality.
Крім того, лейбли в метриках взагалі мають використовуватись для “опису” цієї метрики і можливості вибирати дані, а не для зберігання якихось даних для подальшого використання. Тобто лейбла – це тег, який “описує” метрику, а не поле для передачі параметрів.
Тому тут варіант або змиритись з high cardinality issue і не дотримуватись best practices – або використовувати “сирі логи” в дашбордах.
При роботі з сирими логами в Loki та Grafana ми, звісно, обмежуємо себе, бо на запитах за відносно великий проміжок часу – наприклад, кілька годин – Loki починає жрати ресурси, як дурна, див. колонку CPU – майже 4 ядра зайняті повністю:
Можливо, я все ж спробую створити Recording Rules з IP в лейблах, подивитись як це вплине на систему. Поки у нас невеликий стартап і мало трафіку – це ще може бути варіантом. Але на великих обсягах такого краще не робити.
Іншим рішенням може бути спробувати використати VictoriaLogs (див. VictoriaLogs: знайомство, запуск в Kubernetes, LogsQL та Grafana), яка набагато краще може з цим працювати, і, скоріш за все, на наступному тижні я буду перероблювати цю схему саме з VictoriaLogs, тим більш сама VictoriaLogs вже отримала свій перший реліз, а скоро і її Grafana datasource вже буде офіційно додано до Grafana.
Крім того, до VictoriaLogs вже завели і підтримку Recording Rules, і алерти – див. vmalert.
NAT Gateway та traffic processed – графіки
На додачу до простих Stat панелей може бути корисним створити графіки – аби мати уявлення про те, як якісь зміни впливали на трафік.
Тут запит може бути аналогічним, тільки замість sum_over_time()
використаємо rate()
, в Options використовуємо Type == Range, а в Standart Options > Unit задаємо “bytes/sec”:
sum ( rate( ({logtype="alb", component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_add> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | unwrap bytes | __error__="" )[15m] ) )
Для rate()
беремо період 15 хвилин, бо логи у нас пишуться раз на 10 хвилин – дефолтне значення для flow_log_max_aggregation_interval
в модулі terraform-aws-modules/vpc/aws
.
Сервіси в Kubernetes, які генерують найбільший трафік
Наступним хочеться бачити IP з Kubernetes Pods, які генерують трафік.
Тут можемо створити візуалізацію з типом Pie chart і таким запитом:
topk (5, sum by (pkt_src_addr) ( sum_over_time( ( {component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_addr> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | action="ACCEPT" | pkt_src_addr=ip("10.0.32.0/20") | pkt_src_addr=~"${kubernetes_pod_ip}" | pkt_dst_addr=~"${remote_svc_ip}" | unwrap bytes | __error__="" )[$__range] ) ) )
Використовуємо ip()
з CIDR нашої приватної мережі, аби вибрати записи тільки з IP наших Pods (див. Matching IP addresses), і topk(5)
, аби відобразити тільки ті Pods, які генерують найбільше трафіку.
В результаті маємо таку картину:
В топі у нас IP 10.0.44.66 – глянемо, що за сервіс:
$ kk get pod -A -o wide | grep -w 10.0.44.66 dev-backend-api-ns backend-celery-workers-deployment-b68f88f74-rzq4j ... 10.0.44.66 ...
Є такий Kubernetes Pod, окей. Тепер маємо уяву хто шле багато трафіку.
Grafana Data links
Аби швидко отримати інформацію що за IP, та до якого Kubernetes Pod він належить – можемо додати Grafana Data Links.
Наприклад, в мене є окрема дашборда, де по Pod IP можна отримати всю інформацію про нього.
Тоді можемо створити Data link з полем ${__field.labels.pkt_src_addr}
:
І дашборда по IP “10.0.44.66”:
Всі доступні поля для Data links можна отримати з Ctrl+Space.
Або замість (чи на додачу) Pie chart можемо створити звичайний графік, аби мати “історичну картину”, як ми це робили для NAT Gateway Total traffic:
topk(5, sum by (pkt_src_addr) ( rate( ( {component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_addr> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | action="ACCEPT" | pkt_src_addr=ip("10.0.32.0/20") | pkt_src_addr=~"${kubernetes_pod_ip}" | pkt_dst_addr=~"${remote_svc_ip}" | unwrap bytes | __error__="" )[15m] ) ) )
Remote services, які генерують найбільший трафік
По Kubernetes Pods інформацію отримали – давайте глянемо, звідки до нас приходить найбільше трафіку.
Тут все аналогічно, тільки фільтр робимо по pkt_dst_addr=ip("10.0.32.0/20")
– тобто вибираємо всі записи, де пакет йде ззовні на NAT Gateway і потім до наших Pods:
topk(10, sum by (pkt_src_addr) ( sum_over_time( ( {component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_addr> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | action="ACCEPT" | pkt_dst_addr=ip("10.0.32.0/20") | pkt_src_addr=~"${remote_svc_ip}" | pkt_dst_addr=~"${kubernetes_pod_ip}" | unwrap bytes | __error__="" )[$__range] ) ) )
А в Data Links можемо використати сервіс https://ipinfo.io і поле pkt_src_addr
:
Сервіси в Kubernetes, які генерують найбільший трафік – таблиця з портами
Окремо можна додати табличку, де буде трохи більше інформації по кожному запису з логів.
Чому окремо – бо тут ми робимо запит з великою вибіркою по декільком полям, і через це Loki доведеться тягнути додаткові дані. Тому на запитах за великий проміжок часу нехай краще не прогрузиться одна табличка – але будуть графіки.
В табличку можемо додати відображення портів – буде корисно при визначенні сервісу.
Створюємо візуалізацію з типом Table і таким запитом:
topk(10, sum by (pkt_src_addr, src_port, pkt_dst_addr, dst_port, pkt_dst_aws_service) ( sum_over_time( ( {component="vpc-flow-logs", __aws_s3_vpc_flow="fl-01e52787e4495dfee"} | pattern `<region> <vpc_id> <az_id> <subnet_id> <instance_id> <interface_id> <flow_direction> <src_addr> <dst_addr> <src_port> <dst_port> <pkt_src_addr> <pkt_dst_addr> <pkt_src_aws_service> <pkt_dst_aws_service> <traffic_path> <packets> <bytes> <action>` | interface_id="eni-0352f8c82da6aa229" | action="ACCEPT" | pkt_src_addr=ip("10.0.32.0/20") | pkt_src_addr=~"${kubernetes_pod_ip}" | pkt_dst_addr=~"${remote_svc_ip}" | unwrap bytes | __error__="" )[$__range] ) ) )
В Options задаємо Type == Instant:
Додаємо Transformations:
- Filter fields by name: тут прибираємо Time
- Organize fields by name: міняємо заголовки колонок
Значення для Standard options > Unit та Data Links задаємо через Fields override, бо для кожної колонки у нас будуть власні параметри:
Grafana dashboard: фінальний результат
І все разом в мене поки що вийшло ось так:
Якщо не зважати не проблеми з перформансом Loki при використанні raw logs – то наче непогано. Вже дуже допомогло визначити зайвий трафік, наприклад – багато трафіку йшло від Athena, тому додамо VPC Endpoint для неї, аби не ганяти цей трафік через NAT Gateway.
Далі, мабуть, таки спробую варіант з Recording Rules для Loki, і точно буду пробувати писати логи до VictoriaLogs, і робити графіки та алерти через неї.