Цель

Не жарить, а печь.

Задача

Подружить Packer с облачным провайдером SberCloud

Вступление

Привет! Я начинающий DevOps инженер, на неделе была поставлена цель перейти от создания облачной инфраструктуры ручками к IaaC посредством внедрения Packer + Terraform + Ansible. Если у сбера есть провайдер для Terraform, но для Packer провайдер не завезли.

Облазил весь интернет, и не нашёл готового решения или хотя бы намёка на то куда копать.

Нашёл единственную статью на habr.com от компании КРОК и их облаке которое построено по принципу AWS. Исходя из это статьи начал копать, а именно узнал по какому принципу сделано облако сбера, немного почитав документацию понял - облако сделано по принципу Huawei Cloud. И о везение, существует провайдер Huawei Cloud - ссылочка на доку.

Жарка с провайдером Huawei Cloud

Казалось бы всё, победа! Но не тут то было, посмотрим на базовый пример для создания образа в облаке Huawei

Пример для провайдера Huawei cloud
variable "access_key" {
  type = string
}
variable "secret_key" {
  type = string
}

variable "source_image_id" {
  type = string
}
variable "vpc_id" {
  type = string
}
variable "subent_id" {
  type = string
}

source "huaweicloud-ecs" "basic-example" {
  region             = "cn-north-1"
  access_key         = var.access_key
  secret_key         = var.secret_key
  flavor             = "s6.large.2"
  image_name         = "packer-image"
  source_image       = var.source_image_id
  vpc_id             = var.vpc_id
  subnets            = [var.subent_id]
  security_groups    = ["default"]
  eip_bandwidth_size = 2
  eip_type           = "5_bgp"
  ssh_ip_version     = "4"
  ssh_username       = "root"
}

build {
  sources = ["source.huaweicloud-ecs.basic-example"]

  provisioner "shell" {
    inline = [
      "echo \"start install nginx, sleep 20s first\"",
      "sleep 20",
      "echo \"run install\"",
      "apt install -y nginx",
      "echo \"enable nginx\"",
      "systemctl enable nginx.service",
      "echo \"install nginx done\""
    ]
  }
}

Данный пример на языке HCL2. И тут есть пара очень важных моментов, которые чуток ломают мозг. Если мы обратимся к провайдеру сбера для Terraform, то увидим что для создания ECS, мы используем следующий код.

resource "sbercloud_compute_instance" "ECS_TestBack" {
  ...
}

Обратим внимание на "sbercloud_compute_instance" - создание ECS происходит при вызове этого ресурса, но если мы тоже самое напишем в Packer, то получим ошибку - что логично, ведь провайдер то не знает ни о каком "sbercloud_compute_instance". По этому оставляем как есть.

Далее подставим свои токены и попробуем запустить.

Непосредственно как дружить

Тут я чуток переписал код под себя, но смысл остался тот же.

Сначала указываем провайдера.

Провайдер
packer {
  required_plugins {
    huaweicloud = {
      version ">= 0.4.0"
      source  = "github.com/huaweicloud/huaweicloud"
    }
  }
}

Потом несколько переменных.

Переменные
# Объявление переменных
variable "sber_access_key" {
  type        = string
  description = "Access_key для сбера"
}

variable "sber_secret_key" {
  type        = string
  description = "Secret_key для сбера"
}

variable "ECS_enterprise_project" {
  type        = string
  description = "Тип проекта"
}

variable "vpc_id" {
  type        = string
  description = "Id vpc"
}

variable "source_image_name" {
  type        = string
  description = "Первоначальный образ"
}

variable "security_groups_test_back" {
    description = "Группы безопасности для тестового бэка"
}

variable "security_groups_test_front" {
    description = "Группы безопасности для тестового фронта"
}

Самое интересное и важное, на какой виртуалке создавать образ.
Ну и блок build, в котором описываем что билдим и какой provisioner используем(код ansible не буду показывать, так как смысл статьи в другом)

Настройка виртуальной машины и блок build
# Настройки на какой машине образ будет билдиться
source "huaweicloud-ecs" "test-back" {
  region             = "cn-north-1"
  access_key      = var.sber_access_key
  secret_key      = var.sber_secret_key
  flavor          = "c6.large.2"
  image_name      = "test-back"
  source_image_name    = var.source_image_name
  vpc_id          = var.vpc_id
  subnets         = ["5abf333d-9592-44a8-9833-7fada04c5b24"]
  security_groups = var.security_groups_test_back
  ssh_ip_version  = "4"
  ssh_username    = "root"
}

build {
  sources = ["source.huaweicloud-ecs.test-back"]
  provisioner "ansible" {
      playbook_file = "../Ansible/playbook.yml"
    }
}

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

Не рабочий, но полезный для понимания код
packer {
  required_plugins {
    huaweicloud = {
      version ">= 0.4.0"
      source  = "github.com/huaweicloud/huaweicloud"
    }
  }
}

# Объявление переменных
variable "sber_access_key" {
  type        = string
  description = "Access_key для сбера"
}

variable "sber_secret_key" {
  type        = string
  description = "Secret_key для сбера"
}

variable "ECS_enterprise_project" {
  type        = string
  description = "Тип проекта"
}

variable "vpc_id" {
  type        = string
  description = "Id vpc"
}

variable "source_image_name" {
  type        = string
  description = "Первоначальный образ"
}

variable "security_groups_test_back" {
    description = "Группы безопасности для тестового бэка"
}

variable "security_groups_test_front" {
    description = "Группы безопасности для тестового фронта"
}

# Настройки на какой машине образ будет билдиться
source "sbercloud_compute_instance" "test-back" {
  region             = "cn-north-1"
  access_key      = var.sber_access_key
  secret_key      = var.sber_secret_key
  flavor          = "c6.large.2"
  image_name      = "test-back"
  source_image_name    = var.source_image_name
  vpc_id          = var.vpc_id
  subnets         = ["5abf333d-9592-44a8-9833-7fada04c5b24"]
  security_groups = var.security_groups_test_back
  ssh_ip_version  = "4"
  ssh_username    = "root"
}

build {
  sources = ["source.huaweicloud-ecs.test-back"]
  provisioner "ansible" {
      playbook_file = "../Ansible/playbook.yml"
    }
}

Запускаем и получаем ошибку авторизации, мол таких ключей нет, и тут снова логичней некуда, он пытается стукнуться в Huawei cloud, а мы же со SberCloud.

На самом деле почти победа, нужно внести маленькие правочки, до них можно догадаться если обратиться к Terraform провайдеру (да да они похожи).

Редактировать будем 1 блок, а именно source.

Правка блока с настройками виртуальной машины
# Настройки на какой машине образ будет билдиться
source "huaweicloud-ecs" "test-back" {
  auth_url        = "https://iam.ru-moscow-1.hc.sbercloud.ru/v3"
  region          = "ru-moscow-1"
  access_key      = var.sber_access_key
  secret_key      = var.sber_secret_key
  flavor          = "c6.large.2"
  image_name      = "test-back"
  source_image_name    = var.source_image_name
  vpc_id          = var.vpc_id
  subnets         = ["5abf333d-9592-44a8-9833-7fada04c5b24"]
  security_groups = var.security_groups_test_back
  ssh_ip_version  = "4"
  ssh_username    = "root"
}

Самые важные изменения находятся в строках 3 и 4. Мы говорим явно какая ссылка для авторизации, ну и регион меняем на правильный.

Запуск...

Барабанная дробь

Бинго, всё работает.

Теперь приложу рабочий код, его можно смело копипастить и оно заработает)

Рабочий код конфигурации
packer {
  required_plugins {
    huaweicloud = {
      version ">= 0.4.0"
      source  = "github.com/huaweicloud/huaweicloud"
    }
  }
}

# Объявление переменных
variable "sber_access_key" {
  type        = string
  description = "Access_key для сбера"
}

variable "sber_secret_key" {
  type        = string
  description = "Secret_key для сбера"
}

variable "ECS_enterprise_project" {
  type        = string
  description = "Тип проекта"
}

variable "vpc_id" {
  type        = string
  description = "Id vpc"
}

variable "source_image_name" {
  type        = string
  description = "Первоначальный образ"
}

variable "security_groups_test_back" {
    description = "Группы безопасности для тестового бэка"
}

variable "security_groups_test_front" {
    description = "Группы безопасности для тестового фронта"
}

# Настройки на какой машине образ будет билдиться
source "huaweicloud-ecs" "test-back" {
  auth_url        = "https://iam.ru-moscow-1.hc.sbercloud.ru/v3"
  region          = "ru-moscow-1"
  access_key      = var.sber_access_key
  secret_key      = var.sber_secret_key
  flavor          = "c6.large.2"
  image_name      = "test-back"
  source_image_name    = var.source_image_name
  vpc_id          = var.vpc_id
  subnets         = ["5a33d-9592-44a8-9833-7fada04c5b24"]
  security_groups = var.security_groups_test_back
  ssh_ip_version  = "4"
  ssh_username    = "root"
}

# Настройки билда образов
build {
  sources = ["source.huaweicloud-ecs.test-back"]
  provisioner "ansible" {
      playbook_file = "../Ansible/playbook.yml"
    }
}

Вывод

С этой задачкой я жарился два дня, скорее всего из-за неопытности, но путь пройден и теперь это не проблема)

Надеюсь статья будет полезна для таких же новичков, как и я. И сэкономит очень много времени и нервных клеток.

Комментарии (2)


  1. JuryPol
    09.07.2022 14:26
    -1

    Плюсую, но…

    «Небольшая статья про экспирианс»… а чего вдруг сразу «экспирианс»? Какой смысловой оттенок имеется дополнительно именно в этом слове, что пришлось забраковать слово «опыт»? Слишком сермяжно?

    «Надеюсь статья будет полезна для новичков как и я»… Тоже лучше бы поправить. Вы явно хотели сказать чуть-чуть иначе. Что-то типа «для таких же новичков, как и я».

    Да, и в данных своих поправьте «инжинер» на «инженер».


    1. Froot Автор
      09.07.2022 21:27

      Спасибо за комментарий. Учту замечания которые посчитаю важными и нужными.