Всем привет. Меня зовут Путилин Дмитрий (Добрый Кот) Telegram.
От коллектива FR-Solutions : Продолжаем серию статей о K8S.
Наша команда получила запрос на оценку managed K8S от MTS Cloud и составление объективного обзора проделанной работы инженеров МТС. Хочу отметить, что данная статья не является заказной, поэтому мы сосредоточимся на объективном анализе плюсов и минусов этого решения.
Регистрация
Перед началом работы с облаком требуется пройти процесс регистрации. Замечательной особенностью является возможность входа по номеру телефона. Если у вас есть номер от МТС, вся ваша информация будет автоматически подтянута.
Первоначальная авторизация
При первом входе на страницу вы увидите следующую панель с доступными услугами.
Хотим отметить, что явно присутствует недоработка на данной странице. Проблема заключается в том, что при первом входе вероятно выполняется операция создания рабочей области, и до тех пор, пока она не будет создана, невозможно создать какой-либо ресурс. Поэтому при выборе любой услуги вы увидите пустое окно, как показано на скриншоте выше. Было бы логично отображать информацию о создании области и сообщать, что в ближайшее время вы сможете приступить к работе с ней.
Создание кластера K8S
Чтобы создать кластер K8S, вам необходимо выбрать услугу "Containerum Kubernetes" и нажать кнопку "Добавить".
Однако параметры модификации кластера оказываются довольно ограниченными:
имя кластера
зоны доступности (Москва/Владивосток)
сеть для нод
сеть для подов
версия кластера
single master / HA (вид отказоустойчивости)
описание группы нод (воркеры)
плагины
После выбора необходимой конфигурации вы нажимаете кнопку "Создать" и ожидаете создания кластера.
Сеть
Перед тем, как приступить к выполнению любых задач, вам потребуется настроить сеть. В МТС Облаке для этого доступны ресурсы: Виртуальная частная сеть (VPC) и подсети.
Выражаем свое беспокойство относительно полосы пропускания в 100 Мбит на выходе (не проводили тестирование скорости между узлами).
Созданную подсеть можем указать базовой для наших будущих узлов кластера. Адресация будет выдана по DHCP.
Если речь идет о нодах, то ситуация в целом понятна. Однако, когда дело касается подов, возникают некоторые проблемы. Все решение рассчитано на использование оверлейной сети для контейнеров, что может привести к задержкам (летенси) и уменьшает гибкость доступа от контейнеров до внешних узлов.
Использование SNAT на адрес ноды может затруднить проведение аудита сетевой безопасности, так как необходимо иметь возможность четко отслеживать, какие конкретно запросы отправляются и откуда, так же может затруднить идентификацию точного отправителя в определенный момент времени. Это может создавать проблемы при анализе и мониторинге сетевых активностей для целей безопасности.
Masters
Поскольку мы не имеем доступа к конфигурации кластера из-за ограничений в инфраструктуре, мы можем полагаться на дедукцию и внешние факторы для нашей оценки.
Мастер-ноды Kubernetes разворачиваются в виртуальной частной сети (VPC) пользователя (*проверяется через
kubectl get endpoints -n default kubernetes
там будет отображен список IP от мастер нод)При создании кластера пользователь указывает базовую подсеть нод, в которой будут развернуты мастер-ноды.
Балансировщик нагрузки кластера ведет на мастера и может иметь либо внутреннюю адресацию, либо внешнюю.
Догадки:
OC Flatcar
Для control-plane и data-plane нод не создаются предварительно настроенные образы (Golden Images) - вся настройка производится через cloud-init.
Для выдачи сертификатов вероятно используется инструмент, подобный Vault или аналогичная центральная служба аутентификации (ЦА).
-
На борту системы имеется три пользователя, которые могут получить доступ к системе через SSH:
core (не используется, пароля нет, ssh ключа нет)
root (не используется, пароля нет, ssh ключа нет)
-
admin - с доступом по ssh через ключи типа ssh-ed25519
через него подключается containerum@config-manager
-
Вся конфигурация передается с использованием файлов Ignition config:
сертификаты (private/public ключи)
конфигурационные файлы
для скачивания необходимых бинарных файлов в систему используются триггер-сервисы, которые управляются через зависимости 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:
-
Почему internal и external ip адреса совпадают?
INTERNAL-IP EXTERNAL-IP
10.0.10.5 10.0.10.5
-
Какие availability-zones еще существуют в регионе Москва?
-
-
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 me: https://t.me/Dobry_kot
Комментарии (5)
deepblack
26.06.2023 19:31Замечательной особенностью является возможность входа по номеру телефона.
Вот человек зарегистрировался, закинул денег на счет на год вперед, развернул проект, спустя пол-года поменял номер телефона. При этом доступа к старому номеру нет.
Понимаю что вопрос не к вам, ноКак в такой ситуации восстановить доступ?
В последнее время наблюдаю тенденцию что многие российские сервисы внедрили возможность входа по номеру телефона, при этом удалив возможность войти по email и паролю.
Из недавнего был случай
Из недавнего был случай с Додо Пиццей (Dodo Engineering): не найдя ни на сайте ни в приложении возможности изменить номер (имея залогиненую на старый номер учетку в приложении) обратился в техподдержку с просьбой сменить номер привязанный в личном кабинете (при этом указал что нет доступа к старому номеру телефона, но есть доступ к почте указанной в учетной записе). На что получил ответ что такой возможности нет и прийдется заводить новую учетную запись с нуля на новый номер. Очень клиентоориентированно, учитывая что на старую учетку они слали промокоды со скидкой (при этом сам промокод можно активировать только на той учетной записи на email которой он высылался).
dobry-kot Автор
26.06.2023 19:31На самом деле очень интересный вопрос, что является ID клиента у МТС.
Если использовать номер телефона МТС вроде все прозрачно по идеи должен быть внешний ID пользователя и к нему цепляют телефоны, если использовать внешние ну тут как с почтой даже хуже, если неиспользуется и перешел другому человеку тогда и доступ к ресурсам появится... . В любом случае почта наше все)
dobry-kot Автор
Будем очень признательны если опишите в комментариях, что именно понравилось или не понравилось в статье и как бы мы ее могли улучшить.