Стадия жизненного цикла модуля: General Availability

Включение модуля

Включить модуль можно одним из следующих способов:

  • С помощью веб-интерфейса Deckhouse.

    В разделе «Система» → «Управление системой» → «Deckhouse» → «Модули», откройте модуль stronghold, включите переключатель «Модуль включен». Сохраните изменения.

  • С помощью Deckhouse CLI.

    Выполните следующую команду для включения модуля:

    d8 k -n d8-system exec deploy/deckhouse -c deckhouse -it -- deckhouse-controller module enable stronghold
    
  • С помощью ModuleConfig stronghold.

    Установите spec.enabled в true или false в ModuleConfig stronghold (создайте его, при необходимости).

    Пример манифеста для включения модуля:

    apiVersion: deckhouse.io/v1alpha1
    kind: ModuleConfig
    metadata:
      name: stronghold
    spec:
      enabled: true
    

По умолчанию модуль запустится в режиме Automatic с инлетом Ingress. В текущей версии другие режимы и инлеты отсутствуют.

Возможные ошибки при включении модуля

secret “ingress-tls” not found

Проверьте статус пода stronghold:

d8 k -n d8-stronghold describe pod stronghold-0

В выводе присутствует строка:

MountVolume.SetUp failed for volume "certificates" : secret "ingress-tls" not found

Если используется автоматический заказ TLS-сертификатов (метод ClusterIssuer с LetsEncrypt), то причиной может быть неготовность TLS-сертификата.

Для заказа сертификата и появления секрета ingress-tls в неймспейсе d8-stronghold может потребоваться некоторое время (обычно до 10 минут). После успешного заказа сертификата Stronghold может запуститься не сразу, из-за экспоненциальной задержки перезапуска контейнеров в Kubernetes (Exponential Backoff). В этом случае можно либо дождаться запуска (время зависит от того, насколько долго Stronghold не мог запуститься), либо перезапустить Stronghold вручную, выполнив команду:

d8 k -n d8-stronghold delete po -l app.kubernetes.io/instance=stronghold

Для диагностики проблемы с заказом TLS-сертификата, выполните следующие действия:

  • Проверьте статус заказа TLS-сертификата:

    d8 k -n d8-stronghold get certificate
    

    Если сертификат получен (статус Ready), то можно либо дождаться запуска Stronghold, либо перезапустить его вручную (см. выше).

  • Получите список CertificateRequest:

    d8 k -n d8-stronghold get certificaterequest
    

    Если такие объекты есть, найдите среди них объект начинающийся со stronghold- (в примере будет использоваться stronghold-b5wc6).

  • Посмотрите статус объекта CertificateRequest:

    d8 k -n d8-stronghold describe certificaterequest stronghold-b5wc6
    

    Одной из причин может быть ошибка too many certificates already issued for <DOMAIN>. Часто такое происходит из-за превышения лимита запросо, если используется бесплатный сервис (например sslip.io или getmoss.site). В таком случае нужно либо подождать, пока не пройдёт таймаут ограничения, либо сменить способ создания сертификата для домена stronghold.* (например, выбрать другой ClusterIssuer, использовать selfsigned-сертификат, выполнить ручное подписание сертификата).

    При успешном получении сертификата в статусе CertificateRequest должны быть строки:

    Message:               Certificate fetched from issuer successfully
    Reason:                Issued
    Status:                True
    Type:                  Ready
    

    Также, в неймспейсе d8-stronghold должен присутствовать секрет (Secret) ingress-tls с типом kubernetes.io/tls.

Под stronghold не может запуститься из-за ошибки Readiness-пробы

Выполните команду:

d8 k -n d8-stronghold get po

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

$ d8 k -n d8-stronghold get po
NAME                                   READY   STATUS                       RESTARTS   AGE
stronghold-0                           1/2     Running                      0          33s
stronghold-automatic-594b78ff6-b4pgj   0/1     CreateContainerConfigError   0          15s

