Использование Talm для инициализации кластера Cozystack

talm — декларативный CLI-инструмент, созданный разработчиками Cozystack и оптимизированный для развертывания Cozystack.
Рекомендуется для infrastructure-as-code и GitOps.

В этом руководстве описано, как установить и настроить Kubernetes в кластере Talos Linux с помощью Talm. После выполнения этого руководства у вас будет кластер Kubernetes, готовый к установке Cozystack.

Talm — Helm-подобная утилита для декларативного управления конфигурацией Talos Linux. Talm был создан Ænix, чтобы сделать конфигурации управления кластером более декларативными и настраиваемыми. Talm поставляется с готовыми пресетами для Cozystack.

Предварительные требования

К началу работы с этим руководством Talos Linux должен быть установлен на нескольких узлах, но еще не инициализирован (bootstrapped). Эти узлы должны находиться в одной подсети или иметь публичные IP-адреса.

В руководстве используется пример, где узлы кластера находятся в подсети 192.168.123.0/24 и имеют следующие IP-адреса:

  • node1: private 192.168.123.11 or public 12.34.56.101.
  • node2: private 192.168.123.12 or public 12.34.56.102.
  • node3: private 192.168.123.13 or public 12.34.56.103.

Публичные IP-адреса необязательны. Для установки с Talm нужен только доступ к узлам: напрямую, через VPN, bastion host или другим способом. В примерах этого руководства по умолчанию используются private IP, а public IP используются в инструкциях и примерах, относящихся к конфигурации с public IP.

Если вы используете DHCP, вы можете не знать IP-адреса, назначенные узлам в private subnet. Узлы с Talos Linux открывают Talos API на порту 50000. Чтобы найти их, можно использовать nmap, указав маску сети (192.168.123.0/24 в примере):

nmap -Pn -n -p 50000 192.168.123.0/24 -vv | grep 'Discovered'

Пример вывода:

Discovered open port 50000/tcp on 192.168.123.11
Discovered open port 50000/tcp on 192.168.123.12
Discovered open port 50000/tcp on 192.168.123.13

1. Установка зависимостей

Для этого руководства нужно установить несколько инструментов:

2. Инициализация конфигурации кластера

Первый шаг — инициализировать шаблоны конфигурации и указать значения для шаблонизации.

2.1 Инициализация конфигурации

Начните с инициализации конфигурации для нового кластера, используя preset cozystack:

mkdir -p cozystack-cluster
cd cozystack-cluster
talm init --preset cozystack --name mycluster

Структура проекта в основном повторяет обычный Helm chart:

  • charts - каталог с общим library chart, содержащим функции для запроса информации из Talos Linux.
  • Chart.yaml - файл с общей информацией о проекте; имя chart используется как имя создаваемого кластера.
  • templates - каталог для описания шаблонов генерации конфигурации.
  • secrets.yaml - файл с secrets вашего кластера.
  • secrets.encrypted.yaml, talosconfig.encrypted — зашифрованные копии, создаваемые из talm.key (коммитьте в git именно их, а не файлы в открытом виде).
  • talm.key — локальный для проекта age-ключ, используемый для шифрования / расшифровки. Сделайте его резервную копию; без него зашифрованные файлы нельзя будет открыть.
  • values.yaml - общий values-файл для передачи параметров в шаблоны.
  • nodes - необязательный каталог для описания и хранения сгенерированной конфигурации узлов.

Доступные пресеты

talm поставляется с двумя встроенными пресетами:

  • cozystack — production-пресет, используемый в этом руководстве.
  • talm — минимальный library chart для продвинутых пользователей, желающих построить собственный пресет поверх него.

Имя пресета передаётся через -p / --preset.

Справочник флагов talm init

Каноничный список см. по talm init -h. Сгруппировано по режимам:

Создание нового проекта (режим по умолчанию):

  • -p, --preset <name> — пресет для генерации файлов.
  • -N, --name <cluster-name> — имя кластера.
  • --endpoints <list> — Talos API endpoints (через запятую), встраиваемые в talosconfig.contexts.<name>.endpoints для клиента talosctl. См. «Флаги endpoint: клиент talosctl против control plane Kubernetes» ниже.
  • --cluster-endpoint <url> — URL control-plane Kubernetes, записываемый в values.yaml::endpoint (например, https://<vip>:6443). При init проверяется на наличие scheme + host + port.
  • --image <ref> — переопределить образ установщика Talos, записываемый в values.yaml пресета (например, factory.talos.dev/installer/<sha256>:<version>).
  • --talos-version <ver> — желаемая contract-версия Talos для шаблонизации с обратной совместимостью (например, v1.12).
  • --force — перезаписывать существующие файлы без запроса.
Флаги endpoint: клиент talosctl против control plane Kubernetes

В проектах talm слово «endpoint» обозначает две разные сущности:

  • talosconfig.contexts.<name>.endpoints — список записей host[:port], которые клиент talosctl использует для доступа к Talos API. Заполняется флагом --endpoints (множественное число, список через запятую).
  • values.yaml::endpoint — один URL со scheme + host + port, который чарт подставляет в cluster.controlPlane.endpoint в MachineConfig каждого узла. Именно к нему обращаются kubelet и kube-proxy. Заполняется флагом --cluster-endpoint (единственное число, полный URL).

Когда --endpoints задан ровно с одним значением, init автоматически выводит values.yaml::endpoint как https://<это>:6443, потому что случай с единственной целью однозначен. При нескольких endpoints автоматический вывод не выполняется (выбор одного узла молча привязал бы доступность кластера к нему) — задайте --cluster-endpoint явно или заполните values.yaml::endpoint позже вручную. В конце init выводит подсказку, если поле осталось пустым.

Обновление существующего проекта до последнего встроенного library chart:

  • -u, --update — заново извлечь charts/talm/ и другие файлы пресета из бинарника talm. --preset обязателен; --name — нет.
  • --force — автоматически принимать все diff шаблонов пресета (пропустить интерактивный запрос; безопасно использовать в CI).

--update перезаписывает только файлы, поставляемые пресетом; ваши изменения в values.yaml, secrets.yaml, templates/ и nodes/ сохраняются.

Управление зашифрованными secrets на месте:

  • -e, --encrypt — зашифровать secrets.yaml / talosconfig / kubeconfig в их .encrypted-копии. Требует talm.key.
  • -d, --decrypt — обратная операция. Не требует --preset или --name.

Обновление до новой версии Talm

Когда новая версия talm поставляется с более новым встроенным library chart, обновите проект на месте:

cd cozystack-cluster
talm init --update --preset cozystack          # интерактивно: запрашивает по каждому diff шаблона пресета
talm init --update --preset cozystack --force  # неинтерактивно: автоматически принять все diff

Цикл шифрования / расшифровки

В git вы коммитите зашифрованные копии, а talm читает копии в открытом виде. Для перехода между ними используйте:

talm init --encrypt   # secrets.yaml -> secrets.encrypted.yaml; talosconfig -> talosconfig.encrypted
talm init --decrypt   # обратная операция — не требует --preset или --name

Если потерять файл talm.key, зашифрованные копии станут нечитаемыми, поэтому храните резервную копию ключа отдельно. Когда talm init --decrypt запускается в проекте без talm.key, talm показывает оба пути восстановления в подсказке ошибки: восстановить сохранённый ключ или заново выполнить talm init для регенерации (с явным предупреждением, что регенерация записывает новые secrets, из-за чего старый secrets.encrypted.yaml нельзя будет расшифровать без исходного ключа).

2.2. Редактирование значений конфигурации и шаблонов

Сила Talm — в шаблонизации. Есть несколько файлов с исходными значениями и шаблонами, которые можно редактировать: Chart.yaml, values.yaml и templates/*. Talm использует эти значения и шаблоны для генерации конфигурации Talos для всех узлов кластера: и control plane, и workers.

Все часто изменяемые значения конфигурации находятся в values.yaml:

## Используется для доступа к control plane кластера
endpoint: "https://192.168.100.10:6443"
## Домен кластера Cozystack API — используется сервисами и K8s-кластерами tenant'ов для доступа к управляющему кластеру
clusterDomain: cozy.local
## Floating IP — должен быть неиспользуемым IP-адресом в той же подсети, что и узлы
floatingIP: 192.168.100.10
## Исходный образ Talos: используйте последнюю доступную версию
## https://github.com/cozystack/cozystack/pkgs/container/cozystack%2Ftalos
image: "ghcr.io/cozystack/cozystack/talos:v1.13.0"
## Подсеть Pod'ов — используется для назначения IP-адресов pod'ам
podSubnets:
- 10.244.0.0/16
## Подсеть сервисов — используется для назначения IP-адресов сервисам
serviceSubnets:
- 10.96.0.0/16
## Подсеть с IP-адресами узлов
advertisedSubnets:
- 192.168.100.0/24
## Добавьте URL OIDC issuer, чтобы включить OIDC — см. комментарии ниже.
oidcIssuerUrl: ""
certSANs: []

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

Расширение формируемой конфигурации Talos (Talm v0.30+)

Пресет cozystack поставляется с подобранными значениями по умолчанию для machine.kernel.modules, machine.sysctls, machine.kubelet.extraConfig и machine.files. Операторам, желающим дополнить любой из них без форка чарта, доступны четыре ключа values extra*:

КлючТипСемантика в пресете cozystack
extraKernelModuleslistДобавляется к встроенным модулям (openvswitch, drbd, zfs, spl, vfio_pci, vfio_iommu_type1). Каждый элемент — spec kernel-модуля Talos.
extraKubeletExtraArgsmapОбъединяется с kubelet.extraConfig после заданных пресетом cpuManagerPolicy: static, maxPods: 512. Ключи оператора НЕ должны конфликтовать со встроенными — yaml.v3 отвергает дублирующиеся ключи map при декодировании, поэтому конфликт валит render с точной подсказкой на проблемный ключ. Если нужно другое значение по умолчанию — форкните пресет.
extraSysctlsmapОбъединяется с machine.sysctls после встроенных записей пресета: размеры ARP-кэша gc_thresh1/2/3, всегда включённый тюнинг DRBD/LINSTOR (tcp_orphan_retries, tcp_fin_timeout, netdev_max_backlog, netdev_budget, netdev_budget_usecs), vm.nr_hugepages (когда задан) и тройка tcp_keepalive_*, пока включён tcpKeepaliveTuning. Все они принадлежат пресету — действует тот же контракт «конфликт валит render», что и для extraKubeletExtraArgs. Значения должны быть строками YAML (Talos ожидает строки даже для числовых sysctls).
extraMachineFileslistДобавляется к записям пресета для настройки CRI и lvm.conf. Talos отвергает дублирующиеся path: при применении.

Пример дополнения values.yaml:

extraKernelModules:
  - name: nf_conntrack
extraKubeletExtraArgs:
  feature-gates: "NodeSwap=true"
extraSysctls:
  net.core.somaxconn: "65535"
extraMachineFiles:
  - path: /etc/example.conf
    op: create
    content: "hello = world"

Пресет generic не поставляет значений по умолчанию ни в одной из этих секций — каждый блок формируется только когда соответствующий ключ extra* непуст.

Помимо точек расширения extra*, пресет cozystack предоставляет два преднастроенных параметра, которые можно менять без форка чарта:

КлючПо умолчаниюЭффект
tcpKeepaliveTuningfalseКогда true, добавляет net.ipv4.tcp_keepalive_time=600 / intvl=10 / probes=6 в machine.sysctls, освобождая «мёртвый» простаивающий сокет примерно за 660 с вместо стандартных для ядра ~2 ч. Эти sysctls действуют на всё ядро — они меняют обнаружение сбоев для каждого долгоживущего простаивающего TCP-соединения на узле, а не только для DRBD, — поэтому включаются по желанию. DRBD и так обнаруживает мёртвых пиров за секунды через собственный ping на уровне протокола, поэтому оставляйте выключенным, если вам специально не нужно более быстрое обнаружение мёртвых сокетов на всём узле.
etcd.quotaBackendBytes"8589934592" (8 ГиБ)Потолок размера backend-БД etcd, выставляемый как cluster.etcd.extraArgs.quota-backend-bytes только на узлах controlplane. Поднимает собственное значение etcd по умолчанию в 2 ГиБ, чтобы control plane с большим количеством LINSTOR, суммарно хранящий множество CRD DRBD-ресурсов, не срабатывал по alarm NOSPACE. Это потолок, а не резервирование: небольшая БД остаётся небольшой и не требует дополнительных RAM/диска. Установите "", чтобы вернуться к встроенному значению etcd по умолчанию. Управляет общим размером БД, а не размером отдельного объекта — записи по объектам ограничены фиксированным лимитом тела запроса kube-apiserver в 3 МиБ, у которого нет параметра конфигурации.

Пять всегда включённых sysctls DRBD/LINSTOR, перечисленных в строке extraSysctls выше, поставляются безусловно в пресете cozystack — они устраняют исчерпание TCP-портов, наблюдаемое при штормах переподключений DRBD, и не имеют аналога в пресете generic.

2.3 Добавление конфигурации Keycloak

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

Чтобы настроить Keycloak как OIDC-провайдера, внесите следующие изменения в шаблоны:

  • Для Talm v0.6.6 или новее: в ./templates/_helpers.tpl замените keycloak.example.com на keycloak.<your-domain.tld>.

  • Для Talm старше v0.6.6 обновите ./templates/_helpers.tpl следующим образом:

     cluster:
       apiServer:
         extraArgs:
           oidc-issuer-url: "https://keycloak.example.com/realms/cozy"
           oidc-client-id: "kubernetes"
           oidc-username-claim: "preferred_username"
           oidc-groups-claim: "groups"
    

3. Генерация конфигурационных файлов узлов

Следующий шаг — создать конфигурационные файлы узлов из шаблонов. Создайте каталог nodes и соберите информацию с каждого узла в отдельный файл для этого узла:

mkdir nodes
talm template -e 192.168.123.11 --nodes 192.168.123.11 -t templates/controlplane.yaml -i > nodes/node1.yaml
talm template -e 192.168.123.12 --nodes 192.168.123.12 -t templates/controlplane.yaml -i > nodes/node2.yaml
talm template -e 192.168.123.13 --nodes 192.168.123.13 -t templates/controlplane.yaml -i > nodes/node3.yaml

Параметр --insecure (-i) нужен потому, что Talm должен получить конфигурационные данные с узлов Talos, которые еще не инициализированы, находятся в maintenance mode и поэтому не могут принять аутентифицированное соединение. Узлы будут инициализированы только на следующем шаге с помощью talm apply.

Сгенерированные файлы содержат блок комментариев с обнаруженными сетевыми интерфейсами и дисками. Эти файлы можно отредактировать перед применением, чтобы настроить сетевую конфигурацию. Например, если нужно настроить network bonding (LACP), см. Настройка bonding (LACP).

4. Применение конфигурации и инициализация кластера

На этом этапе конфигурационные файлы в node/*.yaml готовы к применению на узлах.

4.1 Применение конфигурационных файлов

Используйте talm apply, чтобы применить конфигурационные файлы к соответствующим узлам:

talm apply -f nodes/node1.yaml -i
talm apply -f nodes/node2.yaml -i
talm apply -f nodes/node3.yaml -i

Эта команда инициализирует узлы и настраивает аутентифицированное соединение, поэтому дальше -i (--insecure) не потребуется. Если команда выполнена успешно, она вернет IP узла:

$ talm apply -f nodes/node1.yaml -i
- talm: file=nodes/node1.yaml, nodes=[192.168.123.11], endpoints=[192.168.123.11]

Позже с talm apply также можно использовать следующие опции:

  • --dry-run - dry run mode покажет diff с существующей конфигурацией без внесения изменений.
  • -m try - try mode откатит конфигурацию через 1 минуту.

4.2 Ожидание перезагрузки

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

Когда узлы будут готовы, они откроют порт 50000; это признак того, что узел завершил настройку Talos и перезагрузился. Если нужно автоматизировать проверку готовности узлов, используйте такой пример:

timeout 60 sh -c 'until \
  nc -nzv 192.168.123.11 50000 && \
  nc -nzv 192.168.123.12 50000 && \
  nc -nzv 192.168.123.13 50000; \
  do sleep 1; done'

4.3. Инициализация Kubernetes

Инициализируйте кластер Kubernetes, выполнив talm bootstrap для одного из узлов control plane:

talm bootstrap -f nodes/node1.yaml

5. Доступ к кластеру Kubernetes

На этом этапе кластер Kubernetes готов к установке Cozystack.

До этого шага взаимодействие с кластером выполнялось через Talos API и talosctl. Для следующих шагов нужны Kubernetes API и kubectl, которым требуется kubeconfig.

5.1. Получение kubeconfig

Используйте Talm, чтобы сгенерировать административный kubeconfig:

talm kubeconfig -f nodes/node1.yaml

Эта команда создаст файл kubeconfig в текущем каталоге.

5.2. Изменение URL Cluster API

Теперь в kubeconfig URL Cluster API указывает на floating IP (VIP) в private subnet.

Если вместо floatingIP используется public IP, обновите endpoint соответствующим образом. Отредактируйте kubeconfig — замените URL кластера на public IP одного из узлов:

  apiVersion: v1                                                                                                          
  clusters:                                                                                                               
  - cluster:     
      certificate-authority-data: ...                                                                                                         
-     server: https://10.0.1.101:6443   
+     server: https://12.34.56.101:6443   

5.3. Активация kubeconfig

Затем настройте переменную KUBECONFIG или используйте другие инструменты, чтобы сделать этот kubeconfig доступным вашему клиенту kubectl:

export KUBECONFIG=$PWD/kubeconfig

5.4. Проверка доступности кластера

Проверьте, что кластер доступен:

kubectl get ns

Пример вывода:

NAME              STATUS   AGE
default           Active   7m56s
kube-node-lease   Active   7m56s
kube-public       Active   7m56s
kube-system       Active   7m56s

5.5. Проверка состояния узлов

Проверьте состояние узлов кластера:

kubectl get nodes    

Вывод показывает состояние узлов и версию Kubernetes:

NAME    STATUS     ROLES           AGE     VERSION
node1   NotReady   control-plane   7m56s   v1.33.1
node2   NotReady   control-plane   7m56s   v1.33.1
node3   NotReady   control-plane   7m56s   v1.33.1

Обратите внимание, что все узлы показывают STATUS: NotReady, и на этом этапе это нормально. Так происходит потому, что стандартный CNI-плагин Kubernetes был отключен в конфигурации Talos, чтобы Cozystack мог установить собственный CNI-плагин.

Следующие шаги

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