快轉到主要內容
  1. Posts/

Ansible持續集成與持續部署

DevOps Automation Ansible CI/CD DevOps Shell Git SSH Automation
目錄

在現代 DevOps 流程中,利用自動化工具來實現持續集成和持續部署(CI/CD)是提升開發效率的關鍵。Ansible 作為一個強大的配置管理工具,不僅可以簡化伺服器的配置,還能幫助我們輕鬆實現程式碼的部署。本文將介紹如何配置 Ansible ,以及使用 Ansible 將本地程式碼上傳到 Git 並部署到遠端伺服器。

程式範例
#

https://github.com/a607ernie/ansible_demo.git

Ansible 安裝與測試
#

步驟 1:安裝 Ansible
#

首先,你需要在本地機器上安裝 Ansible。你可以透過以下命令進行安裝:

在 Ubuntu 上安裝:

sudo apt update
sudo apt install ansible

在 MacOS 上安裝:

brew install ansible

步驟 2:設置 SSH 連接
#

Ansible 需要能夠透過 SSH 連接到遠端伺服器。為了避免每次執行 Ansible 任務時都要手動輸入密碼,我們需要先確保本地機器與遠端伺服器之間建立了 SSH 信任關係。

  • 使用以下命令生成 SSH 金鑰(如果還沒有):
  • 使用 SSH 將本地機器的公鑰傳送到遠端伺服器:
  • 完成上述步驟後,你應該可以無密碼地透過 SSH 連接到遠端伺服器。

步驟 3:準備 Ansible 清單文件
#

在 Ansible 中,需要創建一個清單文件來指定目標伺服器。這個文件包含你的遠端伺服器的 IP 或主機名稱。這是清單文件的範例:

  • inventory.ini
# 測試
[test_servers]
172.22.15.2  ansible_user=admin ansible_ssh_pass=changeme ansible_port=22 ansible_ssh_extra_args='-o StrictHostKeyChecking=no'

# 其他範例格式參考
[web_servers]
111.11.11.1  ansible_user=user1 ansible_ssh_pass=pass ansible_port=22 # 第一個主機
web2.example.com  ansible_user=admin # 第二個主機

接著 ping 遠端主機,測試配置是否正確

ansible -i inventory.ini test_servers -m ping

若回傳以下訊息,則表示成功

172.22.15.2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong" # 有ping到
}

步驟 4:建立測試的 Ansible Playbook
#

接下來,需要創建一個 Ansible Playbook 來定義部署任務。這是測試能否顯示遠端 硬碟容量 的 Playbook 範例:

  • hello.yml
---
- name: Play with Ansible
  hosts: test_servers
  # become: yes
  # become_user: root
  # become_method: sudo
  # hosts: localhost
  tasks:
     - name: Just execute df -h
       ansible.builtin.command: df -h
       register: output
       changed_when: output.rc == 0

     - name: Show stdout
       ansible.builtin.debug:
         msg: "{{ output.stdout_lines }}"

這段 Ansible Playbook 主要是執行兩個任務:

  • 執行 df -h 命令並註冊結果
  • 顯示 df -h 的標準輸出

步驟 5:執行 Ansible Playbook
#

現在,你已經準備好執行 Playbook 了。使用以下命令來運行它:

ansible-playbook -i inventory.ini hello.yml

這段 Playbook 會連接到 test_servers 主機,執行 df -h 命令以查看磁碟空間使用情況,並將結果顯示出來

設定 Ansible : 部署本地程式碼到遠端伺服器
#

在開始部署之前,我們需要先設定好相關的配置文件。這些配置文件將定義我們的 Git 儲存庫資訊、目標伺服器以及部署路徑。首先,讓我們從設定 Git 儲存庫資訊開始。

設定Git 儲存庫資訊
#

repositories_vars.yaml

repositories:
  - name: ansible_demo
    url: https://github.com/a607ernie/ansible_demo.git
    branch: master
    user: admin  # 替換為遠端電腦的使用者名稱

指定要部署的目標伺服器及其對應目錄路徑
#

hosts_vars/web_server.yml

web_servers_git_path:
  vars:
    NEED_TO_CHANGE_THIS_git_repo_name: # git repo name , e.g. hello_git
      REMOTE_HOST_IP: remote folder path # e.g. 111.11.11.1: /home/Documents/repo/

e.g.

web_servers_git_path:
  vars:
    ansible_demo:
      11.111.111.11: /home/admin/Documents/ansible_demo/
      # 可以加入更多主機

建立一個部署到遠端伺服器的 Ansible Playbook
#

這是將本地程式碼上傳到 Git 並部署到遠端伺服器的 Playbook 範例

deploy.yml

---
- name: Git pull with Ansible
  hosts: test_servers #可改,對應inventory.ini
  # hosts: localhost

  vars_files:
    - ./repositories_vars.yml
    - ./hosts_vars/web_servers.yml
  vars:
    git_repo: "{{ lookup('vars', selected_repo) }}"
    
  # become: yes
  # become_user: root
  # become_method: sudo

  tasks:
    - name: Choose repo
      set_fact:
        git_repo: "{{ item }}"
      loop: "{{ repositories }}"
      when: item.name == "{{ selected_repo }}"

    - name: Get path of remote host
      set_fact:
        dest_path: "{{ vars.web_servers_git_path.vars[git_repo.name][inventory_hostname] }}"

    - name: Show the repo name
      debug:
        msg: "{{ git_repo }}"

    - name: Check if destination path exists
      stat:
        path: "{{ dest_path }}"
      register: dest_path_stat

    - name: Clone the repository if the path does not exist
      git:
        repo: "{{ git_repo.url }}"
        dest: "{{ dest_path }}"
        version: "{{ git_repo.branch }}"
      when: not dest_path_stat.stat.exists

    - name: Fetch remote updates and prune old references
      command: git fetch --prune origin
      args:
        chdir: "{{ dest_path }}"
      when: dest_path_stat.stat.exists

    - name: Ensure local branch tracks remote branch
      command: git branch --set-upstream-to=origin/{{ git_repo.branch }} {{ git_repo.branch }}
      args:
        chdir: "{{ dest_path }}"
      when: dest_path_stat.stat.exists

    - name: Reset local branch to match remote
      command: git reset --hard origin/{{ git_repo.branch }}
      args:
        chdir: "{{ dest_path }}"
      when: dest_path_stat.stat.exists

    - name: Clean untracked files
      command: git clean -fd
      args:
        chdir: "{{ dest_path }}"
      when: dest_path_stat.stat.exists

    - name: Pull the latest changes from remote
      git:
        repo: "{{ git_repo.url }}"
        dest: "{{ dest_path }}"
        version: "{{ git_repo.branch }}"
        update: yes
      when: dest_path_stat.stat.exists
      register: git_result

    - name: Show git module output
      debug:
        msg: "Git module output: {{ git_result }}"

這段 Playbook 會將你的 Git 儲存庫複製到遠端伺服器的指定位置,然後運行一個部署腳本來完成部署。

執行部署到遠端伺服器的 Ansible Playbook
#

這條命令會將本地程式碼從 Git 儲存庫 clone 到遠端伺服器並執行部署腳本。

ansible-playbook -i inventory.ini deploy.yml --extra-vars "selected_repo=YOUR_GIT_REPO_NAME"

e.g.

ansible-playbook -i inventory.ini deploy.yml --extra-vars "selected_repo=ansible_demo"

結論
#

利用 Ansible 來自動化部署過程,你不僅能提高效率,還能減少手動操作的錯誤。無論是部署到一台伺服器還是多台伺服器,Ansible 都能幫助你輕鬆管理和擴展基礎設施。

Ernie
作者
Ernie

相關文章

GitHub Actions 自動化工作流程
DevOps GitHub Python GitHub Actions CI/CD Python 爬蟲 PTT Slack Automation
學習如何使用 GitHub Actions 自動化你的工作流程,包含設定、執行和最佳實務。
GitHub Webhook 自動化程式碼部署教學
DevOps GitHub Python Flask GitHub Webhook 自動化 部署 Python Flask Git SSH
設定 GitHub Webhook 自動拉取最新程式碼並部署到伺服器。
GitLab SSH Key 設定教學:安全又快速的 Git 操作
Git GitLab GitLab SSH 版本控制 Git
此文章提供 GitLab SSH Key 的檢查、建立與新增教學,讓你的 Git 操作更安全、順暢。