Усунення проблем з мультикластерами
Ця сторінка описує, як усувати проблеми з Istio, розгорнутим на кількох кластерах та/або мережах. Перед тим як читати це, слід виконати кроки, зазначені у Встановлення мультикластера та ознайомитися з Моделями розгортання.
Балансування навантаження між кластерами
Найпоширеніша, але також широкомасштабна проблема з багатомережевими установками — це непрацююче балансування навантаження між кластерами. Зазвичай це проявляється в тому, що ви бачите відповіді тільки від кластерної локального екземпляра сервісу:
$ for i in $(seq 10); do kubectl --context=$CTX_CLUSTER1 -n sample exec curl-dd98b5f48-djwdw -c curl -- curl -s helloworld:5000/hello; done
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
Hello version: v1, instance: helloworld-v1-578dd69f69-j69pf
...
При дотриманні інструкцій для перевірки установки мультикластера ми очікували б відповіді від обох версій v1
і v2
, що свідчить про те, що трафік йде до обох кластерів.
Є безліч можливих причин цієї проблеми:
Проблеми з підключенням і брандмауерами
У деяких середовищах може бути неочевидно, що брандмауер блокує трафік між вашими кластерами. Можливо, що ICMP
(ping) трафік може успішно проходити, але HTTP та інші види трафіку — ні. Це може проявлятися як тайм-аут або, в деяких випадках, як більш заплутана помилка, така як:
upstream connect error or disconnect/reset before headers. reset reason: local reset, transport failure reason: TLS error: 268435612:SSL routines:OPENSSL_internal:HTTP_REQUEST
Хоча Istio надає можливості виявлення сервісів для спрощення цього процесу, міжкластерний трафік все одно повинен бути успішним якщо podʼи в кожному кластері знаходяться в одній мережі без Istio. Щоб виключити проблеми з TLS/mTLS, ви можете провести ручне тестування трафіку, використовуючи pod без sidecarʼів Istio.
У кожному кластері створіть новий простір імен для цього тесту. Не вмикайте інʼєкції sidecar:
$ kubectl create --context="${CTX_CLUSTER1}" namespace uninjected-sample
$ kubectl create --context="${CTX_CLUSTER2}" namespace uninjected-sample
Далі розгорніть ті ж самі застосунки, що і в перевірці установки мультикластера:
$ kubectl apply --context="${CTX_CLUSTER1}" \
-f samples/helloworld/helloworld.yaml \
-l service=helloworld -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
-f samples/helloworld/helloworld.yaml \
-l service=helloworld -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER1}" \
-f samples/helloworld/helloworld.yaml \
-l version=v1 -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
-f samples/helloworld/helloworld.yaml \
-l version=v2 -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER1}" \
-f samples/curl/curl.yaml -n uninjected-sample
$ kubectl apply --context="${CTX_CLUSTER2}" \
-f samples/curl/curl.yaml -n uninjected-sample
Перевірте, що є pod helloworld, що працює в cluster2
, використовуючи прапорець -o wide
, щоб отримати IP Pod:
$ kubectl --context="${CTX_CLUSTER2}" -n uninjected-sample get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl-557747455f-jdsd8 1/1 Running 0 41s 10.100.0.2 node-2 <none> <none>
helloworld-v2-54df5f84b-z28p5 1/1 Running 0 43s 10.100.0.1 node-1 <none> <none>
Занотуйте стовпець IP
для helloworld
. У цьому випадку це 10.100.0.1
:
$ REMOTE_POD_IP=10.100.0.1
Далі спробуйте надіслати трафік від podʼа curl
в cluster1
безпосередньо на цей IP Pod:
$ kubectl exec --context="${CTX_CLUSTER1}" -n uninjected-sample -c curl \
"$(kubectl get pod --context="${CTX_CLUSTER1}" -n uninjected-sample -l \
app=curl -o jsonpath='{.items[0].metadata.name}')" \
-- curl -sS $REMOTE_POD_IP:5000/hello
Hello version: v2, instance: helloworld-v2-54df5f84b-z28p5
Якщо успішно, мають бути відповіді тільки від helloworld-v2
. Повторіть ці кроки, але надішліть трафік з cluster2
до cluster1
.
Якщо це успішно, можна виключити проблеми з підключенням. Якщо ні, причина проблеми може лежати поза вашою конфігурацією Istio.
Балансування навантаження по локації
Балансування навантаження по локації може використовуватися для того, щоб клієнти віддавали перевагу трафіку до найближчого призначення. Якщо кластери перебувають в різних локаціях (регіон/зона), балансування навантаження по локації віддасть перевагу локальному кластеру, і це працює як очікується. Якщо балансування навантаження по локації вимкнене або кластери знаходяться в одній локації, може бути інша проблема.
Конфігурація довіри
Трафік між кластерами, як і трафік всередині кластера, залежить від спільного кореня довіри між проксі. Стандартно Istio використовує свої власні індивідуально згенеровані сертифікати кореня. Для мультикластерних установок ми повинні вручну налаштувати спільний корінь довіри. Слідкуйте за підрозділом “Додавання сертифікатів” нижче або читайте Моделі ідентичності та довіри, щоб дізнатися більше.
Додавання сертифікатів:
Щоб перевірити, чи сертифікати налаштовані правильно, ви можете порівняти кореневий сертифікат у кожному кластері:
$ diff \
<(kubectl --context="${CTX_CLUSTER1}" -n istio-system get secret cacerts -ojsonpath='{.data.root-cert\.pem}') \
<(kubectl --context="${CTX_CLUSTER2}" -n istio-system get secret cacerts -ojsonpath='{.data.root-cert\.pem}')
Якщо кореневі сертифікати не збігаються або секрет взагалі не існує, слід слідувати інструкціям з Додавання сертифікатів CA, забезпечуючи виконання кроків для кожного кластера.
Покрокова діагностика
Якщо ви пройшли через вищезазначені розділи та все ще стикаєтеся з проблемами, то час заглибитися трохи глибше.
Наступні кроки передбачають, що ви дотримуєтеся перевірки HelloWorld. Перед тим як продовжити, переконайтеся, що як helloworld
, так і curl
розгорнуті в кожному кластері.
З кожного кластера знайдіть точки доступу сервісу curl
для helloworld
:
$ istioctl --context $CTX_CLUSTER1 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld
Інформація для усунення неполадок відрізняється залежно від того, який кластер є джерелом трафіку:
$ istioctl --context $CTX_CLUSTER1 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld
10.0.0.11:5000 HEALTHY OK outbound|5000||helloworld.sample.svc.cluster.local
Показана тільки одна точка доступу, що вказує на те, що панель управління не може читати точки доступу з віддаленого кластера. Перевірте, чи правильно налаштовані віддалені секрети.
$ kubectl get secrets --context=$CTX_CLUSTER1 -n istio-system -l "istio/multiCluster=true"
- Якщо секрет відсутній, створіть його.
- Якщо секрет присутній:
- Перегляньте конфігурацію в секреті. Переконайтеся, що імʼя кластера використовується як ключ даних для віддаленого
kubeconfig
. - Якщо секрет виглядає правильно, перевірте журнали
istiod
на наявність проблем з підключенням або дозволами для досягнення віддаленого Kubernetes API сервера. Журнали можуть містити повідомленняFailed to add remote cluster from secret
разом з причиною помилки.
- Перегляньте конфігурацію в секреті. Переконайтеся, що імʼя кластера використовується як ключ даних для віддаленого
$ istioctl --context $CTX_CLUSTER2 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld
10.0.1.11:5000 HEALTHY OK outbound|5000||helloworld.sample.svc.cluster.local
Показана тільки одна точка доступу, що вказує на те, що панель управління не може читати точки доступу з віддаленого кластера. Перевірте, чи правильно налаштовані віддалені секрети.
$ kubectl get secrets --context=$CTX_CLUSTER1 -n istio-system -l "istio/multiCluster=true"
- Якщо секрет відсутній, створіть його.
- Якщо секрет присутній і точка доступу є Podʼом в основному кластері:
- Перегляньте конфігурацію в секреті. Переконайтеся, що імʼя кластера використовується як ключ даних для віддаленого
kubeconfig
. - Якщо секрет виглядає правильно, перевірте журнали
istiod
на наявність проблем з підключенням або дозволами для досягнення віддаленого Kubernetes API сервера. Журнали можуть містити повідомленняFailed to add remote cluster from secret
разом з причиною помилки.
- Перегляньте конфігурацію в секреті. Переконайтеся, що імʼя кластера використовується як ключ даних для віддаленого
- Якщо секрет присутній і точка доступу є Podʼом у віддаленому кластері:
- Проксі читає конфігурацію з istiod всередині віддаленого кластера. Коли віддалений кластер має in-cluster istiod, це призначено лише для інʼєкції sidecarʼів та CA. Ви можете перевірити, чи це проблема, шукаючи службу з назвою
istiod-remote
в просторі іменistio-system
. Якщо її немає, перевстановіть, переконавшись, щоvalues.global.remotePilotAddress
налаштований.
- Проксі читає конфігурацію з istiod всередині віддаленого кластера. Коли віддалений кластер має in-cluster istiod, це призначено лише для інʼєкції sidecarʼів та CA. Ви можете перевірити, чи це проблема, шукаючи службу з назвою
Кроки для Основного та Віддаленого кластерів все ще застосовуються для багатомережевих установок, хоча багатомережеве середовище має додатковий випадок:
$ istioctl --context $CTX_CLUSTER1 proxy-config endpoint curl-dd98b5f48-djwdw.sample | grep helloworld
10.0.5.11:5000 HEALTHY OK outbound|5000||helloworld.sample.svc.cluster.local
10.0.6.13:5000 HEALTHY OK outbound|5000||helloworld.sample.svc.cluster.local
У багатомережевих установках ми очікуємо, що одна з IP-адрес точок доступу відповідатиме публічній IP-адресі шлюза для віддаленої мережі. Наявність кількох IP-адрес Pod вказує на одну з двох речей:
- Адресу шлюза для віддаленої мережі не можна визначити.
- Мережа або клієнтського, або серверного podʼа не може бути визначена.
Адресу шлюза для віддаленої мережі не можна визначити:
У віддаленому кластері, якого не можна досягти, перевірте, чи служба має зовнішню IP-адресу:
$ kubectl -n istio-system get service -l "istio=eastwestgateway"
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-eastwestgateway LoadBalancer 10.8.17.119 <PENDING> 15021:31781/TCP,15443:30498/TCP,15012:30879/TCP,15017:30336/TCP 76m
Якщо EXTERNAL-IP
застряг у <PENDING>
, середовище може не підтримувати служби LoadBalancer
. У цьому випадку може бути необхідно налаштувати розділ spec.externalIPs
сервісу вручну, щоб надати шлюзу IP-адресу, доступну ззовні кластеру.
Якщо зовнішня IP-адреса присутня, перевірте, чи сервіс включає мітку topology.istio.io/network
з правильним значенням. Якщо це невірно, перевстановіть шлюз і переконайтеся, що ви встановили прапорець –network на скрипті генерації.
Мережа або клієнтського, або серверного podʼа не може бути визначена:
На podʼі-джерелі перевірте метадані проксі.
$ kubectl get pod $CURL_POD_NAME \
-o jsonpath="{.spec.containers[*].env[?(@.name=='ISTIO_META_NETWORK')].value}"
$ kubectl get pod $HELLOWORLD_POD_NAME \
-o jsonpath="{.metadata.labels.topology\.istio\.io/network}"
Якщо будь-яке з цих значень не встановлене або має неправильне значення, istiod може вважати джерело і клієнтські проксі в одній мережі та надсилати мережеві локальні точки доступу. Коли ці значення не встановлені, перевірте, чи values.global.network
був правильно встановлений під час установки, або чи налаштовано webhook для інʼєкції правильно.
Istio визначає мережу podʼа за допомогою мітки topology.istio.io/network
, яка встановлюється під час інʼєкції. Для podʼів без інʼєкції Istio покладається на мітку topology.istio.io/network
, встановлену на системному просторі імен у кластері.
У кожному кластері перевірте мережу:
$ kubectl --context="${CTX_CLUSTER1}" get ns istio-system -ojsonpath='{.metadata.labels.topology\.istio\.io/network}'
Якщо наведена команда не виводить очікуване імʼя мережі, встановіть мітку:
$ kubectl --context="${CTX_CLUSTER1}" label namespace istio-system topology.istio.io/network=network1