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

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

В этой статье мы поделимся своим опытом разработки Managed K8S под Yandex Cloud и расскажем, как мы создали конфигурацию, которую можно легко адаптировать для запуска в любом облаке или on-premises решении, изменяя только некоторые настройки. Если вы заинтересованы в построении гибких и масштабируемых Kubernetes-кластеров, то этот материал обязательно для вас.

В предыдущих статьях

Базовая организации сертификатов в kubeadm — Сертификаты K8S или как распутать вермишель Часть 1.

Как начать использовать внешний PKI сторедж Vault для хранения и выписывания сертификатов для k8s control‑plane — Сертификаты K8S или как распутать вермишель Часть 2.

Как развернуть Kubernetes кластер по принципу Hard Way — Kubernetes the hard way.

Проблема

Из моего личного опыта могу сказать, что Managed решения в облаках или в онпрем‑серверах — это отличный инструмент для создания своего продукта, и зачастую этого достаточно. Однако, бывают ситуации, когда нужно больше гибкости и возможностей настройки, а Managed решение предоставляет ограниченный набор функций.

Для нас было критично использовать сетевой плагин Cilium с нашими настройками, также нам требовались флаги feature‑gates, которых по дефолту нет в Yandex K8S API.

В принципе, не беда, мы всегда можем развернуть стационарный K8S и закастомизировать его как нам угодно. Возникли следующие вопросы: какие инструменты взять, какой выстроить процесс и как сделать так, что бы создаваемые кластера были одинаковыми?

Выбор инструментов

Для данной задачи однозначно требуются cloud native инструменты, поэтому выбор пал на Terraform. Остались вопросы: как настраивать узлы, нужен ли нам Ansible, Puppet, SaltStack? После 3 месяцев поиска золотой пилюли мы поняли, что для создания кластера нам потребуется только Terraform и cloud‑init.

Архитектура

Так как в основе нашего продукта лежит Terraform, то одно из условий работы с ним — Сервисно‑ресурсная модель (СРМ).

Ресурсами выступают все его компоненты, от балансировщика нагрузки до конфигураци cloud‑init для нашего кластера.

Также CPM позволяет менять одинаковые типы ресурсов без потребности в смене процесса деплоя кластера, таким образом, описав модули создания инфраструктуры под Yandex Cloud, VK Cloud и т. п., и, поменяв намеример модуль Yandex cloud на модуль VK Cloud, получим тот же результат, но в другом окружении.

Сертификаты

Наиболее значимым и сложным этапом было разработать подход работы с сертификатами, проблема была упомянута в предыдущих статьях. Мы определили основные спецификации для сертификатов и описали ресурсы Vault, которые создаются на основе содержимого спецификации. Однако возник вопрос доставки ключей/токенов на мастер-узлы, чтобы клиент на узле мог запросить сертификаты, указанные в спецификации. Было рассмотрено несколько вариантов решения этой проблемы:

  • Для получения secret_id и role_id от Approle можно использовать временный токен, который имеет ограниченный доступ. Для этого токен должен иметь достаточно длительный срок жизни, чтобы виртуальная машина успела запустить клиента, или можно указать, что использование токена допустимо только один раз.

  • Использование сервиса IAM от облачного провайдера для сохранения secret_id/role_id для каждой машины в облаке. Затем, можно использовать cloud-cli для получения необходимых секретов прямо с хоста.

Мы предпочли второй вариант и выбрали его, так как он лучше подходил для нашего случая. Однако первый вариант может быть полезен в тех облаках, где нет поддержки сервиса IAM.

Переменные окружения

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

variable "k8s_global_vars" {
  description = "module:K8S-GLOBAL VARS"
  type        = any
  default     = {}
}

При создании структуры этого модуля мы также уделяли внимание принципу "записал - забыл" - это означает, что если мы хотим добавить только переменную, но нехотим добавлять соответствующий вывод в OUTPUT, нам нужно использовать структурные массивы, в которые мы добавляем только нужные нам переменные, а глобальный вывод остается единым на блок. Например:

