ansible自動化運維

在管理機器上安裝ansible工具html

yum  install ansiblenode

將須要管理的主機加入absible,的主機管理清單配置文件/etc/ansible/hostspython

格式:inventory文件遵循INI文件風格,中括號中的字符爲組名。 能夠將同一個主機同時歸併到多個不一樣的組中;此外,當如若 目標主機使用了非默認的SSH端口,還能夠在主機名稱以後 使用冒號加端口號來標明mysql

1)不分組方式 #不推薦這樣使用linux

192.168.136.5:2222  #冒號後面的2222表示端口號nginx

192.168.136.6git

2)分組方式github

[web]   # web表示組名,分組之後能夠直接經過組名來進行管理組裏面的主機web

192.168.136.5正則表達式

192.168.136.6

[opt]

192.168.136.[7:10]   #這表示範圍,從192.168.136.7到192.168.136.10之間的全部主機

[webservers]

www1.magedu.com

www2.magedu.com

ansible管理主機通常最好是先基於key驗證以後管理起來會比較方便

步驟:

1)生成公私鑰對

ssh-keygen

2)將公鑰複製到全部主機

能夠編寫腳本:完成這一步

也能夠用ssh-copy-id  <主機ip>便可


ansible 配置文件

Ansible 配置文件/etc/ansible/ansible.cfg (通常保持默認)

[defaults]

#inventory      = /etc/ansible/hosts  # 主機列表配置文件

#library  = /usr/share/my_modules/ # 庫文件存放目錄

#remote_tmp  = $HOME/.ansible/tmp  #臨時py命令文件存放在遠程主 機目錄

#local_tmp      = $HOME/.ansible/tmp # 本機的臨時命令執行目錄

#forks          = 5   # 默認併發數

#sudo_user      = root  # 默認sudo 用戶

#ask_sudo_pass = True  #每次執行ansible命令是否詢問ssh密碼

#ask_pass      = True

#remote_port    = 22

#host_key_checking = False  # 檢查對應服務器的host_key,建議取消 註釋

#log_path = /var/log/ansible.log   #會把你執行的命令生成日誌計入在/var/log/ansible.log文件中,建議把這一項啓用起來,


ansible

功能介紹

基於模塊化,遠程管理主機,而且是基於ssh方式鏈接主機的方式,安全性高

格式

<host-pattern> [-m module_name] [-a args]

特色

1)模塊化:調用特定的模塊,完成特定任務

2)有Paramiko,PyYAML,Jinja2(模板語言)三個關鍵模塊

3)支持自定義模塊

4)基於Python語言實現

5)部署簡單,基於python和SSH(默認已安裝),agentless

6)安全,基於OpenSSH

7)支持playbook編排任務

8)冪等性:一個任務執行1遍和執行n遍效果同樣,不因重複執行帶來意外狀況

9)無需代理不依賴PKI(無需ssl)

10)可以使用任何編程語言寫模塊

11)YAML格式,編排任務,支持豐富的數據結構

12)較強大的多層解決方案

ansable系列命令

ansible    

ansible-doc  

ansible-playbook    

ansible-vault    

ansible-console  

ansible-galaxy  

ansible-pull

ansible-doc 查看模

塊幫助用法

ansible-doc –l  列出全部模塊

ansible-doc ping  查看指定模塊幫助用法

ansible-doc –s  ping 查看指定模塊幫助用法

ansible命令執行過程

1. 加載本身的配置文件 默認/etc/ansible/ansible.cfg

2. 加載本身對應的模塊文件,如command

3. 經過ansible將模塊或命令生成對應的臨時py文件,並將該 文 件傳輸至遠程服務器的對應執行用戶 $HOME/.ansible/tmp/ansible-tmp-數字/XXX.PY文件

4. 給文件+x執行

5. 執行並返回結果

6. 刪除臨時py文件,sleep 0退出

執行狀態:

綠色:執行成功而且不須要作改變的操做

黃色:執行成功而且對目標主機作變動

紅色:執行失敗

選項

說明

--version

顯示版本

-m module

指定模塊,默認爲command

-v

詳細過程 –vv  -vvv更詳細

--list-hosts

顯示主機列表,可簡寫—list

--ask-pass

提示鏈接密碼,默認Key驗證

-C,   --check

檢查,並不執行

-T  --timeout=TIMEOUT

執行命令的超時時間,默認10s

-u   --user=REMOTE_USER

執行遠程執行的用戶

-b --become

代替舊版的sudo 切換

模塊介紹

模塊名成

功能介紹及經常使用參數

ping

一個簡單的測試模塊,這個模塊老是在成功的接觸中返回「乒乓」。這是不合理的

可是它對於驗證登陸的能力和可用的python來講是有用的。

配置。這不是ICMP ping,這只是一個簡單的測試模塊。對於Windows目標,使用

(win_ping)模塊。

用法: anisble   主機    -m    ping

command

命令的模塊接受命令名,後面是空格分隔的參數列表。給定的

命令將在全部選定的節點上執行。它不會經過shell進行處理,因此變量

「$ HOME」和操做,好比「<「」、「」>「」,「」|「」、「」;「和」不會起做用(使用shell模塊

若是您須要這些特性)。

常見選項:

1),chdir  <切換目錄>   格式: ansible  主機組   -m command -a  ‘chdir=/app/   ls  -al   /app ’

2),creates <判斷若是文件不存在就執行後面的命令>  格式:  ansible  主機組   -m command -a  ‘creates=/etc/fstab   ls -al /app’

3),removes <判斷若是文件存在就執行後面的命令>  格式: ansible  主機組   -m  command -a  'removes=/etc/fstab  ls-al  /app/'

shell

shell的模塊接受命令名,後面是空格分隔的參數列表。這幾乎是

與命令模塊徹底同樣,可是在遠程節點上經過shell(/bin/sh')運行命令

支持 特殊符號$ HOME」和操做,好比「<「」、「」>「」,「」|「」、「」;「

在執行命令是儘可能使用單引號,

其餘用法基本跟command模塊相同

script

腳本的模塊接受腳本名稱,發送到遠程主機上執行,

格式:ansible 主機組   -m  script   -a   ‘/app/f1 .sh ’

copy

copy'模塊將一個文件從本地或遠程機器複製到遠程機器上的一個位置。使用com

fetch模塊將文件從遠程位置複製到本地框。若是你須要變量插值

在複製的文件中,使用模板模塊。

注意:copy模塊複製文件若是目錄不存在會自動建立目錄

經常使用參數:

content:<把自定義內容複製到遠程主機文件中>  格式 : content=「df -h \nls\n\hostname   dest=/app/f1.sh」

src:<本機源文件>

dest:<指定複製到目標主機的某個目錄或者覆蓋某個文件>  

backup:<文件複製到遠程主機若是文件已存在能夠將源文件作備份,再覆蓋>  格式: backup=yes /no  yes表示作備份,no表示不作備份

directory_mode :<複製整個目錄>

mode:<更改複製過去的文件權限>    格式: mode=644......

owner:<更改複製過去的文件屬主>   格式:owner=wang

格式:ansible 主機組   -m copy -a  ‘src=/etc/fstab dest=/app/  backup=yes mode=644 owner=wang’

fetch

這個模塊的工做方式相似於複製,但反過來。它用於從遠程機器獲取文件

將它們存儲在本地目錄下

經常使用參數:

src:<指定遠程主機的文件>

dest:<指定本地主機的目錄>

格式:ansible  主機組  -m fetch -a  ‘src=/etc/fstab  best=/app/’

file

支持在被控主機建立空文件,建立軟鏈接,刪除文件等做

經常使用選項:

建立空文件:path=<指定建立文件路徑>   通常配合state=touch使用

建立軟鏈接:src=<指定原始文件路徑>  通常配合path=<建立到那個目錄>,state=link<鏈接>

建立目錄:path=<指定路徑>    通常配合state=directory使用

刪除文件:  path=<指定文件路徑>  通常配合state=absent使用

設置文件權限:mode<設置文件權限>     owner<設置文件屬組>

格式:

建立文件

ansible  主機組 -m file -a ‘path=/app/testfile state=touch’

建立軟鏈接

absible 主機組  -m file -a ‘src=/app/testfile path=/tmp/testfile-link  stare=link’

建立目錄

absible 主機住  -m file -a 'path=/app/dir1  state=directory'

刪除文件

ansible 主機組 -m file -a ‘path=/app/testfile state=absent’e

hostname

更改被控主機端的主機名

格式:

ansible 主機   -m hostname -a 'name=名字'

cron

建立計劃任務

minute<分鐘>

day <天>

hour<小時>

weekday<周>

month<月>

job<執行的操做> 注意:命令須要寫全路徑

name<計劃任務的名字>

disabled=yes <yes表示禁用計劃任務,no表示啓用計劃任務>

start=absent <表示刪除計劃任務>

例子:

ansible 主機組  -m cron -a 'minute=*/5 hour=12  weekday=0,6  job="/usr/sbin/wall  is jobs " name="test job"'

此命令原理:  建立一個名爲test job計劃任務 每週六週天,凌晨12點沒5分鐘執行一次wall廣播 is job

禁用,啓用計劃任務

ansible 主機組  -m cron -a 'disabled=yes/on job="執行的操做"  name="計劃任務名字"'

刪除計劃任務

ansible  主機組  -m cron -a 'start=adsent  job="執行的操做" name="計劃任務名字"'

yum

管理軟件包模塊

安裝軟件包

name=包名

start=absent  卸載包

start=latest   裝最新版

updata_cache=yes  更新yum緩存

service

管理服務狀態模塊

經常使用選項

name=<指定包名>

state=<指定運行狀態>   如:stopped<中止>,started<啓動>,restarted<重啓服務>, reloaded<重讀配置文件> ,

enabled=yes  表示把服務設置爲開機自動重啓

格式:

設置服務開機自動啓動而且啓動

ansible 主機組  -m  service -a  'name=httpd state=started  enabled=yes'

user

建立管理用戶

經常使用選項:

name=<指定用戶名>

comment=<描述信息>

uid=<指定uid>

home=<指定家目錄路徑>

group=<指定 主組>

groups=<指定輔助組>

system=yes<yes表示建立的是系統用戶>

shell=<指定shell類型>

remove=yes <yes表示把家目錄等等相關數據全刪除>

例子:

建立普通用戶

ansible 主機組  -m user -a 'name="test" uid=2000 home=/app/test  group=wang groups=root,bin '

建立系統用戶   <注意:默認建立系統用戶會建立家目錄>

ansible 主機組  -m user -a 'name=sys  system=yes  shell=nologin'

刪除用戶並把家目錄刪除

ansible 主機組  -m user -a 'name="test"  state=absent remove=yes’

group

管理組

name=<指定組名>

state=<指定操做>

例子

建立組

ansible 主機組  -m group -a 'name=group1  '

刪除組

ansible 主機組 -m group -a 'name=group1 state=absent'

setup

顯示全部被控主機的,全部主機信息,例如:IP,主機名,版本,等等信息

經常使用選項

filter="*信息*"<做用用來匹配想要查看的信息>

例子:

ansible 主機組 -m setup  -a 'filter="*hostname*"'   注意匹配時須要把匹配的值放在雙星」*「號裏面

匹配主機列表的方式:

All :表示全部Inventory中的全部主機  

ansible all –m ping

*  :通配符  

ansible  「*」  -m ping    #匹配全部主機執行ping模塊操做

ansible  192.168.1.* -m ping  #匹配192.168.1.這個網段的全部主機,執行平模塊操做

ansible  「*srvs」  -m ping  #匹配主機組名後面srvs的主機組執行ping模塊操做

或關係:  

ansible 「websrvs:appsrvs」  -m ping  #這表示匹配兩個主機組裏面的全部主機

  ansible  「192.168.1.10:192.168.1.20」  -m ping   #這是隻針對兩臺主機執行ping模塊操做

邏輯與

ansible 「websrvs:&dbsrvs」 –m ping   在websrvs組而且在dbsrvs組中的主機,才執行ping模塊操做

邏輯非

ansible 'websrvs:!dbsrvs' –m ping   #在websrvs組,但不在dbsrvs組中的主機 ,執行平模塊中操做

綜合邏輯

ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping  #匹配在websrvszu或者在dbsrvs組,而且在appsrvs組,但不在ftpsrvszu裏的主機,纔會執行ping模塊操做

正則表達式

ansible 「~(web|db).*\.magedu\.com」 –m ping  #匹配以帶有web關鍵字後面跟任意字符.magedu.com的主機組,或者帶有db關鍵字後面跟任意字符.magedu.com的主機組,執行ping模塊操做


ansible系列命令

Ansible-vault

功能:管理加密解密yml文件

ansible-vault [create|decrypt|edit|encrypt|rekey|view]

ansible-vault encrypt hello.yml 加密

ansible-vault decrypt hello.yml 解密

ansible-vault view hello.yml 查看

ansible-vault edit  hello.yml 編輯加密文件

ansible-vault rekey  hello.yml 修改口令

ansible-vault create new.yml 建立新文件


Ansible-console:2.0+新增,可交互執行命令,支持tab

root@test (2)[f:10] $   執行用戶@當前操做的主機組 (當前組的主機數量)[f:併發數]$

設置併發數: forks n  例如: forks 10

切換組: cd 主機組  例如: cd web

列出當前組主機列表: list

列出全部的內置命令: ?或help

示例:

root@all (2)[f:5]$ list

root@all (2)[f:5]$ cd appsrvs

root@appsrvs (2)[f:5]$ list

root@appsrvs (2)[f:5]$ yum name=httpd state=present

root@appsrvs (2)[f:5]$ service name=httpd state=started


經常使用選項示例:

查看主機組名裏包括多少臺主機

anisble  主機分組名   --list-host

#普通用戶與root用戶配置

[root@localhost python]# cat /etc/ansible/hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups

# Ex 1: Ungrouped hosts, specify before any group headers.

## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
10.60.32.149

# Ex 2: A collection of hosts belonging to the 'webservers' group

## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

# If you have multiple hosts following a pattern you can specify
# them like this:

## www[001:006].example.com

# Ex 3: A collection of database servers in the 'dbservers' group

## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57

# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com
[docker]
10.60.32.149
[k8s]
10.60.36.220
10.60.36.210
[k8s:vars]
ansible_ssh_user=www
ansible_ssh_port=22
ansible_sudo_pass=123456

 

ansible-playbook 使用詳解

1、什麼是playbooks
playbooks是ansible的腳本、如同shell腳本同樣,它是控制遠程主機的一系列命令的集合,經過YAML語言編寫。執行一些簡單的任務,咱們可使用ad-hoc命令就能夠解決,對於一些較複雜的任務,ad-hoc就不能勝任了,這時候playbooks就派上用場了,在playbooks中能夠編排有序的執行過程,甚至能夠在多組機器間來回有序的執行特定的步驟,而且能夠同步或異步發起任務。

2、YAML語法
一、文件開始符

1
---

二、數組

1
2
3
- name
- hosts
- user

三、字典

1
2
name: restart apache
service: name=httpd state=restarted

字典與字典的嵌套:

1
2
3
vars:
   http_port: 80
   max_clients: 200

字典與數組的嵌套:

1
2
3
4
5
6
7
8
9
tasks:
   - name: ensure apache is at the latest version
     yum: pkg=httpd state=latest
   - name: write the apache config  file
     template: src= /srv/httpd .j2 dest= /etc/httpd .conf
     notify:
     - restart apache
   - name: ensure apache is running
     service: name=httpd state=started

此外,Ansible 使用 "{{ var }}"來引用變量.,若是一個值以 "{" 開頭, YAML 將認爲它是一個字典, 因此咱們必須引用它, 像這樣:foo: "{{ variable }}"

3、playbooks的基本用法
最基本的playbook分爲四部分:

  • 定義主機和用戶

1
2
hosts
users
  • 定義 playbook 執行須要的變量

1
variable
  • 定義任務

1
tasks
  • 定義響應事件

1
handlers

簡單示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
- name: Install apache
   hosts: webservers
   user: root
   gather_facts:  false
   vars:
     http_port: 80
     max_clients: 200
   tasks:
   - name: ensure apache is at the latest version
     yum: pkg=httpd state=latest
   - name: write the apache config  file
     template: src= /srv/httpd .j2 dest= /etc/httpd .conf
     notify:
     - restart apache
   - name: ensure apache is running
     service: name=httpd state=started
   handlers:
     - name: restart apache
       service: name=httpd state=restarted

說明:

  • name參數對此playbook實現的功能的概述,執行時會輸出name變量值。

  • hosts參數指定了在哪些主機上執行playbook

  • user參數指定在遠程主機上使用什麼用戶執行任務

  • gather_facts參數指定了下面任務執行前,是否先執行setup模塊獲取遠程主機相關信息,這些信息在task中能夠做爲變量使用

  • vars參數指定了變量

  • task參數指定了任務,這裏有3個任務。name參數是對具體任務的描述,在執行過程當中會輸出

  • handlers參數指定一個響應事件,當template: src=/srv/httpd.j2 dest=/etc/httpd.conf這個任務執行狀態是changed時纔會觸發。

 一、主機和用戶

key 含 義
hosts 爲主機的IP,或者主機組名,或者關鍵字all
user 在遠程以哪一個用戶身份執行。
become 切換成其它用戶身份執行,值爲yes或者no
become_method 與became一塊兒用,指能夠爲‘sudo’/’su’/’pbrun’/’pfexec’/’doas’
become_user 與bacome一塊兒用,能夠是root或者其它用戶名

通常用法:

1
2
3
---
- hosts: webserver, [all]
   user: root

還能夠在每一個 task 中,定義遠程執行用戶

1
2
3
4
5
6
7
---
- hosts: webserver
   user: root
   tasks:
   - name:  test  connection
     ping :
     remote_user: root

也支持 sudo 方法,在 task中一樣支持,在sudo須要密碼時,能夠加上選項 –ask-sudo-pass

1
2
3
4
5
6
7
8
---
- hosts: all
   user:  test
   sudo :  yes
   task:
     - service: name=nginx state=started
       sudo :  yes
       sudo_user: root

二、任務列表
tasks 是從上到下順序執行,若是中間發生錯誤,整個 playbook 便會中斷。
每個 task 是對module的一次調用,一般會帶有特定參數,參數可使用變量。
每個 task 有一個 name 屬性,name 值會在命令行中輸出,以提示用戶,若是沒有定義,aciton 的值會做爲輸出信息來標記task。

語法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
tasks:
   - name:  make  sure apache is running
     service: name=httpd state=running
//  若是參數過長,可使用空格或者縮進分隔爲多行
tasks:
   - name: copy ansible inventory  file  to client
     copy: src= /etc/ansible/hosts  dest=/etc/ansible/hosts
           owner=root group=root mode=0644
//  或者使用 yaml 的字典做爲參數
tasks:
   - name: copy ansible inventory  file  to client
     copy:
       src:  /etc/ansible/hosts
       dest:  /etc/ansible/hosts
       owner: root
       group: root
       mode: 0644
//  大部分的模塊都是使用 `key-value` 這種格式的,其中有兩個比較特殊,command 和 shell 模塊。
tasks:
   - name: disable selinux
     command :  /sbin/setenforce  0
tasks:
   - name: run this  command  and ignore the result
     shell:  /usr/bin/command  || /bin/true
tasks:
   - name: run some  command  and ignore the reslut
     shell:  /usr/bin/somecommadn
     ignore_error: True

執行狀態:
task中每一個action會調用一個module,在module中會去檢查當前系統狀態是否須要從新執行。
若是本次執行了,那麼action會獲得返回值changed
若是不須要執行,那麼action獲得返回值ok

三、響應事件
每一個主流的編程語言都會有event機制,那麼handler就是playbook的event。
Handlers裏面的每個handler,也是對module的一次調用。而handlers與tasks不一樣,tasks會默認的按定義順序執行每個task,handlers則不會,它須要在tasks中被調用,纔有可能被執行。Tasks中的任務都是有狀態的,changed或者ok。 在Ansible中,只在task的執行狀態爲changed的時候,纔會執行該task調用的handler,這也是handler與普通的event機制不一樣的地方。
什麼狀況下使用handlers呢?
若是你在tasks中修改了apache的配置文件。須要重起apache。此外還安裝了apache的插件。那麼還須要重起apache。像這樣的應該場景中,重啓apache就能夠設計成一個handler。

特性:

  • 一個handler最多隻執行一次

在全部的任務裏表執行以後執行,若是有多個task notify同一個handler,那麼只執行一次。
在下面的例子裏apache只執行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
- hosts: lb
   remote_user: root
   vars:
       random_number1:  "{{ 10000 | random }}"
       random_number2:  "{{ 10000000000 | random }}"
   tasks:
   - name: Copy the  /etc/hosts  to /tmp/hosts.{{ random_number1 }}
     copy: src= /etc/hosts  dest=/tmp/hosts.{{ random_number1 }}
     notify:
       - call  in  every action
   - name: Copy the  /etc/hosts  to /tmp/hosts.{{ random_number2 }}
     copy: src= /etc/hosts  dest=/tmp/hosts.{{ random_number2 }}
     notify:
       - call  in  every action
 
   handlers:
   - name: call  in  every action
     debug: msg= "call in every action, but execute only one time"
  • action是Changed ,纔會執行handler

只有當TASKS種的action的執行狀態是changed時,纔會觸發notify handler的執行。
下面的腳本執行兩次,執行結果是不一樣的:
第一次執行是,tasks的狀態都是changed,會觸發兩個handler
第二次執行是,
第一個task的狀態是OK,那麼不會觸發handlers"call by /tmp/hosts",
第二個task的狀態是changed,觸發了handler"call by /tmp/hosts.random_number"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 示例代碼
---
- hosts: lb
   remote_user: root
   vars:
       random_number:  "{{ 10000 | random }}"
   tasks:
   - name: Copy the  /etc/hosts  to /tmp/hosts
     copy: src= /etc/hosts  dest=/tmp/hosts
     notify:
       - call by  /tmp/hosts
   - name: Copy the  /etc/hosts  to /tmp/hosts.{{ random_number }}
     copy: src= /etc/hosts  dest=/tmp/hosts.{{ random_number }}
     notify:
       - call by  /tmp/hosts .random_number
 
   handlers:
   - name: call by  /tmp/hosts
     debug: msg= "call first time"
   - name: call by  /tmp/hosts .random_number
     debug: msg= "call by /tmp/hosts.random_number"
  • 按Handler的定義順序執行

andlers是按照在handlers中定義個順序執行的,而不是安裝notify的順序執行的。
下面的例子定義的順序是1>2>3,notify的順序是3>2>1,實際執行順序:1>2>3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
- hosts: lb
   remote_user: root
   gather_facts: no
   vars:
       random_number1:  "{{ 10000 | random }}"
       random_number2:  "{{ 10000000000 | random }}"
   tasks:
   - name: Copy the  /etc/hosts  to /tmp/hosts.{{ random_number1 }}
     copy: src= /etc/hosts  dest=/tmp/hosts.{{ random_number1 }}
     notify:
       - define the 3nd handler
   - name: Copy the  /etc/hosts  to /tmp/hosts.{{ random_number2 }}
     copy: src= /etc/hosts  dest=/tmp/hosts.{{ random_number2 }}
     notify:
       - define the 2nd handler
       - define the 1nd handler
 
   handlers:
   - name: define the 1nd handler
     debug: msg= "define the 1nd handler"
   - name: define the 2nd handler
     debug: msg= "define the 2nd handler"
   - name: define the 3nd handler
     debug: msg= "define the 3nd handler"

四、變量
playbook中經常使用變量的幾種狀況:

  • 用戶自定義的變量

用戶能夠在Playbook中,經過vars關鍵字自定義變量,使用時用{{ }}引用以來便可。
示例:

1
2
3
4
5
6
7
8
---
- hosts: web
   vars:
     http_port: 80
   remote_user: root
   tasks:
   - name: insert firewalld rule  for  httpd
     firewalld: port={{ http_port }} /tcp  permanent=true state=enabled immediate=yes
  • 把變量放在單獨的文件中

當變量比較多的時候,或者變量須要在多個playbook中重用的時候,能夠把變量放到一個單獨的文件中。經過關鍵字var_files把文件中定義的變量引入playbook中,使用變量的方法和在本文件中定義的變量相同。

1
2
3
4
5
6
7
8
9
10
- hosts: web
   remote_user: root
   vars_files:
       - vars /server_vars .yml
   tasks:
   - name: insert firewalld rule  for  httpd
     firewalld: port={{ http_port }} /tcp  permanent=true state=enabled immediate=yes
 
#cat vars/server_vars.yml
http_port: 80

定義複雜的變量
當變量的值不是簡單的字符串或者數字,而是一個字典,語法以下

1
2
3
foo:
   field1: one
   field2: two

訪問複雜變量中的子屬性,能夠利用中括號或者點號:

1
2
3
foo[ 'field1' ]
foo.field1
  • 系統變量(facts)

ansible會經過module setup來收集主機的系統信息,這些收集到的系統信息叫作facts,這些facts信息能夠直接以變量的形式使用。
有哪些facts變量能夠引用呢?在命令行上經過調用setup module命令能夠查看:

1
$ ansible all -m setup -u root

系統變量在playbook中能夠直接使用:

1
2
3
4
5
6
7
8
9
10
11
12
---
- hosts: all
   user: root
   tasks:
   - name:  echo  system
     shell:  echo  {{ ansible_os_family }}
   - name  install  ntp on Debian linux
     apt: name=git state=installed
     when: ansible_os_family ==  "Debian"
   - name  install  ntp on redhat linux
     yum: name=git state=present
     when: ansible_os_family ==  "RedHat"

對於複雜的、多層級的facts變量,能夠經過下面的兩種方式的任意一種訪問複雜的變量中的子屬性:
中括號:

1
{{ ansible_ens3[ "ipv4" ][ "address" ] }}

點號:

1
{{ ansible_ens3.ipv4.address }}

關係facts變量,一旦關閉以後就不用調用了。關閉方法:

1
2
- hosts: webserver
   gather_facts: no
  • 註冊變量

把task的執行結果也能夠做爲一個變量值。這個時候就須要用到「註冊變量」,將執行結果註冊到一個變量中,待後面的action使用。

1
2
3
4
5
6
7
8
9
---
- hosts: web
   tasks:
      - shell:  ls
        register: result
        ignore_errors: True
      - shell:  echo  "{{ result.stdout }}"
        when: result.rc == 5
      - debug: msg= "{{ result.stdout }}"

註冊變量常常和debug module一塊兒使用,這樣能夠獲得更多action的輸出信息,幫助用戶調試。

  • 命令行中傳遞的變量

爲了使Playbook更靈活、通用性更強,容許用戶在執行的時候傳入變量的值,這個時候就須要用到「額外變量」。
定義命令行變量
在test.yml文件裏,hosts和user都定義爲變量,須要從命令行傳遞變量值。

1
2
3
4
5
---
- hosts:  '{{ hosts }}'
   remote_user:  '{{ user }}'
   tasks:
   ...

在命令行裏面傳值得的方法:

1
ansible-playbook testyml --extra-vars  "hosts=web user=root"

還能夠用json格式傳遞參數:

1
ansible-playbook  test .yml --extra-vars  "{'hosts':'vm-rhel7-1', 'user':'root'}"

還能夠將參數放在文件裏面:

1
ansible-playbook  test .yml --extra-vars  "@vars.json"

五、如何執行playbook

語法:

1
$ ansible-playbook deploy.yml

查看輸出的細節

1
$ ansible-playbook playbook.yml --verbose

查看該腳本影響哪些hosts

1
$ ansible-playbook playbook.yml --list-hosts

並行執行腳本

1
$ ansible-playbook playbook.yml -f 10

4、playbooks的高級用法
一、邏輯控制

  • when: 條件判斷語句,相似於變成語言中的if

主機爲Debian Linux馬上關機:

1
2
3
4
tasks:
   - name:  "shutdown Debian flavored systems"
     command :  /sbin/shutdown  -t now
     when: ansible_os_family ==  "Debian"

根據action的執行結果,來決定接下來執行的action

1
2
3
4
5
6
7
8
9
10
tasks:
   -  command :  /bin/false
     register: result
     ignore_errors: True
   -  command :  /bin/something
     when: result|failed
   -  command :  /bin/something_else
     when: result|success
   -  command :  /bin/still/something_else
     when: result|skipped

遠程中的系統變量facts變量做爲when的條件,用「|int」還能夠轉換返回值的類型:

1
2
3
4
5
---
- hosts: web
   tasks:
     - debug: msg= "only on Red Hat 7, derivatives, and later"
       when: ansible_os_family ==  "RedHat"  and ansible_lsb.major_release|int >= 6

條件表達式

基本:

1
2
3
tasks:
     - shell:  echo  "This certainly is epic!"
       when: epic

否認:

1
2
3
tasks:
     - shell:  echo  "This certainly isn't epic!"
       when: not epic

變量定義:

1
2
3
4
5
tasks:
     - shell:  echo  "I've got '{{ foo }}' and am not afraid to use it!"
       when: foo is defined
     - fail: msg= "Bailing out. this play requires 'bar'"
       when: bar is not defined

數值表達:

1
2
3
4
tasks:
     -  command :  echo  {{ item }}
       with_items: [ 0, 2, 4, 6, 8, 10 ]
       when: item > 5

與Include一塊兒用:

1
2
- include: tasks /sometasks .yml
   when:  "'reticulating splines' in output"

與Role一塊兒用:

1
2
3
- hosts: webservers
   roles:
      - { role: debian_stock_config, when: ansible_os_family ==  'Debian'  }
  • loop: 循環語句,相似於編程語言的中的while

標準循環
爲了保持簡潔,重複的任務能夠用如下簡寫的方式:

1
2
3
4
- name: add several  users
   user: name={{ item }} state=present  groups =wheel
   with_items:
      - testuser1

若是你在變量文件中或者 'vars' 區域定義了一組YAML列表,你也能夠這樣作:

1
2
3
4
5
6
vars:
   somelist: [ "testuser1" ,  "testuser2" ]
tasks:
   -name: add several user
    user: name={{ item }} state=present  groups =wheel
    with_items:  "{{somelist}}"

使用 'with_items' 用於迭代的條目類型不只僅支持簡單的字符串列表.若是你有一個哈希列表,那麼你能夠用如下方式來引用子項:

1
2
3
4
5
- name: add several  users
   user: name={{ item.name }} state=present  groups ={{ item. groups  }}
   with_items:
     - { name:  'testuser1' ,  groups :  'wheel'  }
     - { name:  'testuser2' ,  groups :  'root'  }

注意:若是同時使用 when 和 with_items (或其它循環聲明),when聲明會爲每一個條目單獨執行。

嵌套循環:

1
2
3
4
5
6
7
8
9
10
11
- name: give  users  access to multiple databases
   mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs= yes  password=foo
   with_nested:
     - [  'alice' ,  'bob'  ]
     - [  'clientdb' ,  'employeedb' ,  'providerd' ]
或者
- name: give  users  access to multiple databases
   mysql_user: name={{ item.0 }} priv={{ item.1 }}.*:ALL append_privs= yes  password=foo
   with_nested:
     - [  'alice' ,  'bob'  ]
     - [  'clientdb' ,  'employeedb' ,  'providerd' ]

對字典使用循環:

1
2
3
4
5
6
7
8
9
10
11
12
13
---
vars:
   users :
     alice:
       name: Alice Appleworth
       telephone: 123-456-7890
     bob:
       name: Bob Bananarama
       telephone: 987-654-3210
tasks:
   - name: Print phone records
     debug: msg= "User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
     with_dict:  "{{users}}"

對文件列表使用循環
with_fileglob 能夠以非遞歸的方式來模式匹配單個目錄中的文件.以下面所示:

1
2
3
4
5
6
7
tasks:
     # first ensure our target directory exists
     -  file : dest= /etc/fooapp  state=directory
     # copy each file over that matches the given pattern
     - copy: src={{ item }} dest= /etc/fooapp/  owner=root mode=600
       with_fileglob:
         -  /playbooks/files/fooapp/ *
  • block: 把幾個tasks組成一塊代碼,便於針對一組操做的異常處理等操做。

多個action組裝成塊,能夠根據不一樣條件執行一段語句 :

1
2
3
4
5
6
7
8
9
10
11
tasks:
      - block:
          - yum: name={{ item }} state=installed
            with_items:
              - httpd
              - memcached
          - template: src=templates /src .j2 dest= /etc/foo .conf
          - service: name=bar state=started enabled=True
        when: ansible_distribution ==  'CentOS'
        become:  true
        become_user: root

組裝成塊處理異常更方便:

1
2
3
4
5
6
7
8
9
10
11
tasks:
   - block:
       - debug: msg= 'i execute normally'
       -  command :  /bin/false
       - debug: msg= 'i never execute, cause ERROR!'
     rescue:
       - debug: msg= 'I caught an error'
       -  command :  /bin/false
       - debug: msg= 'I also never execute :-('
     always:
       - debug: msg= "this always executes"

二、重用playbook

Playbook支持兩種重用機制,一種是重用靜態Playbook腳本,另一種是相似於編程語言中函數的機制。

  • include語句 - 重用靜態的Playbook腳本,使用起來簡單、直接。

Include語句的功能,基本的代碼重用機制。主要重用tasks。同時Include可將tasks分割成多個文件,避免Playbook過於臃腫,使用戶更關注於總體的架構,而不是實現的細節上。
普通用法
像其它語言的Include語句同樣,直接Include:

1
2
3
4
5
6
7
8
---
# possibly saved as tasks/firewall_httpd_default.yml
 
   - name: insert firewalld rule  for  httpd
     firewalld: port=80 /tcp  permanent=true state=enabled immediate=yes
main.yml文件中調用include的方法:
tasks:
     - include: tasks /firewall_httpd_default .yml

高級用法-使用參數
include文件中還能夠定義參數
被include的文件tasks/firewall_httpd_default.yml中,使用{{ port }}定義了一個名字爲port的參數。

1
2
3
---
   - name: insert firewalld rule  for  httpd
     firewalld: port={{ port }} /tcp  permanent=true state=enabled immediate=yes

傳參數的各類方法
在執行的playbook傳參數,能夠加在行尾,使用空格分隔:

1
2
3
4
tasks:
   - include: tasks /firewall .yml port=80
   - include: tasks /firewall .yml port=3260
   - include: tasks /firewall .yml port=423

還可使用yml的字典傳參數:

1
2
3
4
5
6
7
tasks:
   - include: wordpress.yml
     vars:
         wp_user: timmy
         ssh_keys:
           - keys /one .txt
           - keys /two .txt

還能夠把一條task簡寫成成一個類JSON的形式傳參數:

1
- { include: wordpress.yml, wp_user: timmy, ssh_keys: [  'keys/one.txt' ,  'keys/two.txt'  ] }

固然在playbook中已經定義了的參數,就不須要再顯示傳入值了,能夠直接寫成下面的:

1
2
3
4
5
6
7
---
- hosts: lb
   vars:
     port: 3206
   remote_user: root
   tasks:
     - include: tasks /firewall .yml
  • role語言 - Playbook的"函數機制",使用方法稍複雜、功能強大。是Playbook腳本的共享平臺ansible galaxy主要的分享方式

Role是比include更強大靈活的代碼重用和分享機制。Include相似於編程語言中的include,是重用單個文件的,功能有限。
而Role相似於編程語言中的「Package」,能夠重用一組文件造成完整的功能。例如安裝和配置apache,須要tasks實現安裝包和拷貝模版等,httpd.conf和index.html的模版文件,和handler文件實現重起功能。這些文件均可以放在一個role裏面,供不一樣的playbook文件重用。
Ansible很是提倡在playbook中使用role,而且提供了一個分享role的平臺Ansible Galaxy, https://galaxy.ansible.com/, 在galaxy上能夠找到別人寫好的role。
在ansible中,經過遵循特定的目錄結構,就能夠實現對role的定義:
下面的目錄結構定義了一個role:名字爲myrole。在site.yml,調用了這個role。
role的目錄結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
site.yml
roles/
├── myrole
     ├── tasks
     │   └── main.yml
     ├── handlers
     │   └── main.yml
     ├── defaults
     │   └── main.yml
     ├── vars
     │   └── main.yml
     ├── files
     ├── templates
     ├── README.md
     ├── meta
     │   └── main.yml
     └── tests
         ├── inventory
         └──  test .yml

site.yml中調用role

1
2
3
4
---
- hosts: webservers
   roles:
      - myrole

ansible並不要求role包含上述全部的目錄及文件,根據role的功能須要加入對應的目錄和文件。下面是每一個目錄和文件的功能。
若是 roles/x/tasks/main.yml 存在, 其中列出的 tasks 將被添加到 play 中,因此這個文件也能夠視做role的入口文件,想看role作了什麼操做,能夠今後文件看起。
若是 roles/x/handlers/main.yml 存在, 其中列出的 handlers 將被添加到 play 中
若是 roles/x/vars/main.yml 存在, 其中列出的 variables 將被添加到 play 中
若是 roles/x/meta/main.yml 存在, 其中列出的 「角色依賴」 將被添加到 roles 列表中
roles/x/tasks/main.yml中全部tasks,能夠引用 roles/x/{files,templates,tasks}中的文件,不須要指明文件的路徑。
在寫role的時候,通常都要包含role入口文件roles/x/tasks/main.yml,其它的文件和目錄,能夠根據需求選擇加入。
參數在role中是如何定義的呢
定義一個帶參數的role,名字是myrole,那麼目錄結構爲:

1
2
3
4
5
main.yml
roles
   role_with_var
     tasks
       main.yml

在roles/myrole/tasks/main.yml中,使用{{ }}定義的變量就能夠了

1
2
3
---
- name: use param
   debug: msg= "{{ param }}"

使用帶參數的role
那麼在main.yml就能夠用以下的方法使用myrole

1
2
3
4
5
---
- hosts: webservers
   roles:
     - { role: myrole, param:  'Call some_role for the 1st time'  }
     - { role: myrole, param:  'Call some_role for the 2nd time'  }

或者寫成YAML字典格式:

1
2
3
4
5
6
7
---
- hosts: webservers
   roles:
     - role: myrole
       param:  'Call some_role for the 1st time'
     - role: myrole
       param:  'Call some_role for the 2nd time'

role指定默認的參數
指定默認參數後,若是在調用時傳參數了,那麼就使用傳入的參數值.若是調用的時候沒有傳參數,那麼就使用默認的參數值.
指定默認參數很簡單,以上面的role_with_var爲例

1
2
3
4
5
6
7
main.yml
roles:
   myrole
     tasks
       main.yml
     defaults
       main.yml

在roles/myrole/defaults/main.yml中,使用yml的字典定義語法定義param的值,以下:
param: "I am the default value"
這樣在main.yml中,下面兩種調用方法均可以

1
2
3
4
5
---
- hosts: webservers
   roles:
     - role_with_var
     - { role: role_with_var, param:  'I am the value from external'  }

role與條件語句when一塊兒執行,下面的例子中,my_role只有在RedHat系列的server上才執行。

1
2
3
4
5
6
7
8
9
10
11
---
- hosts: webservers
   roles:
     - { role: my_role, when:  "ansible_os_family == 'RedHat'"  }
一樣也能夠寫成YAML字典格式
---
- hosts: webservers
   roles:
     - role: my_role
       when:  "ansible_os_family == 'RedHat'"
roles和tasks的執行順序

若是一個playbook同時出現role和tasks,他們的調用順序以下:
pre_tasks > role > tasks > post_tasks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
---
- hosts: lb
   user: root
   pre_tasks:
     - name: pre
       shell:  echo  'hello'
   roles:
     - { role: some_role }
 
   tasks:
     - name: task
       shell:  echo  'still busy'
 
   post_tasks:
     - name: post
       shell:  echo  'goodbye'
執行的結果爲:
PLAY [lb] **********************************************************************
 
 
TASK [setup] *******************************************************************
ok: [rhel7u3]
 
TASK [pre] *********************************************************************
changed: [rhel7u3]
 
TASK [some_role : some role] ***************************************************
ok: [rhel7u3] => {
     "msg" :  "Im some role"
}
 
TASK [task] ********************************************************************
changed: [rhel7u3]
 
TASK [post] ********************************************************************
changed: [rhel7u3]
 
PLAY RECAP *********************************************************************
rhel7u3                    : ok=5    changed=3    unreachable=0    failed=0

三、tags的用法
若是playbook文件比較大,在執行的時候只是想執行部分功能,這個時候沒有有解決方案呢?Playbook提供了tags便籤能夠實現部分運行。
tags的基本用法
例如,文件example.yml如何所示,標記了兩個tag:packages和configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
tasks:
   - yum: name={{ item }} state=installed
     with_items:
        - httpd
     tags:
        - packages
   - name: copy httpd.conf
     template: src=templates /httpd .conf.j2 dest= /etc/httpd/conf/httpd .conf
     tags:
        - configuration
   - name: copy index.html
     template: src=templates /index .html.j2 dest= /var/www/html/index .html
     tags:
        - configuration

那麼咱們在執行的時候,若是不加任何tag參數,那麼會執行全部的tasks

1
$ ansible-playbook example.yml

指定執行安裝部分的tasks,則能夠利用關鍵字tags

1
$ ansible-playbook example.yml --tags  "packages"

指定不執行packages部分的task,則能夠利用關鍵字skip-tags

1
$ ansible-playbook example.yml --skip-tags  "configuration"

特殊的Tags:「always」
tags的名字是用戶自定義的,可是若是你把tags的名字定義爲「always」,那麼就有點特別了。只要在執行playbook時,沒有明確指定不執行always tag,那麼它就會被執行。
在下面的例子中,即便你只指定執行packages,那麼always也會被執行。

1
2
3
4
5
6
7
8
9
10
11
12
tasks:
   - debug: msg= "Always print this debug message"
     tags:
       - always
   - yum: name= state=installed
     with_items:
        - httpd
     tags:
        - packages
   - template: src=templates /httpd .conf.j2 dest= /etc/httpd/conf/httpd .conf
     tags:
        - configuration

指定運行packages時,仍是會執行always tag對應的tasks

1
2
3
4
5
6
7
8
9
10
11
$ ansible-playbook tags_always.yml --tags  "packages"
「tagged」,「untagged」和「all」
tasks:
   - debug: msg= "I am not tagged"
     tags:
       - tag1
   - debug: msg= "I am not tagged"
分別指定--tags爲「tagged」,「untagged」和「all」試下效果吧:
$ ansible-playbook tags_tagged_untagged_all.yml --tags tagged
$ ansible-playbook tags_tagged_untagged_all.yml --tags untagged
$ ansible-playbook tags_tagged_untagged_all.yml --tags all

在include中和role中使用tags
include語句指定執行的tags的語法:

1
2
- include: foo.yml
   tags: [web,foo]

調用role中的tags的語法爲:

1
2
roles:
   - { role: webserver, port: 5000, tags: [  'web' ,  'foo'  ] }

四、playbook文件加密

ansible-vault命令能夠對配置文件進行基於密碼的加密,防止敏感信息泄漏。

加密已存在文件

1
$ ansible-vault encrypt site.yml

加密並建立文件

1
$ ansible-vault create filename

執行加密後的playbook

1
$ ansible-playbook site.yml --ask-vault-pass

解密

1
$ ansible-vault decrypt site.yml

5、編譯安裝nginx的playbook的實例

playbooks目錄結構:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ tree playbooks
playbooks
├── group_vars
├── roles
│   └── nginx
│       ├── files
│       │   ├── nginx-1.8.0. tar .gz
│       │   └── pcre-8.33. tar .gz
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── templates
│           └── default.conf
└── site.yml

yml文件內內容以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$  cat  playbooks/site.yml
---
- name: Install Nginx
   hosts:  test
   user: admin
 
   roles:
     - nginx
 
$  cat  playbooks/roles/nginx/tasks/main.yml
---
- name: Copy nginx software
   copy: src=nginx-1.8.0. tar .gz dest= /app/admin/soft/nginx-1 .8.0. tar .gz
 
- name: Copy pcre software
   copy: src=pcre-8.33. tar .gz dest= /app/admin/soft/pcre-8 .33. tar .gz
 
- name: Install Pcre
   shell:  cd  /app/admin/soft;tar zxf pcre-8.33.tar.gz;cd pcre-8.33;./configure;make;make install
   sudo :  yes
 
- name: Install Nginx
   shell:  cd  /app/admin/soft;tar zxf nginx-1.8.0.tar.gz;cd nginx-1.8.0;./configure --user=admin --group=app --prefix=/app/admin/nginx --with-http_stub_status_module --with-http_ssl_module;make;make install
 
- name: Copy nginx configuration
   template: src=default.conf dest= /app/admin/nginx/conf/nginx .conf
   notify: restart nginx
[admin@wts-vm-01 ~]$  cat  playbooks/roles/nginx/handlers/main.yml
---
- name: restart nginx
   shell:  /app/admin/nginx/sbin/nginx
   sudo :  yes

6、其它官方例子Ansible官方提供了一些比較經常使用的、通過測試的Playbook例子:https://github.com/ansible/ansible-examplesPlaybook分享平臺:https://galaxy.ansible.com/

相關文章
相關標籤/搜索