Тепер, коли ми майже завершили налаштування всієї інфраструктури та елементів додатку, і наш додаток працює, давайте розглянемо, як спроектувати систему для забезпечення високої доступності. Наш Святий Грааль — це те, щоб не було єдиної точки відмови.
Індіана Джонс з Святим Граалем
Тепер, якщо ми проаналізуємо нашу архітектуру нижче:
ми можемо визначити 4 основні зони відмови:
- Дані
- Мікросервіси
- Інфраструктура додатку та хмарна інфраструктура
- Хмарний регіон
Ми збираємося розглянути кожну з цих зон. Зазначимо, що багато з них ми вже обговорювали раніше. Для тих, що ми вже розглядали докладніше, ми просто надамо інструкції з посиланнями на детальні пояснення, і ви зможете звертатися до них у зручний для вас час.
Обов'язкові умови: 2 регіони
Відмови регіонів — це рідкісні та надзвичайні події. У хмарі Oracle є багато рівнів резервування, вбудованих для забезпечення доступності: від зон доступності та зон відмов до резервованого живлення і мережі, від апаратного забезпечення до програмного та патчів — хмара Oracle пропонує серйозну стійкість. Однак є клієнти, які вимагають, щоб їхні робочі навантаження були стійкими навіть за межами місцевих географічних районів, іноді для виконання регуляторних вимог або через просто фізичний страх перед законами Мерфі.
Це неминуче означає запуск робочих навантажень хоча б у 2 окремих регіонах. Для цілей цієї статті ми будемо використовувати лише 2 регіони: Сідней (c1) і Мельбурн (c2), 2 кластери OKE та 2 екземпляри Oracle Autonomous DB.
Розглянемо кожен з етапів.
Налаштування аварійного відновлення для Oracle Autonomous DB
Oracle Autonomous DB ще не працює в активному-активному режимі між регіонами. Але за кілька кліків або кілька рядків коду Terraform ви можете вибрати пірингові регіони, де запускати інстанс аварійного відновлення для вашої Autonomous DB. Коли ви налаштовуєте базу даних-standby через Autonomous Data Guard, вона автоматично реплікує дані до цільових регіонів.
Перейдіть на сторінку екземпляра Autonomous DB, і в лівому меню ви побачите розділ "Disaster Recovery" (Аварійне відновлення). Клікніть на нього, а потім натисніть "Add Peer Database" (Додати пірингову базу даних). Вам буде запропоновано вибрати Peer Region (Піринговий регіон):
Вибір пірингового регіону для аварійного відновлення Autonomous DB
Залежно від розміру вашої бази даних, цей процес може зайняти від кількох хвилин до кількох годин. Оскільки ми створили нову базу даних для цієї статті, процес створення та синхронізації пірингової бази даних повинен зайняти лише кілька хвилин.
Створення основної інфраструктури для 2 кластерів OKE
Тим часом створіть 2 кластери OKE та пірингуйте їхні VCN. Ви можете використати приклад для мульти-кластерів в Terraform OKE модулі для створення інфраструктури та кластерів. Remote Peering Connections (RPC) вже будуть створені за вас, і все, що вам потрібно зробити, це встановити з'єднання між ними.
Для більш детального пояснення читайте мій попередній пост про це.
Після того, як ви підключите VCN, інфраструктура виглядатиме наступним чином:
Підключені VCN
VCN підключено, і трафік може бути спрямований між ними.
Clustermesh з Cilium
Наступний крок вимагає використання Cilium CNI з OKE.
Якщо ви використовуєте покращені кластери OKE, тепер ви також можете відключити встановлення flannel, додавши наступне в кожну дефініцію модуля:
cluster_addons_to_remove = {
Flannel = {
remove_k8s_resources = true
},
KubeProxy = {
remove_k8s_resources = true
}
}
Метою є можливість запустити розтягнутий кластер Coherence на OKE. Більше про це пізніше.
На цьому етапі ваші кластери мають бути підключені, і ви повинні мати змогу доступатися до подів і сервісів між кластерами:
Підключені кластери OKE з Cilium
Пошук сервісів між кластерами з CoreDNS
Далі, розкрийте сервіс CoreDNS у кожному кластері, використовуючи приватний Network Load Balancer (NLB). Це робиться для того, щоб примусити CoreDNS в кожному кластері виконувати DNS-запити в іншому кластері:
Причина в тому, що ми хочемо, щоб учасники Coherence могли знаходити потенційно існуючих учасників в іншому OKE кластері і створювати єдиний кластер Coherence. Знову ж таки, є детальне пояснення в попередній статті.
З цією налаштуванням ми тепер можемо використовувати CoreDNS для пошуку та виявлення існуючих учасників Coherence в обох OKE кластерах.
Multi-cluster, multi-network, multi-primary Istio
Далі давайте налаштуємо Istio в режимі multi-cluster, multi-network та multi-primary, щоб не було єдиної точки відмови на рівні мікросервісів. Ідея полягає в тому, що якщо запит користувача потрапляє, скажімо, в Сідней, а мікросервіс у Сіднеї зазнає відмови, ми хочемо використовувати можливості керування трафіком Istio (traffic management) та локального балансування навантаження, щоб перенаправити трафік в Мельбурн.
Встановіть Istio в обох кластерах і підключіть їх, щоб сформувати єдину службу mesh:
Служба mesh з multi-cluster, multi-primary, multi-network
Налаштування з'єднання з базою даних для мульти-регіонів
У попередніх статтях, ми використовували Oracle Database Operator для прив'язки кластера OKE до Autonomous Database. Прив'язка бази даних автоматично створює wallet і зберігає його в Kubernetes Secret. Все, що нам залишиться зробити, це переконатися, що наш под змонтував секрет об'єму.
Oracle Net TNS String можна налаштувати для балансування навантаження та відновлення після відмов. Однак наразі є обмеження в тому, як генерується wallet для Autonomous DB. Фактично, коли у Autonomous DB є DR peer (дистанційний партнер по відновленню), wallet вказує тільки на основний екземпляр бази даних, і наразі немає можливості включити опції балансування навантаження та відновлення в згенерований wallet. Поки ми не виправимо це, ми налаштуємо цей крок вручну.
По-перше, завантажте wallet з консолі OCI та витягніть його. Потім відредагуйте файл tnsnames.ora.
За замовчуванням виглядатиме наступним чином:
tasksdb_high = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.ap-sydney-1.oraclecloud.com))(connect_data=(service_name=gaba123456e_tasksdb_high.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))
tasksdb_low = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.ap-sydney-1.oraclecloud.com))(connect_data=(service_name=gaba123456e_tasksdb_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))
tasksdb_medium = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.ap-sydney-1.oraclecloud.com))(connect_data=(service_name=gaba123456e_tasksdb_medium.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))
tasksdb_tp = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.ap-sydney-1.oraclecloud.com))(connect_data=(service_name=gaba123456e_tasksdb_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))
tasksdb_tpurgent = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.ap-sydney-1.oraclecloud.com))(connect_data=(service_name=gaba123456e_tasksdb_tpurgent.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))
Для кожного профілю, який ви хочете використовувати, додайте наступне:
tasksdb_${profile} = (description=
(failover=on)
(retry_count=20)(retry_delay=3)(connect_timeout=120)(transport_connect_timeout=3)
(address_list=(load_balance=on)
(address=(protocol=tcps)(port=1522)(host=adb.${region_primary}.oraclecloud.com)))
(address_list=(load_balance=on)
(address=(protocol=tcps)(port=1522)(host=adb.${region_peer}.oraclecloud.com)))
(connect_data=(service_name=gaba123456e_tasksdb_${profile}.adb.oraclecloud.com))
(security=(ssl_server_dn_match=yes))))
де профіль може бути “high”, “low”, “medium”, “tp” та “tpurgent”, ім’я сервісу — “gaba123456e…” а regionprimary та region_peer відповідають основним та резервним регіонам екземпляра Autonomous DB. Зверніть увагу, що ми додали наступне:
- failover=on
- список екземплярів ADB, включаючи DR peers
3.
load_balance=on
Перед створенням секретів, створіть простір імен (namespace), де ви будете розгортати додаток, і позначте його:
for c in c1 c2; do
kubectx $c
kubectl create ns todo
kubectl label namespace todo istio-injection=enabled
done
Далі створіть секрети вручну, щоб зберігати wallet у обох кластерах:
export OJDBC=$HOME/database/ojdbc.properties
export TNSNAMES=$HOME/database/tnsnames.ora
export SQLNET=$HOME/database/sqlnet.ora
export CWALLET=$HOME/database/cwallet.sso
export EWALLET=$HOME/database/ewallet.p12
export KEYSTORE=$HOME/database/keystore.jks
export TRUSTSTORE=$HOME/database/truststore.jks
for c in c1 c2; do
kubectx $c
kubectl -n todo create secret generic tasksdb-wallet --from-file=ojdbc.properties=$OJDBC --from-file=tnsnames.ora=$TNSNAMES \
--from-file=sqlnet.ora=$SQLNET --from-file=cwallet.sso=$CWALLET --from-file=ewallet.p12=$EWALLET --from-file=keystore.jks=$KEYSTORE \
--from-file=truststore.jks=$TRUSTSTORE
done
Аналогічно, створіть конфігураційний файл Hibernate:
update
jdbc:oracle:thin:@tasksdb_medium?TNS_ADMIN=/wallets/task_db
task_db_user
changeme
oracle.jdbc.OracleDriver
oracle.jdbc.datasource.impl.OracleDataSource
{autoCommit=false}
true
true
120
180
20
30
І збережіть його в Kubernetes Secret:
export HIBERNATE_CFG_XML=$HOME/todo/hibernate.cfg.xml
for c in c1 c2; do
kubectx $c
kubectl -n todo create secret generic hibernate-cfg --from-file=hibernate.cfg.xml=$HIBERNATE_CFG_XML
done
Тепер ми можемо почати розгортати наш додаток.
Розгортання кластера Coherence через кластери
Тепер ми хочемо розгорнути Coherence як єдиний розтягнутий кластер як ми робили раніше:
Coherence підключатиметься до доступної бази даних. У разі помилки запису, ми хочемо, щоб Coherence тримала оборону та намагалася знову підключитись, ініціюючи підключення знову.
У цьому прикладі ми налаштували Coherence в режимі write-behind у конфігурації кешу:
30
Створіть наступне для кластера c1 в Сіднеї, зберігаючи це в todo-dr-c1.yaml:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend
namespace: todo
spec:
host: backend.todo.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
failover:
- from: AP-SYDNEY-1
to: AP-MELBOURNE-1
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 1m
```
А наступне для кластера c2 в Мельбурні, зберігаючи це в todo-dr-c2.yaml:
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: backend
namespace: todo
spec:
host: backend.todo.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
failover:
- from: AP-MELBOURNE-1
to: AP-SYDNEY-1
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 1m
Тепер ви можете застосувати манифести:
for c in c1 c2; do
kubectx $c
kubectl apply -f $HOME/todo/todo-dr-$c.yaml
done
Крос-регіональна висока доступність з OCI Traffic Steering
Цей крок передбачає, що ваш домен керується через OCI DNS.
У консоль OCI перейдіть до Networking > DNS Management > Traffic Management Steering Policies та виконайте наступні дії:
- Створіть політику керування трафіком (Traffic Steering Policy) і виберіть Load Balancer
- У секції Answer(s) додайте 2 записи типу A з IP-адресами вхідних шлюзів як Rdata і рівною вагою
- Додайте нову перевірку здоров'я (Health Check) і виберіть HTTP як протокол
- У секції Attached Domain(s) додайте todo в Subdomain. Виберіть відділ, в якому була створена зона DNS для вашого домену, і потім виберіть зону.
- Тепер ви можете отримати доступ до додатку через todo.domain.tld
Зазначте, що також можна використовувати DNS cname замість записів типу "A".
Наша настройка завершена:
Висока доступність у кількох регіонах на Oracle Cloud
Підсумок
У цій статті ми об'єднали кілька технологій для досягнення високої доступності наших хмарних мікросервісів на OCI:
- Oracle Autonomous Database
- OCI Networking, включаючи DRG та RPC
- OCI Kubernetes Engine як Kubernetes кластер
- Cilium як CNI
- Istio як сервісну мережу (service mesh)
- Oracle Coherence
- Helidon як фреймворк для мікросервісів
- OCI Load Balancers
- OCI DNS
- OCI Traffic Steering
У наступній статті ми будемо симулювати відмови та перевіримо, наскільки стійка наша інфраструктура. Завершуючи, хочу подякувати моїм колегам Шону Леві (Shaun Levy), Тиму Міддлтону і Роману Греко за їхній внесок у цю статтю.
Перекладено з: A cloud native brew with Oracle Database, Helidon, Coherence and Kubernetes — Part 9 Architecting for High Availability