:從基礎到批量管理服務器)
一、什么是 Ansible Playbook學習 Ansible 時我們通常使用 Ad-Hoc 臨時命令例如ansible all -i inventory.ini -m ping或者ansible k8s_cluster -i inventory.ini -m shell -a hostname這種方式適合執(zhí)行簡單、臨時的操作比如快速驗證某臺服務器的連通性或者臨時查看某個服務的運行狀態(tài)。它的優(yōu)點是輸入方便、反饋直接適合在排查問題時隨手使用。但是在真實運維工作中我們經(jīng)常需要執(zhí)行一系列固定操作例如安裝軟件修改配置文件啟動服務配置防火墻創(chuàng)建用戶分發(fā)文件重啟服務批量部署Kubernetes如果每次都手動輸入命令效率非常低。一方面命令一多就容易出錯比如漏掉某個步驟、寫錯參數(shù)另一方面這些操作往往需要在多臺服務器上重復執(zhí)行手動操作不僅耗時而且難以保證每臺機器的配置完全一致。這時候就需要使用Ansible Playbook。Playbook 本質上就是一個 YAML 格式的自動化腳本可以把多個運維操作寫成一個完整的執(zhí)行流程。它把“做什么”“在哪臺機器上做”“以什么權限做”都清晰地描述出來形成一份可讀、可復用、可版本管理的運維文檔。例如我們要在一批服務器上完成 nginx 的部署手動操作需要依次執(zhí)行以下步驟連接服務器 ↓ 安裝 nginx ↓ 啟動 nginx ↓ 設置開機自啟 ↓ 檢查 nginx 狀態(tài)這些操作都可以通過一個 Playbook 自動完成。只要寫好一次之后無論是對 3 臺還是 30 臺服務器都能一鍵批量執(zhí)行并且每次執(zhí)行的結果都是可預期的、一致的。簡單來說Ad-Hoc 命令適合“臨時、單次、簡單”的操作而 Playbook 適合“固定、重復、復雜”的運維流程。掌握了 Playbook就相當于把日常運維工作從“手動敲命令”升級為“編寫自動化腳本”這也是邁向自動化運維的第一步。二、Playbook 基本結構一個最簡單的 Playbook--- - name: Test Ansible Playbook hosts: all become: yes tasks: - name: Show hostname command: hostname保存為test.yml執(zhí)行ansible-playbook -i inventory.ini test.ymlPlaybook 結構說明--- - name: Test Ansible Playbook表示play的名稱主要用于描述這個 Playbook 的作用。hosts: all表示在哪些主機上執(zhí)行。例如hosts: all所有主機。hosts: k8s_cluster只在 Kubernetes 集群執(zhí)行。hosts: web_servers只在 Web 服務器組執(zhí)行。become: yes表示使用 sudo 提權。相當于sudo command例如普通用戶連接服務器ubuntu但是安裝軟件需要 root 權限。那么become: yes就非常重要。tasks:表示任務列表。一個 Playbook 可以包含多個任務。例如tasks: name: Task 1 command: hostname name: Task 2 command: uptimeAnsible 會按照順序執(zhí)行。三、第一個 Playbook 實戰(zhàn)進入 Ansible 工作目錄cd /root/ansible-k8s創(chuàng)建文件nano test.yml寫入--- - name: Test Playbook hosts: k8s_cluster become: yes tasks: - name: Show hostname command: hostname - name: Show system uptime command: uptime檢查語法ansible-playbook -i inventory.ini test.yml --syntax-check如果正確playbook: test.yml執(zhí)行ansible-playbook -i inventory.ini test.yml輸出類似PLAY [Test Playbook] TASK [Gathering Facts] ok: [k8s-master] ok: [k8s-node01] ok: [k8s-node02] TASK [Show hostname] changed: [k8s-master] changed: [k8s-node01] changed: [k8s-node02] PLAY RECAP k8s-master k8s-node01 k8s-node02說明三個節(jié)點都成功執(zhí)行任務。四、Playbook 與 Ad-Hoc 的區(qū)別Ad-Hoc例如ansible all -m shell -a systemctl restart nginx特點臨時執(zhí)行適合簡單任務不方便保存不適合復雜流程Playbook例如tasks: name: Install nginx apt: name: nginx state: present name: Start nginx service: name: nginx state: started特點可以保存??梢灾貜蛨?zhí)行支持多個任務支持變量支持條件判斷支持循環(huán)支持自動化部署實際生產(chǎn)環(huán)境中大部分自動化運維工作都會使用 Playbook。五、Playbook 常用模塊Ansible 的核心是模塊。常見模塊包括模塊作用command執(zhí)行命令shell執(zhí)行 Shell 命令copy復制文件file管理文件aptUbuntu 軟件管理yumCentOS 軟件管理service管理服務systemd管理 systemd 服務user管理用戶group管理用戶組debug輸出信息下面逐個介紹。六、command 模塊創(chuàng)建--- - name: Command Test hosts: k8s_cluster tasks: - name: Show hostname command: hostname執(zhí)行ansible-playbook -i inventory.ini command.yml等價于hostnamecommand 不支持 Shell 特性例如command: ls /tmp | grep nginx可能無法正常執(zhí)行。因為|屬于 Shell 管道。這時候需要使用shell:七、shell 模塊例如--- - name: Shell Test hosts: k8s_cluster become: yes tasks: - name: Check nginx image shell: ctr -n k8s.io images list | grep nginx || true這里|是 Shell 管道。|| true表示即使 grep 沒找到 nginx也不要讓任務失敗。command 與 shell 的區(qū)別commandcommand: hostname適合簡單命令。shellshell: ps aux | grep nginx適合管道重定向變量Shell 語法八、debug 模塊debug 用于輸出信息。例如--- - name: Debug Test hosts: k8s_cluster tasks: - name: Show hostname command: hostname register: hostname_result - name: Print hostname debug: msg: {{ hostname_result.stdout }}執(zhí)行后會輸出k8s-master k8s-node01 k8s-node02九、register 注冊變量Ansible 可以把任務執(zhí)行結果保存到變量。例如- name: Check hostname command: hostname register: result這里result保存了命令執(zhí)行結果。查看- name: Show result debug: var: result輸出可能包含changed: true stdout: k8s-master stderr: rc: 0常用返回值stdout標準輸出{{ result.stdout }}stdout_lines按行輸出{{ result.stdout_lines }}rc返回值{{ result.rc }}例如0通常表示成功。十、copy 模塊copy 用于復制文件。例如--- - name: Copy File hosts: k8s_cluster become: yes tasks: - name: Copy nginx config copy: src: nginx.conf dest: /etc/nginx/nginx.conf結構Ansible 控制節(jié)點 ↓ copy ↓ 遠程服務器十一、file 模塊file 模塊可以管理文件目錄權限軟鏈接例如創(chuàng)建目錄- name: Create directory file: path: /opt/test state: directory創(chuàng)建文件- name: Create file file: path: /opt/test/test.txt state: touch刪除文件- name: Delete file file: path: /opt/test/test.txt state: absent十二、apt 模塊Ubuntu 使用apt:安裝 nginx--- - name: Install nginx hosts: k8s_cluster become: yes tasks: - name: Update apt cache apt: update_cache: yes - name: Install nginx apt: name: nginx state: present執(zhí)行ansible-playbook -i inventory.ini install-nginx.yml十三、service 模塊用于管理服務。啟動 nginx- name: Start nginx service: name: nginx state: started停止- name: Stop nginx service: name: nginx state: stopped重啟- name: Restart nginx service: name: nginx state: restarted開機自啟- name: Enable nginx service: name: nginx enabled: yes十四、完整 Nginx 自動部署 Playbook下面是一個完整案例。創(chuàng)建nano nginx.yml內(nèi)容--- - name: Install and Configure Nginx hosts: k8s_cluster become: yes tasks: - name: Update apt cache apt: update_cache: yes - name: Install nginx apt: name: nginx state: present - name: Start nginx service: name: nginx state: started enabled: yes - name: Check nginx status shell: systemctl is-active nginx register: nginx_status - name: Show nginx status debug: msg: Nginx status: {{ nginx_status.stdout }}執(zhí)行ansible-playbook -i inventory.ini nginx.yml整個流程更新軟件源 ↓ 安裝 nginx ↓ 啟動 nginx ↓ 設置開機自啟 ↓ 檢查 nginx 狀態(tài) ↓ 輸出結果十五、when 條件判斷when 可以實現(xiàn)條件執(zhí)行。例如- name: Only run on master command: hostname when: inventory_hostname k8s-master那么只有k8s-master會執(zhí)行。node01 和 node02 會跳過。Kubernetes 場景例如- name: Pull image on master command: ctr -n k8s.io images pull nginx:latest when: inventory_hostname k8s-master只有 Master 節(jié)點執(zhí)行。十六、循環(huán) loop例如批量安裝軟件- name: Install packages apt: name: {{ item }} state: present loop: - nginx - curl - vim相當于apt install nginx apt install curl apt install vim但是通過 Ansible 自動批量完成。十七、Playbook 冪等性這是 Ansible 最重要的特點之一。例如apt: name: nginx state: present第一次執(zhí)行changed安裝 nginx。第二次執(zhí)行ok因為 nginx 已經(jīng)存在。這叫冪等性意思是同一個 Playbook 執(zhí)行多次最終結果保持一致。例如第一次執(zhí)行 → 安裝 nginx 第二次執(zhí)行 → 不重復安裝 第三次執(zhí)行 → 不重復安裝這非常適合自動化運維。十八、handlers配置改變后重啟服務例如修改 nginx 配置- name: Copy nginx config copy: src: nginx.conf dest: /etc/nginx/nginx.conf notify: - Restart nginx然后handlers: name: Restart nginx service: name: nginx state: restarted完整結構--- - name: Configure nginx hosts: k8s_cluster become: yes tasks: - name: Install nginx apt: name: nginx state: present - name: Copy nginx config copy: src: nginx.conf dest: /etc/nginx/nginx.conf notify: - Restart nginx handlers: - name: Restart nginx service: name: nginx state: restarted只有配置文件發(fā)生變化時Restart nginx才會執(zhí)行。十九、實際 Kubernetes 自動化案例前面我們已經(jīng)使用 Ansible 管理 Kubernetes 集群。例如檢查所有節(jié)點鏡像ansible -i inventory.ini k8s_cluster -m shell -a sudo ctr -n k8s.io images list也可以寫成 Playbook。創(chuàng)建nano check-images.yml內(nèi)容--- - name: Check Kubernetes Images hosts: k8s_cluster become: yes tasks: - name: Check containerd images shell: ctr -n k8s.io images list register: image_list - name: Show images debug: var: image_list.stdout_lines執(zhí)行ansible-playbook -i inventory.ini check-images.yml這樣以后只需要執(zhí)行ansible-playbook check-images.yml就可以自動檢查整個 Kubernetes 集群。二十、常用命令檢查 Playbook 語法ansible-playbook -i inventory.ini nginx.yml --syntax-check查看執(zhí)行計劃ansible-playbook -i inventory.ini nginx.yml --check執(zhí)行 Playbookansible-playbook -i inventory.ini nginx.yml詳細輸出ansible-playbook -i inventory.ini nginx.yml -v更詳細ansible-playbook -i inventory.ini nginx.yml -vvv二十一、推薦目錄結構說明inventory.ini服務器清單。playbooks/存放自動化任務。files/存放需要分發(fā)的文件。templates/存放 Jinja2 模板。roles/存放大型模塊化自動化項目。二十二、總結通過本篇文章我們學習了 Ansible Playbook 的基礎知識。對于 Linux 運維工程師來說Playbook 是必須掌握的技能。因為真實生產(chǎn)環(huán)境通常幾十臺服務器統(tǒng)一配置統(tǒng)一部署統(tǒng)一更新統(tǒng)一檢查Ansible Playbook 正是實現(xiàn)這種批量自動化運維的重要工具。