用Terraform进行局部试验

Dav*_*wer 16 terraform

我们正在研究Terraform作为管理基础设施的一种方式,它看起来非常有趣.

但是,目前我们的公司代理/防火墙terraform apply由于安全限制而导致失败.

在我们等待解决这些网络问题的同时,有什么方法可以在本地试验Terraform而无需连接到Azure或AWS?也许有Virtual Box?

Exa*_*a37 13

在我们等待解决这些网络问题的同时,有什么方法可以让我在本地试验 Terraform 而无需连接到 Azure 或 AWS?也许使用Virtual Box?

我使用 KVM 来拥有尽可能多的虚拟机,因为我需要玩任何东西,我现在正在学习 Terraform,但具体目的是自动创建这些虚拟机。

因此,如果您正在寻找一个本地主机游乐场来学习 Terraform,那么 KVM 是一种很好且更轻量级的方法,然后使用其他重型虚拟化技术,例如您提到的 Virtualbox。

如果您想在使用 AWS 和 Azure 提供商的同时学习 Terraform,那么这对您来说不是一个好的解决方案,否则就试一试。

安装 KVM

首先你需要在你的 Linux 机器上安装 KVM。

sudo apt update &&  sudo apt upgrade
Run Code Online (Sandbox Code Playgroud)

检查系统是否支持硬件虚拟化:

$ egrep -c ‘(svm|vmx)’ /proc/cpuinfo
4
Run Code Online (Sandbox Code Playgroud)

输出要大一些0,否则需要进入Bios开启VT技术。

检查是否支持 KVM 加速:

安装工具:

sudo apt install cpu-checker
Run Code Online (Sandbox Code Playgroud)

检查:

$ sudo kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

Run Code Online (Sandbox Code Playgroud)

安装 KVM

sudo apt install qemu qemu-kvm libvirt-bin  bridge-utils  virt-manager
Run Code Online (Sandbox Code Playgroud)

检查正在运行:

service libvirtd status
Run Code Online (Sandbox Code Playgroud)

如果没有运行:

sudo service libvirtd start && sudo update-rc.d libvirtd enable
Run Code Online (Sandbox Code Playgroud)

另一个检查:

sudo virsh -c qemu:///system list

Run Code Online (Sandbox Code Playgroud)

如何使用 Terraform 在 KVM 中创建 VM

我们将使用此KVM Libvirt Provider创建 VM 。

mkdir playground && cd playground
Run Code Online (Sandbox Code Playgroud)

地形主文件

创建文件main.tf

################################################################################
# ENV VARS
################################################################################

# https://www.terraform.io/docs/commands/environment-variables.html

variable "VM_COUNT" {
  default = 3
  type = number
}

variable "VM_USER" {
  default = "developer"
  type = string
}

variable "VM_HOSTNAME" {
  default = "vm"
  type = string
}

variable "VM_IMG_URL" {
  default = "https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img"
  type = string
}

variable "VM_IMG_FORMAT" {
  default = "qcow2"
  type = string
}

variable "VM_CIDR_RANGE" {
  default = "10.10.10.10/24"
  type = string
}


################################################################################
# PROVIDERS
################################################################################

# instance the provider
provider "libvirt" {
  uri = "qemu:///system"
}


################################################################################
# DATA TEMPLATES
################################################################################

# https://www.terraform.io/docs/providers/template/d/file.html

# https://www.terraform.io/docs/providers/template/d/cloudinit_config.html
data "template_file" "user_data" {
  template = file("${path.module}/cloud_init.cfg")
  vars = {
    VM_USER = var.VM_USER
  }
}

data "template_file" "network_config" {
  template = file("${path.module}/network_config.cfg")
}


################################################################################
# RESOURCES
################################################################################

resource "libvirt_pool" "vm" {
  name = "${var.VM_HOSTNAME}_pool"
  type = "dir"
  path = "/tmp/terraform-provider-libvirt-pool-ubuntu"
}

# We fetch the latest ubuntu release image from their mirrors
resource "libvirt_volume" "vm" {
  count  = var.VM_COUNT
  name   = "${var.VM_HOSTNAME}-${count.index}_volume.${var.VM_IMG_FORMAT}"
  pool   = libvirt_pool.vm.name
  source = var.VM_IMG_URL
  format = var.VM_IMG_FORMAT
}

