# Clusterware

Всякое про гридинфраструктуру

# Добавление кастомного ресурса в Oracle Clusterware: практическое руководство

### Введение

Oracle Clusterware (ранее известный как Oracle Cluster Ready Services) предоставляет надежную платформу для управления высокодоступными приложениями в кластерной среде. В некоторых случаях возникает необходимость интегрировать в кластер пользовательские приложения или сервисы, которые не являются стандартными компонентами Oracle. В этой статье рассмотрим пошаговый процесс добавления кастомного ресурса в кластерную инфраструктуру.

### Преимущества интеграции кастомных ресурсов

- Автоматический запуск и остановка приложения при переключении узлов
- Мониторинг состояния приложения кластером
- Интеграция в общую систему управления кластером
- Зависимости между ресурсами для корректного порядка запуска

### Подготовительные шаги

#### 1. Настройка прав sudo для сервисного пользователя

Создаем файл конфигурации sudo для пользователя grid:

```bash
sudo visudo -f /etc/sudoers.d/custom_service
```

Добавляем содержимое:

```bash
# Sudo permissions for service user to manage custom_service
Defaults:grid !requiretty

Cmnd_Alias CUSTOM_SERVICE_CTL = \
    /usr/bin/systemctl start custom_service.service, \
    /usr/bin/systemctl stop custom_service.service, \
    /usr/bin/systemctl is-active --quiet custom_service.service

grid ALL=(root) NOPASSWD: CUSTOM_SERVICE_CTL
```

#### 2. Создание враппер-скриптов

Создаем скрипты-обертки для управления сервисом:

**/usr/local/bin/cs\_start.sh:**

```bash
#!/bin/bash
exec /usr/bin/sudo /usr/bin/systemctl start custom_service.service
```

**/usr/local/bin/cs\_stop.sh:**

```bash
#!/bin/bash
exec /usr/bin/sudo /usr/bin/systemctl stop custom_service.service
```

**/usr/local/bin/cs\_check.sh:**

```bash
#!/bin/bash
exec /usr/bin/sudo /usr/bin/systemctl is-active --quiet custom_service.service
```

#### 3. Настройка прав доступа к скриптам

```bash
chown root:root /usr/local/bin/cs_start.sh /usr/local/bin/cs_stop.sh /usr/local/bin/cs_check.sh
chmod 755 /usr/local/bin/cs_start.sh /usr/local/bin/cs_stop.sh /usr/local/bin/cs_check.sh
```

### Интеграция с Oracle Clusterware

#### 4. Создание пользовательского типа ресурса

```bash
crsctl add resourcegrouptype custom_app_type -basetype cluster_resourcegroup
```

#### 5. Добавление ресурсной группы

```bash
crsctl add resourcegroup custom_service_rg -type custom_app_type
```

#### 6. Создание ресурса в кластере

```bash
crsctl add resource custom_service \
  -type generic_application \
  -group custom_service_rg \
  -attr "START_PROGRAM='/usr/local/bin/cs_start.sh', \
STOP_PROGRAM='/usr/local/bin/cs_stop.sh', \
CLEAN_PROGRAM='/usr/local/bin/cs_stop.sh', \
CHECK_PROGRAMS='/usr/local/bin/cs_check.sh'"
```

#### 7. Настройка зависимостей ресурса

Указываем зависимости от других ресурсов кластера (в примере - от группы ASM):

```bash
crsctl modify resourcegroup custom_service_rg -attr "START_DEPENDENCIES='hard(ora.asmgroup)'"
```

### Тестирование конфигурации

#### Запуск ресурса

```bash
crsctl start resource custom_service
```

Ожидаемый результат:

```bash
CRS-2672: Attempting to start 'custom_service' on 'node01'
CRS-2676: Start of 'custom_service' on 'node01' succeeded
```

#### Проверка статуса

```bash
crsctl status resource custom_service -t
```

Ожидаемый результат:

```bash
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
custom_service(custom_service_rg)
      1        ONLINE  ONLINE       node01                   STABLE
--------------------------------------------------------------------------------
```

#### Остановка ресурса

```bash
crsctl stop resourcegroup custom_service_rg
```

Ожидаемый результат:

```bash
CRS-33673: Attempting to stop resource group 'custom_service_rg' on server 'node01'
CRS-2673: Attempting to stop 'custom_service' on 'node01'
CRS-2677: Stop of 'custom_service' on 'node01' succeeded
```

<div class="_messagesWrapper_15jqx_8" id="bkmrk-%D0%A0%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D0%B0%D1%86%D0%B8%D0%B8-%D0%B8-%D0%BB%D1%83%D1%87%D1%88%D0%B8"><div class="_container_15jqx_1"><div class="_history_15jqx_16"><article aria-label="Ответ модели DeepSeek V3.1 Terminus внутренний" class="_container_twi1c_1" data-message-id="76a744f1-ac6f-432f-9c38-df5dc9f54cec" data-qa="dst-message">#### Рекомендации и лучшие практики

