ansible基礎

一、ansible

1.1、ansible

ansible基于Python開發(fā),集合了眾多運維工具(puppet、chef、func、fabric)的優(yōu)點,實現(xiàn)了批量系統(tǒng)配置、批量程序部署、批量運行命令等功能。ansible是基于 paramiko 開發(fā)的,并且基于模塊化工作,本身沒有批量部署的能力。真正具有批量部署的是ansible所運行的模塊,ansible只是提供一種框架。ansible不需要在遠程主機上安裝client/agents,因為它們是基于ssh來和遠程主機通訊的。ansible目前已經已經被紅帽官方收購,是自動化運維工具中大家認可度最高的,并且上手容易,學習簡單。是每位運維工程師必須掌握的技能之一。

1.2、ansible特點

部署簡單,只需在主控端部署Ansible環(huán)境,被控端無需做任何操作;
默認使用SSH協(xié)議對設備進行管理;
有大量常規(guī)運維操作模塊,可實現(xiàn)日常絕大部分操作;
配置簡單、功能強大、擴展性強;
支持API及自定義模塊,可通過Python輕松擴展;
通過Playbooks來定制強大的配置、狀態(tài)管理;
輕量級,無需在客戶端安裝agent,更新時,只需在操作機上進行一次更新即可;
提供一個功能強大、操作性強的Web管理界面和REST API接口——AWX平臺。

1.3、ansible架構圖

ansible架構圖
Ansible:Ansible核心程序。
HostInventory:記錄由Ansible管理的主機信息,包括端口、密碼、ip等。
Playbooks:“劇本”YAML格式文件,多個任務定義在一個文件中,定義主機需要調用哪些模塊來完成的功能。
CoreModules:核心模塊,主要操作是通過調用核心模塊來完成管理任務。
CustomModules:自定義模塊,完成核心模塊無法完成的功能,支持多種語言。
ConnectionPlugins:連接插件,Ansible和Host通信使用

1.4、ansible任務執(zhí)行

# 1、ad-hoc模式(點對點模式)
使用單個模塊,支持批量執(zhí)行單條命令。ad-hoc 命令是一種可以快速輸入的命令,而且不需要保存起來的命令。就相當于bash中的一句話shell。
# playbook模式(劇本模式)
是Ansible主要管理方式,也是Ansible功能強大的關鍵所在。playbook通過多個task集合完成一類功能,如Web服務的安裝部署、數(shù)據(jù)庫服務器的批量備份等。可以簡單地把playbook理解為通過組合多條ad-hoc操作的配置文件。
簡單理解就是Ansible在運行時, 首先讀取ansible.cfg中的配置, 根據(jù)規(guī)則獲取Inventory中的管理主機列表, 并行的在這些主機中執(zhí)行配置的任務, 最后等待執(zhí)行返回的結果。

二、ansible搭建

2.1、環(huán)境

ip hostname 備注
192.168.13.211 vm-master-01 ansible控制端
192.168.13.12 vm-master-02 ansible被控制端
192.168.13.225 vm-master-03 ansible被控制端

2.2、安裝

# 官方文檔
https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible-on-rhel-centos-or-fedora
yum install epel-release
yum install ansible
# ansible 幫助信息
ansible-doc -a                      # 顯示所有模塊文檔
ansible-doc -l;--list               # 列出可用模塊
ansible-doc -s                      # 顯示指定模塊的playbook片段
eg:
 ansible-doc -l
ansible-doc ping
ansible-doc -s ping

2.3、ansible配置文件

inventory = /etc/ansible/hosts      #這個參數(shù)表示資源清單inventory文件的位置
library = /usr/share/ansible        #指向存放Ansible模塊的目錄,支持多個目錄方式,只要用冒號(:)隔開就可以
forks = 5       #并發(fā)連接數(shù),默認為5
sudo_user = root        #設置默認執(zhí)行命令的用戶
remote_port = 22        #指定連接被管節(jié)點的管理端口,默認為22端口,建議修改,能夠更加安全
host_key_checking = False       #設置是否檢查SSH主機的密鑰,值為True/False。關閉后第一次連接不會提示配置實例
timeout = 60        #設置SSH連接的超時時間,單位為秒
log_path = /var/log/ansible.log     #指定一個存儲ansible日志的文件(默認不記錄日志)

2.4、ansible常用命令

/usr/bin/ansible  Ansibe AD-Hoc 臨時命令執(zhí)行工具,常用于臨時命令的執(zhí)行
/usr/bin/ansible-doc   Ansible 模塊功能查看工具
/usr/bin/ansible-galaxy  下載/上傳優(yōu)秀代碼或Roles模塊 的官網平臺,基于網絡的
/usr/bin/ansible-playbook  Ansible 定制自動化的任務集編排工具
/usr/bin/ansible-pull  Ansible遠程執(zhí)行命令的工具,拉取配置而非推送配置(使用較少,海量機器時使用,對運維的架構能力要求較高)
/usr/bin/ansible-vault  Ansible 文件加密工具
/usr/bin/ansible-console  Ansible基于Linux Consoble界面可與用戶交互的命令執(zhí)行工具

2.5、ansible控制端環(huán)境配置

# ansible控制端上進行操作
# 1、生成私鑰
ssh-keygen 
# 2、向主機分發(fā)私鑰
ssh-copy-id root@vm-master-01
ssh-copy-id root@vm-master-02
ssh-copy-id root@vm-master-03
# 3、配置hosts
[root@vm-master-01 ansible]# cat /etc/ansible/hosts
[test]
vm-master-01 ansible_ssh_host=192.168.13.211 ansible_ssh_port=22
vm-master-02 ansible_ssh_host=192.168.13.12 ansible_ssh_port=22
vm-master-03 ansible_ssh_host=192.168.13.225 ansible_ssh_port=22

三、ansible基本使用

ansible通過ssh實現(xiàn)配置管理、應用部署、任務執(zhí)行等功能,建議配置ansible端能基于密鑰認證的方式聯(lián)系各個管理節(jié)點:
ansible <host-pattern> [-m module_name] [-a args]
--version  顯示版本
-m module 指定模塊,默認為command
-v 詳細過程 -vv -vvv更為詳細
--list-hosts 顯示主機列表,可簡寫為--list
-k,--ask-pass tishi 提示輸入ssh鏈接密碼,默認key驗證
-C,--check 檢查,并不執(zhí)行
-T,-timeout=TIMEOUT 執(zhí)行命令的超時時間,默認10s
-u,--user=REMOTE_USER  遠程執(zhí)行的用戶
# ansible的host-pattern匹配主機的列表
# 1、All: 表示所有Inventory中的所有主機
        ansible all -m ping
#2、*: 通配符
        ansible "*" -m ping
        ansible 10.10.0.* -m ping
        ansible "*srs" -m ping
# 3、或
        ansible "web1:web2" -m ping
        ansible "192.168.1.10:192.168.1.11" -m ping
# 4、邏輯與
        ansible "web1:&web2" -m ping  # 在web1并且在web2組中的主機
# 5、邏輯非
        ansible 'web1:!web2' -m ping # 在web1組中但不在web2組中
# 6、正則
        ansible "~(wa|we).*\.baidu\.com" -m ping

ansible命令執(zhí)行過程:


ansible命令執(zhí)行過程

3.1、command模塊

# 遠程執(zhí)行命令,command模塊是默認情況下的模塊,這個模塊不支持shell變量和管道
ansible vm-master-01 -m command -a "ls /"                         <可自行>
ansible vm-master-01 -m command -a "ls / | grep data"       <有管道、不可執(zhí)行>

3.2、shell模塊

# 支持shell變量和管道
ansible vm-master-01 -m shell -a "ls /" 
ansible vm-master-01 -m shell -a "ls / | grep data"

3.3、yum模塊

ansible PROD -m yum -a 'name=vsftpd state=present'
常用參數(shù)介紹:
name=  #所安裝的包的名稱
state=  #present--->安裝, latest--->安裝最新的, absent---> 卸載軟件。
update_cache  #強制更新yum的緩存
conf_file  #指定遠程yum安裝時所依賴的配置文件(安裝本地已有的包)。
disable_pgp_check  #是否禁止GPG checking,只用于presentor latest。
disablerepo  #臨時禁止使用yum庫。 只用于安裝或更新時。
enablerepo  #臨時使用的yum庫。只用于安裝或更新時。

3.4、service模塊

ansible vm-master-02 -m service -a "name=vsftpd state=started enabled=yes"
常用參數(shù)介紹:
arguments #命令行提供額外的參數(shù)
enabled #設置開機啟動。
name= #服務名稱
runlevel #開機啟動的級別,一般不用指定。
sleep #在重啟服務的過程中,是否等待。如在服務關閉以后等待2秒再啟動。(定義在劇本中。)
state #有四種狀態(tài),分別為:started--->啟動服務, stopped--->停止服務, restarted--->重啟服務, reloaded--->重載配置

3.5、file模塊

# file模塊用于查看文件的屬性,修改文件屬性,查詢文件是否被修改等
ansible vm-master-03 -m file -a 'path=/etc/passwd'  -------------->查看文件屬性
ansible vm-master-02 -m file -a 'path=/tmp/fzh state=touch mode=755 owner=fzh' --------------->創(chuàng)建文件
ansible vm-master-02 -m file -a 'dest=/tmp/fzh state=absent' ------------------->刪除文件。
ansible vm-master-02 -m file -a 'dest=/tmp/test.sh mode=777' ------------------->修改遠程服務器上文件的屬性。
ansible vm-master-02 -m file -a 'dest=/tmp/test mode=755 owner=fzh group=fzh state=directory' ------->在客戶端相應位置下創(chuàng)建目錄:fzh。(make -p)
ansible vm-master-02 -m file -a 'dest=/tmp/fzh state=absent' --------------->刪除遠程服務器上的文件,這里是目錄。

3.6、copy模塊

# 從控制節(jié)點上拷貝文件到“受控節(jié)點”上
ansible vm-master-02 -m copy -a 'src=/root/test.sh dest=/tmp/ mode=600 owner=fzh group=fzh'
(把本地/root/test文件cp到PROD主機下的/tmp目錄下。)
常用參數(shù)介紹:
src    #被復制到遠程主機的本地文件。可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,則會遞歸復制,用法類似于"rsync"
content   #用于替換"src",可以直接指定文件的值
dest    #必選項,將源文件復制到的遠程主機的絕對路徑
backup   #當文件內容發(fā)生改變后,在覆蓋之前把源文件備份,備份文件包含時間信息
directory_mode    #遞歸設定目錄的權限,默認為系統(tǒng)默認權限
force    #當目標主機包含該文件,但內容不同時,設為"yes",表示強制覆蓋;設為"no",表示目標主機的目標位置不存在該文件才復制。默認為"yes"
others    #所有的 file 模塊中的選項可以在這里使用

3.7、script模塊

# 遠程節(jié)點執(zhí)行本地腳本,腳本位于控制節(jié)點,相當于scp+shell
ansible test -m script -a "/root/hostname.sh"

3.8、synchronize模塊

# 將控制節(jié)點的某個目錄推送到受控制節(jié)點目錄下
ansible test -m synchronize -a 'src=/root/test dest=/tmp/ compress=yes'

3.9、fetch模塊

# 將vm-master-02的/root/vm-master-02.txt文件cp到本機的/root目錄下
[root@vm-master-01 ~]# ansible vm-master-02 -m fetch -a "src=/root/vm-master-02.txt dest=/root/ flat=yes" 
ansible還有很多模塊,在此不一一介紹,具體可以參考中文指南:
http://www.ansible.com.cn/docs/intro_adhoc.html#managing-packages

四、ansible-playbook

4.1、ansible-playbook

playbook 是 ansible 用于配置,部署,和管理被控節(jié)點的劇本。通過 playbook 的詳細描述,執(zhí)行其中的一系列 tasks ,可以讓遠端主機達到預期的狀態(tài)。執(zhí)行一些簡單的任務,使用ad-hoc命令可以方便的解決問題,但是有時一個設施過于復雜,需要大量的操作時候,執(zhí)行的ad-hoc命令是不適合的,這時最好使用playbook。playbook由YMAL語言編寫。YAML( /?j?m?l/ )參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822。

4.2、ansible-playbook yaml文件格式

---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: exec shell
    shell: hostname
  - name: create dir
    file:
      path: /root/dir
      state: directory
# 解析
host:使用 hosts 指示使用哪個主機或主機組來運行下面的 tasks ,每個 playbook 都必須指定 hosts,hosts也可以使用通配符格式。主機或主機組在 inventory 清單中指定,可以使用系統(tǒng)默認的/etc/ansible/hosts,也可以自己編輯,在運行的時候加上-i選項,指定清單的位置即可。
remote_user:指定遠端主機中的哪個用戶來登錄遠端系統(tǒng),在遠端系統(tǒng)執(zhí)行 task 的用戶,可以任意指定,也可以使用 sudo,但是用戶必須要有執(zhí)行相應 task 的權限。
tasks:指定遠端主機將要執(zhí)行的一系列動作,相當于任務列表。tasks 的核心為 ansible 的模塊,前面已經提到模塊的用法。tasks 包含 name 和要執(zhí)行的模塊,name 是可選的,只是為了便于用戶閱讀,不過還是建議加上去,模塊是必須的,同時也要給予模塊相應的參數(shù)。
name:每個task都有對應的name,當我們省略name時,默認以當前任務調用的模塊的名稱作為任務的名稱,不過建議不要省略name,因為當任務存在name時,可讀性比較高。
# 執(zhí)行上述任務
# 1、–list-hosts: 顯示執(zhí)行任務的主機列表,實際并不執(zhí)行
ansible-playbook -i /etc/ansible/hosts --list-hosts /etc/ansible/test.yaml 
# 2、--syntax-check: 語法檢測,實際并不執(zhí)行。執(zhí)行結果顯示playbook名稱即表示沒有語法錯誤。
ansible-playbook -i /etc/ansible/hosts /etc/ansible/test.yaml --syntax-check
# 3、--check: 任務預演,實際并不執(zhí)行
ansible-playbook -i /etc/ansible/hosts /etc/ansible/test.yaml  --check
# 執(zhí)行結果:
綠色代表執(zhí)行成功,系統(tǒng)保持原樣
黃色代表系統(tǒng)代表系統(tǒng)狀態(tài)發(fā)生改變
紅色代表執(zhí)行失敗,顯示錯誤輸出
執(zhí)行過程有三個步驟:
1、收集facts (收集對應目標主機的信息)
2、執(zhí)行tasks
3、報告結果
執(zhí)行結果如下圖:
ansible-playbook執(zhí)行結果