# Create a public network for the VMs
resource "libvirt_network" "vm_public_network" {
   name = "${var.VM_HOSTNAME}_network"
   mode = "nat"
   domain = "${var.VM_HOSTNAME}.local"
   addresses = ["${var.VM_CIDR_RANGE}"]
   dhcp {
    enabled = true
   }
   dns {
    enabled = true
   }
}

# for more info about paramater check this out
# https://github.com/dmacvicar/terraform-provider-libvirt/blob/master/website/docs/r/cloudinit.html.markdown
# Use CloudInit to add our ssh-key to the instance
# you can add also meta_data field
resource "libvirt_cloudinit_disk" "cloudinit" {
  name           = "${var.VM_HOSTNAME}_cloudinit.iso"
  user_data      = data.template_file.user_data.rendered
  network_config = data.template_file.network_config.rendered
  pool           = libvirt_pool.vm.name
}

# Create the machine
resource "libvirt_domain" "vm" {
  count  = var.VM_COUNT
  name   = "${var.VM_HOSTNAME}-${count.index}"
  memory = "1024"
  vcpu   = 1

  cloudinit = "${libvirt_cloudinit_disk.cloudinit.id}"

  # TODO: Automate the creation of public network
  network_interface {
    network_id = "${libvirt_network.vm_public_network.id}"
    #network_id = "6d8e2494-835d-4baf-a14f-3a5c705febcc"
    #network_name = "vm_docker_network"
    network_name = "${libvirt_network.vm_public_network.name}"
  }

  # IMPORTANT
  # Ubuntu can hang is a isa-serial is not present at boot time.
  # If you find your CPU 100% and never is available this is why.
  #
  # This is a known bug on cloud images, since they expect a console
  # we need to pass it:
  # https://bugs.launchpad.net/cloud-images/+bug/1573095
  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  console {
    type        = "pty"
    target_type = "virtio"
    target_port = "1"
  }

  disk {
    volume_id = "${libvirt_volume.vm[count.index].id}"
  }

  graphics {
    type        = "spice"
    listen_type = "address"
    autoport    = true
  }
}


################################################################################
# TERRAFORM CONFIG
################################################################################

terraform {
  required_version = ">= 0.12"
}

Run Code Online (Sandbox Code Playgroud)

环境变量

您可以设置 env vars 以覆盖该ENV VARS部分中定义的变量的任何默认值,但每个 env var 名称必须以 为前缀TF_VAR

export TF_VAR_VM_COUNT=5
Run Code Online (Sandbox Code Playgroud)

云初始化

创建文件cloud_init.cfg

#cloud-config
users:
  - name: ${VM_USER}
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: users, admin
    home: /home/${VM_USER}
    shell: /bin/bash
    ssh-authorized-keys:
      - ssh-rsa your-public-key-here
ssh_pwauth: True
disable_root: false
chpasswd:
  list: |
     ${VM_USER}:linux
  expire: False
package_update: true
package_upgrade: true
packages:
    - qemu-guest-agent
    - apt-transport-https
    - ca-certificates
    - curl
    - gnupg-agent
    - software-properties-common
    - zsh
growpart:
  mode: auto
  devices: ['/']
runcmd:
  - [ sh, -c, 'curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -' ]
  - [ sh, -c, 'sudo apt-key fingerprint 0EBFCD88']
  - [ sh, -c, 'sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"' ]
  - [ sh, -c, 'sudo apt update' ]
  - [ sh, -c, 'sudo apt install -y docker-ce docker-ce-cli containerd.io' ]
  - [ sh, -c, 'printf "\nalias dk=\"sudo docker\"\n" >> /home/${VM_USER}/.bashrc' ]
  - [ sh, -c, 'printf "\nalias dkc=\"sudo docker container\"\n" >> /home/${VM_USER}/.bashrc' ]
  - [ sh, -c, 'printf "\nalias dki=\"sudo docker image\"\n" >> /home/${VM_USER}/.bashrc' ]
  - [ sh, -c, 'printf "\nalias dks=\"sudo docker service\"\n" >> /home/${VM_USER}/.bashrc' ]
  - [ sh, -c, 'printf "\nalias dkn=\"sudo docker node\"\n" >> /home/${VM_USER}/.bashrc' ]

Run Code Online (Sandbox Code Playgroud)

注意:将您的公钥添加到文件中

网络配置

创建文件network_config.cfg

version: 2
ethernets:
  ens3:
     dhcp4: true
Run Code Online (Sandbox Code Playgroud)

运行 Terraform

初始化 Terraform:

terraform init
Run Code Online (Sandbox Code Playgroud)

创建虚拟机:

terraform apply
Run Code Online (Sandbox Code Playgroud)

VMS 的 IP 地址

获取每个 VM 的 ip:

virsh net-dhcp-leases vm_network
Run Code Online (Sandbox Code Playgroud)

注意:我们创建的虚拟机需要几秒钟才能获得 ip,因此您可能需要多次重复此命令,直到获得 ip。

现在只需使用您从virsh以下地址获得的 IP 地址通过 SSH 连接到其中一台虚拟机:

ssh developer@vm-ip-address
Run Code Online (Sandbox Code Playgroud)

玩得开心,享受你的新游乐场。


Fla*_*ito 10

熟悉Terraform擅长的一些方法(依赖管理,数据驱动配置,资源生命周期等)的一种方法是在工作站上使用null_resource配置器.这假设您对工作站有足够的控制权来获取Terraform(这在很多具有高安全性需求的地方非常困难).

通过使用Terraform的null_resource配置器,您可以习惯许多您将使用云的东西.如果你有你的工作站上安装码头工人的能力,你可以去真的远像个云,因为码头工人支持的工作站上的群模式.

例如,

resource "null_resource" "docker_swarm" {

    provisioner "local-exec" {
      command = "docker swarm init"
    }

    provisioner "local-exec" {
      command = <<EOF
        docker swarm leave --force

        # Careful here. This assumes you want a clean Docker slate,
        # remove all Docker volumes from your machine.
        docker volume rm -f $(docker volume ls -q) 
EOF
      when = "destroy"
    }
}

resource "null_resource" "start_stack" {

    provisioner "local-exec" {
      command = "docker stack deploy -c ./docker-stack.yml demostack"
    }

    provisioner "local-exec" {
      command = "docker stack rm demostack"
      when = "destroy"
    }

    depends_on = ["null_resource.docker_swarm"]
}
Run Code Online (Sandbox Code Playgroud)

在上面的简单示例中,您将了解如何管理生命周期.这里有一个很酷的部分:这正是你在AWS,Azure等中启动支持的Docker Swarm的方式,虽然它会有点复杂并需要更长的时间.

如果你没有Docker,我相信你可以想到你工作站上可能有的其他一些创建/破坏生命周期.

祝好运!恕我直言Terraform是我们的键盘最深刻的东西之一(Docker也在那里排名).

  • 很有意思。谢谢你,布莱恩。我将进一步研究所配置的 null_resource。 (2认同)

yda*_*coR 9

Terraform支持一大堆提供商,但绝大多数都是基于公共云的.

但是,您可以设置本地VMWare VSphere集群并使用VSphere提供程序与其进行交互以使您前进.如果要设置OpenStack集群,还有OpenStack的提供程序.

或者,您可以尝试使用类似HPE的Eucalyptus,它提供与AWS的API兼容性,但在内部部署.

也就是说,除非您已经有一个运行VMWare的数据中心,否则所有这些选项都非常糟糕,需要花费很多精力才能进行设置,这样您最好等待防火墙打开.

不幸的是,Virtualbox提供商的第一方实施方案不是很好,但您可以尝试使用第三方Virtualbox提供商.


Jam*_*den 6

如果您可以访问AWS/Azure,为什么不在那里创建一台机器?通过这种方式,您可以使用它来研究terraform,并在没有"no of department"限制的情况下学习它.

使用不同的提供商并不是一个好主意,因为一个提供商中的配置可能与另一个提供商的配置非常不同,甚至是对此问题的身份验证(AWS提供商可能是最佳起点)