locals {

  k8s-addresses = {
    local_api_address           = format("%s.1",  join(".", slice(split(".",local.k8s_network.service_cidr), 0, 3)) )
    dns_address                 = format("%s.10", join(".", slice(split(".",local.k8s_network.service_cidr), 0, 3)) )

    idp_provider_fqdn           = format("auth.%s"          , local.cluster_metadata.base_domain)
    base_cluster_fqdn           = format("%s.%s"            , local.cluster_metadata.cluster_name, local.cluster_metadata.base_domain)
    wildcard_base_cluster_fqdn  = format("%s.%s.%s", "*"    , local.cluster_metadata.cluster_name, local.cluster_metadata.base_domain)
    etcd_server_lb_fqdn         = format("%s.%s.%s", "etcd" , local.cluster_metadata.cluster_name, local.cluster_metadata.base_domain)
  }
}

output "k8s-addresses" {
  value = local.k8s-addresses
}

Cloud init

Генерация cloud-init конфигурации является не менее важным аспектом, поскольку эта конфигурация передается виртуальной машине при ее создании.

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

Мы решили использовать подход, подобный kubeadm. Сначала мы попытались развернуть кластер с помощью kubeadm, но выяснилось, что он не может выполнить первоначальную настройку системы, такую как установка пакетов, добавление конфигурационных файлов и запуск сервисов. Поэтому мы начали разработку инструмента, который бы мог настроить систему до требуемого состояния. Результатом этой работы стал fraimctl - инструмент, который заменил множество шаблонов одной командой fraimctl init.

Таким образом, нам оставалось описать:

  • базовый конфиг fraimctl (устанавливает все компоненты и готовит конфиги к ним);

  • базовый конфиг kubeadm (генерит статик под манифесты и чекает, что кластер поднят);

  • базовый конфиг key-keeper (клиент который запрашивает сертификаты).

У нас есть несколько задач, которые мы должны выполнить, чтобы полностью отказаться от kubeadm. Мы планируем перенести этап создания конфигурационных файлов key-keeper, kubeconfig и static pod manifests в fraimctl. Кроме того, мы добавим функционал для проверки готовности сертификатов и кластера, а также этап маркировки узлов. Это позволит нам полностью отказаться от использования kubeadm и не зависеть от этого инструмента.

Fraimctl

Как уже упоминалось ранее, этот инструмент создан для возможности полного отказа от использования kubeadm и настройки кластеров без его использования.

Пример конфигурациооного файла:

fraimctl.conf
- apiVersion: fraima.io/v1alpha
  kind: Containerd
  spec:

    service:
      extraArgs:
        # This document provides the description of the CRI plugin configuration. 
        # The CRI plugin config is part of the containerd config
        # Default: /etc/containerd/config.toml
        config: /etc/kubernetes/containerd/config.toml

    configuration:
      extraArgs:
        version: 2
        plugins:
          io.containerd.grpc.v1.cri:
            containerd:
              runtimes:
                runc:
                  # Runtime v2 introduces a first class shim API for runtime authors to integrate with containerd. 
                  # The shim API is minimal and scoped to the execution lifecycle of a container.
                  runtime_type: "io.containerd.runc.v2"
                  options:
                    # While containerd and Kubernetes use the legacy cgroupfs driver for managing cgroups by default, 
                    # it is recommended to use the systemd driver on systemd-based hosts for compliance of the "single-writer" rule of cgroups. 
                    # To configure containerd to use the systemd driver, set the following option:
                    SystemdCgroup: true

    downloading:
      - name: containerd
        src: https://github.com/containerd/containerd/releases/download/v1.6.6/containerd-1.6.6-linux-amd64.tar.gz
        checkSum:
          src: https://github.com/containerd/containerd/releases/download/v1.6.6/containerd-1.6.6-linux-amd64.tar.gz.sha256sum
          type: "sha256"
        path: /usr/bin/
        owner: root:root
        permission: 0645
        unzip:
          status: true
          files: 
            - bin/containerd
            - bin/containerd-shim
            - bin/containerd-shim-runc-v1
            - bin/containerd-shim-runc-v2
            - bin/containerd-stress
            - bin/ctr

      - name: runc
        src: https://github.com/opencontainers/runc/releases/download/v1.1.3/runc.amd64
        path: /usr/bin/
        owner: root:root
        permission: 0645

    starting:
      - systemctl enable containerd
      - systemctl start containerd