4.3、handlers

4.3.1、handlers初識

handlers是和tasks平級的另一種任務。但handlers中的任務會被tasks中的任務調用。只有當tasks中的任務真正執(zhí)行(黃色,有改變),handlers中被調用的任務才會被執(zhí)行。當服務的配置文件發(fā)生改變,需要重啟的時候,handlers就能解決此類問題。格式見下:
[root@vm-master-01 ansible]# cat handlers.yaml 
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    notify: handler1
  - name: create dir2
    file: path=/root/dir2
          state=directory
    notify: handler2

  handlers:
  - name: handler1
    file: path=/root/dir1/file1
          state=touch
  - name: handler2
    file: path=/root/dir2/file2
          state=touch
# 解釋:
通過notify關鍵字關聯(lián)tasks和handlers,handlers被執(zhí)行的順序與在playbook中定義的順序是相同的,與被調用執(zhí)行的順序無關。當所有task執(zhí)行完畢后,才會執(zhí)行handlers。如果想改變這種順序需要meta模塊。

4.3.2、handlers meta

[root@vm-master-01 ansible]# cat handlers.yaml 
---
- hosts: vm-03
 remote_user: root
 tasks:
 - name: create dir1
   file: path=/root/dir1
         state=directory
   notify: handler1

 - name: create dir2
   file: path=/root/dir2
         state=directory
   notify: handler2

 - meta: flush_handlers

 - name: create dir3
   file: path=/root/dir3
         state=directory
   notify: handler3

 handlers:
 - name: handler1
   file: path=/root/dir1/file1
         state=touch

 - name: handler2
   file: path=/root/dir2/file2
         state=touch

 - name: handler3
   file: path=/root/dir2/file3
         state=touch

ansible-playbook -i /etc/ansible/hosts /etc/ansible/handlers.yaml執(zhí)行結果見下:


meta flush_handlers
#從上面結果可以看出:
meta是一種特殊的任務,可以影響ansible內部的工作順序,"meta: flush_handlers"表示立即執(zhí)行之前的task所對應的handler。當對應的handler執(zhí)行完畢后,接著執(zhí)行meta下面后續(xù)的task,這些task執(zhí)行完畢后,在執(zhí)行對應的handlers。

4.3.3、一個task對應多個handlers<listen>

[root@vm-master-01 ansible]# cat handlers2.yaml 
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    notify: handler-group

  handlers:
  - name: handler1
    listen: handler-group
    file: path=/root/dir1/file1
          state=touch

  - name: handler2
    listen: handler-group
    file: path=/root/dir1/file2
          state=touch

  - name: handler3
    listen: handler-group
    file: path=/root/dir1/file3
          state=touch

ansible-playbook -i /etc/ansible/hosts /etc/ansible/handlers2.yaml執(zhí)行結果如下:


listen
可以將"listen"和“notify”后面的handler-group看成組,命中組的handler就可以被調用執(zhí)行。
注意:如果不采用上面listen的方式,當定義多個具有相同name的handlers時,只會有一個handler會被執(zhí)行。

4.4、tags

tags: 為任務列表中的指定任務打上標簽,然后可以選擇性的執(zhí)行某一部分或者某一類的任務。

4.4.1、tags定義

[root@vm-master-01 ansible]# cat cat tags.yaml 
cat: cat: No such file or directory
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    notify: handler1
    tags: t1

  - name: create dir2
    file: path=/root/dir2
          state=directory
    notify: handler2
    tags: t2

  - name: create dir3
    file: path=/root/dir3
          state=directory
    notify: handler3
    tags: t3

  handlers:
  - name: handler1
    file: path=/root/dir1/file1
          state=touch

  - name: handler2
    file: path=/root/dir2/file2
          state=touch

  - name: handler3
    file: path=/root/dir3/file3
          state=touch

ansible-playbook -i /etc/ansible/hosts --tags=t3 /etc/ansible/tags.yaml執(zhí)行結果如下:


tags
從結果可以看出:只有tags: t3的task和其handler被執(zhí)行了,也可以一次性指定多個標簽
# t2、t3執(zhí)行
ansible-playbook -i /etc/ansible/hosts --tags t2,t3 /etc/ansible/tags.yaml
# --skip-tags指定不執(zhí)行的task<下面:t2不執(zhí)行,t1、t3執(zhí)行>
ansible-playbook -i /etc/ansible/hosts --skip-tags="t2" /etc/ansible/tags.yaml
# 定義標簽的方式:
[root@vm-master-01 ansible]# cat tags2.yaml 
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    notify: handler1
    tags:
    - t1

  - name: create dir2
    file: path=/root/dir2
          state=directory
    notify: handler2
    tags: ['t2']

  - name: create dir3
    file: path=/root/dir3
          state=directory
    notify: handler3
    tags:
    - t3
    - t4

  - name: create dir4
    file: path=/root/dir4
          state=directory
    tags: t5,t6

  - name: create dir4
    file: path=/root/dir4
          state=directory
    tags: ['t7', 't8']

  handlers:
  - name: handler1
    file: path=/root/dir1/file1
          state=touch

  - name: handler2
    file: path=/root/dir2/file2
          state=touch

  - name: handler3
    file: path=/root/dir3/file3
          state=touch

4.4.2、tags查看

ansible-playbook -i /etc/ansible/hosts --list-tags /etc/ansible/tags.yaml

4.4.3、相同標簽

[root@vm-master-01 ansible]# cat tags3.yaml    
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    tags:
    - t1
    - dir

  - name: create dir2
    file: path=/root/dir2
          state=directory
    tags: ['t2', 'dir']

上面兩個task都有標簽:dir,我們可以以另一種方式表示:

[root@vm-master-01 ansible]# cat tags4.yaml 
---
- hosts: vm-03
  remote_user: root
  tags: dir
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    tags:
    - t1

  - name: create dir2
    file: path=/root/dir2
          state=directory
    tags: ['t2']
當我們執(zhí)行:ansible-playbook -i /etc/ansible/hosts --tags=dir /etc/ansible/tags4.yaml,兩個tasks都會被執(zhí)行,結果見下:
tags

4.4.4、內置tags

4.4.4.1、always

當tags=always時,我們用ansible-playbook執(zhí)行任務,即便我們沒有指定--tags=always,這個任務也會被執(zhí)行,除非使用了'--skip-tags'。

4.4.4.2、never

和always相反,我們執(zhí)行所有任務的時候,加了never標簽的任務不執(zhí)行。

4.4.4.3、tagged

# 下面命令表示只執(zhí)行有標簽的任務,沒有任何標簽的任務不會被執(zhí)行。這里加了never標簽的不會執(zhí)行
ansible-playbook --tags tagged tags.yaml
# 下面命令表示跳過包含標簽的任務,即使對應的任務包含always標簽,也會被跳過
ansible-playbook --skip-tags tagged tags.yaml

4.4.4.4、untagged

# 下面命令表示只執(zhí)行沒有標簽的任務,但是如果某些任務包含always標簽,那么這些任務也會被執(zhí)行
ansible-playbook --tags untagged tags.yaml
# 下面命令表示跳過沒有標簽的任務。意思是只執(zhí)行有標簽的任務。但是加了never標簽的任務不會被執(zhí)行
ansible-playbook --skip-tags untagged tags.yaml

4.4.4.5、all

特殊標簽all表示所有任務會被執(zhí)行,不用指定,默認情況下就是使用這個標簽。

4.5、ignore_errors

# 假如ansible-playbook中的某個task出錯,則按照順序執(zhí)行的后續(xù)任務都不會再執(zhí)行,假如是handler報錯,則不會影響剩下的流程,如果需要忽略此錯誤,可以用ignore_errors
[root@vm-master-01 ansible]# cat ignore_errors.yaml 
---
- hosts: vm-03
  remote_user: root
  tasks:
  - name: create dir1
    file: path=/root/dir1
          state=directory
    notify: handler1

  - name: create dir2
    command: hostnameeeeee
    notify: handler2
    ignore_errors: True

  - name: create dir3
    file: path=/root/dir3
          state=directory
    notify: handler3

  handlers:
  - name: handler1
    file: path=/root/dir1/file1
          state=touch

  - name: handler2
    file: path=/root/dir2/file2
          state=touch

  - name: handler3
    file: path=/root/dir3/file3
          state=touch

執(zhí)行命令: ansible-playbook -i /etc/ansible/hosts /etc/ansible/ignore_errors.yaml 結果如下:


ignore_errors
在第二個任務,人為制造一個報錯,由于目錄/root/dir2/不存在,所以handler2也會出錯,但只在第二個任務處添加"ignore_errors: True"后,后續(xù)的步驟都沒背中斷,即便handler2有報錯,也沒有影響后續(xù)的步驟。

4.6、limit

# 當有多臺主機被命中時,限制其中的某一臺執(zhí)行playbook,但必須在命中的主機列表中:
[root@vm-master-01 ansible]# cat limit.yaml 
---
- hosts: test
  remote_user: root

  tasks:
  - name: limit test
    command: hostname

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/limit.yaml --limit vm-master-02的結果如下:


limit
雖然test命中了三臺主機,但使用limit可以限制playbook在指定的主機上執(zhí)行。

4.7、playbook變量

# 1、變量名:
    僅能由字母、數(shù)字、下劃線組成,且只能以字母開頭
# 2、變量來源:
    1.1、 ansible setup facts 遠程主機的所有變量都可直接調用
    1.2、/etc/ansible/hosts定義
            1.2.1、普通變量:主機組中主機單行定義,優(yōu)先級高于公共變量
            1.2.2、公共(組)變量:針對主機組中所有主機定義的統(tǒng)一變量
    1.3、命令行指定的變量,優(yōu)先級最高
    1.4、playbook中定義
    1.5、role中定義

4.7.1、命令行變量

