Не удается подключиться из Google Cloud Run к внешней базе данных MySQL (база данных MySQL третьей стороны)

Вопрос или проблема

У меня есть приложение Nuxt 3, развернутое на Firebase Hosting, и из этого приложения мне нужно получить доступ к удаленной базе данных MySQL, которая находится на общем хостинге CPanel. Приложение Nuxt 3 является клиент-серверным и использует встроенный сервер Nitro, предоставляемый Nuxt.

Как вы, наверное, знаете, при использовании сервера Nitro или функций Firebase создается функция в Cloud Run, которая и является фактическим сервером.

Чтобы протестировать соединение приложения с базой данных, я разрешил все хосты: (%.%.%.%) в CPanel → Управление доступом хостов.

Все работает нормально напрямую с localhost или через эмуляторы Firebase, но не при размещении на хостинге Firebase.

Кроме того, HTTP-запросы из конечных точек моего сервера Nuxt для тестирования таких ресурсов, как: https://jsonplaceholder.typicode.com/users, работают.

Похоже, что в GCP есть правило брандмауэра, которое блокирует исходящий доступ для протокола mysql.

Может кто-то это подтвердить?

Я также пытался установить правило разрешить всем в правилах брандмауэра VPC (https://console.cloud.google.com/net-security/firewall-manager/firewall-policies/list), но без успеха.

Вот ошибка, которую я получаю в GCP Logs Explorer:

Error: connect ETIMEDOUT at Object.createConnection
(/workspace/node_modules/mysql2/promise.js:253:31) at Object.handler
(file:///workspace/chunks/routes/api/hello.mjs:18:30) at Object.handler
(file:///workspace/chunks/_/nitro.mjs:2805:24) at Object.handler
(file:///workspace/chunks/_/nitro.mjs:3115:34) at Object.handler
(file:///workspace/chunks/_/nitro.mjs:2876:31) at process.processTicksAndRejections
(node:internal/process/task_queues:95:5) at async toNodeHandle
(file:///workspace/chunks/_/nitro.mjs:3147:7) { code: 'ETIMEDOUT', errno: undefined, sqlState: undefined }

В браузере я получаю следующий ответ:

FetchError: [GET] "/api/hello": 500 

Вот код, который я использую:

// файл hello.ts в папке Nuxt 3 /server/api 
import mysql from "mysql2/promise";
import { User } from "~/server/models/User";

export default defineEventHandler(async (event) => {

    try {
// код, вызывающий ошибку:

        const conn = await mysql.createConnection({
            host: <удаленный хост>,
            user: <имя пользователя>,
            database: <имя БД>,
            password: <пароль БД>,
        });
//

        const [rows] = await conn.query("SELECT id FROM users");
        console.log(">>> пользователи: ", rows);
        return rows as User[];
    } catch (error) {
        console.error(">>> Ошибка:", error);
        return error;
    }

});

Буду признателен за любые идеи о том, как решить эту проблему.

Ответ или решение

Проблема подключения вашего приложения Nuxt 3, развернутого на Firebase Hosting, к удаленной базе данных MySQL на хостинге CPanel, может быть связана с несколькими аспектами конфигурации сети и разрешений. В данном ответе я предложу несколько шагов, которые вы можете предпринять для диагностики и решения данной проблемы.

1. Проверка конфигурации CPanel

Убедитесь, что вы правильно настроили разрешения доступа в CPanel. Важно не только открыть доступ с помощью настройки (%.%.%.%), но и убедиться, что это действительно работает. Проверяйте, правильно ли указаны параметры хоста, пользователя и пароля, предварительно протестировав доступ к БД через другие инструменты или локально.

2. Проверка исходящих соединений в Google Cloud Run

Согласно вашей информации, HTTP-запросы работают корректно, что указывает на правильную работу общего сетевого доступа в Cloud Run. Однако соединение с MySQL требует специфических настроек. Убедитесь в следующем:

  • Google Cloud Run использует роль "Cloud Run Invoker", которая должна иметь разрешения на исходящие соединения.
  • Проверьте, нет ли ограничений на уровне VPC, которые могут блокировать TCP-порты 3306 (стандартный порт для MySQL) для исходящих соединений.

3. Конфигурация VPC и брандмауэр

Ваши действия по созданию правил брандмауэра должны включать следующее:

  • Создайте новое правило брандмауэра для исходящих соединений:

    • Источник: 0.0.0.0/0 или оставьте пустым для всех IP.
    • Цель: Все инстансы в сети VPC.
    • Протоколы: TCP.
    • Порт: 3306.
  • Убедитесь, что это правило имеет более высокий приоритет, чем другие правила, которые могут блокировать соединения.

4. Использование Cloud SQL (по желанию)

Если возможно, рассмотрите вариант переноса базы данных на Google Cloud SQL. Это позволит вам избежать проблем с сетевой конфигурацией, так как Cloud SQL будет находиться в том же облаке, что и ваше приложение, что упрощает управление разрешениями доступа.

5. Логи и отладка

Для более глубокой диагностики подключений используйте мониторинг и логи Google Cloud:

  • Включите подробный лог ошибок Cloud Run для анализа.
  • Попробуйте временно добавить дополнительные логи в ваш обработчик, чтобы получить более детальную информацию о текущем процессе.

6. Альтернативная диагностика

Вы можете попробовать подключиться к вашему удаленному серверу MySQL с помощью инструмента telnet или другого MySQL клиента с отвечающим вашим параметрам хоста:

telnet <remote host> 3306

Если соединение не удается, следует обратиться к хостинг-провайдеру, чтобы выяснить, заблокированы ли соединения с вашего IP.

Заключение

Следование вышеуказанным шагам должно помочь вам выявить и устранить причины, по которым ваше приложение не может подключиться к удаленной базе данных MySQL. Очень важно последовательно проверять все настройки и параметры, чтобы обеспечить корректную работу приложения. Если возникнут вопросы или потребуются дополнительные разъяснения, не стесняйтесь обращаться за помощью.

Оцените материал
Добавить комментарий

Капча загружается...