четверг, 11 декабря 2025 г.

Migration rabbitmq 3 to 4 with change default queue from classic to quorum

 Вариант бесшовной миграции  с rabbitmq ver.3 (3.8) (192.168.0.34) to ver.4 (4.2) (192.168.0.33).

1) Настраиваем мониторинг для очистки сиротских очередей, по возможности их удаление. мониторинг на стеке rabbitmq-telegraf-infuldb-grafana.

2) подготовка целевого кластера приемника (4.2)

 2.1) внесение в /etc/rabiitmq/rabbitmq.conf след. настроек:

    docker exec -it rabbit_mq bash -c 'cat <<EOF >> /etc/rabbitmq/rabbitmq.conf

# rabbitmq.conf file content

default_queue_type = quorum

quorum_queue.property_equivalence.relaxed_checks_on_redeclaration = true

EOF'


Затем рестарт (в докере):

docker exec -it rabbit_mq rabbitmqctl stop_app

docker exec -it rabbit_mq rabbitmqctl start_app

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

на запросы, при дефолтом контроле наличия очереди, новый раббит будет отвечать корректно, даже если  клиенты (например использующие питон pika) будут сравниваться x-queue-type, в ответ им придет "classic". Требуется минимальная переделка клиентов, практически 100% из них будут после работать c кворумными очередями, думая что они classic.

3) Забираем конфигурацию строго кластера:

curl -u guest:guest http://192.168.0.34:15672/api/definitions -o definitions.json

3.1) удаляем все явные указания на тип очередей:

jq '(.queues[] | select(.arguments | has("x-queue-type")).arguments) |= del (."x-queue-type")' definitions.json > definitions_quorum.json 

3.2) заливаем на новый кластер: 

curl -u guest:guest -H "Content-Type: application/json" -X POST --data "@definitions_quorum.json" http://192.168.0.33:15672/api/definitions

проверяем через web интерфейс новый кластер, что все очереди , обменники, хосты появились.

4) Создание федерации (federation queue)

4.1) Включаем плагины: 

docker exec -it rabbit_mq rabbitmq-plugins enable rabbitmq_federation rabbitmq_federation_management

4.2) Создаем федерацию, коннектор:

docker exec -it rabbit_mq rabbitmqctl set_parameter federation-upstream cluster-a-upstream '{"uri":"amqp://guest:guest@192.168.0.34", "expires":3600000}' 

4.3) на каждый vhost , включая дефолтный, создаем политики федерации:

Для дефолт vhost:

 docker exec -it rabbit_mq rabbitmqctl set_policy federate-queues-only ".*" '{"federation-upstream-set":"all"}' --priority 10 --apply-to queues

Для my_vhost:

docker exec -it rabbit_mq rabbitmqctl set_policy federate-queues-only ".*" '{"federation-upstream-set":"all"}' --priority 10 --apply-to queues --vhost "my_vhost"  

проверяем на новом раббит, что политики применились ко всем очередям .

5) Тестирование передачи сообщений из очередей старого в новый кластер.

5.1)  переключаем консюмеров consumer со старого кластера на новый для одного из vhost.

условием передачи сообщений из старого кластера к новому это:

отсутствие подключения (по tcpip)  консюмера к старому кластеру и наличие постоянного (не curl post запросы!) tcpip подключения консюмера к новому кластеру. Только тогда новый кластер поведет себя как клиент  и  (через federation queue) заберет себе сообщения bp очереди из старого кластера, а старый кластер их отдаст. У старого кластера бузусловный приоритет локальных коннектов пользователей к себе для выбранной очереди!      

Новый сообщения появятся в одноименной очереди в новом кластере, которая будет уже кворумная. Клиенты (consumer) которые проверяю по умолчанию наличие classic очереди будут получать нужный им ответ и потреблять сообщения из нового кластера. При этом продюсеры будут писать в старый кластер.

5.2) переключить всех пользователей (если одни те же продюсеры могут писать в разные vhost).

Если точно известно, что продюсер и все консюмеры сосредоточены только в одном vhost, то после переноса всех консюмеров этого продюсера можно перенести и самого продюсера на новый кластер.

6) Переключение продюсеров на новый кластер.

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

6.1) по одному переключаем продюсеров к новому кластеру (через смену А записи в DNS, или смены бэкэндов в LB, или dnat на старом сервере раббит для IP продюсера)


7) ссылки, для отработки

git clone https://github.com/deepshig/rabbitmq-docker.git

заменить во раббит приемнике ,мв docker-compose.yml имидж, с rabbitmq:3.8-rc-management на rabbitmq:4-management

развернуть тест можно на  https://labs.play-with-docker.com/





вторник, 11 ноября 2025 г.

Postgres (17+) , CDC и репликация WAL

При использовании Patroni и postgres 17+ с включенными опциями: failover = true (в определении слота), synchronized_standby_slots и sync_replication_slots. Debezium прозрачно продолжит получать WAL поток от текущего standby сервера по порту 6432 от vIP patroni, независимо от прошедшего failover/switchover (с задержкой 1-10сек на переключение внутри patroni)

воскресенье, 9 ноября 2025 г.

Terraform on windows.

 Для запуска terraform в windows из-под proxy провайдера необходимо прописать прокси сервер в файле:

-   for windows:  terraform.rc и потом закинуть в path или в  copy terraform.rc $env:APPDATA/

- for linuх:  ./terraformrc (.terraformrc должен располагаться в корне домашней папки пользователя, например, /home/user/ или /User/user/)

содержимое файла terraform.rc or ./terraformrc :

- for selectel:

provider_installation {
network_mirror {
url = "https://mirror.selectel.ru/3rd-party/terraform-registry/"
include = ["registry.terraform.io/*/*"]
}
direct {
exclude = ["registry.terraform.io/*/*"]
}
}

==== или ====

provider_installation {
network_mirror {
url = "https://tf-proxy.selectel.ru/mirror/v1/"
include = ["registry.terraform.io/*/*"]
}
direct {
exclude = ["registry.terraform.io/*/*"]
}
}


- for yandex:

provider_installation { network_mirror { url = "https://terraform-mirror.yandexcloud.net/" include = ["registry.terraform.io/*/*"] } direct { exclude = ["registry.terraform.io/*/*"] } }


При импорте учесть, что как только terraform импортирует, он удалит этот обьект!
и проект/тенант в том числе.


Конструкция типа:

resource "selectel_vpc_project_v2" "project_1" {
  name = "project99"
}

import {
  id = "<therer id your project>"
  to = selectel_vpc_project_v2.project_1
}

Берет существующий проект/тенант под контроль и считает, что терраформ сам создал его и при terraform destroy - он удалит все что импортировал таким образом.


Чтобы делать что-то в существующем проекте с использованием  существующего облачного роутера данного проекта. То  лучше добавлять только новую сеть в новом развертывании (удалится при destroy), и при  этом, чтобы сразу появлялась связность с новой инфры со старой. то надо создавать конструкцию типа:

file: variables.tf

variable "current_project" {
  default = "8f4acb9d7abd.....5f" // Укажите ваш current project
}

variable "current_rtr" {
  default = "03a7f8d5-5360......cf85" // Укажите ваш current router
}

variable "new_cidr" {
  default = "192.168.3" 
/* Укажите ваш новый cidr для нового развертывания, который будет присоединен к существующему роутеру существующего проекта. здесь укороченный cidr , т.к. в моем случае статические адреса раздаются счетчиком в main.tf 
*/  
}  

Используйте в variables.tf как:
${var.current_project}  вместо selectel_vpc_project_v2.project_1.id где ссылается, типа:

provider "openstack" {
  auth_url    = "https://cloud.api.selcloud.ru/identity/v3"
  domain_name = "499999"
#  tenant_id   = selectel_vpc_project_v2.project_1.id
  tenant_id   = var.current_project
  region      = "ru-3"
}

== and in main.tf ===

resource "openstack_networking_network_v2" "network_1" {
  name           = "private-network99"
  admin_state_up = "true"

  depends_on = [
#    selectel_vpc_project_v2.project_1,  (not need here,  we don't create an new project)
  ]
}

resource "openstack_networking_subnet_v2" "subnet_1" {
  network_id = openstack_networking_network_v2.network_1.id
  cidr       = "${var.new_cidr}.0/24"  
}

data "openstack_networking_network_v2" "external_network_1" {
  external = true

  depends_on = [
#    selectel_vpc_project_v2.project_1,
    selectel_iam_serviceuser_v1.serviceuser_1
  ]
}

# not need here, use existing router
# resource "openstack_networking_router_v2" "router_1" {
#  name                = "router99"
#  external_network_id = data.openstack_networking_network_v2.external_network_1.id
# }

resource "openstack_networking_router_interface_v2" "router_interface_1" {
#  router_id = openstack_networking_router_v2.router_1.id // not need
  router_id = var.current_rtr
  subnet_id = openstack_networking_subnet_v2.subnet_1.id
}

resource "openstack_networking_port_v2" "server_port" {
  count = var.instance_count
  name  = "server-port-${count.index + 1}"
  network_id = openstack_networking_network_v2.network_1.id

  fixed_ip {
    subnet_id  = openstack_networking_subnet_v2.subnet_1.id
    ip_address = "${var.new_cidr}.${count.index + 10}" # сами устанавливаем статические IP с 10..
  }
}

...

Создание ВМ с  доисталляцией через мех-зм cloud-init:

resource "openstack_compute_flavor_v2" "flavor_1" {
  name      = "custom-flavor-with-network-volume-my-only43"
  vcpus     = 2
  ram       = 4096
  disk      = 0
  is_public = false

  lifecycle {
    create_before_destroy = true
  }

}


data "openstack_images_image_v2" "image_1" {
  name        = "Ubuntu 22.04 LTS 64-bit"
  most_recent = true
  visibility  = "public"

  depends_on = [
    #    selectel_vpc_project_v2.project_1,
    selectel_iam_serviceuser_v1.serviceuser_1
  ]
}

resource "openstack_blockstorage_volume_v3" "server_volume" {
  count = var.instance_count
  name  = "preemptible_ssd_volume-${count.index + 1}"
  #  name              = "my_preemptible_ssd_volume"
  size                 = 15                                        # Размер диска в ГБ
  image_id             = data.openstack_images_image_v2.image_1.id # Используем найденный UUID образа
  volume_type          = "universal.${var.region}"                 # Указываем тип SSD диска, который поддерживает заморозку
  availability_zone    = var.region
  enable_online_resize = true

  lifecycle {
    ignore_changes = [image_id]
  }
}

resource "openstack_compute_instance_v2" "server_1" {
  count = var.instance_count
  name  = "opensearch-server-${count.index + 1}"
  #  image_id          = data.openstack_images_image_v2.image_1.id
  #  flavor_id         = "1312"
  flavor_id         = openstack_compute_flavor_v2.flavor_1.id
  key_pair          = selectel_vpc_keypair_v2.keypair_1.name
  availability_zone = var.region
  # is_preemptible    = true

  metadata = {
    preemptible = "true"
  }

  block_device {
    # uuid                  = openstack_blockstorage_volume_v3.server_volume.id
    uuid             = openstack_blockstorage_volume_v3.server_volume[count.index].id
    source_type      = "volume"
    destination_type = "volume"
    boot_index       = 0
    # delete_on_termination = false # Диск сохраняется после удаления сервера
  }
# желтый ниже - это не комментарий а служебное слово!
  user_data = <<EOF
  #cloud-config
  runcmd:
  # Пример 1: Обновление списка пакетов
    - apt update -y
  # 2. Устанавливаем OpenJDK 21 JRE (headless), что необходимо для OpenSearch 3.x
    - apt install -y openjdk-21-jre-headless
  # 3. Проверяем установленную версию
  #  - java -version > /tmp/java_version_output.txt
    - echo JAVA_HOME=\"$(readlink -f /usr/bin/java | sed "s:/bin/java::")\" >> /etc/environment
    - export PATH=$PATH:$JAVA_HOME/bin
    - echo $JAVA_HOME > /tmp/java_version_output.txt
    - echo $PATH >> /tmp/java_version_output.txt
  # Пример 2: Установка веб-сервера nginx
    - apt install -y nginx
  # Пример 3: Запись сообщения в файл
    - echo "Inline runcmd executed successfully!" > /tmp/inline_output.txt
  EOF



  network {
    port = openstack_networking_port_v2.server_port[count.index].id
  }

  lifecycle {
    ignore_changes = [image_id]
  }

  vendor_options {
    ignore_resize_confirmation = true
  }
}


==========================================
Для SSL к внутреннему хосту(ам) , self-signed
(внимание, runcmd и write_files срабаьывают только один раз, т.е. после write_files снова runcmd не сработает. если что-то нужно выполнить после "write_files", то добавляем команду в первой секции "runcmd" и добавляем задержку исполнения sleep 10).

user_data = <<EOF
  #cloud-config
  runcmd:
  # Пример 1: Обновление списка пакетов
    - apt update -y
  # 2. Устанавливаем OpenJDK 21 JRE (headless), что необходимо для OpenSearch 3.x
    - apt install -y openjdk-21-jre-headless
  # 3. Проверяем установленную версию
  #  - java -version > /tmp/java_version_output.txt
    - echo JAVA_HOME=\"$(readlink -f /usr/bin/java | sed "s:/bin/java::")\" >> /etc/environment
    - export PATH=$PATH:$JAVA_HOME/bin
    - echo $JAVA_HOME > /tmp/java_version_output.txt
    - echo $PATH >> /tmp/java_version_output.txt
  # Пример 2: Установка веб-сервера nginx
    - apt install -y nginx
  # Пример 3: Запись сообщения в файл
  #  - echo "Inline runcmd executed successfully!" > /tmp/inline_output.txt
    - openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt -subj "/CN=my.lab"
    - ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
    - sleep 10 && systemctl restart nginx &
  write_files:
    - content: |
        upstream backend_host {
            server 192.168.3.10:5601; # Replace with your upstream host IP and port
        }
        server {
            listen 80;
            listen [::]:80;
            server_name your_domain_or_ip; # Replace with your Nginx server domain/IP
            return 301 https://$host$request_uri;
        }
        server {
            listen 443 ssl;
            listen [::]:443 ssl;
            server_name your_domain_or_ip; # Replace with your Nginx server domain/IP
            ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
            ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
            location / {
                proxy_pass http://backend_host;
                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;
            }
        }
      path: /etc/nginx/sites-available/default
      permissions: '0644'
  EOF



==== Доступны логи  cloud-init на разворачиваемой  машине===
/var/log/cloud-init.log and /var/log/cloud-init-output.log

понедельник, 29 сентября 2025 г.

Архимейт (Sparx) Линки/ссылки на диаграммы. Archimate Links

 Методы привязки ссылок на другие объекты/диаграммы в Sparx для создания вложенных диаграмм.

1) Произвольные (почти) ссылки на диаграммы:

- правой кнопкой мыши -> контекстное меню-> New child diagramm-> Select composite diagramm -> Выбрать свою диаграмму из браузера (иерархия вкладок , слева обычно)

2) Перенести диаграмму/объект из браузера с нажатым CTRL. затем выбрать необходимый вид ссылки. Доступны преформатированные view с уменьшенным масшатбом, как с обектами внутри таки просто графический контейнер.

3) Для диаграмм. переносим левой кнопкой мыши, автоматически предлагается HyperLink выбираем, но визуализация просто как надпись. форму объекта надо подготовить заранее и без названия.    

н

Использование стрелок из Toolbox:

 Выбираем стрелку (Relationships) , просто нажав на неё. Затем  нажав левую кнопку мыши, проводим от сорс обьекта к дестинашен объекту, пока не засветится пунктирная граница на дестинешн, затем отпускаем левую кнопку мыши.

Экспорт в картинку:

Publish-> Save File (выбрать формат)


Изменить тип/направление связи:

правой кнопкой, Advanсed -> Change Type/Reverse Direction


Изменить composition to aggregation (shared)и

aggregation shared (розовый ромб) - означает что может содержаться в нескольких более низкоуровневых обьектах

composition (черный ромб)  - элемент (обычно системное ПО/приклад) может быть частью только этого более низкоуровневого объекта


Изменить контур фигуры (для поянения целевого/не целевого статуса)

правой кнопкой мыши, выбрать цвет в верхнем меню, там же параметры надписи 


Изменить прозрачность (изменяются надписи, появляется тип обьекта и т.д.)

Appearance -> Enable Custon Style

Затем правой кнопкой выбрать появившиеся прямоугольнички "транспаренси" и  выбрать 25,50,75,100 прозрачности.

https://sparxsystems.com/enterprise_architect_user_guide/17.1/the_application_desktop/custom_draw_style_toolbar.html

https://sparxsystems.com/forums/smf/index.php?topic=40318.0


воскресенье, 22 декабря 2024 г.

tuning linux for high load (net)

Pages with twicks


https://www.thegeekdiary.com/sysctl-setting-for-high-load-and-prevent-ddos/

https://easyengine.io/tutorials/linux/sysctl-conf/

https://reintech.io/blog/tuning-linux-kernel-parameters-rocky-linux-9

https://stupin.su/wiki/linux_sysctl/

http://kb.ictbanking.net/article.php?id=348

https://www.cyberciti.biz/tips/linux-increase-outgoing-network-sockets-range.html

https://www.cyberciti.biz/tips/linux-increase-outgoing-network-sockets-range.html

https://habr.com/ru/articles/108763/

https://docs.emqx.com/en/emqx/latest/performance/tune.html







среда, 18 декабря 2024 г.

Публикация VPN сервера Windows 2019 (pptp, l2tp) из приватной сети через NAT checkpoint

1)  При стандартной настройке NAT (incoming NAT for ANY) pptp не работает, хотя tcp/1723  и GRE транслируются во внутрь, проблема в том, что только обратный GRE трафик от сервера не транслируется. Для этого необходимо добавить и  исходящее правило NAT (any, hide) только для GRE трафика и разрешить в ACL исходящий трафик только для GRE.  Ответные же TCP и UDP  от VPN сервера будут автоматический выпущены в контексте инициирующего их  входящего NAT.

2) L2tp по умолчанию не работает, так Windows (клиент и сервер) не понимают NAT-T. для этого необходимо включить  опцию в registy по статье:

https://winitpro.ru/index.php/2017/10/24/reshaem-problemu-podklyucheniya-k-l2tp-ipsec-vpn-serveru-za-nat/

или использовать командлет PowerShell для внесения изменений в реестр:

Set-ItemProperty -Path "HKLM:SYSTEM\CurrentControlSet\Services\PolicyAgent" -Name "AssumeUDPEncapsulationContextOnSendRule" -Type DWORD -Value 2 –Force


понедельник, 10 июня 2024 г.

Архитектура (ИТ)


Матрица Захмана:


или







 TOGAF (the open group architecture framework)

ADM (Architecture Deployment Method)

ADM describes 10 phases and preliminary phase