вторник, 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
Подписаться на:
Комментарии (Atom)