ansible管理變量和事實

ansible管理變量和事實與實施任務控制

在 Ansible 中,變量和事實(Facts)就像給劇本(Playbook)配備的 “信息工具箱”,讓你的自動化配置管理更靈活、更智能。

變量:提前準備的 “預設信息”

變量就像你出門前準備的清單,提前可以提前預先定義好各種信息,用的時候直接拿出來用。

  • 怎么定義?

    • 在 Playbook 里直接寫

      :就像把清單貼在劇本首頁

      - hosts: webserversvars:app_port: 8080  # 定義應用端口變量app_name: "myapp"  # 定義應用名稱變量tasks:- name: 啟動應用command: "/opt/{{ app_name }}/start --port {{ app_port }}"
      
    • 單獨放變量文件

      :就像把清單放進文件夾,更整潔

      # vars/app_vars.yml
      app_port: 8080
      app_name: "myapp"
      

      然后在 Playbook 里引用:

      - hosts: webserversvars_files:- vars/app_vars.yml
      
    • 命令行傳變量

      :臨時改清單,比如臨時換個端口

      ansible-playbook deploy.yml -e "app_port=9090"
      
  • 變量的小技巧

    • 可以用{{ 變量名 }}在任務中調用,像插卡一樣靈活
    • 支持條件判斷,比如 “如果是生產環境,端口用 443;測試環境用 8080”

事實(Facts):自動收集的 “系統情報”

事實就像 Ansible 派出去的 “偵察兵”,會自動收集目標主機的信息(比如 IP 地址、操作系統、內存大小等),不用你手動問。

  • 怎么看收集到的情報?
    跑個命令讓偵察兵匯報:

    ansible webservers -m setup
    

    會得到一堆信息,比如:

    • ansible_facts['os_family']:操作系統類型(比如 RedHat、Debian)
    • ansible_facts['default_ipv4']['address']:主機 IP 地址
    • ansible_facts['memory_mb']['total']:總內存(MB)
  • 在 Playbook 里用事實
    比如根據操作系統選不同的安裝命令:

    - hosts: alltasks:- name: 安裝nginx(Debian系統)apt: name=nginx state=presentwhen: ansible_facts['os_family'] == "Debian"- name: 安裝nginx(RedHat系統)yum: name=nginx state=presentwhen: ansible_facts['os_family'] == "RedHat"
    
  • 小提示

    • 事實默認會自動收集,如果想關掉(比如加快執行速度),可以在 Playbook 里加gather_facts: no
    • 可以自定義事實(local facts),把自己關心的信息存到目標主機的/etc/ansible/facts.d/目錄,Ansible 會自動讀取

總結:變量 vs 事實

  • 變量:你主動告訴 Ansible 的信息(提前設定)
  • 事實:Ansible 主動從目標主機收集的信息(動態獲取)

兩者結合,就像給 Ansible 裝上了 “大腦”—— 既知道你提前安排的計劃,又能根據實際情況靈活調整,讓配置管理既聰明又高效~

管理 VARIABLES

變量簡介

ansible 利用變量來存儲數據,以便在Ansible項目文件中重復引用,有利于簡化項目的創建和維護,降低出錯率。我們在playbook中可以針對如用戶、軟件包、服務、文件等進行變量定義。

變量命名規則
  • 只能包含字母、數字和下劃線(如包含空格、點、$符號都為非法變量名)
  • 只能以字母開頭
變量范圍和優先級

ansible項目文件中多個位置支持定義變量,主要包含三個基本范圍:

  • Global scope:從命令行或 Ansible 配置設置的變量。
  • Play scope:在play和相關結構中設置的變量。
  • Host scope:由清單、事實(fact)收集或注冊的任務,在主機組和個別主機上設置的變量。

優先級從高到低順序:Global -> Play -> Host

在多個級別上定義了相同名稱的變量,則采用優先級別最高的變量。

Play scope

在 Ansible 里,“Play scope”(劇本作用域)可以理解為一個 Play(劇本)的 “管轄范圍” 和 “生效邊界”。它就像給這個 Play 劃了個圈,圈里的規則、變量、設置只在這個范圍內起作用,不會跑到圈外去影響其他 Play。

舉個生活例子:你家里有客廳和臥室兩個區域(相當于兩個 Play)。在客廳里你規定 “看電視音量不能超過 30”(這是客廳 Play 的變量 / 設置),這個規則只在客廳生效,到了臥室就不算數了 —— 這就是每個 Play 有自己獨立的 scope。

具體來說,Play scope 包含這些 “圈內要素”:

  • 目標主機:通過hosts指定的主機 / 主機組,只有這些主機受這個 Play 管理
  • 變量:在 Play 的varsvars_files里定義的變量,只在當前 Play 的任務中可用
  • 提權設置:當前 Play 里的become相關配置,不會影響其他 Play
  • 事實收集gather_facts的開關狀態,只控制當前 Play 是否收集主機信息

比如一個 Playbook 里有兩個 Play:

- name: 管理web服務器  # Play 1hosts: webserversvars:app: "nginx"  # 這個變量只在Play 1里有效tasks:- name: 安裝nginxyum: name={{ app }} state=present- name: 管理數據庫服務器  # Play 2hosts: dbserversvars:app: "mysql"  # 這個變量只在Play 2里有效tasks:- name: 安裝mysqlyum: name={{ app }} state=present

這里兩個 Play 的app變量互不干擾,因為它們各自有獨立的 scope。

簡單說,Play scope 就是 Ansible 里的 “楚河漢界”,讓每個 Play 在自己的地盤里按自己的規則干活,互不打擾~

vars 聲明

