Вопрос или проблема
У меня есть экземпляр виртуальной машины с именем mysql-1
в той же учетной записи, в том же VPC, что и кластер GKE.
У меня развернут сервис k8s:
~ $ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
haproxy-mysql LoadBalancer 10.19.242.236 8.8.8.8 3306:32375/TCP,3307:30748/TCP,3308:30064/TCP 40m
^ здесь заменен фактический внешний IP на 8.8.8.8
На виртуальной машине у меня работает mysql на 3306
user@mysql-1:~$ netstat -ntap |grep 3306|grep LISTE
(Не все процессы могут быть идентифицированы, информация о процессах, не принадлежащих текущему пользователю, не будет показана, вам нужно быть root, чтобы увидеть все.)
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN -
user@mysql-1:~$ ip a|grep 156
inet 10.156.0.13/32 brd 10.156.0.13 scope global dynamic ens4
из k8s pod я могу подключиться к виртуальной машине:
# curl -I 10.156.0.13:3306
curl: (8) Странный ответ сервера
из виртуальной машины я не могу подключиться к сервису haproxy используя как внутренний, так и внешний IPs:
user@mysql-1:~$ curl --connect-timeout 2 10.19.242.236:3306
curl: (28) Время ожидания соединения истекло через 2001 миллисекунду
user@mysql-1:~$ curl --connect-timeout 2 8.8.8.8:3306
curl: (28) Время ожидания соединения истекло через 2001 миллисекунду
когда я использую IP pod, это работает :
$ kubectl get pods -A -o wide |grep haproxy-mysql
default haproxy-mysql-6dd5f8cf64-72gdx 1/1 Running 0 10m 10.16.1.39 gke-blabla-default-pool-370bb0fd-92rb <none> <none>
default haproxy-mysql-6dd5f8cf64-zgmwb 1/1 Running 0 10m 10.16.2.56 gke-blabla-default-pool-370bb0fd-prn7 <none> <none>
user@mysql-1:~$ curl --connect-timeout 2 10.16.1.39:3306
Внимание: Двоичный вывод может испортить ваш терминал. Используйте "--output -" чтобы указать
Внимание: curl выводить его на ваш терминал, или учтите "--output
Внимание: <FILE>" чтобы сохранить в файл.
У меня есть правило межсетевого экрана:
~ $ gcloud compute firewall-rules list|grep 3306
k8s-fw-ad6943bb1121311eab6fc42010a9c005 default INGRESS 1000 tcp:3306,tcp:3307,tcp:3308 False
~ $ gcloud compute firewall-rules describe k8s-fw-ad6943bb1121311eab6fc42010a9c005
allowed:
- IPProtocol: tcp
ports:
- '3306'
- '3307'
- '3308'
creationTimestamp: '2019-11-28T11:18:23.294-08:00'
description: '{"kubernetes.io/service-name":"default/haproxy-mysql", "kubernetes.io/service-ip":"8.8.8.8"}'
direction: INGRESS
disabled: false
id: '2373636381534430096'
kind: compute#firewall
logConfig:
enable: false
name: k8s-fw-ad6943bb1121311eab6fc42010a9c005
network: https://www.googleapis.com/compute/v1/projects/blalala-1234lab/global/networks/default
priority: 1000
selfLink: https://www.googleapis.com/compute/v1/projects/blalala-1234/global/firewalls/k8s-fw-ad6943bb1121311eab6fc42010a9c005
sourceRanges:
- 8.8.8.8/32
- 8.8.8.8/32
- 8.8.8.8/32
- 10.0.0.0/8
- 8.8.8.8/32
- 8.8.8.8/32
- 8.8.8.8/32
- 8.8.8.8/32
targetTags:
- gke-blablabla-4125f0a3-node
с сервера, который явно указан в блоке выше (маскирован как 8.8.8.8/32), я могу подключиться к сервису EXTERNAL-IP
Что я здесь упускаю?
IP-адреса Pod маршрутизируются, IP-адреса сервисов — нет.
Создание кластера VPC-native:
IP-адреса кластера для внутренних сервисов доступны только внутри
кластера. Если вы хотите получить доступ к Kubernetes-сервису из той же
VPC и региона, но за пределами кластера (например, с экземпляра Compute Engine), используйте внутренний балансировщик нагрузки.
Документация по внутреннему балансировщику нагрузки
Что касается доступа с внешнего IP, возможно, такие правила не будут работать, если источник — это частный IP, а цель — внешний IP (даже если это выражается в виде метки там). Для входящих соединений этот частный IP не будет виден как источник IP, и правило не сработает?
Вы следовали всем шагам здесь Настройка балансировки нагрузки HTTP с Ingress для настройки вашего кластера GKE?
Насколько я понимаю, вам нужно Предоставить ваш деплоймент как сервис внутри кластера
Если вы ищете способ подключиться к вашим сервисам GKE из виртуальной машины в той же VPC, то, по состоянию на 2025-03-03, это можно сделать, настроив Cloud DNS в GKE. См. https://cloud.google.com/kubernetes-engine/docs/how-to/cloud-dns#vpc_scope_dns
.
Ответ или решение
Для решения проблемы соединения между виртуальной машиной (VM) и службой GKE в пределах одного VPC на платформе Google Cloud Platform (GCP), давайте рассмотрим все аспекты, начиная с теории основных компонентов GCP, включая архитектуру сети, настройки Kubernetes и правила брандмауэра.
Теория (T)
Виртуальные машины (VM) и кластеры Google Kubernetes Engine (GKE) могут существовать внутри одной виртуальной частной сети (VPC) на GCP, что позволяет обеспечить внутренние взаимодействия между различными элементами инфраструктуры. Понимание того, как GKE и VM работают вместе в контексте VPC, жизненно важно для создания надежной сетевой архитектуры.
-
GKE Службы и IP-адреса:
Внутренние IP-адреса кластера GKE известны как IP-адреса "Сети кластеров" (Cluster IP) и они не доступны вне кластера GKE. Для доступа к этому ресурсу из других источников внутри того же VPC (например, из виртуальной машины) требуется использование внутреннего балансировщика нагрузки.
-
Балансировщик нагрузки:
Google Cloud предлагает внутренние и внешние балансировщики нагрузки для различных сценариев. Использование внутреннего балансировщика нагрузки для службы Kubernetes сделает ее доступной из VM в том же VPC.
-
Правила брандмауэра:
В GCP трафик управляется с помощью правил брандмауэра. Это требует, чтобы необходимые порты были открыты и соответствующие диапазоны IP-адресов были указаны как источники соединений.
Пример (E)
Рассмотрим текущую проблему: на VM mysql-1 запущен MySQL на порту 3306, и имеется k8s служба haproxy-mysql. Интересно отметить, что из VM не удается подключиться к Cluster IP службы, хотя ip-адрес пода работает. Давайте разберем это ситуация:
-
Подключение к Cluster IP:
- Подключения из VPC к Cluster IP блокируются по умолчанию. Эти IP-адреса доступны только внутри кластера GKE, как упоминалось в представленной документации.
-
Подключение к Pod IP:
- Под IP-адреса доступны для маршрутизации внутри того же VPC. Это объясняет, почему ваш curl запрос к Pod IP успешен.
-
Правила брандмауэра:
- Существующее правило брандмауэра открывает порт 3306, но список источников включает только 8.8.8.8/32, в то время как ваш машинный IP (10.156.0.13) необходим для корректного функционирования.
Применение (A)
Для обеспечения стабильного соединения между VM и службой в GKE вам нужно сделать следующее:
-
Создание внутреннего балансировщика нагрузки:
Создайте внутренний балансировщик нагрузки, который будет ассоциирован с вашей службой GKE. Это позволит вам создать IP-адрес, доступный для VM в том же VPC.
apiVersion: v1 kind: Service metadata: name: haproxy-mysql annotations: cloud.google.com/load-balancer-type: "Internal" spec: type: LoadBalancer ports: - port: 3306 targetPort: 3306 selector: app: haproxy
Этот конфигурационный файл будет создаваться с уникальным для вас Cluster IP и сможет использоваться в VPC.
-
Настройка правил брандмауэра:
Обновите ваши правила брандмауэра, чтобы включить все нужные диапазоны IP-адресов из вашего VPC:
gcloud compute firewall-rules create allow-internal-lb \ --network default \ --allow tcp:3306 \ --source-ranges 10.156.0.0/20
Это правило позволит трафику по порту 3306 между вашей VM и лоад-балансером вашего кластера GKE.
-
Проверка и тестирование:
Убедитесь, что ваш балансировщик нагрузки успешно создан и что ваш трафик может передаваться из VM к службе через новый IP-адрес внутреннего балансировщика.
Следуя этим шагам, вы сможете эффективно связать вашу виртуальную машину с вашим кластером GKE в пределах одного VPC, используя внутренние службы и балансировщики нагрузки.