Как добавить некорневой ssh-ключ в экземпляр Openstack, используя Terraform?

Я пытаюсь создать экземпляр Openstack, используя Terraform, и после этого я хочу настроить пользователя "ubuntu" с помощью моего ssh-ключа.

Пока что делаю:

terraform-instances.tf

resource "openstack_compute_keypair_v2" "tf-keypair" {
  name       = "${var.openstack_keypair}"
  public_key = "${file("~/.ssh/id_rsa.pub")}"
}

resource "openstack_compute_instance_v2" "k8s-master" {
  name      = "k8s-master"
  region    = "${var.openstack_region}"
  image_id  = "${var.openstack_image_id}"
  flavor_id = "${var.openstack_flavor_id}"
  key_pair  = "${var.openstack_keypair}"
  depends_on = ["openstack_compute_keypair_v2.tf-keypair"]

  network {
    uuid = "00000000-0000-0000-0000-000000000000"
    name = "public"
  }
  network {
    uuid = "11111111-1111-1111-1111-111111111111"
    name = "private"
  }
}

resource "null_resource" "authkeys" {
  depends_on = ["openstack_compute_instance_v2.k8s-master"]
  provisioner "file" {
    source      = "authorized_keys"
    destination = "/home/ubuntu/.ssh/authorized_keys"
    }

  connection {
    host        = "${openstack_compute_instance_v2.k8s-master.network.0.fixed_ip_v4}"
    type        = "ssh"
    user        = "root"
    private_key = "${file("~/.ssh/id_rsa")}"
    timeout     = "45s"
    }
}

Итак, после запуска:

terraform apply 

Экземпляр создан с моим ssh-ключом для пользователя root, но не для пользователя ubuntu.

Как я могу развернуть свой ssh-ключ для пользователя ubuntu?

3 ответа

Возможно, это не самое элегантное решение, но оно работает. Я в основном запускаю сценарий, переданный с помощьюuser_data. Это позволяет мне загружать несколько открытых ключей, которые я сохраняю в виде списка переменных.

      resource "openstack_compute_instance_v2" "my_instance" {
  name         = "my_instance_name"
  flavor_id    = var.flavor_id_compute
  image_id     = var.image_id
  ...
  security_groups = [var.security_group_name]
  user_data = <<-EOF
    #!/bin/bash
    echo "${join("\n", var.ssh_public_keys)}" > /tmp/authorized_keys
    sudo mv /tmp/authorized_keys /home/ubuntu/.ssh/authorized_keys
    sudo chown ubuntu:ubuntu /home/ubuntu/.ssh/authorized_keys
    sudo chmod 600 /home/ubuntu/.ssh/authorized_keys
    echo "###" > /tmp/authorized_keys
  EOF
}

Тогда в моемvariables.tfфайл у меня есть:

      variable "ssh_public_keys" {
  description = "List of SSH public keys"
  type        = list(string)
  default     = [
    "ssh-rsa xxxxxxxxxxxxx user1”,
    "ssh-rsa xxxxxxxxxxxxx user2”,
    # Add more keys as needed
  ]
}

Вы можете использовать для этого Ansible или scp/ssh. Самый простой способ получить доступ по SSH — позволить Terraform создать пару ключей, а затем использовать закрытый ключ, который хранится в файле tfstate. Фрагмент Terraform для создания пары ключей (которая у вас есть):

      # create a keypair - note priv key will and should be in state file
resource "openstack_compute_keypair_v2" "keypair" {
    name = "keypair"
}

Тогда можно выловить это так:

      jq .resources[].instances[].attributes.private_key terraform.tfstate | awk '{gsub(/\\n/,"\n")}1' | sed -e '/^null/d' -e 's/"//g'  > id_rsa.pem

Затем Ansible можно запустить с опцией --key-file следующим образом:

      ansible-playbook -i inventory.yml playbook.yml --key-file id_rsa.pem

Поскольку вы говорите, что доступ пользователя root работает, вы можете просто запустить ansible и/или scp, чтобы скопировать файлы в папку пользователя ubuntu и использовать для них команду 0600 / chmod ubuntu.

Пример:

      scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /home/ubuntu/.ssh/id_rsa /home/ubuntu/.ssh/id_rsa.pub  root@192.168.10.10:/home/ubuntu/

ansible 192.168.10.10-host-in-inventory -b --become-user root -m shell -a "chown ubuntu file1 file2 && chmod 0600 file1 file2" -i inventory.yml

Вероятно, вам нужно создать файл инвентаризации, который вы можете найти в документации ansible.

Я бы посоветовал использовать cloud-init, поскольку в openstack нет ничего встроенного (и он буквально использует сам cloud-init для предварительного заполнения ключа).

Другие вопросы по тегам