Всем привет. Меня зовут Добрый Кот Telegram.
В этой статье расскажем, как развернуть кластер в Yandex Cloud нашим модулем terraform.
От коллектива FR-Solutions и при поддержке @irbgeo Telegram : Продолжаем серию статей о K8S.

Освежим воспоминания
В предыдущей статье мы рассписали процес развертывания Kubernetes с использованием голых конфигов и базовых бинарных файлов — это рабочий вариант, но в наших реалиях этого недостаточно, мы хотим автоматизацию.
* Пока писали автоматизацию, испытали море эмоций как от специфики шаблонизации, так и наследования ресурсов, но об это позже.
Отрицание
Первая автоматизация с моей стороны была написана на Ansible. Все начиналось лампово, пара тасок там, пара тут и через месяц родилась первая версия IaC кубера на Ansible, но чем больше я писал на Ansible, тем больше понимал, что его недостаточно — нужно постоянно удалять и создавать окружения в облаке.
Для создания окружения в облаке прекрасно подходит terraform, и первая мысль заключалась в том, чтобы скрестить ужа с ежом и получить первые 5 метров колючей проволки.
Получилось весьма неплохо, но в ходе эксплуатации я понял, что от Ansible можно избавиться полностью и написать все на Terraform. Связано это было с тем, что самое важное для сборки kubernetes моим методом — требуется всего лишь один правильный Cloud-INIT и вот для него расчехлять Ansible не хотелось. Ну что, сказано — сделано! Пошли писать на Terraform.
Гнев
Больше всего нервов скушал модуль для Vault, именно его кодовая база является самой большой в нашей автоматизации. Самые трудоемкие части:
-
Спецификация для будущих сертификатов. В ней содержится вся информация:
-
Описание для ролей.
-
Описание для заказа Key-keeper.
-
Описание сейфов и их CA.
-
Мета применимости.
-
-
Описание политик.
-
Описание токенов и аппролей.
В попытке решить базовую проблему безопасности — как передать в ВМ мастера временный токен через Cloud-Init — мы сотворили монстра. (На момент написания статьи Yandex Cloud наконец выпустил terraform provider для внутреннего сервиса LockBox, который позволяет решить проблему через IAM) — скоро пофиксим.
Торг
Дальше пытались задизайнить максимально простую, но достаточно высокодоступную конфигурацию и пришли к вот такой схеме.

Концепт простой, сделать так, чтобы виртуальные машины стали Stateless и не хранили никакой полезной нагрузки, и чтобы, в случае чего, их можно было без труда пересобрать (даже на другой тип операционной системы).
Чтобы такое провернуть, требутся несколько моментов:
-
База Etcd должна быть вынесена на внешние диски.
-
Сертификаты должны заезжать на ноду сами (сертификаты заказывает key-keeper).
-
Весь конфиг должен быть описан в Cloud-init.
-
У ВМ должны быть статичные A записи.
Мы решили все эти задачи и теперь можем работать с узлами мастеров достаточно гибко.
Депрессия
Первая версия на терраформе выглядела как одна большая репка

с ресурсами из-за чего часто были проблемы с добавлением нового или дебага старого. Было принято решение распилить на модули все ресурсы, что вызывало много вопросов «а как лучше?».

