Всем привет. Меня зовут Добрый Кот Telegram.

В этой статье расскажем, как развернуть кластер в Yandex Cloud нашим модулем terraform.

От коллектива FR-Solutions и при поддержке @irbgeo Telegram : Продолжаем серию статей о K8S.

Состояние на момент написания статьи
Состояние на момент написания статьи

Освежим воспоминания

В предыдущей статье мы рассписали процес развертывания Kubernetes с использованием голых конфигов и базовых бинарных файлов - это рабочий вариант, но в наших реалиях этого недостаточно, мы хотим автоматизацию.

* Пока писали автоматизацию, испытали море эмоций как от специфики шаблонизации, так и наследования ресурсов, но об это позже.

Отрицание

Первая автоматизация с моей стороны была написана на Ansible. Все начиналось лампово, пара тасок там, пара тут и через месяц родилась первая версия IaC кубера на Ansible, но чем больше я писал на Ansible, тем больше понимал, что его недостаточно - нужно постоянно удалять и создавать окружения в облаке.

Для создания окружения в облаке прекрасно подходит terraform, и первая мысль заключалась в том, чтобы скрестить ужа с ежом и получить первые 5 метров колючей проволки.

Получилось весьма неплохо, но в ходе эксплуатации я понял, что от Ansible можно избавиться полностью и написать все на Terraform. Связано это было с тем, что самое важное для сборки kubernetes моим методом - требуется всего лишь один правильный Cloud-INIT и вот для него расчехлять Ansible не хотелось. Ну что, сказано - сделано! Пошли писать на Terraform.

Гнев

Больше всего нервов скушал модуль для Vault, именно его кодовая база является самой большой в нашей автоматизации. Самые трудоемкие части:

  1. Спецификация для будущих сертификатов. В ней содержится вся информация:

    1. Описание для ролей.

    2. Описание для заказа Key-keeper.

    3. Описание сейфов и их CA.

    4. Мета применимости.

  2. Описание политик.

  3. Описание токенов и аппролей.

В попытке решить базовую проблему безопасности - как передать в ВМ мастера временный токен через Cloud-Init - мы сотворили монстра. (На момент написания статьи Yandex Cloud наконец выпустил terraform provider для внутреннего сервиса LockBox, который позволяет решить проблему через IAM) - скоро пофиксим.

Торг

Дальше пытались задизайнить максимально простую, но достаточно высокодоступную конфигурацию и пришли к вот такой схеме.

Концепт простой, сделать так, чтобы виртуальные машины стали Stateless и не хранили никакой полезной нагрузки, и чтобы, в случае чего, их можно было без труда пересобрать (даже на другой тип операционной системы).

Чтобы такое провернуть, требутся несколько моментов:

  1. База Etcd должна быть вынесена на внешние диски.

  2. Сертификаты должны заезжать на ноду сами (сертификаты заказывает key-keeper).

  3. Весь конфиг должен быть описан в Cloud-init.

  4. У ВМ должны быть статичные 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. Когда я дописывал последние строки, я прям почувствовал себя Риком Огурчиком!

Эмоций это приключение породило очень много и не все позитивные. Самой большой проблемой было использование модулей внутри модуля, использование наследования переменных и шаблонизация самого терраформа. В перспективе, надеюсь, упростим конфигурацию.

Что дальше?

В принципе, уже на данный момент кластер можно собрать по примеру этого флоу

Вы получите:

  1. Контрол Плейн K8S в HA режиме

  2. Развернутый ворклоуд Cilium, CoreDNS, YandexCSIDriver, YandexCloudController, Gatekeeper, Certmanager, ClusterMachineApprover

  3. В кластер добавится 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

Как обещал, налету можно сменить даже тип операционной системы.

Ждем вас на обсуждения нашей работы в https://t.me/fraima_ru

Полезное чтиво

Kubernetes The Hard Way
https://github.com/fraima/kubernetes
https://github.com/fraima/key-keeper

Комментарии (0)