Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e16de52934 | |||
| 9f287b5f15 | |||
| f242ddd4cb | |||
| 3a96cb441e | |||
| c01886e49b | |||
| 9a21a53e11 | |||
| 83f5e68647 | |||
| 46b4dfec73 | |||
| ff8c1af855 | |||
| fc7486d182 | |||
| ec84ec85e1 | |||
| 52edef245f | |||
| a47571d8af | |||
| df88416247 | |||
| b948e5a433 | |||
| dfebbc3c45 | |||
| 37d1f1f17e | |||
| 968dc9de10 | |||
| d126d05f4d | |||
| 3c441310a4 | |||
| f5d44a3f8f | |||
| 386e89f8f3 | |||
| ba4d5e80e2 | |||
| 8eb2c67453 | |||
| 36ba0c1f0a | |||
| a42f281613 | |||
| e3cf876ccc | |||
| f83c928c47 | |||
| f17badaa68 | |||
| 32731bda89 | |||
| 4afd915f49 | |||
| 54e7130488 | |||
| f66984ced0 | |||
| b3a8881074 | |||
| 96e7b4827a | |||
| 4019438a48 | |||
| 0ad71bd579 | |||
| a7e57c575d | |||
| 4270668c7c | |||
| 9432e755e6 | |||
| 5e284757e7 | |||
| bd08e437b6 | |||
| 49a7b5e0b4 | |||
| 81ee62ef52 | |||
| 601bec1af2 | |||
| efbdef87fa | |||
| b794e5aebd | |||
| 9e3bf98788 | |||
| ef38318ce8 | |||
| 6619c5cc7f | |||
| 70553ded2f | |||
| 184fe5eb1b | |||
| f6111628b0 | |||
| 94bc0035d3 | |||
| d2e654bf25 | |||
| 36f291aba4 | |||
| 41840e657a | |||
| 64bbd09f15 | |||
| 18ad8159cd | |||
| 872b9d519f | |||
| 702190b65a | |||
| ee6b50cb82 | |||
| de75b64133 | |||
| 07052a4160 | |||
| 99e30cda4a | |||
| 2b489b529f | |||
| 4b32ec3950 | |||
| 24116b1633 | |||
| 6bcd90f9bc | |||
| 46ed947331 | |||
| 1a600b7851 | |||
| 64d75d9aef | |||
| 4fdbff209f | |||
| 63e55b74e2 | |||
| f6865fbfe4 | |||
| 8775794f64 | |||
| 510114e1db | |||
| 00edb34a9d | |||
| afd3407309 | |||
| 81bc33a1e9 | |||
| 2495d86655 | |||
| 712f7ddbc0 | |||
| d4888e088e | |||
| 8dbbe46636 | |||
| 4186722ab9 | |||
| 184acc6485 | |||
| 1e42c41971 | |||
| 3331da2399 | |||
| ec841dff60 | |||
| e429ff9a47 | |||
| aa3a35b840 | |||
| 4c2d28fb37 | |||
| 322d7af231 | |||
| 77f37ea74c | |||
| 3194088e94 | |||
| d8020505c3 |
+1
-1
@@ -17,4 +17,4 @@ packages-list.json
|
||||
/.vale
|
||||
/.vscode
|
||||
/.vale.ini
|
||||
/VimpelcomCAG2.pem
|
||||
/.markdownlint.json
|
||||
Submodule
+1
Submodule beecloud-docs added at df88416247
@@ -0,0 +1,40 @@
|
||||
deploy-prod:
|
||||
stage: deploy
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine:3.21.2
|
||||
variables:
|
||||
stand: beecloud-docs.beecloud-docs.cloud.vimpelcom.ru
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "push"
|
||||
when: manual
|
||||
before_script:
|
||||
- |
|
||||
sed -i s%https://dl-cdn.alpinelinux.org/%http://rhrepo.vimpelcom.ru/ext/ya/mirrors/% /etc/apk/repositories && \
|
||||
apk --no-cache add tzdata ca-certificates curl openssh-client yq jq && \
|
||||
rm -rf /var/cache/apk/*
|
||||
- which ssh-agent || (apt-get update -y && apt-get install openssh-client -y)
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir -p ~/.ssh
|
||||
- echo -n "$TECH_SSH_KEY" | tr -d '\r' > ~/.ssh/id_rsa
|
||||
- chmod 700 ~/.ssh
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- >
|
||||
echo "stand: ${stand}"
|
||||
ssh-keyscan "${stand}" >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- PRODUCT="$PRODUCT_DMZ"
|
||||
script:
|
||||
- >
|
||||
echo -e "Connect to ${stand}..." &&
|
||||
scp -o StrictHostKeyChecking=no ci/deploy/deploy.sh "dorootless@${stand}:~/deploy.sh" &&
|
||||
ssh "dorootless@${stand}" "export CONTAINER_REGISTRY=$CONTAINER_REGISTRY &&
|
||||
export PRODUCT=$PRODUCT &&
|
||||
export PRODUCT_VERSION=$PRODUCT_VERSION &&
|
||||
export IMAGE_NAME=$IMAGE_NAME &&
|
||||
chmod 700 ~/deploy.sh &&
|
||||
~/deploy.sh ${IMAGE_NAME} &&
|
||||
rm -f ~/deploy.sh"
|
||||
needs:
|
||||
- job: build-image
|
||||
optional: true
|
||||
Generated
+1972
-1342
File diff suppressed because it is too large
Load Diff
+12
-11
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.6.4",
|
||||
"version": "0.6.5-main",
|
||||
"description": "Beeline Cloud docs",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -15,16 +15,17 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@beeline/design-tokens": "^1.31.0",
|
||||
"vue": "3.4.7"
|
||||
"@beeline/design-tokens": "^1.31.6",
|
||||
"vue": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docsearch/css": "3.3.0",
|
||||
"@types/node": "20.10.7",
|
||||
"@vitejs/plugin-vue": "4.3.4",
|
||||
"sass": "1.69.7",
|
||||
"typescript": "^5.8.3",
|
||||
"vitepress": "1.0.0-rc.40",
|
||||
"vitepress-plugin-tabs": "0.5.0"
|
||||
"@docsearch/css": "4.1.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"@vitejs/plugin-vue": "^6.0.3",
|
||||
"sass": "^1.70.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-plugin-static-copy": "^3.1.4",
|
||||
"vitepress": "^1.6.4",
|
||||
"vitepress-plugin-tabs": "^0.7.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
+188
-45
@@ -1,6 +1,9 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import { overrideComponents } from './override-components'
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
@@ -43,10 +46,11 @@ console.log({ base: typeof new_version !== 'undefined' ? '/' : '/docs/' })
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
srcDir: ".",
|
||||
title: "cloud",
|
||||
title: " ",
|
||||
description: "Документация Beeline Cloud",
|
||||
head: [['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/bee-favicon.png' }]],
|
||||
base: typeof new_version !== 'undefined' ? '/' : '/docs/',
|
||||
appearance: false,
|
||||
markdown: {
|
||||
config(md) {
|
||||
md.use(tabsMarkdownPlugin)
|
||||
@@ -54,8 +58,31 @@ export default defineConfig({
|
||||
},
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: overrideComponents(),
|
||||
}
|
||||
alias: [
|
||||
...overrideComponents(),
|
||||
{
|
||||
find: '@',
|
||||
replacement: fileURLToPath(new URL('./theme', import.meta.url))
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{
|
||||
src: resolve(__dirname, '../../node_modules/@beeline/design-tokens/assets/fonts'),
|
||||
dest: 'assets',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
api: 'modern-compiler',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
locales: {
|
||||
root: {
|
||||
@@ -65,9 +92,9 @@ export default defineConfig({
|
||||
},
|
||||
themeConfig: {
|
||||
logo: {
|
||||
light: '/logo-light-theme.svg',
|
||||
dark: '/logo-dark-theme.svg',
|
||||
alt: 'cloud',
|
||||
light: '/img/logo-cloud.svg',
|
||||
dark: '/img/logo-cloud.svg',
|
||||
alt: '',
|
||||
},
|
||||
search: {
|
||||
provider: 'local',
|
||||
@@ -80,14 +107,8 @@ export default defineConfig({
|
||||
buttonAriaLabel: 'Поиск'
|
||||
},
|
||||
modal: {
|
||||
noResultsText: 'Не удалось загрузить данные',
|
||||
noResultsText: 'По вашему запросу ничего не найдено',
|
||||
resetButtonTitle: 'Сбросить',
|
||||
displayDetails: 'Показать расширенный список',
|
||||
footer: {
|
||||
selectText: 'Выбрать',
|
||||
closeText: 'Закрыть',
|
||||
navigateText: 'Перейти',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,6 +158,58 @@ export default defineConfig({
|
||||
{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/': [
|
||||
{
|
||||
@@ -146,8 +219,9 @@ export default defineConfig({
|
||||
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
||||
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
||||
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
||||
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
||||
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -167,21 +241,47 @@ export default defineConfig({
|
||||
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: 'Снимки ВМ', 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/isolated-to-routed.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',
|
||||
@@ -207,25 +307,58 @@ export default defineConfig({
|
||||
{
|
||||
text: 'Виртуальные машины', link: '/compute/index.md',
|
||||
},
|
||||
{ text: 'Обзор сервиса', link: '/compute/compute-overview.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 по внешнему 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.md' },
|
||||
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip.md' },
|
||||
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-affinity.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: [
|
||||
@@ -239,29 +372,39 @@ export default defineConfig({
|
||||
text: 'Администрирование', link: '/admin/index.md',
|
||||
},
|
||||
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
||||
],
|
||||
'/billing/': [
|
||||
{ text: 'Биллинг', link: '/billing/about.md',
|
||||
],
|
||||
'/vdi/': [
|
||||
{
|
||||
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
||||
},
|
||||
{
|
||||
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Аналитика потребления', link: '/billing/usage-analytics.md' },
|
||||
],
|
||||
},
|
||||
],
|
||||
'/concepts/': [
|
||||
{text: 'Виртуальные дата-центры', link: '/concepts/datacenters.md'},
|
||||
{text: 'DNS', link: '/concepts/dns.md'},
|
||||
{text: 'Edge Gateway', link: '/concepts/edge-gateway.md'},
|
||||
{text: 'NAT', link: '/concepts/nat.md'},
|
||||
{text: 'Типы сетей в vDC', link: '/concepts/network-types.md'},
|
||||
{text: 'Ролевая модель', link: '/concepts/roles.md'},
|
||||
{text: 'vApp', link: '/concepts/vApp.md'},
|
||||
],
|
||||
'/monitoring/': [
|
||||
{
|
||||
text: 'Мониторинг', link: '/monitoring/about.md',
|
||||
},
|
||||
],
|
||||
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'
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -54,10 +54,12 @@ const pageName = computed(() =>
|
||||
<div class="content-container">
|
||||
<slot name="doc-before" />
|
||||
<main class="main">
|
||||
<Content class="vp-doc" :class="[
|
||||
pageName,
|
||||
theme.externalLinkIcon && 'external-link-icon-enabled'
|
||||
]" />
|
||||
<div class="vp-doc" :class="[
|
||||
pageName,
|
||||
theme.externalLinkIcon && 'external-link-icon-enabled'
|
||||
]">
|
||||
<Content />
|
||||
</div>
|
||||
<SectionLinkList v-if="frontmatter.section_links" :links="frontmatter.section_links" />
|
||||
</main>
|
||||
<VPDocFooter>
|
||||
@@ -74,7 +76,7 @@ const pageName = computed(() =>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use 'src/assets/scss/app/helpers/media';
|
||||
@use '@/scss/helpers/media';
|
||||
|
||||
.VPDoc {
|
||||
padding: 32px 24px 96px;
|
||||
|
||||
@@ -6,6 +6,8 @@ import { usePrevNext } from 'vitepress/dist/client/theme-default/composables/pre
|
||||
import VPIconEdit from 'vitepress/dist/client/theme-default/components/icons/VPIconEdit.vue'
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
||||
import VPDocFooterLastUpdated from 'vitepress/dist/client/theme-default/components/VPDocFooterLastUpdated.vue'
|
||||
import CustomIcon from './CustomIcon.vue'
|
||||
import { Icons } from '@beeline/design-tokens/js/iconfont/icons'
|
||||
|
||||
const { theme, page, frontmatter } = useData()
|
||||
|
||||
@@ -43,14 +45,14 @@ const showFooter = computed(() => {
|
||||
<nav v-if="control.prev?.link || control.next?.link" class="prev-next">
|
||||
<div class="pager">
|
||||
<VPLink v-if="control.prev?.link" class="pager-link prev" :href="control.prev.link">
|
||||
<span class="desc" v-html="theme.docFooter?.prev || 'Previous page'"></span>
|
||||
<CustomIcon class="desc-prev" :icon="Icons.ArrowRight" />
|
||||
<span class="title" v-html="control.prev.text"></span>
|
||||
</VPLink>
|
||||
</div>
|
||||
<div class="pager">
|
||||
<VPLink v-if="control.next?.link" class="pager-link next" :href="control.next.link">
|
||||
<span class="desc" v-html="theme.docFooter?.next || 'Next page'"></span>
|
||||
<span class="title" v-html="control.next.text"></span>
|
||||
<CustomIcon class="desc-next" :icon="Icons.ArrowRight" />
|
||||
</VPLink>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -59,7 +61,7 @@ const showFooter = computed(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.VPDocFooter {
|
||||
margin-top: 64px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.edit-info {
|
||||
@@ -98,8 +100,6 @@ const showFooter = computed(() => {
|
||||
}
|
||||
|
||||
.prev-next {
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
padding-top: 24px;
|
||||
display: grid;
|
||||
grid-row-gap: 8px;
|
||||
}
|
||||
@@ -115,10 +115,19 @@ const showFooter = computed(() => {
|
||||
display: block;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 11px 16px 13px;
|
||||
padding: 10px 16px 10px 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: border-color 0.25s;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
color: #1a73e8;
|
||||
|
||||
&.next {
|
||||
padding: 10px 12px 10px 16px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.pager-link:hover {
|
||||
@@ -136,6 +145,14 @@ const showFooter = computed(() => {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
|
||||
&-next {
|
||||
rotate: -270deg;
|
||||
}
|
||||
|
||||
&-prev {
|
||||
rotate: -90deg;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
|
||||
@@ -33,6 +33,8 @@ import { escapeRegExp } from 'vitepress/dist/client/shared'
|
||||
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
|
||||
import { LRUCache } from 'vitepress/dist/client/theme-default/support/lru'
|
||||
import { createSearchTranslate } from 'vitepress/dist/client/theme-default/support/translation'
|
||||
import CustomIcon from './CustomIcon.vue';
|
||||
import { Icons } from '@beeline/design-tokens/js/iconfont/icons';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'close'): void
|
||||
@@ -496,21 +498,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
:title="$t('modal.resetButtonTitle')"
|
||||
@click="resetSearch"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"
|
||||
/>
|
||||
</svg>
|
||||
<CustomIcon :icon="Icons.Close" size="large" style="padding: 12px 0;" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -576,12 +564,6 @@ function formMarkRegex(terms: Set<string>) {
|
||||
<p class="no-results-text">
|
||||
{{ $t('modal.noResultsText') }}
|
||||
</p>
|
||||
<button
|
||||
class="no-results-button"
|
||||
@click="retrySearch(searchIndex, filterText)"
|
||||
>
|
||||
Попробовать еще раз
|
||||
</button>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -610,7 +592,6 @@ function formMarkRegex(terms: Set<string>) {
|
||||
background: var(--vp-local-search-bg);
|
||||
width: min(100vw - 60px, 900px);
|
||||
height: min-content;
|
||||
max-height: min(100vh - 128px, 900px);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
@@ -679,7 +660,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
|
||||
.search-actions button {
|
||||
padding: 8px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.search-actions button:not([disabled]):hover,
|
||||
@@ -728,11 +709,11 @@ function formMarkRegex(terms: Set<string>) {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
box-shadow: var(--vp-c-shadow-3);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(25, 28, 52, 0.18);
|
||||
padding: 8px 0;
|
||||
max-height: min(100vh - 214px, 900px);
|
||||
box-shadow: 0px 6px 38px rgba(0, 0, 0, 0.16), 0px 0px 10px rgba(0, 0, 0, 0.08);
|
||||
|
||||
li:hover {
|
||||
background-color: rgba(25, 28, 52, 0.08);
|
||||
@@ -745,7 +726,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
gap: 8px;
|
||||
transition: none;
|
||||
outline: none;
|
||||
height: 66px;
|
||||
min-height: 66px;
|
||||
}
|
||||
|
||||
.result > div {
|
||||
@@ -858,17 +839,18 @@ function formMarkRegex(terms: Set<string>) {
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
z-index: 100;
|
||||
box-shadow: 0 0 10 0 rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0px 6px 38px rgba(0, 0, 0, 0.16), 0px 0px 10px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(25, 28, 52, 0.18);
|
||||
background-color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.no-results-text {
|
||||
font-weight: 700;
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(25, 28, 52, 0.48);
|
||||
}
|
||||
|
||||
.no-results-button {
|
||||
@@ -879,6 +861,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(9, 11, 22, 0.94);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
||||
@@ -1,11 +1,329 @@
|
||||
.custom-block {
|
||||
padding: 24px;
|
||||
@use "@beeline/design-tokens/scss/tokens/globals/colors";
|
||||
@use "@beeline/design-tokens/scss/tokens/themes";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as *;
|
||||
|
||||
&-title {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
margin-bottom: 12px;
|
||||
.custom-block {
|
||||
padding: 24px;
|
||||
|
||||
&-title {
|
||||
font-size: 17px !important;
|
||||
line-height: 22px !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: .2px !important;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
&.tip a {
|
||||
color: #1a73e8;
|
||||
|
||||
&:hover {
|
||||
color: #1a73e8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
padding: 24px 24px 24px 64px;
|
||||
line-height: 24px;
|
||||
font-size: var(--vp-custom-block-font-size);
|
||||
color: var(--vp-c-text-2);
|
||||
|
||||
&.custom-block.details {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.info {
|
||||
border-color: var(--vp-custom-block-info-border);
|
||||
color: var(--vp-custom-block-info-text);
|
||||
background-color: var(--vp-custom-block-info-bg);
|
||||
}
|
||||
|
||||
.custom-block.info a,
|
||||
.custom-block.info code {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.info a:hover,
|
||||
.custom-block.info a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.info code {
|
||||
background-color: var(--vp-custom-block-info-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.note {
|
||||
border-color: var(--vp-custom-block-note-border);
|
||||
color: var(--vp-custom-block-note-text);
|
||||
background-color: var(--vp-custom-block-note-bg);
|
||||
}
|
||||
|
||||
.custom-block.note a,
|
||||
.custom-block.note code {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.note a:hover,
|
||||
.custom-block.note a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.note code {
|
||||
background-color: var(--vp-custom-block-note-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.tip {
|
||||
border-color: var(--vp-custom-block-tip-border);
|
||||
color: var(--vp-custom-block-tip-text);
|
||||
background-color: var(--vp-custom-block-tip-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-clock);
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.tip a,
|
||||
.custom-block.tip code {
|
||||
color: var(--vp-c-tip-1);
|
||||
}
|
||||
|
||||
.custom-block.tip a:hover,
|
||||
.custom-block.tip a:hover > code {
|
||||
color: var(--vp-c-tip-2);
|
||||
}
|
||||
|
||||
.custom-block.tip code {
|
||||
background-color: var(--vp-custom-block-tip-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.important {
|
||||
border-color: var(--vp-custom-block-important-border);
|
||||
color: var(--vp-custom-block-important-text);
|
||||
background-color: var(--vp-custom-block-important-bg);
|
||||
}
|
||||
|
||||
.custom-block.important a,
|
||||
.custom-block.important code {
|
||||
color: var(--vp-c-important-1);
|
||||
}
|
||||
|
||||
.custom-block.important a:hover,
|
||||
.custom-block.important a:hover > code {
|
||||
color: var(--vp-c-important-2);
|
||||
}
|
||||
|
||||
.custom-block.important code {
|
||||
background-color: var(--vp-custom-block-important-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.warning {
|
||||
border-color: var(--vp-custom-block-warning-border);
|
||||
color: var(--vp-custom-block-warning-text);
|
||||
background-color: var(--vp-custom-block-warning-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-info-circled);
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.warning a,
|
||||
.custom-block.warning code {
|
||||
color: $color-text-link;
|
||||
}
|
||||
|
||||
.custom-block.warning a:hover,
|
||||
.custom-block.warning a:hover > code {
|
||||
color: $color-text-link;
|
||||
}
|
||||
|
||||
.custom-block.warning code {
|
||||
background-color: var(--vp-custom-block-warning-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.danger {
|
||||
border-color: var(--vp-custom-block-danger-border);
|
||||
color: var(--vp-custom-block-danger-text);
|
||||
background-color: var(--vp-custom-block-danger-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-warning-triangle);
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.danger a,
|
||||
.custom-block.danger code {
|
||||
color: var(--vp-c-danger-1);
|
||||
}
|
||||
|
||||
.custom-block.danger a:hover,
|
||||
.custom-block.danger a:hover > code {
|
||||
color: var(--vp-c-danger-2);
|
||||
}
|
||||
|
||||
.custom-block.danger code {
|
||||
background-color: var(--vp-custom-block-danger-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.caution {
|
||||
border-color: var(--vp-custom-block-caution-border);
|
||||
color: var(--vp-custom-block-caution-text);
|
||||
background-color: var(--vp-custom-block-caution-bg);
|
||||
}
|
||||
|
||||
.custom-block.caution a,
|
||||
.custom-block.caution code {
|
||||
color: var(--vp-c-caution-1);
|
||||
}
|
||||
|
||||
.custom-block.caution a:hover,
|
||||
.custom-block.caution a:hover > code {
|
||||
color: var(--vp-c-caution-2);
|
||||
}
|
||||
|
||||
.custom-block.caution code {
|
||||
background-color: var(--vp-custom-block-caution-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.details {
|
||||
border-color: var(--vp-custom-block-details-border);
|
||||
color: var(--vp-custom-block-details-text);
|
||||
background-color: transparent;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
|
||||
pre {
|
||||
border: none !important;
|
||||
|
||||
}
|
||||
|
||||
div {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
&:open {
|
||||
&.custom-block.details summary {
|
||||
background-color: $color-background-base-hover;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
|
||||
&::before {
|
||||
background-image: var(--vp-icon-nav-arrow-up);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details a {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.details a:hover,
|
||||
.custom-block.details a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.details code {
|
||||
background-color: var(--vp-custom-block-details-code-bg);
|
||||
}
|
||||
|
||||
.custom-block-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.custom-block p + p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.custom-block.details summary {
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
font-size: 19px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.2px;
|
||||
display: block;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
content: '';
|
||||
background-image: var(--vp-icon-nav-arrow-down);
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details {
|
||||
h1, h2, h3, h4, h5, ul, p {
|
||||
margin: 0 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
padding: 0 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details summary + p {
|
||||
padding: 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.custom-block a {
|
||||
color: inherit;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
|
||||
.custom-block a:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.custom-block code {
|
||||
font-size: var(--vp-custom-block-code-font-size);
|
||||
}
|
||||
|
||||
.custom-block.custom-block th,
|
||||
.custom-block.custom-block blockquote > p {
|
||||
font-size: var(--vp-custom-block-font-size);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
.VPDocAside {
|
||||
.outline-link {
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
letter-spacing: 0.2px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
@@ -19,10 +19,11 @@
|
||||
}
|
||||
|
||||
.outline-title {
|
||||
font-size: 17px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
line-height: 18px;
|
||||
padding-bottom: 16px;
|
||||
color: colors.$color-text-black-active;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
@@ -1,135 +1,566 @@
|
||||
@use "@beeline/design-tokens/scss/tokens/globals/colors";
|
||||
@use "@beeline/design-tokens/scss/tokens/themes";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as *;
|
||||
|
||||
@mixin font_style($fontSize, $fontWeight, $lineHeight, $letterSpacing) {
|
||||
font-size: $fontSize;
|
||||
font-weight: $fontWeight;
|
||||
line-height: $lineHeight;
|
||||
letter-spacing: $letterSpacing;
|
||||
font-size: $fontSize;
|
||||
font-weight: $fontWeight;
|
||||
line-height: $lineHeight;
|
||||
letter-spacing: $letterSpacing;
|
||||
}
|
||||
|
||||
@mixin generate-numbered-list-styles($start, $end) {
|
||||
@for $counter from $start through $end {
|
||||
$counter-name: list + ' ' + ($counter - 1);
|
||||
ol[start*="#{$counter}"] {
|
||||
list-style-type: none;
|
||||
counter-reset: $counter-name;
|
||||
}
|
||||
@for $counter from $start through $end {
|
||||
$counter-name: list + ' ' + ($counter - 1);
|
||||
ol[start*="#{$counter}"] {
|
||||
list-style-type: none;
|
||||
counter-reset: $counter-name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc {
|
||||
font-size: 17px;
|
||||
font-size: 17px;
|
||||
|
||||
// Titles
|
||||
h1 {
|
||||
@include font_style(44px, 500, 46px, 0.3px);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
// Titles
|
||||
h1 {
|
||||
@include font_style(44px, 500, 56px, 0.3px);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@include font_style(34px, 400, 36px, 0.3px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h2 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin: 40px 0 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h3 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@include font_style(20px, 700, 28px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h4 {
|
||||
@include font_style(20px, 700, 28px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
@include font_style(17px, 500, 22px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h5 {
|
||||
@include font_style(17px, 500, 22px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// Text
|
||||
ol {
|
||||
list-style-type: none;
|
||||
counter-reset: list;
|
||||
margin: 0 0 0 50px;
|
||||
padding: 0 0 5px 0;
|
||||
font-size: 16px;
|
||||
// Text
|
||||
ol {
|
||||
list-style-type: none;
|
||||
counter-reset: list;
|
||||
margin: 0 0 0 50px;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
|
||||
& > * + * {
|
||||
margin-top: 50px;
|
||||
}
|
||||
& > * + * {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@include generate-numbered-list-styles(2, 50);
|
||||
|
||||
ol li {
|
||||
position: relative;
|
||||
padding: 8px 0 0 0;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
margin-top: 8px;
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
}
|
||||
|
||||
ol li:nth-last-of-type(n+2)::after {
|
||||
content: '';
|
||||
border-left: 1px solid rgb(201, 197, 197);
|
||||
position: absolute;
|
||||
line-height: 100%;
|
||||
left: -30px;
|
||||
top: 43px;
|
||||
bottom: -25px;
|
||||
}
|
||||
|
||||
ol li::before {
|
||||
content: counter(list);
|
||||
counter-increment: list;
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -48px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
background-color: colors.$color-background-brand;
|
||||
color: themes.$color-text-active;
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ul li:nth-last-of-type(n):after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
ol ul li::before {
|
||||
counter-increment: list;
|
||||
content: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol li:last-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
ul li:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ol li p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
color: #1a73e8;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover, &:focus-visible, &:focus, &:active {
|
||||
color: #1a73e8;
|
||||
}
|
||||
|
||||
@include generate-numbered-list-styles(2, 50);
|
||||
|
||||
ol li {
|
||||
position: relative;
|
||||
padding: 5px 0 0 0;
|
||||
line-height: 1.4;
|
||||
&:visited {
|
||||
color: #7e00ed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 34px;
|
||||
// Tabs
|
||||
.plugin-tabs {
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
background-color: revert-layer !important;
|
||||
|
||||
&--tab {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
&--content {
|
||||
padding: 24px !important;
|
||||
|
||||
.language- {
|
||||
border: none;
|
||||
padding: 0px !important;
|
||||
overflow-y: hidden !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
ol li::before {
|
||||
content: counter(list);
|
||||
counter-increment: list;
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -48px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
background-color: colors.$color-background-brand;
|
||||
color: themes.$color-text-active;
|
||||
text-align: center;
|
||||
line-height: 25px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
// Code
|
||||
.vp-doc :not(pre, h1, h2, h3, h4, h5, h6) > code {
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-color);
|
||||
}
|
||||
|
||||
ul li:nth-last-of-type(n):after {
|
||||
content: none;
|
||||
}
|
||||
.vp-doc :not(pre) > code {
|
||||
border-radius: 4px;
|
||||
padding: 3px 6px;
|
||||
background-color: var(--vp-code-bg);
|
||||
transition:
|
||||
color 0.25s,
|
||||
background-color 0.5s;
|
||||
}
|
||||
|
||||
ol ul li::before {
|
||||
counter-increment: list;
|
||||
content: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.vp-doc a > code {
|
||||
color: var(--vp-code-link-color);
|
||||
}
|
||||
|
||||
ol li:last-child, ul li:last-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.vp-doc a:hover > code {
|
||||
color: var(--vp-code-link-hover-color);
|
||||
}
|
||||
|
||||
ol li p {
|
||||
margin-top: 0;
|
||||
}
|
||||
.vp-doc h1 > code,
|
||||
.vp-doc h2 > code,
|
||||
.vp-doc h3 > code {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 22px;
|
||||
}
|
||||
.vp-doc div[class*='language-'],
|
||||
.vp-block {
|
||||
position: relative;
|
||||
margin: 16px -24px;
|
||||
background-color: transparent;
|
||||
overflow-x: auto;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
color: #1a73e8;
|
||||
@media (min-width: 640px) {
|
||||
.vp-doc div[class*='language-'],
|
||||
.vp-block {
|
||||
border-radius: 12px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover, &:focus-visible, &:focus, &:active {
|
||||
color: #1a73e8;
|
||||
}
|
||||
@media (max-width: 639px) {
|
||||
.vp-doc li div[class*='language-'] {
|
||||
border-radius: 8px 0 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: #7e00ed;
|
||||
}
|
||||
}
|
||||
}
|
||||
.vp-doc div[class*='language-'] + div[class*='language-'],
|
||||
.vp-doc div[class$='-api'] + div[class*='language-'],
|
||||
.vp-doc div[class*='language-'] + div[class$='-api'] > div[class*='language-'] {
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] pre,
|
||||
.vp-doc [class*='language-'] code {
|
||||
/*rtl:ignore*/
|
||||
direction: ltr;
|
||||
/*rtl:ignore*/
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] pre {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
overflow-x: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code {
|
||||
display: block;
|
||||
padding: 0px;
|
||||
width: fit-content;
|
||||
min-width: 100%;
|
||||
line-height: var(--vp-code-line-height);
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-color);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted {
|
||||
background-color: var(--vp-code-line-highlight-color);
|
||||
transition: background-color 0.5s;
|
||||
margin: 0 -24px;
|
||||
padding: 0 24px;
|
||||
width: calc(100% + 2 * 24px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted.error {
|
||||
background-color: var(--vp-code-line-error-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted.warning {
|
||||
background-color: var(--vp-code-line-warning-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff {
|
||||
transition: background-color 0.5s;
|
||||
margin: 0 -24px;
|
||||
padding: 0 24px;
|
||||
width: calc(100% + 2 * 24px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff::before {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] .has-focused-lines .line:not(.has-focus) {
|
||||
filter: blur(0.095rem);
|
||||
opacity: 0.4;
|
||||
transition:
|
||||
filter 0.35s,
|
||||
opacity 0.35s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] .has-focused-lines .line:not(.has-focus) {
|
||||
opacity: 0.7;
|
||||
transition:
|
||||
filter 0.35s,
|
||||
opacity 0.35s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover .has-focused-lines .line:not(.has-focus) {
|
||||
filter: blur(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.remove {
|
||||
background-color: var(--vp-code-line-diff-remove-color);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.remove::before {
|
||||
content: '-';
|
||||
color: var(--vp-code-line-diff-remove-symbol-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.add {
|
||||
background-color: var(--vp-code-line-diff-add-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.add::before {
|
||||
content: '+';
|
||||
color: var(--vp-code-line-diff-add-symbol-color);
|
||||
}
|
||||
|
||||
.vp-doc div[class*='language-'].line-numbers-mode {
|
||||
/*rtl:ignore*/
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
.vp-doc .line-numbers-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
/*rtl:ignore*/
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
/*rtl:ignore*/
|
||||
border-right: 1px solid var(--vp-code-block-divider-color);
|
||||
padding-top: 20px;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
font-family: var(--vp-font-family-mono);
|
||||
line-height: var(--vp-code-line-height);
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-line-number-color);
|
||||
transition:
|
||||
border-color 0.5s,
|
||||
color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy {
|
||||
/*rtl:ignore*/
|
||||
direction: ltr;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
/*rtl:ignore*/
|
||||
right: 12px;
|
||||
z-index: 3;
|
||||
border: none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
background-image: var(--vp-icon-copy);
|
||||
background-position: 50%;
|
||||
background-size: 20px;
|
||||
background-repeat: no-repeat;
|
||||
transition:
|
||||
border-color 0.25s,
|
||||
background-color 0.25s,
|
||||
opacity 0.25s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover > button.copy,
|
||||
.vp-doc [class*='language-'] > button.copy:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy:hover,
|
||||
.vp-doc [class*='language-'] > button.copy.copied {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy.copied,
|
||||
.vp-doc [class*='language-'] > button.copy:hover.copied {
|
||||
/*rtl:ignore*/
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy.copied::before,
|
||||
.vp-doc [class*='language-'] > button.copy:hover.copied::before {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
/*rtl:ignore*/
|
||||
transform: translateX(calc(-100% - 1px));
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: none;
|
||||
/*rtl:ignore*/
|
||||
border-right: 0;
|
||||
padding: 0 10px;
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-code-copy-code-active-text);
|
||||
white-space: nowrap;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > span.lang {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
/*rtl:ignore*/
|
||||
right: 8px;
|
||||
z-index: 2;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-code-lang-color);
|
||||
transition:
|
||||
color 0.4s,
|
||||
opacity 0.4s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover > button.copy + span.lang,
|
||||
.vp-doc [class*='language-'] > button.copy:focus + span.lang {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// Banner
|
||||
.vp-doc .custom-block {
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p {
|
||||
margin: 8px 0;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] {
|
||||
margin: 8px 0;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] code {
|
||||
font-weight: 400;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block .vp-code-group .tabs {
|
||||
margin: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
// Table
|
||||
.vp-doc table {
|
||||
display: block;
|
||||
border-collapse: collapse;
|
||||
overflow-x: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
// width: 100%;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.vp-doc tr {
|
||||
border-top: hidden;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc tr:nth-child(2n) {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.vp-doc th,
|
||||
.vp-doc td {
|
||||
padding: 18px 16px;
|
||||
padding: 18px 16px;
|
||||
width: 100vh;
|
||||
background-color: var(--vp-c-bg);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vp-doc tbody tr {
|
||||
border-top: 1px solid $color-border;
|
||||
|
||||
&:last-child{
|
||||
border-bottom: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc th {
|
||||
@include font_style(15px, 500, 20px, 0.2px);
|
||||
color: $color-text-active;
|
||||
background-color: var(--vp-c-bg);
|
||||
border-top: 1px solid $color-border;
|
||||
}
|
||||
|
||||
.vp-doc td {
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
padding: 18px 16px;
|
||||
background-color: var(--vp-c-bg);
|
||||
border-right: hidden;
|
||||
border-left: hidden;
|
||||
color: $color-text-active;
|
||||
}
|
||||
|
||||
// Block
|
||||
.vp-doc .custom-block {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p {
|
||||
margin: 8px 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] {
|
||||
margin: 40px 0;
|
||||
border-radius: 12px;
|
||||
|
||||
&.vp-doc .custom-block {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] code {
|
||||
font-weight: 400;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block .vp-code-group .tabs {
|
||||
margin: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/navigationDrawer';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as theme;
|
||||
@use 'src/assets/scss/app/helpers/media';
|
||||
@use '@/scss/helpers/media';
|
||||
|
||||
.VPSidebar {
|
||||
--vp-sidebar-bg-color: var(--vp-c-bg);
|
||||
|
||||
+5
@@ -1,3 +1,8 @@
|
||||
@use '@beeline/design-tokens/scss/font-face';
|
||||
@use "@beeline/design-tokens/scss/iconfont/iconfont" with (
|
||||
$font-path-iconfont: '../assets/fonts/iconfont'
|
||||
);
|
||||
@use "@beeline/design-tokens/scss/iconfont/icons";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
@use "@beeline/design-tokens/scss/iconfont/iconfont" with (
|
||||
$font-path-iconfont: '/fonts/iconfont'
|
||||
);
|
||||
@use "@beeline/design-tokens/scss/iconfont/icons";
|
||||
|
||||
$font-path-beeline-sans: '/fonts/beeline-sans' !default;
|
||||
|
||||
@mixin beeline-sans-font($type, $weight, $style: normal) {
|
||||
@font-face {
|
||||
font-family: "Beeline Sans";
|
||||
src:url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.woff2') format('woff2'),
|
||||
url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.woff') format('woff'),
|
||||
url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.ttf') format('truetype');
|
||||
font-weight: $weight;
|
||||
font-style: $style;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin beeline-sans-font-pair($type, $weight) {
|
||||
@include beeline-sans-font($type, $weight);
|
||||
|
||||
}
|
||||
|
||||
@include beeline-sans-font-pair(Regular, 400);
|
||||
|
||||
@include beeline-sans-font-pair(Medium, 500);
|
||||
|
||||
@include beeline-sans-font-pair(Bold, 700);
|
||||
|
||||
@include beeline-sans-font-pair(Black, 900);
|
||||
|
||||
$font-path-roboto-mono: '/fonts/roboto-mono' !default;
|
||||
|
||||
@mixin roboto-mono-font($type, $weight, $style: normal) {
|
||||
@font-face {
|
||||
font-family: "Roboto Mono";
|
||||
src:url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.woff2') format('woff2'),
|
||||
url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.woff') format('woff'),
|
||||
url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.ttf') format('truetype');
|
||||
font-weight: $weight;
|
||||
font-style: $style;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin roboto-mono-font-pair($type, $weight) {
|
||||
@include roboto-mono-font($type, $weight);
|
||||
|
||||
}
|
||||
|
||||
@include roboto-mono-font-pair(Light, 300);
|
||||
|
||||
@include roboto-mono-font-pair(Regular, 400);
|
||||
|
||||
@include roboto-mono-font-pair(Medium, 500);
|
||||
|
||||
@include roboto-mono-font-pair(Bold, 700);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
@forward "media";
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
@use "sass:map";
|
||||
|
||||
// @deprecated
|
||||
@mixin media($minWidth, $maxWidth) {
|
||||
@media (min-width: $minWidth) and (max-width: $maxWidth) {
|
||||
@@ -27,7 +29,7 @@ $breakpoints: (
|
||||
);
|
||||
|
||||
@mixin max($breakpoint) {
|
||||
$value: map-get($breakpoints, $breakpoint);
|
||||
$value: map.get($breakpoints, $breakpoint);
|
||||
|
||||
@if $value {
|
||||
@media (max-width: $value) {
|
||||
@@ -1,4 +1,3 @@
|
||||
@use "fonts";
|
||||
@use "design-system";
|
||||
@use "design-tokens";
|
||||
@use "vars";
|
||||
@use "components";
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
:root {
|
||||
--vp-font-family-base: 'Beeline Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
--vp-font-family-mono: 'Roboto Mono', monospace;
|
||||
--vp-font-family-mono: 'JetBrains Mono', monospace;
|
||||
|
||||
// Code
|
||||
// --vp-code-font-size: ;
|
||||
@@ -183,16 +183,18 @@
|
||||
--vp-custom-block-code-font-size: 17px;
|
||||
--vp-custom-block-tip-border: transparent;
|
||||
--vp-custom-block-tip-text: var(--vp-c-text-1);
|
||||
--vp-custom-block-tip-bg: #f1f1f3;
|
||||
--vp-custom-block-tip-bg: #f9f9f9;
|
||||
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
||||
--vp-custom-block-warning-bg: #fff4e1;
|
||||
--vp-custom-block-danger-bg: #ffecef;
|
||||
--vp-custom-block-warning-bg: #e3f2ff;
|
||||
--vp-custom-block-warning-icon: #1a73e8;
|
||||
--vp-custom-block-danger-bg: #fff4e1;
|
||||
--vp-custom-block-danger-icon: #ff9419;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-custom-block-warning-bg: #3d392a;
|
||||
--vp-custom-block-warning-bg: #132338;
|
||||
--vp-custom-block-tip-bg: #36383c;
|
||||
--vp-custom-block-danger-bg: #371313;
|
||||
--vp-custom-block-danger-bg: #3d392a;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,5 +206,11 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
--vp-icon-copy: url('../../../public/icons/copy.svg');
|
||||
--vp-icon-clock: url('../../../public/icons/clock.svg');
|
||||
--vp-icon-info-circled: url('../../../public/icons/info_circled.svg');
|
||||
--vp-icon-warning-triangle: url('../../../public/icons/warning_triangle.svg');
|
||||
--vp-icon-nav-arrow-down: url('../../../public/icons/nav_arrow_down.svg');
|
||||
--vp-icon-nav-arrow-up: url('../../../public/icons/nav_arrow_up.svg');
|
||||
--vp-sidebar-width: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
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.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Назначение сервиса
|
||||
|
||||
Данный сервис предназначен для команд, которым требуется надёжный и масштабируемый конвейер данных без необходимости самостоятельно разворачивать и обслуживать инфраструктуру 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 используется как готовый сервис, не вовлекаясь в вопросы настройки и обслуживания.
|
||||
@@ -0,0 +1,244 @@
|
||||
# Подключение и работа с кластером 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 Примечание
|
||||
Операция перераспределения партиций требует времени и может создавать дополнительную нагрузку на кластер. Выполнение рекомендуется в период наименьшей активности.
|
||||
:::
|
||||
@@ -0,0 +1,64 @@
|
||||
# Рекомендации по настройке топика (тариф 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`). Если один брокер перезагрузится, запись в топик станет невозможной — система будет ждать подтверждения от всех трёх реплик, а одна недоступна.
|
||||
:::
|
||||
@@ -0,0 +1,108 @@
|
||||
# Конфигурация кластера
|
||||
|
||||
В разделе описаны технические параметры кластера 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** - рассчитывается с учетом количества партиций, объема сообщений и числа подключений продюсеров и консьюмеров;
|
||||
- **Тип и объем дискового хранилища** - определяется на основе среднего и максимального размера сообщения, частоты отправки, срока хранения и фактора репликации;
|
||||
- **Параметры репликации** - учитывают заданный фактор репликации и обеспечивают отказоустойчивость кластера.
|
||||
@@ -0,0 +1,138 @@
|
||||
# Подключение и работа с кластером 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 Примечание
|
||||
Операция перераспределения партиций требует времени и может создавать дополнительную нагрузку на кластер. Выполнение рекомендуется в период наименьшей активности.
|
||||
:::
|
||||
@@ -0,0 +1,144 @@
|
||||
# Параметры конфигурации 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-адресов.
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
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.
|
||||
@@ -0,0 +1,88 @@
|
||||
# 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;
|
||||
- администрирование баз данных через веб-интерфейс без прямого доступа к серверам кластера.
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# Описание технических параметров
|
||||
|
||||
Данный раздел содержит технические параметры кластера 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.
|
||||
|
||||
Выбор конкретного способа подключения зависит от архитектуры приложений и требований к безопасности.
|
||||
@@ -0,0 +1,88 @@
|
||||
# Общая схема подключения
|
||||
|
||||
Подключение к кластеру **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>`
|
||||
@@ -0,0 +1,104 @@
|
||||
# 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** | Метрика, показывающая объем свободного дискового пространства на файловой системе сервера. |
|
||||
@@ -0,0 +1,67 @@
|
||||
# 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. Нажмите **Сохранить**.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Возможности пользователя
|
||||
|
||||
Данный раздел описывает права, которые предоставляются пользователю 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**. Это означает, что он может просматривать состояние репликации, но не может изменять или вмешиваться в процесс репликации.
|
||||
|
||||
:::
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Cloud PostgreSQL
|
||||
link: /PaaS/PostgreSQL/PostgreSQL-index.md
|
||||
description: Обзор сервиса PostgreSQL
|
||||
- title: IPSEC
|
||||
link: /PaaS/IPSEC.md
|
||||
description: Параметры конфигурации IPSEC
|
||||
---
|
||||
|
||||
# Начало работы в Cloud PostgreSQL
|
||||
@@ -1,13 +0,0 @@
|
||||
# Матрица региональной доступности
|
||||
|
||||
Регион доступности — это один или несколько центров обработки данных (ЦОД), в которых могут быть размещены компоненты облачной инфраструктуры.
|
||||
|
||||
| Регион | Статус | Гипервизор | Процессор | HDD| SSD | NVME|
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| **ДатаФорт 1** | Доступен | OpenStack | Intel® Xeon® Gold 6248R | ✘ | ✘ | ✅ |
|
||||
|
||||
Условные обозначения:
|
||||
|
||||
✅ — есть возможность выдачи ресурсов.
|
||||
|
||||
✘ — нет возможности выдачи ресурсов.
|
||||
@@ -10,5 +10,3 @@ section_links:
|
||||
При [регистрации пользователя](../start/getting-started.md#1-регистрация-в-beeline-cloud) в Beeline Cloud создается аккаунт и проект в Beeline Cloud.
|
||||
|
||||
С помощью аккаунта можно управлять профилем пользователя - добавлять SSH-ключи, чтобы подключаться к виртуальным машинам без ввода пароля.
|
||||
|
||||
В проекте можно создавать ресурсы, добавлять пользователей в проект и управлять доступом к ресурсам.
|
||||
@@ -1,40 +0,0 @@
|
||||
# Квоты и лимиты
|
||||
|
||||
Ограничения включают в себя лимиты и квоты на потребление ресурсов в проекте.
|
||||
|
||||
Квоты ограничивают потребление ресурсов в проекте. В проекте на каждый ресурс выделяется квота, не превышающая лимит.
|
||||
|
||||
После создания проекту становятся доступны базовые квоты. Для них установлены значения по умолчанию.
|
||||
|
||||
**Базовые квоты**
|
||||
|
||||
| Название квоты | Количество |
|
||||
|---------------------|------------|
|
||||
| Количество виртуальных ВМов | 3 штуки|
|
||||
| ЦПУ | 200 |
|
||||
| ОЗУ | 200 Гбайт |
|
||||
| Хранилище NVME | 5000 Гбайт |
|
||||
| Объектное хранилище | 100 Гбайт |
|
||||
|
||||
## Просмотр квот проекта
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Обзор**.
|
||||
|
||||
## Редактирование квот проекта
|
||||
|
||||
::: tip Информация
|
||||
Изменить квоты проекта может пользователь с ролью **Владелец проекта**.
|
||||
:::
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Обзор**.
|
||||
6. В правом верхнем углу нажмите **Изменить квоты**.
|
||||
7. Увеличите или уменьшите квоты для ресурсов.
|
||||
8. Нажмите **Сохранить**.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Управление проектами
|
||||
|
||||
Проект — это структурная единица публичного облака, в которой содержатся ресурсы: виртуальные машины, хранилища, IP-адреса и др.
|
||||
|
||||
Ресурсы могут быть вычислительными и аппаратными.
|
||||
|
||||
Вычислительные ресурсы:
|
||||
- оперативная память (ОЗУ);
|
||||
- ядра процессора (ЦПУ);
|
||||
- локальные диски;
|
||||
- сетевые диски;
|
||||
- IP-адреса.
|
||||
|
||||
Аппаратные ресурсы (ВМы, сети, диски) размещены в центрах обработки данных (ЦОД). Каждый дата-центр разделен на модули. Модули оснащены независимыми системами электропитания и охлаждения.
|
||||
|
||||
При получении доступа в публичное облако текущий пользователь становится менеджера проектов. Менеджер проектов может создавать новые проекты, в которых он получает роль владельца проекта. Владелец проекта может добавлять пользователей в проект, назначая им роли.
|
||||
|
||||
Доступ к проекту осуществляется из консоли управления.
|
||||
|
||||
## Создать проект
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Нажмите кнопку **Создать → Проект** в правом верхнем углу.
|
||||
3. Заполните информацию о проекте:
|
||||
- **Название**: введите наименование проекта.
|
||||
- **Идентификатор**: введите идентификатор проекта:
|
||||
- допустимы строчные и прописные буквы латинского алфавита, цифры и дефис;
|
||||
- длина не более 64 символов;
|
||||
- не должно начинаться или заканчиваться дефисом.
|
||||
- **Описание**: введите краткое описание проекта.
|
||||
4. Нажмите **Создать**.
|
||||
|
||||
## Изменить имя проекта
|
||||
|
||||
::: tip Информация
|
||||
Изменить имя и описание проекта может только пользователь с ролью **Владелец проекта**.
|
||||
:::
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Настройки → Основное**.
|
||||
6. Измените имя, описание проекта.
|
||||
7. Нажмите **Сохранить**.
|
||||
|
||||
## Удаление проекта
|
||||
|
||||
Функциональность не предусмотрена в публичном облаке.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Ролевая модель
|
||||
|
||||
Управление проектом основано на ролевой модели.
|
||||
|
||||
**Базовые роли**
|
||||
|
||||
В проекте предусмотрен базовый набор ролей:
|
||||
|
||||
- **Владелец продукта** — управление пользователями проекта, просмотр ресурсов.
|
||||
- **DevOps-инженер** — управление инфраструктурой, стандартное администрирование ОС UNIX по протоколу ssh и права управления виртуальными ВМами и дисками в консоли управления.
|
||||
|
||||
## Матрица ролей
|
||||
|
||||
| Действие | Владелец проекта | DevOps-инженер |
|
||||
|---|---|---|
|
||||
| Обзор проекта<br> (квоты и количество использованных ресурсов)| ✅ | ✅ |
|
||||
| ВМы: обзор | ✅ | ✅ |
|
||||
| ВМы: мониторинг | ✅ | ✅ |
|
||||
| ВМы: создать ВМ |✘ | ✅ |
|
||||
| ВМы: подключить диск | ✘ | ✅ |
|
||||
| ВМы: отключить диск | ✘ | ✅ |
|
||||
| ВМы: добавить диск | ✘ | ✅ |
|
||||
| ВМы: теги | ✘ |✅ |
|
||||
| ВМы: масштабирование ВМа | ✘ | ✅ |
|
||||
| ВМы: выключить ВМ | ✘ | ✅ |
|
||||
| ВМы: включить ВМ | ✘ | ✅ |
|
||||
| ВМы: перезагрузить ВМ | ✘ | ✅ |
|
||||
| ВМы: принудительно перезагрузить ВМ | ✘ | ✅ |
|
||||
| ВМы: удалить ВМ | ✘ | ✅ |
|
||||
| ВМы: группы размещения | ✘ | ✅ |
|
||||
| ВМы: IP-адреса | ✘ | ✅ |
|
||||
| Диски: просмотр дисков | ✅ | ✅ |
|
||||
| Диски: добавление дискового пространства | ✘ | ✅ |
|
||||
| Диски: удалить диск| ✘ | ✅ |
|
||||
| Объектное хранилище: просмотр| ✅ | ✅ |
|
||||
| Объектное хранилище: добавить хранилище | ✘ | ✅ |
|
||||
| Объектное хранилище: удалить хранилище | ✘ | ✅|
|
||||
| DNS: добавить зону | ✘ | ✅ |
|
||||
| DNS: редактировать зону | ✘ | ✅ |
|
||||
| DNS: удалить зону |✘ | ✅ |
|
||||
| Настройки проекта: просмотр| ✅ | ✅ |
|
||||
| Настройки проекта: изменить описание проекта |✅ | ✘ |
|
||||
| Участники: просмотр | ✅ | ✅ |
|
||||
| Участники: добавить участника | ✅ | ✘ |
|
||||
| Участники: удалить участника | ✅ | ✘ |
|
||||
| Участники: назначить роль | ✅| ✘ |
|
||||
| Квоты: просмотр | ✅ | ✅ |
|
||||
| Веб-обработчики | ✘ | ✅ |
|
||||
| Наблюдаемость | ✅ | ✅ |
|
||||
+4
-4
@@ -10,7 +10,7 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Добавить SSH-ключ
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Нажмите **Добавить ключ**.
|
||||
@@ -31,14 +31,14 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Посмотреть SSH-ключи
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. В таблице показаны SSH-ключи пользователя.
|
||||
|
||||
## Изменить название SSH-ключа
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Выберите нужный ключ.
|
||||
@@ -48,7 +48,7 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Удалить SSH-ключ
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Выберите нужный ключ.
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# Управление пользователями в проекте
|
||||
|
||||
В консоли управления можно добавлять пользователей, управлять ролями пользователей в проекте. Один пользователей может участвовать в нескольких проектах и иметь в них разные роли.
|
||||
|
||||
::: tip Информация
|
||||
Добавлять и удалять пользователей, изменять права пользователей в проекте может только владелец проекта.
|
||||
:::
|
||||
|
||||
## Добавить пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Нажмите **Добавить пользователя**.
|
||||
4. Найдите пользователя по ФИО или email.
|
||||
5. Назначьте [роль](../admin/roles.md) пользователю.
|
||||
6. Нажмите **Добавить**.
|
||||
|
||||
## Назначить права пользователю
|
||||
|
||||
Каждому пользователю проекта должна быть выдана хотя бы одна роль. У пользователя может быть несколько ролей в одном проекте.
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Редактировать**.
|
||||
5. Назначьте [роль](../admin/roles.md) пользователю: установите флажок напротив роли.
|
||||
6. Нажмите **Сохранить**.
|
||||
|
||||
Права на существующие ОС применятся в течение 10 минут.
|
||||
|
||||
## Отозвать права у пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Редактировать**.
|
||||
5. Отзовите роль у пользователя: уберите флажок напротив роли. Оставьте пользователю хотя бы одну роль в проекте.
|
||||
6. Нажмите кнопку **Сохранить**.
|
||||
|
||||
## Удалить пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Удалить**.
|
||||
|
||||
Пользователь будет удален из списка участников проекта. Ресурсы проекта станут недоступны пользователю.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,38 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
|
||||
:root {
|
||||
--app-navbar-height: #{$app-navbar-height};
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html.dark-theme {
|
||||
background-color: $color-background-base;
|
||||
color: $color-text-active;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: $color-text-active !important;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@import 'variables';
|
||||
@import 'base';
|
||||
@import 'form';
|
||||
@import 'helpers';
|
||||
@import 'components';
|
||||
@@ -1,3 +0,0 @@
|
||||
// Navbar
|
||||
$app-navbar-height: 3.5rem;
|
||||
$app-header-height: 64px;
|
||||
@@ -1,122 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/fab' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/button' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/globals' as *;
|
||||
@use '@beeline/design-tokens/scss/mixin';
|
||||
|
||||
@mixin fab_button {
|
||||
background-color: $button-overlay-background-color;
|
||||
padding-left: $button-only-text-small-padding-horizontal;
|
||||
padding-right: $button-only-text-small-padding-horizontal;
|
||||
letter-spacing: $button-small-text-font-letter-spacing;
|
||||
line-height: $button-small-text-font-line-height;
|
||||
font-size: $button-small-text-font-size;
|
||||
height: $button-small-height;
|
||||
color: $button-overlay-text-color;
|
||||
box-shadow: none;
|
||||
border: 1px solid $button-outline-border-color;
|
||||
border-radius: $button-border-radius;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: $button-overlay-background-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab {
|
||||
height: $fab-standard-height;
|
||||
width: $fab-standard-width;
|
||||
position: fixed;
|
||||
z-index: 50;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border: 0;
|
||||
padding: $fab-standard-padding;
|
||||
letter-spacing: $fab-text-font-letter-spacing;
|
||||
line-height: $fab-text-font-line-height;
|
||||
font-size: $fab-text-font-size;
|
||||
font-weight: $fab-text-font-weight;
|
||||
box-shadow: $fab-shadow;
|
||||
background-color: $color-background-inverse;
|
||||
color: $color-text-active-inverse;
|
||||
cursor: pointer;
|
||||
|
||||
&__icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
// background-color: $fab-hover-background-color;
|
||||
}
|
||||
|
||||
&--focused {
|
||||
border-color: $fab-focused-border-color;
|
||||
border-width: $fab-focused-border-width;
|
||||
}
|
||||
|
||||
&--mini {
|
||||
height: $fab-mini-height;
|
||||
width: $fab-mini-width;
|
||||
border-radius: $fab-mini-border-radius;
|
||||
padding: $fab-mini-padding;
|
||||
}
|
||||
|
||||
&--extended {
|
||||
height: $fab-extended-height;
|
||||
border-radius: $fab-extended-border-radius;
|
||||
padding-right: $fab-extended-padding-right;
|
||||
padding-left: $fab-extended-padding-left;
|
||||
|
||||
& &__icon {
|
||||
margin-right: $fab-extended-icon-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab--extended.app-fab--mini {
|
||||
height: $fab-mini-height;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: $fab-disabled-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab-dialog {
|
||||
position: fixed;
|
||||
bottom: 44px;
|
||||
right: 0;
|
||||
// background-color: $color-background-medium;
|
||||
background-color: transparent;
|
||||
// border-radius: 12px;
|
||||
padding: 1rem;
|
||||
// border: 1px solid $color-border;
|
||||
// min-width: 300px;
|
||||
// box-shadow: $elevation-medium;
|
||||
|
||||
.icon-contained {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: $color-status-neutral-background;
|
||||
color: $color-status-neutral;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
#feedback_button {
|
||||
@include fab_button();
|
||||
}
|
||||
|
||||
#bug_button {
|
||||
@include fab_button();
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
a#bug_button,
|
||||
a#bug_button:visited,
|
||||
a#bug_button:active {
|
||||
color: $button-overlay-text-color !important;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import 'fab';
|
||||
@@ -1 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/formfield' as formfield;
|
||||
@@ -1,104 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/textarea' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/formfield';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
.textarea-field {
|
||||
$px: 16px;
|
||||
|
||||
display: block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: $textarea-without-label-medium-text-margin-top $px $textarea-text-margin-bottom;
|
||||
height: $textarea-without-label-medium-height;
|
||||
background: formfield.$formfield-background-color;
|
||||
border: formfield.$formfield-border-width formfield.$formfield-border-style formfield.$formfield-border-color;
|
||||
border-radius: formfield.$formfield-border-radius;
|
||||
|
||||
& &__label {
|
||||
position: absolute;
|
||||
top: $textarea-with-label-text-margin-top;
|
||||
left: $px;
|
||||
transition: font-size 300ms ease-out;
|
||||
color: formfield.$formfield-label-color;
|
||||
}
|
||||
|
||||
& textarea {
|
||||
height: $textarea-medium-text-height;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
resize: none;
|
||||
background-color: transparent;
|
||||
color: themes.$color-text-active;
|
||||
}
|
||||
|
||||
& &__resizer {
|
||||
position: absolute;
|
||||
bottom: $textarea-resizer-margin-bottom;
|
||||
right: $textarea-resizer-margin-right;
|
||||
rotate: -45deg;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
&:hover {
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: flex;
|
||||
background-color: darkslategrey;
|
||||
width: 10px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: flex;
|
||||
position: relative;
|
||||
right: -3px;
|
||||
bottom: -2px;
|
||||
background-color: darkslategrey;
|
||||
width: 4px;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.textarea-field--with-label {
|
||||
height: $textarea-with-label-medium-height;
|
||||
padding-top: $textarea-with-label-text-margin-top;
|
||||
|
||||
&.textarea-field--floated .textarea-field__label {
|
||||
top: $textarea-medium-label-floated-margin-top;
|
||||
line-height: $textarea-small-label-floated-font-line-height;
|
||||
font-size: $textarea-small-label-floated-font-size;
|
||||
}
|
||||
|
||||
&.textarea-field--small {
|
||||
height: $textarea-with-label-small-height;
|
||||
padding-top: $textarea-small-label-margin-top;
|
||||
top: $textarea-small-label-floated-margin-top;
|
||||
|
||||
& .textarea-field__label {
|
||||
font-size: $textarea-small-label-font-size;
|
||||
font-weight: $textarea-small-label-font-weight;
|
||||
letter-spacing: $textarea-small-label-font-letter-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.textarea-field--focused {
|
||||
border-color: formfield.$formfield-border-color-focus;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&.textarea-field--small {
|
||||
padding-top: $textarea-without-label-small-text-margin-top;
|
||||
height: $textarea-without-label-small-height;
|
||||
|
||||
& textarea {
|
||||
height: $textarea-small-text-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/textfield' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/globals';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as theme;
|
||||
|
||||
.textfield {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: globals.$size-control-height-medium;
|
||||
border: globals.$size-border-width-regular solid transparent;
|
||||
padding-top: $textfield-without-label-medium-text-margin-vertical;
|
||||
padding-bottom: $textfield-without-label-medium-text-margin-vertical;
|
||||
background-color: theme.$color-control-background;
|
||||
border-radius: 12px; // globals.$size-border-radius-x6;
|
||||
|
||||
&:hover {
|
||||
background-color: theme.$color-control-background-hover;
|
||||
}
|
||||
|
||||
// input
|
||||
input {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
// label
|
||||
&--with-label {
|
||||
// padding-top: $textfield-with-label-medium-text-margin-top;
|
||||
// padding-bottom: $textfield-with-label-medium-text-margin-bottom;
|
||||
}
|
||||
|
||||
&__label {
|
||||
// padding-top: $textfield-medium-label-margin-top;
|
||||
|
||||
&.textfield__label--floated {
|
||||
// padding-top: $textfield-medium-label-margin-top-floated;
|
||||
}
|
||||
}
|
||||
|
||||
// small
|
||||
&--small {
|
||||
height: globals.$size-control-height-small;
|
||||
}
|
||||
|
||||
// large
|
||||
&--large {
|
||||
height: globals.$size-control-height-large;
|
||||
padding-top: $textfield-without-label-large-text-margin-vertical;
|
||||
padding-bottom: $textfield-without-label-large-text-margin-vertical;
|
||||
|
||||
&.textfield--with-label {
|
||||
padding-top: $textfield-with-label-large-text-margin-top;
|
||||
padding-bottom: $textfield-with-label-large-text-margin-bottom;
|
||||
}
|
||||
|
||||
.textfield__label {
|
||||
padding-top: $textfield-large-label-margin-top;
|
||||
|
||||
&.textfield__label--floated {
|
||||
padding-top: $textfield-large-label-margin-top-floated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// states
|
||||
&--focused {
|
||||
border-color: theme.$color-border-focus;
|
||||
background-color: theme.$color-background-base;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
|
||||
.app-bg-status-error {
|
||||
background-color: $color-status-error-background;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.app-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@import 'text';
|
||||
@import 'color';
|
||||
@import 'media';
|
||||
@import 'common';
|
||||
@@ -1,80 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as theme;
|
||||
@use 'src/assets/scss/app/mixins' as mixins;
|
||||
|
||||
@mixin truncate {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@mixin truncate-lines($lines: 2) {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $lines;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.app-text-active {
|
||||
color: theme.$color-text-active;
|
||||
}
|
||||
|
||||
.app-text-inactive {
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
|
||||
// styles for hyperlinks
|
||||
.app-link {
|
||||
color: theme.$color-text-active;
|
||||
|
||||
&:hover {
|
||||
color: theme.$color-text-active;
|
||||
}
|
||||
}
|
||||
|
||||
.app-text-caption {
|
||||
@include mixins.text-caption;
|
||||
}
|
||||
|
||||
.app-text-truncate {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// Sizes
|
||||
.app-text-size-subtitle-3 {
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.app-text-size-body-3 {
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
letter-spacing: 0.2px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
// Colors
|
||||
.app-text-color-caption {
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
.app-text-warning {
|
||||
color: theme.$color-status-warning;
|
||||
}
|
||||
.app-text-info {
|
||||
color: theme.$color-status-info;
|
||||
}
|
||||
.app-text-error {
|
||||
color: theme.$color-status-error;
|
||||
}
|
||||
.app-text-success {
|
||||
color: theme.$color-status-success;
|
||||
}
|
||||
|
||||
// Breaks
|
||||
.app-break-keep-all {
|
||||
word-break: keep-all;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import 'spinner';
|
||||
@@ -1,6 +0,0 @@
|
||||
@use 'src/assets/scss/app/variables' as v;
|
||||
|
||||
.app-loading-screen {
|
||||
display: block;
|
||||
height: calc(100vh - v.$app-header-height);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@forward 'text';
|
||||
@@ -1,29 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as theme;
|
||||
|
||||
%text_caption {
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
@mixin text_caption {
|
||||
@extend %text_caption;
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
|
||||
@mixin text_caption_error {
|
||||
@extend %text_caption;
|
||||
color: theme.$color-status-error;
|
||||
}
|
||||
|
||||
@mixin text_body_2 {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
@mixin truncate {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
|
||||
:root {
|
||||
@include themes.theme();
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
@include themes.theme(dark.$theme);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/font-face' with (
|
||||
$font-path-beeline-sans: '../fonts/beeline-sans'
|
||||
);
|
||||
@@ -1,40 +0,0 @@
|
||||
// @use "@beeline/design-tokens/scss/iconfont/iconfont" with (
|
||||
// $font-path-iconfont: '../fonts/iconfont'
|
||||
// );
|
||||
@use '@beeline/design-tokens/scss/iconfont/icons';
|
||||
|
||||
@font-face {
|
||||
font-display: block;
|
||||
font-family: 'BeelineIcons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src:
|
||||
url('../fonts/iconfont/BeelineIcons.woff2') format('woff2'),
|
||||
url('../fonts/iconfont/BeelineIcons.woff') format('woff'),
|
||||
url('../fonts/iconfont/BeelineIcons.ttf') format('ttf');
|
||||
}
|
||||
|
||||
.beeline-icons {
|
||||
font-family: 'BeelineIcons', sans-serif;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px; /* Preferred icon size */
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
|
||||
/* Support for all WebKit browsers. */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
/* Support for Safari and Chrome. */
|
||||
text-rendering: optimizeLegibility;
|
||||
|
||||
/* Support for Firefox. */
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Support for IE. */
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@import 'fonts';
|
||||
@import 'icons';
|
||||
@import 'base';
|
||||
@import 'scrollbar';
|
||||
@@ -1,29 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
html {
|
||||
scrollbar-color: themes.$color-text-inactive transparent;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: themes.$color-text-inactive;
|
||||
border: 4px solid transparent;
|
||||
background-clip: content-box;
|
||||
border-radius: 100px;
|
||||
min-height: 28px;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
@use 'sass:map';
|
||||
@use '@beeline/design-tokens/scss/tokens/globals';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/light';
|
||||
@use '@beeline/design-tokens/scss/tokens/components/button';
|
||||
|
||||
// Colors
|
||||
$primary: globals.$color-background-brand;
|
||||
$background: map.get(light.$theme, 'color-background-base');
|
||||
$info: map.get(light.$theme, 'color-status-info');
|
||||
$success: map.get(light.$theme, 'color-status-success');
|
||||
$warning: map.get(light.$theme, 'color-status-warning');
|
||||
$danger: map.get(light.$theme, 'color-status-error');
|
||||
|
||||
// Typography
|
||||
$family-primary: globals.$font-family-text;
|
||||
$title-color: map.get(light.$theme, 'color-text-active');
|
||||
$subtitle-color: map.get(light.$theme, 'color-text-inactive');
|
||||
|
||||
// Radius
|
||||
$radius: globals.$size-border-radius-x6;
|
||||
|
||||
// Buttons
|
||||
$button-padding-vertical: globals.$size-spacing-x4;
|
||||
$button-padding-horizontal: globals.$size-spacing-x5;
|
||||
$button-background-color: button.$button-plain-background-color;
|
||||
$button-focus-border-color: map.get(light.$theme, 'color-background-base-focused');
|
||||
$button-disabled-opacity: button.$button-opacity-disabled;
|
||||
|
||||
// Box
|
||||
$box-radius: $radius;
|
||||
$box-shadow: globals.$elevation-low;
|
||||
$box-padding: globals.$size-spacing-x6;
|
||||
$box-link-hover-shadow: globals.$elevation-medium;
|
||||
$box-link-active-shadow: globals.$elevation-medium;
|
||||
|
||||
// Form
|
||||
$input-color: map.get(light.$theme, 'color-text-active');
|
||||
$input-background-color: map.get(light.$theme, 'color-control-background');
|
||||
$label-color: map.get(light.$theme, 'color-text-inactive');
|
||||
$label-weight: globals.$font-weight-caption;
|
||||
|
||||
// Table
|
||||
$table-color: map.get(light.$theme, 'color-text-active');
|
||||
$table-background-color: map.get(light.$theme, 'color-background-base');
|
||||
$table-cell-border: 1px solid map.get(light.$theme, 'color-control-background');
|
||||
$table-cell-padding: 16px 16px;
|
||||
$table-cell-heading-color: map.get(light.$theme, 'color-text-active');
|
||||
$table-head-cell-border-width: 1px;
|
||||
|
||||
@import 'bulma/bulma';
|
||||
@import 'overrides';
|
||||
@@ -1,12 +0,0 @@
|
||||
@use 'sass:map';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
|
||||
.box {
|
||||
.dark-theme & {
|
||||
background-color: map.get(dark.$theme, 'color-background-low');
|
||||
|
||||
&:hover {
|
||||
background-color: map.get(dark.$theme, 'color-background-medium');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/button' as button;
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
.button {
|
||||
font-weight: button.$button-medium-text-font-weight;
|
||||
color: themes.$color-text-active;
|
||||
|
||||
&:hover {
|
||||
color: themes.$color-text-active;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
.dropdown {
|
||||
&-content {
|
||||
background-color: themes.$color-background-medium;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
color: themes.$color-text-active;
|
||||
|
||||
&:hover {
|
||||
background-color: themes.$color-background-base-hover;
|
||||
color: themes.$color-text-active;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
@import 'button';
|
||||
@import 'title';
|
||||
@import 'box';
|
||||
@import 'form';
|
||||
@import 'table';
|
||||
@import 'dropdown';
|
||||
@import 'text';
|
||||
@@ -1,42 +0,0 @@
|
||||
@use 'sass:map';
|
||||
@use '@beeline/design-tokens/scss/tokens/globals';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/light';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
@use '@beeline/design-tokens/scss/tokens/components/button';
|
||||
|
||||
.table {
|
||||
.dark-theme & {
|
||||
color: map.get(dark.$theme, 'color-text-active');
|
||||
background-color: map.get(dark.$theme, 'color-background-base');
|
||||
|
||||
td,
|
||||
th {
|
||||
border: 1px solid map.get(dark.$theme, 'color-control-background');
|
||||
}
|
||||
|
||||
th {
|
||||
color: map.get(dark.$theme, 'color-text-active');
|
||||
}
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: globals.$font-weight-medium;
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
&:last-child {
|
||||
td,
|
||||
th {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
|
||||
code {
|
||||
background-color: $color-background-base;
|
||||
}
|
||||
|
||||
pre {
|
||||
color: $color-text-active;
|
||||
background-color: $color-background-base;
|
||||
}
|
||||
|
||||
.help {
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/mixin' as bee;
|
||||
|
||||
.title {
|
||||
@include bee.h3();
|
||||
|
||||
&.is-1 {
|
||||
@include bee.h1();
|
||||
}
|
||||
&.is-2 {
|
||||
@include bee.h2();
|
||||
}
|
||||
&.is-3 {
|
||||
@include bee.h3();
|
||||
}
|
||||
&.is-4 {
|
||||
@include bee.h4();
|
||||
}
|
||||
&.is-5 {
|
||||
@include bee.h5();
|
||||
}
|
||||
&.is-6 {
|
||||
@include bee.h6();
|
||||
}
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
@include bee.subtitle2();
|
||||
|
||||
&.is-1 {
|
||||
@include bee.subtitle1();
|
||||
}
|
||||
&.is-2 {
|
||||
@include bee.subtitle2();
|
||||
}
|
||||
&.is-3 {
|
||||
@include bee.subtitle3();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@import 'shared';
|
||||
@import 'select';
|
||||
@import 'input-textarea';
|
||||
@import 'title';
|
||||
@@ -1,46 +0,0 @@
|
||||
@use 'sass:map';
|
||||
// @use "@beeline/design-tokens/scss/tokens/globals";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/light';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
|
||||
%input-textarea {
|
||||
box-shadow: none;
|
||||
border: 1px solid transparent;
|
||||
color: map.get(light.$theme, 'color-text-active');
|
||||
background: map.get(light.$theme, 'color-control-background');
|
||||
|
||||
&:hover {
|
||||
border-color: map.get(light.$theme, 'color-border-focus');
|
||||
}
|
||||
|
||||
.dark-theme & {
|
||||
color: map.get(dark.$theme, 'color-text-active');
|
||||
background: map.get(dark.$theme, 'color-control-background');
|
||||
|
||||
&:hover {
|
||||
border-color: map.get(dark.$theme, 'color-border-focus');
|
||||
}
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&.is-focused,
|
||||
&:active,
|
||||
&.is-active {
|
||||
box-shadow: none !important;
|
||||
border-color: map.get(light.$theme, 'color-border-focus');
|
||||
background: map.get(light.$theme, 'color-background-base');
|
||||
|
||||
.dark-theme & {
|
||||
background: map.get(dark.$theme, 'color-background-base');
|
||||
border-color: map.get(dark.$theme, 'color-border-focus');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
@extend %input-textarea;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
@extend %input-textarea;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
@use 'sass:map';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/light';
|
||||
|
||||
.select {
|
||||
select {
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
border: 1px solid map.get(light.$theme, 'color-border-focus');
|
||||
background-color: map.get(light.$theme, 'color-background-base');
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.is-multiple):not(.is-loading)::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&.is-focused,
|
||||
&:active,
|
||||
&.is-active {
|
||||
select {
|
||||
border: 1px solid map.get(light.$theme, 'color-border-focus');
|
||||
background-color: map.get(light.$theme, 'color-background-base');
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.dark-theme & {
|
||||
select {
|
||||
border: 1px solid map.get(dark.$theme, 'color-border-focus');
|
||||
background-color: map.get(dark.$theme, 'color-background-base');
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dark-theme & {
|
||||
color: map.get(dark.$theme, 'color-text-active');
|
||||
|
||||
& select {
|
||||
color: map.get(dark.$theme, 'color-text-active');
|
||||
background-color: map.get(dark.$theme, 'color-control-background');
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user