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 phần mềm, 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 cơ sở hạ tầng 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 phần cứng 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-exec
và local-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 count
và 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.
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 all
vì hosts
, 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.
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-exec
và remote-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_location
và public_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.
Đ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.
.