Каждый компонент имеет четыре стадии:

  • downloading (загружает бинарные файлы, проверяет контрольные суммы, распаковывает необходимые компоненты и размещает их в соответствующих папках.)

  • service (генерирует службу systemd, и с помощью параметра extraArgs можно настроить ее поведение под свои нужды.)

  • configuration (генерирует конфигурацию для службы systemd, и с помощью параметра extraArgs можно настроить ее поведение под свои нужды.)

  • starting (выполняет необходимые команды после первых трех этапов.)

Одной из ключевых особенностей этого инструмента является этап загрузки (Downloading), который загружает бинарные файлы компонентов. Это позволяет не зависеть от производителя операционной системы и разворачивать единым подходом на любом хосте, не нужно думать о множестве условий (if else) и о том какая операционная система в основе.

Также предусмотрены отдельные конфигурационные файлы для настройки sysctl и modprobe.

fraimctl.conf
- apiVersion: fraima.io/v1alpha
  kind: Sysctl
  spec:
    configuration:
      extraArgs:
        net.ipv4.ip_forward: 1
    starting:
      - sudo sysctl --system

- apiVersion: fraima.io/v1alpha
  kind: Modprob
  spec:
    configuration:
      extraArgs:
      - br_netfilter
      - overlay
    starting:
      - sudo modprobe overlay
      - sudo modprobe br_netfilter
      - sudo sysctl --system

Инфраструктура

Каждый кубик в Terraform представляет собой ресурс и логически определяется как класс в языке программирования. Мы можем определить класс, например, loadBalancer, который принимает определенный набор аргументов и возвращает структуру, которая также заранее определена. Это означает, что мы можем изменять кубики по нашему усмотрению, а при смене облака все компоненты будут взаимодействовать друг с другом благодаря структуре входных и выходных параметров.

Благодаря этой архитектуре мы можем обновлять операционные системы без проблем и даже менять производителя операционной системы на лету.

kubectl get no -o wide
root@master-2-cluster-2:/home/dkot# kubectl get nodes -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# kubectl get nodes -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   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

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

Реализация

Давайте рассмотрим базовый проект и то, как можно начать использовать этот инструмент.

  1. Скачиваем репозиторий https://github.com/fraima/kubernetes

  2. В этом репозитории есть несколько разделов

    1. infrastructure-vault (создает рут PKI в Vault)

    2. infrastructure-yandex (создает базовую конфигурацию в YC, которая включает в себя создание VPC, таблицы маршрутизации и создание сервисных аккаунтов по умолчанию)

    3. infrastructure-keycloak (устанавливает базовую конфигурацию для Keycloak, которая позволяет авторизоваться в кластере через этот инструмент)

    4. k8s-yandex-cluster (проект-шаблон, который используется для создания кластера.)

  3. Заходим в каждый раздел по очереди и применяем, что прописано в Readme.

Подготовка

Для начала работы вам понадобятся переменные для подключения к Vault, YC и Keycloak.

