Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef904ca952 | |||
| e8dc61f5a1 | |||
| 62f12c8ce1 | |||
| a9cafb629c | |||
| abdc7bd70e | |||
| 7fd1755a7d |
Submodule beecloud-docs deleted from df88416247
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "docs",
|
"name": "docs",
|
||||||
"version": "0.6.5-main",
|
"version": "0.6.4-link",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "docs",
|
"name": "docs",
|
||||||
"version": "0.6.5-main",
|
"version": "0.6.4-link",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@beeline/design-tokens": "^1.31.6",
|
"@beeline/design-tokens": "^1.31.6",
|
||||||
|
|||||||
+236
-268
@@ -2,7 +2,7 @@ import { defineConfig } from 'vitepress'
|
|||||||
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
||||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||||
import { overrideComponents } from './override-components'
|
import { overrideComponents } from './override-components'
|
||||||
import { resolve } from 'node:path'
|
import { resolve } from 'path'
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
@@ -41,7 +41,240 @@ const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|||||||
`
|
`
|
||||||
|
|
||||||
const new_version = process.env?.VITE_NEW_VERSION;
|
const new_version = process.env?.VITE_NEW_VERSION;
|
||||||
console.log({ base: typeof new_version !== 'undefined' ? '/' : '/docs/' })
|
|
||||||
|
const sidebarConfig = {
|
||||||
|
'/platform/': [
|
||||||
|
{
|
||||||
|
text: 'Платформа Beeline Cloud', link: '/platform/index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/platform/about.md'},
|
||||||
|
{text: 'Техническая поддержка', link: '/platform/support/support-overview.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/start/': [
|
||||||
|
{
|
||||||
|
text: 'Начало работы в Beeline Cloud', link: '/start/index.md',
|
||||||
|
},
|
||||||
|
{text: 'Начать работу', link: '/start/getting-started.md'},
|
||||||
|
{text: 'Бесплатный период', link: '/start/trial.md'},
|
||||||
|
{text: 'Платное использование', link: '/start/organization.md'},
|
||||||
|
],
|
||||||
|
// '/billing/': [
|
||||||
|
|
||||||
|
// ],
|
||||||
|
'/backups/': [
|
||||||
|
{
|
||||||
|
text: 'Резервное копирование', link: '/backups/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/backups/about.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Квоты и лимиты', link: '/backups/backup-quatos.md'},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{text: 'Резервное копирование виртуальных машин Beeline Cloud', link: '/backups/backup-internal-infra.md'},
|
||||||
|
{text: 'Резервное копирование собственной инфраструктуры в Beeline Cloud', link: '/backups/backup-external-infra.md'},
|
||||||
|
{text: 'Каталог резервных копий', link: '/backups/view-backups.md'},
|
||||||
|
|
||||||
|
],
|
||||||
|
'/vdc/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
||||||
|
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'
|
||||||
|
},
|
||||||
|
|
||||||
|
{ text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Создание дата-центра', link: '/vdc/vdc-how-to/vdc-create.md' },
|
||||||
|
{ text: 'Вход в дата-центр', link: '/vdc/vdc-how-to/vdc-enter.md' },
|
||||||
|
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Виртуальные машины', link: '/vdc/vdc-how-to/vm/vm-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Создание ВМ', link: '/vdc/vdc-how-to/vm/create-vm.md'},
|
||||||
|
{text: 'Создание vApp', link: '/vdc/vdc-how-to/vm/create-vapp.md'},
|
||||||
|
{text: 'Управление состоянием ВМ', link: '/vdc/vdc-how-to/vm/manage-vm.md'},
|
||||||
|
{text: 'Клонирование ВМ', link: '/vdc/vdc-how-to/vm/clone-vm.md'},
|
||||||
|
{text: 'Изменение конфигурации ВМ', link: '/vdc/vdc-how-to/vm/edit-vm.md'},
|
||||||
|
{text: 'Удаление ВМ', link: '/vdc/vdc-how-to/vm/delete-vm.md'},
|
||||||
|
{text: 'Группы размещения', link: '/vdc/vdc-how-to/vm/create-affinity-rules.md'},
|
||||||
|
{text: 'Снимки ВМ', link: '/vdc/vdc-how-to/vm/create-snapshot.md'},
|
||||||
|
{text: 'VMware Tools', link: '/vdc/vdc-how-to/vm/vmware-tools.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Диски', link: '/vdc/vdc-how-to/disks/disks-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/vdc/vdc-how-to/disks/about.md'},
|
||||||
|
{text: 'Создание диска', link: '/vdc/vdc-how-to/disks/create-disk.md'},
|
||||||
|
{text: 'Проверка состояния диска', link: '/vdc/vdc-how-to/disks/view-disk.md'},
|
||||||
|
{text: 'Управление выделенными дисками', link: '/vdc/vdc-how-to/disks/attach-disk.md'},
|
||||||
|
{text: 'Изменение политики хранения дисков ВМ', link: '/vdc/vdc-how-to/disks/change-storage-policy-of-vm.md'},
|
||||||
|
{text: 'Редактирование параметров диска', link: '/vdc/vdc-how-to/disks/edit-disk.md'},
|
||||||
|
{text: 'Удаление диска', link: '/vdc/vdc-how-to/disks/delete-disk.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Сети', link: '/vdc/vdc-how-to/networks/networks-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Обзор', link: '/vdc/vdc-how-to/networks/about.md'},
|
||||||
|
{text: 'Настройка доступа к ВМ из интернета', link: '/vdc/vdc-how-to/networks/allow-external-connections-to-vm.md'},
|
||||||
|
{text: 'Подключение ВМ в vApp к сети', link: '/vdc/vdc-how-to/networks/connect-vapp-to-network.md'},
|
||||||
|
{text: 'Подключение ВМ к интернету', link: '/vdc/vdc-how-to/networks/connect-vm-to-network.md'},
|
||||||
|
{text: 'Создание сети в организации и подключение к Edge Gateway', link: '/vdc/vdc-how-to/networks/create-network.md'},
|
||||||
|
{text: 'Подключение сети к Edge Gateway', link: '/vdc/vdc-how-to/networks/connect-to-edge-gateway.md'},
|
||||||
|
{text: 'Создание Pre-Shared Key', link: '/vdc/vdc-how-to/networks/create-psk.md'},
|
||||||
|
{ text: 'Настройка site-to-site подключения с помощью IPSec', link: '/vdc/vdc-how-to/networks/how-to-setup-ipsec-vpn.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Настройка ASAv', link: '/vdc/vdc-how-to/networks/ipsec/asav.md'},
|
||||||
|
{text: 'Настройка CSR 1000v', link: '/vdc/vdc-how-to/networks/ipsec/csr1000v.md'},
|
||||||
|
{text: 'Настройка Fortigate', link: '/vdc/vdc-how-to/networks/ipsec/fortigate.md'},
|
||||||
|
{text: 'Проверить сетевую связанность', link: '/vdc/vdc-how-to/networks/ipsec/check-vpn-status.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Пользователи и роли', link: '/vdc/vdc-how-to/users/users-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Ролевая модель', link: '/vdc/vdc-how-to/users/roles.md'},
|
||||||
|
{text: 'Создание пользователя', link: '/vdc/vdc-how-to/users/add-user.md'},
|
||||||
|
{text: 'Изменение пароля пользователя', link: '/vdc/vdc-how-to/users/change-users-password.md'},
|
||||||
|
{text: 'Настройка квот', link: '/vdc/vdc-how-to/users/quotas.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Двухфакторная аутентификация', link: '/vdc/vdc-how-to/vdc-2fa.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
||||||
|
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
||||||
|
'/compute/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные машины', link: '/compute/index.md',
|
||||||
|
},
|
||||||
|
{ text: 'Обзор сервиса', link: '/compute/compute-overview-index.md' ,
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Техническое описание', link: '/compute/compute-overview.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/compute/compute-quatos.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{text: 'Быстрый старт', link: '/compute/compute-getting-started.md', excludeFromIndex: true },
|
||||||
|
{ text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Создание ВМ', link: '/compute/compute-how-to/compute-servers-create.md' },
|
||||||
|
{ text: 'Создание ВМ джамп-хоста', link: '/compute/compute-how-to/compute-servers-jump-create.md' },
|
||||||
|
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Подключение по SSH по внешнему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-public.md'},
|
||||||
|
{ text: 'Подключение по SSH по внутреннему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-inside.md' },
|
||||||
|
{ text: 'Подключение по SSH по логину и паролю', link: '/compute/compute-how-to/compute-connect-pwd.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Управление ВМ', link: '/compute/compute-how-to/compute-servers-manage.md' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks/compute-disk-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-disks/compute-disk-about.md' },
|
||||||
|
{ text: 'Создание диска', link: '/compute/compute-how-to/compute-disks/compute-disk-create.md' },
|
||||||
|
{ text: 'Управление дисками', link: '/compute/compute-how-to/compute-disks/compute-disk-manage.md' },
|
||||||
|
{ text: 'Удаление диска', link: '/compute/compute-how-to/compute-disks/compute-disk-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-ip/compute-ip-about.md' },
|
||||||
|
{ text: 'Просмотр IP-адресов', link: '/compute/compute-how-to/compute-ip/compute-ip-view.md' },
|
||||||
|
{ text: 'Создание IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-create.md' },
|
||||||
|
{ text: 'Управление IP-адресами', link: '/compute/compute-how-to/compute-ip/compute-ip-manager.md' },
|
||||||
|
{ text: 'Удаление IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Обзор', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-about.md'},
|
||||||
|
{ text: 'Создание группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-create.md'},
|
||||||
|
{ text: 'Управление группами размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-manager.md' },
|
||||||
|
{ text: 'Удаление группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-del.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ text: 'Сети', link: '/compute/compute-how-to/compute-network/compute-network-index.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Настройка site-to-site VPN с помощью VyOS', link: '/compute/compute-how-to/compute-network/compute-vpn-vyos.md' },
|
||||||
|
{ text: 'Подключение ВМ закрытого контура к интернету', link: '/compute/compute-how-to/compute-network/compute-network-inside.md' },
|
||||||
|
],
|
||||||
|
excludeFromIndex: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/admin/': [
|
||||||
|
{
|
||||||
|
text: 'Администрирование', link: '/admin/index.md',
|
||||||
|
},
|
||||||
|
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
||||||
|
],
|
||||||
|
'/vdi/': [
|
||||||
|
{
|
||||||
|
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'О сервисе', link: '/vdi/vdi-about.md' },
|
||||||
|
{ text: 'Техническое описание', link: '/vdi/vdi-tech.md' },
|
||||||
|
{ text: 'Квоты и лимиты', link: '/vdi/vdi-quatos.md' },
|
||||||
|
{ text: 'Тарификация', link: '/vdi/vdi-tarif.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Заказ виртуальных рабочих столов', link: '/vdi/vdi-how-to/vdi-create.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Настройка сервиса', link: '/vdi/vdi-how-to/vdi-nastroika.md',
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Настройка интеграции с Active Directory', link: '/vdi/vdi-how-to/vdi-connect-to-ad.md' },
|
||||||
|
{ text: 'Настройка сети', link: '/vdi/vdi-how-to/vdi-interconnect.md' },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// text: 'Gold-образ', link: '/vdi/vdi-how-to/vdi-gold.md'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
text: 'Подключение к виртуальному рабочему месту', link: '/vdi/vdi-how-to/vdi-connect.md'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -140,272 +373,7 @@ export default defineConfig({
|
|||||||
outline: {
|
outline: {
|
||||||
label: 'Содержание'
|
label: 'Содержание'
|
||||||
},
|
},
|
||||||
sidebar: {
|
sidebar: sidebarConfig,
|
||||||
'/platform/': [
|
|
||||||
{
|
|
||||||
text: 'Платформа Beeline Cloud', link: '/platform/index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/platform/about.md'},
|
|
||||||
{text: 'Техническая поддержка', link: '/platform/support/support-overview.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/start/': [
|
|
||||||
{
|
|
||||||
text: 'Начало работы в Beeline Cloud', link: '/start/index.md',
|
|
||||||
},
|
|
||||||
{text: 'Начать работу', link: '/start/getting-started.md'},
|
|
||||||
{text: 'Бесплатный период', link: '/start/trial.md'},
|
|
||||||
{text: 'Платное использование', link: '/start/organization.md'},
|
|
||||||
],
|
|
||||||
|
|
||||||
'/PaaS/': [
|
|
||||||
{
|
|
||||||
text: 'Начало работы в Cloud PostgreSQL', link: '/PaaS/index.md',
|
|
||||||
},
|
|
||||||
{ text: 'Cloud PostgreSQL', link: '/PaaS/PostgreSQL/PostgreSQL-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор сервиса', link: '/PaaS/PostgreSQL/about.md'},
|
|
||||||
{text: 'Описание технических параметров', link: '/PaaS/PostgreSQL/cluster-parameter.md'},
|
|
||||||
{text: 'Общая схема подключения', link: '/PaaS/PostgreSQL/connection.md'},
|
|
||||||
{text: 'Возможности пользователя', link: '/PaaS/PostgreSQL/user-capabilities.md'},
|
|
||||||
{text: 'Веб-интерфейс pgAdmin', link: '/PaaS/PostgreSQL/pgadmin.md'},
|
|
||||||
{text: 'Веб-интерфейс Grafana', link: '/PaaS/PostgreSQL/grafana.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{text: 'Параметры конфигурации IPSEC', link: '/PaaS/IPSEC.md'},
|
|
||||||
],
|
|
||||||
|
|
||||||
'/Apache-Kafka/': [
|
|
||||||
{ text: 'Apache-Kafka', link: '/Apache-Kafka/Kafka-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор сервиса', link: '/Apache-Kafka/about-service.md'},
|
|
||||||
{text: 'Работа с кластером Kafka по тарифу Base', link: '/Apache-Kafka/base-tier-connection.md'},
|
|
||||||
{text: 'Настройка топика по тарифу Base', link: '/Apache-Kafka/base-tier-topics-guide.md'},
|
|
||||||
{text: 'Конфигурация кластера', link: '/Apache-Kafka/cluster-configuretion.md'},
|
|
||||||
{text: 'Работа с кластером Kafka по тарифу Full', link: '/Apache-Kafka/full-tier-connection.md'},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// '/billing/': [
|
|
||||||
|
|
||||||
// ],
|
|
||||||
'/backups/': [
|
|
||||||
{
|
|
||||||
text: 'Резервное копирование', link: '/backups/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/backups/backups-overview.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'О сервисе', link: '/backups/about.md'},
|
|
||||||
{text: 'Квоты и лимиты', link: '/backups/backup-quatos.md'},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{text: 'Резервное копирование виртуальных машин Beeline Cloud', link: '/backups/backup-internal-infra.md'},
|
|
||||||
{text: 'Резервное копирование собственной инфраструктуры в Beeline Cloud', link: '/backups/backup-external-infra.md'},
|
|
||||||
{text: 'Каталог резервных копий', link: '/backups/view-backups.md'},
|
|
||||||
|
|
||||||
],
|
|
||||||
'/vdc/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
|
||||||
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'
|
|
||||||
},
|
|
||||||
|
|
||||||
{ text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Создание дата-центра', link: '/vdc/vdc-how-to/vdc-create.md' },
|
|
||||||
{ text: 'Вход в дата-центр', link: '/vdc/vdc-how-to/vdc-enter.md' },
|
|
||||||
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Виртуальные машины', link: '/vdc/vdc-how-to/vm/vm-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Создание ВМ', link: '/vdc/vdc-how-to/vm/create-vm.md'},
|
|
||||||
{text: 'Создание vApp', link: '/vdc/vdc-how-to/vm/create-vapp.md'},
|
|
||||||
{text: 'Управление состоянием ВМ', link: '/vdc/vdc-how-to/vm/manage-vm.md'},
|
|
||||||
{text: 'Клонирование ВМ', link: '/vdc/vdc-how-to/vm/clone-vm.md'},
|
|
||||||
{text: 'Изменение конфигурации ВМ', link: '/vdc/vdc-how-to/vm/edit-vm.md'},
|
|
||||||
{text: 'Удаление ВМ', link: '/vdc/vdc-how-to/vm/delete-vm.md'},
|
|
||||||
{text: 'Группы размещения', link: '/vdc/vdc-how-to/vm/create-affinity-rules.md'},
|
|
||||||
{text: 'Снимки ВМ', link: '/vdc/vdc-how-to/vm/create-snapshot.md'},
|
|
||||||
{text: 'VMware Tools', link: '/vdc/vdc-how-to/vm/vmware-tools.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Диски', link: '/vdc/vdc-how-to/disks/disks-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/vdc/vdc-how-to/disks/about.md'},
|
|
||||||
{text: 'Создание диска', link: '/vdc/vdc-how-to/disks/create-disk.md'},
|
|
||||||
{text: 'Проверка состояния диска', link: '/vdc/vdc-how-to/disks/view-disk.md'},
|
|
||||||
{text: 'Управление выделенными дисками', link: '/vdc/vdc-how-to/disks/attach-disk.md'},
|
|
||||||
{text: 'Изменение политики хранения дисков ВМ', link: '/vdc/vdc-how-to/disks/change-storage-policy-of-vm.md'},
|
|
||||||
{text: 'Редактирование параметров диска', link: '/vdc/vdc-how-to/disks/edit-disk.md'},
|
|
||||||
{text: 'Удаление диска', link: '/vdc/vdc-how-to/disks/delete-disk.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Сети', link: '/vdc/vdc-how-to/networks/networks-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Обзор', link: '/vdc/vdc-how-to/networks/about.md'},
|
|
||||||
{text: 'Настройка доступа к ВМ из интернета', link: '/vdc/vdc-how-to/networks/allow-external-connections-to-vm.md'},
|
|
||||||
{text: 'Подключение ВМ в vApp к сети', link: '/vdc/vdc-how-to/networks/connect-vapp-to-network.md'},
|
|
||||||
{text: 'Подключение ВМ к интернету', link: '/vdc/vdc-how-to/networks/connect-vm-to-network.md'},
|
|
||||||
{text: 'Создание сети в организации и подключение к Edge Gateway', link: '/vdc/vdc-how-to/networks/create-network.md'},
|
|
||||||
{text: 'Подключение сети к Edge Gateway', link: '/vdc/vdc-how-to/networks/connect-to-edge-gateway.md'},
|
|
||||||
{text: 'Создание Pre-Shared Key', link: '/vdc/vdc-how-to/networks/create-psk.md'},
|
|
||||||
{ text: 'Настройка site-to-site подключения с помощью IPSec', link: '/vdc/vdc-how-to/networks/how-to-setup-ipsec-vpn.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Настройка IPSec VPN', link: '/vdc/vdc-how-to/networks/ipsec/setup-ipsec-vpn.md'},
|
|
||||||
{text: 'Настройка ASAv', link: '/vdc/vdc-how-to/networks/ipsec/asav.md'},
|
|
||||||
{text: 'Настройка CSR 1000v', link: '/vdc/vdc-how-to/networks/ipsec/csr1000v.md'},
|
|
||||||
{text: 'Настройка Fortigate', link: '/vdc/vdc-how-to/networks/ipsec/fortigate.md'},
|
|
||||||
{text: 'Проверить сетевую связанность', link: '/vdc/vdc-how-to/networks/ipsec/check-vpn-status.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Пользователи и роли', link: '/vdc/vdc-how-to/users/users-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Ролевая модель', link: '/vdc/vdc-how-to/users/roles.md'},
|
|
||||||
{text: 'Создание пользователя', link: '/vdc/vdc-how-to/users/add-user.md'},
|
|
||||||
{text: 'Изменение пароля пользователя', link: '/vdc/vdc-how-to/users/change-users-password.md'},
|
|
||||||
{text: 'Настройка квот', link: '/vdc/vdc-how-to/users/quotas.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Двухфакторная аутентификация', link: '/vdc/vdc-how-to/vdc-2fa.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
|
||||||
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
|
||||||
'/compute/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные машины', link: '/compute/index.md',
|
|
||||||
},
|
|
||||||
{ text: 'Обзор сервиса', link: '/compute/compute-overview-index.md' ,
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Техническое описание', link: '/compute/compute-overview.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/compute/compute-quatos.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{text: 'Быстрый старт', link: '/compute/compute-getting-started.md'},
|
|
||||||
{ text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Создание ВМ', link: '/compute/compute-how-to/compute-servers-create.md' },
|
|
||||||
{ text: 'Создание ВМ джамп-хоста', link: '/compute/compute-how-to/compute-servers-jump-create.md' },
|
|
||||||
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Подключение по SSH по внешнему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-public.md'},
|
|
||||||
{ text: 'Подключение по SSH по внутреннему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-inside.md' },
|
|
||||||
{ text: 'Подключение по SSH по логину и паролю', link: '/compute/compute-how-to/compute-connect-pwd.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Управление ВМ', link: '/compute/compute-how-to/compute-servers-manage.md' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks/compute-disk-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-disks/compute-disk-about.md' },
|
|
||||||
{ text: 'Создание диска', link: '/compute/compute-how-to/compute-disks/compute-disk-create.md' },
|
|
||||||
{ text: 'Управление дисками', link: '/compute/compute-how-to/compute-disks/compute-disk-manage.md' },
|
|
||||||
{ text: 'Удаление диска', link: '/compute/compute-how-to/compute-disks/compute-disk-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-ip/compute-ip-about.md' },
|
|
||||||
{ text: 'Просмотр IP-адресов', link: '/compute/compute-how-to/compute-ip/compute-ip-view.md' },
|
|
||||||
{ text: 'Создание IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-create.md' },
|
|
||||||
{ text: 'Управление IP-адресами', link: '/compute/compute-how-to/compute-ip/compute-ip-manager.md' },
|
|
||||||
{ text: 'Удаление IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-about.md'},
|
|
||||||
{ text: 'Создание группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-create.md'},
|
|
||||||
{ text: 'Управление группами размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-manager.md' },
|
|
||||||
{ text: 'Удаление группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-del.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ text: 'Сети', link: '/compute/compute-how-to/compute-network/compute-network-index.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Настройка site-to-site VPN с помощью VyOS', link: '/compute/compute-how-to/compute-network/compute-vpn-vyos.md' },
|
|
||||||
{ text: 'Подключение ВМ закрытого контура к интернету', link: '/compute/compute-how-to/compute-network/compute-network-inside.md' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'/admin/': [
|
|
||||||
{
|
|
||||||
text: 'Администрирование', link: '/admin/index.md',
|
|
||||||
},
|
|
||||||
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
|
||||||
],
|
|
||||||
'/vdi/': [
|
|
||||||
{
|
|
||||||
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'О сервисе', link: '/vdi/vdi-about.md' },
|
|
||||||
{ text: 'Техническое описание', link: '/vdi/vdi-tech.md' },
|
|
||||||
{ text: 'Квоты и лимиты', link: '/vdi/vdi-quatos.md' },
|
|
||||||
{ text: 'Тарификация', link: '/vdi/vdi-tarif.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Заказ виртуальных рабочих столов', link: '/vdi/vdi-how-to/vdi-create.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Настройка сервиса', link: '/vdi/vdi-how-to/vdi-nastroika.md',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Настройка интеграции с Active Directory', link: '/vdi/vdi-how-to/vdi-connect-to-ad.md' },
|
|
||||||
{ text: 'Настройка сети', link: '/vdi/vdi-how-to/vdi-interconnect.md' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// text: 'Gold-образ', link: '/vdi/vdi-how-to/vdi-gold.md'
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
text: 'Подключение к виртуальному рабочему месту', link: '/vdi/vdi-how-to/vdi-connect.md'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import type { Plugin } from 'vite'
|
||||||
|
import type { SidebarItem } from './utils/types'
|
||||||
|
import { processAllFiles } from './hook/process-files'
|
||||||
|
|
||||||
|
export const autoSectionLinksPlugin = (
|
||||||
|
srcDir: string,
|
||||||
|
sidebarConfig: Record<string, SidebarItem[]>
|
||||||
|
): Plugin => ({
|
||||||
|
name: 'auto-section-links',
|
||||||
|
buildStart: () => {
|
||||||
|
processAllFiles(srcDir, sidebarConfig)
|
||||||
|
},
|
||||||
|
configureServer: () => {
|
||||||
|
processAllFiles(srcDir, sidebarConfig)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export const INDEX_FILE = 'index.md'
|
||||||
|
export const INDEX_FILE_PATTERN = /-index\.md$|index\.md$/
|
||||||
|
export const FRONTMATTER_REGEX = /^---\s*\n([\s\S]*?)\n---/
|
||||||
|
export const SECTION_LINK_KEYS = ['title', 'link', 'description'] as const
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { existsSync } from 'fs'
|
||||||
|
import { relative, resolve } from 'path'
|
||||||
|
import type { SidebarItem } from '../utils/types'
|
||||||
|
import { findMarkdownFiles } from '../utils/file-finder'
|
||||||
|
import { processIndexFile, processPageWithItems } from '../utils/file-processor'
|
||||||
|
import { INDEX_FILE, INDEX_FILE_PATTERN } from '../constants'
|
||||||
|
|
||||||
|
export const processAllFiles = (
|
||||||
|
srcDir: string,
|
||||||
|
sidebarConfig: Record<string, SidebarItem[]>
|
||||||
|
) => {
|
||||||
|
const srcPath = resolve(srcDir)
|
||||||
|
|
||||||
|
for (const [folderPath, items] of Object.entries(sidebarConfig)) {
|
||||||
|
const normalizedFolder = folderPath.replace(/^\/+|\/+$/g, '')
|
||||||
|
const folderFullPath = resolve(srcPath, normalizedFolder)
|
||||||
|
|
||||||
|
if (!existsSync(folderFullPath)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const mdFiles = findMarkdownFiles(folderFullPath)
|
||||||
|
|
||||||
|
for (const filePath of mdFiles) {
|
||||||
|
const fileName = filePath.split(/[/\\]/).pop() || ''
|
||||||
|
const relativePath = relative(srcPath, filePath).replace(/\\/g, '/')
|
||||||
|
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
||||||
|
|
||||||
|
if (fileName === INDEX_FILE) {
|
||||||
|
processIndexFile(filePath, items, srcPath)
|
||||||
|
} else if (INDEX_FILE_PATTERN.test(fileName) && fileName !== INDEX_FILE) {
|
||||||
|
processPageWithItems(filePath, items, srcPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { readFileSync, existsSync } from 'fs'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import { parseFrontmatter } from './frontmatter'
|
||||||
|
|
||||||
|
export const getPageDescription = (filePath: string, srcDir: string) => {
|
||||||
|
try {
|
||||||
|
const fullPath = resolve(srcDir, filePath.replace(/^\//, ''))
|
||||||
|
if (!existsSync(fullPath)) return undefined
|
||||||
|
|
||||||
|
const fileContent = readFileSync(fullPath, 'utf-8')
|
||||||
|
const { frontmatter } = parseFrontmatter(fileContent)
|
||||||
|
|
||||||
|
return frontmatter.description as string | undefined
|
||||||
|
} catch {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { readdirSync, statSync } from 'fs'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
export const findMarkdownFiles = (dir: string) => {
|
||||||
|
const files: string[] = []
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entries = readdirSync(dir)
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = join(dir, entry)
|
||||||
|
const stat = statSync(fullPath)
|
||||||
|
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
files.push(...findMarkdownFiles(fullPath))
|
||||||
|
} else if (entry.endsWith('.md')) {
|
||||||
|
files.push(fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
||||||
|
import { relative, resolve } from 'path'
|
||||||
|
import type { SidebarItem } from './types'
|
||||||
|
import { parseFrontmatter, stringifyFrontmatter } from './frontmatter'
|
||||||
|
import { mergeSectionLinks, extractTopLevelLinks, extractItemsForPage } from './links'
|
||||||
|
import { normalizeLink } from './path-utils'
|
||||||
|
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
||||||
|
|
||||||
|
const removeDuplicates = (links: SectionLinkListItem[]) => {
|
||||||
|
const result: SectionLinkListItem[] = []
|
||||||
|
const seenLinks = new Set<string>()
|
||||||
|
|
||||||
|
for (const link of links) {
|
||||||
|
if (link.link) {
|
||||||
|
const normalized = normalizeLink(link.link)
|
||||||
|
if (!seenLinks.has(normalized)) {
|
||||||
|
seenLinks.add(normalized)
|
||||||
|
result.push(link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasChanges = (
|
||||||
|
existingLinks: SectionLinkListItem[],
|
||||||
|
mergedLinks: SectionLinkListItem[]
|
||||||
|
) => {
|
||||||
|
if (existingLinks.length !== mergedLinks.length) return true
|
||||||
|
|
||||||
|
const existingSet = new Set(
|
||||||
|
existingLinks
|
||||||
|
.filter(link => link.link)
|
||||||
|
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
const mergedSet = new Set(
|
||||||
|
mergedLinks
|
||||||
|
.filter(link => link.link)
|
||||||
|
.map(link => `${normalizeLink(link.link!)}|${link.title}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (existingSet.size !== mergedSet.size) return true
|
||||||
|
|
||||||
|
for (const item of existingSet) {
|
||||||
|
if (!mergedSet.has(item)) return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export const processIndexFile = (
|
||||||
|
filePath: string,
|
||||||
|
sidebarItems: SidebarItem[],
|
||||||
|
srcDir: string
|
||||||
|
) => {
|
||||||
|
if (!existsSync(filePath)) return false
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fileContent = readFileSync(filePath, 'utf-8')
|
||||||
|
const { frontmatter, content } = parseFrontmatter(fileContent)
|
||||||
|
|
||||||
|
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
||||||
|
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
||||||
|
|
||||||
|
const existingLinks = removeDuplicates(
|
||||||
|
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
||||||
|
)
|
||||||
|
const newLinks = extractTopLevelLinks(sidebarItems, normalizedPath, srcDir)
|
||||||
|
|
||||||
|
if (!newLinks.length) return false
|
||||||
|
|
||||||
|
const mergedLinks = removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
||||||
|
|
||||||
|
if (!hasChanges(existingLinks, mergedLinks)) return false
|
||||||
|
|
||||||
|
frontmatter.section_links = mergedLinks
|
||||||
|
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const processPageWithItems = (
|
||||||
|
filePath: string,
|
||||||
|
sidebarItems: SidebarItem[],
|
||||||
|
srcDir: string
|
||||||
|
) => {
|
||||||
|
if (!existsSync(filePath)) return false
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fileContent = readFileSync(filePath, 'utf-8')
|
||||||
|
const { frontmatter, content } = parseFrontmatter(fileContent)
|
||||||
|
|
||||||
|
const relativePath = relative(srcDir, filePath).replace(/\\/g, '/')
|
||||||
|
const normalizedPath = relativePath.startsWith('/') ? relativePath : `/${relativePath}`
|
||||||
|
|
||||||
|
const existingLinks = removeDuplicates(
|
||||||
|
Array.isArray(frontmatter.section_links) ? [...frontmatter.section_links] : []
|
||||||
|
)
|
||||||
|
const newLinks = extractItemsForPage(sidebarItems, normalizedPath, srcDir)
|
||||||
|
|
||||||
|
const mergedLinks = newLinks.length > 0
|
||||||
|
? removeDuplicates(mergeSectionLinks(existingLinks, newLinks))
|
||||||
|
: []
|
||||||
|
|
||||||
|
if (!hasChanges(existingLinks, mergedLinks)) return false
|
||||||
|
|
||||||
|
frontmatter.section_links = mergedLinks
|
||||||
|
writeFileSync(filePath, stringifyFrontmatter(frontmatter, content), 'utf-8')
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
import type { Frontmatter } from './types'
|
||||||
|
import { SECTION_LINK_KEYS, FRONTMATTER_REGEX } from '../constants'
|
||||||
|
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
||||||
|
|
||||||
|
export const parseFrontmatter = (content: string) => {
|
||||||
|
const frontmatterMatch = content.match(FRONTMATTER_REGEX)
|
||||||
|
if (!frontmatterMatch) {
|
||||||
|
const cleanContent = content.replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
||||||
|
return { frontmatter: {}, content: cleanContent || content }
|
||||||
|
}
|
||||||
|
|
||||||
|
const [, frontmatterText] = frontmatterMatch
|
||||||
|
const frontmatterEnd = frontmatterMatch[0].length
|
||||||
|
let cleanContent = content.slice(frontmatterEnd)
|
||||||
|
cleanContent = cleanContent.replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
||||||
|
if (!cleanContent) {
|
||||||
|
cleanContent = content.slice(frontmatterEnd).replace(/^---[\s\S]*?---\s*\n*/g, '').trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const frontmatter: Frontmatter = {}
|
||||||
|
const lines = frontmatterText.split('\n')
|
||||||
|
let currentKey: string | undefined
|
||||||
|
let currentValue: SectionLinkListItem[] = []
|
||||||
|
let currentItem: Record<string, string> | undefined
|
||||||
|
let inArray = false
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const trimmed = line.trim()
|
||||||
|
if (trimmed && !trimmed.startsWith('#')) {
|
||||||
|
const lineIndent = line.match(/^(\s*)/)?.[1]?.length ?? 0
|
||||||
|
|
||||||
|
if (lineIndent === 0 && trimmed.includes(':')) {
|
||||||
|
if (inArray && currentKey) {
|
||||||
|
frontmatter[currentKey] = currentValue
|
||||||
|
currentValue = []
|
||||||
|
inArray = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const colonMatch = trimmed.match(/^([^:]+):\s*(.*)$/)
|
||||||
|
if (colonMatch) {
|
||||||
|
const [, key, value] = colonMatch
|
||||||
|
currentKey = key.trim()
|
||||||
|
const trimmedValue = value.trim()
|
||||||
|
|
||||||
|
if (trimmedValue === '') {
|
||||||
|
inArray = true
|
||||||
|
currentValue = []
|
||||||
|
} else {
|
||||||
|
frontmatter[currentKey] = trimmedValue.replace(/^["']|["']$/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (lineIndent === 2 && trimmed.startsWith('- ')) {
|
||||||
|
if (!inArray && currentKey) {
|
||||||
|
inArray = true
|
||||||
|
currentValue = []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentItem && currentItem.title && currentItem.link !== undefined) {
|
||||||
|
const link: SectionLinkListItem = {
|
||||||
|
title: currentItem.title,
|
||||||
|
link: currentItem.link,
|
||||||
|
description: currentItem.description
|
||||||
|
}
|
||||||
|
if (!currentValue.some(item => item.link === link.link)) {
|
||||||
|
currentValue.push(link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemText = trimmed.slice(2).trim()
|
||||||
|
if (itemText.includes(':')) {
|
||||||
|
currentItem = {}
|
||||||
|
const parts = itemText.split(',').map(p => p.trim())
|
||||||
|
for (const part of parts) {
|
||||||
|
const colonMatch = part.match(/^(\w+):\s*(.+)$/)
|
||||||
|
if (colonMatch) {
|
||||||
|
const [, key, value] = colonMatch
|
||||||
|
if (SECTION_LINK_KEYS.includes(key as typeof SECTION_LINK_KEYS[number])) {
|
||||||
|
currentItem[key] = value.replace(/^["']|["']$/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentValue.push({ title: itemText, link: '' })
|
||||||
|
}
|
||||||
|
} else if (lineIndent >= 4 && currentItem && trimmed.includes(':')) {
|
||||||
|
const colonIndex = trimmed.indexOf(':')
|
||||||
|
if (colonIndex !== -1) {
|
||||||
|
const key = trimmed.substring(0, colonIndex).trim()
|
||||||
|
const value = trimmed.substring(colonIndex + 1).trim()
|
||||||
|
if (SECTION_LINK_KEYS.includes(key as typeof SECTION_LINK_KEYS[number])) {
|
||||||
|
currentItem[key] = value === '' ? '' : value.replace(/^["']|["']$/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentItem && inArray && currentItem.title && currentItem.link !== undefined) {
|
||||||
|
const link: SectionLinkListItem = {
|
||||||
|
title: currentItem.title,
|
||||||
|
link: currentItem.link,
|
||||||
|
description: currentItem.description
|
||||||
|
}
|
||||||
|
if (!currentValue.some(item => item.link === link.link)) {
|
||||||
|
currentValue.push(link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inArray && currentKey) {
|
||||||
|
frontmatter[currentKey] = currentValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return { frontmatter, content: cleanContent || content }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const stringifyFrontmatter = (frontmatter: Frontmatter, content: string) => {
|
||||||
|
const lines: string[] = []
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(frontmatter)) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
lines.push(`${key}:`)
|
||||||
|
for (const item of value) {
|
||||||
|
if (typeof item === 'object' && item) {
|
||||||
|
const link = item as SectionLinkListItem
|
||||||
|
lines.push(` - title: ${link.title ?? ''}`)
|
||||||
|
if (link.link) lines.push(` link: ${link.link}`)
|
||||||
|
if ('description' in link && link.description !== undefined && link.description !== null && String(link.description).trim() !== '') {
|
||||||
|
lines.push(` description: ${String(link.description)}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lines.push(` - ${item}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (value) {
|
||||||
|
const strValue = String(value)
|
||||||
|
const needsQuotes = strValue.includes(':') || (strValue.includes(' ') && !strValue.startsWith('"')) || strValue === ''
|
||||||
|
const escaped = strValue.replace(/"/g, '\\"')
|
||||||
|
lines.push(`${key}: ${needsQuotes ? `"${escaped}"` : strValue}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return `---\n${lines.join('\n')}\n---\n\n${content}`
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import type { SidebarItem } from './types'
|
||||||
|
import { getPageDescription } from './descriptions'
|
||||||
|
import { normalizeLink } from './path-utils'
|
||||||
|
import { SectionLinkListItem } from '../../theme/components/SectionLinkList/SectionLinkList.types'
|
||||||
|
|
||||||
|
export const mergeSectionLinks = (
|
||||||
|
existingLinks: SectionLinkListItem[],
|
||||||
|
newLinks: SectionLinkListItem[]
|
||||||
|
) => {
|
||||||
|
const existingLinksMap = new Map<string, SectionLinkListItem>()
|
||||||
|
const result: SectionLinkListItem[] = []
|
||||||
|
const processedLinks = new Set<string>()
|
||||||
|
|
||||||
|
for (const existingLink of existingLinks) {
|
||||||
|
if (existingLink.link) {
|
||||||
|
const normalizedLink = normalizeLink(existingLink.link)
|
||||||
|
if (!existingLinksMap.has(normalizedLink)) {
|
||||||
|
existingLinksMap.set(normalizedLink, existingLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const newLink of newLinks) {
|
||||||
|
if (newLink.link) {
|
||||||
|
const normalizedLink = normalizeLink(newLink.link)
|
||||||
|
|
||||||
|
if (!processedLinks.has(normalizedLink)) {
|
||||||
|
processedLinks.add(normalizedLink)
|
||||||
|
|
||||||
|
if (existingLinksMap.has(normalizedLink)) {
|
||||||
|
const existingLink = existingLinksMap.get(normalizedLink)!
|
||||||
|
result.push({ ...existingLink, title: newLink.title })
|
||||||
|
} else {
|
||||||
|
result.push(newLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extractTopLevelLinks = (
|
||||||
|
items: SidebarItem[],
|
||||||
|
currentIndexPath: string,
|
||||||
|
srcDir: string
|
||||||
|
) => {
|
||||||
|
const links: SectionLinkListItem[] = []
|
||||||
|
const normalizedCurrentPath = normalizeLink(currentIndexPath)
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
if ('excludeFromIndex' in item && item.excludeFromIndex) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.link) {
|
||||||
|
const normalizedItemPath = normalizeLink(item.link)
|
||||||
|
if (normalizedItemPath === normalizedCurrentPath) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
links.push({
|
||||||
|
title: item.text || '',
|
||||||
|
link: item.link,
|
||||||
|
description: getPageDescription(item.link, srcDir)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
const findItemsRecursive = (
|
||||||
|
itemsList: SidebarItem[],
|
||||||
|
pagePath: string,
|
||||||
|
srcDir: string
|
||||||
|
): SectionLinkListItem[] => {
|
||||||
|
const normalizedPagePath = normalizeLink(pagePath)
|
||||||
|
const links: SectionLinkListItem[] = []
|
||||||
|
|
||||||
|
for (const item of itemsList) {
|
||||||
|
if (item.link) {
|
||||||
|
const normalizedItemPath = normalizeLink(item.link)
|
||||||
|
|
||||||
|
if (normalizedItemPath === normalizedPagePath && item.items && Array.isArray(item.items) && item.items.length > 0) {
|
||||||
|
for (const subItem of item.items) {
|
||||||
|
if ('excludeFromIndex' in subItem && subItem.excludeFromIndex) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subItem.link) {
|
||||||
|
links.push({
|
||||||
|
title: subItem.text || '',
|
||||||
|
link: subItem.link,
|
||||||
|
description: getPageDescription(subItem.link, srcDir)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.items && Array.isArray(item.items)) {
|
||||||
|
const found = findItemsRecursive(item.items, pagePath, srcDir)
|
||||||
|
if (found.length > 0) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return links
|
||||||
|
}
|
||||||
|
|
||||||
|
export const extractItemsForPage = (
|
||||||
|
items: SidebarItem[],
|
||||||
|
pagePath: string,
|
||||||
|
srcDir: string
|
||||||
|
) => findItemsRecursive(items, pagePath, srcDir)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export const normalizeLink = (link: string): string =>
|
||||||
|
!link ? '' : link
|
||||||
|
.replace(/^\/+/, '')
|
||||||
|
.replace(/\.md$/, '')
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.trim()
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { SectionLinkListItem } from "../../theme/components/SectionLinkList/SectionLinkList.types"
|
||||||
|
|
||||||
|
export type SidebarItem = {
|
||||||
|
text: string
|
||||||
|
link?: string
|
||||||
|
items?: SidebarItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Frontmatter = {
|
||||||
|
section_links?: SectionLinkListItem[]
|
||||||
|
[key: string]: string | number | boolean | string[] | SectionLinkListItem[] | undefined
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ export type SectionLinkListItem = {
|
|||||||
title: string,
|
title: string,
|
||||||
link: string,
|
link: string,
|
||||||
description?: string
|
description?: string
|
||||||
|
collapsed?: boolean
|
||||||
|
excludeFromIndex?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SectionLinkListProps = {
|
export type SectionLinkListProps = {
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
section_links:
|
|
||||||
- title: Назначение сервиса
|
|
||||||
link: /Apache-Kafka/about-service.md
|
|
||||||
description: Назначения и преимущества сервиса
|
|
||||||
- title: Работа с кластером Kafka по тарифу Base
|
|
||||||
link: /Apache-Kafka/base-tier-connection.md
|
|
||||||
description: Подключение и работа с кластером Kafka по тарифу Base
|
|
||||||
- title: Настройка топика по тарифу Base
|
|
||||||
link: /Apache-Kafka/base-tier-topics-guide.md
|
|
||||||
description: Рекомендации по настройке топика Kafka по тарифу Base
|
|
||||||
- title: Конфигурация кластера
|
|
||||||
link: /Apache-Kafka/cluster-configuretion.md
|
|
||||||
description: Конфигурации и возможности кластера Kafka
|
|
||||||
- title: Работа с кластером Kafka по тарифу Full
|
|
||||||
link: /Apache-Kafka/full-tier-connection.md
|
|
||||||
description: Подключение и работа с кластером Kafka по тарифу Full
|
|
||||||
---
|
|
||||||
|
|
||||||
# Apache-Kafka
|
|
||||||
|
|
||||||
В данном разделе представлена документация по управляемому сервису **Apache-Kafka** платформы Beeline Cloud.
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
# Назначение сервиса
|
|
||||||
|
|
||||||
Данный сервис предназначен для команд, которым требуется надёжный и масштабируемый конвейер данных без необходимости самостоятельно разворачивать и обслуживать инфраструктуру Kafka.
|
|
||||||
|
|
||||||
**Apache Kafka** - это распределённая система для потоковой передачи данных в реальном времени. Сервис обеспечивает надёжную и масштабируемую доставку сообщений между компонентами приложений, гарантируя отказоустойчивость и высокую производительность.
|
|
||||||
|
|
||||||
В архитектуре современных информационных систем Kafka выполняет роль централизованного конвейера данных: одни сервисы (продюсеры) публикуют сообщения, а другие (консьюмеры) получают эти сообщения по мере необходимости.
|
|
||||||
|
|
||||||
## Основные понятия
|
|
||||||
|
|
||||||
| Термин | Описание |
|
|
||||||
|--------------------------------|----------|
|
|
||||||
| **Продюсер (Producer)** | Программный компонент, который отправляет данные в Kafka. Продюсером может выступать любой сервис, генерирующий события: модуль приложения, система логирования, датчик IoT-устройства. |
|
|
||||||
| **Консьюмер (Consumer)** | Программный компонент, который получает данные из Kafka. Консьюмер подписывается на интересующие его события и обрабатывает поступающие сообщения. |
|
|
||||||
| **Топик (Topic)** | Именованный канал для хранения сообщений определённого типа. Топики организуют потоки данных по смыслу: например, «заказы», «ошибки», «события авторизации». Консьюмеры подписываются на один или несколько топиков для получения релевантных данных. |
|
|
||||||
| **Партиция (Partition)** | Каждый топик разделяется на партиции - логические сегменты, распределяемые между серверами кластера. Партиции обеспечивают параллельную обработку данных: различные части одного топика могут обрабатываться одновременно несколькими консьюмерами. |
|
|
||||||
| **Репликация (Replication)** | Для обеспечения отказоустойчивости партиции копируются на несколько серверов (брокеров). При выходе одного сервера из строя данные остаются доступными на других узлах кластера. |
|
|
||||||
| **Микросервисная архитектура** | Kafka является стандартным решением для организации связи между микросервисами. В такой архитектуре сервисы обмениваются событиями асинхронно, что повышает надёжность и масштабируемость системы в целом. |
|
|
||||||
|
|
||||||
## Преимущества управляемого сервиса
|
|
||||||
|
|
||||||
#### Администрирование
|
|
||||||
|
|
||||||
Клиенту не требуется самостоятельно разворачивать и обслуживать кластер Kafka. Сервис включает в себя управление инфраструктурой, обновление версий, масштабирование и поддержку работоспособности.
|
|
||||||
|
|
||||||
#### Мониторинг
|
|
||||||
|
|
||||||
Предоставляются готовые дашборды в Grafana с визуализацией ключевых метрик:
|
|
||||||
|
|
||||||
- состояние брокеров;
|
|
||||||
- нагрузка на кластер;
|
|
||||||
- настроенная система оповещений о критических событиях;
|
|
||||||
- заполнение дискового пространства.
|
|
||||||
|
|
||||||
#### Безопасность
|
|
||||||
|
|
||||||
Поддерживается шифрованное подключение к кластеру с использованием SSL/TLS-сертификатов, что гарантирует защиту данных при передаче.
|
|
||||||
|
|
||||||
#### Экспертная поддержка
|
|
||||||
|
|
||||||
Сервис создан с учётом практического опыта администрирования более 500 кластеров Kafka. Накопленная экспертиза позволяет обеспечивать стабильность работы, своевременно выявлять и устранять потенциальные проблемы, оптимизировать конфигурации под конкретные задачи.
|
|
||||||
|
|
||||||
## Тарифные планы
|
|
||||||
|
|
||||||
### 1. Тариф "Base"
|
|
||||||
|
|
||||||
Тарифный план для тех, кто имеет собственную экспертизу в работе с Kafka и желает самостоятельно управлять объектами верхнего уровня.
|
|
||||||
|
|
||||||
**Обязательства провайдера:**
|
|
||||||
|
|
||||||
- поддержка инсталляции кластера;
|
|
||||||
- своевременное обновление версий Kafka;
|
|
||||||
- расширение вычислительных ресурсов кластера по запросу клиента.
|
|
||||||
|
|
||||||
**Возможности:**
|
|
||||||
|
|
||||||
- **Управление учетными записями и правами доступа** – создание пользователей и настройка их прав для работы с Kafka;
|
|
||||||
- **Администрирование топиков** - полный цикл управления: создание, конфигурирование, настройка параметров и удаление;
|
|
||||||
- **Управление консьюмер-группами (Consumer Groups)** – возможность создавать, изменять и удалять логические объединения консьюмеров, которые совместно читают сообщения из топиков. Это обеспечивает высокую производительность и отказоустойчивость при обработке данных;
|
|
||||||
- **Работа с transactional ID** – полный цикл управления транзакционными идентификаторами (создание, изменение, удаление). Транзакционный идентификатор присваивается продюсеру Kafka для обеспечения атомарности операций: запись нескольких сообщений или коммит оффсетов выполняются по принципу «всё или ничего», а также предотвращается появление «зомби-продюсеров» при перезапусках.
|
|
||||||
|
|
||||||
Инфраструктурное ядро кластера (брокеры, репликация, отказоустойчивость) остаётся под управлением провайдера.
|
|
||||||
|
|
||||||
### 2. Тариф "Full"
|
|
||||||
|
|
||||||
Тарифный план для тех, кто предпочитает полностью делегировать задачи по администрированию Kafka.
|
|
||||||
|
|
||||||
**Обязательства провайдера:**
|
|
||||||
|
|
||||||
- полное управление кластером;
|
|
||||||
- администрирование топиков;
|
|
||||||
- управление консьюмер-группами;
|
|
||||||
- работа с transactional id.
|
|
||||||
|
|
||||||
Kafka используется как готовый сервис, не вовлекаясь в вопросы настройки и обслуживания.
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
# Подключение и работа с кластером Kafka (тариф Base)
|
|
||||||
|
|
||||||
Раздел содержит описание способов подключения к управлению кластером Kafka. Поддерживаются два типа подключения:
|
|
||||||
- `SASL_PLAINTEXT` - незашифрованное;
|
|
||||||
- `SASL_SSL` - зашифрованное (через SSL-сертификат).
|
|
||||||
|
|
||||||
Также в разделе приведены примеры работы с клиентскими утилитами и базовые операции администрирования.
|
|
||||||
|
|
||||||
## Предварительные требования
|
|
||||||
|
|
||||||
Для начала работы с кластером Kafka необходимо выполнить предварительную настройку:
|
|
||||||
|
|
||||||
1. **Установить клиент Kafka** - скачивается дистрибутив Kafka (например, kafka_2.13-4.2.0) и распаковывается в удобную директорию;
|
|
||||||
2. **Установить среду выполнения Java** - для работы необходимо установить среду выполнения, с помощью команды: `sudo apt install openjdk-17-jre-headless`. Рекомендуется использовать версию OpenJDK 17 или выше;
|
|
||||||
3. **Доступ к брокерам** - адреса брокеров (bootstrap servers) предоставляются после развертывания кластера;
|
|
||||||
4. **Учетные данные**:
|
|
||||||
- **Имя пользователя (username)** - стандартное значение client;
|
|
||||||
- **Пароль** - предоставляется после развертывания кластера.
|
|
||||||
5. **Корневой сертификат (для SSL-подключения)** - сертификат для зашифрованного подключения предоставляется файлом при заказе сервиса Kafka.
|
|
||||||
|
|
||||||
## Структура клиентского дистрибутива
|
|
||||||
|
|
||||||
После распаковки архива Kafka в директории bin доступны основные скрипты для управления:
|
|
||||||
|
|
||||||
| Скрипт | Назначение |
|
|
||||||
| --------------------------- | -------------------------------------------------- |
|
|
||||||
| `kafka-topics.sh` | Управление топиками (создание, удаление, просмотр) |
|
|
||||||
| `kafka-console-producer.sh` | Отправка сообщений в топик |
|
|
||||||
| `kafka-console-consumer.sh` | Чтение сообщений из топика |
|
|
||||||
| `kafka-consumer-groups.sh` | Управление консьюмер-группами |
|
|
||||||
| `kafka-configs.sh` | Изменение конфигурации топиков и других объектов |
|
|
||||||
| `kafka-acls.sh` | Управление списками доступа (ACL) |
|
|
||||||
|
|
||||||
В разделе ниже приведены примеры использования скриптов.
|
|
||||||
|
|
||||||
Подробное описание операций с данными и другими скриптами приведено в [официальной документации Kafka](https://kafka.apache.org/42/getting-started/introduction/). Дополнительную информацию можно получить, выполнив любой скрипт с флагом --help:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-topics.sh --help
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Конфигурационные файлы клиента
|
|
||||||
|
|
||||||
Для подключения к Kafka используется файл настроек **client.properties**, который содержит параметры аутентификации, протокола и его механизмов (рекомендуются SCRAM_SHA_512 и SCRAM_SHA_256).
|
|
||||||
|
|
||||||
## Незашифрованное подключение (SASL_PLAINTEXT)
|
|
||||||
|
|
||||||
Создается файл **client.properties** со следующим содержимым:
|
|
||||||
|
|
||||||
```
|
|
||||||
sasl.mechanism=SCRAM-SHA-512
|
|
||||||
security.protocol=SASLPLAINTEXT
|
|
||||||
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
|
|
||||||
username="client" \
|
|
||||||
password="вашпароль";
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для незашифрованного подключения (SASL_PLAINTEXT) используется порт 9091;
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Зашифрованное подключение (SASL_SSL)
|
|
||||||
|
|
||||||
Для зашифрованного подключения (в production-средах рекомендуется использовать именно его) дополнительно требуется корневой сертификат и хранилище доверенных сертификатов (truststore).
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для зашифрованного подключения (SASL_SSL) используется порт 9092.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Шаг 1. Создание truststore
|
|
||||||
|
|
||||||
С помощью утилиты **keytool** выполняется импорт сертификата в хранилище:
|
|
||||||
|
|
||||||
```
|
|
||||||
keytool -importcert -storetype PKCS12 -keystore /путь/к/трастстору/truststore.jks -alias myalias -file ca.crt -storepass любойвашпароль -keypass любойвашпароль
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **keystore** - путь к создаваемому хранилищу;
|
|
||||||
- **alias** - псевдоним сертификата в хранилище;
|
|
||||||
- **file** - путь к загруженному корневому сертификату;
|
|
||||||
- **storepass** - пароль для доступа к хранилищу;
|
|
||||||
- **keypass** - пароль для доступа к ключу.
|
|
||||||
|
|
||||||
### Шаг 2. Настройка client.properties
|
|
||||||
|
|
||||||
В файл **client.properties** добавляются параметры SSL:
|
|
||||||
|
|
||||||
```
|
|
||||||
sasl.mechanism=SCRAM-SHA-512
|
|
||||||
security.protocol=SASLSSL
|
|
||||||
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
|
|
||||||
username="client" \
|
|
||||||
password="вашпароль";
|
|
||||||
ssl.truststore.location=/путь/к/трастстору/truststore.jks
|
|
||||||
ssl.truststore.password=парольотхранилища
|
|
||||||
```
|
|
||||||
|
|
||||||
## Работа с кластером Kafka
|
|
||||||
|
|
||||||
### Создание топиков
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-topics.sh --bootstrap-server <IP машины 0>:9092,<IP машины 1>:9092,<IP машины X>:9092 --command-config ../config/client.properties --create --topic <имя топика> --partitions <количество партиций> --replication-factor <значение> --config min.insync.replicas=<значение>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Ознакомиться с рекомендациями по настройке топиков можно в разделе [Настройка топиков](./base-tier-topics-guide.md).**
|
|
||||||
|
|
||||||
По умолчанию топик создаётся с --partitions 10 --replication-factor 3 --config min.insync.replicas=2, поэтому, если нет необходимости создавать топик со специфическими настройками, эти флаги в команде можно не указывать.
|
|
||||||
|
|
||||||
### Просмотр списка топиков
|
|
||||||
|
|
||||||
Выполняется команда с указанием брокеров и файла конфигурации:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-topics.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_2>:9092 --command-config ~/client.properties --list
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **bootstrap-server** - список брокеров кластера (адреса и порты);
|
|
||||||
command-config - путь к файлу с настройками клиента;
|
|
||||||
- **list** - вывод списка топиков.
|
|
||||||
|
|
||||||
### Отправка сообщения в топик
|
|
||||||
|
|
||||||
Выполняется команда с указанием брокеров, файла конфигурации и топика:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-console-producer.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_2>:9092 --command-config~/client.properties --topic test-topic
|
|
||||||
```
|
|
||||||
|
|
||||||
После выполнения команды сообщения вводятся построчно. Для завершения используется сочетание клавиш Ctrl+C.
|
|
||||||
|
|
||||||
### Чтение сообщений из топика
|
|
||||||
|
|
||||||
Выполняется команда с указанием топика и, при необходимости, consumer group:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-console-consumer.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_2>:9092 --command-config~/client.properties --topic test-topic --from-beginning --group my-new-consumer-group
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **from-beginning**- чтение всех сообщений с начала (при отсутствии параметра чтение начинается с новых сообщений);
|
|
||||||
- **group** - название consumer group, которая создастся автоматически.
|
|
||||||
|
|
||||||
## Управление пользователями и доступом
|
|
||||||
|
|
||||||
### Рекомендации к созданию пароля
|
|
||||||
|
|
||||||
**Длина пароля (рекомендуемая):**
|
|
||||||
|
|
||||||
- для учётной записи пользователя - не менее 12 знаков;
|
|
||||||
- для учётных записей администраторов, технических и служебных учётных записей - не менее 16 знаков.
|
|
||||||
|
|
||||||
**Сложность пароля:** рекомендуется использовать уникальный пароль, содержащий символы как минимум трёх из четырёх указанных ниже групп (при отсутствии технических ограничений):
|
|
||||||
|
|
||||||
- буквы латинского алфавита в верхнем регистре (A-Z);
|
|
||||||
- буквы латинского алфавита в нижнем регистре (a-z);
|
|
||||||
- цифры (0-9);
|
|
||||||
- специальные символы и знаки пунктуации (например, `!@#$%^&*(),.?`).
|
|
||||||
|
|
||||||
**Периодичность смены:** рекомендуемая периодичность смены пароля - не реже одного раза в год.
|
|
||||||
|
|
||||||
### Создание пользователей
|
|
||||||
|
|
||||||
Для удобства можно написать скрипт, который создает пользователя сразу для двух методов шифрования - SHA-256 и SHA-512:
|
|
||||||
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
|
||||||
username="имя_пользователя"
|
|
||||||
password="сгенерированный_пароль"
|
|
||||||
bootstrap="<IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_X>:9092"
|
|
||||||
|
|
||||||
/opt/kafka/bin/kafka-configs.sh \
|
|
||||||
--bootstrap-server $bootstrap \
|
|
||||||
--alter \
|
|
||||||
--add-config SCRAM-SHA-256=[password="$password"] \
|
|
||||||
--command-config /opt/kafka/config/client.properties \
|
|
||||||
--entity-type users \
|
|
||||||
--entity-name $username
|
|
||||||
|
|
||||||
/opt/kafka/bin/kafka-configs.sh \
|
|
||||||
--bootstrap-server $bootstrap \
|
|
||||||
--alter \
|
|
||||||
--add-config SCRAM-SHA-512=[password="$password"] \
|
|
||||||
--command-config /opt/kafka/config/client.properties \
|
|
||||||
--entity-type users \
|
|
||||||
--entity-name $username
|
|
||||||
```
|
|
||||||
|
|
||||||
**Запуск скрипта:**
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo ./kafka-user-add.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Просмотр данных о пользователе
|
|
||||||
|
|
||||||
Для просмотра информации о существующих пользователях выполняется команда:
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo ./kafka-console-consumer.sh --bootstrap-server <IP_брокеров>:9092 --describe --command-config ../config/client.properties --entity-type users
|
|
||||||
```
|
|
||||||
|
|
||||||
### Управление consumer groups
|
|
||||||
|
|
||||||
Consumer Group создается автоматически при обращении к ней. Например, при чтении сообщений из топика с указанием этой consumer group:
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo ./kafka-console-consumer.sh --bootstrap-server <IP_брокеров>:9092 --command-config ../config/client.properties --topic test-topic --group test-group --from-beginning
|
|
||||||
```
|
|
||||||
|
|
||||||
### Просмотр списка ACL
|
|
||||||
|
|
||||||
Действия с ACL из командной строки осуществляются скриптом kafka-acls.sh. Пример просмотра списка ACL:
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo ./kafka-acls.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_X>:9092 --command-config ../config/client.properties --list
|
|
||||||
```
|
|
||||||
|
|
||||||
## Администрирование кластера
|
|
||||||
|
|
||||||
#### Изменение объема RAM
|
|
||||||
|
|
||||||
Для изменения объема оперативной памяти, выделенной под Kafka, направляется обращение в техническую поддержку с указанием требуемого объема RAM.
|
|
||||||
|
|
||||||
#### Изменение количества брокеров
|
|
||||||
|
|
||||||
Выполняется также через обращение в техническую поддержку.
|
|
||||||
|
|
||||||
Брокеров в кластере рекомендуется поддерживать **нечетным** для корректной работы механизмов выборов лидера.
|
|
||||||
|
|
||||||
После добавления брокера выполняется перераспределение существующих партиций с учетом нового узла с помощью утилиты **kafka-reassign-partitions.sh:**
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-reassign-partitions.sh --bootstrap-server <адреса_брокеров> --generate --topics-to-move-json-file topics.json --broker-list "0,1,2" --execute
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Операция перераспределения партиций требует времени и может создавать дополнительную нагрузку на кластер. Выполнение рекомендуется в период наименьшей активности.
|
|
||||||
:::
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
# Рекомендации по настройке топика (тариф Base)
|
|
||||||
|
|
||||||
В разделе описаны основные параметры топиков Apache Kafka, влияющие на производительность, отказоустойчивость и параллелизм обработки данных.
|
|
||||||
|
|
||||||
## Базовые параметры топика
|
|
||||||
|
|
||||||
### Имя топика
|
|
||||||
|
|
||||||
При именовании топика применяются следующие правила:
|
|
||||||
|
|
||||||
**Допустимые символы:**
|
|
||||||
- первый символ — буква (a–z, A–Z), цифра (0–9) или подчёркивание (_);
|
|
||||||
- последующие символы — буквы, цифры, точки (.), дефисы (-) или подчёркивания;
|
|
||||||
- длина имени — от 3 до 200 символов.
|
|
||||||
|
|
||||||
**Ограничения:**
|
|
||||||
- имя топика нельзя изменить после создания;
|
|
||||||
- не рекомендуется использовать имена, различающиеся только точкой и подчёркиванием (например, `topic_1` и `topic.1`): Kafka не различает такие названия;
|
|
||||||
- имена с двойным подчёркиванием в начале (например, `__consumer_offsets`) зарезервированы для внутренних топиков Kafka.
|
|
||||||
|
|
||||||
### Количество партиций (partitions)
|
|
||||||
|
|
||||||
Партиции определяют уровень параллелизма при чтении и записи данных. Количество партиций выбирается исходя из требуемой пропускной способности.
|
|
||||||
|
|
||||||
**Правила:**
|
|
||||||
- количество партиций можно только увеличивать (уменьшение невозможно);
|
|
||||||
- при наличии нескольких брокеров рекомендуется выбирать число партиций, кратное количеству брокеров — для равномерного распределения нагрузки;
|
|
||||||
- рекомендуется мониторить отставание потребителей (consumer lag) и при необходимости увеличивать число партиций.
|
|
||||||
|
|
||||||
**Расчет количества партиций:**
|
|
||||||
Количество партиций определяется по формуле:
|
|
||||||
|
|
||||||
```
|
|
||||||
Partitions = max(NP, NC)
|
|
||||||
```
|
|
||||||
где:
|
|
||||||
- NP = TT / TP - количество необходимых продюсеров;
|
|
||||||
- NC = TT / TC - количество необходимых консьюмеров;
|
|
||||||
- TT - общая ожидаемая пропускная способность системы;
|
|
||||||
- TP - максимальная пропускная способность одного продюсера для одной партиции;
|
|
||||||
- TC - максимальная пропускная способность одного консьюмера для одной партиции.
|
|
||||||
|
|
||||||
## Фактор репликации (replication-factor)
|
|
||||||
|
|
||||||
Фактор репликации определяет количество копий данных, хранящихся на разных брокерах.
|
|
||||||
|
|
||||||
**Рекомендация для production-сред:** установите значение **3**.
|
|
||||||
При этом каждая партиция получает одного лидера и две реплики, что обеспечивает отказоустойчивость при выходе одного брокера.
|
|
||||||
|
|
||||||
## Дополнительные параметры конфигурации
|
|
||||||
|
|
||||||
Параметр `min.insync.replicas` (минимальное количество синхронизированных реплик) работает вместе с настройкой продюсера `acks=all`. Он задаёт, сколько реплик (включая лидера) должны подтвердить запись, чтобы она считалась успешной.
|
|
||||||
|
|
||||||
**Для production-кластера с фактором репликации = 3**
|
|
||||||
Установите `min.insync.replicas = 2`.
|
|
||||||
|
|
||||||
Что это даёт:
|
|
||||||
|
|
||||||
- **надёжность** — данные точно попали минимум на два брокера;
|
|
||||||
- **доступность** — если один брокер упадёт, запись продолжится.
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Не рекомендуется устанавливать значение равным фактору репликации (например, `min.insync.replicas = 3`). Если один брокер перезагрузится, запись в топик станет невозможной — система будет ждать подтверждения от всех трёх реплик, а одна недоступна.
|
|
||||||
:::
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
# Конфигурация кластера
|
|
||||||
|
|
||||||
В разделе описаны технические параметры кластера Kafka и порядок их первичной настройки.
|
|
||||||
|
|
||||||
Конфигурация выполняется администратором облачного провайдера на этапе развёртывания сервиса. Пользователь не имеет прямого доступа к изменению этих параметров. Перед созданием кластера клиент передаёт менеджеру перечень требуемых параметров. Администратор выполняет настройку в соответствии с согласованными требованиями.
|
|
||||||
|
|
||||||
## Выбор типа и размера дискового хранилища
|
|
||||||
|
|
||||||
Производительность брокера сообщений напрямую зависит от скорости чтения и записи на диск. При заказе кластера необходимо выбрать тип дискового хранилища — он определяет максимальную скорость работы (IOPS) и время отклика.
|
|
||||||
|
|
||||||
**IOPS** (Input/Output Operations Per Second) — количество операций чтения или записи, которые диск выполняет за секунду. Чем выше IOPS, тем быстрее брокер обрабатывает запросы.
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Каждые 15 IOPS обеспечивают примерно 1 Мбит/с скорости чтения или записи при размере блока данных 64 КБ.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Доступные типы хранилищ:
|
|
||||||
|
|
||||||
|Название | Лимит IOPS |
|
|
||||||
|---------------|--------------------|
|
|
||||||
|**Fast SAS** | до 2 IOPS на 1 ГБ |
|
|
||||||
|**SSD** | до 5 IOPS на 1 ГБ |
|
|
||||||
|**Fast SSD** | до 10 IOPS на 1 ГБ |
|
|
||||||
|**Ultra NVMe** | до 25 IOPS на 1 ГБ |
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
После выбора типа диска необходимо указать объем дискового хранилища, который будет выделен под данные кластера Kafka. Минимальный объем зависит от выбранного типа хранилища
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Конфигурация вычислительных ресурсов
|
|
||||||
|
|
||||||
В данном разделе определяются вычислительные мощности кластера: процессорные ресурсы, оперативная память и количество серверов (нод), из которых будет состоять кластер Kafka.
|
|
||||||
|
|
||||||
#### Основные понятия
|
|
||||||
|
|
||||||
| Термин | Описание |
|
|
||||||
|-------------------------------|----------|
|
|
||||||
| **Количество нод в кластере** | Количество нод определяет отказоустойчивость кластера и возможность распределять запросы на чтение между репликами. Чем больше нод, тем выше надежность и производительность чтения. Количество нод выбирается в диапазоне от 3 до 14. |
|
|
||||||
| **Процессор (CPU)** | Процессор - это вычислительная мощность, которая выделяется каждой ноде кластера. Количество vCPU определяет, насколько быстро брокер сообщений сможет обрабатывать запросы, выполнять сложные операции (сортировки, объединения таблиц) и обслуживать одновременные подключения. Доступный диапазон выбора процессора: от 2 шт до 24 шт. |
|
|
||||||
| **Оперативная память (RAM)** | Оперативная память - один из ключевых ресурсов для производительности. Данные, помещающиеся в RAM, обрабатываются максимально быстро, без обращения к диску. Доступный диапазон выбора оперативной памяти: от 4 ГБ до 768 ГБ. |
|
|
||||||
|
|
||||||
## Интернет
|
|
||||||
|
|
||||||
При заказе сервиса можно выбрать пропускную способность канала связи, через который будет осуществляться доступ к кластеру Kafka из сети интернет.
|
|
||||||
|
|
||||||
**Доступные варианты скорости:**
|
|
||||||
|
|
||||||
- 50 Мбит/с;
|
|
||||||
- 100 Мбит/с;
|
|
||||||
- 200 Мбит/с;
|
|
||||||
- 300 Мбит/с;
|
|
||||||
- 400 Мбит/с;
|
|
||||||
- 500 Мбит/с;
|
|
||||||
- 1000 Мбит/с (1 Гбит/с).
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для выбранного канала предоставляется **публичный IP-адрес**.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Сетевой доступ к кластеру
|
|
||||||
|
|
||||||
Выбор способа подключения зависит от архитектуры приложений и требований к безопасности. Доступны два варианта:
|
|
||||||
|
|
||||||
- **IPsec-подключение** — организация защищённого туннеля между инфраструктурой клиента и кластером Kafka. Подробнее см. раздел «IPsec»;
|
|
||||||
- **Interconnect** — прямое сетевое соединение между сервисами внутри платформы без использования публичных сетей. Подробнее см. раздел «Interconnect».
|
|
||||||
|
|
||||||
**Особенности Interconnect:**
|
|
||||||
- сначала закажите PaaS-сервис и дождитесь его предоставления;
|
|
||||||
- затем отдельно закажите Interconnect через менеджера.
|
|
||||||
|
|
||||||
## Калькулятор расчёта кластера
|
|
||||||
|
|
||||||
Для расчёта параметров кластера Kafka разработан специализированный калькулятор — простое веб-приложение.
|
|
||||||
|
|
||||||
**Как работает:**
|
|
||||||
- в калькулятор вносятся исходные данные о планируемой нагрузке (пропускная способность, количество партиций и т.д.);
|
|
||||||
- после нажатия кнопки **«Получить»** автоматически рассчитывается конфигурация кластера.
|
|
||||||
|
|
||||||
Все поля обязательны для заполнения. Формы можно удалять, добавлять и дублировать — это позволяет гибко настраивать параметры под разные сценарии использования.
|
|
||||||
|
|
||||||
## Параметры топиков
|
|
||||||
|
|
||||||
| Параметр |Описание |
|
|
||||||
|---------------------------------------|---------|
|
|
||||||
| **Имя топика** |Уникальное наименование топика в рамках кластера. Поле обязательное. Используется для идентификации топика при расчетах.|
|
|
||||||
| **Число партиций** |Количество партиций, на которые будет разбит топик. Значение должно быть больше числа консьюмеров.|
|
|
||||||
| **Фактор репликации** |Количество копий данных, хранящихся на разных брокерах. Для продуктивных кластеров рекомендуется значение не менее 3. <br>**Примечание:** Количество узлов кластера формируется на основании параметра фактора репликации. Рекомендуется выбирать нечетное количество узлов для корректной работы механизмов выборов лидера.|
|
|
||||||
| **Средний размер сообщения** |Средний объем одного сообщения, передаваемого через топик.|
|
|
||||||
| **Максимальный размер сообщения** |Максимальный объем одного сообщения. Используется для расчета пиковых нагрузок.|
|
|
||||||
| **Частота сообщений** |Количество сообщений, отправляемых в топик за единицу времени.|
|
|
||||||
| **Срок хранения сообщения** |Период времени, в течение которого сообщения хранятся в топике после записи. По истечении этого срока данные удаляются.|
|
|
||||||
| **Имя продюсера** |Наименование приложения-отправителя (для идентификации в расчетах)|
|
|
||||||
| **Количество экземпляров продюсера** |Число одновременно работающих экземпляров продюсера.|
|
|
||||||
| **Имя консьюмера** |Наименование приложения-получателя (для идентификации в расчетах).|
|
|
||||||
| **Количество экземпляров консьюмера** |Число одновременно работающих экземпляров консьюмера. <br>**Примечание:** Формы продюсеров и консьюмеров можно добавлять, удалять и дублировать. Это позволяет учитывать множественные источники и приемники данных в рамках одного расчета.|
|
|
||||||
|
|
||||||
## Расчет конфигурации кластера
|
|
||||||
|
|
||||||
После заполнения всех полей нажимается кнопка **Получить**. Все расчеты выполняются в соответствии с планированием ресурсов, указанных в официальной документации Apache Kafka.
|
|
||||||
В результате, рассчитанные параметры служат основой для формирования заказа на управляемый сервис Kafka.
|
|
||||||
|
|
||||||
Калькулятор автоматически производит расчет следующих параметров:
|
|
||||||
|
|
||||||
- **Количество узлов** - формируется на основании параметра фактора репликации (replication.factor). Рекомендуется выбирать нечетное количество узлов для корректной работы механизмов выборов лидера;
|
|
||||||
- **vCPU** - вычисляется из планируемого количества входящих сообщений и масштабируется в зависимости от числа узлов: чем больше кластер, тем меньше требуется CPU на отдельный сервер благодаря распределению нагрузки;
|
|
||||||
- **RAM** - рассчитывается с учетом количества партиций, объема сообщений и числа подключений продюсеров и консьюмеров;
|
|
||||||
- **Тип и объем дискового хранилища** - определяется на основе среднего и максимального размера сообщения, частоты отправки, срока хранения и фактора репликации;
|
|
||||||
- **Параметры репликации** - учитывают заданный фактор репликации и обеспечивают отказоустойчивость кластера.
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
# Подключение и работа с кластером Kafka (тариф Full)
|
|
||||||
|
|
||||||
Раздел содержит описание способов подключения к управлению кластером Kafka. Поддерживаются два типа подключения:
|
|
||||||
- `SASL_PLAINTEXT` - незашифрованное;
|
|
||||||
- `SASL_SSL` - зашифрованное (через SSL-сертификат).
|
|
||||||
|
|
||||||
Также в разделе приведены примеры работы с клиентскими утилитами и базовые операции администрирования.
|
|
||||||
|
|
||||||
## Предварительные требования
|
|
||||||
|
|
||||||
Для начала работы с кластером Kafka необходимо выполнить предварительную настройку:
|
|
||||||
|
|
||||||
1. **Установить клиент Kafka** - скачивается дистрибутив Kafka (например, kafka_2.13-4.2.0) и распаковывается в удобную директорию;
|
|
||||||
2. **Установить среду выполнения Java** - для работы необходимо установить среду выполнения, с помощью команды: `sudo apt install openjdk-17-jre-headless`. Рекомендуется использовать версию OpenJDK 17 или выше;
|
|
||||||
3. **Доступ к брокерам** - адреса брокеров (bootstrap servers) предоставляются после развертывания кластера;
|
|
||||||
4. **Учетные данные**:
|
|
||||||
- Имя пользователя (username) - стандартное значение client;
|
|
||||||
- Пароль - предоставляется после развертывания кластера.
|
|
||||||
5. **Корневой сертификат (для SSL-подключения)** - сертификат для зашифрованного подключения предоставляется файлом при заказе сервиса Kafka.
|
|
||||||
|
|
||||||
## Структура клиентского дистрибутива
|
|
||||||
|
|
||||||
После распаковки архива Kafka в директории bin доступны скрипты, например:
|
|
||||||
|
|
||||||
| Скрипт | Назначение |
|
|
||||||
|---------------------------|--------------------------|
|
|
||||||
|`kafka-console-producer.sh`|Отправка сообщений в топик|
|
|
||||||
|`kafka-console-consumer.sh`|Чтение сообщений из топика|
|
|
||||||
|
|
||||||
В разделе ниже приведены примеры использования скриптов.
|
|
||||||
|
|
||||||
Подробное описание операций с данными и другими скриптами приведено в [официальной документации Kafka](https://kafka.apache.org/42/getting-started/introduction/). Дополнительную информацию можно получить, выполнив любой скрипт с флагом --help:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-console-producer.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Конфигурационные файлы клиента
|
|
||||||
|
|
||||||
Для подключения к Kafka используется файл настроек **client.properties**, который содержит параметры аутентификации, протокола и его механизмов (рекомендуются SCRAM_SHA_512 и SCRAM_SHA_256).
|
|
||||||
|
|
||||||
### Незашифрованное подключение (SASL_PLAINTEXT)
|
|
||||||
|
|
||||||
Создается файл client.properties со следующим содержимым:
|
|
||||||
|
|
||||||
```
|
|
||||||
sasl.mechanism=SCRAM-SHA-512
|
|
||||||
security.protocol=SASLPLAINTEXT
|
|
||||||
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
|
|
||||||
username="вашлогин" \
|
|
||||||
password="вашпароль";
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для незашифрованного подключения (SASL_PLAINTEXT) используется порт 9091;
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Зашифрованное подключение (SASL_SSL)
|
|
||||||
|
|
||||||
Для зашифрованного подключения (в production-средах рекомендуется использовать именно его) дополнительно требуется корневой сертификат и хранилище доверенных сертификатов (truststore).
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для зашифрованного подключения (SASL_SSL) используется порт 9092.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Шаг 1. Создание truststore
|
|
||||||
|
|
||||||
С помощью утилиты **keytool** выполняется импорт сертификата в хранилище:
|
|
||||||
|
|
||||||
```
|
|
||||||
keytool -importcert -storetype PKCS12 -keystore /путь/к/трастстору/truststore.jks -alias myalias -file ca.crt -storepass любойвашпароль -keypass любойвашпароль
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **keystore** - путь к создаваемому хранилищу;
|
|
||||||
- **alias** - псевдоним сертификата в хранилище;
|
|
||||||
- **file** - путь к загруженному корневому сертификату;
|
|
||||||
- **storepass** - пароль для доступа к хранилищу;
|
|
||||||
- **keypass** - пароль для доступа к ключу.
|
|
||||||
|
|
||||||
### Шаг 2. Настройка client.properties
|
|
||||||
|
|
||||||
В файл **client.properties** добавляются параметры SSL:
|
|
||||||
|
|
||||||
```
|
|
||||||
sasl.mechanism=SCRAM-SHA-512
|
|
||||||
security.protocol=SASLSSL
|
|
||||||
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
|
|
||||||
username="вашлогин" \
|
|
||||||
password="вашпароль";
|
|
||||||
ssl.truststore.location=/путь/к/трастстору/truststore.jks
|
|
||||||
ssl.truststore.password=парольотхранилища
|
|
||||||
```
|
|
||||||
|
|
||||||
### Отправка сообщения в топик
|
|
||||||
|
|
||||||
Выполняется команда с указанием брокеров, файла конфигурации и топика:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-console-producer.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_2>:9092 --command-config~/client.properties --topic test-topic
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **bootstrap-server** - список брокеров кластера (адреса и порты);
|
|
||||||
- **command-config** - путь к файлу с настройками клиента;
|
|
||||||
|
|
||||||
После выполнения команды сообщения вводятся построчно. Для завершения используется сочетание клавиш Ctrl+C.
|
|
||||||
|
|
||||||
### Чтение сообщений из топика
|
|
||||||
|
|
||||||
Выполняется команда с указанием топика и, при необходимости, consumer group:
|
|
||||||
|
|
||||||
```
|
|
||||||
./kafka-console-consumer.sh --bootstrap-server <IP_брокера_0>:9092,<IP_брокера_1>:9092,<IP_брокера_2>:9092 --command-config~/client.properties --topic test-topic --from-beginning --group my-new-consumer-group
|
|
||||||
```
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
|
|
||||||
- **from-beginning** - чтение всех сообщений с начала (при отсутствии параметра чтение начинается с новых сообщений);
|
|
||||||
- **group** - название consumer group, которая при её указании создастся автоматически.
|
|
||||||
|
|
||||||
## Администрирование кластера
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Для изменения параметров кластера Kafka (CPU, RAM, DISK, количества брокеров, параметров топиков) необходимо направить запрос в **Service Desk** по адресу `servicedesk@datafort.ru` с указанием требуемых значений.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Изменение количества брокеров
|
|
||||||
|
|
||||||
Выполняется также через обращение в техническую поддержку.
|
|
||||||
|
|
||||||
Брокеров в кластере рекомендуется поддерживать **нечетным** для корректной работы механизмов выборов лидера.
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Операция перераспределения партиций требует времени и может создавать дополнительную нагрузку на кластер. Выполнение рекомендуется в период наименьшей активности.
|
|
||||||
:::
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
# Параметры конфигурации IPsec-соединения
|
|
||||||
|
|
||||||
В данном разделе приведены параметры конфигурации IPsec-соединения, используемого для организации защищенного канала связи между инфраструктурой заказчика и кластерами. Материал описывает настройки этапов установки соединения и передачи данных, включая методы аутентификации, алгоритмы шифрования и хеширования, группы Диффи-Хеллмана, а также параметры времени жизни ключей.
|
|
||||||
|
|
||||||
Ниже приведены основные параметры, задаваемые при развертывании кластера Kafka. Часть параметров определяется клиентом на этапе заказа услуги, часть - фиксирована и не подлежит изменению.
|
|
||||||
|
|
||||||
## Данные о конфигурации IPSEC
|
|
||||||
|
|
||||||
Параметры подключения (имя туннеля, устройство, публичный IP-адрес) заполняются вручную на основании информации, предоставленной заказчиком.
|
|
||||||
|
|
||||||
#### Версия IKE (Internet Key Exchange)
|
|
||||||
|
|
||||||
Версия IKE выбирается из выпадающего списка, который содержит в себе два параметра - **v1** и **v2**.
|
|
||||||
|
|
||||||
- **IKE v1** - более ранняя версия протокола;
|
|
||||||
- **IKE v2** - более современная версия (обеспечивает более устойчивое соединение и гибкую обработку ошибок).
|
|
||||||
|
|
||||||
Рекомендуется использовать **IKE v2**, если оборудование заказчика это поддерживает.
|
|
||||||
|
|
||||||
## Метод аутентификации
|
|
||||||
|
|
||||||
Метод аутентификации выбирается вручную из выпадающего списка, который содержит два варианта:
|
|
||||||
|
|
||||||
- **PSK (Pre-Shared Key)** - метод аутентификации, при котором используется заранее согласованный общий ключ;
|
|
||||||
- **Certificate** - аутентификация с использованием цифровых сертификатов.
|
|
||||||
|
|
||||||
## Этап 1 - установка защищенного соединения
|
|
||||||
|
|
||||||
#### Hash
|
|
||||||
|
|
||||||
Определяет алгоритм хеширования **для защиты управляющего канала**.
|
|
||||||
|
|
||||||
Данный параметр заполняется вручную из выпадающего списка следующего содержания:
|
|
||||||
|
|
||||||
- **SHA 1** - Формирует хеш длиной 160 бит, имеет коллизии (уязвимости), в современных системах считается устаревшим, используется только для совместимости со старым оборудованием;
|
|
||||||
- **SHA 2 - 256** - Формирует хеш длиной 256 бит, существенно более устойчив к атакам, оптимальный баланс между безопасностью и производительностью, а также, на сегодняшний день, является стандартом по умолчанию в большинстве систем;
|
|
||||||
- **SHA 2 - 384** - Длина хеша составляет 384 бита, имеет повышенную криптостойкость, требует больше вычислительных ресурсов, чем SHA-1 и SHA 2-256. Используется в средах с повышенными требованиями к безопасности;
|
|
||||||
- **SHA 2 - 512** - Длина хеша составляет 512 бит, осуществляет самый высокий уровень стойкости из перечисленных, а также создает большую нагрузку на процессор. Обычно применяется в системах с повышенными требованиями к криптографии.
|
|
||||||
|
|
||||||
#### Шифрование
|
|
||||||
|
|
||||||
Определяет **алгоритм симметричного шифрования.**
|
|
||||||
|
|
||||||
Данный параметр заполняется вручную из выпадающего списка следующего содержания:
|
|
||||||
|
|
||||||
- **AES 128** - имеет 128-битный ключ, обеспечивает быстрое шифрование, имеет достаточный уровень безопасности для большинства задач;
|
|
||||||
- **AES 256** - имеет 256-битный ключ, обеспечивает более высокую криптостойкость, оказывает немного большую нагрузку на CPU;
|
|
||||||
- **AES GCM 12** / **AES GCM 192** / **AES GCM 256** - данные алгоритмы совмещают шифрование и контроль целостности, обладают более современным режимом работы, считаются более эффективными по производительности, а также рекомендуются в современных конфигурациях. Разница между этими тремя алгоритмами лишь в длине ключа.
|
|
||||||
|
|
||||||
#### DH Group - группа Деффи Хеллмана
|
|
||||||
|
|
||||||
Механизм Diffie-Hellman используется **для безопасной генерации общего секретного ключа** между сторонами туннеля без передачи этого ключа по сети.
|
|
||||||
Чем выше номер группы и длина ключа - тем выше криптографическая стойкость соединения.
|
|
||||||
|
|
||||||
Данный параметр так же содержит в себе выпадающий список, состоящий из следующих значений:
|
|
||||||
- **group 2**;
|
|
||||||
- **group 5**;
|
|
||||||
- **group 14**;
|
|
||||||
- **group 15**;
|
|
||||||
- **group 16**;
|
|
||||||
- **group 19**;
|
|
||||||
- **group 20**;
|
|
||||||
- **group 21**.
|
|
||||||
|
|
||||||
#### IKE Mode (только для IKEv1)
|
|
||||||
|
|
||||||
Параметр IKE Mode **определяет способ установления соединения** на этапе 1 при использовании протокола IKEv1.
|
|
||||||
|
|
||||||
Доступны два режима: **Main** и **Aggressive**. Они отличаются количеством сообщений при установке соединения и уровнем защиты идентификационных данных.
|
|
||||||
- Main Mode - является стандартным и более безопасным режимом работы IKEv1.
|
|
||||||
- Aggressive Mode - упрощённый и ускоренный режим установления соединения. (более низкий уровень защиты данных)
|
|
||||||
|
|
||||||
#### Время жизни
|
|
||||||
|
|
||||||
Определяет, как долго действуют согласованные ключи в рамках первой фазы.
|
|
||||||
|
|
||||||
- Рекомендуемое значение: 86400 секунд (24 часа);
|
|
||||||
- После истечения времени выполняется повторная генерация ключей.
|
|
||||||
|
|
||||||
|
|
||||||
## Этап 2 - передача данных
|
|
||||||
|
|
||||||
Этап 2 IPsec-соединения отвечает за шифрование и защиту пользовательского трафика после того, как защищённый канал был установлен на этапе 1. Этот этап регулирует передачу данных между сторонами через безопасный туннель, который обеспечивает конфиденциальность и целостность данных.
|
|
||||||
|
|
||||||
#### Hash
|
|
||||||
|
|
||||||
Аналогично этапу 1, параметр Hash используется **для защиты целостности передаваемых данных**. Он обеспечивает проверку, что данные не были изменены при передаче.
|
|
||||||
|
|
||||||
Содержит элементы для выбора:
|
|
||||||
|
|
||||||
- **SHA 1**;
|
|
||||||
- **SHA 2 - 256**;
|
|
||||||
- **SHA 2 - 384**;
|
|
||||||
- **SHA 2 - 512**.
|
|
||||||
|
|
||||||
#### Шифрование
|
|
||||||
|
|
||||||
Этап 2 отвечает за **шифрование пользовательского трафика**. Это важнейший параметр, который защищает данные при их передаче по сети.
|
|
||||||
|
|
||||||
Доступны следующие алгоритмы:
|
|
||||||
|
|
||||||
- **AES 128**;
|
|
||||||
- **AES 256**;
|
|
||||||
- **AES GCM 128**;
|
|
||||||
- **AES GCM 192**;
|
|
||||||
- **AES GCM 256**.
|
|
||||||
|
|
||||||
#### PFS
|
|
||||||
|
|
||||||
**Enable perfect forward secrecy (PFS)** - параметр, активирующий генерацию нового ключа на этапе 2. При включенном PFS группа DH будет такая же как и на 1-й фазе. Данный параметр представлен в виде чекбокса.
|
|
||||||
|
|
||||||
При его включении:
|
|
||||||
|
|
||||||
- На этапе 2 выполняется дополнительный обмен ключами Diffie-Hellman;
|
|
||||||
- Для каждой новой IPsec-сессии формируется новый независимый криптографический секрет;
|
|
||||||
- Ключи шифрования пользовательского трафика не зависят от ключей этапа 1.
|
|
||||||
|
|
||||||
#### DH Group - группа Деффи Хеллмана
|
|
||||||
|
|
||||||
Группа DH **определяет параметры обмена ключами** между сторонами. Чем выше номер группы, тем выше криптографическая стойкость и безопасность обмена.
|
|
||||||
|
|
||||||
Данный параметр так же содержит в себе выпадающий список, состоящий из следующих значений:
|
|
||||||
|
|
||||||
- **group 2**;
|
|
||||||
- **group 5**;
|
|
||||||
- **group 14**;
|
|
||||||
- **group 15**;
|
|
||||||
- **group 16**;
|
|
||||||
- **group 19**;
|
|
||||||
- **group 20**;
|
|
||||||
- **group 21**.
|
|
||||||
|
|
||||||
#### Время жизни (в секундах)
|
|
||||||
|
|
||||||
Определяет, как долго действуют согласованные ключи в рамках второй фазы.
|
|
||||||
|
|
||||||
- Рекомендуемое значение: 3600 секунд (1 час).
|
|
||||||
- После истечения времени выполняется повторная генерация ключей.
|
|
||||||
|
|
||||||
#### Префиксы локальной сети заказчика
|
|
||||||
|
|
||||||
Этот параметр определяет, какие сети на стороне заказчика будут маршрутизироваться через IPsec-туннель.
|
|
||||||
|
|
||||||
Префиксы задаются в формате `192.168.1.0/24`, который позволяет указать диапазон IP-адресов.
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
section_links:
|
|
||||||
- title: Назначение сервиса
|
|
||||||
link: /PaaS/PostgreSQL/about.md
|
|
||||||
description: Конфигурации и возможности сервиса
|
|
||||||
- title: Параметры кластера PostgreSQL
|
|
||||||
link: /PaaS/PostgreSQL/cluster-parameter.md
|
|
||||||
description: Технические параметры кластера PostgreSQL
|
|
||||||
- title: Схема подключения
|
|
||||||
link: /PaaS/PostgreSQL/connection.md
|
|
||||||
description: Общая схема подключения к Cloud PostgreSQL
|
|
||||||
- title: Возможности пользователя
|
|
||||||
link: /PaaS/PostgreSQL/user-capabilities.md
|
|
||||||
description: Возможности пользователя при создании сервиса
|
|
||||||
- title: Веб-интерфейс Grafana
|
|
||||||
link: /PaaS/PostgreSQL/grafana.md
|
|
||||||
description: Инструкция по работе с Grafana
|
|
||||||
- title: Веб-интерфейс PgAdmin
|
|
||||||
link: /PaaS/PostgreSQL/pgadmin.md
|
|
||||||
description: Инструкция по работе с PgAdmin
|
|
||||||
---
|
|
||||||
|
|
||||||
# Cloud PostgreSQL
|
|
||||||
|
|
||||||
В данном разделе представлена документация по управляемому сервису **Cloud PostgreSQL** платформы Beeline Cloud.
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
# Cloud PostgreSQL
|
|
||||||
|
|
||||||
## Назначение сервиса
|
|
||||||
|
|
||||||
**Cloud PostgreSQL** - это управляемый облачный сервис реляционной базы данных PostgreSQL. Он позволяет развернуть и использовать отказоустойчивый кластер базы данных без необходимости самостоятельно настраивать серверы, репликацию и механизмы отказоустойчивости.
|
|
||||||
|
|
||||||
PostgreSQL - это современная система управления базами данных, которая поддерживает стандарт SQL и используется для хранения и обработки данных приложений.
|
|
||||||
|
|
||||||
В **Cloud PostgreSQL** все основные операции по управлению кластером выполняются автоматически.
|
|
||||||
|
|
||||||
Сервис самостоятельно:
|
|
||||||
- управляет ролями серверов базы данных (основной сервер и реплики);
|
|
||||||
- отслеживает состояние узлов;
|
|
||||||
- автоматически переключает основной сервер при сбоях.
|
|
||||||
|
|
||||||
Для обеспечения стабильной работы сервиса используется несколько инфраструктурных компонентов:
|
|
||||||
- **Patroni** - управляет кластером PostgreSQL и автоматическим переключением при отказах;
|
|
||||||
- **etcd** - хранит состояние кластера и обеспечивает согласованность работы узлов;
|
|
||||||
- **HAProxy** - обеспечивает единую точку подключения и распределяет клиентские подключения между узлами.
|
|
||||||
|
|
||||||
Подключение к базе данных выполняется через прокси-узлы сервиса. Пользователю не требуется подключаться к отдельным серверам кластера — все операции производятся через единую точку доступа.
|
|
||||||
|
|
||||||
Для управления базами данных и пользователями доступен [web-интерфейс **pgAdmin**](./pgadmin.md), позволяющий выполнять администрирование непосредственно через браузер.
|
|
||||||
|
|
||||||
## Конфигурации кластера
|
|
||||||
|
|
||||||
Сервис **Cloud PostgreSQL** поддерживает версии СУБД с 13 по 17 включительно.
|
|
||||||
|
|
||||||
Кластер предоставляется в архитектуре Primary–Standby, которая обеспечивает:
|
|
||||||
|
|
||||||
- синхронную репликацию данных;
|
|
||||||
- повышенную отказоустойчивость.
|
|
||||||
|
|
||||||
В рамках данной конфигурации создаётся кластер из виртуальных серверов, включающий:
|
|
||||||
|
|
||||||
- **Primary** (основной сервер) — обязательный узел, на котором выполняются операции записи данных;
|
|
||||||
- **Replica** (реплики) — дополнительные узлы (от 0 до 4), создаваемые по желанию пользователя.
|
|
||||||
|
|
||||||
Реплики являются полноценными участниками кластера PostgreSQL и могут использоваться для выполнения запросов, не изменяющих данные (например, SELECT).
|
|
||||||
|
|
||||||
В многоузловой конфигурации серверы кластера размещаются на разных физических хостах гипервизора, что повышает устойчивость сервиса к отказам оборудования.
|
|
||||||
|
|
||||||
## Режимы репликации
|
|
||||||
|
|
||||||
По умолчанию фиксация изменений выполняется в **синхронном режиме**. Это означает, что операция записи считается завершённой только после того, как данные будут зафиксированы как на основном сервере, так и на одной из реплик.
|
|
||||||
|
|
||||||
Если в кластере настроено несколько реплик, синхронный режим применяется только к одной из них. Остальные реплики работают в асинхронном режиме — изменения передаются на них без ожидания подтверждения.
|
|
||||||
|
|
||||||
При необходимости режим репликации может быть изменён на полностью **асинхронный**. В этом случае изменения сначала фиксируются на основном сервере, а затем передаются на реплики с задержкой.
|
|
||||||
|
|
||||||
## Доступ к серверам и оптимизация соединений
|
|
||||||
|
|
||||||
Прямой доступ к серверам кластера (например, по протоколу SSH) не предоставляется. Пользователь взаимодействует с базой данных исключительно через точки подключения, предоставленные сервисом.
|
|
||||||
|
|
||||||
На каждом узле кластера установлен пулер соединений **PgBouncer**, который может использоваться для ускорения работы приложений за счёт оптимизации подключений к базе данных.
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
|
|
||||||
Использование PgBouncer не является обязательным - подключение возможно как напрямую к PostgreSQL, так и через пулер, а также одновременно обоими способами.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Возможности сервиса
|
|
||||||
|
|
||||||
**Cloud PostgreSQL** предоставляет набор возможностей, позволяющих использовать PostgreSQL в облаке без необходимости самостоятельного администрирования инфраструктуры.
|
|
||||||
|
|
||||||
Сервис обеспечивает:
|
|
||||||
|
|
||||||
- автоматическое управление кластером PostgreSQL;
|
|
||||||
- высокую доступность за счёт репликации и автоматического переключения primary-узла;
|
|
||||||
- единую точку подключения к базе данных через прокси;
|
|
||||||
- автоматическое переключение при отказе узлов кластера без вмешательства пользователя;
|
|
||||||
- web-доступ к управлению базами данных и пользователями через pgAdmin;
|
|
||||||
- совместимость со стандартными клиентскими инструментами PostgreSQL;
|
|
||||||
- возможность установки расширений PostgreSQL в базу данных.
|
|
||||||
|
|
||||||
## Сценарии использования сервиса
|
|
||||||
|
|
||||||
**Cloud PostgreSQL** подходит для использования в системах, где требуется надёжное хранение данных и упрощённое управление инфраструктурой базы данных.
|
|
||||||
|
|
||||||
Сервис может применяться в следующих сценариях:
|
|
||||||
|
|
||||||
- размещение production-баз данных с высокими требованиями к доступности;
|
|
||||||
- использование PostgreSQL в микросервисной архитектуре с единой точкой подключения к базе данных;
|
|
||||||
- хранение критичных данных с минимальным временем простоя при отказах инфраструктуры;
|
|
||||||
- быстрое развёртывание PostgreSQL-кластера без необходимости ручной настройки репликации и failover;
|
|
||||||
- администрирование баз данных через веб-интерфейс без прямого доступа к серверам кластера.
|
|
||||||
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
# Описание технических параметров
|
|
||||||
|
|
||||||
Данный раздел содержит технические параметры кластера PostgreSQL и порядок их первичной конфигурации.
|
|
||||||
|
|
||||||
Настройка указанных параметров выполняется администратором облачного провайдера на этапе развёртывания сервиса. Пользователь не имеет прямого доступа к их самостоятельной установке.
|
|
||||||
|
|
||||||
Перед созданием кластера клиент предоставляет перечень требуемых параметров менеджеру. Администратор облачного провайдера выполняет конфигурацию в соответствии с согласованными требованиями.
|
|
||||||
|
|
||||||
## Выбор типа и размера дискового хранилища
|
|
||||||
|
|
||||||
Производительность базы данных напрямую зависит от скорости, с которой она может читать и записывать данные на диск. При заказе кластера необходимо выбрать тип дискового хранилища, который определит максимальную скорость работы (IOPS) и время отклика.
|
|
||||||
|
|
||||||
**IOPS (Input/Output Operations Per Second)** — количество операций чтения или записи, которые диск может выполнить за секунду. Чем выше этот показатель, тем быстрее база данных обрабатывает запросы.
|
|
||||||
|
|
||||||
## Доступные типы хранилищ:
|
|
||||||
|
|
||||||
| Название | Лимит IOPS |
|
|
||||||
| -------------- | ------------------ |
|
|
||||||
| **Fast SAS** | до 2 IOPS на 1 ГБ |
|
|
||||||
| **SSD** | до 5 IOPS на 1 ГБ |
|
|
||||||
| **Fast SSD** | до 10 IOPS на 1 ГБ |
|
|
||||||
| **Ultra NVMe** | до 25 IOPS на 1 ГБ |
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
|
|
||||||
После выбора типа диска необходимо указать объем дискового хранилища, который будет выделен под данные кластера PostgreSQL. Минимальный объем - 50 ГБ.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Конфигурация вычислительных ресурсов
|
|
||||||
|
|
||||||
В данном разделе определяются вычислительные мощности кластера: процессорные ресурсы, оперативная память и количество серверов (нод), из которых будет состоять кластер PostgreSQL.
|
|
||||||
|
|
||||||
#### Количество нод в кластере
|
|
||||||
|
|
||||||
Количество нод определяет отказоустойчивость кластера и возможность распределять запросы на чтение между репликами. Чем больше нод, тем выше надёжность и производительность операций чтения.
|
|
||||||
|
|
||||||
Количество нод выбирается в диапазоне **от 1 до 5**.
|
|
||||||
|
|
||||||
#### Процессор (CPU)
|
|
||||||
|
|
||||||
Процессор — это вычислительная мощность, выделяемая каждой ноде кластера. Количество vCPU определяет, насколько быстро база данных сможет:
|
|
||||||
|
|
||||||
- обрабатывать запросы;
|
|
||||||
- выполнять сложные операции (сортировки, объединения таблиц);
|
|
||||||
- обслуживать одновременные подключения.
|
|
||||||
|
|
||||||
Доступный диапазон: **от 2 до 24 vCPU** на ноду.
|
|
||||||
|
|
||||||
#### Оперативная память (RAM)
|
|
||||||
|
|
||||||
Оперативная память — один из ключевых ресурсов для производительности базы данных. Данные, помещающиеся в RAM, обрабатываются максимально быстро, без обращения к диску.
|
|
||||||
|
|
||||||
Доступный диапазон: **от 4 до 768 ГБ RAM** на ноду.
|
|
||||||
|
|
||||||
#### Доступ в интернет
|
|
||||||
|
|
||||||
При заказе сервиса можно выбрать пропускную способность канала связи, через который будет осуществляться доступ к кластеру PostgreSQL из сети интернет.
|
|
||||||
|
|
||||||
**Доступные варианты скорости:**
|
|
||||||
- 50 Мбит/с;
|
|
||||||
- 100 Мбит/с;
|
|
||||||
- 200 Мбит/с;
|
|
||||||
- 300 Мбит/с;
|
|
||||||
- 400 Мбит/с;
|
|
||||||
- 500 Мбит/с;
|
|
||||||
- 1000 Мбит/с (1 Гбит/с).
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
|
|
||||||
Для выбранного канала предоставляется статический белый IP-адрес.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Сетевой доступ к кластеру
|
|
||||||
|
|
||||||
Для организации защищенного подключения к кластеру Kafka доступны стандартные механизмы, используемые во всех сервисах платформы:
|
|
||||||
- **IPsec-подключение** - организация защищенного туннеля между инфраструктурой и кластером PostgreSQL. Подробнее см. [раздел IPsec](../IPSEC.md);
|
|
||||||
- **Interconnection** - прямое сетевое соединение между сервисами внутри платформы без выхода в интернет. Подробнее см. раздел Interconnection.
|
|
||||||
|
|
||||||
Выбор конкретного способа подключения зависит от архитектуры приложений и требований к безопасности.
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
# Общая схема подключения
|
|
||||||
|
|
||||||
Подключение к кластеру **Cloud PostgreSQL** осуществляется через прокси-сервер. Клиентские подключения принимаются прокси, который маршрутизирует трафик к соответствующим узлам кластера (master или replica) в зависимости от выбранного порта.
|
|
||||||
|
|
||||||
Прокси является единой точкой входа для всех клиентских подключений и принимает входящие соединения от приложений, административных инструментов и пользователей.
|
|
||||||
|
|
||||||
В зависимости от выбранного порта прокси автоматически направляет трафик:
|
|
||||||
- **на активный primary-узел** - для операций чтения и записи
|
|
||||||
- **на реплики** - для операций только чтения
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
Прямое подключение к отдельным узлам базы данных **не используется и не предоставляется**. Взаимодействие с кластером всегда выполняется **через прокси-сервер**.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Подключение к базе данных
|
|
||||||
|
|
||||||
Для подключения к базе данных необходимо использовать IP-адрес прокси-сервера, который предоставляется после заказа услуги.
|
|
||||||
|
|
||||||
Этот IP-адрес является единой точкой входа для работы с кластером PostgreSQL. Все подключения к базе данных - как из приложений, так и из клиентских инструментов - выполняются через него.
|
|
||||||
|
|
||||||
Использование других IP-адресов или попытка прямого подключения к отдельным узлам кластера не предусмотрены.
|
|
||||||
|
|
||||||
## Доступные порты
|
|
||||||
|
|
||||||
Для разных типов нагрузки используются разные порты:
|
|
||||||
|
|
||||||
|Порт |Назначение |
|
|
||||||
|------|-----------------------------------------|
|
|
||||||
|5432 |Primary (чтение и запись) |
|
|
||||||
|15432 |Replica (только чтение) |
|
|
||||||
|6432 |Primary через PgBouncer (чтение и запись)|
|
|
||||||
|16432 |Replica через PgBouncer (только чтение) |
|
|
||||||
|
|
||||||
#### Особенности работы портов
|
|
||||||
|
|
||||||
- Порты **для чтения и записи** (5432, 6432) всегда направляют трафик на активный primary-узел. При смене primary переключение происходит автоматически;
|
|
||||||
- Порты **только для чтения** (15432, 16432) направляют трафик на активные реплики. Если реплик несколько, нагрузка распределяется между ними по принципу round-robin;
|
|
||||||
- Если в кластере **отсутствуют реплики**, порты для чтения не используются - подключение по ним не устанавливается.
|
|
||||||
|
|
||||||
#### Рекомендации по выбору порта
|
|
||||||
|
|
||||||
- Для OLTP-нагрузки и большого количества соединений рекомендуется использовать **порты PgBouncer (6432 или 16432)**;
|
|
||||||
- Для операций записи используйте **master-порты (5432 или 6432)**;
|
|
||||||
- Для read-only запросов можно использовать **replica-порты (15432 или 16432)**.
|
|
||||||
|
|
||||||
## Доступ к pgAdmin
|
|
||||||
|
|
||||||
Для администрирования базы данных используется [web-интерфейс pgAdmin](./pgadmin.md).
|
|
||||||
Доступ осуществляется по DNS-имени, которое нужно прописать локально в инфраструктуре откуда будет происходить доступ к web-интерфейсу сервиса:
|
|
||||||
`10.X.X.4 <domain>.cloud-pg.dfcloud.ru`
|
|
||||||
|
|
||||||
После добавления записи pgAdmin будет доступен по адресу:
|
|
||||||
`https://<domain>.cloud-pg.dfcloud.ru`
|
|
||||||
|
|
||||||
Авторизация выполняется с использованием учётных данных, предоставленных вместе с доступом к сервису.
|
|
||||||
|
|
||||||
::: warning Примечание
|
|
||||||
|
|
||||||
- подключение к базе данных возможно только через указанный прокси-IP;
|
|
||||||
- в интерфейсе pgAdmin уже добавлен сервер базы данных, созданный для данной инсталляции. Для подключения требуется ввести пароль от учётной записи базы данных;
|
|
||||||
- pgAdmin предназначен для администрирования и не рекомендуется для выполнения тяжёлых или длительных запросов в production-среде.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Примеры подключения к PostgreSQL
|
|
||||||
|
|
||||||
Подключение к primary:
|
|
||||||
`psql -h 10.X.X.4 -p 5432 -U <username> -d <database>`
|
|
||||||
|
|
||||||
Подключение через PgBouncer:
|
|
||||||
`psql -h 10.X.X.4 -p 6432 -U <username> -d <database>`
|
|
||||||
|
|
||||||
#### Подключение через DBeaver / DataGrip
|
|
||||||
|
|
||||||
При создании подключения укажите:
|
|
||||||
- Host: 10.X.X.4;
|
|
||||||
- Port: 5432 или 6432;
|
|
||||||
- Database: `<database>`;
|
|
||||||
- User / Password: согласно выданным доступам;
|
|
||||||
- Тип подключения: PostgreSQL.
|
|
||||||
|
|
||||||
#### Пример строки подключения
|
|
||||||
|
|
||||||
Primary:
|
|
||||||
`postgresql://<username>:<password>@10.X.X.4:5432/<database>`
|
|
||||||
|
|
||||||
Через PgBouncer:
|
|
||||||
`postgresql://<username>:<password>@10.X.X.4:6432/<database>`
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
# Grafana
|
|
||||||
|
|
||||||
## Инструкция по работе с метриками
|
|
||||||
|
|
||||||
Доступ к метрикам кластера предоставляется после запроса соответствующих прав. После получения доступа можно перейти в систему мониторинга по ссылке: https://metrics.dfcloud.ru. После перехода по ссылке будет представлена главная страница Grafana.
|
|
||||||
|
|
||||||
Для просмотра метрик кластера PostgreSQL выполните следующие шаги:
|
|
||||||
|
|
||||||
1. В левом боковом меню нажмите **Dashboard**;
|
|
||||||
2. В списке доступных дашбордов выберите **папку Cloud PostgreSQL**;
|
|
||||||
3. Внутри папки выберите **дашборд Cloud PostgreSQL** — в нём отображаются все метрики кластера.
|
|
||||||
|
|
||||||
## Управление отображаемыми данными
|
|
||||||
|
|
||||||
В верхней части дашборда доступны селекторы для настройки отображения:
|
|
||||||
|
|
||||||
- **InstallationID** - выбор одного опеределенного кластера;
|
|
||||||
- **Cluster node name** - выбор конкретного нода кластера, в котором значения графиков меняются в зависимости от выбранного хоста (селектор влияет на все графики, кроме блока Patroni);
|
|
||||||
- **Database** - выбор базы данных, по которым отображаются метрики;
|
|
||||||
- **Lock table** - выбор типа блокировки для отображения (применим не для всех графиков).
|
|
||||||
|
|
||||||
## Метрики PostgreSQL
|
|
||||||
|
|
||||||
Метрики отображают ключевые параметры конфигурации и текущие показатели работы экземпляра PostgreSQL.
|
|
||||||
|
|
||||||
| Наименование метрики | Описание метрики |
|
|
||||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| **Version** | Показывает текущую версию PostgreSQL, установленную на кластере. |
|
|
||||||
| **Current fetch data** | Объем данных, извлеченных из базы за текущий период (операции чтения). |
|
|
||||||
| **Current insert data** | Объем данных, вставленных в базу (операции записи новых данных). |
|
|
||||||
| **Current update data** | Объем данных, обновленных в базе. |
|
|
||||||
| **Seq Page Cost** | Стоимость последовательного чтения страницы данных. Влияет на выбор плана запроса: чем выше значение, тем реже оптимизатор будет выбирать последовательное сканирование таблиц. |
|
|
||||||
| **Random Page Cost** | Стоимость чтения случайной страницы данных. Низкое значение говорит о том, что в системе используются быстрые диски, и оптимизатор будет чаще выбирать доступ по индексам. |
|
|
||||||
| **Max Connections** | Максимальное количество одновременных подключений к базе данных, разрешенное на сервере. |
|
|
||||||
| **Shared Buffers** | Объем оперативной памяти, выделенный под кэш данных PostgreSQL. Здесь хранятся часто используемые данные для ускорения доступа к ним. |
|
|
||||||
| **Effective Cache** | Предполагаемый размер системного кэша файлов. Используется оптимизатором для оценки вероятности нахождения данных в кэше операционной системы. |
|
|
||||||
| **Maintenance Work Mem** | Объем памяти для выполнения операций обслуживания. |
|
|
||||||
| **Work Mem** | Объем памяти, выделяемый для внутренних сортировок и хеш-таблиц при выполнении запросов (на каждую операцию). |
|
|
||||||
| **Max WAL Size** | Максимальный размер журнала предзаписи, после достижения которого запускается процесс контрольной точки (checkpoint). |
|
|
||||||
| **Max Worker Processes** | Максимальное количество фоновых процессов, которые могут быть запущены в системе. |
|
|
||||||
| **Max Parallel Workers** | Максимальное количество параллельных процессов, которые могут быть задействованы при выполнении одного запроса. |
|
|
||||||
|
|
||||||
## Метрики Database Stats
|
|
||||||
|
|
||||||
Метрики отображают текущую нагрузку и состояние баз данных в кластере PostgreSQL. Данные метрики позволяют:
|
|
||||||
- оценить эффективность работы баз данных;
|
|
||||||
- отследить скачки нагрузки;
|
|
||||||
- своевременно среагировать на потенциальные проблемы до того, как они повлияют на работу приложений.
|
|
||||||
|
|
||||||
| Наименование | Описание |
|
|
||||||
|---------------------------| -------------------|
|
|
||||||
| **Average CPU Usage** | Показывает время, затраченное на выполнение пользовательских и системных задач, а также, насколько интенсивно используются вычислительные ресурсы сервера базы данных. |
|
|
||||||
| **Average Memory Usage** | Средний объем оперативной памяти, используемой процессами PostgreSQL за 5-минутные интервалы. Показывает, сколько памяти потребляет база данных в процессе работы. |
|
|
||||||
| **Open File Descriptors** | Количество открытых файловых дескрипторов процессами PostgreSQL. Метрика показывает среднее (Mean), последнее (Last), максимальное (Max) и минимальное (Min) значение за интервал. |
|
|
||||||
| **Active sessions** | Показывает, сколько в данный момент выполняется запросов к PostgreSQL. Метрика показывает среднее (Mean), последнее (Last), максимальное (Max) значение. |
|
|
||||||
| **Transcations** | Количество транзакций в базах данных кластера. Метрика разделена на два типа операций: commits (успешно завершенные транзакции) и rollbacks (откаченные транзакции). |
|
|
||||||
| **Update data** | Объем данных, обновленных в базах данных кластера. Показывает, сколько данных было изменено в результате выполнения операций UPDATE. |
|
|
||||||
| **Fetch data (SELECT)** | Объем данных, извлеченных из базы с помощью запросов SELECT. Показывает, сколько данных было считано из базы в результате операций чтения. |
|
|
||||||
| **Insert data** | Объем данных, вставленных в базы данных кластера. Показывает, сколько данных было добавлено в результате выполнения операций INSERT. |
|
|
||||||
| **Lock tables** | Количество блокировок таблиц в базах данных кластера. Показывает, сколько раз таблицы были заблокированы для выполнения операций.<br>AccessShareLock - это блокировка, которая возникает, когда кто-то читает данные из таблицы (делает SELECT). Данная блокировка не мешает операциям чтения, но не дает удалить в этот момент таблицу или изменить ее структуру. |
|
|
||||||
| **Return data** | Объем данных, возвращаемых клиенту в результате выполнения запросов. Показывает, сколько данных было отправлено обратно клиенту после обработки запросов в базе. |
|
|
||||||
| **Idle sessions** | Количество бездействующих сессий подключения к базе данных. Показывает, сколько открытых подключений в данный момент не выполняют никаких запросов и просто ждут. |
|
|
||||||
| **Delete data** | Объем данных, удаленных из базы данных в результате выполнения операций DELETE. Показывает, сколько данных было удалено из таблиц. |
|
|
||||||
| **Cache Hit Rate** | Показывает процент запросов к данным, которые были удовлетворены из кэша (оперативной памяти), без обращения к диску. Показывает, насколько эффективно используется кэш PostgreSQL. |
|
|
||||||
| **Buffers (bgwriter)** | Метрика, показывающая активность фонового процесса записи, который занимается синхронизацией данных из оперативной памяти на диск. |
|
|
||||||
| **Conflicts/Deadlocks** | Метрика, отслеживающая две проблемы при работе с базой данных: конфликты восстановления и взаимоблокировки. |
|
|
||||||
| **Temp File (Bytes)** | Объем данных, записанных во временные файлы при выполнении запросов в базах данных. PostgreSQL создает временные файлы на диске, когда для выполнения запроса не хватает оперативной памяти. |
|
|
||||||
| **Checkpoint Stats** | Метрика, показывающая время, затрачиваемое на выполнение checkpoints в PostgreSQL, где: <br>- **write_time** - время, затраченное на запись данных на диск во время checkpoint (сколько миллисекунд ушло на запись файлов).<br>- **sync_time** - время, затраченное на синхронизацию файлов с диском (чтобы данные гарантированно сохранились). |
|
|
||||||
|
|
||||||
## Метрики Patroni
|
|
||||||
|
|
||||||
Метрик отображают состояние и конфигурацию кластера PostgreSQL под управлением Patroni. Эти метрики позволяют контролировать отказоустойчивость кластера, отслеживать переключения мастера и убеждаться, что репликация работает штатно.
|
|
||||||
|
|
||||||
| Наименование | Описание |
|
|
||||||
|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| **Patroni Leader** | Метрика, которая показывает, какая нода в кластере PostgreSQL в данный момент является master-сервером, принимающим запросы на запись. |
|
|
||||||
| **Patroni Replica** | Метрика, которая показывает, какие узлы кластера PostgreSQL в данный момент выполняют роль реплики. |
|
|
||||||
| **Sync Standby** | Метрика, которая показывает, какая из реплик в кластере PostgreSQL назначена синхронной. |
|
|
||||||
| **PostgreSQL WAL Replay** | Метрика, которая показывает, включена ли на узлах кластера синхронизация данных через WAL. |
|
|
||||||
| **PostgreSQL Pending Restart** | Метрика, которая показывает, требуется ли перезагрузка PostgreSQL на узлах кластера после изменения конфигурационных параметров. |
|
|
||||||
| **Patroni Primary Node** | Метрика, которая показывает, какой узел в кластере PostgreSQL в данный момент является основным и принимает запросы на запись. |
|
|
||||||
| **Patroni Secondary Nodes** | Метрика, которая показывает, какие узлы кластера PostgreSQL в определенные моменты времени выполняли роль реплик. |
|
|
||||||
| **Replicas Received WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), полученных каждой репликой кластера. |
|
|
||||||
| **Primary WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), на основном сервере кластера PostgreSQL. |
|
|
||||||
| **Replicas Replayed WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), которые были не просто получены, а уже применены на репликах кластера. |
|
|
||||||
| **WAL Replay Paused** | Метрика, которая отслеживает, не приостановлен ли процесс применения WAL-журналов на узлах кластера. Если передача или применение WAL-файлов останавливается, на графике происходит скачок. |
|
|
||||||
|
|
||||||
## Метрики Hosts
|
|
||||||
|
|
||||||
Блок Hosts управляется селектором **Cluster node name**. Метрики отображают состояние и ресурсы серверов, на которых развернут кластер PostgreSQL. Данные метрики позволяют оценить, хватает ли серверу ресурсов для текущей нагрузки, и своевременно обнаружить проблемы с производительностью или нехваткой места на дисках.
|
|
||||||
|
|
||||||
| Наименование | Описание |
|
|
||||||
| -------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| **CPU Busy** | Метрика, показывающая общую загруженность всех процессорных ядер на сервере, где работает PostgreSQL. |
|
|
||||||
| **RAM Used** | Метрика, показывающая процент оперативной памяти, который занят на сервере всеми процессами. |
|
|
||||||
| **CPU Cores** | Метрика, показывающая общее количество процессорных ядер, доступных на сервере, где работает PostgreSQL. |
|
|
||||||
| **RAM Total** | Метрика, показывающая общий объем оперативной памяти, установленный на сервере. |
|
|
||||||
| **DB Disk Total** | Метрика, показывающая общий объем дискового пространства, выделенного для хранения данных базы данных PostgreSQL на сервере. |
|
|
||||||
| **CPU Basic** | Метрика, которая показывает детальную разбивку загрузки процессора по типам выполняемых задач. Она позволяет увидеть, на что именно тратится процессорное время на сервере. |
|
|
||||||
| **Memory Basic** | Метрика, которая показывает детальную разбивку использования оперативной памяти на сервере, а также информацию о SWAP. |
|
|
||||||
| **Disk IOps** | Метрика, показывающая количество операций чтения и записи, выполняемых на диске сервера в секунду. |
|
|
||||||
| **Disk Space Used Basic** | Метрика, показывающая процент занятого дискового пространства на всех подключенных файловых системах сервера. |
|
|
||||||
| **Disk R/W Data** | Показывает объем данных в байтах, читаемых с диска и записываемых на диск в секунду. |
|
|
||||||
| **Filesystem space available** | Метрика, показывающая объем свободного дискового пространства на файловой системе сервера. |
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# PgAdmin
|
|
||||||
|
|
||||||
После предоставления доступа к сервису **Cloud PostgreSQL** пользователь получает возможность управлять базами данных через веб-интерфейс **pgAdmin**. Ниже приведена инструкция по входу в систему и выполнению основных операций.
|
|
||||||
|
|
||||||
## Вход в pgAdmin
|
|
||||||
|
|
||||||
1. Откройте веб-браузер и перейдите по адресу, предоставленному для доступа к pgAdmin;
|
|
||||||
2. На странице авторизации введите **логин и пароль от pgAdmin**;
|
|
||||||
> Учетные данные направляются пользователю на электронную почту при предоставлении доступа.
|
|
||||||
3. После входа в систему в левой панели навигации откройте раздел **Servers**;
|
|
||||||
4. Выберите предварительно настроенный сервер с названием **PostgreSQL**;
|
|
||||||
5. В открывшемся окне введите пароль;
|
|
||||||
> Важно: на данном этапе необходимо указать **пароль учетной записи базы данных**, а не пароль от pgAdmin.
|
|
||||||
6. Нажмите **ОК**.
|
|
||||||
|
|
||||||
После успешной аутентификации станет доступен веб-интерфейс СУБД PostgreSQL.
|
|
||||||
|
|
||||||
## Реплики и параметры конфигураций
|
|
||||||
|
|
||||||
pgAdmin позволяет осуществлять мониторинг реплик, входящих в состав кластера. Чтобы просмотреть список реплик необходимо открыть раздел **Replica nodes** в панели навигации.
|
|
||||||
|
|
||||||
|
|
||||||
### Просмотр состояния репликаций
|
|
||||||
|
|
||||||
Чтобы проверить состояние репликации:
|
|
||||||
1. Выберите нужную реплику в разделе **Replica nodes**;
|
|
||||||
2. Перейдите в подраздел **Replication**;
|
|
||||||
3. Откройте пункт **Replication stats**;
|
|
||||||
4. Разверните раздел **Подробности** - в нем отображаются все параметры и текущее состояние репликации.
|
|
||||||
|
|
||||||
Вкладка **Replication** позволяет определить, выполняется ли передача данных на дополнительные узлы кластера.
|
|
||||||
|
|
||||||
### Просмотр конфигураций реплики
|
|
||||||
|
|
||||||
Чтобы просмотреть **параметры конфигурации PostgreSQL**, применённые к конкретной реплике, перейдите в раздел **Конфигурация**, расположенный в блоке **Replica nodes**.
|
|
||||||
|
|
||||||
Раздел **Конфигурация** содержит следующие параметры:
|
|
||||||
- **Имя** - наименование конфигурационного параметра;
|
|
||||||
- **Категория** - логическая группа параметра;
|
|
||||||
- **Значение** - текущее установленное значение;
|
|
||||||
- **Единицы** - единицы измерения (если применимо);
|
|
||||||
- **Описание** - краткое пояснение назначения параметра.
|
|
||||||
> Вкладка **Конфигурация** предназначена для просмотра текущих настроек реплики.
|
|
||||||
|
|
||||||
## Базы данных
|
|
||||||
|
|
||||||
### Просмотр существующих баз данных:
|
|
||||||
|
|
||||||
Чтобы просмотреть существующие базы данных, откройте раздел Базы данных в левой панели навигации. В этом разделе отображается перечень всех созданных баз.
|
|
||||||
|
|
||||||
### Создание новой базы данных:
|
|
||||||
|
|
||||||
1. Щелкните правой кнопкой мыши по разделу **Базы данных**;
|
|
||||||
2. В контекстном меню выберите **Создать**, затем - **База данных**;
|
|
||||||
3. Заполните обязательные поля в открывшейся форме;
|
|
||||||
4. Нажмите **Сохранить**.
|
|
||||||
|
|
||||||
## Роли входа / группы
|
|
||||||
|
|
||||||
В разделе **Роли входа/группы** отображается список пользователей (ролей), имеющих доступ к базам данных кластера.
|
|
||||||
|
|
||||||
### Создание новой роли:
|
|
||||||
|
|
||||||
1. Щелкните правой кнопкой мыши по разделу **Роли входа/группы**;
|
|
||||||
2. Выберите **Создать**, затем - **Роль входа/группы**;
|
|
||||||
3. Заполните необходимые параметры в форме создания роли;
|
|
||||||
4. Нажмите **Сохранить**.
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
# Возможности пользователя
|
|
||||||
|
|
||||||
Данный раздел описывает права, которые предоставляются пользователю PostgreSQL при создании сервиса **Cloud PostgreSQL**, а также перечень административных операций, доступных ему для самостоятельного выполнения.
|
|
||||||
|
|
||||||
При развертывании сервиса автоматически создаётся пользователь базы данных с преднастроенными атрибутами и привилегиями. Эти права позволяют заказчику самостоятельно управлять своими базами данных, ролями и пользователями в рамках созданного экземпляра PostgreSQL.
|
|
||||||
|
|
||||||
|
|
||||||
## Общая информация о пользователе
|
|
||||||
|
|
||||||
При инициализации сервиса автоматически создаётся пользователь:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
client
|
|
||||||
```
|
|
||||||
|
|
||||||
Данный пользователь является основной учётной записью для административной работы в рамках предоставленного экземпляра PostgreSQL.
|
|
||||||
|
|
||||||
Он предназначен для самостоятельного управления в пределах выданных привилегий:
|
|
||||||
- базами данных;
|
|
||||||
- ролями;
|
|
||||||
- правами доступа.
|
|
||||||
|
|
||||||
|
|
||||||
## Выданные права и ограничения
|
|
||||||
|
|
||||||
Пользователю `client` назначается набор атрибутов и привилегий, позволяющих выполнять административные операции в рамках своего экземпляра базы данных.
|
|
||||||
|
|
||||||
#### Атрибуты роли
|
|
||||||
|
|
||||||
Пользователь создаётся со следующими атрибутами:
|
|
||||||
- `CREATEDB` — разрешено создание и удаление баз данных;
|
|
||||||
- `CREATEROLE` — разрешено создание ролей и пользователей, а также управление их.
|
|
||||||
|
|
||||||
Атрибут `SUPERUSER` пользователю не предоставляется. Соответственно, доступ к системным операциям уровня кластера и настройкам сервера отсутствует.
|
|
||||||
|
|
||||||
#### Права на системную базу postgres:
|
|
||||||
|
|
||||||
К стандартной базе данных `postgres` пользователю предоставлено только право подключения — `CONNECT`
|
|
||||||
|
|
||||||
**Иные привилегии (создание объектов, изменение схем и т.д.) на данную базу не выдаются.**
|
|
||||||
|
|
||||||
|
|
||||||
## Мониторинг и системные представления
|
|
||||||
|
|
||||||
Для выполнения базовых задач мониторинга пользователю дополнительно предоставлены:
|
|
||||||
- членство в роли `pg_monitor`;
|
|
||||||
- право `SELECT` на системное представление:
|
|
||||||
```sql
|
|
||||||
pg_catalog.pg_stat_replication
|
|
||||||
```
|
|
||||||
|
|
||||||
Доступ к системной информации предоставляется исключительно **в режиме чтения**. Изменение системных представлений и параметров сервера недоступно.
|
|
||||||
|
|
||||||
|
|
||||||
## Изменение пароля
|
|
||||||
|
|
||||||
После первого подключения к базе данных пользователь `client` обязан выполнить изменения пароля.
|
|
||||||
|
|
||||||
Изменить пароля можно:
|
|
||||||
- в открытом виде (с передачей нового значения пароля);
|
|
||||||
- с указанием заранее сгенерированного хэша.
|
|
||||||
|
|
||||||
На сервере используется алгоритм шифрования паролей:
|
|
||||||
|
|
||||||
```
|
|
||||||
scram-sha-256
|
|
||||||
```
|
|
||||||
|
|
||||||
При использовании **SCRAM** применяется следующий формат хэша:
|
|
||||||
|
|
||||||
```
|
|
||||||
$<iterations>:<salt>$<storedkey>:<serverkey>
|
|
||||||
```
|
|
||||||
|
|
||||||
| Операция | Описание | Команда SQL |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
|Смена пароля в открытом виде | Для смены пароля в открытом виде | ```ALTER USER client WITH PASSWORD 'new_strong_password';``` |
|
|
||||||
|Смена пароля с указанием хэша | Рекомендуется использовать сложный уникальный пароль, соответствующий требованиям информационной безопасности, и хранить его в защищённом хранилище | ```ALTER USER client WITH ENCRYPTED PASSWORD '$4096:...';``` |
|
|
||||||
|Создание новой базы данных | Для создания базы данных | ```CREATE DATABASE app_db;``` |
|
|
||||||
|Создание базы данных с указанием владельца | Пользователь, указанный как владелец, будет иметь полный контроль над базой данных, включая права на её удаление и изменение. По умолчанию владельцем создаваемой базы данных является пользователь, который её создает | ```CREATE DATABASE app_db OWNER client;``` |
|
|
||||||
|
|
||||||
### Требования к паролям
|
|
||||||
|
|
||||||
**Длина пароля (рекомендуемая):**
|
|
||||||
|
|
||||||
- для учётной записи пользователя - не менее 12 знаков;
|
|
||||||
- для учётных записей администраторов, технических и служебных учётных записей - не менее 16 знаков.
|
|
||||||
|
|
||||||
**Сложность пароля:** рекомендуется использовать уникальный пароль, содержащий символы как минимум трёх из четырёх указанных ниже групп (при отсутствии технических ограничений):
|
|
||||||
|
|
||||||
- буквы латинского алфавита в верхнем регистре (A-Z);
|
|
||||||
- буквы латинского алфавита в нижнем регистре (a-z);
|
|
||||||
- цифры (0-9);
|
|
||||||
- специальные символы и знаки пунктуации (например, `!@#$%^&*(),.?`).
|
|
||||||
|
|
||||||
**Периодичность смены:** рекомендуемая периодичность смены пароля - не реже одного раза в год.
|
|
||||||
|
|
||||||
## Создание пользователей и ролей
|
|
||||||
|
|
||||||
Пользователь `client` имеет право создавать новые роли и пользователей для приложений, а также управлять их правами доступа.
|
|
||||||
|
|
||||||
| Операция | Описание | Команда SQL |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
|Создание роли без логина | Для входа в базу данных (например, для организации прав доступа) | ```CREATE ROLE app_role; ```|
|
|
||||||
|Создание пользователя с паролем | Для создания пользователя с паролем. После выполнения этой команды новый пользователь `app_user` будет иметь возможность входа в базу данных, используя указанный пароль. | ```CREATE USER app_user WITH PASSWORD 'app_password';``` |
|
|
||||||
|Назначение роли пользователю | Для назначения роли пользователю. Данная команда позволяет управлять правами пользователя в рамках определённой роли. После выполнения этой команды пользователь `app_user` станет членом роли `app_role`, и будет наследовать все права, связанные с этой ролью. | ```GRANT app_role TO app_user; ``` |
|
|
||||||
|
|
||||||
|
|
||||||
## Управление правами доступа
|
|
||||||
|
|
||||||
После создания пользователей и ролей необходимо назначить им соответствующие права доступа.
|
|
||||||
|
|
||||||
| Операция | Описание | Команда SQL |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
|Передача владельца базы данных | Для передачи прав владения базой данных другому пользователю. После выполнения этой команды база данных `app_db` будет принадлежать пользователю `app_user`, и он будет иметь полный контроль над ней.| ```ALTER DATABASE app_db OWNER TO app_user;``` |
|
|
||||||
|Выдача прав на подключение к базе данных | Для предоставления прав к подключению к базе данных. После выполнения этой команды пользователь может `app_user` подключаться к базе данных `app_db`. | ```GRANT CONNECT ON DATABASE app_db TO app_user;```|
|
|
||||||
|Предоставление прав на схему public | Для предоставления прав на использование схемы `public`. После выполнения этой команды пользователь `app_user` может использовать объекты в схеме `public`, а также создавать новые объекты внутри неё. | ```GRANT USAGE, CREATE ON SCHEMA public TO app_user;```|
|
|
||||||
|Предоставление прав на существующие таблицы | Для предоставления доступа пользователю к существующим таблицам в схеме `public`. После выполнения этой команды пользователь `app_user` может выполнять операции чтения, вставки, обновления и удаления данных в существующих таблицах схемы `public`.| ```GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;``` |
|
|
||||||
|Предоставление прав на будущие таблицы | Если необходимо автоматически предоставить пользователю права на новые таблицы, создаваемые в схеме `public`. После выполнения этой команды все будущие таблицы, создаваемые в схеме `public`, будут автоматически иметь права для пользователя `app_user` на чтение, вставку, обновление и удаление данных. | ```ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;```|
|
|
||||||
|
|
||||||
|
|
||||||
## Мониторинг репликации
|
|
||||||
|
|
||||||
Пользователь `client` имеет доступ к системным представлениям для мониторинга состояния репликации в кластере PostgreSQL.
|
|
||||||
|
|
||||||
| Операция | Описание | Команда SQL |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
|Просмотр состояния репликации | Для просмотра текущего статуса репликации. Этот запрос возвращает информацию о всех репликах, подключённых к основному (primary) серверу. |```SELECT * FROM pg_stat_replication;```|
|
|
||||||
|
|
||||||
::: warning Ограничения доступа реплкации
|
|
||||||
|
|
||||||
Пользователь `client` имеет доступ к данным в представлении `pg_stat_replication` только в режиме **read-only**. Это означает, что он может просматривать состояние репликации, но не может изменять или вмешиваться в процесс репликации.
|
|
||||||
|
|
||||||
:::
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
section_links:
|
|
||||||
- title: Cloud PostgreSQL
|
|
||||||
link: /PaaS/PostgreSQL/PostgreSQL-index.md
|
|
||||||
description: Обзор сервиса PostgreSQL
|
|
||||||
- title: IPSEC
|
|
||||||
link: /PaaS/IPSEC.md
|
|
||||||
description: Параметры конфигурации IPSEC
|
|
||||||
---
|
|
||||||
|
|
||||||
# Начало работы в Cloud PostgreSQL
|
|
||||||
@@ -7,8 +7,8 @@ section_links:
|
|||||||
link: /compute/compute-how-to/compute-connect-inside.md
|
link: /compute/compute-how-to/compute-connect-inside.md
|
||||||
description: Подключиться к виртуальной машине по SSH с помощью ключевой пары по внутреннему IP-адресу через джамп-хост
|
description: Подключиться к виртуальной машине по SSH с помощью ключевой пары по внутреннему IP-адресу через джамп-хост
|
||||||
- title: Подключение по SSH по логину и паролю
|
- title: Подключение по SSH по логину и паролю
|
||||||
link: /compute/compute-how-to/compute-connect-inside.md
|
link: /compute/compute-how-to/compute-connect-pwd.md
|
||||||
description: Подключиться к виртуальной машине по SSH с помощью логина и пароля
|
description: Подключиться к виртуальной машине по SSH с помощью логина и пароля
|
||||||
---
|
---
|
||||||
|
|
||||||
# Подключение к ВМ
|
# Подключение к ВМ
|
||||||
@@ -14,9 +14,9 @@ section_links:
|
|||||||
description: Резервирование, назначение IP-адреса виртуальной машине, удаление IP-адресов
|
description: Резервирование, назначение IP-адреса виртуальной машине, удаление IP-адресов
|
||||||
- title: Группы размещения
|
- title: Группы размещения
|
||||||
link: /compute/compute-how-to/compute-affinity.md
|
link: /compute/compute-how-to/compute-affinity.md
|
||||||
description: Создание правил размещения виртуальных машин на физических хостах, управление группами размещения
|
description: Создание правил размещения виртуальных машин на физических хостах, управление группами размещения
|
||||||
---
|
---
|
||||||
|
|
||||||
# Виртуальные машины
|
# Виртуальные машины
|
||||||
|
|
||||||
Сервис **Виртуальные машины** предоставляет пользователям виртуальные машины.
|
Сервис **Виртуальные машины** предоставляет пользователям виртуальные машины.
|
||||||
+1
-11
@@ -91,7 +91,7 @@ services:
|
|||||||
- title: Резервное копирование
|
- title: Резервное копирование
|
||||||
description: Создание, хранение и восстановление копии виртуальных машин
|
description: Создание, хранение и восстановление копии виртуальных машин
|
||||||
icon: refresh
|
icon: refresh
|
||||||
link: /backups/index
|
link: /backups/index
|
||||||
- title: Базы данных
|
- title: Базы данных
|
||||||
articles:
|
articles:
|
||||||
- title: ClickHouse
|
- title: ClickHouse
|
||||||
@@ -100,16 +100,6 @@ services:
|
|||||||
- title: MongoDB
|
- title: MongoDB
|
||||||
description: В работе
|
description: В работе
|
||||||
icon: database
|
icon: database
|
||||||
- title: PostgreSQL
|
|
||||||
description: Объектно-реляционная СУБД с открытым кодом, обеспечивающая высокую надёжность и масштабируемость
|
|
||||||
icon: database
|
|
||||||
link: /PaaS/index
|
|
||||||
- title: Брокеры сообщений
|
|
||||||
articles:
|
|
||||||
- title: Apache Kafka
|
|
||||||
description: Распределённая система для потоковой передачи данных в реальном времени
|
|
||||||
icon: message
|
|
||||||
link: /Apache-Kafka/Kafka-index
|
|
||||||
- title: Аналитика
|
- title: Аналитика
|
||||||
articles:
|
articles:
|
||||||
- title: Визуализация и анализ данных
|
- title: Визуализация и анализ данных
|
||||||
|
|||||||
Reference in New Issue
Block a user