Стадия жизненного цикла модуля: General Availability
Возможности API
Документация API для внешней интеграции доступна в интерфейсе Deckhouse Commander в меню настроек в правом верхнем углу.
Для того чтобы использовать это API, нужно выпустить токен. Токен также выпускается в интерфейсе
Deckhouse Commander. Токен нужно передавать в заголовке X-Auth-Token.
Существует два вида токенов, которым доступны разные методы в API:
- Глобальные токены, которые выпускаются на странице управления рабочими пространствами. С помощью глобальных токенов можно создавать рабочие пространства и управлять их назначениями.
- Токены рабочих пространств, которые выпускаются на странице рабочего пространства. С помощью токенов рабочих пространств можно управлять сущностями рабочего пространства (кластерами, шаблонами кластеров, каталогами инвентаря, реестрами). Доступно управление сущностями только того рабочего пространства, в котором он был выпущен.
Что доступно в API при использовании глобального токена:
- Просмотр глобальных ролей
GET /api/v1/global_roles
- Просмотр и создание рабочих пространств
GET /api/v1/workspacesPOST /api/v1/workspaces
- Создание, изменение, удаление назначений в рабочих пространствах
GET /api/v1/workspace_role_bindingsPOST /api/v1/workspace_role_bindingsGET /api/v1/workspace_role_bindings/:idPUT /api/v1/workspace_role_bindings/:idDELETE /api/v1/workspace_role_bindings/:id
Что доступно в API при использовании токена рабочего пространства:
- Управление шаблонами кластеров
GET /api/v1/cluster_templatesPOST /api/v1/cluster_templatesGET /api/v1/cluster_templates/:idPUT /api/v1/cluster_templates/:idDELETE /api/v1/cluster_templates/:id
- Чтение каталогов инвентаря
GET /api/v1/catalogsGET /api/v1/catalogs/:id
- Создание, изменение, удаление кластеров
POST /api/v1/clustersGET /api/v1/clustersGET /api/v1/clusters/:idPUT /api/v1/clusters/:idDELETE /api/v1/clusters/:id
- Создание, изменение, удаление записей в каталогах
POST /api/v1/recordsGET /api/v1/recordsGET /api/v1/records/:idPUT /api/v1/records/:idDELETE /api/v1/records/:id
- Создание, просмотр, удаление реестров
POST /api/v1/registriesGET /api/v1/registriesGET /api/v1/registries/:idDELETE /api/v1/registries/:id
- Операции с задачами кластера
GET /api/v1/cluster_tasksGET /api/v1/cluster_task_logs
Создание рабочего пространства и назначение глобальной роли пользователям
Создание рабочего пространства
curl -X 'POST' \
"https://$COMMANDER_HOST/api/v1/workspaces" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"Рабочее пространство из API"}'
В ответ на запрос создания получим данные рабочего пространства, для последующих запросов понадобится его id.
{
"id": "088b8e03-e7c0-4655-aae7-d11b7609c579",
"slug": "sftpp",
"name": "Рабочее пространство из API",
"comment": null,
"main": false,
"current_revision": 0,
"created_at": "2026-01-15T12:19:57.002+03:00",
"updated_at": "2026-01-15T12:19:57.002+03:00"
}
Получение глобальной роли
Чтобы назначить глобальную роль пользователю или группе пользователей, необходимо получить id глобальной роли.
curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/global_roles" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN"
Нас интересует поле id нужной роли:
[
{
"id": "818c3814-4973-452e-9985-d75fbe35eb4c",
"name": "commander-admin",
"comment": null,
"labels": {
"commander.deckhouse.io/owned-by": "commander"
},
"current_revision": 0,
"commander_rules": [
{
"id": "455ccf46-f34c-4c75-970d-4dbc361adc68",
"verbs": [
"*"
],
"resources": [
"*"
],
"resource_names": null,
"created_at": "2025-04-30T23:46:18.616+03:00",
"updated_at": "2025-04-30T23:46:18.616+03:00"
}
],
"kubernetes_rules": [
{
"id": "9713527d-69df-4ecb-9db2-35df194e18b5",
"verbs": [
"*"
],
"resources": [
"*"
],
"resource_names": null,
"api_groups": [
"*"
],
"created_at": "2025-06-06T16:56:32.208+03:00",
"updated_at": "2025-06-06T16:56:32.208+03:00"
}
],
"created_at": "2025-04-30T23:46:18.567+03:00",
"updated_at": "2025-04-30T23:46:18.567+03:00"
}
]
Создание назначения рабочего пространства
Теперь можем создать назначение глобальной роли для пользователя в созданном рабочем пространстве:
PAYLOAD="$(jq -nc '{
"workspace_id": "088b8e03-e7c0-4655-aae7-d11b7609c579",
"name": "workspace-admins",
"comment": "Назначение из API",
"role": {
"type": "GlobalRole",
"id": "818c3814-4973-452e-9985-d75fbe35eb4c"
},
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io"
}
]
}')"
curl -X 'POST' \
"https://$COMMANDER_HOST/api/v1/workspace_role_bindings" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H 'Content-Type: application/json' \
-d "$PAYLOAD"
Получим успешный ответ сервера:
{
"id": "05b3abdf-20a5-447b-823b-8e1a57b46158",
"name": "workspace-admins",
"comment": "Назначение из API",
"current_revision": 0,
"role_type": "GlobalRole",
"role": {
"id": "818c3814-4973-452e-9985-d75fbe35eb4c",
"name": "commander-admin",
"comment": null,
"labels": {
"commander.deckhouse.io/owned-by": "commander"
},
"current_revision": 0,
"created_at": "2025-04-30T23:46:18.567+03:00",
"updated_at": "2025-04-30T23:46:18.567+03:00"
},
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io",
"created_at": "2026-01-15T14:01:01.858+03:00",
"updated_at": "2026-01-15T14:01:01.858+03:00"
}
],
"created_at": "2026-01-15T14:01:01.821+03:00",
"updated_at": "2026-01-15T14:01:01.821+03:00"
}
Добавление группы пользователей в назначение
API позволяет добавлять и удалять пользователей и группы пользователей в назначениях рабочих пространств.
В качестве примера добавим группу пользователей в существующее назначение:
PAYLOAD="$(jq -nc '{
"current_revision": 0,
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io"
},
{
"kind": "Group",
"name": "Administrators"
}
]
}')"
curl -X 'PUT' \
"https://$COMMANDER_HOST/api/v1/workspace_role_bindings/05b3abdf-20a5-447b-823b-8e1a57b46158" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H 'Content-Type: application/json' \
-d "$PAYLOAD"
Получим успешный ответ с изменённым списком subjects:
{
"id": "05b3abdf-20a5-447b-823b-8e1a57b46158",
"name": "workspace-admins",
"comment": null,
"current_revision": 1,
"role_type": "GlobalRole",
"role": {
"id": "818c3814-4973-452e-9985-d75fbe35eb4c",
"name": "commander-admin",
"comment": null,
"labels": {
"commander.deckhouse.io/owned-by": "commander"
},
"current_revision": 0,
"created_at": "2025-04-30T23:46:18.567+03:00",
"updated_at": "2025-04-30T23:46:18.567+03:00"
},
"subjects": [
{
"kind": "Group",
"name": "Administrators",
"created_at": "2026-01-15T14:15:04.020+03:00",
"updated_at": "2026-01-15T14:15:04.020+03:00"
},
{
"kind": "User",
"name": "commander-admin@deckhouse.io",
"created_at": "2026-01-15T14:01:01.858+03:00",
"updated_at": "2026-01-15T14:01:01.858+03:00"
}
],
"created_at": "2026-01-15T14:01:01.821+03:00",
"updated_at": "2026-01-15T14:15:03.991+03:00"
}
Создание кластера с использованием записи из каталога
Получение актуальной версии шаблона
Чтобы создать кластер, нам нужен ID версии шаблона. Мы возьмем последнюю версию, которая
записана в шаблоне в поле current_cluster_template_version_id. Тело версий шаблона громоздкое,
поэтому опустим вывод версий:
curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r 'del(.cluster_template_versions)'
Нас интересует поле current_cluster_template_version_id:
{
"id": "fb999a72-efe7-4db7-af53-11b17bc0a687",
"name": "YC Dev",
"current_cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"comment": "Канал обновлений и версия k8s задаются",
"current_revision": 12,
"immutable": false,
"created_at": "2024-02-05T17:35:44.318+03:00",
"updated_at": "2024-04-10T18:00:57.835+03:00",
"archived_at": null,
"archive_number": null
}
TEMPLATE_VERSION_ID="$(curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r '.current_cluster_template_version_id')"
Получение записи для входных параметров
Получим схему входных параметров и убедимся, что среди них есть запись из каталога yandex-cloud-slot
curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r --arg templ_version "$TEMPLATE_VERSION_ID" '
.cluster_template_versions[]
| select(.id == $templ_version)
| .params'
Рассмотрим схему входных параметров шаблона, она же — схема параметров кластера. Схема
предусматривает три обязательных параметра среди которых запись из каталога yandex-cloud-slot
(параметр slot, свойство catalog):
[
{
"header": "Параметры кластера"
},
{
"key": "slot",
"span": 4,
"title": "Слот для кластера в Yandex Cloud",
"catalog": "yandex-cloud-slot",
"immutable": true
},
{
"key": "releaseChannel",
"enum": [ "Alpha", "Beta", "EarlyAccess", "Stable", "RockSolid" ],
"span": 1,
"title": "Канал обновлений",
"default": "EarlyAccess"
},
{
"key": "kubeVersion",
"enum": [ "Automatic", "1.25", "1.26", "1.27", "1.28", "1.29" ],
"span": 1,
"title": "Версия Kubernetes",
"default": "Automatic"
}
]
Найдем запись из этого каталога. Для начала определим ID каталога по его идентификатору (slug).
CATALOG_ID="$(curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/catalogs?without_archived=true" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r '.[] | select(.slug == "yandex-cloud-slot") | .id')"
Теперь выберем первую попавшуюся запись из этого каталога, который еще не занят другим кластером.
Эту запись нужно подготовить к использованию в кластере. Для записи необходимо помимо значений
указать его ID в специальном поле x-commander-record-id. Это поле названо так, чтобы не вводить
ограничение на поле id, которое может потребоваться пользователям в самих записях:
SLOT_RECORD="$(curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/records?without_archived=true" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -rc --arg catalog_id "$CATALOG_ID" '[
.[] |
select(
.catalog_id == $catalog_id
and
.cluster_id == null
)
][0]
| .values + { "x-commander-record-id": .id }')"
Полученная структура:
{
"ip": "158.166.177.188",
"name": "x",
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee"
}
Создание кластера
Теперь можем создать кластер:
PAYLOAD="$(jq -nc --argjson slot "$SLOT_RECORD" '{
"name": "Кластер из API",
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"values": {
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess",
"slot": $slot
}
}')"
curl -v -X 'POST' \
"https://$COMMANDER_HOST/api/v1/clusters" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" \
-H 'Content-Type: application/json' \
-d "'$PAYLOAD'"
curl -v -X 'POST' \
"https://$COMMANDER_HOST/api/v1/clusters" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"Кластер из API","cluster_template_version_id":"8e75210a-f05c-421d-84b3-fc0697814d6d","values":{"kubeVersion":"1.29","releaseChannel":"EarlyAccess","slot":{"ip":"158.160.110.223","name":"b","x-commander-record-id":"5f6727e7-630c-4b18-bcf0-868ea96a27ee"}}}'
{
"name": "Кластер из API",
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"values": {
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess",
"slot": {
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee",
"ip": "158.166.177.188",
"name": "x"
}
}
}
"'" "$(jq -n --argjson slot "$SLOT_RECORD" '{
"name": "Кластер из API",
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"values": {
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess",
"slot": $slot
}
}')" "'"
В ответ на запрос создания придут данные кластера. Часть полей в примере ниже мы опустили для краткости, в том числе отрендеренную конфигурацию:
{
"id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"name": "Кластер из API",
"values": {
"slot": {
"ip": "158.166.177.188",
"name": "x",
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee"
},
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess"
},
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"was_created": false,
"status": "new"
}
Теперь проследим процесс создания кластера. Мы должны дождаться статуса in_sync:
cluster_status="$(curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/clusters/5436e6ef-d811-472f-9c9c-46cb9c6321d9" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r '.status')"
while [ "in_sync" != "$cluster_status" ]
do
cluster_status="$(curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/clusters/5436e6ef-d811-472f-9c9c-46cb9c6321d9" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r '.status')"
echo $cluster_status
sleep 5
done
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
creating
# ...
in_sync
Удаление кластера
Если кластер больше не нужен, его можно удалить. В ответ придет состояние кластера, но уже со
статусом delete.
curl -s -X 'DELETE' \
"https://$COMMANDER_HOST/api/v1/clusters/5436e6ef-d811-472f-9c9c-46cb9c6321d9" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN"
{
"id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"current_revision": 1834,
"name": "Кластер из API",
"values": {
"slot": {
"ip": "158.166.177.188",
"name": "x",
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee"
},
"kubeVersion": "1.29",
"createWorker": true,
"releaseChannel": "EarlyAccess",
"installResources": true
},
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"cluster_template_version_switched_at": "2024-04-24T21:40:35.222+03:00",
"created_at": "2024-04-24T21:40:35.525+03:00",
"updated_at": "2024-04-25T12:57:51.621+03:00",
"archived_at": null,
"archive_number": null,
"was_created": true,
"is_locked": true,
"cluster_type": "cloud",
"status": "delete",
"agent_status": null,
"agent_api_key": null,
"cluster_configuration_applied_at": "2024-04-24T22:10:57.191+03:00",
"cluster_configuration_checked_at": "2024-04-25T12:57:45.479+03:00",
"resources_sync_state": "no",
"resources_state_results": [
// ...
],
"resources_checked_at": "2024-04-25T12:57:31.084+03:00",
"resources_applied_at": "2024-04-24T22:04:59.813+03:00",
"init_configuration_rendered": "...",
"init_resources_rendered": "...",
"dhctl_configuration_rendered": "...",
"applied_cluster_configuration_rendered": "...",
"applied_provider_specific_cluster_configuration_rendered": "...",
"applied_resources_rendered": "......",
"desired_cluster_configuration_rendered": "...",
"desired_provider_specific_cluster_configuration_rendered": "...",
"desired_resources_rendered": "......",
"render_errors": [],
"cluster_agent_data": [
// ...
]
}