在 Ansible 中,vars就像給 Playbook 準備的 “變量口袋”,用來提前存放各種需要反復使用的信息。聲明變量的方式靈活多樣,就像你可以把東西放在口袋、抽屜或專門的收納盒里一樣。

1. 直接在 Play 里聲明(最直觀)

就像把常用物品直接揣在口袋里,隨用隨拿。在 Play 的vars塊里定義變量,只在當前 Play 中生效。

- name: 部署web應用hosts: webserversvars:app_name: "blog"       # 應用名稱app_port: 8080         # 運行端口max_connections: 100   # 最大連接數tasks:- name: 創建應用目錄file:path: "/opt/{{ app_name }}"  # 引用變量state: directory

2. 單獨放變量文件(更整潔)

如果變量太多,就像東西太多需要用抽屜分類收納。把變量寫在單獨的 YAML 文件里,再在 Playbook 中引用。

# 變量文件:vars/app_settings.yml
app_name: "blog"
app_port: 8080
db_host: "db.example.com"

在 Playbook 中調用這個文件:

- name: 部署web應用hosts: webserversvars_files:- vars/app_settings.yml  # 引入外部變量文件tasks:- name: 配置數據庫連接lineinfile:path: "/opt/{{ app_name }}/config.ini"line: "db_host = {{ db_host }}"

3. 命令行臨時聲明(應急用)

就像臨時從口袋里掏出個備用物品,適合臨時修改變量值,不用改 Playbook 本身。用-e參數傳遞:

# 臨時把端口改成9090運行
ansible-playbook deploy.yml -e "app_port=9090"

4. 主機 / 組變量(按目標分類)

如果不同主機需要不同變量(比如 web 服務器和數據庫服務器配置不同),可以在inventory目錄下創建專門的變量文件,Ansible 會自動對應。

目錄結構通常是這樣:

inventory/├── hosts                # 主機清單├── group_vars/          # 組變量(對整個組生效)│   ├── webservers.yml   # web服務器組的變量│   └── dbservers.yml    # 數據庫服務器組的變量└── host_vars/           # 主機變量(對單臺主機生效)└── web01.yml        # 給web01主機單獨的變量

比如group_vars/webservers.yml里寫:

app_type: "nginx"
log_path: "/var/log/nginx"

變量使用小技巧

  • 引用變量時用雙大括號{{ 變量名 }},比如{{ app_name }}

  • 變量名可以包含字母、數字和下劃線(不能以數字開頭)

  • 支持嵌套,比如:

    app:name: "blog"port: 8080
    

    引用時用

    {{ app.name }}
    
    {{ app.port }}
    

簡單說,vars聲明就是給 Ansible 提前 “備課”—— 把需要用的信息整理好,用的時候直接喊名字就能調出來,不用重復寫死,既靈活又好維護~

Host scope

主機變量應用于主機和主機組。主機變量優先級高于主機組變量。

主機清單中定義

較舊的做法是直接在清單文件中定義。不建議采用,但仍可能會遇到。

[servers]
node1 user=laoma
node2[servers:vars]
user=laowang
目錄分層結構定義

在項目目錄中創建如下目錄:

  • group_vars,定義主機組變量。目錄中文件名可以直接使用 主機組名 或者 主機組名.yaml

  • host_vars,定義主機變量。目錄中文件名可以直接使用 主機名 或者 主機名.yaml

主機連接特殊變量

詳情參考:主機連接特殊變量。

  • ansible_connection,與主機的連接類型,可以是 smart、ssh 或 paramiko。默認為smart。

  • ansible_host,要連接的主機的名稱,默認值就是主機清單名稱。

  • ansible_port,ssh 端口號,如果不是 22。

  • ansible_user,ssh 用戶名。

  • ansible_ssh_pass,要使用的 ssh 密碼。切勿以純文本形式存儲此變量,始終使用保管庫。

  • ansible_ssh_private_key_file,ssh 使用的私鑰文件。如果使用多個密鑰并且您不想使用 SSH 代理,這很有用。

  • ansible_ssh_common_args,此設置始終附加到 sftp、scp 和 ssh 的默認命令行。

  • ansible_sftp_extra_args,此設置始終附加到默認的 sftp 命令行。

  • ansible_scp_extra_args,此設置始終附加到默認的 scp 命令行。

  • ansible_ssh_extra_args,此設置始終附加到默認的 ssh 命令行。

  • ansible_become,等效于 ansible_sudo 或 ansible_su,允許強制提權。

  • ansible_become_method,允許設置權限提升方法。

  • ansible_become_user,等效于 ansible_sudo_user 或 ansible_su_user,允許設置您通過權限升級成為的用戶。

  • ansible_become_pass,等效于 ansible_sudo_pass 或 ansible_su_pass,允許您設置權限提升密碼(切勿以純文本形式存儲此變量;始終使用保管庫。請參閱變量和保管庫)。

數組變量

除了將與同一元素相關的配置數據(軟件包列表、服務列表和用戶列表等)分配到多個變量外,管理員也可以使用數組變量,將多個值存儲在同一變量中。

示例:

user1_first_name: Bob
user1_last_name: Jones
user1_home_dir: /users/bjones
user2_first_name: Anne
user2_last_name: Cook
user2_home_dir: /users/acook

改寫如下:

users:bjones:first_name: Boblast_name: Joneshome_dir: /users/bjonesacook:first_name: Annelast_name: Cookhome_dir: /users/acook

數組變量引用方式一:

# Returns 'Bob'
users.bjones.first_name
# Returns '/users/acook'
users.acook.home_dir

數組變量引用方式二:

# Returns 'Bob'
users['bjones']['first_name']
# Returns '/users/acook'
users['acook']['home_dir']

引用方式總結:

  • 如果使用方法一**.分隔符**引用的關鍵字與python的功能函數同名,例如discard、copy、add,那么就會出現問題。方法二[‘’]引用方式可以避免這種錯誤。
  • 盡管兩種方法都可以使用,為了減少排故難度,Ansible中統一使用其中一種方法。

示例1:

---
- name: test vars statement in playhosts: node1vars: users:laoma:user_name: laomahome_path: /home/laomalaowang:user_name: laowanghome_path: /home/laowangtasks:- name: add user {{ users.laoma.user_name }}user:name: '{{ users.laoma.user_name }}'home: "{{ users.laoma.home_path }}"- name: debug laowangdebug: msg: >username is {{ users['laowang']['user_name'] }}home_path is {{ users['laowang']['home_path'] }}

示例2:

---
- name: test vars statement in playhosts: node1vars: users:- user_name: laoma1home_path: /home/laoma1- user_name: laoma2home_path: /home/laoma2tasks:- name: add user {{ users.0.user_name }}user:name: "{{ users.0.user_name }}"home: "{{ users.0.home_path }}"- name: debug {{ users[1].user_name }}debug: msg: "{{ users[1].user_name }}"
register 語句

**register 語句捕獲任務輸出。**輸出保存在一個臨時變量中,稍后在playbook中可用于調試用途或者達成其他目的。

示例:

---
- name: Installs a package and prints the resulthosts: node1tasks:- name: Install the packageyum:name: httpdstate: installedregister: install_result- debug: var: install_result

在 Ansible 里,register就像給任務裝了個 “記錄儀”,能把任務執行的結果(比如命令輸出、狀態信息)存起來,方便后面的任務 “回看” 或 “利用” 這些結果。

打個比方:就像你讓同事去查一個文件的大小,他回來告訴你 “文件有 100MB”——register就相當于把這句話記在筆記本上,你后面可以根據這個結果決定 “要不要備份”(如果大于 50MB 就備份)。

基本用法:記錄任務結果

在任務里加register: 變量名,就會把結果存到這個變量里。比如記錄ls命令的輸出:

- name: 查看/tmp目錄內容command: ls /tmpregister: tmp_files  # 把結果存到tmp_files變量里- name: 打印剛才的結果debug:var: tmp_files  # 顯示變量內容

運行后會看到tmp_files里包含很多信息:命令是否成功(success)、輸出內容(stdout)、錯誤信息(stderr)等。

實用場景:根據結果做判斷

最常用的是結合when條件,根據記錄的結果決定下一步操作。

比如:檢查某個進程是否存在,存在就重啟,不存在就啟動:

- name: 檢查nginx進程command: pgrep nginxregister: nginx_statusignore_errors: yes  # 即使命令失敗(進程不存在)也不終止Playbook- name: 如果進程存在,就重啟nginxservice:name: nginxstate: restartedwhen: nginx_status.rc == 0  # rc=0表示命令成功(進程存在)- name: 如果進程不存在,就啟動nginxservice:name: nginxstate: startedwhen: nginx_status.rc != 0  # rc≠0表示命令失敗(進程不存在)

這里nginx_status.rc是命令的返回碼(rc即 return code),0 代表成功,非 0 代表失敗。

常用的結果字段

register變量里有很多有用的 “子信息”,常用的有:

  • stdout:命令的標準輸出(比如ls列出的文件)
  • stderr:命令的錯誤輸出(如果命令失敗)
  • rc:返回碼(0 = 成功,非 0 = 失敗)
  • changed:任務是否改變了系統狀態(布爾值)
  • failed:任務是否失敗(布爾值)

比如只想看命令輸出的內容:

- name: 查看系統版本command: cat /etc/os-releaseregister: os_info- name: 打印系統版本信息debug:msg: "系統版本:{{ os_info.stdout }}"  # 只取stdout部分

簡單說,register就是 Ansible 里的 “記事貼”—— 讓任務之間能 “傳遞消息”,根據前面的結果動態決定后面的操作,讓 Playbook 變得更智能、更靈活~

MAGIC 變量

magic 變量由 Ansible 自動設置,可用于獲取與特定受管主機相關的信息。

假設當前清單內容為:

controller[webs]
node1
node2[dbs]
node3
node4

最常用四個 Magic 變量:

  • inventory_hostname,包含清單中配置的當前受管主機的主機名稱。這可能因為各種原因而與FACTS報告的主機名稱不同。

    [laoma@controller web]$ ansible node1 -m debug -a 'var=inventory_hostname'
    node1 | SUCCESS => {"inventory_hostname": "node1"
    }
    
  • group_names,列出當前受管主機所屬的所有主機組。

    [laoma@controller web]$ ansible node1 -m debug -a 'var=group_names'
    node1 | SUCCESS => {"group_names": ["webs"]
    }
    
  • groups,列出清單中的所有組,以及組中含有的主機。

    [laoma@controller web]$ ansible node1 -m debug -a 'var=groups'
    node1 | SUCCESS => {"groups": {"all": ["workstation","node1","node2","node3","node4"],"dbs": ["node3","node4"],"ungrouped": ["controller"],"webs": ["node1","node2"]}
    }
    
  • hostvars,包含所有受管主機的變量,可用于獲取另一臺受管主機的變量的值。如果還沒有為受管主機收集FACTS,則它不會包含該主機的 FACTS。

    例如:hostvars.controller.group_names

在 Ansible 里,“MAGIC 變量”(魔法變量)就像自帶的 “萬能鑰匙”,不需要你手動定義,Ansible 會自動生成并提供這些變量,幫你快速獲取 inventory(主機清單)里的各種信息,讓 Playbook 更靈活地處理主機間的關系。

它們之所以叫 “魔法變量”,是因為你不用聲明就能直接用,就像憑空出現的工具,專門解決和主機清單相關的問題。

最常用的幾個 “魔法變量”:

1. inventory_hostname:當前主機的 “身份證”

返回當前正在處理的主機在 inventory 里的名字(不是主機的 hostname,而是你在清單里寫的名字)。

比如 inventory 里寫著 web01.example.com,那這個變量就返回它。

- name: 顯示當前主機名debug:msg: "正在處理的主機:{{ inventory_hostname }}"
2. groups:主機組的 “花名冊”

返回所有主機組的列表,以及每個組里的主機。比如想知道 webservers 組有哪些主機:

- name: 顯示web服務器組的所有主機debug:msg: "web組主機:{{ groups['webservers'] }}"

如果想獲取所有主機組的名字,用 groups.keys()

3. group_names:當前主機的 “所屬群組”

返回當前主機所在的所有組(列表形式)。比如一臺主機既在 webservers 組又在 prod 組,這個變量就會返回這兩個組名。

- name: 顯示當前主機所屬的組debug:msg: "我屬于這些組:{{ group_names }}"
4. hostvars:其他主機的 “信息庫”

可以獲取其他主機的變量或 facts 信息,相當于 “跨主機查資料”。

比如想獲取 db01 主機的 IP 地址(需要先收集過 facts):

- name: 顯示db01的IPdebug:msg: "數據庫IP:{{ hostvars['db01']['ansible_default_ipv4']['address'] }}"
5. play_hosts:當前 Play 的 “任務清單”

返回當前 Play 中正在處理的所有主機(受 hosts 字段限制的主機列表)。

- name: 顯示當前Play要處理的所有主機debug:msg: "本次任務涉及主機:{{ play_hosts }}"

為什么需要魔法變量?

它們就像 Ansible 內置的 “導航系統”,幫你在復雜的主機清單中定位信息:

  • 比如跨主機通信(web 服務器需要知道數據庫服務器的 IP)
  • 比如根據主機所在組執行不同任務
  • 比如動態獲取當前處理的主機信息

管理 SECRETS

Ansible Vault 簡介

Ansible可能需要訪問密碼或API密鑰等敏感數據,此信息可能以純文本形式存儲在清單變量或其他Ansible文件中。任何有權訪問Ansible文件的用戶或存儲這些Ansible文件的版本控制系統都能夠訪問此敏感數據。

這顯然存在安全風險。Ansible隨附的 Ansible Vault 可以加密任何由Ansible使用的結構化數據文件,包括清單變量、playbook中含有的變量文件、在執行playbook時作為參數傳遞的變量文件,以及Ansible角色中定義的變量。

變量管理推薦做法
  • 包含敏感變量的文件可通過 ansible-vault 命令進行保護。
  • 敏感變量和所有其他變量保存在相互獨立的文件中。
  • 管理組變量和主機變量的首選方式是在項目目錄中創建子目錄。

可為每個主機組或受管主機使用獨立的目錄。這些目錄可包含多個變量文件,它們都由該主機組或受管主機使用。

管理 FACTS

FACTS 介紹

FACTS 是 Ansible 在受管主機上自動檢測到的變量,默認保存在內容中,只存在于本次playbook執行期間。

FACTS含有主機相關的信息,可以像play中的常規變量一樣使用。

受管主機的 facts 包括:

? 主機名稱 ? 內核版本 ? 網絡接口 ? IP地址 ? 操作系統版本 ? 各種環境變量
? CPU數量 ? 提供的或可用的內存 ? 可用磁盤空間

借助 facts,可以方便地檢索受管主機的狀態,并根據該狀態確定要執行的操作。

例如:

  • 可以根據當前內核版本的FACTS運行條件任務,以此來重新啟動服務器。
  • 可以根據通過FACTS報告的可用內存來自定義 MySQL 配置文件。
  • 可以根據FACTS的值設置配置文件中使用的 IPv4 地址。

通常,每個play在執行第一個任務之前會先自動收集FACTS。

查看 FACTS 內容

示例1:查看所有變量

---
- name: Dump factshosts: node1tasks:- name: Print all factsdebug:var: ansible_facts

示例2:查看單個變量

---
- hosts: node1tasks:- name: Print Ansible factsdebug: msg: >The default IPv4 address of {{ ansible_fqdn }}is {{ ansible_default_ipv4.address }}
部分 FACTS
FACTVARIABLE
短主機名ansible_facts[‘hostname’]
完全限定的域名ansible_facts[‘fqdn’]
主要IPv4地址(基于路由)ansible_facts[‘default_ipv4’][‘address’]
所有網絡接口的名稱列表ansible_facts[‘interfaces’]
/dev/vdal磁盤分區的大小ansible_facts[‘devices’][‘vda’][‘partitions’]['vda1][‘size’]
DNS服務器列表ansible_facts[‘dns’][‘nameservers’]
當前運行的內核的版本ansible_facts[‘kernel’]
setup 和 gather_facts 模塊

setup 和 gather_facts 模塊都可以用來收集facts:

  • gather_facts 模塊,只能用來收集facts。

  • setup 模塊,除了用來收集facts,還提供額外選項:

    • filter 選項,用于查看特定facts值。

    • gather_subset 選項,用于控制收集facts范圍

關閉 FACTS 收集

關閉 FACTS 收集部分原因:

  • 不使用任何FACTS
  • 希望加快play速度或減小play在受管主機上造成的負載
  • 受管主機因為某種原因而無法運行setup模塊
  • 需要安裝一些必備軟件后再收集FACTS

Ansible配置文件設置

[defaults]
gathering = explicit

play中設置

---
- name: Fact dumphosts: node1gather_facts: no

即使關閉以后,也可以隨時使用setup模塊收集facts。

實施任務控制

編寫循環任務

利用循環,管理員無需編寫多個使用同一模塊的任務。例如,確保存在五個用戶,不需要編寫五個任務,而是只需編寫一個任務來對含有五個用戶的列表迭代。

Ansible支持使用 loop 關鍵字對一組項目迭代任務。您可以配置循環以利用列表中的各個項目、列表中各個文件的內容、生成的數字序列或更為復雜的結構來重復任務。

簡單循環

簡單循環對一組項目迭代任務。loop關鍵字添加到任務中, 將應對其迭代任務的項目列表取為值。循環變量item保存每個迭代過程中使用的值。

示例:

---
- name: add several usershosts: node1gather_facts: notasks:- name: add user janeuser:name: "jane"groups: "wheel"state: present- name: add user joeuser:name: "joe"state: presentgroups: "wheel"

使用loop循環改寫:

- name: test loophosts: node1gather_facts: notasks:- name: add usersuser:name: "{{ item }}"groups: "wheel"state: presentloop:- jane- joe

這個 Playbook 的作用是在node1主機上批量創建兩個用戶(jane 和 joe),并將他們加入wheel組。

  • name: test loop:這是 Play 的名稱,用于標識這個 Play 的用途
  • hosts: node1:指定在node1這臺主機上執行
  • gather_facts: no:關閉 facts 收集,加快執行速度(因為這個任務不需要系統信息)
  • 任務部分使用了loop關鍵字,后面跟著一個用戶列表[jane, joe]

在循環過程中,Ansible 會自動將列表中的每個元素依次賦值給item變量,然后執行user模塊:

  • 第一次循環:item = jane,創建用戶 jane 并加入 wheel 組
  • 第二次循環:item = joe,創建用戶 joe 并加入 wheel 組

user模塊的參數說明:

  • name: "{{ item }}":用戶名,這里引用循環變量
  • groups: "wheel":指定用戶所屬的附加組(wheel 組通常用于 sudo 權限)
  • state: present:確保用戶存在(如果不存在則創建)

執行這個 Playbook 后,目標主機上會新增 jane 和 joe 兩個用戶,且都屬于 wheel 組。這種循環方式非常適合需要批量執行相同操作的場景,避免了重復編寫任務代碼。

循環散列或字典列表

在以下示例中,列表中的每個項實際上是散列或字典。

示例中的每個散列或字典具有兩個鍵,即name和groups,當前item循環變量中每個鍵的值可以分別通過item.name和item.groups變量來檢索。

示例:

- name: test loophosts: node1gather_facts: notasks:- name: add usersuser:name: "{{ item.name }}"groups: "{{ item.groups }}"state: presentloop: - name: janegroups: wheel- name: joegroups: root

改寫為:

---
- name: add several usershosts: node1gather_facts: novars:users:- name: janegroups: wheel- name: joegroups: roottasks:- name: add users user:name: "{{ item.name }}"state: presentgroups: "{{ item.groups }}"  loop: "{{ users }}"
Register 與 Loop

示例:

---
- name: Loop Register Testhosts: node1gather_facts: notasks:- name: Looping Echo Taskshell: "echo This is my item: {{ item }}"loop:- one- tworegister: result- name: Show result variabledebug:var: result- name: Show result variable stdoutdebug:msg: "STDOUT from previous task: {{ item.stdout }}"loop: "{{ result.results }}"

編寫條件任務

Ansible可使用conditionals在符合特定條件時執行任務或play。

例如,管理員可利用條件來區分不同的受管節點,并根據它們所符合的條件來分配功能角色。 Playbook變量、注冊的變量和ANSIBLE FACTS都可通過條件來進行測試。可以使用比較字符串、數字數據和布爾值的運算符。

用例:

  1. 定義變量min_memory,判斷被管理節點可用內存是否滿足該值。
  2. 捕獲命令輸出,判定task是否執行完成,以便決定是否進行下一步操作。
  3. 被管理節點上收集到的網絡facts,判定是否適合哪種綁定(bonding或者trunking)。
  4. 根據CPU的數量決定如何調優web服務器。
  5. Registered變量與預定義的變量對比,判斷是否有變化。例如文件的MD5值。
when 語句

ansible playbook 中使用 when 來運行條件任務。

when 用于有條件地運行任務,取要測試的條件作為值。如果條件滿足,則運行任務。若條件不滿足,則跳過任務。

注意:通常的慣例是將可能存在的任何when關鍵字放在任務名稱和模塊(及模塊參數)的后面。原因是任務是YAML散列/字典,when 語句只是任務中的一個鍵,就如任務的名稱以及它所使用的模塊一樣。

常見判斷
操作示例
等于(值為字符串)ansible_machine == “x86_64”
等于(值為數字)max_memory == 512
小于min_memory < 128
大于min_memory > 256
小于等于min_memory <= 256
大于等于min_memory >= 512
不等于min_memory != 512
變量存在min_memory is defined
變量不存在min_memory is not defined
布爾變量值是1、True或yes的求值為memory_available
布爾變量值是0、False或no的求值為memory_available
memory_available變量值為真,最終結果為not memory_available
第一個變量的值存在,作為第二個變量的列表中的值ansible_distribution in supported_distros
布爾值變量判斷

示例:

---
- name: test hosts: node1gather_facts: novars:run_my_task: truetasks:- name: test whendebug:msg: "Hello run my task"when: run_my_task

示例中的when語句導致:任務僅在run_my_task為 true時運行。

變量是否定義判斷

變量判斷:

  • defined == not undefined 變量定義返回真
  • undefined == not defined 變量未定義返回真
  • none 變量定義了,但是值是空值,返回真

示例1:

---
- hosts: node1gather_facts: novars:username: laomatasks:- debug:msg: "var: username is defined"when: username is defined

示例2:判斷受管主機是否具有相應設備。

---
- name: create and use lvhosts: node1tasks:- name: Create a logical volume of 4000mlvol:vg: researchlv: datasize: 4000when: ansible_lvm.vgs.research is defined- debug:msg: Volume group does not existwhen: ansible_lvm.vgs.research is not defined
文件屬性判斷
  • file:如果路徑是一個普通文件,返回真
  • directory:如果路徑是一個目錄,返回真
  • link:如果路徑是一個軟連接,返回真
  • mount:如果路徑是一個掛載點,返回真
  • exist:如果路徑是存在,返回真

示例:

---
- hosts: node1gather_facts: novars:file_name: /etc/hoststasks:- debug:msg: "{{ file_name }} is regular file"when: file_name is file
任務執行結果判斷
  • succeeded,通過任務的返回信息判斷,任務執行成功返回真。
  • failed,通過任務的返回信息判斷,任務執行失敗返回真。
  • changed,通過任務的返回信息判斷,任務執行狀態為changed返回真。
  • skipped,通過任務的返回信息判斷,任務沒有滿足條件跳過執行,返回真。

示例:

---
- hosts: node1gather_facts: novars:doshell: "yes"tasks:- shell: cat /etc/hostsregister: resultignore_errors: truewhen: doshell == "yes"- name: successdebug:msg: successwhen: result is succeeded- name: faileddebug:msg: failedwhen: result is failed- name: changeddebug:msg: changedwhen: result is changed- name: skippeddebug:msg: skipwhen: result is skipped

其他測試:

  • 設置doshell: “no”
  • 設置shell: cat /etc/hosts-no-exist
in 和 not in 判斷

示例1:給用戶添加組

---
- name: test hosts: node1gather_facts: novars:username: devopssupergroup: wheeltasks:- name: gather user informationshell: id {{ username }}register: result- name: Task run if user is in supergroupsuser:name: "{{ username }}"groups: "{{ supergroup }}"append: yeswhen:  supergroup not in result.stdout

示例2:給用戶添加多個組

---
- name: test hosts: node1gather_facts: novars:username: devopssupergroups: - wheel- roottasks:- name: gather user informationshell: id {{ username }}register: result- name: Task run username is in supergroupsuser:name: "{{ username }}"groups: "{{ item }}"append: yeswhen:  item not in result.stdoutloop: "{{ supergroups }}"

Ansible Handlers

Ansible Handlers 功能

Ansible的模塊的設計是可以多次執行的,當被管理節點是預期狀態時,是不會做任何更改的。然而,有時候執行了一個任務,還需要進一步執行下一個任務。

例如,更改了服務配置文件之后,需要重新加載配置文件才能生效。Handlers是由其他任務通知執行的任務,可看做inactive任務,通過notify調用。

示例:

---
- name: deploy web serverhosts: node1tasks:- name: install packagesyum:name: httpdstate: presentnotify:- enable and restart apache- name: install httpd-manualyum:name: httpd-manualstate: presentnotify:- enable and restart apache- debug: msg: last task in taskshandlers:- name: enable and restart apacheservice:name: httpdstate: restartedenabled: yes

在 Ansible 中,Handlers(處理器) 就像一個 “待命的助手”,專門用來處理那些 “只有在系統狀態發生變化時才需要執行” 的操作。它有點像 “觸發器”—— 只有當某個任務真正改變了系統狀態(比如修改了配置文件),Handlers 才會被觸發執行。

為什么需要 Handlers?

舉個例子:當你修改了 Nginx 的配置文件(nginx.conf),只有在配置文件真的被改動時,才需要重啟 Nginx 服務。如果配置文件沒變化,重啟操作就是多余的。

Handlers 正是為這種場景設計的:它能 “監聽” 任務是否導致了系統狀態變更(通過changed: true標識),只有變更發生時才執行指定操作,避免無效重復執行。

基本用法:定義和觸發 Handlers

Handlers 的使用分為兩步:定義 Handlers在任務中通知(notify)Handlers

- name: 配置Nginx并按需重啟hosts: webserverstasks:- name: 修改Nginx配置文件copy:src: ./nginx.confdest: /etc/nginx/nginx.confnotify:  # 當這個任務導致狀態變更時,通知Handlers- 重啟Nginx服務  # 這里的名稱要和Handlers中定義的一致handlers:  # 定義Handlers(放在Play的handlers塊中)- name: 重啟Nginx服務  # 名稱要和notify中的完全匹配service:name: nginxstate: restarted
執行邏輯:
  1. 執行 “修改 Nginx 配置文件” 任務:
    • 如果配置文件有變化(changed: true),則標記 “重啟 Nginx 服務” 這個 Handler 為 “待執行”
    • 如果配置文件無變化(changed: false),則不通知 Handler
  2. 當 Play 中所有任務執行完畢后,Ansible 會統一執行所有被標記為 “待執行” 的 Handlers。

Handlers 的特點

  1. 延遲執行:Handlers 不會在被通知后立即執行,而是等到當前 Play 中所有任務都執行完才統一運行。

  2. 冪等性保障:即使多個任務通知同一個 Handler,它也只會執行一次。例如:

    tasks:- name: 修改配置文件Acopy: src=a.conf dest=/etc/nginx/notify: 重啟Nginx服務- name: 修改配置文件Bcopy: src=b.conf dest=/etc/nginx/notify: 重啟Nginx服務
    

    無論兩個任務是否都觸發了變更,“重啟 Nginx 服務” 只會執行一次,避免多次重啟。

  3. 名稱唯一:Handlers 通過name標識,notify必須嚴格匹配名稱(包括大小寫),否則無法觸發。

常見使用場景

Handlers 最適合處理 “配置變更后需要生效的操作”,例如:

  • 服務重啟(Nginx、MySQL、Apache 等)
  • 重新加載配置(systemctl reload
  • 重建緩存(如systemctl daemon-reload
  • 重新編譯(當源碼或 Makefile 被修改時)

簡單說,Handlers 就像 “按需執行的收尾工作”—— 平時待命,只有當系統真的發生了需要它處理的變化時,才會出手完成必要的后續操作,讓 Playbook 更高效、更符合實際運維邏輯。

處理 Errors

Errors 介紹

Ansible評估各任務的返回代碼,從而確定任務是成功還是失敗。通常而言, 當某個主機執行任務失敗時,Ansible將立即終止該主機繼續執行play,其他主機可以繼續執行play。

---
- name: testhosts: node1,node2tasks:- name: show /etc/myhostsshell: cat /etc/myhosts- name: echo enddebug:msg: echo end
ignore_errors

您可能希望即使在任務失敗時也繼續執行play。例如,您或許預期特定任務有可能會失敗,并且希望通過有條件地運行某項其他任務來恢復。

ignore_errors可以定義在以下位置:

  • 定義在 play 中,則play中所有任務忽略錯誤。
  • 定義在 task 中,則特定task忽略錯誤。

示例:

---
- name: testhosts: node1tasks:- name: install a not exist packageyum:name: notexitpackagestate: presentignore_errors: yesregister: result- name: debug install resultdebug:msg: notexitpackage is not exitwhen: result is failed
fail 模塊

fail 模塊,執行該任務,任務必定 failed。

示例:

- name: test fail modulehosts: node1gather_facts: notasks:- debug:msg: task1- fail:- debug:msg: task3

提示:fail模塊本身也可以配置when判斷,實現說明情況下任務是失敗的。

failed_when

指明什么條件下,判定任務執行失敗。

示例:

- name: test failed_whenhosts: node1tasks:- shell: /root/adduserregister: command_resultfailed_when: "'failed' in command_result.stdout"

環境準備:

[root@node1 ~]# cat /root/adduser 
#!/bin/bash
useradd devops &> /dev/null
if [ $? -eq 0 ];thenecho add user devops success
elseecho add user devops failed
fi
[root@node1 ~]# chmod +x /root/adduser 

以上示例:

  • 當devops用戶不存在時,shell模塊跳過執行。
  • 當devops用戶存在時,shell模塊執行失敗。

以上示例可改寫為fail模塊和when語句聯合使用:

- name: test fail modulehosts: node1tasks:- shell: /root/adduserregister: command_result- fail:msg: "add user devops failed"when: "'failed' in command_result.stdout"
changed_when

指明什么條件下,判定任務執行結果為changed。

示例1:

- name: changed_whenhosts: node1tasks:- name: upgrade-databaseshell: /usr/local/bin/upgrade-databaseregister: resultchanged_when: "'Success' in result.stdout"notify:- restart_databasehandlers:- name: restart_databaseservice:name: mariadbstate: restarted

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919180.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919180.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919180.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32--寄存器與標準庫函數--基本定時器

目錄 前言 基本定時器概念 定時時間 定時器時鐘確定 倍頻鎖相環被正確配置為168MHz 定時器的庫函數操作 代碼 定時器的寄存器操作 代碼 寄存器 后言 前言 使用平臺:STM32F407ZET6 使用數據手冊&#xff1a;STM32F407數據手冊.pdf 使用參考手冊&…

PCA 實現多向量壓縮:首個主成分的深層意義

PCA 實現多向量壓縮 第一個主成分(components_[0])正是數據協方差矩陣中最大特征值對應的特征向量。 ,layer_attention_vector[layer] 被賦值為 pca.components_[0],這確實是一個特征向量,具體來說是 PCA 分解得到的第一個主成分(主特征向量)。 關于它的維度: 假設 c…

網絡常識-DNS如何解析

DNS&#xff08;Domain Name System&#xff0c;域名系統&#xff09;是互聯網的“地址簿”&#xff0c;負責將人類易記的域名&#xff08;如www.example.com&#xff09;轉換為計算機可識別的IP地址&#xff08;如192.168.1.1&#xff09;。其工作流程可以簡單理解為“從域名到…

Java中 23 種設計模式介紹,附帶示例

文章目錄設計模式六大原則設計模式分類1、創建型模式&#xff08;Creational Patterns&#xff09;2、結構型模式&#xff08;Structural Patterns&#xff09;3、行為型模式&#xff08;Behavioral Patterns&#xff09;一、創建型模式&#xff08;Creational Patterns&#x…

嵌入式開發入門——電子元器件~電磁繼電器、蜂鳴器

文章目錄電磁繼電器定義關鍵參數實物蜂鳴器實物內部結構分類關鍵參數電磁繼電器 定義 概述&#xff1a;電磁繼電器是利用電磁感應原理職稱的一種電磁開關&#xff0c;他能通過&#xff1a;低電壓、低電流的電路&#xff0c;來控制高電壓、高電流的電路。 關鍵參數 線圈電壓…

ROS2基礎

1.helloworld案例1.創建功能包&#xff08;C&#xff09;終端下&#xff0c;進入ws00_helloworld/src目錄&#xff0c;使用如下指令創建一個C 功能包:ros2 pkg create pkg01_helloworld_cpp --build-type ament_cmake --dependencies rclcpp --node-name helloworld執行完畢&a…

Python爬蟲實戰:研究pygalmesh,構建Thingiverse平臺三維網格數據處理系統

1. 引言 1.1 研究背景 在數字化浪潮席卷全球的當下,三維建模技術已成為連接虛擬與現實的核心紐帶,廣泛滲透于工程設計、地理信息系統(GIS)、虛擬現實(VR)、增強現實(AR)、醫學影像等關鍵領域。例如,在建筑工程中,BIM(建筑信息模型)技術依賴高精度三維網格實現施工…

開發者說 | EmbodiedGen:為具身智能打造可交互3D世界生成引擎

概述 具身智能的發展離不開高質量、多樣化的可交互3D仿真環境。為突破傳統構建方式的瓶頸&#xff0c;我們提出了EmbodiedGen&#xff0c;一個基于生成式AI技術的自動化3D世界生成引擎&#xff0c;助力低成本、高效率地創建真實且可交互的3D場景。用戶僅需輸入任務定義或場景圖…

GitHub Copilot:AI編程助手的架構演進與真實世界影響

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 1. 技術背景與核心架構 GitHub Copilot 是由 GitHub 與 OpenAI 聯合開…

PDF OCR + 大模型:讓文檔理解不止停留在識字

在企業數字化的實際場景中&#xff0c;PDF OCR 已經很普遍了&#xff1a;從掃描件提取文本、表格到生成可搜索 PDF。但這類技術往往停留在"把圖片變成文字"&#xff0c;對文檔背后的語義、邏輯、業務價值理解不足。 而當 OCR 遇上大語言模型&#xff08;LLM&#xff…

半敏捷衛星觀測調度系統的設計與實現

半敏捷衛星觀測調度系統的設計與實現 摘要 本文詳細闡述了一個基于Python的半敏捷衛星觀測調度系統的設計與實現過程。系統針對半敏捷衛星特有的機動能力限制&#xff0c;綜合考慮了地面目標觀測需求、衛星資源約束、能源管理等多重因素&#xff0c;提出了一種混合啟發式算法解…

軟件測試中,常用的抓包工具有哪些?抓包的原理是什么?

回答重點在軟件測試中&#xff0c;常用的抓包工具主要有&#xff1a;1&#xff09;Fiddler2&#xff09;Wireshark3&#xff09;Charles4&#xff09;Postman&#xff08;它的攔截器功能也可以用于抓包&#xff09;5&#xff09;tcpdump抓包的原理大致是通過安裝在本地的抓包工…

Cesium學習(二)-地形可視化處理

Cesium地形可視化是其核心功能之一&#xff0c;允許開發者在3D地球中展示真實的地形數據。以下是關于Cesium地形可視化的詳細處理方法&#xff1a; 文章目錄1. 啟用地形可視化基本地形加載自定義地形提供者2. 地形相關操作地形高度采樣地形夸張效果3. 地形可視化設置地形照明效…

《告別 if-else 迷宮:Python 策略模式 (Strategy Pattern) 的優雅之道》

《告別 if-else 迷宮:Python 策略模式 (Strategy Pattern) 的優雅之道》 大家好,我是你的朋友,一位與 Python 代碼相伴多年的開發者。在我們的編程生涯中,幾乎都曾與一種“代碼怪獸”搏斗過,它就是那冗長、復雜、牽一發而動全身的 if-elif-else 結構。 每當一個新的需求…

Redis--day7--黑馬點評--優惠券秒殺

&#xff08;以下內容全部來自上述課程&#xff09;優惠券秒殺 1. 全局唯一ID 每個店鋪都可以發布優惠券:當用戶搶購時&#xff0c;就會生成訂單并保存到tb voucher order這張表中&#xff0c;而訂單表如果使用數據庫自增ID就存在一些問題: id的規律性太明顯受單表數據量的限制…

Vue 與 React 深度對比:設計哲學、技術差異與應用場景

一、核心設計理念對比 特性 Vue React 設計目標 漸進式框架,降低學習曲線 構建大型應用,保持靈活性 設計哲學 “約定優于配置” “配置優于約定” 核心思想 響應式數據綁定 函數式編程 + 虛擬DOM 模板語言 HTML-based 模板 JSX(JavaScript XML) 狀態管理 內置響應式系統 依…

軟件開發 - foreground 與 background

foreground 與 background 1、foreground詞性含義n.前景&#xff1b;最突出的位置.v使突出&#xff1b;強調# 例詞in the 【foreground】&#xff08;在最顯眼的位置&#xff09;【foreground】 task&#xff08;前臺任務&#xff09;【foreground】 color&#xff08;前景色&a…

深度學習——03 神經網絡(2)-損失函數

2 損失函數 2.1 概述作用&#xff1a;衡量模型預測結果&#xff08;y^\hat{y}y^?&#xff09;和真實標簽&#xff08;yyy&#xff09;的差異&#xff0c;差異越大&#xff0c;說明模型參數“質量越差”&#xff08;需要調整&#xff09;&#xff1b;本質&#xff1a;深度學習訓…

【大模型微調系列-04】 神經網絡基礎與小項目實戰

【大模型微調系列-04】 神經網絡基礎與小項目實戰&#x1f4a1; 本章目標&#xff1a;通過構建一個能識別手寫數字的AI模型&#xff0c;讓你真正理解神經網絡是如何"學習"的。2-3小時后&#xff0c;你將擁有第一個自己訓練的AI模型&#xff01;4.1 理論講解&#xff…

JavaWeb前端(HTML,CSS具體案例)

前言 一直在學習B站黑馬程序員蒼穹外賣。現在已經學的差不多了&#xff0c;但是我學習一直是針對后端開發的&#xff0c;前端也沒太注重去學&#xff08;他大部分都給課程資料嘻嘻&#x1f92a;&#xff09;&#xff0c;但我還是比較感興趣&#xff0c;準備先把之前學JavaWeb&…