Saturday, November 23, 2024

[Terraform] Lesson 21 – Packer and Terraform

-

1. Khái niệm về Packer and Terraform?

Packer và Terraform là hai công cụ mã nguồn mở được phát triển bởi HashiCorp để quản lý hạ tầng.

Packer là một công cụ để tạo ra các image máy ảo có thể tái sử dụng trên nhiều nền tảng khác nhau, như AWS, Azure, VMware, Docker, v.v. Packer cho phép tạo ra các image chuẩn, đảm bảo tính nhất quán cho toàn bộ hạ tầng và giảm thiểu thời gian cấu hình thủ công.

Terraform là một công cụ để tạo ra và quản lý cơ sở hạ tầng dưới dạng mã (Infrastructure as Code). Terraform hỗ trợ nhiều nhà cung cấp đám mây và hạ tầng khác nhau, bao gồm AWS, Azure, Google Cloud Platform, VMware, v.v. Terraform cho phép người dùng xây dựng hạ tầng một cách dễ dàng, đảm bảo tính nhất quán và khả năng tái sử dụng.

Packer và Terraform có thể được sử dụng cùng nhau để tạo ra các image chuẩn và sau đó sử dụng các image này để triển khai hạ tầng bằng Terraform. Điều này giúp tăng tính nhất quán và giảm thiểu thời gian cấu hình thủ công trong quá trình triển khai và quản lý hạ tầng.

2. Tại sao phải sử dụng Packer với Terraform?

Có một số lý do quan trọng để sử dụng kết hợp Packer và Terraform:

  • Quản lý hạ tầng dễ dàng hơn: Khi sử dụng cả Packer và Terraform, người dùng có thể tạo ra các image của hệ điều hành và cấu hình máy ảo một lần và sau đó sử dụng chúng để tạo ra các máy chủ một cách đồng nhất trên nhiều môi trường khác nhau. Điều này giúp giảm thiểu lỗi và tăng tính nhất quán của hạ tầng.
  • Tích hợp hoàn hảo: Packer và Terraform đều là các công cụ được phát triển bởi HashiCorp và được thiết kế để tương tác với nhau một cách mượt mà. Điều này cho phép người dùng tạo ra các image từ Packer và sau đó sử dụng chúng như một phần của cấu hình hạ tầng được quản lý bởi Terraform.
  • Quản lý và triển khai mã dễ dàng hơn: Sử dụng kết hợp Packer và Terraform cho phép người dùng quản lý tất cả mã của họ trong một nơi duy nhất. Điều này giúp cho việc triển khai và quản lý hạ tầng dễ dàng hơn bằng cách tận dụng tính linh hoạt của Terraform và khả năng đóng gói của Packer.
  • Tối ưu hóa thời gian triển khai: Sử dụng Packer để tạo ra các image đồng nhất và sau đó sử dụng Terraform để triển khai chúng giúp tối ưu hóa thời gian triển khai của hạ tầng. Các image được tạo bởi Packer có thể được sử dụng để triển khai các máy chủ mới trong vòng vài phút bằng cách sử dụng Terraform.
  • Tăng tính đáng tin cậy của hạ tầng: Bằng cách sử dụng kết hợp Packer và Terraform, người dùng có thể tạo ra các image đồng nhất và chắc chắn rằng các máy chủ được triển khai từ các image này đều có cùng một cấu hình và các phần mềm cần thiết. Điều này giúp tăng tính đáng tin cậy và giảm thiểu lỗi cho hạ tầng.

3. Các lưu ý khi kết hợp Packer với Terraform.

Dưới đây là một số lưu ý khi sử dụng Packer trong Terraform:

  • Tách biệt việc xây dựng và triển khai hệ thống: Packer là công cụ để xây dựng các image, còn Terraform là công cụ để triển khai hệ thống sử dụng các image này. Vì vậy, cần phải tách biệt giữa quá trình xây dựng và triển khai.
  • Sử dụng file variables để quản lý các biến: Sử dụng các file variables để quản lý các biến giúp việc triển khai trở nên dễ dàng và linh hoạt hơn. Các biến có thể được sử dụng để cấu hình các khối xây dựng, nhưng cũng có thể được sử dụng để truyền các thông số cho các khối provisioning.
  • Sử dụng cấu hình được định nghĩa trước (immutable infrastructure): Packer cho phép xây dựng các image không thay đổi, điều này giúp đảm bảo tính nhất quán và dễ quản lý của hệ thống. Khi một thay đổi được thực hiện, image mới sẽ được xây dựng và triển khai.
  • Sử dụng các khối provisioner: Packer hỗ trợ nhiều khối provisioner để cấu hình các hệ thống. Các khối này có thể được sử dụng để cài đặt phần mềm, cấu hình mạng, và thực hiện các tác vụ khác trên hệ thống.
  • Sử dụng các file shell script để quản lý các công việc phức tạp: Các file shell script có thể được sử dụng để thực hiện các công việc phức tạp, như cài đặt và cấu hình các ứng dụng, hoặc đặt các giá trị cấu hình.
  • Cập nhật thường xuyên các image: Các image được xây dựng sẽ cần được cập nhật thường xuyên để đảm bảo tính bảo mật và ổn định của hệ thống.
  • Sử dụng các plugin bổ sung: Packer hỗ trợ nhiều plugin để mở rộng khả năng của nó. Các plugin này có thể được sử dụng để tích hợp với các công cụ và dịch vụ khác như AWS, Docker, VMware, v.v.
  • Kiểm tra cấu hình trước khi triển khai: Trước khi triển khai hệ thống, cần phải kiểm tra cấu hình của các image để đảm bảo tính đúng đắn và đảm bảo an toàn cho hệ thống. Có thể sử dụng các công cụ như Packer để tạo ra các image chuẩn để triển khai hệ thống.
  • Sử dụng công cụ quản lý cấu hình: Các công cụ quản lý cấu hình như Ansible, Chef, Puppet, hoặc SaltStack có thể được sử dụng để cài đặt và cấu hình các ứng dụng và dịch vụ trên các máy ảo hoặc máy chủ vật lý.
  • Giám sát và điều tra sự cố: Hệ thống cần phải được giám sát để phát hiện các sự cố và điều chỉnh trước khi chúng gây ra tác hại cho hệ thống. Có thể sử dụng các công cụ như Prometheus, Grafana hoặc Zabbix để giám sát hệ thống.
  • Xác thực và phân quyền: Đảm bảo rằng chỉ các người dùng có quyền truy cập mới có thể truy cập vào các tài nguyên của hệ thống. Các công cụ quản lý xác thực và phân quyền như Vault có thể được sử dụng để quản lý quyền truy cập cho hệ thống.
  • Quản lý dịch vụ: Các dịch vụ cần phải được quản lý và theo dõi để đảm bảo tính khả dụng và độ tin cậy của hệ thống. Có thể sử dụng các công cụ quản lý dịch vụ như Consul hoặc etcd để quản lý dịch vụ trên hệ thống.
  • Đảm bảo an toàn và bảo mật: Cần đảm bảo rằng hệ thống được bảo mật và an toàn. Các công cụ quản lý bảo mật như Vault có thể được sử dụng để quản lý các chứng chỉ và bí mật trong hệ thống. Ngoài ra, cần đảm bảo rằng hệ thống được bảo vệ chống lại các cuộc tấn công mạng và các lỗ hổng bảo mật.

4. Cú pháp khai báo Packer khi kết hợp với Terraform.

Để sử dụng Packer kết hợp với Terraform, cần có cấu trúc thư mục như sau:

packer/
  packer.json
terraform/
  main.tf
  variables.tf

Trong đó, file packer.json chứa cấu hình cho Packer và file main.tfvariables.tf chứa cấu hình cho Terraform.

Trong file main.tf, ta sử dụng provider null_resource để đọc output từ Packer và sử dụng đó để triển khai các resources bằng Terraform.

5. Ưu điểm và nhược điểm khi kết hợp Packer với Terraform.

Kết hợp Packer và Terraform là một cách hiệu quả để triển khai các hệ thống phức tạp trên đám mây hoặc trên môi trường địa phương. Dưới đây là một số ưu điểm và nhược điểm của việc kết hợp Packer và Terraform:

Ưu điểm:

  • Tính đồng nhất: Packer và Terraform sử dụng cùng một mã nguồn để triển khai hệ thống, giúp đảm bảo tính đồng nhất trong quá trình triển khai và giảm thiểu các lỗi liên quan đến sự khác biệt giữa các môi trường.
  • Tăng tốc quá trình triển khai: Khi kết hợp Packer và Terraform, bạn có thể tạo ra các image AMI, Docker hoặc Vagrant box có sẵn, từ đó giảm thiểu thời gian cài đặt, cấu hình và triển khai hệ thống.
  • Dễ dàng quản lý cấu hình: Việc kết hợp Packer và Terraform giúp bạn quản lý cấu hình hệ thống một cách dễ dàng. Bạn có thể sử dụng Packer để tạo ra các image cơ bản và sử dụng Terraform để triển khai và quản lý các tài nguyên của hệ thống.
  • Giảm thiểu sự phát triển lặp lại: Sử dụng Packer và Terraform giúp giảm thiểu sự phát triển lặp lại của mã nguồn. Bạn chỉ cần tạo một bản định nghĩa cấu hình hệ thống duy nhất và sử dụng nó cho mọi môi trường.

Nhược điểm:

  • Một trong những nhược điểm khi kết hợp Packer với Terraform là quá trình triển khai sẽ trở nên chậm hơn. Việc sử dụng Packer và Terraform cùng nhau tạo ra sự phức tạp trong việc triển khai vì cả hai công cụ đều phải thực hiện các bước độc lập nhau để triển khai.
  • Ngoài ra, việc kết hợp Packer và Terraform cũng có thể gây ra sự nhầm lẫn trong quản lý tài nguyên và phiên bản. Vì cả hai công cụ đều có thể tạo ra các tài nguyên giống nhau, việc quản lý và theo dõi chúng có thể trở nên phức tạp.
  • Cuối cùng, sử dụng Packer và Terraform cùng nhau có thể đòi hỏi một số kiến thức chuyên sâu để triển khai hiệu quả. Vì vậy, nếu không có đội ngũ kỹ thuật đủ trình độ, việc triển khai có thể gặp khó khăn.

6. Các ví dụ cụ thể.

– Ví dụ sử dụng Packer với Terraform với hệ thống AWS.

Để minh họa việc sử dụng Packer với Terraform trong môi trường AWS, ta có thể tạo một AMI (Amazon Machine Image) bằng Packer, sau đó sử dụng AMI này trong Terraform để tạo ra một EC2 instance.

Dưới đây là ví dụ về file Packer và file Terraform để tạo ra một EC2 instance với AMI đã được tạo bởi Packer.

Ví dụ Packer:

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "us-east-1",
      "source_ami_filter": {
        "filters": {
          "virtualization-type": "hvm",
          "name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
          "root-device-type": "ebs"
        },
        "owners": ["099720109477"],
        "most_recent": true
      },
      "instance_type": "t2.micro",
      "ssh_username": "ubuntu",
      "ami_name": "ubuntu-xenial-16.04-amd64-server-{{timestamp}}",
      "tags": {
        "Name": "ubuntu-xenial-16.04-amd64-server"
      }
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "sleep 30",
        "sudo apt-get update",
        "sudo apt-get -y install apache2",
        "sudo service apache2 start"
      ]
    }
  ]
}

Trong ví dụ này, ta định nghĩa một builder để tạo AMI với các thông số sau:

  • Region: us-east-1
  • Source AMI filter: Chọn AMI có nameubuntu/images/*ubuntu-xenial-16.04-amd64-server-*owners là Amazon. Lấy AMI mới nhất.
  • Instance type: t2.micro
  • SSH username: ubuntu
  • AMI name: Đặt tên AMI là ubuntu-xenial-16.04-amd64-server-{{timestamp}} để đảm bảo tính duy nhất.
  • Tags: Đánh dấu AMI với tên ubuntu-xenial-16.04-amd64-server.

Sau khi tạo ra AMI, ta sẽ sử dụng AMI này để tạo một EC2 instance bằng file Terraform.

Ví dụ Terraform:

provider "aws" {
  region = "us-east-1"
}

data "aws_ami" "ubuntu" {
  filter {
    name   = "name"
    values = ["ubuntu-xenial-16.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  most_recent = true
  owners      = ["099720109477"]
}

resource "aws_instance" "example" {
  ami           = "${data.aws_ami.ubuntu.id}"
  instance_type = "t2.micro"

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get -y install apache2",
      "sudo service apache2 start"
    ]
  }

  tags = {
    Name = "example-instance"
  }
}

Trong ví dụ trên, chúng ta sử dụng Packer để tạo ra một AMI có sẵn Apache và PHP trên một base image của Amazon Linux 2. Sau đó, chúng ta sử dụng Terraform để triển khai một instance EC2 từ AMI đã tạo và cài đặt cấu hình web server Apache và PHP.

Để sử dụng kết hợp Packer với Terraform, cần khai báo một số thông tin chung như AWS region, access key, secret key, ami_id (được tạo bởi Packer) trong file terraform.tfvars hoặc thông qua các biến môi trường. Ngoài ra, cần cung cấp các khai báo cụ thể cho từng công cụ.

Với Packer, chúng ta sẽ cần tạo file json để định nghĩa các builders, provisioners và các khai báo khác để tạo ra image mong muốn. Trong khi đó, với Terraform, chúng ta sẽ cần khai báo các tài nguyên EC2, khai báo các security group và các biến khác để triển khai môi trường.

Khi sử dụng kết hợp Packer và Terraform, cần đảm bảo rằng cấu hình của từng công cụ phù hợp với nhau và không gây ra xung đột trong quá trình triển khai. Ngoài ra, cần lưu ý đến việc quản lý mã nguồn và phiên bản để đảm bảo tính ổn định và dễ dàng bảo trì trong tương lai.

– Ví dụ sử dụng Packer với Terraform với hệ thống KVM.

Để sử dụng Packer kết hợp với Terraform trên hệ thống KVM, ta cần thực hiện các bước sau:

Bước 1: Tạo file ubuntu-20.04-amd64.json để cấu hình Packer như sau:

{
    "variables": {
        "memory": "1024",
        "vcpus": "1",
        "disk_size": "20000",
        "ssh_username": "ubuntu",
        "kvm_type": "qemu"
    },
    "builders": [{
        "type": "qemu",
        "iso_url": "http://releases.ubuntu.com/20.04.3/ubuntu-20.04.3-live-server-amd64.iso",
        "iso_checksum_type": "sha256",
        "iso_checksum": "aa73b8d2a61391603f5c70a5fc5c5f6163c9aeb5e431b0e5081d857ec3b81c4c",
        "boot_wait": "5s",
        "headless": false,
        "accelerator": "{{user `kvm_type`}}",
        "disk_size": "{{user `disk_size`}}",
        "memory": "{{user `memory`}}",
        "vcpus": "{{user `vcpus`}}",
        "network_interface": "nat",
        "ssh_username": "{{user `ssh_username`}}",
        "ssh_password": "password",
        "ssh_port": 22,
        "ssh_wait_timeout": "15m",
        "shutdown_command": "sudo shutdown -P now"
    }],
    "provisioners": [{
        "type": "shell",
        "inline": [
            "sleep 30",
            "sudo apt-get update",
            "sudo apt-get install -y nginx",
            "sudo systemctl enable nginx",
            "sudo systemctl start nginx"
        ]
    }],
    "post-processors": [{
        "type": "vagrant",
        "output": "output-{{.Provider}}-{{.BuildName}}-{{.BuildType}}"
    }]
}

Bước 2: Tạo file kvm.tf để cấu hình Terraform như sau:

provider "libvirt" {
  uri = "qemu:///system"
}

data "libvirt_image" "ubuntu" {
  name = "ubuntu-20.04"
}

data "libvirt_pool" "default" {
  name = "default"
}

data "libvirt_network" "default" {
  name = "default"
}

resource "libvirt_volume" "volume" {
  name      = "test-vm.img"
  pool_name = data.libvirt_pool.default.name
  capacity  = "1G"
}

resource "libvirt_domain" "vm" {
  name   = "test-vm"
  memory = 1024
  vcpu   = 1

  network_interface {
    network_name = data.libvirt_network.default.name
  }

  disk {
    volume_id = libvirt_volume.volume.id
  }

  console {
    type        = "pty"
    target_type = "serial"
    target_port = "0"
  }

  graphics {
    type            = "spice"
    listen_type     = "address"
    listen_address  = "0.0.0.0"
  }

  cloudinit {
    user_data = "#cloud-config\n\npassword: password\nchpasswd: { expire: False }\nssh_pwauth: True\n"
  }

  depends_on = [
    libvirt_volume.volume,
  ]

  provisioner "file" {
    source      = "${path.module}/cloud-init.yaml"
    destination = "/tmp/cloud-init.yaml"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt-get update -y",
      "sudo apt-get install -y cloud-init",
      "sudo cloud-init init",
      "sudo cloud-init modules --mode config",
      "sudo cloud-init modules --mode final",
    ]
  }
}

output "vm_ip_address" {
  value = libvirt_domain.vm.network_interface.0.addresses.0
}

Sau khi đã tạo xong các file cấu hình Packer và Terraform, để triển khai image với KVM, ta thực hiện các bước sau:

  • Kiểm tra lại các file cấu hình Packer và Terraform xem có lỗi không.
  • Chạy Packer để build image KVM và lưu image vào KVM pool.
$ packer build -var-file=packer/variables.json packer/kvm.json
  • Kiểm tra image đã được tạo thành công trong KVM pool:
$ virsh vol-list default
  • Tạo workspace mới trong Terraform để triển khai máy ảo từ image KVM vừa tạo.
terraform workspace new kvm
  • Chạy lệnh terraform init để khởi tạo môi trường Terraform.
terraform init
  • Chạy lệnh terraform apply để triển khai máy ảo từ image KVM đã tạo.
terraform apply

Sau khi các bước trên được thực hiện thành công, máy ảo KVM sẽ được triển khai từ image đã build bằng Packer và được quản lý bởi Terraform.

– Ví dụ sử dụng Packer với Terraform với hệ thống vCenter.

Đây là một ví dụ cơ bản về việc sử dụng Packer và Terraform cùng nhau để tạo ra một image và triển khai nó trên hệ thống vCenter:

  • Tạo một file packer.json để định nghĩa cấu hình cho Packer:
{
  "builders": [{
    "type": "vmware-iso",
    "iso_url": "http://iso.example.com/ubuntu-20.04-server-amd64.iso",
    "iso_checksum_type": "sha256",
    "iso_checksum": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "vcenter_server": "vcenter.example.com",
    "username": "user",
    "password": "password",
    "insecure_connection": "true",
    "vm_name": "ubuntu-20.04",
    "guest_os_type": "ubuntu-64",
    "disk_size": "40000",
    "network_adapters": [{
      "network": "VM Network"
    }]
  }],
  "provisioners": [{
    "type": "shell",
    "script": "bootstrap.sh"
  }],
  "post-processors": [{
    "type": "vsphere",
    "host": "vcenter.example.com",
    "username": "user",
    "password": "password",
    "insecure_connection": "true",
    "datacenter": "dc1",
    "cluster": "cluster1",
    "resource_pool": "pool1",
    "folder": "packer-images",
    "vm_name": "ubuntu-20.04",
    "overwrite": "true"
  }]
}
  • Tạo một file bootstrap.sh để cài đặt các phần mềm cần thiết trên image:
#!/bin/bash
sudo apt-get update
sudo apt-get install -y nginx
  • Chạy lệnh sau để tạo image sử dụng Packer:
packer build packer.json
  • Tạo một file terraform.tf để định nghĩa cấu hình cho Terraform:
provider "vsphere" {
  user           = "user"
  password       = "password"
  vsphere_server = "vcenter.example.com"
  allow_unverified_ssl = true
}

data "vsphere_datacenter" "dc" {
  name = "dc1"
}

data "vsphere_datastore" "ds" {
  name          = "datastore1"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network_interface" "nic" {
  name          = "VM Network"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine_template" "template" {
  name          = "ubuntu-20.04"
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "vm" {
  name             = "ubuntu-20.04"
  resource_pool_id = "pool1"
  datastore_id     = data.vsphere_datastore.ds.id

  network_interface {
    network_id   = data.vsphere_network_interface.nic.network_id
    adapter_type = "vmxnet3"
  }

  clone {
    template_uuid = data.vsphere_virtual_machine_template.template.template_uuid
  }

  provisioner "file" {
    source      = "index.html"
    destination = "/var/www/html/index.html"
    connection {
      type     = "ssh"
      user     = "ubuntu"
      password = "ubuntu"
      host     = "${self.default_ip_address}"
    }
  }
}

provisioner "remote-exec" {
  inline = [
  "sudo apt-get update",
  "sudo apt-get install -y nginx",
  "sudo systemctl enable nginx",
  "sudo systemctl start nginx"
  ]
  connection {
      type = "ssh"
      user = "ubuntu"
      password = "ubuntu"
      host = "${self.default_ip_address}"
    }
}

connection {
    type = "ssh"
    user = "ubuntu"
    password = "ubuntu"
    host = "${self.default_ip_address}"
  }
}
  • Chạy lệnh sau để triển khai máy ảo sử dụng Terraform:
terraform init
terraform apply

Lưu ý rằng trong ví dụ này, file index.html được sử dụng để kiểm tra việc cài đặt nginx trên máy ảo. Nếu thành công, file này sẽ được chuyển đến máy ảo và được đặt trong thư mục /var/www/html/. Bạn có thể sử dụng trình duyệt web để truy cập vào máy ảo và kiểm tra rằng nginx đã được cài đặt và hoạt động đúng cách.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories