воскресенье, 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

Комментариев нет:

Отправить комментарий