environments
export TF_VAR_YC_CLOUD_ID=""
export TF_VAR_YC_FOLDER_ID=""
export TF_VAR_YC_TOKEN=""
export TF_VAR_YC_ZONE=""
export TF_VAR_VAULT_TOKEN=""
export TF_VAR_VAULT_ADDR=""
export TF_VAR_KEYCLOAK_REALM=""
export TF_VAR_KEYCLOAK_CLIENT_ID=""
export TF_VAR_KEYCLOAK_USER=""
export TF_VAR_KEYCLOAK_PASSWORD=""
export TF_VAR_KEYCLOAK_URL=""

Этот подход позволяет использовать Terraform в контейнере через инструмент CI/CD, не указывая реальные значения переменных в провайдерах.

Если вы работаете с чистым Terraform, не забывайте выделять каждый кластер в отдельный workspace.

terraform workspace new example

terraform plan    -var-file vars/example.tfvars
terraform apply   -var-file vars/example.tfvars
terraform destroy -var-file vars/example.tfvars

Инит конфиг

Основная конфигурация зависит от двух файлов в проекте.

  • locals.defaults.tf - базовые значения, которые определены для всех наших кластеров.

  • vars/${cluster_name}.tf - переменные, которые специально указаны для конкретного кластера.

vars/${cluster_name}.tf
global_vars = {
    cluster_name    = "example"
    pod_cidr        = "10.102.0.0/16"

    serviceaccount_k8s_controllers_name = "yandex-k8s-controllers"

    kube_apiserver_flags = {
        oidc-issuer-url         = "https://auth.dobry-kot.ru/auth/realms/master"
        oidc-client-id          = "kubernetes-clusters"
        oidc-username-claim     = "sub"
        oidc-groups-claim       = "groups"
        oidc-username-prefix    = "-"
    }

    kube_controller_manager_flags = {
        cluster-name = "kubernetes"
    }

    kube_scheduler_flags = {
        
    }

    addons = {
        cilium = {
            enabled = true
            extra_values = {
                cluster = {
                    name = "example"
                    id = 12
                }
            }
        }

        vault-issuer = {
            enabled = true
            extra_values = {}
        }

        coredns = {
            enabled = true
            extra_values = {}
        }

        gatekeeper = {
            enabled = true
            extra_values = {}
        }

        certmanager = {
            enabled = true
            extra_values = {}
        }

        machine-controller-manager = {
            enabled = true
            extra_values = {}
        }

        yandex-cloud-controller = {
            enabled = true
            extra_values = {}
        }

        yandex-csi-controller = {
            enabled = true
            extra_values = {}
        }

        compute-instance = {
            enabled = true
            custom_values = {
                subnet_id   = "e9bndv0b3c5asheadg09"
                zone        = "ru-central1-a"
                image_id    = "fd8ingbofbh3j5h7i8ll"
                replicas    = 1
            }
            extra_values = {
                metadata = {
                    nodeLabels = {
                        "node-role.kubernetes.io/worker" = ""
                        "provider" = "yandex"    
                    }
                    cloudLabels = {
                        tair = "critical"
                    }
                }
            }
        }
    }

}

cloud_metadata = {
    cloud_name  = "cloud-uid-vf465ie7"
    folder_name = "example"
}

master_group = {
    name                = "master"
    count               = 3

    default_subnet      = "10.0.0.0/24"
    default_zone        = "ru-central1-a"

    metadata = {
        # user_data_template = "fraima-hbf"
        user_data_template = "fraima"
    }
}

Этот ENV-параметр дает возможность изменить значения, которые будут использованы в конфигурационных файлах или ресурсах в будущем.

Например, мы можем изменить или добавить флаги Kube-apiserver с помощью переменной "kube_apiserver_flags".

В файле с переменными на данный момент определены три группы.

  1. "master_group" определяет, какие мастера следует заказать, в какой подсети они будут находиться, в какой зоне, будут ли они в разных зонах или нет, а также количество мастер-нод (это значение можно определить только один раз, изменить его с 1 на 3 в настоящее время невозможно).

  2. "global_vars" определяет будущую конфигурацию кластера, включая его имя, подсети для подов, флаги для компонент, которые будут использоваться, а также какие аддоны будут добавлены.

  3. "cloud_metadata" содержатся указатели на облачный провайдер, такие как cloud_name" и "folder_name".

Запускаем

time terraform apply -var-file vars/example.tfvars  -auto-approve

По умолчанию будет развернут кластер с тремя мастер-нодами, каждая из которых имеет 6 CPU, 12 ГБ оперативной памяти и 100 ГБ дискового пространства, а также 10 ГБ для ETCD.

Для каждого кластера будет создан внешний балансер, к которому вы сможете подключиться. Также будут созданы аддоны, которые настроят сеть, базовые интеграции с YC, такие как CSI driver, Cloud Controller и Machine Controller Manager для заказа воркер-нод в облаке.

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

Apply complete! Resources: 86 added, 0 changed, 0 destroyed.

Outputs:

LB-IP = "kubectl config set-cluster  cluster --server=https://158.160.63.64:443 --insecure-skip-tls-verify"

real    6m4,698s
user    0m24,182s
sys     0m1,582s

dk@dobry-kot-system:~/workspace/fraima/kubernetes/k8s-yandex-cluster-naked$ kubectl get nodes -o wide
NAME                STATUS   ROLES                  AGE     VERSION    INTERNAL-IP   EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master-50d858e0-1   Ready    control-plane,master   9m34s   v1.23.12   10.0.0.12     158.160.51.95    Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6
master-50d858e0-2   Ready    control-plane,master   9m33s   v1.23.12   10.0.0.6      158.160.38.139   Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6
master-50d858e0-3   Ready    control-plane,master   9m34s   v1.23.12   10.0.0.19     158.160.42.200   Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6

Вы можете заметить, что кластер успешно запущен и функционирует. Кроме того, у узлов теперь есть внешние IP-адреса и свидетельствует о том, что интеграция с YC работает.

Если вы используете keycloak для подключения, не забудьте установить плагин "kubectl login" и воспользоваться универсальным kubeconfig.

kubeconfig
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://158.160.63.64:443
  name: cluster
contexts:
- context:
    cluster: cluster
    namespace: kube-fraima-machine-controller-manager
    user: cluster
  name: cluster
current-context: cluster
kind: Config
preferences: {}
users:
- name: cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - oidc-login
      - get-token
      - --oidc-issuer-url=https://$KEYCLOAK-SERVER/auth/realms/master
      - --oidc-client-id=kubernetes-clusters
      - --oidc-client-secret=kube-client-secret
      - --certificate-authority=/usr/local/share/ca-certificates/oidc-ca.pem
      - --skip-open-browser
      - --grant-type=password
      - --username=$USERNAME
      - --password=$PASSWORD
      command: kubectl
      env:
      - name: context
        value: $(kubectl config current-context)
      interactiveMode: IfAvailable
      provideClusterInfo: false

Наполнение

NAME                                     STATUS   AGE
default                                  Active   11m
kube-fraima-certmanager                  Active   8m48s # CERTMANAGER
kube-fraima-dns                          Active   9m57s # COREDNS
kube-fraima-machine-controller-manager   Active   8m55s
kube-fraima-opa                          Active   9m44s # GATEKEEPER
kube-fraima-sdn                          Active   10m   # CILIUM
kube-fraima-yandex-cloud-controller      Active   11m
kube-fraima-yandex-csi-controller        Active   9m54s
kube-node-lease                          Active   11m
kube-public                              Active   11m
kube-system                              Active   11m

Внимание

Одной из важных особенностей этих кластеров является отсутствие приватных ключей от СА на мастерах, так как они хранятся в VAULT. Однако, такой подход приводит к определенным проблемам.

Вы можете добавить любую ноду в кластер через csr bootstraping, где нода генерирует запрос на сертификат и отправляет его в API, а затем вы подтверждаете этот запрос и нода получает свои сертификаты и добавляется в кластер. Однако, в данной инсталляции это нельзя сделать стандартными средствами.

