Istio: причина и решения ошибки «SQLSTATE Connection refused»

Автор: | 04/22/2021
 

Во время старта подов возникает ошибка «SQLSTATE[HY000] [2002] Connection refused’«, при чём в двух разных приложения — на РНР и на NodeJS.

В РHР/Yii она возникает во время выполения pre-install hook в деплое Helm и выполнении MySQL Migration Job:

Yii Migration Tool (based on Yii v2.0.38)Exception ‘yii\db\Exception’ with message ‘SQLSTATE[HY000] [2002] Connection refused’in /app/vendor/yiisoft/yii2/db/Connection.php:642Error Info:
Array
(
[0] => HY000
[1] => 2002
[2] => Connection refused
)Caused by: Exception ‘PDOException’ with message ‘SQLSTATE[HY000] [2002] Connection refused»

Содержание

Причина

Причина банальна: когда мы подключаем Istio, он добавляет запуск своего sidecar-контейнера в под с приложением. При этом возможны случаи, когда контейнер istio-proxy не будет готов к работе в то время как контейнер с приложением уже запущен и начинает выполнять запросы.

См. Delaying application start until sidecar is ready, App container unable to connect to network before sidecar is fully running и Pod fails to start: Application container unable to access network before sidecar ready.

Решения

В целом, Istio ожидает изменений от самого Kubenetes:

The full solution to this in Kubernetes is for k8s to support Sidecar containers as a first class concept, starting them up entirely before starting up the application container.

См. вот этот комментарий.

Но это решение пока не включено даже в 1.19, а наш AWS Elastic Kubernetes Service вообще работает на 1.18.

Тем временем, Istio 1.7 добавил своё решение:

Added config option values.global.proxy.holdApplicationUntilProxyStarts, which causes the sidecar injector to inject the sidecar at the start of the pod’s container list and configures it to block the start of all other containers until the proxy is ready.

Можно добавить глобально на уровне всего меша:

apiVersion: v1
data:
  mesh: |-
    defaultConfig:
      discoveryAddress: istiod.istio-system.svc:15012
      proxy:
        holdApplicationUntilProxyStarts: true
...

Или на уровне определённого пода через аннотации:

annotations:
  proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'

Кроме того, есть утилиты типа envoy-preflight — выполняет проверку istio-proxy, и только потом позволяет запустить остальные окнтейнеры в поде.

В нашем случае всё оказалось проще: istio-proxy не стартовал из-за ошибки NodeLocal DNS и ошибка «lookup istiod.istio-system.svc on lookup: no such host».

Соответственно, когда запускалось приложение и пыталось подключиться к внешнему хосту — получали Connection reset, т.к. Envoy не мог спроксировать трафик.