my_postresql
6 subscribers
3 photos
3 videos
12 files
111 links
Download Telegram
В Proxmox VE (Virtual Environment) можно настроить ограничение на количество одновременных подключений к веб-интерфейсу для повышения безопасности и предотвращения перегрузки сервера. Это особенно полезно в высоконагруженных системах или для защиты от атак типа "отказ в обслуживании" (DoS).

Proxmox использует веб-сервер pveproxy для обработки запросов к веб-интерфейсу. Настройки ограничения подключений можно изменить через конфигурационные файлы.

---

### 1. Настройка ограничения подключений в Proxmox

#### Шаг 1: Изменение конфигурации `pveproxy`
Конфигурация pveproxy находится в файле /etc/default/pveproxy. В этом файле можно задать параметры, которые ограничивают количество одновременных подключений.

1. Откройте файл для редактирования:
   nano /etc/default/pveproxy


2. Найдите или добавьте параметр PVEPROXY_MAXCONNECTIONS. Этот параметр определяет максимальное количество одновременных подключений. Например:
   PVEPROXY_MAXCONNECTIONS=50


3. Сохраните изменения и закройте редактор.

#### Шаг 2: Перезапуск службы `pveproxy`
После изменения конфигурации необходимо перезапустить службу pveproxy:
systemctl restart pveproxy


---

### 2. Дополнительные настройки для повышения безопасности

#### Ограничение по IP
Если вы хотите ограничить доступ к веб-интерфейсу Proxmox по IP-адресам, можно использовать файрволл (например, iptables или nftables).

Пример с использованием iptables:
# Разрешить доступ только с определенного IP
iptables -A INPUT -p tcp --dport 8006 -s 192.168.1.100 -j ACCEPT
iptables -A INPUT -p tcp --dport 8006 -j DROP


#### Использование обратного прокси
Для дополнительной защиты и балансировки нагрузки можно настроить обратный прокси (например, Nginx или Apache) перед Proxmox. Это позволит:
- Ограничить количество подключений.
- Включить SSL/TLS.
- Использовать дополнительные механизмы защиты.

Пример конфигурации Nginx:
server {
listen 80;
server_name proxmox.example.com;

location / {
proxy_pass https://localhost:8006;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}


---

### 3. Мониторинг подключений
Для мониторинга текущих подключений к веб-интерфейсу Proxmox можно использовать команду:
pvesh get /nodes/localhost/status

Или проверить количество активных соединений через ss или netstat:
ss -tnp | grep pveproxy


---

### 4. Рекомендации
- Убедитесь, что значение PVEPROXY_MAXCONNECTIONS соответствует вашим потребностям и ресурсам сервера.
- Используйте брандмауэр для ограничения доступа к порту 8006 (веб-интерфейс Proxmox).
- Регулярно обновляйте Proxmox для получения последних исправлений безопасности.

Если у вас есть дополнительные вопросы или требуется помощь с конкретной настройкой, уточните, пожалуйста!
pg_stat_statements
pg_stat_kcache
auto_explain
pg_wait_sampling
plprofiler
### pg_stat_statements
- Что это: Расширение для сбора статистики по выполненным SQL-запросам.
- Зачем: Анализ производительности запросов (время выполнения, количество вызовов, использование ресурсов).
- Пример: Поиск самых медленных или частых запросов.

### pg_stat_kcache
- Что это: Расширение для сбора данных об использовании CPU и оперативной памяти запросами.
- Зачем: Оценка нагрузки на CPU и память для оптимизации.
- Пример: Анализ запросов, потребляющих больше всего CPU.

### auto_explain
- Что это: Модуль для автоматического логирования планов выполнения запросов.
- Зачем: Понимание, как PostgreSQL выполняет запросы (индексы, соединения и т.д.).
- Пример: Логирование планов для запросов, выполняющихся дольше определённого времени.

### pg_wait_sampling
- Что это: Расширение для сбора статистики о времени ожидания (wait events) в PostgreSQL.
- Зачем: Анализ узких мест, связанных с ожиданием (I/O, блокировки и т.д.).
- Пример: Определение, на что тратится больше всего времени (например, ожидание диска).

### plprofiler
- Что это: Инструмент для профилирования хранимых процедур и функций на PL/pgSQL.
- Зачем: Поиск узких мест в логике хранимых процедур.
- Пример: Анализ времени выполнения отдельных частей функции.

Итог: Каждый инструмент решает свою задачу — от анализа запросов до профилирования хранимых процедур и анализа ожиданий.
Вот краткое описание каждого из перечисленных инструментов для мониторинга и профилирования в PostgreSQL:

### 1. pg_stat_statements

Описание: Встроенный модуль, собирающий статистику выполнения SQL-запросов. Позволяет отслеживать время выполнения, количество выполнений, объем возвращаемых данных и другие метрики для каждой группы похожих запросов.

Применение: Используется для выявления медленных или часто выполняемых запросов, что помогает в оптимизации производительности базы данных.

### 2. pg_stat_kcache

Описание: Модуль, предоставляющий статистику использования кеша ядра операционной системы (OS). Помогает понять, насколько эффективно PostgreSQL использует кеширование на уровне ОС.

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

### 3. auto_explain

Описание: Расширение, позволяющее автоматически собирать планы выполнения для медленных запросов. Запросы, превышающие определенный порог времени, будут логироваться вместе с планом выполнения.

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

### 4. pg_wait_sampling

Описание: Инструмент для мониторинга ожиданий (waits) в PostgreSQL. Собирает данные о том, какие процессы ожидают завершения операций (например, блокировок, ввода-вывода).

Применение: Помогает диагностировать причины задержек в работе базы данных, вызванные ожиданиями ресурсов.

### 5. plprofiler

Описание: Профайлер для процедурных языков PL/pgSQL, позволяющий измерять время выполнения отдельных частей кода внутри функций.

Применение: Используется для детального анализа производительности пользовательских функций, написанных на PL/pgSQL.

Эти инструменты помогают администраторам баз данных и разработчикам лучше понимать поведение и производительность своих систем, что способствует улучшению общей эффективности приложений.
pgpro_stats — это инструмент для сбора и анализа статистики в PostgreSQL Pro (коммерческая версия PostgreSQL от компании Postgres Pro). Этот инструмент предоставляет расширенные возможности мониторинга и анализа производительности базы данных, что особенно полезно для высоконагруженных систем.

---

### Основные возможности `pgpro_stats`
1. Сбор статистики:
- Информация о выполнении запросов.
- Статистика использования индексов.
- Данные о блокировках и ожиданиях.

2. Анализ производительности:
- Выявление медленных запросов.
- Анализ использования ресурсов (CPU, память, диск).

3. Визуализация данных:
- Интеграция с инструментами визуализации, такими как Grafana.

4. Расширенные метрики:
- Подробная информация о работе планировщика, ввода-вывода и других компонентов СУБД.

---

### Установка и настройка `pgpro_stats`

#### 1. Установка
pgpro_stats поставляется в составе Postgres Pro Enterprise. Убедитесь, что у вас установлена соответствующая версия PostgreSQL Pro.

1. Установите Postgres Pro:
   sudo apt-get install postgrespro-enterprise


2. Убедитесь, что модуль pgpro_stats доступен:
   pg_config --sharedir

Проверьте наличие файлов pgpro_stats в каталоге расширений.

3. Подключите расширение в базе данных:
   CREATE EXTENSION pgpro_stats;


---

#### 2. Настройка
После установки расширения необходимо настроить сбор статистики.

1. Включите сбор статистики в postgresql.conf:
   shared_preload_libraries = 'pgpro_stats'
pgpro_stats.track = all


2. Перезапустите PostgreSQL для применения изменений:
   sudo systemctl restart postgresql


3. Настройте параметры сбора статистики:
   ALTER SYSTEM SET pgpro_stats.track_activities = 'on';
ALTER SYSTEM SET pgpro_stats.track_counts = 'on';
ALTER SYSTEM SET pgpro_stats.track_io_timing = 'on';


4. Примените изменения:
   SELECT pg_reload_conf();


---

### Использование `pgpro_stats`

#### 1. Просмотр статистики
pgpro_stats предоставляет несколько представлений для анализа данных:

- `pg_stat_activity`: Активные запросы и их состояние.
- `pg_stat_user_tables`: Статистика по таблицам.
- `pg_stat_user_indexes`: Статистика по индексам.
- `pg_stat_io`: Статистика ввода-вывода.

Пример запроса для просмотра активных запросов:
SELECT * FROM pg_stat_activity;


#### 2. Анализ медленных запросов
Используйте представление pg_stat_statements для анализа медленных запросов:
SELECT query, calls, total_time, rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;


#### 3. Мониторинг блокировок
Для анализа блокировок используйте:
SELECT * FROM pg_locks;


---

### Интеграция с Grafana
Для визуализации данных, собранных pgpro_stats, можно использовать Grafana.

1. Установите Grafana и PostgreSQL Data Source.
2. Настройте подключение к базе данных.
3. Создайте дашборды для отображения ключевых метрик, таких как:
- Количество запросов в секунду.
- Время выполнения запросов.
- Использование дискового ввода-вывода.

---

### Рекомендации
- Регулярно анализируйте статистику для выявления узких мест.
- Настройте автоматический сбор и очистку данных.
- Используйте расширенные возможности pgpro_stats для глубокого анализа производительности.

---

Если у вас есть дополнительные вопросы или требуется помощь с конкретной настройкой, уточните, пожалуйста!
На основе предоставленного содержания файла pgpro.pdf и перечисленных модулей, давайте рассмотрим каждый из них более подробно, включая возможные учебные материалы и примеры для лучшего понимания.

---

### 1. Редакции и возможности
#### Описание:
Обзор различных редакций Postgres Pro (например, Standard, Enterprise) и их возможностей. Включает сравнение функциональности, лицензирование и поддержку.

#### Учебные материалы:
- Документация Postgres Pro: [Postgres Pro Documentation](https://postgrespro.ru/docs)
- Сравнение редакций: таблица с возможностями каждой версии.

#### Пример:
- Postgres Pro Enterprise поддерживает расширенные функции, такие как многомастерная репликация и сжатая файловая система (CFS), которые недоступны в Standard.

---

### 2. Установка, настройка, обновление
#### Описание:
Процесс установки Postgres Pro, начальная настройка и обновление до новых версий.

#### Учебные материалы:
- Руководство по установке: [Postgres Pro Installation Guide](https://postgrespro.ru/docs/enterprise/installation)
- Настройка параметров postgresql.conf.

#### Пример:
- Установка на Ubuntu:
  sudo apt-get install postgrespro-enterprise-13

- Настройка postgresql.conf:
  shared_buffers = 4GB
work_mem = 64MB


---

### 3. Управление транзакциями
#### Описание:
Основы управления транзакциями в PostgreSQL: ACID-свойства, блокировки, изоляция.

#### Учебные материалы:
- Документация по транзакциям: [PostgreSQL Transactions](https://www.postgresql.org/docs/current/tutorial-transactions.html)
- Примеры использования BEGIN, COMMIT, ROLLBACK.

#### Пример:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT;


---

### 4. CFS — сжатая файловая система
#### Описание:
Использование сжатой файловой системы (CFS) для экономии дискового пространства и повышения производительности.

#### Учебные материалы:
- Руководство по CFS: [Postgres Pro CFS Documentation](https://postgrespro.ru/docs/enterprise/cfs)
- Примеры создания таблиц с использованием CFS.

#### Пример:
CREATE TABLE compressed_table (id SERIAL, data TEXT) WITH (compression = cfs);


---

### 5. Оптимизация запросов
#### Описание:
Методы оптимизации запросов: использование индексов, анализ планов выполнения, настройка параметров.

#### Учебные материалы:
- Использование EXPLAIN и EXPLAIN ANALYZE.
- Руководство по индексам: [PostgreSQL Indexes](https://www.postgresql.org/docs/current/indexes.html)

#### Пример:
EXPLAIN ANALYZE SELECT * FROM orders WHERE order_date = '2023-10-01';
CREATE INDEX idx_order_date ON orders(order_date);


---

### 6. Адаптивная оптимизация
#### Описание:
Использование адаптивных методов оптимизации, таких как автоматическая настройка параметров и планировщика.

#### Учебные материалы:
- Документация по адаптивной оптимизации: [Postgres Pro Adaptive Optimization](https://postgrespro.ru/docs/enterprise/adaptive-optimization)

#### Пример:
- Включение адаптивной оптимизации:
  SET adaptive_optimization = on;


---

### 7. Анализ производительности
#### Описание:
Инструменты для анализа производительности: pg_stat_activity, pg_stat_statements, pgpro_pwr.

#### Учебные материалы:
- Руководство по мониторингу: [Postgres Pro Monitoring](https://postgrespro.ru/docs/enterprise/monitoring)

#### Пример:
SELECT * FROM pg_stat_activity;
SELECT query, calls, total_time FROM pg_stat_statements ORDER BY total_time DESC;


---

### 8. Отчеты по нагрузке pgpro_pwr
#### Описание:
Использование расширения pgpro_pwr для генерации отчетов о нагрузке и производительности.

#### Учебные материалы:
- Руководство по pgpro_pwr: [Postgres Pro PWR Documentation](https://postgrespro.ru/docs/enterprise/pgpro-pwr)

#### Пример:
SELECT * FROM pgpro_pwr_get_report('2023-10-01', '2023-10-02');


---

### 9. Профили пользователей
#### Описание:
Управление пользователями и ролями, настройка прав доступа.

#### Учебные материалы:
- Документация по ролям: [PostgreSQL Roles](https://www.postgresql.org/docs/current/user-manag.html)
#### Пример:
CREATE ROLE analyst WITH LOGIN PASSWORD 'secret';
GRANT SELECT ON employees TO analyst;


---

### 10. Аудит
#### Описание:
Настройка аудита для отслеживания действий пользователей.

#### Учебные материалы:
- Руководство по аудиту: [Postgres Pro Audit](https://postgrespro.ru/docs/enterprise/audit)

#### Пример:
CREATE AUDIT POLICY audit_policy ON ALL TABLES;


---

### 11. Планировщик заданий
#### Описание:
Использование планировщика заданий для автоматизации задач, таких как резервное копирование и очистка данных.

#### Учебные материалы:
- Руководство по планировщику: [Postgres Pro Job Scheduler](https://postgrespro.ru/docs/enterprise/job-scheduler)

#### Пример:
CREATE JOB backup_job AS 'pg_dump -U postgres -F c -b -v -f backup.dump testdb';


---

### 12. Резервное копирование
#### Описание:
Методы резервного копирования: полное, инкрементальное, PITR (Point-in-Time Recovery).

#### Учебные материалы:
- Руководство по резервному копированию: [Postgres Pro Backup](https://postgrespro.ru/docs/enterprise/backup)

#### Пример:
pg_basebackup -U postgres -D /backup -Ft -z -P


---

### 13. Синхронный кластер multimaster
#### Описание:
Настройка и управление синхронным кластером с поддержкой multimaster-репликации.

#### Учебные материалы:
- Руководство по multimaster: [Postgres Pro Multimaster](https://postgrespro.ru/docs/enterprise/multimaster)

#### Пример:
- Настройка multimaster-репликации:
  synchronous_standby_names = 'node1, node2'


---

Этот расширенный план с примерами поможет вам лучше понять и применить знания, полученные в ходе обучения. Если у вас есть дополнительные вопросы, уточните, пожалуйста!
нужна автоматизация ansible скрипты bash
## Введение в программное обеспечение

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

### Обзор возможностей PostgreSQL и Patroni

#### PostgreSQL

- Высокая производительность: Поддержка параллельных запросов, оптимизированные алгоритмы индексирования и запросы.
- Отказоустойчивость: Поддержка репликации и резервного копирования.
- Поддержка сложных данных: JSONB, массивы, геопространственные объекты.
- Расширяемость: Возможность добавления новых функций и модулей.

#### Patroni

- Автоматическое управление кластером: Автоматический выбор мастера и переключение на резервный узел в случае отказа.
- Мониторинг и диагностика: Инструменты для мониторинга состояния узлов и выполнения административных задач.
- Упрощенное администрирование: Централизованное управление конфигурациями и обновление версий.

### Основные архитектурные принципы, сценарии использования и преимущества кластеризации

Архитектурные принципы:
- High Availability (HA): Обеспечение непрерывной доступности сервиса даже при отказе отдельных компонентов.
- Replication: Копирование данных между узлами для обеспечения консистентности и отказоустойчивости.
- Failover: Автоматическое переключение на резервный узел при сбое основного узла.

Сценарии использования:
- Веб-приложения с высокими требованиями к доступности.
- Бизнес-критичные приложения, где потеря данных недопустима.
- Распределенные системы, работающие в разных географических зонах.

Преимущества кластеризации:
- Повышенная отказоустойчивость.
- Улучшение производительности за счет распределения нагрузки.
- Легкость масштабирования.

---

## Установка и настройка ПО

### Пошаговое руководство по установке PostgreSQL и Patroni на сервере

#### Установка PostgreSQL

1. Установите PostgreSQL:
   apt-get install postgresql-server


2. Инициализируйте базу данных:
   initdb -D /var/lib/postgresql/data


3. Запустите сервис PostgreSQL:
   systemctl start postgresql


#### Установка Patroni

1. Установите Python и pip:
   apt-get install python3-pip


2. Установите Patroni:
   pip3 install patroni


3. Создайте конфигурационный файл Patroni:
   scope: my_cluster
name: node1
restapi:
listen: 127.0.0.1:8008
connect_address: 127.0.0.1:8008
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
parameters:
wal_level: hot_standby
hot_standby: "on"
max_connections: 100
max_worker_processes: 8
shared_buffers: 128MB
effective_cache_size: 384MB
maintenance_work_mem: 64MB
checkpoint_completion_target: 0.9
wal_buffers: 16MB
default_statistics_target: 100
random_page_cost: 4.0
effective_io_concurrency: 200
work_mem: 6553kB
min_wal_size: 1GB
max_wal_size: 2GB
postgresql:
listen: 127.0.0.1:5432
connect_address: 127.0.0.1:5432
data_dir: /data/pgsql/data
bin_dir: /usr/lib/postgresql/13/bin
config_dir: /data/pgsql/config
pgpass: /tmp/passfile
authentication:
superuser:
username: postgres
password: example_password
replication:
username: replicator
password: example_replication_password
parameters:
wal_level: replica
max_wal_senders: 10
wal_keep_segments: 32
hot_standby: on
archive_mode: on
archive_command: 'cp %p /archivedir/%f'
restore_command: 'cp /archivedir/%f %p'
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false


4. Запустите Patroni:
   patroni /path/to/your/config.yml
### Подготовка окружения и основные параметры конфигурации для стабильной работы системы

1. Создание пользователей и ролей:
   CREATE ROLE patroni_user WITH LOGIN PASSWORD 'example_password';
GRANT ALL PRIVILEGES ON DATABASE my_db TO patroni_user;


2. Настройка сетевого взаимодействия:
Откройте порты PostgreSQL и Patroni в брандмауэре.

3. Оптимизация параметров PostgreSQL:
Отредактируйте файл postgresql.conf:
   max_connections = 500
shared_buffers = 1GB
effective_cache_size = 3GB
work_mem = 256MB
maintenance_work_mem = 512MB
autovacuum = on


---

## Администрирование

### Основы администрирования PostgreSQL в Patroni кластере

#### Управление ролями экземпляров

1. Создание роли:
   CREATE ROLE new_role WITH LOGIN PASSWORD 'password';


2. Предоставление привилегий:
   GRANT USAGE ON SCHEMA public TO new_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO new_role;


#### Выполнение задач по поддержке баз данных и диагностике

1. Резервное копирование:
   pg_dump -U postgres -h localhost -p 5432 my_db > backup.sql


2. Диагностика:
   EXPLAIN ANALYZE SELECT * FROM my_table WHERE id = 123;


---

## Конфигурация, режимы репликации, поддержка слотов логической репликации

### Углубленное изучение настройки репликации в PostgreSQL

#### Логическая репликация

1. Создание слота репликации:
   SELECT * FROM pg_create_logical_replication_slot('my_slot', 'test_decoding');


2. Подключение к слоту:
   START REPLICATION SLOT my_slot LOGICAL my_lsn;


#### Создание и поддержка слотов репликации для повышения отказоустойчивости

1. Мониторинг слотов:
   SELECT * FROM pg_replication_slots;


2. Удаление слота:
   SELECT pg_drop_replication_slot('my_slot');


---

## Конвертация экземпляра в Patroni кластер

### Перевод существующего экземпляра PostgreSQL в кластер Patroni

1. Остановите PostgreSQL:
   systemctl stop postgresql


2. Создайте конфигурационный файл Patroni:
   scope: my_cluster
name: node1
restapi:
listen: 127.0.0.1:8008
connect_address: 127.0.0.1:8008
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
parameters:
wal_level: hot_standby
hot_standby: "on"
max_connections: 100
max_worker_processes: 8
shared_buffers: 128MB
effective_cache_size: 384MB
maintenance_work_mem: 64MB
checkpoint_completion_target: 0.9
wal_buffers: 16MB
default_statistics_target: 100
random_page_cost: 4.0
effective_io_concurrency: 200
work_mem: 6553kB
min_wal_size: 1GB
max_wal_size: 2GB
postgresql:
listen: 127.0.0.1:5432
connect_address: 127.0.0.1:5432
data_dir: /data/pgsql/data
bin_dir: /usr/lib/postgresql/13/bin
config_dir: /data/pgsql/config
pgpass: /tmp/passfile
authentication:
superuser:
username: postgres
password: example_password
replication:
username: replicator
password: example_replication_password
parameters:
wal_level: replica
max_wal_senders: 10
wal_keep_segments: 32
hot_standby: on
archive_mode: on
archive_command: 'cp %p /archivedir/%f'
restore_command: 'cp /archivedir/%f %p'
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false


3. Запустите Patroni:
   patroni /path/to/your/config.yml


---

## Обновление мажорной версии PostgreSQL

### Безопасные методы обновления PostgreSQL до новой мажорной версии с минимизацией простоев и рисков

1. Резервное копирование:
   pg_dumpall -U postgres -h localhost -p 5432 > backup.sql


2. Остановите Patroni:
   patroni stop


3. Обновите PostgreSQL:
   apt-get update && apt-get upgrade postgresql-server


4. Запустите Patroni:
   patroni start


---
## Резервный кластер, несколько ЦОДов

### Настройка резервных кластеров PostgreSQL для нескольких дата-центров

1. Создание нового кластера:
   patroni create-cluster secondary_cluster


2. Настройка репликации:
   ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM SET synchronous_commit = 'remote_write';


3. Синхронизация данных:
   pg_basebackup -h primary_host -U replicator -D /secondary_data_dir


---

Эти шаги помогут вам эффективно управлять PostgreSQL и Patroni кластерами, обеспечивая высокую доступность и надежность ваших баз данных.
ФОРС УЦ
Forwarded from IT Portal
This media is not supported in your browser
VIEW IN TELEGRAM
Очередной годный сайт для прокачки навыков SQL-запросов

На платформе вам предстоит решать задачи, используя базу данных больницы. Задачи разделены по уровням сложности, начиная с простых запросов с SELECT и постепенно переходя к более сложным

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

@PortalToIT
Please open Telegram to view this post
VIEW IN TELEGRAM