# 1、var_command_line.yaml文件內容
[root@vm-master-01 ansible]# cat var_command_line.yaml 
---
- hosts: test
  remote_user: root

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts -e "prefix=pre1" -e "var=command-line-var" -e "suffix=suf1" /etc/ansible/var_command_line.yaml結果如下:


命令行變量

4.7.2、playbook變量

# 1、var_playbook.yaml文件內容
[root@vm-master-01 ansible]# cat var_playbook.yaml 
---
- hosts: test
  remote_user: root
  vars:
    - prefix: pre2
    - var: playbook-var
    - suffix: suf2

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/var_playbook.yaml結果如下:


playbook變量

4.7.3、普通變量

# 1、/etc/ansible/hosts文件內容
[root@vm-master-01 ansible]# head -n 4 /etc/ansible/hosts
[test]
vm-master-01 ansible_ssh_host=192.168.13.211 ansible_ssh_port=22 prefix=vm01_pre3 var=common-var suffix=vm01_suf3
vm-master-03 ansible_ssh_host=192.168.13.225 ansible_ssh_port=22 prefix=vm03_pre3 var=common-var suffix=vm03_suf3
# 2、var_common.yaml文件內容
[root@vm-master-01 ansible]# cat var_common.yaml 
---
- hosts: test
  remote_user: root

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/var_common.yaml結果如下:


普通變量

4.7.4、公共(組)變量

# 1、hosts文件內容
[root@vm-master-01 ansible]# head -n 7 hosts
[test]
vm-master-01 ansible_ssh_host=192.168.13.211 ansible_ssh_port=22
vm-master-03 ansible_ssh_host=192.168.13.225 ansible_ssh_port=22
[test:vars]
prefix=test_pre4
var=group-var
suffix=test_suf4
# 2、var_group.yaml文件內容
[root@vm-master-01 ansible]# cat var_group.yaml
---
- hosts: test
  remote_user: root

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/var_group.yaml結果若下:


公共變量

4.7.5、變量優(yōu)先級比較

# 1、hosts文件內容
[root@vm-master-01 ansible]# head -n 8 /etc/ansible/hosts
[test]
vm-master-01 ansible_ssh_host=192.168.13.211 ansible_ssh_port=22 prefix=vm01_pre3 var=common-var suffix=vm01_suf3
vm-master-03 ansible_ssh_host=192.168.13.225 ansible_ssh_port=22 prefix=vm03_pre3 var=common-var suffix=vm03_suf3
[test:vars]
prefix=test_pre4
var=group-var
suffix=test_suf4
# 2、var_priority.yaml文件內容
[root@vm-master-01 ansible]# cat /etc/ansible/var_priority.yaml
---
- hosts: test
  remote_user: root
  vars:
    - prefix: pre2
    - var: playbook-var
    - suffix: suf2
  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

命令行傳入變量執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts -e "prefix=pre1" -e "var=command-line-var" -e "suffix=suf1" /etc/ansible/var_priority.yaml結果如下:


命令行傳入變量-命令行變量優(yōu)先級最高

命令行不傳入變量執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/var_priority.yaml 結果如下:


命令行不傳入變量-playbook變量優(yōu)先級最高
# 只修改/etc/ansible/var_priority.yaml將playbook變量刪掉:
[root@vm-master-01 ansible]# cat /etc/ansible/var_priority.yaml 
---
- hosts: test
  remote_user: root

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt

命令行不傳入變量數(shù)執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/var_priority.yaml 結果如下:


命令行不傳入變量同時playbook不定義變量-普通變量優(yōu)先級高于公共(組)變量
補充:對于"ansible setup facts"中的變量,我們可以借助于:ansible vm-01 -m setup命令查看,我做了實驗,但沒有截圖在這里,他的優(yōu)先級要高于普通變量低于playbook變量

由以上例子可證明優(yōu)先級排序為:命令行變量>playbook變量>ansible setup facts中的變量>普通變量>公共(組)變量,在執(zhí)行playbook時會使用優(yōu)先級高的變量。

4.7.6、將變量寫入單獨的yaml文件中

[root@vm-master-01 ansible]# cat vars.yaml 
prefix: file_pre5
var: var-file
suffix: file_suf5
[root@vm-master-01 ansible]# cat var_file.yaml 
---
- hosts: test
  remote_user: root
  vars_files:
    - vars.yaml

  tasks:
    - name: exec shell echo {{ var }}
      shell: echo {{ prefix }}_{{ var }}_{{ suffix }} > /tmp/var.txt
# 此時的變量相當于playbook的變量,優(yōu)先級也一樣,變量文件和var_file.yaml放在同級目錄。

4.8、templates

4.8.1、templates語法

文本文件,嵌套有腳本(使用模版編程語言編寫)
jinja2語言,使用字面量,有下面形式:
        字符串:使用單引號或雙引號
        數(shù)字:整數(shù),浮點數(shù)
        列表:[item1,item2,...]
        元組:{item1,item2,...}
        字典:{key1:value1,key2:value2,...}
        布爾型:true、false