Если под stronghold не может запуститься из-за ошибки Readiness-пробы (пример выше), проверьте статус следующей командой:

d8 k -n d8-stronghold exec stronghold-0 -it -- stronghold status

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

$ d8 k -n d8-stronghold exec stronghold-0 -it -- stronghold status
Defaulted container "stronghold" out of: stronghold, kube-rbac-proxy
Key                Value
---                -----
...
Initialized        true
Sealed             true
...
Unseal Progress    0/1   <-
Unseal Nonce       n/a   <-
...

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

Выполните следующие шаги для удаления старых данных Stronghold, если вы не планируете их использовать:

  1. Уменьшите количество реплик Stronghold до 0:

    d8 k -n d8-stronghold scale statefulset stronghold --replicas=0
    
  2. Выполните на всех master-узлах кластера команду для удаления старых данных Stronghold:

    sudo rm -Ir /var/lib/deckhouse/stronghold/{node-id,vault.db,raft}
    
  3. Увеличьте количество реплик Stronghold обратно до необходимого значения (по количеству master-узлов, обычно 1 или 3):

    Пример для 1 реплики:

    d8 k -n d8-stronghold scale statefulset stronghold --replicas=1
    

Выключение модуля

Перед выключением модуля рекомендуется сохранить секрет stronghold-keys в неймспейсе d8-stronghold, содержащий root и unseal-ключи, для возможности дальнейшего доступа к данным Stronghold.

При отключении модуля удалятся все контейнеры Stronghold из неймспейса d8-stronghold, а также секрет stronghold-keys с root и unseal-ключами. При этом, данные сервиса не удалятся с узла. Вы можете включить модуль снова, создать и поместить в неймспейс d8-stronghold сохраненную копию секрета stronghold-keys, тогда доступ к данным будет восстановлен. Если секрет stronghold-keys потерян, доступ к данным будет также утерян навсегда.

Выключить модуль можно одним из следующих способов:

  • С помощью веб-интерфейса Deckhouse.

    В разделе «Система» → «Управление системой» → «Deckhouse» → «Модули», откройте модуль stronghold, выключите переключатель «Модуль включен». Сохраните изменения.

  • С помощью Deckhouse CLI.

    Выполните следующие команды для выключения модуля:

    d8 k annotate mc stronghold modules.deckhouse.io/allow-disabling=true
    d8 system module disable stronghold
    

После выключения модуля, если старые данные больше не нужны, выполните следующую команду для их удаления на каждом master-узле кластера:

sudo rm -Ir /var/lib/deckhouse/stronghold/{node-id,vault.db,raft}

Ручное распечатывание кластера

Для ручного распечатывания кластера Stronghold:

  1. Зайдите на master-узел.

  2. Подготовьте инструмент командной строки stronghold для работы.

  3. Установите переменные окружения:

    export VAULT_ADDR=https://`d8 k -n d8-stronghold get ingress stronghold -o jsonpath='{.spec.rules[0].host}'`
    export VAULT_SKIP_VERIFY=true
    
  4. Получите ключ из Secret d8 k -n d8-stronghold get secret stronghold-keys -o jsonpath='{.data.unsealKey}' | base64 -d;echo.

  5. Выполните команду stronghold operator unseal.

  6. Введите unseal-ключ.

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

Доступ к сервису осуществляется через инлеты. Инлет - это источник входных данных для пода. В примере доступен один инлет - Ingress Адрес веб-интерфейса Stronghold формируется следующим образом: в шаблоне publicDomainTemplate глобального параметра конфигурации Deckhouse ключ %s заменяется на stronghold.

Например, если publicDomainTemplate установлен как %s-kube.mycompany.tld, веб-интерфейс Stronghold будет доступен по адресу stronghold-kube.cmycompany.tld.

Использование хранилища данных. Режимы работы

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

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

В текущей версии модуля присутствует только режим Automatic, в котором при первом запуске модуля происходит автоматическая инициализация хранилища. В процессе инициализации, ключ разблокирования и root-token помещаются в секрет stronghold-keys неймспейса d8-stronghold. После инициализации, модуль автоматически разблокирует узлы кластера Stronghold. В автоматическом режиме, при перезапуске узлов Stronghold, хранилище также будет автоматически разблокировано без вмешательства пользователя.

Управление доступами

В автоматическом режиме Automatic в Stronghold после инициализации хранилища создается роль deckhouse_administrators, для которой включается доступ к веб-интерфейсу через OIDC аутентификацию Dex. Также настраивается автоматическое подключение текущего кластера Deckhouse к Stronghold для работы модуля secrets-store-integration.

Для того, чтоб выдать пользователям, находящимся в группе admins (членство в группе передаётся из используемого IdP или LDAP с помощью Dex), нужно указать эту группу в массиве administrators в ModuleConfig stronghold:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: stronghold
spec:
  enabled: true
  version: 1
  settings:
    management:
      mode: Automatic
      administrators:
      - type: Group
        name: admins

Для того, чтоб выдать права administrator пользователям manager и securityoperator, можно использовать следующие параметры в ModuleConfig stronghold:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: stronghold
spec:
  enabled: true
  version: 1
  settings:
    management:
      mode: Automatic
      administrators:
      - type: User
        name: manager@mycompany.tld
      - type: User
        name: securityoperator@mycompany.tld

В дальнейшем можно создать пользователей в Stronghold с различными правами доступа к секретам с помощью встроенного механизма хранилища.

Первый запуск

Первый запуск подразумевает отсутствие папки /var/lib/deckhouse/stronghold в файловой системе узлов, на которых будут запускаться экземпляры Stronghold (по умолчанию это master-узлы) и отключенный модуль Stronghold.

Для выполнения приведенных далее команд необходим kubectl, настроенный на работу с кластером (либо, можно выполнять команды на master-узле от пользователя root).

Далее приведены варианты организации доступа к модулю через инлет Ingress, а также процесс включения и проверки работоспособности модуля.

Способы организации доступа через инлет Ingress

ClusterIssuer LetsEncrypt

Этот метод получения сертификата настроен по умолчанию. Однако, подойдёт только для сервисов доступных из Интернета (не для внутренних сетей). Выполняем проверку доступности:

  1. Получаем адрес платформы аутентификации командой:
    d8 k -n d8-user-authn get ing dex
    # Ожидаемый ответ
    # NAME   CLASS   HOSTS               ADDRESS         PORTS     AGE
    # dex    nginx   dex.mycompany.tld   34.85.243.109   80, 443   4d20h
    
    Под столбцом HOSTS наш проверяемый домен, а под ADDRESS – его IP адрес. Теперь нужно убедиться, что домен правильно резолвится на указанный IP адрес. Для этого выполняем команду:
    nslookup dex.mycompany.tld 8.8.8.8
    # Ожидаемый ответ
    # ...
    # Name:	dex.mycompany.tld
    # Address: 34.85.243.109
    # ...
    
    # Либо
    dig @8.8.8.8 dex.mycompany.tld
    # Ожидаемый ответ
    # ...
    # ;; ANSWER SECTION:
    # dex.mycompany.tld. 3600 IN A	34.85.243.109
    # ...
    
    Если ответом стала ошибка с кодом NXDOMAIN, нужно настроить DNS пользователя.
  2. В браузере открываем https://dex.mycompany.tld/healthz, либо выполняем команду curl -kL https://dex.mycompany.tld/healthz. Должен вернуться ответ Health check passed.
  3. Проверяем, что Ingress контроллер обрабатывает запросы на ваш поддомен stronghold.mycompany.tld. Снова в браузере, либо командой curl -kL открываем https://stronghold.mycompany.tld. Должна вернуться 404 ошибка.

ClusterIssuer с самоподписанным центром сертификации

Эта опция подходит, если вы хотите использовать свой самоподписанный Центр сертификации. В качестве примера мы будем использовать уже созданный ClusterIssuer ресурс selfsigned. Для добавления Issuer или ClusterIssuer со своим самоподписанным Центром сертификации, воспользуйтесь официальной документацией

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

Редактируем настройки global модуля. Сделать это можно, например, командой d8 k edit mc global. Добавляем параметр settings.modules.https.certManager.clusterIssuerName: selfsigned. В результате конфигурация модуля должна выглядеть так:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: global
spec:
  settings:
    modules:
      https:
        certManager:
          clusterIssuerName: selfsigned    # Единственный параметр, который нужно добавить
      publicDomainTemplate: '%s.mycompany.tld'
  version: 2

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

  1. Получаем адрес платформы аутентификации командой:
    d8 k -n d8-user-authn get ing dex
    # Ожидаемый ответ
    # NAME   CLASS   HOSTS               ADDRESS         PORTS     AGE
    # dex    nginx   dex.mycompany.tld   34.85.243.109   80, 443   4d20h
    
    Под столбцом HOSTS наш проверяемый домен, а под ADDRESS – его IP адрес. Теперь нужно убедиться, что домен правильно резолвится на указанный IP адрес. Для этого выполняем команду:
    nslookup dex.mycompany.tld
    # Ожидаемый ответ
    # ...
    # Name:	dex.mycompany.tld
    # Address: 34.85.243.109
    # ...
    
    # Либо
    dig dex.mycompany.tld
    # Ожидаемый ответ
    # ...
    # ;; ANSWER SECTION:
    # dex.mycompany.tld. 3600 IN A	34.85.243.109
    # ...
    
    Если ответом стала ошибка с кодом NXDOMAIN, нужно настроить DNS пользователя. Если домен не доступен из Интернета, дополнительно необходимо выполнить дополнительный шаг

    Как временное решение можно добавить следующую строку в файл /etc/hosts вашей Unix системы

    34.85.243.109 dex.mycompany.tld stronghold.mycompany.tld
    
  2. В браузере открываем https://dex.mycompany.tld/healthz, либо выполняем команду curl -kL https://dex.mycompany.tld/healthz. Должен вернуться ответ Health check passed.
  3. Проверяем, что Ingress контроллер обрабатывает запросы на ваш поддомен stronghold.mycompany.tld. Снова в браузере, либо командой curl -kL открываем https://stronghold.mycompany.tld. Должна вернуться 404 ошибка.

Используя файл сертификата

Нужно создать СА, сертификат, и подписать его созданым СА. Если уже есть СА, сертификат можно подписать существущим. Важно сделать сертификат с цепочкой (fullchain).

Ниже представлен скрипт createCertificate.sh, который с помощью openssl создает нужную пару сертификат + ключ для домена mycompany.tld (*.mycompany.tld).

#!/bin/bash

set -e
caName="MyOrg-RootCA"            # Имя CA (CN)
publicDomain="mycompany.tld"     # Имя кластерного домена (см. publicDomainTemplate)
certName="kubernetes"            # Имя сертификата для кластера (CN)

mkdir -p "${caName}"
cd "${caName}"

[ ! -f "${caName}.key" ] && openssl genrsa -out "${caName}.key" 4096

[ ! -f "${caName}.crt" ] &&  openssl req -x509 -new -nodes -key "${caName}.key" -sha256 -days 1826 -out "${caName}.crt" \
   -subj "/CN=${caName}/O=MyOrganisation"

openssl req -new -nodes -out ${certName}.csr -newkey rsa:4096 -keyout "${certName}.key" \
  -subj "/CN=${certName}/O=MyOrganisation"

# v3 ext file
cat > "${certName}.v3.ext" << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${publicDomain}
DNS.2 = *.${publicDomain}
EOF

openssl x509 -req -in "${certName}.csr" -CA "${caName}.crt" -CAkey "${caName}.key" -CAcreateserial -out "${certName}.crt" -days 730 -sha256 -extfile "${certName}.v3.ext"

cat "${certName}.crt" "${caName}.crt" > "${certName}_fullchain.crt"

Используя полученные файлы kubernetes.key и kubernetes_fullchain.crt нужно создать секрет в неймспейсе d8-system

d8 k -n d8-system create secret tls mycompany-wildcard-tls --cert=kubernetes_fullchain.crt --key=kubernetes.key

Для использования полученного сертификата в кластере нужно привести конфигурацию модуля global к такому виду. Сделать это можно например командой d8 k edit mc global

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: global
spec:
  settings:
    modules:
      https:
        customCertificate:
          secretName: mycompany-wildcard-tls    # здесь указываем название объекта secret, содержащий fullchain сертификат и ключ
        mode: CustomCertificate                 # меняем режим работы с tls для всех модулей
      publicDomainTemplate: '%s.mycompany.tld'
  version: 2

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

  1. Получаем адрес платформы аутентификации командой:
    d8 k -n d8-user-authn get ing dex
    # Ожидаемый ответ
    # NAME   CLASS   HOSTS               ADDRESS         PORTS     AGE
    # dex    nginx   dex.mycompany.tld   34.85.243.109   80, 443   4d20h
    
    Под столбцом HOSTS наш проверяемый домен, а под ADDRESS – его IP адрес. Теперь нужно убедиться, что домен правильно резолвится на указанный IP адрес. Для этого выполняем команду:
    nslookup dex.mycompany.tld
    # Ожидаемый ответ
    # ...
    # Name:	dex.mycompany.tld
    # Address: 34.85.243.109
    # ...
    
    # Либо
    dig dex.mycompany.tld
    # Ожидаемый ответ
    # ...
    # ;; ANSWER SECTION:
    # dex.mycompany.tld. 3600 IN A	34.85.243.109
    # ...
    
    Если ответом стала ошибка с кодом NXDOMAIN, нужно настроить DNS пользователя. Если домен не доступен из Интернета, дополнительно необходимо выполнить дополнительный шаг

    Как временное решение можно добавить следующую строку в файл /etc/hosts вашей Unix системы

    34.85.243.109 dex.mycompany.tld stronghold.mycompany.tld
    
  2. В браузере открываем https://dex.mycompany.tld/healthz, либо выполняем команду curl -kL https://dex.mycompany.tld/healthz. Должен вернуться ответ Health check passed.
  3. Проверяем, что Ingress контроллер обрабатывает запросы на ваш поддомен stronghold.mycompany.tld. Снова в браузере, либо командой curl -kL открываем https://stronghold.mycompany.tld. Должна вернуться 404 ошибка.

Включение модуля

После организации доступа через инлет Ingress, можно включить модуль stronghold. Инициализация и настройка интеграции с dex произойдет автоматически.

После запуска модуля можно выплонить следующие проверки:

  1. Убедитесь в наличии сертификата для домена stronghold.* либо через веб-интерфейса Deckhouse, либо командой:

    d8 k -n d8-stronghold get ingress-tls
    

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

  1. Убедитесь в доступности адреса https://stronghold./v1/sys/health (используйте домен, согласно установленному шаблону, утсановленному в глобальном параметре publicDomainTemplate):

  2. Проверьте соответствие Издателя сертификата с CA сертификатом (Опционально)

Как получить бинарный файл stronghold

Чтобы получить бинарный файл stronghold, выполните на master-узле кластера из-под пользователя root следующую команду:

mkdir $HOME/bin
sudo cp /proc/$(pidof stronghold)/root/usr/bin/stronghold $HOME/bin/stronghold && sudo chmod a+x $HOME/bin/stronghold
export PATH=$PATH:$HOME/bin

Исполняемый файл stronghold будет размещен в папке /bin/stronghold домашней папки пользователя.