Ansible 新手入門:實作以 Vagrant 建立主機並安裝 Nginx 的範例

什麼是 Ansible?

Ansible 是 Red Hat 公司的 IT 自動化工具產品;Ansible 基於 PythonYaml 格式的設定檔案,可以用於同時管理大量的主機。Ansible 的運作方式是透過 SSH 至遠端機器後,蒐集狀態並且執行特定的腳本,因為是使用程式定義,所以可確保所有的遠端的機器狀態可以達到一致,可排除每台機器狀態不同的複雜度問題。類似的工具有 Chef, Puppet。

如何安裝 Ansible

你可以透過 Python 的套件管理工具 pip 安裝 Ansible,此文撰寫時最新的版本為 2.9,你會需要 Python 3.8 以上才能安裝 Ansible。安裝的更多說明可以參考 Installing Ansible 文件。

如何開始使用 Ansible

開始使用 Ansible 的第一步是先定義有哪些機器可以連線,這些可以被連線的機器被稱呼為 Inventory。你可以透過 /etc/ansible/hosts 這個預設路徑的檔案定義,但大多數的情況你會期望不同的專案有不同的連線機器,此時你可以在專案底下撰寫 ansible.cfg 來指定 Inventory 的資料夾或是檔案路徑。設定 Inventory 你可以透過 YAML 格式檔案或是 ini 格式檔案,詳細的設定方法可以參考官方文件:How to build your inventory

Ansible 強大的地方在於他有許多內建好的模組 (Module),舉例來說當你設定好 Inventory 時,你可以直接透過 ansible all -m ping 指令來觸發 ping 模組測試是否可以連線到你設定的 Inventory 機器。我們可以將模組組合成一個腳本,在 Ansible 我們稱呼模組組成的腳本為 Playbook。這些 Playbook 會使用 Yaml 的形式撰寫,你可以使用 ansible-playbook 指令來執行它們。

什麼是 Vagrant

Vagrant 是 HashiCorp 公司的虛擬主機環境建置產品,它讓你可以很容易的管理虛擬機器環境,他可以與一些部署工具共同使用,例如 Ansible, Chef, Puppet...等

安裝 Vagrant

你可以在 Vagrant 的官方網站找到下載連結,如果你是使用 macOS 或是 Linux 環境,你可以透過作業系統上的套件管理工具例如 brew, deb, yum 來安裝 Vagrant 工具。因為 Vagrant 是依賴於其他工具建立虛擬環境,你會需要另外 VirtualBox 或是 VMware 才能夠讓它正常運作。

使用 Vagrant 建立虛擬主機

安裝完 Vagrant 後,首先第一步你可以使用 vagrant init hashicrop/bionic64 指令來建立 VagrantFile 並指示使用 hashicrop/bionic64 這個 box。在 Vagrant 的世界裡會稱呼映像檔為 box,可以到 Vagrant Cloud 瀏覽有哪些可以使用的 box,你也可以製作屬於你自己的 box。

稍微審視 VagrantFile 裡面的設定後,你接下來可以使用 vagrant up 來建立機器,第一次建立會需要花較多時間。相關的設定內容可以參考 VagrantFile 的說明文件。當機器運作起來後,你可以使用 vagrant ssh 指令來連線到虛擬主機上。

使用 Ansible 連線至 Vagrant 虛擬主機並安裝 Nginx

Nginx 是一個常見的網頁伺服器 (Web Server),預設會開啟 HTTP 80 Port 來提供網頁服務。我們這次的任務是在 Vagrant 建置好的虛擬主機上安裝 Nginx,然後透過本地主機端的瀏覽器來瀏覽 Nginx 提供的網頁。

首先我們要先修改 VagrantFile 中的 Port Forwarding 設定,讓虛擬主機內的 80 Port 暴露到本地主機端的 8080 (可依自己的需求設定)。

第二步我們需要撰寫未來要放置於虛擬主機上 Ngninx 的設定檔案 site.conf.j2 ,這邊的 j2 是 jinja template 的語法,讓我們可以帶入 Ansible 的變數。

server {
  listen 80;
  listen [::]:80;
  root /var/www/example.com;
  location / {
    try_files $uri $uri/ =404;
  }
}

第三步是撰寫安裝 Ngnix 的 Playbook

- hosts: web
  become: yes
  tasks:
  - name: "apt-get update"
    apt:
      update_cache: yes
      cache_valid_time: 3600

  - name: "install nginx"
    apt:
      name: ['nginx']
      state: latest

  - name: "create www directory"
    file:
      path: /var/www/example.com
      state: directory
      mode: '0775'
      owner: "{{ ansible_user }}"
      group: "{{ ansible_user }}"

  - name: delete default nginx site
    file:
      path: /etc/nginx/sites-enabled/default
      state: absent
    notify: restart nginx

  - name: copy nginx site.conf
    template:
      src: site.conf.j2
      dest: /etc/nginx/sites-enabled/example.com
      owner: root
      group: root
      mode: '0644'
    notify: restart nginx

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

第四步我們定義 inventory.yml

web:
  hosts:
    192.168.56.10
  vars:
    ansible_user: vagrant
    ansible_ssh_private_key_file: ~/.ssh/id_rsa

最後執行 ansible-playbook nginx.yaml -i inventory.yml 就可以完成安裝

本文的範例程式碼可以到 github 上進行瀏覽