算術運算:+,-,*,/,//,%,**
比較操作:==,!=,>,>=,<,<=
邏輯運算:and,or,not
流表達式:for if when
template文件必須以.j2結尾

4.8.2、一個例子

需要在vm-03上安裝nginx,并將其開啟的worker進程數(shù)量在auto(cpu的核心數(shù))的基礎上+2

# 1、ansible setup模塊確定auto的變量名稱
[root@vm-master-01 ansible]# ansible vm-03 -m setup | grep ansible_processor_vcpus
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
        "ansible_processor_vcpus": 8,    # vm-03有8個core
# 2、nginx.conf.j2配置<次文件放在templates目錄下,templates目錄和nginx.yaml文件平級,執(zhí)行playbook時會自動尋找到對應名稱的模版文件>
[root@vm-master-01 ansible]# head -n 6 templates/nginx.conf.j2  
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes {{ ansible_processor_vcpus + 2 }};  # ansible_processor_vcpus由"1"獲取
# 3、nginx.yaml
[root@vm-master-01 ansible]# cat nginx.yaml 
---
- hosts: vm-03
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates nginx.conf.j2
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start nginx
      service: name=nginx state=started enabled=true

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/nginx.yaml結果如下:


帶有templates的yaml執(zhí)行過程

nginx worker開啟的數(shù)量為:8+2

執(zhí)行命令:ansible vm-03 -m shell -a "grep worker_processes /etc/nginx/nginx.conf"查看vm-03上nginx的配置文件:


vm-03中nginx配置文件中worker_processes的值

4.9、when

1、條件測試:如果需要根據(jù)變量、facts或者此前任務的執(zhí)行結果來做為某個task執(zhí)行與否的前提時要用到條件測試,通過when語句實現(xiàn),在task中使用jinja2的語法格式
2、使用:在task后添加when子句即可使用條件測試;when語句支持jinja2表達式語法
3、例子:
        name: "if RedHat exec command"
        command: hostname
        when: ansible_os_family == "RedHat"
# 1、需求:我們修改上面nginx配置文件的需求,假如vm-03中"ansible_os_family!=RedHat",我們就不傳遞vm-01上修改過的nginx.conf文件,而使用vm-03上原有的配置文件
# 2、說明:vm-03上ansible_os_family為"RedHat",可以通過setup模塊獲取,作為演示:我已經卸載了vm-03上面已經安裝過的nginx
# 2、nginx.yaml
[root@vm-master-01 ansible]# cat nginx.yaml 
---
- hosts: vm-03
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates nginx.conf.j2
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      when: ansible_os_family != "RedHat"
    - name: start nginx
      service: name=nginx state=started enabled=true

執(zhí)行相關命令結果如下:


when使用
從上面例子可以看出:由于when條件不成立,并沒有執(zhí)行template操作。

4.10、with_items

with_items表迭代:當有重復執(zhí)行的任務時,可以使用迭代機制
        使用固定變量"item"作為迭代項的引用
使用with_items給定迭代的元素列表:
        字符串
        字典等
# 下面yaml文件將在vm-03主機的/tmp目錄下創(chuàng)建三個文件:f1、f2、f3
[root@vm-master-01 ansible]# cat with_items.yaml 
---
- hosts: vm-03
  remote_user: root
  tasks:
    - name: create files
      file: name=/tmp/{{ item }} state=touch
      when: ansible_os_family == "RedHat"
      with_items:
        - f1
        - f2
        - f3

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts /etc/ansible/with_items.yaml得到的結果如下:


with_items

4.11、for流程控制

# 1、for.yaml文件內容
[root@vm-master-01 ansible]# cat for.yaml 
---
- hosts: vm-03
  remote_user: root
  vars:
    people:
      - name: zhangsan
        age: 23
        high: 1.68
      - name: lisi
        high: 1.70
      - name: wangwu
        age: 25
        high: 1.71

  tasks:
    - name: copy file
      template: src=for1.txt.j2 dest=/tmp/for1.txt
# 2、for1.txt.j2文件內容:
[root@vm-master-01 ansible]# cat templates/for1.txt.j2 
{% for p in people %}
info of people {
    name: {{ p.name }}
  {% if p.age is defined %}
    age: {{ p.age }}
  {% endif %}
  hige: {{ p.high }}
}
{% endfor %}

執(zhí)行yaml文件并查看vm-03下的文件/tmp/for1.txt的內容:


for

4.12、register

假如有這樣一個需求,使用shell命令檢查nginx進程是否存在,當不存在時就重啟。我們可以通過register將使用ps命令抓取的進程數(shù)賦值給info,然后通過info的相應字段(從下面截圖中應該可以看出相應的字段為info.stdout)來判斷進程數(shù)是否為0,為0則重啟。
[root@vm-master-01 ansible]# cat sum_process_nginx.yml 
---
- hosts: vm-master-03
  gather_facts: no
  tasks:
    - name: get nginx process
      shell: ps -ef | grep nginx | grep -v grep | wc -l
      register: info
    - name: display vars
      debug:
        var: info
    - name: if sum(nginx process) < 1 then start it
      service: name=nginx
               state=started
      when: info.stdout == "0"
    - name: check if nginx started success or not
      shell: systemctl status nginx

