Прикольно, как некоторые относительно продвинутые инструменты и фрейморки стараются выглядеть проще и понятнее, и в результате превращаются во что-то ещё более зубодробительно невнятное. Давным-давно так было с git, когда мне пришлось перейти на командную строку и прочитать ‘Pro GIT’ целиком, чтобы гитовские GUI клиенты обрели хоть какую-то логику. Та же ерунда позже получилась с kubernetes, когда с более «простыми» kubectl run
и kubectl expose
было совсем непонятно, что же происходит на самом деле, в то время как перейдя на уровень ниже, к kubectl apply
и YAML конфигурациям, всё стало на удивление простым логичным.
И вот теперь пришла очередь гугловых балансировщиков нагрузки — GCP load balancers. Глядя на все эти чекбоксы и кнопочки в гугловых визардах, я иногда чувствую себя младшим бухгалтером советского колхоза. С одной стороны, непонятно, что же именно я делаю. С другой стороны, непонятно — зачем. А вот как только создашь всё руками через файлы конфигурации, так всё снова кажется логичным.
Для примера возьмём, например, Internal Load Balancer, и посмотрим, как его можно сконфигурировать через Deployment Manager. Если всё пройдёт как я думаю, то оно действительно будет выглядеть логичным.
Что такое Internal Load Balancer (ILB)
Идея ILB вполне себе простая: мы будем распределять входящие запросы между несколькими виртуальными машинами — инстансами, и при этом и инстансы, и запросы будут находиться в одной и той же сети. Зачем такое может быть? Ну, например, один приватный микросервис захочет общаться с другим, который, к головной боли окружающих, масштабируется горизонтально.
Вот так выглядела бы очень упрощённая диаграмма такого общения.
Сверху на общую айпишку приходят запросы, и при помощи чёрной магии распределяются по конкретным хостам. И вот именно чёрная магия нас сейчас больше всего и интересует.
Разбираем магию.
Вообще говоря, в ILB не так уж и много составных частей. Секретные ингредиенты там вот какие:
- forwarding rule,
- backend service и health check,
- managed instance group и шаблон instance для неё.
На всё это можно ещё повесить статическую внутреннюю айпишку, но можно обойтись и эфемерной.
Посмотрим теперь на эти компоненты в обратном порядке.
Managed instance group и instance template.
Managed instance group (MIG) — это гугловый ресурс, который будет поддерживать заданное число виртуальных машин, которые он сам же создаст из шаблона. То есть, если я захочу создать десять идентичных виртуальных машин, то мне не нужно десять раз повторять одну и ту же команду или прокликивать одни и те же формы. Создал шаблон, сконфигурировал группу, задал ей targetSize
в 10, и поехали. Именно MIG будет разговаривать с остальными кусками load balancer’а.
Вообще говоря, балансировку нагрузки можно было бы сделать и среди неуправляемой группы инстансов (unmanaged), но в таком случае все десять виртуальных машин действительно пришлось бы создавать руками. Да и автоматически масштабировать такие группы не получится. autoscaler
— ещё один облачный ресурс — работает только с управляемыми группами).
Вот как создание управляемой группы и шаблона инстанса для неё выглядит в deployment manager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
resources: - name: managed-instance-group type: compute.v1.regionInstanceGroupManager properties: instanceTemplate: $(ref.apache-instance-template.selfLink) region: us-central1 targetSize: 3 - name: apache-instance-template type: compute.v1.instanceTemplate properties: properties: machineType: f1-micro disks: - autoDelete: true boot: true deviceName: boot initializeParams: sourceImage: projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts type: PERSISTENT networkInterfaces: - accessConfigs: - name: External NAT type: ONE_TO_ONE_NAT network: global/networks/default metadata: items: - key: startup-script value: | #! /bin/bash apt-get update apt-get install apache2 -y service apache2 restart echo "http-`hostname`" | tee /var/www/html/index.html EOF" |
Да, ещё один момент: internal load balancer — штука региональная, поэтому и MIG ей нужен соответствующий — regionalInstanceGroupManager
.
backend service и health check для него
Бэкэнд сервис — это уже группа из одного или нескольких MIG, которые предоставляют один и тот же сервис. Например, API, контент, или что-нибудь ещё. На уровне сервиса мы и будем указывать, как именно распределять запросы между этими группами. Будет ли это INTERNAL или EXTERNAL балансировка, какой там будет протокол, по какому правилу распределять запросы, и прочее.
Бэкенду также полагается health check, чтобы он мог хоть как-то различать, кто ещё в состоянии принимать траффик, а кто уже не жилец. Неочевидная особенность таких проверок — им нужны отдельные правила файрвола, которые автоматически не проставляются, и поэтому их нужно задавать вручную (ну или через deployment manager).
Наш балансировщик — INTERNAL, протокол — TCP (ILB всего-то два протокола поддерживает: TCP и UDP), так что забросим-ка ещё немного YAML в конфигурацию и посмотрим, на что это теперь похоже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
- name: allow-tcp-health-check type: compute.v1.firewall properties: network: global/networks/default sourceRanges: - 35.191.0.0/16 - 130.211.0.0/22 allowed: - IPProtocol: tcp - name: tcp-health-check type: compute.v1.healthCheck properties: type: TCP tcpHealthCheck: port: 80 - name: backend-service type: compute.v1.regionBackendService properties: region: us-central1 protocol: TCP loadBalancingScheme: INTERNAL backends: - group: $(ref.managed-instance-group.instanceGroup) healthChecks: - $(ref.tcp-health-check.selfLink) |
Как в случае с regionInstanceGroupManager
, сервис тоже региональный — regionBackendService
, и он находится в том же регионе, что и MIG. Ну а начинается YAML с задания правил файрвола, чтобы health checks таки смогли пробиться к инстансам.
forwarding rule и статическая айпишка
Последний ресурс — forwarding rule — соединяет вместе айпишку с одной стороны и получателя траффика с неё с другой. Настраивать его проще простого, поэтому для разнообразия пусть он хотя бы пользуется статический региональной айпишкой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
- name: internal-regional-forwarding-rule type: compute.v1.forwardingRule properties: region: us-central1 ports: - 80 loadBalancingScheme: INTERNAL backendService: $(ref.backend-service.selfLink) network: global/networks/default IPAddress: $(ref.static-ip.selfLink) - name: static-ip type: compute.v1.address properties: addressType: INTERNAL region: us-central1 |
Результат
Вот на что в результате стал похож наш internal load balancer:
Разноцветных прямоугольников там больше, чем хотелось бы, но при некотором ментальном усилии во всём этом теперь можно разглядеть смысл. Теперь мы можем отправить YAML в Deployment Manager, создать какую-нибудь тестовую виртуальную машину в той же сети, что и ILB (в нашем случае это — default), найти адрес нашей статический айпишки (gcloud compute addresses list
) и начать развлекаться:
Развёртываем:
1 2 3 4 5 6 7 8 9 10 11 12 |
gcloud deployment-manager deployments create test-ilb --config config.yaml #The fingerprint of the deployment is AnJC0hR9-lFVXZWPT7xsjg== #Waiting for create [operation-1540145630432-578c119344b02-c4904215-7c4c481a]...done. #Create operation operation-1540145630432-578c119344b02-c4904215-7c4c481a completed successfully. #NAME TYPE STATE ERRORS INTENT #allow-tcp-health-check compute.v1.firewall COMPLETED [] #apache-instance-template compute.v1.instanceTemplate COMPLETED [] #backend-service compute.v1.regionBackendService COMPLETED [] #internal-regional-forwarding-rule compute.v1.forwardingRule COMPLETED [] #managed-instance-group compute.v1.regionInstanceGroupManager COMPLETED [] #static-ip compute.v1.address COMPLETED [] #tcp-health-check compute.v1.healthCheck COMPLETED [] |
Находим айпишку:
1 2 3 |
gcloud compute addresses list #NAME REGION ADDRESS STATUS #static-ip us-central1 10.128.0.2 IN_USE |
Отправляем пару тестовых запросов на неё:
1 2 3 4 5 6 7 8 |
ping-tool:~$ curl 10.128.0.2 #http-managed-instance-group-szlk ping-tool:~$ curl 10.128.0.2 #http-managed-instance-group-szlk ping-tool:~$ curl 10.128.0.2 #http-managed-instance-group-5rwt ping-tool:~$ curl 10.128.0.2 #http-managed-instance-group-5rwt |
Вуаля! Штука работает. И даже в гугловой консоли оно всё похоже на настоящий GCP балансировщик нагрузки:
Хотите верьте, хотите нет, но на самом деле это один из самых простых лоад балансеров в GCP. Чтобы доказать это, в следующий раз я таким же образом препарирую какой-нибудь внешний глобальный HTTP(s) балансировщик, и тогда посмотрим, на что это будет похоже.
Хороший блог. Спасибо. Про облака и инстансы с LB вообще песня. Правда я юзаю AWS, но разница не шибко большая. Пиши побольше об этом. Ну и ELS тоже полезно)).
Спасибо!