<div class="markdown _content_twi1c_27"><div aria-atomic="true" aria-busy="false" aria-live="polite" class="markdown" tabindex="-1">1. **Тестирование отказоустойчивости** - убедитесь, что ресурс корректно перезапускается при переключении узлов
2. **Логирование** - настройте детальное логирование для диагностики проблем
3. **Таймауты** - при необходимости настройте параметры времени ожидания для операций
4. **Зависимости** - тщательно продумайте зависимости между ресурсами

</div></div>#### Заключение

Интеграция кастомных приложений в Oracle Clusterware позволяет создать единую систему управления всеми критически важными компонентами инфраструктуры. Представленная методика обеспечивает надежное функционирование пользовательских сервисов в высокодоступной среде с минимальными затратами на администрирование.

<div class="g-box g-flex _footer_twi1c_22" data-qa="dst-message-footer"><div>  
</div><div>  
</div><div>  
</div></div></article></div></div></div>

# Спортивно, на лету, пересобираем АСМ группу

Иногда возникает необходимость изменить структуру *failgroup* в уже существующей ASM disk group. Например, чтобы перераспределить диски между группами отказоустойчивости и привести конфигурацию к новой схеме.

На первый взгляд задача выглядит просто: удалить диск из одной *failgroup* и добавить его в другую. Однако на практике Oracle ASM контролирует баланс дисков между *failgroup* и не позволяет выполнять такие изменения без соблюдения внутренних ограничений.

Разберем этот сценарий на конкретном примере.

#### Исходная конфигурация

Допустим, у нас есть ASM disk group `DATA` со следующей конфигурацией:

```sql
select group_number, operation, state, power, actual, sofar, est_work, est_rate, est_minutes, error_code
from v$asm_operation
order by group_number, operation;

GROUP_NUMBER DISK_NUMBER NAME           PATH           FAILGROUP  HEADER_STA MODE_STA MOUNT_ST STATE
------------ ----------- --------- ------------------ ---------- ---------- -------- -------- ------
           1           0 DISK1     /dev/ASM_DISK1_P1   FG1        MEMBER     ONLINE   CACHED   NORMAL
           1           1 DISK2     /dev/ASM_DISK2_P1   FG1        MEMBER     ONLINE   CACHED   NORMAL
           1           2 DISK3     /dev/ASM_DISK3_P1   FG1        MEMBER     ONLINE   CACHED   NORMAL
           1           3 DISK4     /dev/ASM_DISK4_P1   FG2        MEMBER     ONLINE   CACHED   NORMAL
           1           4 DISK5     /dev/ASM_DISK5_P1   FG2        MEMBER     ONLINE   CACHED   NORMAL
           1           5 DISK6     /dev/ASM_DISK6_P1   FG2        MEMBER     ONLINE   CACHED   NORMAL
```

Текущая схема выглядит так:

- `FG1`: `DISK1`, `DISK2`, `DISK3`
- `FG2`: `DISK4`, `DISK5`, `DISK`

#### Целевая конфигурация

Необходимо получить следующую схему:

```sql
GROUP_NUMBER DISK_NUMBER NAME  PATH               FAILGROUP HEADER_STA MODE_STA MOUNT_ST STATE
------------ ----------- ----- ------------------ --------- ---------- -------- -------- ------
           1           0 DISK1 /dev/ASM_DISK1_P1  FG1       MEMBER     ONLINE   CACHED   NORMAL
           1           1 DISK2 /dev/ASM_DISK2_P1  FG1       MEMBER     ONLINE   CACHED   NORMAL
           1           2 DISK4 /dev/ASM_DISK4_P1  FG2       MEMBER     ONLINE   CACHED   NORMAL
           1           3 DISK5 /dev/ASM_DISK5_P1  FG2       MEMBER     ONLINE   CACHED   NORMAL
           1           4 DISK3 /dev/ASM_DISK3_P1  FG3       MEMBER     ONLINE   CACHED   NORMAL
           1           5 DISK6 /dev/ASM_DISK6_P1  FG3       MEMBER     ONLINE   CACHED   NORMAL
```

То есть итоговая структура должна быть такой:

- `FG1`: `DISK1`, `DISK2`
- `FG2`: `DISK4`, `DISK5`
- `FG3`: `DISK3`, `DISK6`

#### Почему это не получится сделать напрямую

Если просто начать по одному удалять диски из `+DATA`, Oracle ASM не позволит это сделать.

*Предположим, в данном сценарии нельзя сразу вывести по одному диску из `FG1` и `FG2`, чтобы сразу собрать `FG3`, поскольку для такого ребаланса недостаточно свободного места.*

В этом случае Oracle выдаст ошибку:

```sql
ERROR at line 1:
ORA-15032: not all alertations performed
ORA-15411: Failure groups in disk group DATA have different number of disks.
```

ASM проверяет симметрию распределения дисков между *failgroup* и блокирует изменения, которые временно нарушают эту структуру.

#### Временный обход ограничения

В подобных случаях можно временно отключить часть внутренних проверок ASM с помощью скрытых параметров.

> \[!WARNING\] Использование hidden parameters — потенциально рискованная и официально не рекомендуемая практика. Применяйте этот подход только при полном понимании последствий, желательно после проверки на тестовом стенде и при наличии актуальной резервной копии.

Включаем параметры:

```sql
alter system set "_asm_disable_failgroup_size_checking"=true;
alter system set "_asm_disable_dangerous_failgroup_checking"=true;
```

Эти параметры временно позволяют ASM не блокировать изменения, связанные с неравномерным количеством дисков в *failgroup*.

#### Шаг 1. Удаление диска из текущей failgroup

```sql
ALTER DISKGROUP DATA DROP DISK DISK3 REBALANCE POWER 0;
ALTER DISKGROUP DATA REBALANCE POWER 24;
```

Здесь используется следующая логика:

- команда `DROP DISK` инициирует удаление диска из группы;
- `REBALANCE POWER 0` позволяет не запускать активный ребаланс немедленно;
- затем отдельной командой задается нужная мощность ребаланса.

#### Контроль состояния ребаланса

После каждого удаления или добавления диска необходимо дождаться завершения ребаланса.

Проверить статус можно так:

```sql
select group_number, operation, state, power, actual, sofar, est_work, est_rate, est_minutes, error_code
from v$asm_operation
order by group_number, operation;
```

Переходить к следующему шагу следует только после того, как в `v$asm_operation` не останется активных операций.

#### Шаг 2. Добавление диска в новую failgroup

После завершения ребаланса добавляем тот же диск обратно, но уже в новую *failgroup* `FG3`:

```sql
ALTER DISKGROUP DATA ADD FAILGROUP FG3 DISK '/dev/ASM_DISK3_P1' NAME DISK3 REBALANCE POWER 0;
ALTER DISKGROUP DATA REBALANCE POWER 24;
```

После этого снова необходимо дождаться завершения ребаланса.

#### Шаг 3. Повторение операции для второго диска

Далее аналогичным образом переносим диск `/dev/ASM_DISK6_P1` в `FG3`.

Последовательность та же:

1. удалить диск из текущей *failgroup*;
2. дождаться завершения ребаланса;
3. добавить диск обратно в `FG3`;
4. снова дождаться завершения ребаланса.

#### Возврат скрытых параметров в исходное состояние

После завершения всех операций параметры необходимо вернуть в исходное состояние:

```sql
alter system set "_asm_disable_failgroup_size_checking"=false;
alter system set "_asm_disable_dangerous_failgroup_checking"=false;
```

#### На что стоит обратить внимание

#### 1. Операция связана с риском

Фактически на время работ отключаются встроенные защитные механизмы ASM. Если в этот момент произойдет дополнительный сбой диска или failgroup, последствия могут быть критичными.

#### 2. Нужен запас свободного места

Даже при поэтапном переносе ASM должен иметь достаточно свободного пространства для перемещения экстентов во время ребаланса.

#### 3. Ребаланс нужно завершать на каждом этапе

Не стоит выполнять несколько операций подряд без контроля. Каждое удаление и каждое добавление диска должно завершаться полным ребалансом.

#### 4. Значение `POWER` нужно подбирать осознанно

В примере используется `REBALANCE POWER 24`, но реальное значение зависит от:

- нагрузки на систему;
- требований по времени выполнения работ;
- допустимого влияния на производительность.

#### 5. Важно не ошибиться при повторном добавлении диска

Перед выполнением команды необходимо внимательно проверить:

- путь к устройству;
- имя диска;
- имя целевой *failgroup*.

---

#### Итог

Если нужно перераспределить диски между *failgroup* в Oracle ASM, стандартные проверки ASM могут не позволить выполнить это напрямую. В частности, Oracle блокирует сценарии, в которых *failgroup* временно получают разное количество дисков.

В такой ситуации задачу можно решить поэтапно:

1. временно отключить внутренние проверки;
2. удалить диск из текущей *failgroup*;
3. дождаться завершения ребаланса;
4. добавить диск в новую *failgroup*;
5. повторить процедуру для остальных дисков;
6. вернуть параметры в исходное состояние.

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

#### Полезные запросы для контроля

#### Проверка активных операций ASM

```sql
select group_number, operation, state, power, actual, sofar, est_work, est_rate, est_minutes, error_code
from v$asm_operation
order by group_number, operation;
```

#### Просмотр текущего состава дисков в disk group

```sql
select group_number,
       disk_number,
       name,
       path,
       failgroup,
       header_status,
       mode_status,
       mount_status,
       state
from v$asm_disk
where group_number is not null
order by group_number, disk_number;
```

#### Дисклеймер

> \[!CAUTION\] Описанный подход использует скрытые параметры Oracle ASM. Перед применением в production-среде рекомендуется:
> 
> - проверить сценарий на тестовом стенде;
> - убедиться в наличии актуальной резервной копии;
> - оценить объем свободного места в disk group;
> - заранее продумать план отката.