Поскольку kube-controller-manager занимается выдачей сертификатов для узлов, то без доступа к приватному ключу CA этот функционал теряется. Однако, мы нашли способ получить сертификаты, установив Certmanager и Gatekeeper, а затем настроив ClusterIssuer в Certmanager для интеграции с VAULT. С помощью этого ClusterIssuer можно будет выписывать сертификаты только для worker/master узлов. Затем в Gatekeeper настраиваем мутацию ресурса CSR, который изменит базовый SIGNERNAME с "kubernetes.io/kubelet-serving" на "clusterissuers.cert-manager.io/vault-issuer". Таким образом, мы сможем получить необходимые сертификаты.

dk@dobry-kot-system:~/Downloads$ kubectl get csr
NAME                                                   AGE     SIGNERNAME                                    REQUESTOR                       REQUESTEDDURATION   CONDITION
csr-52cx7                                              12m     kubernetes.io/kubelet-serving                 system:node:master-50d858e0-3   <none>              Pending
csr-lbhqf                                              12m     kubernetes.io/kubelet-serving                 system:node:master-50d858e0-1   <none>              Pending
csr-n27p4                                              12m     kubernetes.io/kubelet-serving                 system:node:master-50d858e0-2   <none>              Pending
node-csr-3l5VT-i7YinQWaTvbCY467d27GQLnSqnT_BYgk_PFII   8m17s   clusterissuers.cert-manager.io/vault-issuer   system:bootstrap:663273         <none>              Pending

Как вы можете заметить, новый узел запросил сертификат через CSR, но SIGNERNAME у него установлен как "clusterissuers.cert-manager.io/vault-issuer". После подтверждения этого
запроса Certmanager выдаст сертификат, который будет храниться во внешнем хранилище Vault.

kubectl certificate approve node-csr-3l5VT-i7YinQWaTvbCY467d27GQLnSqnT_BYgk_PFII

После этого появится еще один запрос на сертификат, который также нужно подтвердить, и после этого узел будет добавлен в кластер.

dk@dobry-kot-system:~/Downloads$ kubectl get no -o wide
NAME                                         STATUS   ROLES                  AGE   VERSION    INTERNAL-IP   EXTERNAL-IP      OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master-50d858e0-1                            Ready    control-plane,master   24m   v1.23.12   10.0.0.12     158.160.51.95    Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6
master-50d858e0-2                            Ready    control-plane,master   24m   v1.23.12   10.0.0.6      158.160.38.139   Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6
master-50d858e0-3                            Ready    control-plane,master   24m   v1.23.12   10.0.0.19     158.160.42.200   Ubuntu 20.04.4 LTS   5.4.0-124-generic   containerd://1.6.6
worker-yandex-compute-instance-68ffc-f2sd2   Ready    worker                 11m   v1.23.12   10.154.0.11   51.250.72.216    Ubuntu 22.04.1 LTS   5.15.0-46-generic   containerd://1.6.6

Планы

  1. Расширить функционал Fraimctl, чтобы отказаться от использования Kubeadm.

  2. Написать инфраструктурные модули для AWS и VK-Cloud.

  3. Покрыть Terraform тестами.

  4. Организовать модули более четко и удалить ненужное.

  5. Перейти с использования Terraform + Helm на Terraform + Flux.

  6. Написать расширение для K8S API для добавления нашего кастомного функционала.

  7. Добавить инструмент для настройки узлов как Day2 операций.

У нашего коллектива амбициозные планы и мы нацелены на получение статуса CNCF.

Если вы оценили наш контент, присоединяйтесь к нашему чату, где вы сможете задать любые интересующие вас вопросы. Мы также будем рады любой помощи в нашем проекте.

Контакты

terraform modules: https://github.com/fraima/terraform-modules
terraform cluster: https://github.com/fraima/kubernetes

telegram community: https://t.me/fraima_ru
telegram me: https://t.me/Dobry_kot

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


  1. dobry-kot Автор
    13.04.2023 15:31
    +1

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

    Если есть потребность, готовы написать отдельные статьи по интересующим вас темам.


    1. D1abloRUS
      13.04.2023 15:31

      Да всем пофиг


      1. dobry-kot Автор
        13.04.2023 15:31

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


        1. D1abloRUS
          13.04.2023 15:31
          -1

          Расскажи, как стать богатым


          1. dobry-kot Автор
            13.04.2023 15:31
            +2

            Надо пройти весь путь по кубу с нуля и устроиться в сбер)


    1. itoracle
      13.04.2023 15:31
      +1

      Во-первых поздравляю.

      Во-вторых всегда есть люди, которым не пофиг.

      Мой совет (совершенно искренний, ни над кем не издеваюсь): причесать «котов» в репе, вместо dkot какой-нибудь cshell написать, в cncf не поймут.

      А так гордиться нам надо, что наши айтишники бороздят просторы несмотря на.

      Труд в широком смысле не уважают, рекламу сразу видят. По этой же причине коньяк 5* max, памятники истории «ремонтируют» путем сноса и т.д.


      1. dobry-kot Автор
        13.04.2023 15:31
        +2

        Ваш отзыв как бальзам на душу, большое спасибо.

        Советы учтем и поправим.


    1. mc2
      13.04.2023 15:31
      +1

      Быть может посмотреть в сторону чего то, типа https://gitbooks.io/, что бы создавать большую "книгу"?


      1. dobry-kot Автор
        13.04.2023 15:31

        Да уже начали задумываться над единой документацией,  https://gitbooks.io/ интересный проект но пока осваиваем https://squidfunk.github.io/mkdocs-material/ .

        Спасибо за совет.


  1. grossws
    13.04.2023 15:31

    Спасибо за статью. Интересно несмотря на ощущение ещё одного инструмента для создания bespoken cluster(s), который будет доставлять боль в поддержке годами))

    Такие статьи требуют кроме внимательного прочтения ещё и пачки экспериментов чтобы ощутить всю прелесть. Ну а ужас можно ощутить только в процессе эксплуатации результата, но большинство на это просто не пойдет и возьмёт более выверенные временем вещи типа kubeadm, kops, okd или флантовский deckhouse. Или k3s кому много не надо. Время и деньги на эксперименты не у всех есть..


    1. dobry-kot Автор
      13.04.2023 15:31
      +1

      Спасибо за ваш отзыв. На тему bespoken cluster(s) да вы правы это еще один инструмент для развертования, но т.к ограничен по времени и сил, не могу рассказать всю суть проекта сразу) Наш проект ориентирован на среды, где очень щепетильны к безопасности и на данный момент нету сборщиков кластеров с сертификатами из компанейского УЦ, это основное отличие, дальше повторили опыт фланта, улучшили многие места (в основной реп фланта yandex-cloud-controller, yandex-csi-controller помогли актуализировать их репозитории, добавили чарты, что бы их контроллеры можно было установить в vanila) и расширили кастомизацию за счет запуска напрямую с терраформа, а не через бинарь. (в первую очередь мы пытались сделать коробку но которая не имела бы ограничений на кастомизацию)

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


      1. itoracle
        13.04.2023 15:31

        Вопрос из чисто научного интереса: в списке узлов указана установленная версия 1.23. Надеюсь, Вы и новые разворачиваете, тут просто именно такая нужна была?


        1. dobry-kot Автор
          13.04.2023 15:31

          О, а это баг а не фича))

          Да мы последнее время тестировали на 1.23.12 и пропустили момент кастомизации этого куска, чуть позже выпущу фикс.

          Тут вопрос как описывать содержимое т.к от версии к версии компоненты надо дружить между собой по версиям.

          Версии вот отсюда тянутся там пока хардкод

          Спасибо за вашу наблюдательность)