# Оглавление - [Введение](#введение) - [Что такое Talos OS](#что-такое-talos-os) - [Подготовка к развороту кластера](#подготовка-к-развороту-кластера) - [Подготовка schematic.yaml для генерации образа](#подготовка-schematicyaml-для-генерации-образа-через-публичныйприватный-image-factory) - [Отправка schematic.yaml, получение и скачивание образа](#отправка-schematicyaml-в-сторону-image-factory-получение-id-образа-и-скачивание-образа) - [Подготовка виртуальных машин](#подготовка-виртуальных-машин) - [Сборка кластера](#сборка-кластера) - [Генерация конфига кластера](#генерация-конфига-кластера) - [Патчи machineconfig для узлов кластера](#патчи-machineconfig-для-узлов-кластера) - [Применение конфигурации к узлам кластера](#применение-конфигурации-к-узлам-кластера) - [Сброс кластера](#сброс-кластера) # Введение ## Что такое Talos OS Talos Linux — минималистичный immutable-дистрибутив, спроектированный исключительно для запуска Kubernetes. Talos не имеет SSH, интерактивного шелла и пакетного менеджера — вся конфигурация узла и управление им происходят декларативно через API (`talosctl`) и файл `machineconfig`. ##### Ключевые особенности в сравнении с классическим разворотом кластера (kubeadm/ansible/kubespray поверх Ubuntu/Debian/RHEL): - Управление узлом только через API поверх mTLS, нет SSH и шелла - меньшая поверхность атаки - Конфигурация декларативная (`machineconfig` YAML), применяется атомарно, а не пошагово скриптами/ролями - Обновления ОС и компонентов кластера (etcd, kubelet, kube-apiserver) атомарные, по схеме A/B, с возможностью отката одной командой - Дополнительный функционал ОС подключается через System Extensions, встроенные в образ на этапе сборки (см. ниже), а не через установку пакетов после разворота - Конфигурация - единственный источник истины: узел либо соответствует заданному `machineconfig`, либо нет, что снижает риск конфигурационного дрейфа Именно из-за этой модели первым шагом идёт сборка кастомного образа через Image Factory: дополнительные компоненты уровня ОС (iscsi, nfs, qemu-guest-agent и т.д.) нельзя доустановить после разворота - они должны быть встроены в образ заранее. # Подготовка к развороту кластера #### Требуемые инструменты Для выполнения команд из этого документа потребуются установленные `talosctl` ([инструкция по установке](https://www.talos.dev/latest/talos-guides/install/talosctl/)), `kubectl` и `helm`. ##### Про пути в командах: Все команды в этом документе выполнялись из директории `examples/` - именно там лежат `schematics/`, `patches/`, `test-cluster/`, `images/` и `cilium-values.yaml`. Перед копированием команд нужно перейти в эту директорию (`cd examples`). ## Подготовка schematic.yaml для генерации образа через публичный/приватный Image Factory ```yaml customization: systemExtensions: officialExtensions: - siderolabs/iscsi-tools - siderolabs/nfs-utils - siderolabs/qemu-guest-agent - siderolabs/util-linux-tools extraKernelArgs: - net.ifnames=0 ``` ##### В образ добавляются расширения: - `siderolabs/iscsi-tools` - утилиты для работы с сетевыми дисками по протоколу iscsi - `siderolabs/nfs-utils` - утилиты для монтирования фс по протоколу nfs - `siderolabs/qemu-guest-agent` - гостевой агент для виртуальных машин, запущенных в среде QEMU/KVM (тестовый кластер разворачивается в Proxmox VE) - `siderolabs/util-linux-tools` - набор низкоуровневых утилит Linux, нужен для диагностики и для некоторых CSI драйверов ##### Дополнительные аргументы ядра: - `net.ifnames=0` - отключает predictable naming сетевых интерфейсов (имена вида `enp6s18`), интерфейсы получают классические имена `eth0`, `eth1` и т.д. ## Отправка schematic.yaml в сторону Image Factory, получение ID образа и скачивание образа #### Следующая команда отправляет файл в сторону Image Factory: `curl -X POST --data-binary @schematics/schematic.yaml https://factory.talos.dev/schematics` - `--data-binary @schematics/schematic.yaml` - передача файла; в данном случае файл размещён в директории для удобства, но может быть размещён и в корне проекта - `https://factory.talos.dev/schematics` - URL публичного Image Factory ##### В ответ прилетит JSON с ID образа и информацией об установленных расширениях: ```json { "id": "e142ceb080fb243141b5b6891cfcf0c60bc9430d69be0adf803999d2b62dc885", "schematic": "customization:\n extraKernelArgs:\n - net.ifnames=0\n systemExtensions:\n officialExtensions:\n - siderolabs/iscsi-tools\n - siderolabs/nfs-utils\n - siderolabs/qemu-guest-agent\n - siderolabs/util-linux-tools\n" } ``` ##### Скачать образ можно командой: `curl -L -o images/metal-amd64.iso "https://factory.talos.dev/image/e142ceb080fb243141b5b6891cfcf0c60bc9430d69be0adf803999d2b62dc885/v1.13.7/metal-amd64.iso"` - `e142ceb080fb243141b5b6891cfcf0c60bc9430d69be0adf803999d2b62dc885` - ID, полученный в ответе ранее - `metal-amd64.iso` - образ для bare metal и виртуальных машин без поддержки cloud-init ## Подготовка виртуальных машин #### Будет развернут кластер следующего вида: - 3 мастера: 1vcpu, 2G ram, 15G ssd - 3 воркера с доп диском под данные: 3vcpu, 6G ram, 15G + 30G ssd - 3 воркера без доп дисков: 3vcpu, 6G ram, 15G ssd ##### Для мастеров будут закреплены IP: - `10.255.200.201` - `10.255.200.202` - `10.255.200.203` ##### Для воркеров будут закреплены IP: - `10.255.200.204` - `10.255.200.205` - `10.255.200.206` - `10.255.200.207` - `10.255.200.208` - `10.255.200.209` ##### Скрин со списком виртуальных машин: ![vm](/img/pve-vms.png) ##### Скрин с настройками статики для сети в maintenance mode: ![net](/img/talos-net.png) По аналогии настройки сети нужно провести для всех виртуальных машин. # Сборка кластера Сейчас узлы запущены в maintenance mode из iso образа и для первичной заливки machineconfig нужно в явном виде указать флаг `--insecure`. ##### Про флаг `--insecure`: Он нужен только для самой первой отправки machineconfig - на этом этапе узел ещё не имеет сертификатов и не может поднять mTLS-соединение с `talosctl`. После применения конфигурации узел переходит в защищённый режим, и все дальнейшие обращения к API идут только по mTLS с использованием сертификата из `talosconfig`. ## Генерация конфига кластера #### Перед генерацией конфига отдельно генерируем bundle с секретами кластера (сертификаты, токены): `talosctl gen secrets -o test-cluster/secrets.yaml` Секреты вынесены в отдельный файл специально: `controlplane.yaml`, `worker.yaml` и `talosconfig` можно пересоздавать сколько угодно раз (например, при смене эндпоинта или структуры патчей) на основе одного и того же `secrets.yaml`, не перевыпуская сертификаты и токены и не теряя доступ к уже развернутому кластеру. `talosctl gen config test-cluster https://10.255.200.201:6443 -o ./test-cluster --with-secrets test-cluster/secrets.yaml` - `talosctl gen config` - команда генерации конфига - `test-cluster` - имя кластера - `https://10.255.200.201:6443` - эндпоинт, в данном случае первый мастер (может быть адрес/домен балансировщика) - `-o ./test-cluster` - сохранение конфигов для доступа к кластеру - `--with-secrets test-cluster/secrets.yaml` - использовать ранее сгенерированный bundle секретов вместо генерации нового ##### Пример выполнения команды: ``` generating PKI and tokens Created test-cluster/controlplane.yaml Created test-cluster/worker.yaml Created test-cluster/talosconfig ``` - `test-cluster/talosconfig` - конфиг с секретом для управления узлами после бутстрапа - `test-cluster/controlplane.yaml` - конфигурация для мастер узлов - `test-cluster/worker.yaml` - конфигурация для воркер узлов ##### Про хранение секретов: - `test-cluster/secrets.yaml` - самый чувствительный файл во всей связке: в нём лежат корневые сертификаты и токены, из которых выводится всё остальное (`talosconfig`, machineconfig узлов). Его нужно хранить в надёжном месте (менеджер секретов/зашифрованное хранилище) и не коммитить в git в открытом виде - `test-cluster/talosconfig` и весь каталог `test-cluster/` также стоит сохранить - без `secrets.yaml` повторная генерация конфига перевыпустит все сертификаты и токены заново, и доступ к уже развернутому кластеру по старому `talosconfig` будет потерян ## Патчи machineconfig для узлов кластера ### Общий патч для установки ОС на диск: ```yaml machine: install: disk: /dev/sda image: factory.talos.dev/installer/e142ceb080fb243141b5b6891cfcf0c60bc9430d69be0adf803999d2b62dc885:v1.13.7 ``` #### Патч указывает на образ, который будет установлен на диск `/dev/sda` ### Общие патчи для мастер- и воркер-нод с зависимостью от дополнительного диска: - #### patch-controlplane.yaml ```yaml machine: network: kubespan: enabled: true mtu: 1420 advertiseKubernetesNetworks: false cluster: discovery: enabled: true network: cni: name: none proxy: disabled: true ``` - #### patch-worker-with-disk.yaml ```yaml machine: kernel: modules: - name: iscsi_tcp disks: - device: /dev/sdb partitions: - mountpoint: /var/lib/longhorn kubelet: extraMounts: - destination: /var/lib/longhorn type: bind source: /var/lib/longhorn options: - bind - rshared - rw network: kubespan: enabled: true mtu: 1420 advertiseKubernetesNetworks: false cluster: discovery: enabled: true network: cni: name: none proxy: disabled: true ``` - #### patch-worker-without-disk.yaml ```yaml machine: network: kubespan: enabled: true mtu: 1420 advertiseKubernetesNetworks: false cluster: discovery: enabled: true network: cni: name: none proxy: disabled: true ``` #### В патчах для мастер- и воркер-нод заданы настройки для: - Kubespan - настройка wireguard mesh сети между узлами кластера - Отключение kube-proxy и установки дефолтного CNI (Flannel) - Для нод с доп диском дополнительно загружается модуль ядра `iscsi_tcp` - он нужен Longhorn для подключения томов по iSCSI - Для нод с доп диском описано монтирование доп диска и проброс его в контейнер kubelet для корректной работы - Точка монтирования `/var/lib/longhorn` подготовлена под будущую установку Longhorn CSI; установка и настройка Longhorn описаны в отдельном документе - [README_LONGHORN.md](README_LONGHORN.md) ### Патч для настроек сети - в качестве примера показан только для одного из мастеров, по аналогии такие патчи сделаны для всех узлов ```yaml machine: network: interfaces: - deviceSelector: hardwareAddr: "bc:24:11:80:a1:9b" addresses: - 10.255.200.201/24 routes: - network: 0.0.0.0/0 gateway: 10.255.200.1 dhcp: false nameservers: - 9.9.9.9 ``` Интерфейс выбирается через `deviceSelector` по MAC-адресу (`hardwareAddr`), а не по имени (`eth0`) - привязка к MAC не зависит от порядка обнаружения интерфейсов и не сломается при добавлении/замене сетевых карт. MAC-адрес каждой виртуальной машины можно посмотреть в настройках сетевого устройства в Proxmox VE. ##### Получение MAC-адреса через talosctl: Пока узел работает в maintenance mode, MAC-адреса его интерфейсов можно узнать напрямую через API Talos (столбец `HW ADDR` в выводе): ```sh talosctl get links -n 10.255.200.201 --insecure ``` На уже настроенном узле команда та же, но без `--insecure` и с указанием эндпоинта: ```sh talosctl get links -n 10.255.200.201 -e 10.255.200.201 ``` Вывод содержит все интерфейсы, включая служебные (`lo`, `kubespan`, `siderolink` и т.д.) - нужен физический интерфейс типа `ether` (обычно `eth0`). ## Применение конфигурации к узлам кластера #### Экспорт переменной TALOSCONFIG для работы с talosctl: `export TALOSCONFIG=$(pwd)/test-cluster/talosconfig` ### Применение machineconfig для всех узлов кластера с патчами ```sh talosctl apply-config \ --insecure -n 10.255.200.201 \ --file ./test-cluster/controlplane.yaml \ --config-patch @patches/patch-install.yaml \ --config-patch @patches/patch-controlplane.yaml \ --config-patch @patches/patch-net-master-1.yaml ``` #### Остальные узлы по аналогии, нужно только указать соответствующие узлу и роли патчи #### После применения machineconfig нужно выполнить bootstrap на первом мастере, адрес которого был указан при инициализации конфига `talosctl bootstrap -n 10.255.200.201 -e 10.255.200.201` #### Проверить, что кластер подает признаки жизни командами ```sh talosctl etcd members -n 10.255.200.201 -e 10.255.200.201,10.255.200.202,10.255.200.203 talosctl health -n 10.255.200.201 -e 10.255.200.201,10.255.200.202,10.255.200.203 talosctl get members -n 10.255.200.201 -e 10.255.200.201,10.255.200.202,10.255.200.203 ``` ##### Про флаг `-e`: Указывает конечные точки API Talos, к которым обращается `talosctl`. Для отказоустойчивости стоит перечислять все мастера через запятую (как в примерах выше) либо использовать адрес балансировщика/VIP перед мастерами - тогда потеря одного мастера не блокирует управление кластером. #### Получить и добавить в переменную kubeconfig: ```sh talosctl kubeconfig ./kubeconfig -n 10.255.200.201 -e 10.255.200.201,10.255.200.202,10.255.200.203 export KUBECONFIG=$(pwd)/kubeconfig ``` ### Установка CNI cilium в кластер через helm #### cilium-values.yaml ```yaml ipam: mode: kubernetes routingMode: tunnel tunnelProtocol: vxlan autoDirectNodeRoutes: false kubeProxyReplacement: true k8sServiceHost: localhost k8sServicePort: 7445 bpf: masquerade: true cgroup: autoMount: enabled: false hostRoot: /sys/fs/cgroup securityContext: capabilities: ciliumAgent: - CHOWN - KILL - NET_ADMIN - NET_RAW - IPC_LOCK - SYS_ADMIN - SYS_RESOURCE - DAC_OVERRIDE - FOWNER - SETGID - SETUID cleanCiliumState: - NET_ADMIN - SYS_ADMIN - SYS_RESOURCE hubble: enabled: true relay: enabled: true ui: enabled: true MTU: 1370 ``` ##### Ключевые моменты конфигурации: - `routingMode: tunnel` + `tunnelProtocol: vxlan` - трафик между подами инкапсулируется в VXLAN - `kubeProxyReplacement: true` с `k8sServiceHost: localhost` и `k8sServicePort: 7445` - cilium заменяет kube-proxy (он отключен в патчах) и обращается к kube-apiserver через локальный KubePrism-балансировщик Talos на порту 7445 - `cgroup.autoMount.enabled: false` - Talos уже монтирует cgroup fs, повторное монтирование не требуется - `MTU: 1370` - MTU Kubespan (1420) минус накладные расходы VXLAN-инкапсуляции (50 байт) #### Подключение репозитория helm для cilium и установка CNI: ```sh helm repo add cilium https://helm.cilium.io/ helm repo update cilium helm install cilium cilium/cilium --version 1.19.6 --namespace kube-system -f cilium-values.yaml ``` #### Проверить доступность узлов кластера: ```sh kubectl get node ``` #### Доступ к Hubble UI: В `cilium-values.yaml` включены Hubble, Hubble Relay и Hubble UI (`hubble.enabled`, `hubble.relay.enabled`, `hubble.ui.enabled`) - web-интерфейс для наблюдения за сетевыми потоками между подами. Наружу UI не опубликован; для доступа можно пробросить порт: ```sh kubectl -n kube-system port-forward svc/hubble-ui 12000:80 ``` После этого UI доступен на `http://localhost:12000` - в нём видна карта сервисов и сетевые потоки в реальном времени с вердиктами (forwarded/dropped). ## Сброс кластера ##### Внимание: операция необратима и стирает данные на диске узла, включая установленную ОС и все данные приложений (в т.ч. на дисках под Longhorn). #### Если нужно вернуть узел(ы) обратно в maintenance mode и стереть данные: ```sh talosctl reset -n 10.255.200.201 -e 10.255.200.201 --graceful=false --reboot ``` - `--graceful=false` - пропустить graceful-выход из etcd/кластера (нужно, если кластер уже неработоспособен) - `--reboot` - перезагрузить узел после сброса, чтобы он снова загрузился в maintenance mode Команду нужно выполнить отдельно для каждого узла кластера, который требуется сбросить - за один вызов сбрасывается только узел, указанный в `-n`.