執(zhí)行命令:ansible-playbook sum_process_nginx.yml結果如下:


register

五、ansible-playbook生產實踐

5.1、說明

基于上面介紹,對于nginx的安裝,做一個生產級別的介紹

5.2、項目結構

[root@vm-master-01 ansible]# pwd
/etc/ansible
[root@vm-master-01 ansible]# tree ./
./
├── ansible.cfg
├── hosts
├── nginx_role.yml
└── roles
    ├── mysql
    ├── nginx
    │   ├── files
    │   │   └── index.html
    │   ├── handlers
    │   │   ├── main.yml
    │   │   └── restart.yml
    │   ├── tasks
    │   │   ├── copyfile.yml
    │   │   ├── group.yml
    │   │   ├── main.yml
    │   │   ├── start.yml
    │   │   ├── template.yml
    │   │   ├── user.yml
    │   │   └── yum.yml
    │   ├── templates
    │   │   └── nginx.conf.j2
    │   └── vars
    │       └── main.yml
    ├── redis
    └── supervisor
        ├── files
        ├── handlers
        ├── tasks
        ├── templates
        └── vars

15 directories, 15 files
下面我分別貼下沒個文件的內容。

5.2.1、role

關于role的各個目錄做下簡要的概述

files:存放由copy、script模塊等調用的文件
templates:template模塊查找所需要模塊文件的目錄
tasks:定義task,至少包含一個名為main.yml的文件,其他文件需要再次文件中通過include進行包含
handlers:至少應該包含一個名為main.yml的文件,其他文件需要在此文件中通過include進行包含
vars:定義變量,至少包含一個名為main.yml的文件,其他文件需要在此文件中通過include進行包含
meta:定義當前角色的特殊設定以及其依賴關系,至少應該包含一個名為main.yml的文件,其它文件需要在此文件中通過include進行包含
default:設定默認變量時使用此目錄中的main.yml文件
[root@vm-master-01 ansible]# cat nginx_role.yml 
- hosts: vm-03
  remote_user: root
  roles:
    - { role: nginx, tags: ['app', 'ops'], when: ansible_os_family == 'RedHat' }
    - { role: mysql, tags: 'app' }

5.2.2、files目錄

[root@vm-master-01 files]# ls
index.html
[root@vm-master-01 files]# cat index.html 
nginx playbook

5.2.3、handlers目錄

[root@vm-master-01 handlers]# ls
main.yml  restart.yml
[root@vm-master-01 handlers]# cat main.yml 
- include: restart.yml
[root@vm-master-01 handlers]# cat restart.yml 
- name: nginx restart
  service: name=nginx state=restarted

5.2.4、tasks目錄

[root@vm-master-01 tasks]# ls
copyfile.yml  group.yml  main.yml  start.yml  template.yml  user.yml  yum.yml
[root@vm-master-01 tasks]# cat copyfile.yml 
- name: copy index.html
  copy: src=index.html dest=/usr/share/nginx/html/
  notify: nginx restart
[root@vm-master-01 tasks]# cat group.yml 
- name: create group
  group: name={{ username }} gid=88
[root@vm-master-01 tasks]# cat main.yml 
- include: group.yml
- include: user.yml
- include: yum.yml
- include: template.yml
- include: start.yml
- include: copyfile.yml
[root@vm-master-01 tasks]# cat start.yml 
- name: start service
  service: name=nginx state=started enabled=yes
[root@vm-master-01 tasks]# cat template.yml 
- name: copy file
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@vm-master-01 tasks]# cat user.yml 
- name: create user
  user: name={{ username }} group={{ groupname }} system=yes shell=/sbin/nologin
[root@vm-master-01 tasks]# cat yum.yml 
- name: install nginx
  yum: name=nginx

5.2.5、templates目錄

[root@vm-master-01 templates]# ls
nginx.conf.j2
[root@vm-master-01 templates]# cat nginx.conf.j2 
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user {{ username }};
worker_processes {{ ansible_processor_vcpus + 2 }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

5.2.6、vars目錄

[root@vm-master-01 vars]# ls
main.yml
[root@vm-master-01 vars]# cat main.yml 
groupname: nginx
username: nginx

5.3、執(zhí)行playbook

執(zhí)行命令:ansible-playbook -i /etc/ansible/hosts --tags=app nginx_role.yml結果如下:


playbook執(zhí)行過程

5.4、瀏覽器訪問

瀏覽器查看playbook執(zhí)行結果

六、注意

1、我上面執(zhí)行ansible或ansible-playbook時,結果中多處有提示:[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
是因為我hosts中資源清單的組中有使用符號“-",這不符合相關語法規(guī)范,修改掉即可。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容