В основе лежит первый модуль yandex-cluster, в нем описывается спецификация будущего кластера и кастомизация входных аргументов модуля.
init
module "k8s-yandex-cluster" { source = "../modules/k8s-yandex-cluster" cluster_name = var.cluster_name base_domain = "dobry-kot.ru" vault_server = "http://193.32.219.99:9200/" service_cidr = "29.64.0.0/16" master_group = { name = "master" # Разрешенный префикс для сертификатов. count = 1 vpc_id = yandex_vpc_network.cluster-vpc.id default_subnet_id = yandex_vpc_subnet.master-subnets["ru-central1-a"].id default_zone = "ru-central1-a" subnet_id_overwrite = { master-1 = { subnet = yandex_vpc_subnet.master-subnets["ru-central1-a"].id zone = "ru-central1-a" } master-2 = { subnet = yandex_vpc_subnet.master-subnets["ru-central1-b"].id zone = "ru-central1-b" } master-3 = { subnet = yandex_vpc_subnet.master-subnets["ru-central1-c"].id zone = "ru-central1-c" } } resources = { core = 6 memory = 12 core_fraction = 100 etcd_disk = 60 first_disk = 30 } os_image = "fd8kdq6d0p8sij7h5qe3" ssh_username = "dkot" ssh_rsa_path = "~/.ssh/id_rsa.pub" } }
vault_server — обязательный параметр, требуется для заказа сертификатов с ноды
subnet_id_overwrite — необязательный, применяется если требуется мастера разнести по разным подсетям и зонам
master_group — спецификация будущих мастеров
Для инициализации Control Plane достаточно создать VPC и подсети для мастеров, а в Vault должен быть создан корневой сертификат компании.
Дальше кастомные параметры попадают в модуль k8s-config-vars — в этом модуле формируются и растекаются по всем остальным модулям все переменные окружения кластера.
После того, как переменные окружения сформированы, мы собираем для каждой будущей ноды Cloud-init окружение в Vault. От k8s-vault-master мы получаем токен и подкидываем в Coud-init.
Последним действием мы создаем нужную инфраструктуру и узлы с нашими Cloud-Init конфигами.
Принятие

Как итог работы мы получили рабочий модуль для Yandex Cloud по созданию Control Plane Kubernetes. Когда я дописывал последние строки, я прям почувствовал себя Риком Огурчиком!
Эмоций это приключение породило очень много и не все позитивные. Самой большой проблемой было использование модулей внутри модуля, использование наследования переменных и шаблонизация самого терраформа. В перспективе, надеюсь, упростим конфигурацию.
Что дальше?
В принципе, уже на данный момент кластер можно собрать по примеру этого флоу
Вы получите:
-
Контрол Плейн K8S в HA режиме
-
Развернутый ворклоуд Cilium, CoreDNS, YandexCSIDriver, YandexCloudController, Gatekeeper, Certmanager, ClusterMachineApprover
-
В кластер добавится Worker узел — с сертификатами от волта, но выписанный кубом (Немного магии — расскажем позже)
Перед собой ставим цели собрать минимальную коробку с бестпрактисами:
-
Дописать модуль для Data-Plane (заказ workers).
-
Добавить интеграцию с etcd-backup-restore и yandex s3.
-
Настроить базовый мониторинг.
-
Настроить SSO на базе Keycloak.
-
Добавить Автоскейлер.
-
Переписать на GO рендер cloud-init.
-
Отрефакторить RBAC для мастеров.
-
Переделать мастера c instances на group-instances
Вишенка на торте
Статус
root@master-3-cluster-2:/home/dkot# kg no -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME master-1-cluster-2 Ready control-plane,master 2m50s v1.23.12 10.1.0.11 51.250.66.122 Ubuntu 20.04.4 LTS 5.4.0-124-generic containerd://1.6.8 master-2-cluster-2 Ready control-plane,master 2m53s v1.23.12 10.2.0.33 84.201.139.95 Ubuntu 20.04.4 LTS 5.4.0-124-generic containerd://1.6.8 master-3-cluster-2 Ready control-plane,master 2m55s v1.23.12 10.3.0.21 51.250.40.244 Ubuntu 20.04.4 LTS 5.4.0-124-generic containerd://1.6.8
После пересборки
root@master-2-cluster-2:/home/dkot# kg no -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME master-1-cluster-2 Ready <none> 37s v1.23.12 10.1.0.12 62.84.119.244 Debian GNU/Linux 10 (buster) 4.19.0-18-amd64 containerd://1.6.8 master-2-cluster-2 Ready control-plane,master 12m v1.23.12 10.2.0.16 51.250.27.187 Debian GNU/Linux 10 (buster) 4.19.0-18-amd64 containerd://1.6.8 master-3-cluster-2 Ready control-plane,master 12m v1.23.12 10.3.0.13 51.250.45.49 Debian GNU/Linux 10 (buster) 4.19.0-18-amd64 containerd://1.6.8
root@master-2-cluster-2:/home/dkot# kg po -A NAMESPACE NAME READY STATUS RESTARTS AGE fraima-ccm cluster-machine-approver-679bdb498-rv4fs 1/1 Running 0 11m fraima-ccm yandex-cloud-controller-manager-vzxm8 1/1 Running 2 (2m2s ago) 11m fraima-ccm yandex-cloud-controller-manager-z8694 1/1 Running 2 (2m21s ago) 11m fraima-certmanager cert-manager-7b7db46cc-q7qfs 1/1 Running 0 11m fraima-certmanager cert-manager-cainjector-5bc7858445-s29pr 1/1 Running 0 11m fraima-certmanager cert-manager-webhook-5f9bc5fd88-qrqss 1/1 Running 0 11m fraima-cni cilium-g6pj2 1/1 Running 0 13m fraima-cni cilium-k4gqk 1/1 Running 0 13m fraima-cni cilium-operator-77d7d656d9-4t29t 1/1 Running 0 13m fraima-cni cilium-operator-77d7d656d9-tcpn5 1/1 Running 0 13m fraima-cni cilium-xw7tm 1/1 Running 0 13m fraima-csi csi-controller-656b87cd-ll7nn 6/6 Running 1 (8s ago) 11m fraima-csi csi-node-fz4fd 3/3 Running 0 11m fraima-csi csi-node-n4wgg 3/3 Running 1 (2m13s ago) 11m fraima-csi csi-node-vtnwv 3/3 Running 1 (2m37s ago) 11m fraima-dns coredns-6f67cdb5c-5x82v 1/1 Running 0 12m fraima-dns coredns-6f67cdb5c-8nx9d 1/1 Running 0 12m fraima-dns coredns-6f67cdb5c-jfsvx 0/1 Running 0 12m fraima-gatekeeper gatekeeper-audit-6b8d6d54d7-xc57p 1/1 Running 0 11m fraima-gatekeeper gatekeeper-controller-manager-597b75cb8b-8qkqj 0/1 Running 0 11m fraima-gatekeeper gatekeeper-controller-manager-597b75cb8b-q7dzg 1/1 Running 0 11m fraima-gatekeeper gatekeeper-controller-manager-597b75cb8b-qp9g4 1/1 Running 0 11m kube-system etcd-master-1-cluster-2 1/1 Running 0 53s kube-system etcd-master-2-cluster-2 1/1 Running 0 12m kube-system etcd-master-3-cluster-2 1/1 Running 0 12m kube-system kube-apiserver-master-1-cluster-2 1/1 Running 0 53s kube-system kube-apiserver-master-2-cluster-2 1/1 Running 0 2m58s kube-system kube-apiserver-master-3-cluster-2 1/1 Running 0 2m56s kube-system kube-controller-manager-master-1-cluster-2 1/1 Running 0 53s kube-system kube-controller-manager-master-2-cluster-2 1/1 Running 0 12m kube-system kube-controller-manager-master-3-cluster-2 1/1 Running 0 11m kube-system kube-scheduler-master-1-cluster-2 1/1 Running 0 53s kube-system kube-scheduler-master-2-cluster-2 1/1 Running 0 12m kube-system kube-scheduler-master-3-cluster-2 1/1 Running 0 11m
Как обещал, налету можно сменить даже тип операционной системы.
Полезное чтиво
Kubernetes The Hard Way
https://github.com/fraima/kubernetes
https://github.com/fraima/key-keeper
ссылка на оригинал статьи https://habr.com/ru/post/704410/
Добавить комментарий