Як оптимізувати хмарну інфраструктуру: шлях DevOps-інженера від процесорів x86 до ARM (Graviton) архітектури
Галузь мікропроцесорів зазнає змін, відмовляючись від традиційного панування архітектури х86. ARM (Advanced RISC Machine) архітектура стає головним гравцем індустрії мікропроцесорів, уже завоювавши мобільний сектор, зробивши значний крок вперед завдяки Apple M SoC у ноутбуках, а також закріпивши свою присутність у серверній інфраструктурі Amazon через процесор Graviton3.
Amazon Web Services (AWS) розробила спеціальні процесори, відомі як Graviton, а також Graviton3, що є його сучасною ітерацією. Ці процесори були створені для хмарних ресурсів Amazon EC2 з метою підвищення їхньої продуктивності, енергоефективності та економічності. Розроблені на основі архітектури ARM, Graviton3 характеризується великою кількістю ядер, достатньою кеш-пам’яттю та одночасною підтримкою багатопотоковості. Інтегровані в систему AWS Nitro, процесори Graviton оптимізують загальну продуктивність системи, безпеку та керованість.
Ресурси на основі Graviton є доступними в різних модифікаціях, що задовольнять різноманітні вимоги до робочого навантаження. Завдяки потужній екосистемі та рентабельній ціні процесори Graviton стають прекрасною альтернативу традиційним процесорам x86 для хмарних робочих навантажень.
Планування
Після отримання завдання щодо міграції хмарної архітектури, першим етапом є обговорення задач з відділом розробки та оцінка сумісності коду продукту із запропонованими змінами архітектури. Нашим наступним кроком стало продовження дослідження інфраструктури проєкту для визначення тих елементів, які потребують змін, а також вивчення шляхів їхнього впровадження. Враховуючи те, що наша хмарна інфраструктура розгортається як код за допомогою Terraform, необхідно було вивчити всі нюанси та залежності.
Перш за все слід зосередитися на кластері EKS і групах вузлів, де в коді відбуваються всі розгортання та операції. Щоб уникнути переривання активних процесів розробки, дієвим підходом є створення окремої групи вузлів з архітектурою ARM і застосування до неї Taint.
workers = {
min_capacity = 1
max_capacity = 4
desired_capacity = 3
instance_types = ["m6a.xlarge", "m5a.xlarge"]
capacity_type = "SPOT"
disk_size = 50
k8s_labels = {
"node.kubernetes.io/lifecycle" = "spot"
}
}
graviton-workers = {
min_capacity = 1
max_capacity = 3
desired_capacity = 2
instance_types = ["m6g.large"]
capacity_type = "SPOT"
disk_size = 50
taints = [
{
key = "type"
value = "graviton-workers"
effect = "NO_SCHEDULE"
}
]
k8s_labels = {
"node.kubernetes.io/lifecycle" = "spot"
}
}
Набір типів групи вузлів х86 і ARM
Тут варто наголосити на важливості taints
і olerations
, а також селекторів вузлів (Nodeselectors
) як ключових інструментів для розрізнення модулів між окремими архітектурами в хмарній інфраструктурі, зосередженій навколо кластера Kubernetes.
Це особливо важливо, коли компанії та розробники використовують різноманітні інструменти, і не всі з них підтримують архітектуру ARM. Ми розуміли це, тому наш наступний крок передбачав вибір тегів / версій Docker-образів для сумісності з різними ресурсами та подальше тестування продуктів з відкритим кодом, як-от Jenkins, Prometheus, Grafana, ArgoCD тощо. Останній етап у процесі планування полягав у визначенні можливостей і вимог щодо відповідності AWS CodeBuild, що давало можливість створювати та запускати тести образу Docker на архітектурі ARM.
Тестування
Імплементація технології Graviton і нової серверної архітектури робочих станцій на ранньому етапі викликало певні складнощі. Дослідження коду, особливо процесу створення програм на новій архітектурі, почалося з емуляції за допомогою buildx
(docker buildx build -- platform linux/arm64...
).
Основна проблема полягала в уповільненні швидкості виконання збірки через емуляцію іншої архітектури, що призвело до
Стабільність машини для збирання стала критичною проблемою, оскільки збірки зависали на певних етапах, що призводило до зависання на невизначений термін. Тому необхідно було оперативно ухвалювати рішення щодо вирішення цих проблем.
Зважаючи на проблеми, описані вище, гарною ідеєю стало рішення запустити сервер збірки на примірнику Graviton EC2. Для первинного аналізу та тестування простіше використовувати окремі екземпляри, на яких можна створити код та одразу налаштувати збірку, передаючи зміни, наприклад, у файл Docker
або бібліотеку, які використовує ваша програма, оскільки не всі бібліотеки й пакети стабільно працюють на ARM.
Після створення всіх необхідних образів Docker необхідно з’ясувати, де саме вони повинні розташовуватися та як розгорнути їх у тестовому середовищі. На цьому етапі потрібно підняти групу Graviton вузлів у кластері. У проєкті ми використовували Helm Chart для розгортання мікросервісів у кластері, але для інших типів розгортання основні дії будуть аналогічними. У файлі values.yaml helm
потрібно розмістити nodeselector
і tolerations
. Там, де kubernetes.io/arch:arm64
є стандартною міткою, tolerations
відповідатимуть тегу, який зображено на секції з кодом вище.
Ще один важливий момент полягає в тому, що вам доведеться комбінувати архітектури для використання в різних середовищах, тестах тощо. Для цього потрібно відрізняти назву образу ARM від х86. Найпростіший варіант — це додати -arm-
або будь-яке інше слово до тегу образу, щоб воно відрізнялося від застарілих х86. Для цього ми можемо використовувати функцію regexMatch
у Helmchart.
{{- if .Chart.AppVersion | regexMatch "-arm-" -}}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- else -}}
nodeSelector: {}
{{- end }}
{{- end }}
{{- if .Chart.AppVersion | regexMatch "-arm-" -}}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- else -}}
tolerations: []
{{- end }}
{{- end }}
Логіка розрізнення архітектур у Helm deployment.yaml
За допомогою цієї функції ми можемо контролювати, які tolearations
і nodeselectors
будуть записані під час розгортання. Якщо функція знайде -arm-
у тезі образу, їй буде призначене значення, прописане у Values.yaml
.
nodeSelector:
kubernetes.io/arch: arm64
tolerations:
- key: "type"
value: "graviton-workers"
operator: "Equal"
effect: "NoSchedule"
Приклад значень nodeselector
і tolerations
в Helm values.yaml
У іншому разі буде прописане порожнє значення, що спрямовує розгортання до будь-якого вільного вузла. Така гнучкість дозволяє вам передавати будь-які значення, які ви вважаєте необхідними.
Не варто також забувати про інструменти, які використовуються під час міграції. Окрім допоміжних інструментів, в кожному проєкті будуть використовуватися бази даних.
Під час тестування наші бази даних продемонстрували надійну роботу. Мікросервіси на архітектурі ARM без проблем взаємодіють з базою даних на х86. Їх перенесення на нову архітектуру не є простим завданням, оскільки потрібно обов’язково зберігати всі дані. Проте якщо ви регулярно оновлюєте та використовуєте продукти від офіційних провайдерів, то проблем не буде. Лише перевірте, чи ваша версія образу підтримує архітектуру ARM. Якщо так, то вам слід додати nodeselector
і tolerations
у файлі значень Helm
вашої бази даних і обов’язково зробити бекап перед міграцією. Якщо у вас застаріла або специфічна версія бази даних, яка не підтримує архітектуру ARM, тоді необхідно оновити версію бази даних та переконатися, що всі ваші застосунки працюють належно. Тільки після цього ви зможете переходити на архітектуру ARM.
Міграція
Після успішно проведеного локального тестування ви можете переходити до міграції на нове середовище. На цьому етапі вкрай важливо вибрати момент, коли розпочати міграцію. Якщо це проєкт, який постійно оновлюється (релізиться), зупинка такого процесу може спровокувати втрату значних коштів. Найкращим моментом тут буде етап циклу, коли код із середовища production
переходить у stage
, щоб QA-команда мала час його протестувати, а ви — внести відповідні виправлення. У нашому випадку інтеграція в CI/CD виглядала так: Dev repo > AWS CodeBuild > ECR & Helm repo > ArgoCD > EKS
).
Першим кроком є передача оновлених файлів Docker із залежностями (наприклад, встановлення пакетів тощо) до репозиторіїв розробників, де розташований програмний код. Оскільки AWS CodeBuild використовується для створення образів Docker, вам потрібно внести зміни до buildspec
файлу. Зверніть увагу, що команди для взаємодії з новим образом ARM aws/codebuild/amazonlinux2-aarch64-standard:3.0
відрізнятимуться від стандартного типу образу aws/codebuild/standard:5.0.
.
Крім того, щоб створити ці збірки за допомогою Terraform, вам доведеться оновлювати код. Щоб не повторювати цей код для створення кожної окремої збірки, варто використати Terragrunt, що дозволяє автоматизовано вставляти змінні.
inputs = {
name = local.name
aws_region = "us-east-1"
codebuild_role_policy_arn = dependency.infra.outputs.codebuild_role_policy_arn
codebuild_vpc_id = dependency.infra.outputs.vpc_id
codebuild_subnet_ids = dependency.infra.outputs.vpc_private_subnet_ids
codebuild_security_group_ids = [dependency.infra.outputs.codebuild_security_group_id]
codebuild_source_location_name = local.name
codebuild_environment_type = "ARM_CONTAINER"
codebuild_image_type = "aws/codebuild/amazonlinux2-aarch64-standard:3.0"
}
Приклад змінних в Terragrunt
Після того, як ви успішно створили та налаштували ресурси в AWS CodeBuild, постає питання, як одночасно підтримувати розробку на новій та старій х86 архітектурі, яка все ще використовується в середовищах stage
і production
. Для цього варто зберегти застарілі збірки x86. В AWS CodeBuild можна скористатися зручною функцією — використання файлів buildspec
для різних місць розташування. Ці файли можна брати як з репозиторію, так і з консолі AWS, інтегрувавши їх в конфігурації збірки.
Важливо залучити всі залежності образу для тестування збірки в новий файл buildspec
. Це дозволить ефективно керувати збірками з єдиного репозиторію. Для цього потрібно додати умову if
у специфікацію збірки для ARM. Ця умова буде застосовується лише тоді, коли буде зроблено коміт до гілки розробника. Водночас у застарілому файлі buildspec
, який розташованій на консолі AWS, можна дозволити збірки з комітів, що надходять на stage
і до основної гілки. Разом із розробкою, нова архітектура розширюватиметься на додаткові середовища. Умова if
коригуватиметься, допоки остаточно не буде скасована, коли зникне потреба підтримувати середовище x86.
version: 0.2
env:
shell: bash
phases:
install:
commands:
- export BRANCH_NAME="${CODEBUILD_WEBHOOK_HEAD_REF:11:100}"
- |
if [[ "${BRANCH_NAME}" == hotfix/* || "${BRANCH_NAME}" == "stage"|| "${BRANCH_NAME}" == "main" ]]; then
exit 1
fi
Блокування збірки на ARM в обраних гілках (buildspec.yaml
)
Моніторинг і стабілізація
Моніторинг і стабілізація розгортання середовища Graviton вимагає ретельного підходу, зосередженого на розподілі ресурсів, оптимізації продуктивності та виявленні аномалій. Після процесу розгортання обов’язковим є розв’язання потенційних проблем, зокрема ризику уповільнення роботи модулів через неправильний розподіл ресурсів.
За умов реального навантаження також можуть виникати незначні проблеми, що потребують швидкого усунення. Щоб уміло контролювати продуктивність машин Graviton, рекомендуємо використовувати такі інструменти, як Amazon CloudWatch або Prometheus. Вони дозволяють здійснювати моніторинг у реальному часі, сприяючи швидкому реагуванню на будь-які порушення і відхилення в системі.
Важливим аспектом цього етапу є також точне налаштування параметрів ресурсів вузлів на робочій станції. Така оптимізація є ключовою для встановлення базової лінії, що забезпечуватиме стабільну та ефективну роботу програми. DevOps-інженерам та системним адміністраторам необхідно глибше занурюватися в деталі роботи центрального процесора та розподілу пам’яті і прагнути досягти оптимального балансу, який зменшить ризик уповільнення та ефективно використовуватиме доступні EC2-ресурси.
Amazon CloudWatch — це комплексна служба моніторингу, що дає змогу адміністраторам отримати цілісну картину використання ресурсів і дозволяє завчасно виявляти та усувати проблемні моменти. Використовуючи показники CloudWatch, користувачі можуть налаштувати сигнали сповіщення для випадків, коли попередньо визначені порогові значення перевищено.
Prometheus — ще один популярний набір інструментів для моніторингу та попередження з відкритим кодом, що вирізняється здатністю збирати та зберігати дані, забезпечуючи надійну основу для поглибленого аналізу. Його гнучкість дозволяє створювати спеціальні показники та запити, підвищуючи деталізацію моніторингу. У поєднанні з Grafana, Prometheus дозволяє створювати інтуїтивно зрозумілі інформаційні панелі, що оптимізує інтерпретацію великої кількості інформації про продуктивність системи.
У пошуках оптимальних налаштувань ресурсів адміністраторам варто проводити безперервне тестування продуктивності під змінним навантаженням. Такі інструменти, як Apache JMeter або K6, можуть симулювати різні робочі навантаження, визначаючи потенційні точки конфлікту ресурсів. Цей підхід до ітераційного тестування є важливим для уточнення параметрів розподілу ресурсів і завчасного усунення проблемних місць продуктивності.
Висновок
Перехід з архітектури x86 на ARM у хмарній інфраструктурі — це шлях трансформації, який вимагає ретельного планування, тестування та стратегічного підходу до міграції. Коли ми починаємо використовувати ARM-процесори, зокрема AWS Graviton3, вкрай важливим є застосування таких інструментів, як Terraform, Helm і AWS CodeBuild.
Інтеграція в наявні CI/CD, адаптація файлів buildspec
і одночасне керування ARM і x86 збірками є ключовими компонентами успішної стратегії міграції. Використання функції if
у buildspec
забезпечує співіснування обох архітектур протягом перехідного періоду.
Після міграції основну увагу слід приділити моніторингу та стабілізації. Використання Amazon CloudWatch і Prometheus забезпечить отримання інформацію про використання ресурсів у режимі реального часу та дасть можливість адміністраторам оперативно вирішувати проблемні моменти і підтримувати оптимальну продуктивність. Безперервне тестування продуктивності за змінних навантажень має важливе значення для вдосконалення розподілу ресурсів і усунення потенційних конфліктів.
Загалом, архітектура ARM, особливо з процесорами AWS Graviton, є прекрасною альтернативою традиційним процесорам x86. Міграція, описана в цій статті, демонструє складнощі та нюанси такого переходу і наголошує на важливості стратегічного планування, тестування та ретельного моніторингу. Оскільки хмарні технології постійно розвиваються, адаптивність, продемонстрована DevOps-інженерами в моєму кейсі, стає основою для впровадження нових рішень і оптимізації продуктивності.
8 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів