Managed K8S от MTS Cloud

от автора

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

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

Наша команда получила запрос на оценку managed K8S от MTS Cloud и составление объективного обзора проделанной работы инженеров МТС. Хочу отметить, что данная статья не является заказной, поэтому мы сосредоточимся на объективном анализе плюсов и минусов этого решения.

Регистрация

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

Первоначальная авторизация

При первом входе на страницу вы увидите следующую панель с доступными услугами.

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

Создание кластера K8S

Чтобы создать кластер K8S, вам необходимо выбрать услугу «Containerum Kubernetes» и нажать кнопку «Добавить».

Однако параметры модификации кластера оказываются довольно ограниченными:

  • имя кластера

  • зоны доступности (Москва/Владивосток)

  • сеть для нод

  • сеть для подов

  • версия кластера

  • single master / HA (вид отказоустойчивости)

  • описание группы нод (воркеры)

  • плагины

После выбора необходимой конфигурации вы нажимаете кнопку «Создать» и ожидаете создания кластера.

Сеть

Перед тем, как приступить к выполнению любых задач, вам потребуется настроить сеть. В МТС Облаке для этого доступны ресурсы: Виртуальная частная сеть (VPC) и подсети.

Выражаем свое беспокойство относительно полосы пропускания в 100 Мбит на выходе (не проводили тестирование скорости между узлами).

Созданную подсеть можем указать базовой для наших будущих узлов кластера. Адресация будет выдана по DHCP.

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

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

Masters

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

  1. Мастер-ноды Kubernetes разворачиваются в виртуальной частной сети (VPC) пользователя (*проверяется через
    kubectl get endpoints -n default kubernetes
    там будет отображен список IP от мастер нод)

  2. При создании кластера пользователь указывает базовую подсеть нод, в которой будут развернуты мастер-ноды.

  3. Балансировщик нагрузки кластера ведет на мастера и может иметь либо внутреннюю адресацию, либо внешнюю.

Догадки:

  1. OC Flatcar

  2. Для control-plane и data-plane нод не создаются предварительно настроенные образы (Golden Images) — вся настройка производится через cloud-init.

  3. Для выдачи сертификатов вероятно используется инструмент, подобный Vault или аналогичная центральная служба аутентификации (ЦА).

  4. На борту системы имеется три пользователя, которые могут получить доступ к системе через SSH:

    1. core (не используется, пароля нет, ssh ключа нет)

    2. root (не используется, пароля нет, ssh ключа нет)

    3. admin — с доступом по ssh через ключи типа ssh-ed25519

      1. через него подключается containerum@config-manager

  5. Вся конфигурация передается с использованием файлов Ignition config:

    1. сертификаты (private/public ключи)

    2. конфигурационные файлы

    3. для скачивания необходимых бинарных файлов в систему используются триггер-сервисы, которые управляются через зависимости systemd services.

Догадки строятся основываясь на устройстве нод от data-plane.

Workers

При создании группы узлов в кластере, добавляются новые узлы с определенными метаданными:

  • OS IMAGE: Flatcar Container Linux by Kinvolk 3374.2.0 (Oklo)

  • KERNEL-VERSION: 5.15.74-flatcar

  • CONTAINER-RUNTIME: containerd://1.6.8

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

Для получения доступа к узлу можно создать контейнер в привилегированном режиме и использовать механизм hostPath с монтированием директории /host. Затем можно выполнить команду chroot /host внутри контейнера, чтобы перейти в корневую файловую систему узла и получить доступ к его содержимому.

--- apiVersion: v1 kind: Pod metadata:   name: chroot-pod spec:   hostNetwork: true   containers:   - name: chroot-container     image: nginx:stable     securityContext:       privileged: true     volumeMounts:     - name: host-root       mountPath: /host   volumes:   - name: host-root     hostPath:       path: /

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

Давайте рассмотрим процесс бутстрапа нашего хоста. Для этого выполним следующую команду:

journalctl --identifier=ignition --all
список созданных файлов
 writing file "/etc/environment"  writing file "/etc/hostname"  writing file "/etc/coredns.conf"  writing file "/etc/hosts"  writing link "/etc/resolv.conf" -> "/run/systemd/resolve/stub-resolv.conf"  writing file "/etc/flatcar/update.conf"  writing file "/etc/kubernetes/kube-proxy.yaml"  writing file "/etc/kubernetes/node.kubeconfig"  writing file "/etc/kubernetes/kube-proxy.kubeconfig"  writing file "/etc/kubernetes/kubelet.yaml"  writing file "/opt/kubelet/config.json"  writing file "/etc/sysctl.d/k8s.conf"  writing file "/etc/sysctl.d/80-swappiness.conf"  writing file "/etc/modules-load.d/k8s.conf"  writing file "/etc/logrotate.d/overrides.conf"  writing file "/etc/systemd/resolved.conf"  writing file "/etc/containerd/config.toml"  writing file "/etc/kubernetes/pki/node.key"  writing file "/etc/kubernetes/pki/ca.crt"  writing file "/etc/systemd/system/vmtoolsd.service" 

Далее приведен результат, содержащий список записанных файлов.

environment

/# cat /etc/environment  export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/opt/bin/:/opt/cni/bin # For crictl export CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock

Возникает вопрос, почему было необходимо передавать переменную окружения
CONTAINER_RUNTIME_ENDPOINT, если имеется опция --config, указывающая на
файл /etc/crictl.yaml.

MDNS

В системе используется плагин COREDNS — MDNS, который обеспечивает поддержку мультисервисного обнаружения (mDNS). Этот плагин позволяет устройствам и сервисам в сети обнаруживать и взаимодействовать друг с другом без необходимости во внешних DNS-серверах.

coredns-mdns bootstrap
####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system-preset/20-ignition.preset | grep coredns enable coredns.service enable coredns-download.service  ####################################################### set-thrush-bce3f9-233564 /home/admin # systemctl status coredns.service ● coredns.service - CoreDNS DNS server      Loaded: loaded (/etc/systemd/system/coredns.service; enabled; vendor preset: enabled)      Active: active (running) since Sat 2023-06-10 18:26:18 UTC; 21h ago        Docs: https://coredns.io    Main PID: 934 (mdns-coredns)       Tasks: 8 (limit: 15420)      Memory: 33.4M         CPU: 46.814s      CGroup: /system.slice/coredns.service              └─934 /opt/bin/mdns-coredns -conf=/etc/coredns.conf  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system/coredns-download.service [Unit] Description=downloading coredns  Wants=network-online.target network.target After=network-online.target ConditionFileNotEmpty=|/opt/coredns64.tgz ConditionFileNotEmpty=|!/opt/bin/mdns-coredns  [Service] Type=oneshot  Environment="URL=https://nexus.dev.cloud.mts.ru/repository/golang-raw/containers/mdns-coredns/mdns-coredns-v1.10.0-3.tgz" Environment="FILE=/opt/coredns64.tgz"  ExecStart=/usr/bin/wget -c --retry-connrefused --tries 50 -O $FILE $URL ExecStartPost=tar -xvf $FILE -C /opt/  [Install] WantedBy=multi-user.target   ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/coredns.conf .:5000 {   log . "[global] {combined}"{     class denial error   }    debug    bind lo   cache 30    forward . 10.99.43.154 {     policy sequential     expire 60s # expire (cached) connections after this time   } }  containerum:5000 {   debug   bind lo   log . "[mdns] {combined}"   mdns containerum 3 } 

Используют плагин COREDNS — MDNS

KUBE-PROXY

kube-proxy bootstrap
####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system-preset/20-ignition.preset | grep proxy enable kube-proxy.service enable kube-proxy-download.service  ####################################################### set-thrush-bce3f9-233564 /home/admin # systemctl status kube-proxy.service ● kube-proxy.service - kube-proxy      Loaded: loaded (/etc/systemd/system/kube-proxy.service; enabled; vendor preset: enabled)      Active: active (running) since Sat 2023-06-10 21:47:16 UTC; 18h ago    Main PID: 142352 (kube-proxy)       Tasks: 5 (limit: 15420)      Memory: 39.9M         CPU: 4min 7.100s      CGroup: /system.slice/kube-proxy.service              └─142352 /opt/bin/kube-proxy --config=/etc/kubernetes/kube-proxy.yaml  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/kubernetes/kube-proxy.yaml --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration clientConnection:   kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig" mode: "ipvs" clusterCIDR: 100.70.0.0/16  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system/kube-proxy-download.service [Unit] Description=downloading kube-proxy  Wants=network-online.target network.target After=network-online.target ConditionFileNotEmpty=|!/opt/bin/kube-proxy ConditionFileIsExecutable=|!/opt/bin/kube-proxy  [Service] Type=oneshot  # Environment="URL=https://storage.googleapis.com/kubernetes-release/release/v1.24.6/bin/linux/amd64/kube-proxy" Environment="URL=https://nexus.dev.cloud.mts.ru/repository/containerum-binaries/kube-proxy/kube-proxy-v1.24.6" Environment="FILE=/opt/bin/kube-proxy"  ExecStart=/usr/bin/wget -c --retry-connrefused --tries 50 -O $FILE $URL ExecStartPost=/usr/bin/chmod 755 $FILE  [Install] WantedBy=multi-user.target 

KUBELET BOOT

kubelet-bootstrap
####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system-preset/20-ignition.preset | grep kubelet enable kubelet.service enable kubelet-download.service  ####################################################### set-thrush-bce3f9-233564 /home/admin # systemctl status kubelet.service ● kubelet.service - Kubernetes Kubelet      Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled)      Active: active (running) since Sun 2023-06-11 00:04:06 UTC; 16h ago    Main PID: 206921 (kubelet)       Tasks: 0 (limit: 15420)      Memory: 53.1M         CPU: 226ms      CGroup: /system.slice/kubelet.service              ‣ 206921 /opt/bin/kubelet \         --config=/etc/kubernetes/kubelet.yaml \         --kubeconfig=/etc/kubernetes/node.kubeconfig \         --container-runtime=${KUBELET_RUNTIME} \         --container-runtime-endpoint=${KUBELET_RUNTIME_ENDPOINT} \         --cloud-provider=external \         --runtime-cgroups=/systemd/system.slice \         --root-dir=/opt/kubelet \         --v=2  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system/kubelet-download.service [Unit] Description=downloading kubelet  Wants=network-online.target network.target After=network-online.target ConditionFileNotEmpty=|!/opt/bin/kubelet ConditionFileIsExecutable=|!/opt/bin/kubelet  [Service] Type=oneshot  # Environment="URL=https://storage.googleapis.com/kubernetes-release/release/v1.24.6/bin/linux/amd64/kubelet" Environment="URL= https://nexus.dev.cloud.mts.ru/repository/containerum-binaries/kubelet/kubelet-v1.24.6" Environment="FILE=/opt/bin/kubelet"  ExecStart=/usr/bin/wget -c --retry-connrefused --tries 50 -O $FILE $URL ExecStartPost=/usr/bin/chmod 755 $FILE  [Install] WantedBy=multi-user.target  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/kubernetes/kubelet.yaml kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 authentication:   anonymous:     enabled: false   webhook:     enabled: true   x509:     clientCAFile: "/etc/kubernetes/pki/ca.crt" authorization:   mode: Webhook clusterDomain: "cluster.local" clusterDNS:   - 100.71.0.10 podCIDR: 100.70.0.0/16 runtimeRequestTimeout: "15m" cgroupDriver: systemd kubeletCgroups: "/systemd/system.slice" systemCgroups: "" tlsCertFile: "/etc/kubernetes/pki/node.crt" tlsPrivateKeyFile: "/etc/kubernetes/pki/node.key" staticPodPath: /etc/kubernetes/manifests volumePluginDir: "/opt/kubelet/libexec/kubernetes/kubelet-plugins/volume/exec/"  #######################################################  set-thrush-bce3f9-233564 /home/admin # cat /etc/kubernetes/node.kubeconfig apiVersion: v1 kind: Config current-context: default contexts: - context:     cluster: set-thrush-bce3f9     user: system:node:set-thrush-bce3f9-233564   name: default clusters: - cluster:     certificate-authority-data: ***     server: https://ExternalIP:6443     tls-server-name: set-thrush-bce3f9   name: set-thrush-bce3f9 users: - user:     client-certificate-data: ***==     client-key-data: ***   name: system:node:set-thrush-bce3f9-233564 

Хочется обратить внимание на конфигурационный файл kubelet, kubeconfig и файл /opt/kubelet/config.json

KUBELET-CONFIG

mts-kubelet-config
--- kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 authentication:   anonymous:     enabled: false   webhook:     enabled: true   x509:     clientCAFile: "/etc/kubernetes/pki/ca.crt" authorization:   mode: Webhook clusterDomain: "cluster.local" clusterDNS:   - 100.71.0.10 podCIDR: 100.70.0.0/16 runtimeRequestTimeout: "15m" cgroupDriver: systemd kubeletCgroups: "/systemd/system.slice" systemCgroups: "" tlsCertFile: "/etc/kubernetes/pki/node.crt" tlsPrivateKeyFile: "/etc/kubernetes/pki/node.key" staticPodPath: /etc/kubernetes/manifests volumePluginDir: "/opt/kubelet/libexec/kubernetes/kubelet-plugins/volume/exec/" 

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

fr-solutions-kubelet-config
registerNode: true cgroupDriver: "systemd" clusterDomain: "cluster.local" cpuManagerReconcilePeriod: "0s" fileCheckFrequency: "0s" healthzBindAddress: "127.0.0.1" httpCheckFrequency: "0s" imageMinimumGCAge: "0s" memorySwap: {} nodeStatusReportFrequency: "1s" nodeStatusUpdateFrequency: "1s" resolvConf: "/run/systemd/resolve/resolv.conf" runtimeRequestTimeout: "0s" shutdownGracePeriod: "15s" shutdownGracePeriodCriticalPods: "5s" streamingConnectionIdleTimeout: "0s" syncFrequency: "0s" volumeStatsAggPeriod: "0s" containerLogMaxSize: "50Mi" maxPods: 250 kubeAPIQPS: 50 kubeAPIBurst: 100 podPidsLimit: 4096 serializeImagePulls: false rotateCertificates: false serverTLSBootstrap: true tlsMinVersion: "VersionTLS12" evictionPressureTransitionPeriod: "5s"  imageGCHighThresholdPercent: 55 imageGCLowThresholdPercent: 50  authentication:     anonymous:         enabled: false     webhook:         cacheTTL: "0s"         enabled: true  authorization:     mode: "Webhook"     webhook:       cacheAuthorizedTTL:   "0s"       cacheUnauthorizedTTL: "0s"  logging:   flushFrequency: 0   options:     json:          infoBufferSize:  0   verbosity:  0  systemReserved:   ephemeral-storage: "1Gi"   featureGates:   RotateKubeletServerCertificate: true   APIPriorityAndFairness:         true   DownwardAPIHugePages:           true   PodSecurity:                    true   CSIMigrationAWS:                false   CSIMigrationAzureFile:          false   CSIMigrationGCE:                false   CSIMigrationvSphere:            false   tlsCipherSuites:   - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"   - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"   - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"   - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"   - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"   - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"  allowedUnsafeSysctls:   - "net.core.somaxconn"  evictionSoft:   "memory.available":   "3Gi"   "nodefs.available":   "25%"   "nodefs.inodesFree":  "15%"   "imagefs.available":  "30%"   "imagefs.inodesFree": "25%"  evictionSoftGracePeriod:   "memory.available":   "2m30s"   "nodefs.available":   "2m30s"   "nodefs.inodesFree":  "2m30s"   "imagefs.available":  "2m30s"   "imagefs.inodesFree": "2m30s"  evictionHard:   "memory.available":   "2Gi"   "nodefs.available":   "20%"   "nodefs.inodesFree":  "10%"   "imagefs.available":  "25%"   "imagefs.inodesFree": "15%"

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

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

KUBELET-KUBECONFIG

node-kubeconfig
#######################################################  set-thrush-bce3f9-233564 /home/admin # cat /etc/kubernetes/node.kubeconfig apiVersion: v1 kind: Config current-context: default contexts: - context:     cluster: set-thrush-bce3f9     user: system:node:set-thrush-bce3f9-233564   name: default clusters: - cluster:     certificate-authority-data: ***     server: https://ExternalIP:6443     tls-server-name: set-thrush-bce3f9   name: set-thrush-bce3f9 users: - user:     client-certificate-data: ***==     client-key-data: ***   name: system:node:set-thrush-bce3f9-233564

Данный конфигурационный файл дает пищу для размышления.

  • Сертификаты передаются в открытом и нешифрованном виде через ignition config

  • В MTS Cloud, основанной на виртуализации VMWARE, конфигурационные файлы
    ignition хранятся в метаданных виртуализации в виде параметра kwargs, к
    которому могут иметь доступ инженеры

    • *Мы очень надеемся, что приватные ключи Центра Аутентификации (ЦА) не
      передаются вместе с бутстрап-конфигурацией кластера таким образом

  • Поскольку механизм bootstrap-kubeconfig не используется, можно предположить, что инженеры:

    • Используют внешний PKI из-за чего kube-controller-manager не обладает приватным ключом Центра Аутентификации (ЦА) и, следовательно, не может выписывать сертификаты узлам через стандартный механизм CSR APPROVE

    • Не используют данный механизм и разработали собственный метод обновления сертификатов, через ssh под пользователем admin — сервисом containerum@config-manager

  • Сертификаты выписываются на 1год, что по нашему мнению слишком много:

    • В нашей практике мы придерживаемся использования срока действия сертификатов не более одного месяца и регулярно обновляем их каждые две недели

В любом случае, есть куда расти и оптимизировать, так как многие best practice базируются на том, что в мультитенантных окружениях провайдер обеспечивает только стабильность своей области и не пересекает периметр клиента, где может размещаться критическая информация. Для реализации такого подхода рекомендуется использовать pull-модель и четко разделять ответственность между владельцами control-plane и data-plane.

/opt/kubelet/config.json

{"auths":{"registry.resources.cloud.mts.ru":{"username":"containerum-registry-guest","password":"cxqZrnmCy7LK7AQ","auth":"Y29udGFpbmVydW0tcmVnaXN0cnktZ3Vlc3Q6Y3hxWnJubUN5N0xLN0FR"}}} 

Предположим, что эта учетная запись не имеет критического значения для безопасности системы, но ее можно получить, тогда как доступ к registry можно получить только с узлов K8S.

CONTAINERD

Данный инструмент сконфигурирован интересным образом.

containerd bootstrap
####################################################### set-thrush-bce3f9-233564 /home/admin # systemctl status containerd ● containerd.service - containerd container runtime      Loaded: loaded (/run/systemd/system/containerd.service; enabled-runtime; vendor preset: disabled)     Drop-In: /etc/systemd/system/containerd.service.d              └─10-use-custom-config.conf      Active: active (running) since Sat 2023-06-10 18:26:17 UTC; 22h ago        Docs: https://containerd.io     Process: 852 ExecStartPre=mkdir -p /run/docker/libcontainerd (code=exited, status=0/SUCCESS)     Process: 856 ExecStartPre=ln -fs /run/containerd/containerd.sock /run/docker/libcontainerd/docker-containerd.sock (code=exited, status=0/SUCCESS)    Main PID: 857 (containerd)       Tasks: 29      Memory: 142.6M         CPU: 25min 14.223s      CGroup: /system.slice/containerd.service  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/systemd/system/containerd.service.d/10-use-custom-config.conf  [Service] ExecStart= ExecStart=/usr/bin/containerd --config /etc/containerd/config.toml  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/containerd/config.toml version = 2  # persistent data location root = "/var/lib/containerd" # runtime state information state = "/run/containerd" # set containerd as a subreaper on linux when it is not running as PID 1 subreaper = true # set containerd's OOM score oom_score = -999 disabled_plugins = []  # grpc configuration [grpc] address = "/run/containerd/containerd.sock" # socket uid uid = 0 # socket gid gid = 0  [plugins."containerd.runtime.v1.linux"] # shim binary name/path shim = "containerd-shim" # runtime binary name/path runtime = "runc" # do not use a shim when starting containers, saves on memory but # live restore is not supported no_shim = false  [plugins."io.containerd.grpc.v1.cri"] # enable SELinux labeling enable_selinux = true  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] # setting runc.options unsets parent settings runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".registry] # registries mirrors path config_path = "/etc/containerd/certs.d"  ####################################################### set-thrush-bce3f9-233564 /home/admin # ls -al /etc/containerd/certs.d total 36 drwxr-xr-x. 9 root root 4096 Jun 10 17:35 . drwxr-xr-x. 3 root root 4096 Jun 10 17:35 .. drwxr-xr-x. 2 root root 4096 Jun 10 17:35 docker.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 gcr.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 ghcr.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 k8s.gcr.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 quay.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 registry-1.docker.io drwxr-xr-x. 2 root root 4096 Jun 10 17:35 registry.k8s.io  ####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/containerd/certs.d/k8s.gcr.io/hosts.toml  server = "https://k8s.gcr.io"  [host."https://registry.resources.cloud.mts.ru/v2/k8s-gcr-io-proxy"]   override_path = true   capabilities = ["pull", "resolve"]

