Ще одна історія, яка добре демонструє те, як взагалі відбувається взаємодія між ІТ-фахівцем та замовниками.
Отже, мені на ФОП-рахунок в Укрсіб банку прийшли гроші – перша зарплата на новому проекті, після чого я отримав такого собі “листа щастя”:
Що трапилося?
на ФОП-рахунок прийшли гроші
банк гадки не має – хто та чому мені їх відправив, але він має звітувати перед Податковою службою в разі, якщо у тої до мене виникнуть питання (“Звідки гроші, Галя?!“)
Тож банк звертається до мене, як власника банківского рахунку, щоб я надав документи, які підтвержують, що я отримав ці гроші як сплату за мої послуги, і що я сплачу за них податок.
Для цього банк потребує відправити їм лист-роз’яснення – на підставі чого ці гроші прийшли.
Для того, щоб врешті-решт таки отримати свої гроші – потрібно два документи:
договір з проектом – він буде підставою для оформленя Інвойсу
інвойс за серпень – він буде підставою для зарахування вам грошей
Договір про надання послуг / Service Agreement
Мій договір з проектом виглядає якось так:
Найменування ВЕД
В Договорі варто звернути увагу на пункт 1.2:
1.2. Виконавець є суб’єктом підприємницької
діяльності-фізичною особою з видом діяльності: консультування з питань інформатизації.
Бо саме він має відповідати вашому Виду економічної діяльності (Найменування ВЕД), який вказано для вашого ФОП.
Крім того, в Договорі мають бути вказани ваші реквізити, по яких (за якими?) компанія буде нараховувати вам гроші, та має право це робити виключно згідно цього пункту:
І – важливо – назва компаніі, з рахунку якої прийшли гроші – вочевидь, вона має співпадати з назвою компаніі в Договорі.
Рахунок – оферта / Invoice
Другим – потрібно знайти інвойс, за яким вам нарахували гроші – його вам має вислати компанія-замовник. Мій виглядає ось так:
Знов-таки – увага на Опис – саме там вказана послуга, за яку ви отримали гроші – і вона знов-таки має співпадати з вашим ВЕД.
Відповідь банку та отримання грошей
І тепер, коли знайшли всі документи – клікаємо на Відповісти на запит:
Прикріпляємо два документи – Договір та Інвойс:
У полі “Додаткова інформація” – вказуємо:
“У відповідь на “ІТ- Експорт – документи до надходження NNNN.73 USD 31.08.2022″ повідомляємо, що кошти надійшли як оплата згідно договору №NNNN від 22.08.2022. Документи надаємо разом з відповіддю.”
Тобто роз’яснюємо банку – на підставі чого ви отримали гроші.
Monobank та зміна реквізитів
В Монобанку все це наче якось простіше відбувається, принаймні після першої зарплати на рахунок Моно мені ніхто не писав, все обробилося автоматично:
І зверніть увагу на SWIFT Code – MT103 – виявляється, там ціла система, див. MT103.
Доречі, коли я змінював рахунок ФОП з Укрсібу на Моно, то до основного Договіру з Проектом треба було підписати додаток, в якому зазначалися нові реквізити – саме на підставі його Проект може далі робити переводи.
Продовжимо серію постів про Apache Druid. В першій частині розібралися з самім Друідом – його архітектурою та моніторингом, в другій частині – розгорнули кластер PostgreSQL та налаштували його моніторинг.
Повертаємося до druid-operator/examples/tiny-cluster.yaml, та оновлюємо конфіг – відключаємо ZooKeeper, додаємо новий екстешен druid-kubernetes-extensions і додаткові параметри:
Додаємо RBAC Role та RoleBinding, інакше будемо мати помилки авторізації по типу такої:
ERROR [org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcherbroker] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher – Error while watching node type [BROKER]
org.apache.druid.java.util.common.RE: Expection in watching pods, code[403] and error[{“kind”:”Status”,”apiVersion”:”v1″,”metadata”:{},”status”:”Failure”,”message”:”pods is forbidden: User \”system:serviceaccount:druid:default\” cannot watch resource
\”pods\” in API group \”\” in the namespace \”druid\””,”reason”:”Forbidden”,”details”:{“kind”:”pods”},”code”:403}
$ kubectl -n druid apply -f druid-serviceaccout.yaml
role.rbac.authorization.k8s.io/druid-cluster created
rolebinding.rbac.authorization.k8s.io/druid-cluster created
[/simterm]
І за хвилину перевіряємо логи:
[simterm]
...
2022-09-21T17:01:15,916 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Starting NodeRoleWatcher for [HISTORICAL]...
2022-09-21T17:01:15,916 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Started NodeRoleWatcher for [HISTORICAL].
2022-09-21T17:01:15,916 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Created NodeRoleWatcher for nodeRole [HISTORICAL].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Creating NodeRoleWatcher for nodeRole [PEON].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Starting NodeRoleWatcher for [PEON]...
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Started NodeRoleWatcher for [PEON].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Created NodeRoleWatcher for nodeRole [PEON].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Creating NodeRoleWatcher for nodeRole [INDEXER].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Starting NodeRoleWatcher for [INDEXER]...
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Started NodeRoleWatcher for [INDEXER].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Created NodeRoleWatcher for nodeRole [INDEXER].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Creating NodeRoleWatcher for nodeRole [BROKER].
2022-09-21T17:01:15,917 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Starting NodeRoleWatcher for [BROKER]...
2022-09-21T17:01:15,918 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider$NodeRoleWatcher - Started NodeRoleWatcher for [BROKER].
2022-09-21T17:01:15,918 INFO [main] org.apache.druid.k8s.discovery.K8sDruidNodeDiscoveryProvider - Created NodeRoleWatcher for nodeRole [BROKER].
...
$ kubectl -n postgres-operator get pods
NAME READY STATUS RESTARTS AGE
postgres-operator-649799f4bd-dz5bl 1/1 Running 0 82s
postgres-operator-ui-5cfff55c65-v4bjj 1/1 Running 0 22s
[/simterm]
Вікриваємо собі доступ до Сервісу веб-морди Оператора:
[simterm]
$ kubectl port-forward svc/postgres-operator-ui 8081:80
Forwarding from 127.0.0.1:8081 -> 8081
Forwarding from [::1]:8081 -> 8081
[/simterm]
Перевіряємо:
Тут ми нічого робити не будемо – візьмемо готові приклади конфігу кластера.
Запуск PostgreSQL кластеру
Клонуємо репозіторій:
[simterm]
$ https://github.com/zalando/postgres-operator.git
$ cd postgres-operator/
[/simterm]
В каталозі manifests є декілька прикладів, візьмемо собі manifests/minimal-master-replica-svcmonitor.yaml – він описує неймспейс, кластер-юзерів-бази, два Service та два ServiceMonitors + Sidecars с Prometheus Exporter.
Застосовуємо його:
[simterm]
$ kubectl apply -f manifests/minimal-master-replica-svcmonitor.yaml
namespace/test-pg created
postgresql.acid.zalan.do/acid-minimal-cluster created
service/acid-minimal-cluster-svc-metrics-master created
service/acid-minimal-cluster-svc-metrics-replica created
servicemonitor.monitoring.coreos.com/acid-minimal-cluster-svcm-master created
servicemonitor.monitoring.coreos.com/acid-minimal-cluster-svcm-replica created
[/simterm]
Перевіряєм кластер:
[simterm]
$ kk -n test-pg get postgresql
NAME TEAM VERSION PODS VOLUME CPU-REQUEST MEMORY-REQUEST AGE STATUS
acid-minimal-cluster acid 13 2 1Gi 2m21s Running
[/simterm]
Та його поди:
[simterm]
$ kk -n test-pg get po
NAME READY STATUS RESTARTS AGE
acid-minimal-cluster-0 2/2 Running 0 37s
acid-minimal-cluster-1 1/2 Running 0 24s
[/simterm]
У кожного є своя роль, яка задається в лейблах – spilo-role=master або spilo-role=replica.
І для кожного з них створюється окремий Kubernetes Secret:
[simterm]
$ kk -n test-pg get secret
NAME TYPE DATA AGE
foo-user.acid-minimal-cluster.credentials.postgresql.acid.zalan.do Opaque 2 38m
postgres.acid-minimal-cluster.credentials.postgresql.acid.zalan.do Opaque 2 38m
standby.acid-minimal-cluster.credentials.postgresql.acid.zalan.do Opaque 2 38m
zalando.acid-minimal-cluster.credentials.postgresql.acid.zalan.do Opaque 2 38m
Тобто, Оператор створює StatefulSet, в якому задає змінні POSTGRES_USER та POSTGRES_PASSWORD, які ми використовуємо для сайдкару, щоб задати його власні змінні.
На новому проекті бухгалтерію свого ФОП маю вести сам, отже, “Валєра! Настало твайо врємя!” – нарешті є прекрасний шанс поринути в деталі ведення власного ФОП, бо раніше за мене це робила бухгалтерія компанії.
Ну а раз така тема, а деталей там буде досить – то вирішив ще й нову рубрику на RTFM завести, а так як тема стосується тільки України та її податкової системи, то й мова постів в цій рубриці буде виключно українська.
ФОП та банки
Отже, що маємо наразі: у меня є ФОП 3 групи, 5% податку, подача декларації – раз на квартал, плюс щорічна декларація. Про групи та деклараціх якось напишу окремо, як буду подавати.
Між іншим, в Дії мають бути всі ваши документи в тому числі и по ФОП, де можна глянути деталі, наприклад – групу, бо до цього моменту я її навіть не знав 🙂
Для цього переходимо в Послуги – Податки ФОП, та при потребі – Детальна інформація (там же можна включити більше тесну інтеграцію с деякими банками, але про це теж згодом):
UkrSib Bank vs Monobank
Щодо банків та рахунків – маю відкритий колись давно ФОП-рахунок в UkrSib Bank, до якого є нарікання, наприклад операції з рахунками ФОП тільки в банківські дні та час, або необхідності відправляти на продаж валюту до 13.00, щоб отримати кошти від продажу в той самий день, а не наступний.
Чому Моно? Бо по-перше – миттєві операції по рахунках, по друге, як кажуть – там набагато простіше виконувати всякі операціі по податкам, плюс тісна інтеграція з Дією. Але, нажаль, немає і не буде веб-морди. Будемо звикати. Доречі – є якийсь Бухалтерський кабінет, саме як WebUI, в якому мають бути доступні як раз операціі з податками та звітами.
Що буду робити – відкрию Моно ФОП в гривні, до нього – в USD, і передам IBAN нового долларового рахунку бухгалтерії нового проекту.
Перша компенсація (такий собі замінник слову “зарплатня”) тут буде на старий рахунок ФОП в Укрсибі (де мав радість знайомства с оформленням нових контрактів, хочется окремо записати), а вже всі наступні платежі підуть на новий Моно-рахунок.
Відкриття ФОП в Моно
Тут насправді особо нема й чого писати, бо як й усе в Монобанку – процесс досить тривіальний.
Вид економічної діяльності ФОП
Єдине, на що варто звернути увагу, це опис вашої діяльності – взагалі, Моно має витягти її автоматично, начебто з Дії, але можно описати вручну.
Він має співпадати з вашим Видом економічної діяльності. Якщо не знаєте його – то можно перевірити в Свідоцтві платника єдиного податку, або скористатися такими сервісами як https://opendatabot.ua, або його телегоботом – @OpenDataUABot:
Ну і сам процесс на кшалт “кілька разів кликнути “Окей, згода, погнали далі”. Нажаль, скріни з рос. версії:
Після відкриття рахунку в гривні – з’явиться можливість відкрити другий рахунок, в долларах. Там процесс ще простіший.
І нарешті маємо два рахунки – долларовий, на який приходить “експортна виручка” aka salary:
Та гривнєвий, на який буде переводитися гривня, виручена за продаж тієї самої експортної виручки, і з якого можна буде платити податки та переводити гроші на свої картки:
Далі треба буде потикати “Ліміти обігу ФОП”, ну і можно будет починати платити податки та подавати звіти.
Apache Druid – колонкова база даних, орієнтована на роботу з великими обсягами даних, що поєднує в собі можливості та переваги Time-Series Database, Data Warehouse та пошукової системи.
Загальне завдання – налаштувати моніторинг кластера Druid в Kubernetes, для чого спочатку подивимося, що це взагалі таке і як воно все працює, а потім запустимо Друїд і помацаємо його руками.
Головна фіча Друїда особисто для мене це те, що система розроблялася для використання в хмарах типу AWS та Kubernetes, тому має чудові можливості зі скейлінгу, зберігання даних та відновлення роботи у разі падіння одного з сервісів.
Крім того, Друїд це:
колонковий формат зберігання даних: для обробки завантажується лише необхідна таблиця, що значно збільшує швидкість обробки запитів. Крім того, для швидкого сканування та агрегації даних Друїд оптимізує сховище колонки відповідно до її типу даних.
масштабована розподілена система: кластера Друїда можуть розташовуватися на десятках і сотнях окремих серверів
паралельна обробка даних: Друїд може обробляти кожен запит паралельно на незалежних інстансах
self-healing та self-balancing: у будь-який момент можна додати або видалити нові ноди в кластер, при цьому кластер сам виконує балансування запитів та перемикання між ними без будь-якого даунтайму. Більше того, Друїд дозволяє без даунтайму виконувати і оновлення версій
власне, cloud-native и fault-tolerant архитектура: Друїд від початку спроектований до роботи у розподілених системах. Після отримання нових даних, він відразу ж копіює їх у свій Deep Storage, в ролі якого можуть бути сервіси зберігання даних типу Amazon S3, HDFS або мережна файлова система, і дозволяє відновити дані навіть у тому випадку, якщо всі друїдні сервери впадуть. Якщо впала лише частина серверів Друїда – вбудована реплікація даних дозволить продовжувати виконання запитів (вже сверблять руки повбивати його ноди, і подивитися на реакцію Друїда – але не цього разу)
ідекси для швидкого пошуку: Друїд використовує стислі Bitmap-індекси, дозволяючи виконувати швидкий пошук по кількох колонках
Time-based partitioning: за замовчуванням Друїд розділяє дані у часі, дозволяючи створювати додаткові сегменти з інших полях. В результаті, при виконанні запитів з тимчасовими проміжками будуть використані лише необхідні сегменти даних
Друїд має декілька внутрішніх сервісів, що використовуються для роботи з даними, і ці сервіси можна групувати за трьома типами серверів – Master, Query і Data, див. Pros and cons of colocation.
Master servers – управління додаванням нових даних та доступністю (ingest/indexing) – відповідають за запуск нових завдань щодо додавання нових даних та координацію доступності даних:
Coordinator: відповідає за розміщення сегментів даних на конкретні ноди з Historical процесами
Overlord: відповідають за розміщення завдань з додавання даних на Middle Managers і за координацію передачі створених сегментів у Deep Store
Broker: отримує запити від клієнтів, визначає які з Historical або Middle Manager процесів/нід містять необхідні сегменти, і з вихідного запиту клієнта формує та відправляє підзапит (sub-query) кожному з цих процесів, після чого отримує від них відповіді, формує з них загальну відповідь з даними для клієнта, і надсилає йому.
При цьому Historical відповідають на підзапити, які відносяться до сегментів даних, які вже зберігаються в Deep Store, а Middle Manager – відповідають на запити, які відносяться до нещодавно отриманих даних, які ще знаходяться в пам’яті і не відправлені в Deep Store
Router: опціональний сервіс, який надає загальний API для роботи з Брокерами, Оверлордами та Координаторами, хоча їх можна використовувати і безпосередньо. Крім того, Router надає Druid Console – WebUI для роботи з кластером, побачимо її трохи згодом
Data servers – керують додаванням нових даних у кластер і зберігають дані для клієнтів:
Historical: “головні робочі конячки” (с) Друїда, які обслуговують сховище та запити до “історичних” даних, тобто. тим, які вже знаходяться в Deep Store – завантажують звідти сегменти на локальний диск хоста, на якому працює Historical процес, та формують відповіді за цими даними для клієнтів
Middle Manager: обробляє додавання нових даних у кластер – читають дані із зовнішніх джерел та створюють з них нові сегменти даних, які потім завантажуються у Deep Store
Peons: за додавання даних до кластера може відповідати кілька завдань. Для логування та ізоляції ресурсів Middle Manager створює Peons, які є окремими процесами JVM і відповідають за виконання конкретного завдання від Middle Manager. Запускається завжди на тому ж хості, де запущено процес Middle Manager, який породив Peon-процес
Indexer: альтернатива Middle Manager і Peon – замість створення окремої JVM на кожне завдання від Middle Manager, Indexer виконує їх в окремих потоках своєї JVM.
Розробляється як простіша альтернатива Middle Manager і Peon, поки є експерементальною фічею, але в майбутньому замінить Middle Manager і Peon
Окрім внутрішніх процесів, для роботи Друїд також використовує зовнішні сервіси – Deep storage, Metadata storage та ZooKeeper:
deep storage: використовується для зберігання всіх даних, доданих у систему і є розподіленим сховищем, доступним кожному серверу Друїда. Це можуть бути Amazon S3, HDFS або NFS
metadata storage: використовується для зберігання внутрішніх метаданих, таких як інформація про використання сегментів та поточні завдання. У ролі такого сховища можуть бути класичні СУДБ типу PostgreSQL чи MySQL
ZooKeeper: використовується для service discovery та координації роботи сервісів (у Kubernetes замість нього можна використовувати druid-kubernetes-extensions, спробуємо також, але в інший раз)
Druid data flow
Подивимося, як виконується додавання даних (Data ingest) та відповіді клієнтам (Data query, Query Answering).
Data ingest
Додавання даних можна розділити на два етапи: у першому, інстанси Middle Manager запускають завдання з індексування, ці завдання створюють сегменти даних і відправляють їх у Deep Store, а в другому – Historical інстанси завантажують сегменти даних із Deep store, щоб використовувати їх при формуванні відповіді на запити клієнтів.
Перший етап – отримання даних із зовнішніх джерел, індексування та створення сегментів даних, та їх завантаження в Deep store:
При цьому в процесі створення сегментів даних вони вже доступні для виконання запитів по них.
Другий етап – Coordinator опитує Metadata store у пошуках нових сегментів. Як тільки процес Coordinator-а їх знаходить, він вибирає інстанс Historical, який повинен завантажити сегмент з Deep store, щоб він став доступним для обробки запитів:
Coordinator опитує Metadata Store у пошуках нових сегментів. Як тільки він їх знаходить, Coordinator вибирає інстанс Historical, який має завантажити сегмент із Deep store. Коли сегмент завантажений – Historical готовий використовувати його для обробки запитів
Data query
Клієнти надсилають запити до Broker безпосередньо або через Router.
Коли такий запит отримано, Broker визначає, які процеси обслуговують необхідні сегменти даних.
Якщо дані вимагають сегментів одночасно і з Deep store (якісь старі), і з Middle Manager (які отримуємо прямо зараз зі стриму), то Брокер формує та надсилає окремі підзапити до Historical та Middle Manager, де кожен з них виконає свою частину та поверне дані Брокера. Брокер їх агрегує і відповідає клієнту з фінальним результатом.
Далі, спробуємо цю справу розгорнути і потикати гілочкою, а потім зверху додамо моніторингу.
Запуск Druid в Kubernetes
Запускаємо Minikube, додаємо пам’яті і ЦПУ, щоб спокійно запускати всі поди, тут виділяємо 24 RAM і 8 ядер – там Java, най їсть:
[simterm]
$ minikube start --memory 12000 --cpus 8
😄 minikube v1.26.1 on Arch "rolling"
✨ Automatically selected the virtualbox driver
👍 Starting control plane node minikube in cluster minikube
🔥 Creating virtualbox VM (CPUs=8, Memory=12000MB, Disk=20000MB) ...
🐳 Preparing Kubernetes v1.24.3 on Docker 20.10.17 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
[/simterm]
Перевіряємо:
[simterm]
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
[/simterm]
І ноди:
[simterm]
$ kubectl get node
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 41s v1.24.3
[/simterm]
Переходимо до встановлення Apache Druid operator.
Установка Druid Operator
Створюємо Namespace для оператора:
[simterm]
$ kubectl create namespace druid-operator
namespace/druid-operator created
Для Grafana є готова community дашборда, поки додамо її, а взагалі потім зробимо свою.
Відкриваємо в браузері localhost:8080, логінимся, переходимо в Dashboards > Import:
Вказуємо ID 12155, завантажуємо:
ВибираємоPrometheus як datasource:
Отримуємо таку борду, але поки що без даних:
Запуск Druid Exporter
Клонуємо репозиторій:
[simterm]
$ cd ../
$ git clone https://github.com/opstree/druid-exporter.git
$ cd druid-exporter/
[/simterm]
Перевіряємо Druid Router Service – нам треба його повне ім’я, щоб налаштувати Exporter:
[simterm]
$ kubectl -n druid get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
...
druid-tiny-cluster-routers ClusterIP None <none> 8088/TCP 4m3s
...
[/simterm]
Встановлюємо експортер в неймспейсmonitoring, в параметрі druidURL вказуємо URL сервісу Router нашого Друїд-кластера, дивилися вище, його порт, включаємо створення Kubernetes ServiceMonitor та неймспейс, в якому у нас працює Prometheus (monitoring):
Додаємо лейблу release: kube-prometheus-stack, щоб Prometheus почав з цього ServiceMonitor збирати метрики:
Чекаємо на хвилину-дві, перевіряємо монітори ще раз:
Перевіряємо метрики:
Окей – тепер у нас є Druid Cluster, є Prometheus, який збирає метрики – залишилося налаштувати ці самі метрики.
Apache Druid Monitoring
Налаштування моніторингу Друїда включає Emitters і Monitors: емітери “пушать” метрики з Друїда “назовні”, а монітори визначають те, які саме метрики будуть доступні. При цьому для деяких метрик потрібно включати додаткові розширення.
Усі сервіси мають загальні метрики, наприклад query/time, та свої власні, наприклад для Broker є метрика sqlQuery/time, які можуть бути задані для конкретного сервісу через його runtime.properties.
Druid Metrics Emitters
Щоб включити “емітинг” метрик – редагуємо examples/tiny-cluster.yaml та в common.runtime.properties додаємо:
Зберігаємо, оновлюємо кластер, чекаємо на рестарт подів, і через пару хвилин перевіряємо метрики:
Інша справа!
І дашборда в Графані:
Чудово.
У Running/Failed Tasks у нас все ще No Data, тому що нічого не запускали. Якщо завантажити тестові дані із вже згаданого відео – то з’являться та ці метрики.
налаштувати збір логів (куди? поки не придумали, але швидше за все Promtail && Loki)
ну і власне – зібрати нормальну дашборду для Графани
А вже маючи моніторинг можна буде поганяти якісь тести навантаження і погратися з тюнінгом продуктивності кластера, але це все вже в наступних частинах.
AWS VPC Flow Logs – сервіс Amazon, який дозволяє логувати інформацію про трафік між мережевими інтерфейсами у AWS VPC. Далі, ці логи можуть бути передані у AWS CloudWatch Logs для подальшого аналізу, при цьому логування трафіку ніяк не впливає на швидкість роботи мережі.
Коротко розглянемо основні поняття, доступні опції та налаштуємо Flow Logs для VPC з передачею даних для аналізу у CloduWatch Logs.
Опис VPC Flow Logs
Логи можуть бути включені для цілої VPC, підмережі, або конкретного інтерфейсу. При включенні для всієї VPC – логування буде включено для всіх мережевих інтерфейсів цієї мережі.
Сервіси, для яких можна використовувати Flow Logs:
Elastic Load Balancing
Amazon RDS
Amazon ElastiCache
Amazon Redshift
Amazon WorkSpaces
NAT gateways
Transit gateways
Дані будуть записані у вигляді flow log records, які представляють собою текстовий запис з заданними полями.
Use Cases – приклади використання
Що можна відстежити за допомогою Flow logs?
спрацьовування правил SecuirtyGroup/Network Access List – заблоковані запити будуть відмічені як REJECTED
те, заради чого логі впроваджуємо ми – отримати картину трафіку між VPC та сервісами, щоб зрозуміти хто найбільше трафіку споживає, де і скільки cross-AZ трафіку тощо
моніторинг віддалених логінів у систему – стежити за портами 22 (SSH), 3389 (RDP)
відстеження сканування портів
Flow Log record – поля
Кожен запис у логах містить дані про IP-трафіку, отриманому за aggregation interval і є рядком з полями, розділені пробілами, де кожне поле містить інформацію про передачу даних, наприклад – Source IP, Destination IP і протокол.
Див. таблицю Available fields в документації – все у колонці Version 2 включено у default format. Інші версії доступні у Custom Format.
При створенні Flow Logs, ми можемо використовувати дефолтний формат або створити свій – розглянемо його трохи нижче:
Обмеження VPC Flow Logs
не можна використовувати з інстансами EC2-Classic
не можна створити логі для VPC-пірингів, якщо вони ведуть до VPC в іншому акаунті
після створення лога – не можна змінити його конфігурацію чи формат записів
якщо в інтерфейсу кілька IPv4-адрес, і траїфк відправляється до одного з secondary-адрес, то в полі dstaddr буде відображено primary-адресу; щоб отримати оригінальну адресу – використовуйте поле pkt-dstaddr
якщо трафік відправлений з або на мережевий інтерфейс, поля srcaddr та dstaddr будуть містити його primary private IPv4 адресу; щоб отримати оригінальну адресу – використовуйте поле pkt-dstaddr та pkt-dstaddr
Також, враховуйте, що:
не логуються записи до DNS Amazon, але пишуться, якщо використовується свій DNS
не логгується трафік на та з адреси 169.254.169.254 для отримання метаданих EC2-інстансу
не логується трафік між мережевим інтерфейсом EC2 та інтерфейсом AWS Network Load Balancer
Переходимо в IAM Roles, створюємо нову, вибираємо тип EC2:
Знаходимо створену вище політику, підключаємо:
Задаємо ім’я, зберігаємо:
Переходимо до Role Trust relationshitp (див. AWS: IAM AssumeRole – описание, примеры), редагуємо – змінюємо значення поля Service на vpc-flow-logs.amazonaws.com:
У CloudWatch Logs створюємо новий Log group, назвемо його bttrm-eks-dev-1-21-vpc-fl-custom, не забуваємо про retention, щоб дані не лежали вічно (ну і взагалі не забуваємо, що CloudWatch не самий дешевий сервіс):
Повертаємось до VPC, знаходимо потрібну мережу, створюємо новий Flow Log, назвемо його bttrm-eks-dev-1-21-vpc-fl-custom:
Вибираємо Custom Format та поля, які хочемо записувати. При цьому враховуйте, що порядок полів у логах буде такий, який ви використовуєте під час вибору полів.
Тобто, якщо першим клікнути на “region” – то й у логах він буде йти першим:
Flow Log Custom format та CloudWatch Logs Insights
Але якщо ми тепер ми зайдемо в Logs Insights, і спробуємо будь-який із попередніх запитів – отримаємо зовсім не ті поля, які хотіли:
Тобто, дані бачимо, але як розбити поля по колонках?
Ми навряд чи будемо щільно користуватися CloudWatch Logs, швидше за все в продакшені дані підуть у S3 і потім в ELK (logz.io), тому докладно тут зупинятись не буду, проте принцип роботи подивимося.
CloudWatch Logs за замовчуванням створює кілька мета-полів, які ми можемо використовувати у запитах:
@message: “сирі” дані – все повідомлення в text
@timestamp: час події
@logStream: ім’я стриму
Для Custom format, щоб сформувати поля, використовуємо команду parse, якою передаємо поле @message з усім змістом, а потім парсимо його по полях, які розділені пробілами:
Тут кількість “*” в @message має бути рівним кількості імен полів, які ми задаємо – ${vpc-id} і т.д.
Крім того, імена полів не повинні містити тире. Тобто, оригінальне ім’я поля ${vpc-id} для виведення імені колонки вказуємо як vpc_id (або vpcID – кому який формат більше подобається).
І додамо фільтр на вибірку тільки вхідних запитів – flow_direction == ingress:
...
| filter action="REJECT"
| filter (srcaddr not like "162.142.125.") and (flow_direction like "ingress")
| stats count(action) as redjects by flow_direction, srcaddr, dstaddr, pkt_srcaddr, pkt_dstaddr
| sort redjects desc
Отримуємо топ відкинутих запитів – спрацювало правило SecurityGroup або VPC Network Access List.
І дивимося – що за IP у dstaddr – кому йшов пакет, який був заблокований?
Переходимо в EC2 > Network Interfaces, шукаємо Private IP:
Знаходимо “Elastic IP address owner“:
LoadBalancer.
Якщо адреса не знаходиться в AWS – можливо, це якийсь ендпоінт у Kubernetes – шукаємо наприклад так: