Изначальная структура сети и почему мы решили от неё отказаться.
Так получилось, что АО «АльфаСтрахование» был одним из первых клиентов, которые начали использовать облачную платформу Яндекс.Облако. Множество фич и функционала, которые сейчас присутствуют в платформе тогда отсутствовали, а перед нами стояла задача организовать крупную сеть с множеством изолированных сегментов.
Поскольку в облаке, в тот момент времени, отсутствовал необходимый функционал, мы решили построить архитектуру с использованием CSR.
Как видно из схемы на CSR-2 был развернут IPSEC-туннель, который соединял Яндекс.Облако с нашей инфраструктурой. У каждого из CSR были основные и дополнительные интерфейсы, сабнеты которых были развернуты в отдельных VPC-фолдерах. Таким образом осуществлялась сетевая связность и сетевая фильтрация, дополнительная фильтрация осуществлялась, в том числе на пограничном межсетевом экране в нашей инфраструктуре.
Причины отказа от старой схемы и IPSEC-туннеля.
Изменения были очень болезненны и вызывали downtime, так как для добавления новых сабнетов необходимо было проводить технические работы на CSR с IPSEC-туннелем, а также на CSR в котором был добавлен новый сабнет. Новые сабнеты были необходимы для горизонтального масштабирования облачной инфраструктуры.
IPSEC-туннель являлся для нас «узким местом» при реализации ресурсоемких задач, а связанные с этим процессы приводили к нестабильной работе CSR-2. Соединение осуществлялось через сеть Интернет, а значит провайдеры становились точками отказа. При сбоях в зоне «A» CSR-2 вел себя нестабильно и сбрасывал туннель, терялась связность облака и нашей инфраструктуры. Все это очень мешало нашим разработчикам нормально работать.
Подготовка и переезд на Interconnect.
По прошествии времени, часть функционала в облаке, который нам требовался был реализован командой Яндекс.Облака (за что им огромное спасибо) и мы, с удовольствием, двинулись дальше в использовании более технологичных подходов, которые требовали глобальное изменение архитектуры применяемых решений.
Yandex Cloud Interconnect - позволяет установить приватное выделенное оптическое соединение между локальной сетевой инфраструктурой компании и Яндекс.Облаком.
После появления в «preview» групп безопасности мы стали использовать этот инструмент для осуществления фильтрации трафика. На данный момент в нашем облаке используется более 100 групп безопасности.
Во время подготовки к переезду на Interconnect перед нами возник ряд задач по оптимизации работы инфраструктуры. В этот момент возникла идея отказа от CSR для обеспечения маршрутизации трафика внутри облака, при этом IPSEC-туннель по-прежнему оставался на CSR-2.
Необходимо было перенести виртуальные машины из текущих сабнетов в новые с аналогичной адресацией, так как сетевые доступы были настроены на межсетевом экране внутри нашей инфраструктуры.
Переназначение сабнетов необходимо было осуществлять для всех ресурсов в фолдере за один раз, так как при создании дублирующей сети, она автоматически “выигрывала” у существующей, и маршрутизация начинала осуществляться через нее. Это происходило в связи существованием статического маршрута, который создали коллеги из Яндекс.Облака на своем оборудовании для реализации схемы с CSR.
Перенос виртуальных машин производился при помощи инструментов Yandex.Cloud CLI и Terraform:
Создание сети:
resource "yandex_vpc_subnet" "имя ресурса" {
name = "имя сабнета"
v4_cidr_blocks = ["cidr сабнета"]
zone = "ru-central1-b" //зона сабнета
network_id = "id VPC в default фолдере"
description = null folder_id = "id целевого фолдера"
labels = null route_table_id = "необходимая таблица маршрутизации"
dhcp_options {
domain_name = null domain_name_servers = ["8.8.8.8", "8.8.8.8"]
ntp_servers = ["8.8.8.8", "8.8.8.8"]
}
}
Перенос ВМ в новый сабнет:
yc compute instance update-network-interface id-вм --subnet-id=id-сабнета --ipv4-address=ip-вм --network-interface-index=0 --security-group-id=группа безопасности.
yc compute instance add-one-to-one-nat --id=fhm27r0odfkn5kjcv6lr --network-interface-index=0 --nat-address=0.0.0.0 - назначение public-ip на ВМ (уточню что перед назначением все public ip-адреса были переключены в статические через консоль управления в облаке.)
Если для виртуальных машинами схема переключения была достаточно прозрачной, то в переключении кластерных решений оказалось больше “подводных камней”.
Для того, чтобы осуществить перенос K8S-кластеров, необходимо было пересоздать их с восстановлением из бекапа при помощи Velero.
В этот же момент возникла проблема: имеющиеся в работе кластеры были deprecated-версий (снятых с поддержки в Яндекс.Облаке). Для осуществления и последующей развертки бекапа необходимо было обновить текущие кластеры на новую версию, и только после этого осуществить резервное копирование и развертку нового кластера.
После переключения кластеров, их Сервисным аккаунтам потребовались новые роли (vpc.user, vpc.admin) на главный фолдер (default) в котором находилась основная VPC и это стало для нас неожиданностью. В итоге проблему с доступом мы решали во время запланированных работ. Появилась необходимость создать особые группы безопасности, но на тот момент их ещё не было в официальной документации Яндекс.Облака, и мы получили их через нашего менеджера от Яндекс.Облака:
resource "yandex_vpc_security_group" "k8s-main-sg" {
name = "k8s-main-sg"
description = "Правила группы обеспечивают базовую работоспособность кластера. Примените ее к кластеру и группам узлов."
network_id = "<идентификатор облачной сети>"
ingress {
protocol = "TCP"
description = "Правило разрешает проверки доступности с диапазона адресов балансировщика нагрузки. Нужно для работы отказоустойчивого кластера и сервисов балансировщика."
v4_cidr_blocks = ["198.18.235.0/24", "198.18.248.0/24"]
from_port = 0
to_port = 65535
}
ingress {
protocol = "ANY"
description = "Правило разрешает взаимодействие master-to-node и node-to-node внутри группы безопасности."
predefined_target = "self_security_group"
from_port = 0
to_port = 65535
}
ingress {
protocol = "ANY"
description = "Правило разрешает взаимодействие pod-to-pod и service-to-service. Укажите подсети вашего кластера и сервисов."
v4_cidr_blocks = ["10.129.0.0/24"]
from_port = 0
to_port = 65535
}
ingress {
protocol = "ICMP"
description = "Правило разрешает отладочные ICMP-пакеты из внутренних подсетей."
v4_cidr_blocks = ["172.16.0.0/12"]
}
egress {
protocol = "ANY"
description = "Правило разрешает весь исходящий трафик. Узлы могут связаться с Yandex Object Storage, Yandex Container Registry, Docker Hub и т. д."
v4_cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 65535
}
}
resource "yandex_vpc_security_group" "k8s-public-services" {
name = "k8s-public-services"
description = "Правила группы разрешают подключение к сервисам из интернета. Примените правила только для групп узлов."
network_id = "<идентификатор облачной сети>"
ingress {
protocol = "TCP"
description = "Правило разрешает входящий трафик из интернета на диапазон портов NodePort. Добавьте или измените порты на нужные вам."
v4_cidr_blocks = ["0.0.0.0/0"]
from_port = 30000
to_port = 32767
}
}
resource "yandex_vpc_security_group" "k8s-nodes-ssh-access" {
name = "k8s-nodes-ssh-access"
description = "Правила группы разрешают подключение к узлам кластера через SSH. Примените правила только для групп узлов."
network_id = "<идентификатор облачной сети>"
ingress {
protocol = "TCP"
description = "Правило разрешает подключение к узлам по SSH с указанных IP-адресов."
v4_cidr_blocks = ["85.32.32.22/32"]
port = 22
}
}
resource "yandex_vpc_security_group" "k8s-master-whitelist" {
name = "k8s-master-whitelist"
description = "Правила группы разрешают доступ к Kubernetes API из интернета. Примените правила только к кластеру."
network_id = "<идентификатор облачной сети>”
ingress {
protocol = "TCP"
description = "Правило разрешает подключение к Kubernetes API через порт 6443 из указанной сети."
v4_cidr_blocks = ["203.0.113.0/24"]
port = 6443
}
ingress {
protocol = "TCP"
description = "Правило разрешает подключение к Kubernetes API через порт 443 из указанной сети."
v4_cidr_blocks = ["203.0.113.0/24"]
port = 443
}
}
Подробнее можно посмотреть тут: https://cloud.yandex.ru/docs/managed-kubernetes/operations/security-groups
Перенос MDB-кластеров осуществлялся через резервную копию и пересоздание в новых сабнетах с последующей разверткой бекапа. Проблем с этими операциями не возникло. Группы виртуальных машин были развернуты в новых сетях, и их сервисным аккаунтам понадобилась новая роль в фолдере default (vpc.user). Без этой роли группа виртуальных машин не разворачивалась в новом сабнете при автоматическом пересоздании ноды. К счастью, данную проблему, мы обнаружили на этапах тестирования.
Новая структура сети, работа через интерконнект.
Новая структура сети позволила легко создавать новые фолдеры и привязывать к ним сети. При использовании Interconnect появилась необходимость анонсировать новые сети через техническую поддержку Яндекс.Облака. Так же нахождение всех сетей в одном VPC позволило отказаться от использования Таблиц Маршрутизации для сабнетов. Самым большим плюсом стала возможность отделить права доступа на использование сетей и Групп безопасности от остальных фолдеров. Основным недостатком данной схемы являются недокументированные проблемы с нехваткой прав доступа.
Для перехода на новую сетевую маршрутизацию была проделана огромная совместная работа подразделений Информационной безопасности и Разработки.
В итоге, Коллеги из разработки были обеспечены надежным каналом связи, а мы контролем сетевых подключений как внутри Яндекс.Облака на конечных точках управления, так и в разрезе Облако-Инфраструктура компании.
Список источников:
Общие концепции Групп Безопасности