####################################################### set-thrush-bce3f9-233564 /home/admin # cat /etc/containerd/certs.d/k8s.gcr.io/hosts.toml  server = "https://k8s.gcr.io"  [host."https://registry.resources.cloud.mts.ru/v2/k8s-gcr-io-proxy"]   override_path = true   capabilities = ["pull", "resolve"]

В данной конфигурации осуществляется проксирование основных репозиториев через Nexus-registry от MTS Cloud. Это позволяет получать полезную информацию о используемых образах, их уязвимостях и других статистических данных при правильной настройке и подходе. Однако, в случае недоступности реестра МТS, сборки клиентов станут недоступными.

Как говорится два стула.

MTS cloud-controller

Cloud-controller имеет ряд контроллеров:

  • Node controller

    • Маркировка и аннотирование узла

    • Обогощение ресурса Node информацией полученной из MTS Cloud

    • Проверка работоспособности узла

    • Получение Internal и external ip адресов

  • Route controller

    • Отвечает за правильную настройку маршрутов в облаке

  • Service controller

    • Создание K8S сервиса type=LoadBalancer

Сразу вопросы:

  • Node controller:

  • Route controller:

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

  • Service controller:

    • В данном случае все в порядке, однако некоторое беспокойство вызывает время создания сервиса типа LoadBalancer, которое иногда достигает 15-20 секунд

MTS csi-controller

Поскольку все окружение основано на стеке VMware, рекомендуется использовать нативный провайдер дисков для VMware, что и сделали инженеры MTS.

По умолчанию в MTS K8S имеется 4 класса хранилищ (storage class):

dk@dobry-kot-system:~/$ kubectl get  storageclass NAME                     PROVISIONER              RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE mts-ssd-basic            csi.vsphere.vmware.com   Delete          Immediate           false                  2d23h mts-ssd-fast (default)   csi.vsphere.vmware.com   Delete          Immediate           false                  2d23h mts-ssd-ultra            csi.vsphere.vmware.com   Delete          Immediate           false                  2d23h mts-ssd-ultra-plus       csi.vsphere.vmware.com   Delete          Immediate           false                  2d23h 

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

IAM

MTS обладает значительным опытом в области управления идентификацией и аутентификацией (IAM), однако на данный момент не предоставлены интеграции с Kubernetes (K8S). Мы ожидаем, что в будущем будут предоставлены возможности интеграции для предоставления доступа командам с использованием нативного механизма управления доступом на основе ролей (RBAC), аналогичного тому, что предоставляет Yandex Cloud.

*Т.К не предоставляется возможным изменять конфигурацию kube-apiserver то сделать интеграцию со своим IDP не получится.

IAC

К сожалению, в настоящий момент отсутствует поддержка инструментов IaC, таких как Terraform и Pulumi. Это означает, что всю конфигурацию придется настраивать вручную, без возможности автоматизировать этот процесс.

Reconciliation loop

На момент создания кластера MTS разворачивает базовое окружение внутри K8S кластера:

  • calico

  • kube-state-metrics

  • coredns

  • etc..

Заострять внимание на компонентах не будем, так как неясно, для чего они там существуют. Клиент в любой момент может их удалить, исправить или сломать, и нет никакого механизма защиты от этого со стороны MTS. Если защита отсутствует, то скорее всего MTS не отвечают за эти компоненты и не помогут, если они сломаются. По моему мнению, лучше предоставить пустой кластер или написать собственный контроллер, который будет поддерживать актуальное состояние управляемых компонентов и их конфигурационных файлов.

Вывод

После проведения первичного анализа, мы хотим отметить значительную работу, проделанную командой инженеров MTS при разработке своего продукта. Несмотря на то, что данный продукт является относительно новым и требует некоторой доработки, он уже функционирует и закрывает базовые потребности.

Лично нам продукт не подходит т.к отсутствуют необходимые инструменты взаимодействия, такие как поддержка terraform providers, механизмы изменения Feature Gates или хотя бы чтения установленных. Кроме того, в перспективе мы надеемся на наличие модифицированной конфигурации kubelet, так как при определенных нагрузках на узлы клиенты могут столкнуться с проблемами при использовании текущей конфигурации.

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

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

Контакты

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

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


ссылка на оригинал статьи https://habr.com/ru/articles/741178/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *