Подключение к базе данных AWS от GKE

0

У меня проблемы с подключением модуля облачной платформы Google Kubernetes к внешнему MySQL, работающему на AWS.

Вот мой файл развертывания (некоторые важные части заменены на ***):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: watches-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: watches-v1
  template:
    metadata:
      labels:
        app: watches-v1
    spec:
      containers:
      - name: watches-v1
        image: silasberger/watches:1.0
        imagePullPolicy: Always
        ports:
        - containerPort: 3000
        env:
        - name: MYSQL_HOST
          value: "***.eu-west-1.rds.amazonaws.com"
        - name: MYSQL_DB
          value: "***"
        - name: MYSQL_USER
          value: "***"
        - name: MYSQL_PASS
          value: "***"
        - name: API_USER
          value: "***"
        - name: API_PASS
          value: "***"

Это Dockerfile, который я создаю и отправляю в Dockerhub как watches:1.0:

FROM node:8

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

ENV MICROSERVICE="watches"
ENV WATCHES_API_VERSION="1"

CMD [ "npm", "start" ]

Следующие вещи работают:

  • Подключитесь к экземпляру AWS MySQL из bash с помощью команды mysql
  • запуск образа Docker в локальном контейнере, ошибок нет, все как положено

Однако, как только я применяю развертывание в моем кластере Kubernetes, модули не могут подключиться к базе данных AWS. Приложение запускается, я могу получить доступ к странице kubectl logs <pod-name>, но когда я запускаю команду kubectl logs <pod-name>, я всегда получаю эту ошибку:

Unable to connect to the database: { SequelizeConnectionError: connect ETIMEDOUT
    at Utils.Promise.tap.then.catch.err (/usr/src/app/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:149:19)
    at tryCatcher (/usr/src/app/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/usr/src/app/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/usr/src/app/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/usr/src/app/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/usr/src/app/node_modules/bluebird/js/release/promise.js:690:18)
    at _drainQueueStep (/usr/src/app/node_modules/bluebird/js/release/async.js:138:12)
    at _drainQueue (/usr/src/app/node_modules/bluebird/js/release/async.js:131:9)
    at Async._drainQueues (/usr/src/app/node_modules/bluebird/js/release/async.js:147:5)
    at Immediate.Async.drainQueues (/usr/src/app/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:810:20)
    at tryOnImmediate (timers.js:768:5)
    at processImmediate [as _immediateCallback] (timers.js:745:5)
  name: 'SequelizeConnectionError',
  parent: 
   { Error: connect ETIMEDOUT
    at Connection._handleTimeoutError (/usr/src/app/node_modules/mysql2/lib/connection.js:192:13)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5)
     errorno: 'ETIMEDOUT',
     code: 'ETIMEDOUT',
     syscall: 'connect',
     fatal: true },
  original: 
   { Error: connect ETIMEDOUT
    at Connection._handleTimeoutError (/usr/src/app/node_modules/mysql2/lib/connection.js:192:13)
    at ontimeout (timers.js:498:11)
    at tryOnTimeout (timers.js:323:5)
    at Timer.listOnTimeout (timers.js:290:5)
     errorno: 'ETIMEDOUT',
     code: 'ETIMEDOUT',
     syscall: 'connect',
     fatal: true } }

Он выбирает правильный хост, имя БД и учетные данные (как указано в предыдущей части журнала, не показанной здесь), но, очевидно, не может подключиться к нему. Как видите, приложение написано в Node.js и использует Sequelize.

Все исследования, которые я до сих пор проводил, указывали на проблему с брандмауэром, поэтому я установил следующее правило VPC для облачной платформы Google для этого проекта:

$ gcloud compute firewall-rules describe allow-all-outbound
allowed:
- IPProtocol: all
creationTimestamp: '2018-11-14T02:51:20.808-08:00'
description: Allow all inbound connections
destinationRanges:
- 0.0.0.0/0
direction: EGRESS
disabled: false
id: '7178441953737326791'
kind: compute#firewall
name: allow-mysql-outbound
network: https://www.googleapis.com/compute/v1/projects/adept-vine-222109/global/networks/default
priority: 1000
selfLink: https://www.googleapis.com/compute/v1/projects/adept-vine-222109/global/firewalls/allow-mysql-outbound

Поскольку это ничего не изменило, я также попытался снова добавить то же правило с direction INGRESS, но это тоже не сработало (как я и ожидал).

Я совершенно новичок в облачной платформе Google и в Kubernetes, так что, возможно, это просто глупая ошибка, но я действительно не знаю, как заставить ее работать.

  • 1
    А как насчет AWS? Служба RDS разрешает соединения из любого места?
  • 0
    Да, я считаю, что это должно (как уже упоминалось, я новичок в этом). Флажок «Общедоступная доступность» установлен в настройках сети и безопасности экземпляра. Я могу подключиться к нему с помощью терминала, и я не занес в белый список свой IP или что-то еще. С того же компьютера локальные контейнеры Docker также могут получить к нему доступ.
Показать ещё 1 комментарий
Теги:
amazon-web-services
google-cloud-platform
sequelize.js
kubernetes

1 ответ

1

Как оказалось, проблема была на стороне AWS. Спасибо Джейкобу Томлинсону за предложение.

Хотя Public Accessibility был активирован для экземпляра AWS MySQL, он явно не разрешал доступ из всех источников. Я не уверен, почему это работало с моей локальной машины, но все равно.

Я смог решить эту проблему, добавив группу безопасности в AWS, которая разрешает входящий трафик на все порты и со всеми протоколами для источника 0.0.0.0/0. Затем я связал эту группу безопасности с моим экземпляром MySQL (перейдите к экземпляру, нажмите "Изменить", перейдите в "Настройки сети и безопасности", выберите вновь созданную группу, сохраните изменения). Мне все еще нужно настроить это правило с точки зрения безопасности, но, по крайней мере, теперь все работает.

  • 0
    Я действительно рекомендую против этих настроек - вы в значительной степени просите взломать вашу базу данных. Лучше ограничить трафик определенными диапазонами IP-адресов, и если вам нужно подключиться удаленно, я бы использовал туннель SSH.
  • 0
    Согласовано. Хотя это решило вашу проблему, вы могли бы причинить себе много боли здесь. Одним из решений было бы установить VPN-соединение между кластером gcloud EKS и вашим AWS VPC. cloud.google.com/solutions/...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню