Cách sử dụng Ansible với Terraform để quản lý cấu hình

Tác giả đã chọn Quỹ Nguồn mở và Miễn phí để nhận một khoản đóng góp như một phần của chương trình Viết cho DO donate.

Giới thiệu

Ansible là một công cụ quản lý cấu hình thực thi sách chơi, là danh sách các hành động có thể tùy chỉnh được viết bằng YAML trên các máy chủ mục tiêu được chỉ định. Nó có thể thực hiện tất cả các hoạt động khởi động, như cài đặt và cập nhật , tạo và xóa người dùng cũng như cấu hình các dịch vụ hệ thống. Do đó, nó phù hợp để đưa lên các máy chủ mà bạn triển khai bằng Terraform, được tạo trống theo mặc định.

Ansible và Terraform không phải là các giải pháp cạnh tranh, vì chúng giải quyết các giai đoạn khác nhau của và triển khai phần mềm. Terraform cho phép bạn xác định và tạo cơ sở hạ tầng của hệ thống, bao gồm mà các ứng dụng của bạn sẽ chạy trên đó. Ngược lại, Ansible định cấu hình và triển khai phần mềm bằng cách thực thi các sách phát của nó trên các phiên bản máy chủ được cung cấp. Chạy Ansible trên các tài nguyên Terraform được cung cấp trực tiếp sau khi tạo cho phép bạn làm cho các tài nguyên có thể sử dụng được cho trường hợp sử dụng của mình nhanh hơn nhiều. Nó cũng cho phép bảo trì và khắc phục sự cố dễ dàng hơn, bởi vì tất cả các máy chủ đã triển khai sẽ có các hành động giống nhau được áp dụng cho chúng.

Trong hướng dẫn này, bạn sẽ triển khai Droplets bằng Terraform và ngay sau khi tạo, bạn sẽ khởi động Droplets bằng Ansible. Bạn sẽ gọi Ansible trực tiếp từ Terraform khi một tài nguyên triển khai. Bạn cũng sẽ tránh giới thiệu các điều kiện cuộc đua bằng cách sử dụng Terraform's remote-execlocal-exec các điều khoản dự phòng trong cấu hình của bạn, điều này sẽ đảm bảo rằng việc triển khai Droplet được hoàn tất đầy đủ trước khi bắt đầu thiết lập thêm.

Điều kiện tiên quyết

Ghi chú: Hướng dẫn này đã được thử nghiệm cụ thể với Terraform 1.0.2.

Bước 1 – Xác định giọt

Trong bước này, bạn sẽ xác định các Droplets mà sau đó bạn sẽ chạy một playbook Ansible, sẽ thiết lập máy chủ web Apache.

Giả sử bạn đang ở trong terraform-ansible thư mục mà bạn đã tạo như một phần của điều kiện tiên quyết, bạn sẽ xác định tài nguyên Droplet, tạo ba bản sao của nó bằng cách chỉ định countvà xuất địa chỉ IP của chúng. Bạn sẽ lưu trữ các định nghĩa trong một tệp có tên droplets.tf. Tạo và mở nó để chỉnh sửa bằng cách chạy:

Add the following lines:

~/terraform-ansible/droplets.tf

resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "web-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"

  ssh_keys = [
      data.digitalocean_ssh_key.terraform.id
  ]
}

output "droplet_ip_addresses" {
  value = {
    for droplet in digitalocean_droplet.web:
    droplet.name => droplet.ipv4_address
  }
}

Tại đây, bạn xác định tài nguyên Droplet chạy Ubuntu 18.04 với RAM 1GB trên lõi CPU trong khu vực fra1. Terraform sẽ kéo khóa SSH mà bạn đã xác định trong điều kiện tiên quyết từ tài khoản của bạn và thêm nó vào Droplet được cấp phép với phần tử danh sách ID duy nhất được chỉ định được chuyển vào ssh_keys. Terraform sẽ triển khai Droplet ba lần vì count tham số được thiết lập. Khối đầu ra theo sau nó sẽ hiển thị địa chỉ IP của ba giọt. Vòng lặp đi qua danh sách các giọt và đối với mỗi trường hợp, ghép tên của nó với địa chỉ IP của nó và gắn nó vào bản đồ kết quả.

Lưu và đóng tệp khi bạn hoàn tất.

Bây giờ bạn đã xác định các Droplets mà Terraform sẽ triển khai. Trong bước tiếp theo, bạn sẽ viết một playbook Ansible sẽ thực thi trên từng giọt trong số ba Giọt được triển khai và sẽ triển khai máy chủ web Apache. Sau đó, bạn sẽ quay lại mã Terraform và thêm tích hợp với Ansible.

Bước 2 - Viết một Playbook Ansible

Bây giờ bạn sẽ tạo một playbook Ansible thực hiện các tác vụ thiết lập máy chủ ban đầu, chẳng hạn như tạo người dùng mới và nâng cấp các gói đã cài đặt. Bạn sẽ hướng dẫn Ansible những việc cần làm bằng cách viết nhiệm vụ, là các đơn vị hành động được thực thi trên các máy chủ đích. Các tác vụ có thể sử dụng các chức năng cài sẵn hoặc chỉ định các lệnh tùy chỉnh để chạy. Bên cạnh các tác vụ cho thiết lập ban đầu, bạn cũng sẽ cài đặt máy chủ web Apache và kích hoạt mod_rewrite mô-đun.

Xem tiếp:   Cách ngăn Windows 10 mở lại các ứng dụng sau khi khởi động lại máy tính

Trước khi viết playbook, hãy đảm bảo rằng các khóa SSH công khai và riêng tư của bạn, tương ứng với khóa trong tài khoản DigitalOcean của bạn, có sẵn và có thể truy cập được trên máy mà bạn đang chạy Terraform và Ansible. Một vị trí điển hình để lưu trữ chúng trên Linux sẽ là ~/.ssh (mặc dù bạn có thể lưu trữ chúng ở những nơi khác).

Ghi chú: Trên Linux, bạn cần đảm bảo rằng tệp khóa riêng có các quyền thích hợp. Bạn có thể đặt chúng bằng cách chạy:

  • chmod 600 your_private_key_location

Bạn đã xác định một biến cho khóa riêng tư, vì vậy bạn chỉ cần thêm một biến cho vị trí khóa công khai.

Mở ra provider.tf để chỉnh sửa bằng cách chạy:

Add the following line:

~/terraform-ansible/provider.tf

terraform {
  required_providers {
    digitalocean = {
      source = "digitalocean/digitalocean"
      version = "~> 2.0"
    }
  }
}

variable "do_token" {}
variable "pvt_key" {}
variable "pub_key" {}

provider "digitalocean" {
  token = var.do_token
}

data "digitalocean_ssh_key" "terraform" {
  name = "terraform"
}

Khi bạn hoàn tất, hãy lưu và đóng tệp.

Với pub_key hiện đã được xác định, bạn sẽ bắt đầu viết playbook Ansible. Bạn sẽ lưu trữ nó trong một tệp có tên là apache-install.yml. Tạo và mở nó để chỉnh sửa:

You'll be building the playbook gradually. First, you'll need to define on which hosts the playbook will run, its name, and if the tasks should be run as root. Add the following lines:

~/terraform-ansible/apache-install.yml

- become: yes
  hosts: all
  name: apache-install

Bằng cách thiết lập become đến yes, bạn hướng dẫn Ansible chạy các lệnh với tư cách là superuser và bằng cách chỉ định allhosts, bạn cho phép Ansible chạy các tác vụ trên bất kỳ máy chủ nhất định nào — thậm chí cả những tác vụ được chuyển qua dòng lệnh, như Terraform làm.

Tác vụ đầu tiên mà bạn sẽ thêm sẽ tạo một người dùng mới, không phải root. Nối định nghĩa nhiệm vụ sau vào sổ chơi của bạn:

~ / terraform-ansible / apache-install.yml

  tasks:
    - name: Add the user 'sammy' and add it to 'sudo'
      user:
        name: sammy
        group: sudo

Trước tiên, bạn xác định một danh sách các nhiệm vụ và sau đó thêm một nhiệm vụ vào đó. Nó sẽ tạo một người dùng có tên sammy và cấp cho họ quyền truy cập siêu người dùng bằng cách sử dụng sudo bằng cách thêm chúng vào nhóm thích hợp.

Tác vụ tiếp theo sẽ thêm khóa SSH công khai của bạn vào người dùng, vì vậy bạn sẽ có thể kết nối với khóa này sau này:

~ / terraform-ansible / apache-install.yml

    - name: Add SSH key to 'sammy'
      authorized_key:
        user: sammy
        state: present
        key: "{{ lookup('file', pub_key) }}"

Tác vụ này sẽ đảm bảo rằng khóa SSH công khai, được tra cứu từ một tệp cục bộ, là present vào mục tiêu. Bạn sẽ cung cấp giá trị cho pub_key biến từ Terraform trong bước tiếp theo.

Bây giờ bạn có thể đặt hàng cài đặt Apache và mod_rewrite mô-đun bằng cách thêm các nhiệm vụ sau:

~ / terraform-ansible / apache-install.yml

    - name: Wait for apt to unlock
      become: yes
      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;

    - name: Install apache2
      apt:        
        name: apache2
        update_cache: yes
        state: latest

    - name: Enable mod_rewrite
      apache2_module:
        name: rewrite
        state: present
      notify:
        - Restart apache2

  handlers:
    - name: Restart apache2
      service:
      name: apache2
      state: restarted

Nhiệm vụ đầu tiên sẽ đợi cho đến khi cài đặt gói trước đó bằng cách sử dụng apt trình quản lý gói đã hoàn tất. Nhiệm vụ thứ hai sẽ chạy apt để cài đặt Apache. Sau đó, cái thứ ba sẽ đảm bảo rằng mod_rewrite mô-đun là present. Sau khi nó được kích hoạt, bạn cần đảm bảo rằng bạn khởi động lại Apache mà bạn không thể cấu hình từ chính tác vụ. Để giải quyết vấn đề đó, bạn gọi một trình xử lý để yêu cầu khởi động lại.

Xem tiếp:   Cách triển khai nhiều môi trường trong dự án Terraform của bạn mà không cần mã trùng lặp

Tại thời điểm này, playbook của bạn sẽ giống như sau:

~ / terraform-ansible / apache-install.yml

- become: yes
  hosts: all
  name: apache-install
  tasks:
    - name: Add the user 'sammy' and add it to 'sudo'
      user:
        name: sammy
        group: sudo

    - name: Add SSH key to 'sammy'
      authorized_key:
        user: sammy
        state: present
        key: "{{ lookup('file', pub_key) }}"

    - name: Wait for apt to unlock
      become: yes
      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;

    - name: Install apache2
      apt:
        name: apache2
        update_cache: yes
        state: latest

    - name: Enable mod_rewrite
      apache2_module:
        name: rewrite 
        state: present
      notify:
        - Restart apache2

  handlers:
    - name: Restart apache2
      service:
        name: apache2
        state: restarted

Khi bạn hoàn tất, hãy kiểm tra xem các thụt lề của tất cả các phần tử YAML có chính xác và khớp với các phần tử được hiển thị ở trên hay không. Đây là tất cả những gì bạn cần xác định ở phía Ansible, vì vậy hãy lưu và đóng playbook. Bây giờ bạn sẽ sửa đổi mã triển khai Droplet để thực thi playbook này khi Droplet đã cấp phép xong.

Bước 3 - Chạy Ansible trên các giọt đã triển khai

Bây giờ bạn đã xác định các hành động mà Ansible sẽ thực hiện trên các máy chủ mục tiêu, bạn sẽ sửa đổi cấu hình Terraform để chạy nó khi tạo Droplet.

Terraform cung cấp hai trình điều khiển thực thi các lệnh: local-execremote-exec, chạy các lệnh cục bộ hoặc từ xa (trên mục tiêu), tương ứng. remote-exec yêu cầu dữ liệu kết nối, chẳng hạn như loại và khóa truy cập, trong khi local-exec mọi thứ trên máy Terraform đang thực thi và do đó không yêu cầu thông tin kết nối. Điều quan trọng cần lưu ý là local-exec chạy ngay lập tức sau khi tài nguyên bạn đã định nghĩa nó đã hoàn tất cấp phép; do đó, nó không đợi tài nguyên thực sự khởi động. Nó chạy sau khi nền tảng đám mây thừa nhận sự hiện diện của nó trong hệ thống.

Bây giờ bạn sẽ thêm các định nghĩa cấp phép vào Droplet của mình để chạy Ansible sau khi triển khai. Mở ra droplets.tf để chỉnh sửa:

Add the highlighted lines:

~/terraform-ansible/droplets.tf

resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "web-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"

  ssh_keys = [
      data.digitalocean_ssh_key.terraform.id
  ]

  provisioner "remote-exec" {
    inline = ["sudo apt update", "sudo apt install python3 -y", "echo Done!"]

    connection {
      host        = self.ipv4_address
      type        = "ssh"
      user        = "root"
      private_key = file(var.pvt_key)
    }
  }

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u root -i '${self.ipv4_address},' --private-key ${var.pvt_key} -e 'pub_key=${var.pub_key}' apache-install.yml"
  }
}

output "droplet_ip_addresses" {
  value = {
    for droplet in digitalocean_droplet.web:
    droplet.name => droplet.ipv4_address
  }
}

Giống như Terraform, Ansible chạy cục bộ và kết nối với các máy chủ mục tiêu thông qua SSH. Để chạy nó, bạn xác định một local-exec điều khoản trong định nghĩa Droplet chạy ansible-playbook chỉ huy. Điều này được chuyển vào tên người dùng (nguồn gốc), IP của Giọt hiện tại (được truy xuất bằng ${self.ipv4_address}), khóa công khai và riêng tư SSH và chỉ định tệp playbook để chạy (apache-install.yml). Bằng cách thiết lập ANSIBLE_HOST_KEY_CHECKING biến môi trường thành False, bạn bỏ qua việc kiểm tra xem máy chủ đã được kết nối trước đó chưa.

Như đã lưu ý, local-exec Provisioner chạy mà không cần đợi Droplet khả dụng, vì vậy việc thực thi playbook có thể xảy ra trước tính khả dụng thực tế của Droplet. Để khắc phục điều này, bạn xác định remote-exec điều khoản để chứa các lệnh để thực thi trên máy chủ đích. Vì remote-exec để thực thi, máy chủ đích phải có sẵn. Từ remote-exec chạy trước local-exec, máy chủ sẽ được khởi tạo hoàn toàn vào thời điểm Ansible được gọi. python3 được cài đặt sẵn trên Ubuntu 18.04, vì vậy bạn có thể nhận xét hoặc xóa lệnh nếu cần.

Khi bạn thực hiện xong các thay đổi, hãy lưu và đóng tệp.

Sau đó, triển khai Droplets bằng cách chạy lệnh sau. Nhớ thay private_key_locationpublic_key_location với các vị trí của khóa riêng tư và khóa công khai của bạn tương ứng:

  • terraform apply -var "do_token=${DO_PAT}" -var "pvt_key=private_key_location" -var "pub_key=public_key_location"

Đầu ra sẽ dài. Droplets của bạn sẽ cung cấp và sau đó kết nối sẽ thiết lập với mỗi. Tiếp theo remote-exec người cung cấp sẽ thực thi và cài đặt python3:

Output

... digitalocean_droplet.web[1] (remote-exec): Connecting to remote host via SSH... digitalocean_droplet.web[1] (remote-exec): Host: ... digitalocean_droplet.web[1] (remote-exec): User: root digitalocean_droplet.web[1] (remote-exec): Password: false digitalocean_droplet.web[1] (remote-exec): Private key: true digitalocean_droplet.web[1] (remote-exec): Certificate: false digitalocean_droplet.web[1] (remote-exec): SSH Agent: false digitalocean_droplet.web[1] (remote-exec): Checking Host Key: false digitalocean_droplet.web[1] (remote-exec): Connected! ...

Sau đó, Terraform sẽ chạy local-exec điều khoản cho mỗi giọt, thực thi Ansible. Kết quả sau cho thấy điều này cho một trong các giọt:

Output

... digitalocean_droplet.web[2] (local-exec): Executing: ["/bin/sh" "-c" "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u root -i 'ip_address,' --private-key private_key_location -e 'pub_key=public_key_location' apache-install.yml"] digitalocean_droplet.web[2] (local-exec): PLAY [apache-install] ********************************************************** digitalocean_droplet.web[2] (local-exec): TASK [Gathering Facts] ********************************************************* digitalocean_droplet.web[2] (local-exec): ok: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Add the user 'sammy' and add it to 'sudo'] ******************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Add SSH key to 'sammy''] ******************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Update all packages] ***************************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Install apache2] ********************************************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Enable mod_rewrite] ****************************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): RUNNING HANDLER [Restart apache2] ********************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): PLAY RECAP ********************************************************************* digitalocean_droplet.web[2] (local-exec): [ip_address] : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ...

Ở cuối đầu ra, bạn sẽ nhận được danh sách ba giọt và địa chỉ IP của chúng:

Output

droplet_ip_addresses = { "web-0" = "..." "web-1" = "..." "web-2" = "..." }

Bây giờ bạn có thể điều hướng đến một trong các địa chỉ IP trong trình duyệt của mình. Bạn sẽ đến trang chào mừng Apache mặc định, báo hiệu việc cài đặt thành công máy chủ web.

Xem tiếp:   Các trường hợp không gõ được tiếng Việt trên windows và cách khắc phục.

Trang chào mừng của Apache

Điều này có nghĩa là Terraform đã cấp phép máy chủ của bạn và sách vở Ansible của bạn được thực thi trên đó thành công.

Để kiểm tra xem khóa SSH đã được thêm đúng vào sammy trên Droplets được cung cấp, hãy kết nối với một trong số chúng bằng lệnh sau:

  • ssh -i private_key_location sammy@droplet_ip_address

Hãy nhớ nhập vị trí khóa riêng tư và địa chỉ IP của một trong những giọt được cấp phép, bạn có thể tìm thấy những thứ này trong đầu ra Terraform của mình.

Đầu ra sẽ giống như sau:

Output

Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-121-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of ... System load: 0.0 Processes: 88 Usage of /: 6.4% of 24.06GB Users logged in: 0 Memory usage: 20% IP address for eth0: ip_address Swap usage: 0% IP address for eth1: ip_address 0 packages can be updated. 0 updates are security updates. New release '20.04.1 LTS' available. Run 'do-release-upgrade' to upgrade to it. *** System restart required *** Last login: ... ...

Bạn đã kết nối thành công với mục tiêu và có được quyền truy cập trình bao cho sammy người dùng, xác nhận rằng khóa SSH đã được định cấu hình chính xác cho người dùng đó.

Bạn có thể phá hủy các giọt đã triển khai bằng cách chạy lệnh sau, nhập yes khi được nhắc:

  • terraform destroy -var "do_token=${DO_PAT}" -var "pvt_key=private_key_location" -var "pub_key=public_key_location"

Trong bước này, bạn đã thêm vào thực thi sách vở Ansible dưới dạng local-exec người cung cấp định nghĩa Droplet của bạn. Để đảm bảo rằng máy chủ có sẵn cho các kết nối, bạn đã bao gồm remote-exec Provisioner, có thể dùng để cài đặt python3 điều kiện tiên quyết, sau đó Ansible sẽ chạy.

Phần kết luận

Terraform và Ansible cùng nhau tạo thành một quy trình làm việc linh hoạt để quay các máy chủ với cấu hình phần cứng và phần mềm cần thiết. Chạy trực tiếp Ansible như một phần của quá trình triển khai Terraform cho phép bạn thiết lập và khởi động các máy chủ với các phụ thuộc cho công việc phát triển và ứng dụng của bạn nhanh hơn nhiều.

Hướng dẫn này là một phần của loạt bài Cách Quản lý Cơ sở hạ tầng với Terraform. Loạt bài này bao gồm một số chủ đề về Terraform, từ việc cài đặt Terraform lần đầu tiên đến quản lý các dự án phức tạp.

Bạn cũng có thể tìm thấy các nguồn nội dung Ansible bổ sung trên trang chủ đề Ansible của chúng tôi.

.

Check Also

Cách cung cấp các ứng dụng Flask với Gunicorn và Nginx trên Ubuntu

Giới thiệu Trong hướng dẫn này, bạn sẽ xây dựng một ứng dụng Python bằng …