<bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>

    PlayBook 詳解

    4)Playbook

    4.1)Playbook 介紹

    PlayBookad-hoc 相比,是一種完全不同的運用 Ansible 的方式,類似與 Saltstack 的 state 狀態文件。ad-hoc 無法持久使用,PlayBook 可以持久使用。
    PlayBook 劇本是 由一個或多個 "Play" 組成 的列表
    Play 的主要功能在于將預定義的一組主機,裝扮成事先通過 Ansible 中的 Task 定義好的角色。
    從根本上來講,所謂的 Task 無非是調用 Ansible 的一個 module。將多個 Play 組織在一個 PlayBook 中,即可以讓它們聯合起來按事先編排的機制完成某一任務。

    PlayBook 文件是采用 YAML 語言 編寫的。

    4.1.1)PlayBook 核心元素

    • Host: 執行的遠程主機列表
    • Tasks: 任務集
    • Varniables: 內置變量或自定義變量在 PlayBook 中調用
    • Templates: 模板文件,即使用模板語法的文件,比如配置文件等
    • Handlers: 和 notity 結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
    • Tags: 標簽,指定某條任務執行,用于選擇運行 PlayBook中的部分代碼。

    PlayBook 翻譯過來就是 劇本,可以簡單理解為使用不同的模塊完成一件事情,
    具體 PlayBook 組成如下

    • Play:定義的是主機的角色
    • Task:定義的是具體執行的任務
    • PlayBook:由一個或多個 Play 組成,一個 Play 可以包含多個 Task 任務

    image.png

    4.1.2)PlayBook 優勢

    • 功能比 ad-hoc 更全
    • 能很好的控制先后執行順序,以及依賴關系
    • 語法展現更加的直觀
    • ad-hoc 無法持久使用,PlayBook 可以持久使用

    4.1.3)PlayBook 語法

    PlayBook 的配置語法是由 yaml 語法描述的,擴展名是 yml 或 yaml,遵循 yaml 格式

    • 縮進: YAML 使用固定的縮進風格表示層級結構,每個縮進由兩個空格組成,不能使用 Tab
    • 冒號: 以冒號結尾的除外,其他所有冒號后面所有必須有空格
    • 短橫線: 表示列表項,使用一個短橫杠加一個空格,多個項使用同樣的縮進級別作為同一列表

    4.2)YAML 語言

    4.2.1)YAML 語言介紹

    YAML: YAML Ain't Markup Language,即 YAML 不是標記語言。
    不過,在開發的這種語言時,YAML 的意思其實是:"Yet Another Markup Language"( 仍是一種標記語言 )

    YAML 是一個可讀性高的用來表達資料序列的格式。

    YAML 參考了其他多種語言,包括:XML、C 語言、Python、Perl 以及電子郵件格式 RFC2822 等。Clark Evans 在 2001 年在首次發表了這種語言,另外 Ingy d?t Net 與 Oren Ben-Kiki 也是這語言的共同設計者,目前很多最新的軟件比較流行采用此格式的文件存放配置信息,如:Ubuntu,Anisble,Docker,Kubernetes 等

    YAML 官方網站:http://www.yaml.org
    Ansible 官網: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

    4.2.2)YAML 語言特性

    • YAML 的可讀性好
    • YAML 和腳本語言的交互性好
    • YAML 使用實現語言的數據類型
    • YAML 有一個一致的信息模型
    • YAML 易于實現
    • YAML 可以基于流來處理
    • YAML 表達能力強,擴展性好

    4.2.3)YAML 語法簡介

    1. 在單一文件第一行,用連續** 三個連字號 "-" 開始**
    2. 還有 選擇性的連續三個點號 ( ... ) 用來 表示文件的結尾
    3. 次行開始正常寫 Playbook 的內容,一般建議寫明該 Playbook 的功能描述
    4. 可以使用 # 號注釋代碼
    5. 縮進必須是統一的,不能空格和 Tab 混用( 正常使用兩個空格縮進 )
    6. 縮進的級別也必須是一致的,同樣的縮進代表同樣的級別,程序判別配置的級別是通過縮進結合換行來實現的
    7. YAML 文件內容是區別大小寫的,key/value 的值 均需大小寫敏感
    8. 多個 key/value 可同行寫也可換行寫,同行使用,分隔
    9. key 后面冒號要加一個空格,比如:key: value
    10. value 可是個字符串,也可是另一個列表
    11. YAML 文件擴展名通常為 yml 或 yaml

    4.2.4)支持的數據類型

    YAML 支持以下 常用幾種數據類型

    • 標量: 單個的、不可再分的值
      • 示例: age: 18
    • 對象: 鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)
      • 示例:account:
    • 數組: 一組按次序排列的值,又稱為序列(sequence) / 列表(list)
      • 示例: course: [ linux , golang , python ]

    4.2.4.1)標量:scalar

    方式一: 鍵值對

    name: wang
    age: 18
    

    方式二: 使用縮進方式

    name:
      wang
    age:
      18
    

    標量是最基本的,不可再分的值,包括:

    • 字符串
    • 布爾值
    • 整數
    • 浮點數
    • Null
    • 時間
    • 日期

    4.2.4.2)字典:Dictionary

    字典由多個 key 與 value 構成,key 和 value 之間用 分隔

    并且,后面有一個空格,所有 k/v 可以放在一行,或者每個 k/v 分別放在不同行

    格式

    account: { name: wang, age: 30 }
    

    使用縮進方式

    account: 
      name: wang
      age: 18
    

    范例:

    # 不同行
    # An employee record
    name: Example Developer
    job: Developer
    skill: Elite(社會精英)
    
    # 同一行, 也可以將 key:value放置于{}中進行表示,用,分隔多個key:value
    # An employee record
    {name: "Example Developer", job: "Developer", skill: "Elite"}
    

    4.2.4.3)列表:List

    列表由多個元素組成,每個元素放在不同行,且元素前均使用 "-" 打頭,并且 - 后有一個空格

    或者將所有元素用 [ ] 括起來放在同一行

    // 格式
    course: [ linux , golang , python ]
    
    // 也可以寫成以 - 開頭的多行
    course:
     - linux
     - golang
     - python
     
    // 數據里面也可以包含字典
    course:
     - linux: manjaro
     - golang: gin
     - python: django
    

    范例:

    # 不同行, 行以-開頭, 后面有一個空格
    # A list of tasty fruits
    - Apple
    - Orange
    - Strawberry
    - Mango
    
    # 同一行
    [Apple,Orange,Strawberry,Mango]
    

    范例:YAML 表示一個家庭

    name: John Smith
    age: 41
    gender: Male
    spouse: { name: Jane Smith, age: 37, gender: Female } # 1) 寫在一行里
      name: Jane Smith   # 2) 也可以寫成多行
      age: 37
      gender: Female
      
    children: [ {name: Jimmy Smith,age: 17, gender: Male}, {name: Jenny Smith, age: 13, gender: Female}, {name: hao Smith, age: 20, gender: Male } ]  # 寫在一行
      - name: Jimmy Smith    # 3) 寫在多行, 更為推薦的寫法
        age: 17
        gender: Male
      - {name: Jenny Smith, age: 13, gender: Female}
      - {name: hao Smith, age: 20, gender: Male }    
    

    4.2.5)三種常見的數據格式

    參考:https://juejin.cn/post/7041815877825593374

    XML:Extensible Markup Language,可擴展標記語言,可用于數據交換和配置。
    JSON:JavaScript Object Notation,JavaScript 對象表記法,主要用來數據交換或配置,不支持注釋。
    YAML:YAML Ain't Markup Language YAML 不是一種標記語言, 主要用來配置,大小寫敏感,不支持 Tab。


    也可以用工具互相轉換,參考網站:
    https://www.json2yaml.com/
    http://www.bejson.com/json/json2yaml/

    4.3)Playbook 核心組件

    官方文檔:https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywords

    一個 PlayBook 中由多個組件組成,其中所用到的 **常見組件類型 **如下:

    • Hosts:執行的 遠程主機列表
    • Tasks: 任務集,由多個 task 的元素組成的列表實現,每個 task 是一個字典,一個完整的代碼塊功能需最少元素需包括 name 和 task,一個 name 只能包括一個 task
    • Variables: 內置變量或自定義變量 在 PlayBook 中調用
    • Templates: 模板,可替換模板文件中的變量并實現一些簡單邏輯的文件
    • Handlersnotify 結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
    • Tags: 標簽 指定某條任務執行,用于選擇運行 playbook 中的部分代碼。ansible 具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些代碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags 跳過此些代碼片段。

    4.3.1)hosts 組件

    Hosts: PlayBook 中的每一個 Play 的目的都是為了讓特定主機以某個指定的用戶身份執行任務。hosts 用于指定要執行指定任務的主機,須事先定義在主機清單中。

    one.example.com
    one.example.com:two.example.com
    192.168.1.50
    192.168.1.*
    Websrvs:dbsrvs     # 或者, 兩個組的并集
    Websrvs:&dbsrvs    # 與, 兩個組的交集
    webservers:!dbsrvs # 在 websrvs 組, 但不在dbsrvs組
    

    案例:

    - hosts: websrvs:appsrvs
    

    4.3.2)remote_user 組件

    remote_user:可用于 Host 和 task 中。也可以通過指定其通過 sudo 的方式在遠程主機上執行任務,其可用于 play 全局或某任務;此外,甚至可以在 sudo 時使用 sudo_user 指定 sudo 時切換的用戶

     remote_user: root            # 方式一
        
     tasks:
       - name: test connection
         ping:
           remote_user: magedu    # 方式二
           sudo: yes         		  # 默認 sudo 為 root
           sudo_user:wang    			# sudo 為 wang
    

    4.3.3)task 列表和 action 組件

    Play 的主體部分是 task list,task list 中有一個或多個 task,各個 task 按次序逐個在 hosts 中指定的所有主機上執行,即在所有主機上完成第一個 task 后,再開始第二個 task。

    task 的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致。

    每個 task 都應該有其 name,用于 PlayBook 的執行結果輸出,建議其內容能清晰地描述任務執行步驟。如果未提供 name,則 action 的結果將用于輸出。

    task 兩種格式:

    action: module arguments    # 示例: action: shell wall hello 
    module: arguments           # 建議使用 # 示例: shell: wall hello 
    

    注意: Shell 和 Command 模塊后面跟命令,而非 key=value

    范例:

    [root@ansible ansible] cat hello.yaml
    ---
    # first yaml file 
    - hosts: websrvs
      remote_user: root
      gather_facts: no   # 不收集系統信息, 提高執行效率
      
      tasks:
        - name: test network connection
          ping:
        - name: wall
          shell: wall "hello world!"
          
    # 檢查語法
    [root@ansible ansible] ansible-playbook --syntax-check hello.yaml
    
    # 驗證腳本 ( 不真實執行 )
    # 模擬執行 hello.yaml 文件中定義的 playbook, 不會在被控節點上應用任何更改
    [root@ansible ansible] ansible-playbook -C hello.yaml
    
    # 真實執行
    [root@ansible ansible] ansible-playbook hello.yaml
    

    范例: 初識 Ansible

    [root@ansible ansible] vim test.yml
    ---
    # 初識 Ansible
    - hosts: websrvs
      remote_user: root
      gather_facts: yes     # 需開啟,否則無法收集到主機信息
    
      tasks:
        - name: '存活性檢測'
          ping:
        - name: '查看主機名信息'
          setup: filter=ansible_nodename
        - name: '查看操作系統版本'
          setup: filter=ansible_distribution_major_version
        - name: '查看內核版本'
          setup: filter=ansible_kernel
        - name: '查看時間'
          shell: date
    
      tasks:
        - name: '安裝 HTTPD'
          yum: name=httpd
        - name: '啟動 HTTPD'                                                                   
          service: name=httpd state=started enabled=yes
          
    # 檢查語法
    [root@ansible ansible] ansible-playbook --syntax-check test.yml
    
    # 執行腳本
    [root@ansible ansible] ansible-playbook test.yml
    

    范例:

    Ansible PlayBook 由有序列表中的一個或多個 Play 組成。在這里,您可以認為劇本是執行指令以實現劇本總體目標的代碼的一部分。

    每個 Play 運行一個 Task,每個 Task 調用 Ansible Modules 在一個或多個 Nodes 托管目標節點上執行指令。

    ---
    - hosts: websrvs
      remote_user: root
      gather_facts: no           # 是否收集系統 facts 信息
      
      tasks:
        - name: install httpd    # 描述信息
          yum: name=httpd        # 調用 yum 模塊
        - name: start httpd
          service: name=httpd state=started enabled=yes    # 調用 service 模塊
    

    image.png

    ---
    - hosts: websrvs
      remote_user: root
      gather_facts: no    # 是否收集系統 facts 信息
      
      tasks:
        - name: ping
          ping:
        - name: wall
          shell: wall hello                   
    
    - hosts: websrvs
      remote_user: root                  
      tasks:
        - name: install httpd
          yum: name=httpd
        - name: start httpd
          service: name=httpd state=started enabled=yes
    
    # 驗證腳本 ( 不真實執行 )
    [root@ansible ansible] ansible-playbook -C hello.yaml
    
    # 真實執行
    [root@ansible ansible] ansible-playbook hello.yaml      
    

    4.3.4)其它組件

    某任務的狀態在運行后為 changed 時,可通過 "notify" 通知給相應的 handlers 任務。
    還可以通過 "tags" 給 task 打標簽,可在 ansible-playbook 命令上使用 -t 指定進行調用

    4.3.5)Shell Scripts VS Playbook 案例

    # SHELL 腳本實現
    #!/bin/bash
    # 安裝 Apache
    yum install --quiet -y httpd
    
    # 復制配置文件
    cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
    cp /tmp/vhosts.conf /etc/httpd/conf.d/
    
    # 啟動 Apache, 并設置開機啟動
    systemctl enable --now httpd
    
    # Playbook 實現
    ---
    - hosts: dbsrvs
      remote_user: root
      gather_facts: no        # 是否收集系統 facts 信息 ( 取消收集能提高 ansible 執行速度 )
    
      tasks:
        - name: "安裝Apache"
          yum: name=httpd
        - name: "復制配置文件"
          copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
        - name: "復制配置文件"
          copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
        - name: "啟動Apache, 并設置開機啟動"
          service: name=httpd state=started enabled=yes
    

    4.4)PlayBook 命令

    // 格式
    ansible-playbook <filename.yml> ... [options]
    

    PlayBook 常用選項

    // "常見選項"
    --syntax-check    # 語法檢查, 可縮寫成 --syntax, 相當于 bash -n 
    -C --check        # 模擬執行, 只檢測可能會發生的改變, 但不真正執行操作, dry run
    --list-hosts      # 列出運行任務的主機    # 舉例: ansible-playbook hello.yaml --list-hosts
    --list-tags       # 列出 tag             
    --list-tasks      # 列出 task            # 舉例: ansible-playbook hello.yaml --list-tasks
    --limit 主機列表  # 針對主機列表中的特定主機執行    # 舉例: ansible-playbook hello.yaml --limit 192.168.80.28
    -i INVENTORY      # 指定主機清單文件, 通常一個項對應一個主機清單文件    # 舉例: ansible-playbook hello.yaml -i /root/hosts
    --start-at-task START_AT_TASK    # 從指定 task 開始執行, 而非從頭開始, START_AT_TASK 為任務的 name    # 舉例: ansible-playbook hello.yml --start-at="start httpd"
    -v -vv  -vvv      # 顯示過程
    
    // 舉例: ansible-playbook hello.yaml --list-hosts
    // 舉例: ansible-playbook hello.yaml --list-tasks
    // 舉例: ansible-playbook hello.yaml --limit 192.168.80.28
    // 舉例: ansible-playbook hello.yaml -i /root/hosts
    // 舉例: ansible-playbook hello.yml --start-at="start httpd"
    

    4.5)Playbook 初步

    4.5.1)利用 PlayBook 創建 MySQL 用戶

    根據寫 Shell 腳本的思路來編寫 PlayBook 即可。( 順序執行 )

    范例: mysql_user.yml

    ---
    - hosts: dbsrvs
      name: 創建 MySQL 用戶
      remote_user: root
      gather_facts: no
    
      tasks:
        - name: '創建 MySQL 用戶組'
          group: 
            name: mysql 
            gid: 306 
            system: yes
        
        - name: '創建 MySQL 用戶'
          user: 
            name: mysql 
            uid: 306 
            group: mysql 
            system: yes
            shell: /sbin/nologin
            home: /data/mysql
            create_home: yes
        
        - name: '查看 MySQL 用戶信息'
          shell: id mysql
      
    # 檢查遠程主機用戶信息              
    [root@ansible ansible] ansible dbsrvs -m shell -a "id mysql"
    
    # 驗證 PlayBook 腳本                
    [root@ansible ansible] ansible-playbook -C mysql_user.yml
    
    # 執行腳本
    [root@ansible ansible] ansible-playbook mysql_user.yml
    

    image.png

    范例: delete-mysql-user.yaml

    [root@ansible ansible] vim delete-mysql-user.yaml
    ---
    - hosts: dbsrvs
      name: 移除 MySQL 用戶
      remote_user: root
      gather_facts: no
    
      tasks:
        - name: '刪除 MySQL 用戶'
          user: name=mysql state=absent remove=yes
        
    [root@ansible ansible] ansible-playbook delete-mysql-user.yaml
    

    image.png

    4.5.2)利用 PlayBook 安裝 nginx

    范例: install_nginx.yml

    # 先將遠程主機的 HTTPD 服務卸載
    [root@ansible ansible] ansible websrvs -m yum -a 'name=httpd state=absent'
    
    # Ansible 控制節點 安裝 nginx 軟件包 ( 實驗: 主要為了拿到 nginx conf 文件 )
    [root@ansible ansible] yum install nginx -y
    [root@ansible ansible] mkdir files
    
    # 拷貝 nginx 配置文件
    [root@ansible ansible] cp /etc/nginx/nginx.conf files/
    [root@ansible ansible] vim files/nginx.conf
        server {
            listen       8080;           # 修改該行                                                           
            listen       [::]:80;
            server_name  _;
            root         /usr/share/nginx/html;
    
    
    # 編寫 HTML 文件 ( 增加 UTF-8 防止亂碼 )
    [root@ansible ansible] vim files/index.html
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <h1> 微信公眾號: 開源極客行 </h1>                                                       
    </head>
    <body>
    </body>
    </html>
    
    # 編寫 PlayBook 文件
    [root@ansible ansible] vim install_nginx.yml
    ---
    # install nginx
    - hosts: websrvs
      remote_user: root
      gather_facts: no
    
      tasks:
        - name: "創建 nginx 用戶組"
          group: name=nginx state=present
        - name: "創建 nginx 用戶"
          user: name=nginx state=present group=nginx
        - name: "安裝 nginx"
          yum: name=nginx state=present
        - name: "拷貝 nginx 配置文件"
          copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf                                 
        - name: "拷貝 nginx 網頁文件"
          copy: src=files/index.html dest=/usr/share/nginx/html/index.html
        - name: "啟動 nginx 服務"
          service: name=nginx state=started enabled=yes
          
    # 驗證 PlayBook 腳本 ( 重要 )
    [root@ansible ansible] ansible-playbook -C install_nginx.yml
    
    # 執行 PalyBook 腳本
    [root@ansible ansible] ansible-playbook install_nginx.yml
    
    # 驗證控制節點端口啟用情況
    [root@ansible ansible] ansible websrvs -m shell -a 'netstat -nltp | grep 8080'
    


    $ vim remove-nginx.yaml
    ---
    - hosts: websrvs
      name: 移除 nginx 軟件
      remote_user: root
      gather_facts: no
    
      tasks:
        - name: 停止nginx服務
          service: name=nginx state=stopped
        - name: 移除nginx軟件
          yum: name=nginx state=absent
        - name: 刪除nginx用戶
          user: name=nginx state=absent remove=yes
        - name: 刪除nginx用戶組
          group: name=nginx state=absent
    

    4.5.3)利用 PlayBook 安裝和卸載 httpd

    范例: install_httpd.yml

    [root@centos8 ansible] vim files/index.html
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <h1> 微信公眾號: 開源極客行 </h1>                                                       
    </head>
    <body>
    </body>
    </html>
    
    [root@centos8 ansible] vim install_httpd.yml 
    ---
    # install httpd
    - hosts: websrvs
      remote_user: root
      gather_facts: no
      
      tasks:
        - name: "Install httpd"
          yum: name=httpd state=present
        - name: "Modify config listen port"
          lineinfile:
            path: /etc/httpd/conf/httpd.conf
            regexp: '^Listen'
            line: 'Listen 8080'
        - name: "Modify config data directory one"
          lineinfile:
            path: /etc/httpd/conf/httpd.conf
            regexp: '^DocumentRoot "/var/www/html"'
            line: 'DocumentRoot "/data/html"'
        - name: "Modify config data directory two"
          lineinfile:
            path: /etc/httpd/conf/httpd.conf
            regexp: '^<Directory "/var/www/html">'
            line: '<Directory "/data/html">'
        - name: "Mkdir website directory"
          file: path=/data/html state=directory
        - name: "copy Web html file"
          copy: src=files/index.html dest=/data/html/
        - name: "Start httpd service"
          service: name=httpd state=started enabled=yes
    
    # 僅針對 192.168.80.28 執行操作
    [root@centos8 ansible] ansible-playbook install_httpd.yml --limit 192.168.80.28
    

    image.png
    image.png

    范例: remove_httpd.yml

    [root@centos8 ansible] vim remove_httpd.yml
    ---
    - hosts: websrvs
      remote_user: root
      gather_facts: no
    
      tasks:
      - name: "remove httpd package"
        yum: name=httpd state=absent
      - name: "remove apache user"
        user: name=apache state=absent
      - name: "remove config file"
        file: name=/etc/httpd state=absent
      - name: "remove web html"
        file: name=/data/html/ state=absent
    
    # 驗證 PlayBook 腳本 ( 重要 )                           
    [root@centos8 ansible] ansible-playbook -C remove_httpd.yml
    
    # 執行 PlayBook 腳本
    [root@centos8 ansible] ansible-playbook remove_httpd.yml 
    

    image.png

    4.5.4)利用 PlayBook 安裝 MySQL 5.6

    范例: 安裝 mysql-5.6.46-linux-glibc2.12
    注意: 建議 MySQL 客戶機的內存需超過 2 G,否則可能會報錯

    # 下載 MySQL 軟件包
    [root@ansible ~] mkdir /data/ansible/files -p && cd /data/ansible/files
    [root@ansible ~] wget https://ftp.iij.ad.jp/pub/db/mysql/Downloads/MySQL-5.6/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
    
    # MySQL 配置文件
    [root@ansible ~] vim /data/ansible/files/my.cnf
    [mysqld]
    socket=/tmp/mysql.sock
    user=mysql
    symbolic-links=0
    datadir=/data/mysql
    innodb_file_per_table=1
    log-bin
    pid-file=/data/mysql/mysqld.pid
    
    [client]
    port=3306
    socket=/tmp/mysql.sock
    
    [mysqld_safe]
    log-error=/var/log/mysqld.log
    
    # 編寫 MySQL 初始腳本
    [root@ansible ~] vim /data/ansible/files/secure_mysql.sh
    #!/bin/bash
    /usr/local/mysql/bin/mysql_secure_installation <<EOF
    y
    123456
    123456
    y
    y
    y
    y
    
    [root@ansible files] chmod +x secure_mysql.sh
    
    [root@ansible files]# tree /data/ansible/files/
    /data/ansible/files/
    ├── my.cnf
    ├── mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
    └── secure_mysql.sh
    
    0 directories, 3 files
    
    # 編寫 PlayBook
    [root@ansible ~] vim /data/ansible/install_mysql.yml
    ---
    # install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
    - hosts: dbsrvs
      remote_user: root
      gather_facts: no
      
      tasks:
        - name: "install packages"
          yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
        - name: "create mysql group"
          group: name=mysql gid=306
        - name: "create mysql user"
          user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
        - name: "copy tar to remote host and file mode"
          unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz dest=/usr/local/ owner=root group=root
        - name: "create linkfile /usr/local/mysql"
          file: src=/usr/local/mysql-5.6.46-linux-glibc2.12-x86_64 dest=/usr/local/mysql state=link
        - name: "create dir /data/mysql"
          file: path=/data/mysql state=directory
        - name: "data dir"	# 該步驟貌似有點問題
          shell: chdir=/usr/local/mysql ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
          tags: data
          ignore_errors: yes	# 忽略錯誤,繼續執行
        - name: "config my.cnf"
          copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf 
        - name: "service script"
          shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
        - name: "enable service"
          shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
          
          tags: service
        - name: "PATH variable"
          copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
        - name: "secure script"
          script: src=/data/ansible/files/secure_mysql.sh
          tags: script
    
    # 執行 PlayBook 腳本
    [root@ansible ~] ansible-playbook install_mysql.yml
    

    image.png

    范例: install_mariadb.yml

    # 編寫 PlayBook
    [root@ansible ~] vim /data/ansible/install_mariadb.yml
    ---
    # Installing MariaDB Binary Tarballs
    - hosts: dbsrvs
      remote_user: root
      gather_facts: no
      tasks:
        - name: create group
          group: name=mysql gid=27 system=yes
        - name: create user
          user: name=mysql uid=27 system=yes group=mysql shell=/sbin/nologin home=/data/mysql create_home=no
        - name: mkdir datadir
          file: path=/data/mysql owner=mysql group=mysql state=directory
        - name: unarchive package
          unarchive: src=/data/ansible/files/mariadb-10.2.27-linux-x86_64.tar.gz dest=/usr/local/ owner=root group=root
        - name: link
         file: src=/usr/local/mariadb-10.2.27-linux-x86_64 path=/usr/local/mysql state=link
         - name: install database
           shell: chdir=/usr/local/mysql  ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
        - name: config file
          copy: src=/data/ansible/files/my.cnf  dest=/etc/ backup=yes
        - name: service script
          shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
        - name: start service
          service: name=mysqld state=started enabled=yes
        - name: PATH variable
          copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
        
    # 執行 PlayBook 腳本
    [root@ansible ~] ansible-playbook install_mariadb.yml    
    

    4.6)ignore_errors 忽略錯誤

    如果一個 Task 出錯,默認將不會繼續執行后續的其它 Task

    我們可以利用 **ignore_errors:yes ** 忽略此 Task 的錯誤,繼續向下執行 PlayBook 其它 Task

    [root@ansible ansible] vim test_ignore.yml
    ---
    - hosts: websrvs
      
      tasks:
        - name: error test
          command: /bin/false    # 返回失敗結果的命令
          ignore_errors: yes     # 忽略錯誤, 繼續執行
        - name: continue
          command: wall continue
          
    [root@ansible ansible] ansible-playbook test_ignore.yml
    

    4.7)Playbook 中使用 handlers 和 notify

    Handlers 本質是 task list,類似于 MySQL 中的觸發器觸發的行為,其中的 task 與前述的 task 并沒有本質上的不同,主要用于當關注的資源發生變化時,才會采取一定的操作。
    而 Notify 對應的 action 可用于在每個 play 的最后被觸發,這樣可避免多次有改變發生時每次都執行指定的操作,僅在所有的變化發生完成后一次性地執行指定操作。在 notify 中列出的操作稱為 handler,也即 notify 中調用 handler 中定義的操作。

    注意:

    • 如果多個 Task 通知了相同的 handlers, 此 handlers 僅會在所有 Tasks 結束后運行一次。
    • 只有 notify 對應的 task 發生改變了才會通知 handlers,沒有改變則不會觸發 handlers。
    • handlers 是在所有前面的 tasks 都成功執行才會執行,如果前面任何一個 task 失敗,會導致 handler 跳過執行,可以使用 force_handlers:yes 強制執行 handler。

    案例:

    ---
    - hosts: websrvs
      remote_user: root
      gather_facts: no
      
      tasks:
        - name : Install httpd
          yum: name=httpd state=present
        - name : Install configure file
          copy: src=files/httpd.conf dest=/etc/httpd/conf/
        # 修改 http 服務的端口號
        - name: config httpd conf
          lineinfile: "path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 8080'"
          notify:
            - restart httpd 
            - wall
        - name: ensure apache is running
          service: name=httpd state=started enabled=yes
    
      handlers:
        - name: restart httpd
          service: name=httpd state=restarted
        - name: wall
          command: wall "The config file is changed"
    

    案例:
    在 Ansible 中,handlers 部分 用于定義當某些條件滿足時應該執行的任務。
    這些任務通常是 由 notify 指令觸發的,這些 notify 指令可以放在其他任務中。
    當任務完成并且其狀態發生變化時,與任務相關聯的 notify 指令會觸發相應的 handler。
    案例: 當 Copy Nginx Config File 任務完成并發生改變時,它會觸發名為 Restart Nginx Service 的 handler。Nginx 服務將被重啟,以應用新的配置。
    模塊的大概執行流程:https://blog.csdn.net/wangjiachenga/article/details/122980073

    [root@ansible ansible] vim files/nginx.conf
        server {
            listen       80;                # 修改該行
            listen       [::]:80;
            server_name  _;
            root         /usr/share/nginx/html;
    
    [root@ansible ansible] vim install_nginx.yml
    ---
    # install nginx
    - hosts: websrvs
      remote_user: root
      gather_facts: no
    
      tasks:
        - name: "Add Nginx Group"
          group: name=nginx state=present
        - name: "Add Nginx User"
          user: name=nginx state=present group=nginx
        - name: "Install Nginx"
          yum: name=nginx state=present
        - name: "Copy Nginx Config File"
          copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf
          notify: Restart Nginx Service    # 定義 notify 觸發器
        - name: "Copy Web Page File"
          copy: src=files/index.html dest=/usr/share/nginx/html/index.html
        - name: "Start Nginx Service"
          service: name=nginx state=started enabled=yes
            
       
      handlers:    # 觸發如下操作
        - name: "Restart Nginx Service"
          service: name=nginx state=restarted enabled=yes
          
    [root@ansible ansible] ansible-playbook install_nginx.yml
    

    范例: 強制執行 handlers

    - hosts: websrvs
      force_handlers: yes # 無論 task 中的任何一個 task 失敗, 仍強制執行 handlers
      tasks:
        - name: config file
          copy: src=nginx.conf dest=/etc/nginx/nginx.conf
          notify: restart nginx
        - name: install package
          yum: name=no_exist_package
        
      handlers:
        - name: "restart nginx"
          service: name=nginx state=restarted
    

    4.8)Playbook 中使用 tags 組件

    官方文檔:https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html
    參考文檔:https://blog.csdn.net/weixin_42171272/article/details/135268747
    如果寫了一個很長的 PlayBook,其中有很多的任務,這并沒有什么問題,不過在實際使用這個劇本時,可能只是想要執行其中的一部分任務。
    或者,你只想要執行其中一類任務而已,而并非想要執行整個劇本中的全部任務,這個時候我們就可以借助 tags 標簽實現這個需求。

    tags 可以幫助我們對任務進行 打標簽 的操作,與模塊名同級,當任務存在標簽以后,我們就可以在執行 PlayBook 時,借助標簽,指定執行哪些任務,或者指定不執行哪些任務了。

    在 PlayBook 文件中,利用 tags 組件,為特定 task 指定標簽。
    當在執行 PlayBook 時,可以只執行特定 tags 的 task,而非整個 PlayBook 文件??梢砸粋€ task 對應多個 tag,也可以多個 task 對應一個 tag。
    還有另外 3 個特殊關鍵字用于標簽,tagged,untagged 和 all,它們分別是僅運行已標記,只有未標記和所有任務。

    [root@ansible ~] vim httpd.yml
    ---
    # tags example
    - hosts: websrvs
      remote_user: root
      gather_facts: no
      
    tasks:
      - name: "Install httpd"
        yum: name=httpd state=present
      - name: "Install configure file"
        copy: src=files/httpd.conf dest=/etc/httpd/conf/
        tags: [ conf,file ]    # 寫在一行
          - conf               # 寫成多行
          - file
      - name: "start httpd service"
        tags: service          # 寫在一行
        service: name=httpd state=started enabled=yes
    
    # 查看標簽
    [root@ansible ~] ansible-playbook --list-tags httpd.yml
    
    # 僅執行標簽動作
    [root@ansible ~] ansible-playbook -t conf,service httpd.yml
    
    # 跳過標簽動作 
    [root@ansible ~] ansible-playbook --skip-tags conf httpd.yml
    [root@ansible ~] ansible-playbook httpd.yml --skip-tags untagged
    

    4.9)Playbook 中 使用變量

    Playbook 中同樣也支持變量

    變量名: 僅能由字母、數字和下劃線組成,且只能以字母開頭

    // 變量定義
    # variable=value
    variable: value    # 建議
    

    范例:

    # http_port=80
    http_port: 80    # 建議
    

    變量調用方式:
    通過 {{ variable_name }} 調用變量,且變量名前后建議加空格,
    有時用 "{{ variable_name }}" 才生效

    變量來源:

    1. ansible 的 setup facts 遠程主機的所有變量 都可直接調用
    2. 通過命令行指定變量,優先級最高
    ansible-playbook -e varname=value test.yml
    
    1. 在 PlayBook 文件中定義
    vars:
      var1: value1
      var2: value2
    
    1. 在獨立的變量 YAML 文件中定義
    - hosts: all
      vars_files:
        - vars.yml
    
    1. 在主機清單文件中定義
    • 主機(普通)變量:主機組中主機單獨定義,優先級高于公共變量
    • 組(公共)變量:針對主機組中所有主機定義統一變量
    1. 在項目中針對主機和主機組定義

    在項目目錄中創建 host_vars 和 group_vars 目錄

    1. 在 role 中定義

    變量的優先級從高到低如下

    -e 選項定義變量 > playbook 中 vars_files > playbook 中 vars 變量定義 > host_vars/主機名 文件 > 主機清單中主機變量 > group_vars/主機組名文件 > group_vars/all文件 > 主機清單組變量

    4.9.1)使用 setup 模塊中變量

    本模塊自動在 PlayBook 調用,不要用 ansible 命令調用,生成的系統狀態信息,并存放在 facts 變量中。
    facts 包括的信息很多,**如: **主機名,IP,CPU,內存,網卡等
    facts 變量的實際使用場景案例

    • 通過 facts 變量獲取被控端 CPU 的個數信息,從而生成不同的 Nginx 配置文件
    • 通過 facts 變量獲取被控端內存大小信息,從而生成不同的 memcached 的配置文件
    • 通過 facts 變量獲取被控端主機名稱信息,從而生成不同的 Zabbix 配置文件
    • ......

    案例:使用 setup 變量

    [root@centos8 ~] ansible 192.168.80.18 -m setup -a "filter=ansible_nodename"
    [root@centos8 ~] ansible 192.168.80.18 -m setup -a 'filter="ansible_default_ipv4"'
    

    范例:

    [root@ansible ~] vim var.yml
    ---
    # var1.yml
    - hosts: websrvs
      remote_user: root
      gather_facts: yes    # 注意: 這個需要 yes 啟用
      
      tasks:
        - name: "create log file"
          file: name=/root/{{ ansible_nodename }}.log state=touch owner=wangj mode=600
          
    [root@ansible ~] ansible-playbook var.yml
    

    范例: 顯示 ens33 網卡的 IP 地址

    [root@ansible ansible] vim show_ip.yml 
    - hosts: websrvs
      
      tasks:
        - name: show eth0 ip address {{ ansible_facts["ens33"]["ipv4"]["address"] }}    # name 中也可以調用變量
          debug:
            msg: IP address {{ ansible_ens33.ipv4.address }}    # 注意: 網卡名稱
            # msg: IP address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
            # msg: IP address {{ ansible_facts.eth0.ipv4.address }}
            # msg: IP address {{ ansible_default_ipv4.address }}
            # msg: IP address {{ ansible_eth0.ipv4.address }}
            # msg: IP address {{ ansible_eth0.ipv4.address.split('.')[-1] }} # 取 IP 中的最后一個數字
    
    [root@ansible ansible] ansible-playbook -v show_ip.yml
    

    范例:

    [root@ansible ~] vim test.yml
    ---
    - hosts: websrvs
      tasks:
        - name: test var
          file: path=/root/{{ ansible_facts["ens33"]["ipv4"]["address"] }}.log state=touch    # 注意: 網卡名稱信息
          # file: path=/root/{{ ansible_ens33.ipv4.address }}.log state=touch # 和上面效果一樣
    
    [root@ansible ~] ansible-playbook test.yml
    

    4.9.2)在 PlayBook 命令行中定義變量

    范例:

    [root@ansible ~] vim var2.yml
    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: "install package"
          yum: name={{ pkname }} state=present    # 調用變量
    
    # 在 PlayBook 命令行中定義變量
    [root@ansible ~] ansible-playbook -e pkname=vsftpd var2.yml
    

    范例:
    也可以將多個變量放在一個文件中

    # 也可以將多個變量放在一個文件中
    [root@ansible ~] cat vars
    pkname1: memcached
    pkname2: redis
    
    [root@ansible ~] vim var2.yml
    ---
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: install package {{ pkname1 }}    # 名稱也調用變量 ( 利于我們清楚正在安裝什么軟件包 )
          yum: name={{ pkname1 }} state=present
        - name: install package {{ pkname2 }}
          yum: name={{ pkname2 }} state=present
    
    # 方式一
    [root@ansible ~] ansible-playbook -e pkname1=memcached -e pkname2=redis var2.yml
    
    # 方式二 ( 指定存放著變量的文件 )
    [root@ansible ~] ansible-playbook -e '@vars' var2.yml
    

    4.9.3)在 PlayBook 文件中定義變量

    范例: 也可以在 PlayBook 文件中定義變量

    [root@ansible ~] vim var3.yml
    ---
    - hosts: websrvs
      remote_user: root
      vars:
        username: user1        # 定義變量
        groupname: group1      # 定義變量
    
      tasks:
        - name: "create group {{ groupname }}"
          group: name={{ groupname }} state=present
        - name: "create user {{ username }}"
          user: name={{ username }} group={{ groupname }} state=present
    
    # 執行 PlayBook 文件
    [root@ansible ~] ansible-playbook var3.yml
    
    # 驗證
    [root@ansible ~] ansible websrvs -m shell -a 'id user1'
    

    范例:變量之間的相互調用

    [root@ansible ~] vim var4.yaml
    ---
    - hosts: websrvs
      remote_user: root
      vars:
        collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"	# 基于默認變量定義了一個新的變量
    
      tasks:
        - name: "Create IP directory"
          file: name="{{collect_info}}" state=directory		# 引用變量
    
    # 執行結果
    tree /data/test/
    /data/test/
    └── 192.168.80.18
    
    1 directory, 0 files
    

    范例: 變量之間的 相互調用

    [root@ansible ansible] cat var2.yml
    ---
    - hosts: websrvs
      vars:
        suffix: "txt"
        file: "{{ ansible_nodename }}.{{suffix}}"		# 基于默認變量定義了一個新的變量
        
      tasks:
        - name: test var
          file: path="/data/{{file}}" state=touch		# 引用變量
    

    范例:安裝多個包

    # 實例一
    [root@ansible ~] cat install.yml 
    - hosts: websrvs
      vars:
        web: httpd
        db: mariadb-server
        
      tasks:
        - name: install {{ web }} {{ db }}
          yum:
            name:
              - "{{ web }}"
              - "{{ db }}"
            state: latest
    
    # 實例二      
    [root@ansible ~] cat install2.yml 
    - hosts: websrvs
      tasks:
        - name: install packages
          yum: name={{ pack }}
          vars:
            pack:
              - httpd
              - memcached
    

    范例: 安裝指定版本的 MySQL
    新增 PlayBook 定義變量功能

    [root@ansible ansible] cat install_mysql.yml 
    ---
    # install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
    - hosts: dbsrvs
      remote_user: root
      gather_facts: no
      vars:
        version: "mysql-5.6.46-linux-glibc2.12-x86_64"
        suffix: "tar.gz"
        file: "{{version}}.{{suffix}}"
        
      tasks:
        - name: "install packages"
          yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
        - name: "create mysql group"
          group: name=mysql gid=306
        - name: "create mysql user"
          user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
        - name: "copy tar to remote host and file mode"
          unarchive: src=/data/ansible/files/{{file}} dest=/usr/local/ owner=root group=root
        - name: "create linkfile /usr/local/mysql"
          file: src=/usr/local/{{version}} dest=/usr/local/mysql state=link
        - name: "data dir"
          shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
          tags: data
        - name: "config my.cnf"
          copy: src=/data/ansible/files/my.cnf  dest=/etc/my.cnf
        - name: "service script"
          shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
        - name: "enable service"
          shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
          tags: service
        - name: "PATH variable"
          copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
        - name: "secure script"
          script: /data/ansible/files/secure_mysql.sh
          tags: script
    

    4.9.4)使用變量文件

    可以在一個 獨立的 PlayBook 文件 中定義變量,在另一個 PlayBook 文件中引用變量文件中的變量,比 PlayBook 中定義的變量優化級高

    # 編寫變量文件
    vim vars.yml
    ---
    # variables file
      package_name: mariadb-server
      service_name: mariadb
    
    # 在 PlayBook 調用變量文件
    vim var5.yml
    ---
    # install package and start service
    - hosts: dbsrvs
      remote_user: root
      vars_files:            # 在 PlayBook 調用變量文件
        - vars.yml
        
      tasks:
        - name: "install package"
          yum: name={{ package_name }}
          tags: install
        - name: "start service"
          service: name={{ service_name }} state=started enabled=yes
    

    范例:

    cat vars2.yml
    ---
    var1: httpd
    var2: nginx
    
    cat var6.yml
    ---
    - hosts: web
      remote_user: root
      vars_files:
        - vars2.yml
        
      tasks:
        - name: create httpd log
          file: name=/app/{{ var1 }}.log state=touch
        - name: create nginx log
          file: name=/app/{{ var2 }}.log state=touch
    

    4.9.5)針對主機和主機組 定義變量

    4.9.5.1)在主機清單中 針對所有項目的主機和主機分組對應變量

    所有項目的 主機變量
    在 inventory 主機清單文件中 為指定的主機定義變量 以便于在 PlayBook 中使用

    // 范例: 定義主機變量
    [websrvs]
    www1.magedu.com http_port=80 maxRequestsPerChild=808
    www2.magedu.com http_port=8080 maxRequestsPerChild=909
    

    所有項目的組(公共)變量
    在 inventory 主機清單文件中 賦予給指定組內所有主機上
    在 PlayBook 中可用的變量,如果和主機變量是同名,優先級低于主機變量

    // 范例: 公共變量
    [websrvs:vars]
    http_port=80
    ntp_server=ntp.magedu.com
    nfs_server=nfs.magedu.com
    
    -- K8S 案例 --
    [all:vars]
    # --------- Main Variables ---------------
    # Cluster container-runtime supported: docker, containerd
    CONTAINER_RUNTIME="docker"
    
    # Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
    CLUSTER_NETWORK="calico"
    
    # Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
    PROXY_MODE="ipvs"
    
    # K8S Service CIDR, not overlap with node(host) networking
    SERVICE_CIDR="192.168.0.0/16"
    
    # Cluster CIDR (Pod CIDR), not overlap with node(host) networking
    CLUSTER_CIDR="172.16.0.0/16"
    
    # NodePort Range
    NODE_PORT_RANGE="20000-60000"
    
    # Cluster DNS Domain
    CLUSTER_DNS_DOMAIN="magedu.local."
    

    范例:

    [root@ansible ~] vim /etc/ansible/hosts
    [websrvs]
    192.168.80.18 hname=www1 domain=magedu.io    # 定義主機變量 ( 主機變量 優先級高 )
    192.168.80.28 hname=www2
    
    [websrvs:vars]        # 定義分組變量
    mark="-"
    
    [all:vars]            # 定義公共變量 ( 公共變量優先級低 )
    domain=magedu.org
    
    # 調用變量 ( 修改主機名 )
    [root@ansible ~] ansible websrvs -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
    

    # 命令行指定變量:
    # -e 定義變量的優先級更高
    [root@ansible ~] ansible websrvs -e domain=magedu.cn -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
    

    范例: K8S 的 ansible 變量文件

    [etcd]
    10.0.0.104 NODE_NAME=etcd1
    10.0.0.105 NODE_NAME=etcd2
    10.0.0.106 NODE_NAME=etcd3
    
    [kube-master]
    10.0.0.103 NEW_MASTER=yes
    10.0.0.101
    10.0.0.102
    
    [kube-node]
    10.0.0.109 NEW_NODE=yes
    10.0.0.107
    10.0.0.108
    
    [harbor]
    
    [ex-lb]
    10.0.0.111 LB_ROLE=master EX_APISERVER_VIP=10.0.0.100 EX_APISERVER_PORT=8443
    10.0.0.112 LB_ROLE=backup EX_APISERVER_VIP=10.0.0.100 EX_APISERVER_PORT=8443
    
    [chrony]
    
    [all:vars]
    CONTAINER_RUNTIME="docker"
    CLUSTER_NETWORK="calico"
    PROXY_MODE="ipvs"
    SERVICE_CIDR="192.168.0.0/16"
    CLUSTER_CIDR="172.16.0.0/16"
    NODE_PORT_RANGE="20000-60000"
    CLUSTER_DNS_DOMAIN="magedu.local."
    bin_dir="/usr/bin"
    ca_dir="/etc/kubernetes/ssl"
    base_dir="/etc/ansible"
    

    4.9.5.2)針對當前項目的主機和主機組的變量

    上面的方式是針對所有項目都有效,而官方更建議的方式是使用 ansible 特定項目的主機變量和組變量。生產建議在項目目錄中創建額外的兩個變量目錄,分別是 host_vars 和 group_vars。
    host_vars: 下面的文件名和主機清單主機名一致,針對單個主機進行變量定義,格式:host_vars/hostname( 主機變量 )
    group_vars: 下面的文件名和主機清單中組名一致,針對單個組進行變量定義,格式:gorup_vars/groupname( 分組變量 )
    group_vars/all: 文件內定義的變量對所有組都有效( 公共變量 )

    范例: 特定項目的主機變量和分組變量
    建議: 主機清單不定義變量( 僅存放主機分組信息 )
    變量統一定義在項目目錄下的變量目錄中( 條理非常清晰 )

    # 創建項目目錄
    [root@ansible ansible] mkdir /data/ansible/test_project -p
    [root@ansible ansible] cd /data/ansible/test_project
    
    # 編寫項目主機清單文件 ( 僅存放主機分組信息 )
    [root@ansible test_project] vim hosts
    [websrvs]
    192.168.80.18
    192.168.80.28
    
    # 創建項目主機變量目錄
    [root@ansible test_project] mkdir host_vars
    
    # 創建項目分組變量目錄
    [root@ansible test_project] mkdir group_vars
    
    # 定義項目主機變量信息
    [root@ansible test_project] vim host_vars/192.168.80.18
    id: 1
    [root@ansible test_project] vim host_vars/192.168.80.28
    id: 2
    
    # 定義項目分組變量信息
    [root@ansible test_project] vim group_vars/websrvs 
    name: web
    [root@ansible test_project] vim group_vars/all
    domain: magedu.org
    
    # 驗證項目變量文件
    [root@ansible test_project] tree host_vars/ group_vars/
    host_vars/
    ├── 192.168.80.18
    └── 192.168.80.28
    group_vars/
    ├── all
    └── websrvs
    
    0 directories, 4 files
    
    # 定義 PlayBook 文件
    [root@ansible test_project] vim test.yml
    - hosts: websrvs
    
      tasks:
        - name: get variable
          command: echo "{{name}}{{id}}.{{domain}}"
          register: result
        - name: print variable
          debug:
            msg: "{{result.stdout}}"
            
    # 執行
    [root@ansible test_project] ansible-playbook test.yml
    

    4.9.6)register 注冊變量( 重要 )

    參考:https://blog.csdn.net/byygyy/article/details/105624602
    在 PlayBook 中可以使用 register 將捕獲命令的輸出 保存在臨時變量中
    然后使用 debug 模塊進行顯示輸出
    范例: 利用 debug 模塊輸出變量
    作用: 將 Shell 模塊中命令的輸出信息賦值給 register 注冊變量中
    注意: ansible 執行結果一般都會返回一個字典類型的數據,你會看到很多你不關心的字段,可以通過指定字典的 key,例如 stdout 或 stdout_lines,只看到你關心的數據。

    [root@ansible ~] vim register1.yml
    - hosts: 192.168.80.18
      tasks:
        - name: "get variable"
          shell: hostname
          register: name
          
        - name: "print variable"
          debug:
            msg: "{{ name }}"                   # 輸出 register 注冊的 name 變量的全部信息, 注意: 變量要加 "" 引起來
            # msg: "{{ name.cmd }}"             # 顯示命令
            # msg: "{{ name.rc }}"              # 顯示命令成功與否
            # msg: "{{ name.stdout }}"          # 顯示命令的輸出結果為字符串形式
            # msg: "{{ name.stdout_lines }}"    # 顯示命令的輸出結果為列表形式
            # msg: "{{ name.stdout_lines[0] }}" # 顯示命令的輸出結果的列表中的第一個元素
            # msg: "{{ name['stdout_lines'] }}" # 顯示命令的執行結果為列表形式
            
    // 說明
    在第一個 task 中, 使用了 register 注冊變量名為 name;
    當 Shell 模塊執行完畢后, 會將數據放到該
    變量中.
    在第二個 task 中, 使用了 debug 模塊, 并從變量 name 中獲取數據.
    
    // 注意:
    # 輸出的 name 實際上相當于是一個字典
    # 里面包含很多個鍵值對信息 ( 我們需要哪個鍵值對信息,需要指定性選擇該鍵值 )
    # 比如: name.stdout ( 在 name 變量后調用鍵信息 )
    [root@centos8 ~] ansible-playbook register1.yml
    

    ansible 執行結果一般都會返回一個字典類型的數據,以此你會看到很多你不關心的字段,我們可以通過指定字典的 key,例如 stdout 或 stdout_lines,只看到你關心的數據。

    [root@ansible ~] vim register1.yml
    - hosts: 192.168.80.18
      tasks:
        - name: "get variable"
          shell: hostname
          register: name
          
        - name: "print variable"
          debug:
            msg: "{{ name.stdout }}"            # 取 name 變量的 stdout 鍵值
            
    [root@centos8 ~] ansible-playbook register1.yml
    

    范例:使用 register 注冊變量 創建文件

    [root@ansible ~] vim register2.yml 
    - hosts: websrvs
    
      tasks:
        - name: "get variable"
          shell: hostname
          register: name
        - name: "create file"
          file: dest=/root/{{ name.stdout }}.log state=touch
    
    [root@ansible ~] ansible-playbook register2.yml
    [root@centos8 ~] ll /root | grep log
    

    范例: register 和 debug 模塊
    參考:http://www.diao-diao.com/dgp-zjz/p/15683546.html
    自定義 debug 模塊的輸出結果( 默認輸出的 msg 鍵內容 )

    [root@ansible ~] vim debug_test.yml
    ---
    - hosts: 192.168.80.8
      tasks:
    
        - shell: echo "hello world"
          register: say_hi
    
        - shell: "awk -F: 'NR==1{print $1}' /etc/passwd"
          register: user
    
        - debug:
            var: say_hi.stdout   # 自定義輸出變量代替 msg
        - debug:
            var: user.stdout     # 自定義輸出變量代替 msg
    
    [root@ansible ~] ansible-playbook debug_test.yml
    

    范例: 安裝啟動服務并檢查

    [root@ansible ansible] vim service.yml
    ---
    - hosts: websrvs
      vars:
        package_name: nginx
        service_name: nginx
    
      tasks:
        - name: "install {{ package_name }}"
          yum: name={{ package_name }}
        - name: "start {{ service_name }}"
          service: name={{ service_name }} state=started enabled=yes
        - name: "check service status"
          shell: ps aux | grep {{ service_name }}
          register: check_service
        - name: debug
          debug:
            msg: "{{ check_service.stdout_lines }}"
    
    [root@ansible ansible] ansible-playbook service.yml
    

    范例: 批量修改主機名

    [root@ansible ansible] vim hostname.yml
    - hosts: websrvs
      vars:
        host: web
        domain: wuhanjiayou.cn
    
      tasks:
        - name: "get variable"
          shell: echo $RANDOM | md5sum | cut -c 1-8
          register: get_random
        - name: "print variable"
          debug:
            msg: "{{ get_random.stdout }}"
        - name: "set hostname"
          hostname: name={{ host }}-{{ get_random.stdout }}.{{ domain }}
    
    [root@ansible ansible] ansible-playbook hostname.yml     
    

    posted @ 2024-03-14 14:24  譜次·  閱讀(166)  評論(0編輯  收藏  舉報
    免费视频精品一区二区_日韩一区二区三区精品_aaa在线观看免费完整版_世界一级真人片
    <bdo id="4g88a"><xmp id="4g88a">
  • <legend id="4g88a"><code id="4g88a"></code></legend>