天天看點

自動化運維工具之ansibleAnsible簡述Ansible安裝Ansible配置檔案Ansible指令Ansible常用子產品詳解YAML文法簡介Ansible playbook基礎Playbook變量、handlers使用Playbook模闆templatesTemplate中for和ifPlaybook whenPlaybook字典with_ itemsAnsible Roles

自動化運維工具之ansible

  • Ansible簡述
    • Ansible的特性
    • Ansible架構
    • 利用ansible實作管理的方式
    • Ansible主要操作對象
    • 注意事項
  • Ansible安裝
    • rpm包安裝
    • 編譯安裝
    • Git方式
    • pip安裝: pip是安裝Python包的管理器,類似yum
    • 确認安裝
  • Ansible配置檔案
  • Ansible指令
  • Ansible常用子產品詳解
    • 主機連通性測試
    • command 子產品
    • shell 子產品
    • copy 子產品
    • script子產品
    • file 子產品
    • fetch 子產品
    • hostname子產品
    • cron子產品
    • yum子產品
    • service子產品
    • user子產品
    • group子產品
    • setup子產品
  • YAML文法簡介
  • Ansible playbook基礎
  • Playbook變量、handlers使用
  • Playbook模闆templates
  • Template中for和if
    • for
    • if
  • Playbook when
  • Playbook字典with_ items
    • 疊代:with_items
    • 疊代嵌套子變量
  • Ansible Roles
    • Roles目錄編排

Ansible簡述

Ansible是一款自動化運維工具,基于Python開發,集合了衆多運維工具(puppet、cfengine、chef、func、fabric)優點,實作了批量系統配置、批量程式部署、批量運作指令等功能。ansible是基于子產品工作,本身沒有批量部署的能力。真正具有批量部署的是ansible所運作的子產品,ansible隻是提供一種架構。主要包括:

(1)連接配接插件connection plugins:負責和被監控端實作通信;

(2)host inventory : 指定操作的主機,是一個配置檔案裡面定義監控的主機;

(3)各種子產品核心子產品、command子產品、自定義子產品;

(4)借助于插件完成記錄日志郵件等功能;

(5)playbook:劇本執行多個任務時,非必須可以讓節點一次運作多個任務

Ansible的特性

  1. 子產品化:調用特定的子產品,完成特定任務
  2. 有Paramiko , PyYAML , Jinja2 (模闆語言)三個關鍵子產品
  3. 支援自定義子產品
  4. 基于Python語言實作
  5. 部署簡單,基于python和SSH(預設已安裝) , agentless
  6. 安全,基于OpenSSH
  7. 支援playbook編排任務
  8. 幂等性:一個任務執行1遍和執行n遍效果一 樣,不因重複執行帶來意外情況
  9. 無需代理不依賴PKI (無需ssI )
  10. 可使用任何程式設計語言寫子產品
  11. YAML格式,編排任務,支援豐富的資料結構
  12. 較強大的多層解決方案

Ansible架構

自動化運維工具之ansibleAnsible簡述Ansible安裝Ansible配置檔案Ansible指令Ansible常用子產品詳解YAML文法簡介Ansible playbook基礎Playbook變量、handlers使用Playbook模闆templatesTemplate中for和ifPlaybook whenPlaybook字典with_ itemsAnsible Roles
Ansible:Ansible核心程式。
HostInventory:記錄由Ansible管理的主機資訊,包括端口、密碼、ip等。
Playbooks:“劇本”YAML格式檔案,多個任務定義在一個檔案中,定義主機需要調用哪些子產品來完成的功能。
Core Modules:核心子產品,主要操作是通過調用核心子產品來完成管理任務。
CustomModules:自定義子產品,完成核心子產品無法完成的功能,支援多種語言。
PLUGINS :子產品功能的補充,如連接配接類型插件、循環插件、變量插件、過濾插
件等,該功能不常用
ConnectionPlugins:連接配接插件,Ansible和Host通信使用
           

利用ansible實作管理的方式

  1. Ad-Hoc即ansible指令, 主要用于臨時指令使用場景
  2. Ansible-playbook主要用于長期規劃好的,大型項目的場景,需要有前提的規劃。

Ansible主要操作對象

  1. HOSTS主機
  2. NETWORKING網絡裝置

注意事項

  1. 執行ansible的主機-般稱為主要端,中控, master或堡壘機
  2. 主要端Python版本需要2.6或以上
  3. 被控端Python版本小于2.4需要安裝python-simplejson
  4. 被控端如開啟SELinux需 要安裝libselinux-python
  5. windows不能做為主要端

Ansible安裝

rpm包安裝

//擷取EPEL源
[[email protected] ~]# cd /etc/yum.repos.d/
[[email protected] yum.repos.d]#mkdir bak && mv C* bak/
[[email protected] yum.repos.d]#wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
--2020-05-20 21:45:57--  http://mirrors.aliyun.com/repo/epel-7.repo
正在解析主機 mirrors.aliyun.com (mirrors.aliyun.com)... 183.201.230.97, 183.201.230.100, 183.201.230.94, ...
正在連接配接 mirrors.aliyun.com (mirrors.aliyun.com)|183.201.230.97|:80... 已連接配接。
已發出 HTTP 請求,正在等待回應... 200 OK
長度:664 [application/octet-stream]
正在儲存至: “/etc/yum.repos.d/epel.repo”

100%[============================================================================================>] 664         --.-K/s 用時 0s      

2020-05-20 21:45:58 (269 MB/s) - 已儲存 “/etc/yum.repos.d/epel.repo” [664/664])
[[email protected] ~]# yum install -y ansible
.............
           

編譯安裝

yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
           

Git方式

gitclone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
           

pip安裝: pip是安裝Python包的管理器,類似yum

yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
           

确認安裝

[[email protected] ~]# ansible --version
ansible 2.9.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
           

Ansible配置檔案

配置檔案

配置檔案 作用
/etc/ansible/ansible.cfg 主配置檔案,配置ansible工作特性
/etc/ansible/hosts 主機清單
/etc/ansible/roles/ 存放角色的目錄

配置檔案/etc/ansible/ansible.cfg

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 #日志檔案

定義主機清單即要被控制的主機

//vim /etc/ansible/hosts在最後添加
[webservers]
10.0.0.137
           

ansible配置公私鑰

上面我們已經提到過 ansible 是基于 ssh 協定實作的,是以其配置公私鑰的方式與 ssh 協定的方式相同,具體操作步驟如下:

//生成私鑰
[[email protected] ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xHXbYgRfPN6lB+zQR7h45tlSjNT+HC+rixbAuFcLVxQ [email protected]
The key's randomart image is:
+---[RSA 2048]----+
|          ooE=.+.|
|       . . +o+O +|
|       oo  .=*[email protected]|
|      ..+ o...O.*|
|       .S= . + *+|
|      . . o   = =|
|       .   .   + |
|          ..  .  |
|         .. oo   |
+----[SHA256]-----+

//向主機分發私鑰
[[email protected] ~]# ssh-copy-id 10.0.0.137
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '10.0.0.137 (10.0.0.137)' can't be established.
ECDSA key fingerprint is SHA256:HdwXx3rYMt0dZtBvrXEM5D+imcJqc/1vfn6Cnj7SddQ.
ECDSA key fingerprint is MD5:dd:7e:55:12:9e:61:a7:04:35:ab:cf:21:77:d1:4b:f5.
Are you sure you want to continue connecting (yes/no)? yes   //确認連接配接
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password: 	//輸入連接配接的密碼

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '10.0.0.137'"
and check to make sure that only the key(s) you wanted were added.
           

Ansible指令

ansible:主程式,臨時指令執行工具

Usage:ansible <host-pattern>[-m module_name] [-a args]
		-m:指定要使用的子產品,不指定預設是command
		-v:檢視詳細資訊,同時支援-vvv,-vvvv可檢視更詳細資訊
		-a:子產品的參數	
		--version:顯示版本
		--list-hosts:顯示主機清單,可簡寫--list
		-k, --ask-pass:提示輸入ssh連接配接密碼,預設Key驗證
		-K, --ask-become-pass:提示輸入sudo時的密碼
		-C, --check:檢查,并不執行
		-T, --timeout=TIMEOUT:執行指令的逾時時間,預設10s
		-u, --user= REMOTE_USER:執行遠端執行的使用者
		-b, --become:代替舊版的sudo切換
           
ansible的Host-pattern
比對主機的清單
	All:表示所有Inventory中的所有主機
		ansible all -m ping
	*:通配符
		ansible  "*" -m ping
		ansible 192.168.1.* -m ping
		ansible "*srvs" -m ping
	或關系
		ansible "websrvs:appsrvs" -m ping
		ansible "192.168.1.10:192.168.1.20" -m ping
	邏輯與
		ansible "websrvs:&dbsrvs" -m ping
		在websrvs組并且在dbsrvs組中的主機
	邏輯非
		ansible 'websrvs:!dbsrvs' -m ping
		在websrvs組,但不在dbsrvs組中的主機
		注意:此處為單引号
	綜合邏輯
		ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' -m ping
	正規表達式
		ansible "websrvs:&dbsrvs" -m ping
		ansible "~(web|db).*\.magedu\.com" -m 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退出

執行狀态:

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

黃色:執行成功并且對目标主機做變更

紅色:執行失敗

ansible-doc:檢視配置文檔,子產品功能檢視工具

Usage: ansible-doc [options] [module...]
		-a:顯示所有子產品的文檔
		-s:顯示指定子產品的playbook片段
		-l:列出可用的子產品
           

ansible-galaxy:下載下傳和上傳優秀代碼或Roles子產品的官網平台

usage: ansible-galaxy [-h] [--version] [-v] TYPE ...
		list:列出所有已經安裝的galaxy
		install:安裝galaxy,角色包
		remove:删除galaxy角色包
           

ansible-playbook:定制自動化任務,編排劇本工具

usage: ansible-playbook [-h] [--version] [-v] [-k]
		-t:運作指定的tags
		-e:定義變量
		-C:檢查playbook文法
           

ansible-pull:遠端執行指令的工具,拉取配置而非推送配置

ansible-vault:檔案加密工具

encrypt	       加密yml檔案
decrypt        解密yml檔案
view           檢視yml加密檔案
edit           編輯加密檔案
rekey          重新修改加密密碼
create         建立新檔案
           

ansible-console基于Console界面與使用者互動的執行工具

Ansible常用子產品詳解

主機連通性測試

我們使用ansible all -m ping指令來進行主機連通性測試,效果如下:

[[email protected] ansible]# ansible all -m ping
10.0.0.137 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
           

command 子產品

這個子產品可以直接在遠端主機上執行指令,并将結果傳回本主機。

[[email protected] ansible]# ansible all  -m command -a 'ss -ntl'
10.0.0.137 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:80                       *:*                  
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      128    127.0.0.1:631                      *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128    127.0.0.1:6010                     *:*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      128        ::1:631                     :::*                  
LISTEN     0      100        ::1:25                      :::*                  
LISTEN     0      128        ::1:6010                    :::*      
           

指令子產品接受指令名稱,後面是空格分隔的清單參數。給定的指令将在所有標明的節點上執行。它不會通過shell進行處理,比如$HOME和操作如"<",">","|",";","&" 工作(需要使用(shell)子產品實作這些功能)。注意,該指令不支援| 管道指令。

 

該子產品下常用的幾個指令:

chdir       # 在執行指令之前,先切換到該目錄

executable # 切換shell來執行指令,需要使用指令的絕對路徑

free_form   # 要執行的Linux指令,一般使用Ansible的-a參數代替。

creates  # 一個檔案名,當這個檔案存在,則該指令不執行,可以

用來做判斷

removes # 一個檔案名,這個檔案不存在,則該指令不執行

shell 子產品

shell子產品可以在遠端主機上調用shell解釋器運作指令,支援shell的各種功能,例如管道等。

[[email protected] ansible]# ansible all  -m shell -a 'cat /etc/passwd |grep "root"'
10.0.0.137 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
           

隻要是我們的shell指令,都可以通過這個子產品在遠端主機上運作。

copy 子產品

這個子產品用于将檔案複制到遠端主機,同時支援給定内容生成檔案和修改權限等。

其相關選項如下:
src          	  #被複制到遠端主機的本地檔案。可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,則會遞歸複制,用法類似于"rsync"
content   		   #用于替換"src",可以直接指定檔案的值
dest            #必選項,将源檔案複制到的遠端主機的絕對路徑
backup            #當檔案内容發生改變後,在覆寫之前把源檔案備份,備份檔案包含時間資訊
directory_mode    #遞歸設定目錄的權限,預設為系統預設權限
force   		   #當目标主機包含該檔案,但内容不同時,設為"yes",表示強制覆寫;設為"no",表示目标主機的目标位置不存在該檔案才複制。預設為"yes"
others           #所有的 file 子產品中的選項可以在這裡使用
           

舉例:

1、複制檔案

[[email protected] ~]# ansible all -m copy -a 'src=12345 dest=/root'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "e9b2de1c4e921b09ad8a8f17b0236a379fe07ee4", 
    "dest": "/root/12345", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "4d701311bad1fe03103044e744812f21", 
    "mode": "0644", 
    "owner": "root", 
    "size": 10, 
    "src": "/root/.ansible/tmp/ansible-tmp-1590162116.92-13109-195905256318648/source", 
    "state": "file", 
    "uid": 0
}
           

2、給定内容生成檔案,并制定權限

[[email protected] ~]# ansible all -m copy -a 'content="Hello world\n" dest=/data/name mode=666'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "33ab5639bfd8e7b95eb1d8d0b87781d4ffea4d5d", 
    "dest": "/data/name", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "f0ef7081e1539ac00ef5b761b4fb01b3", 
    "mode": "0666", 
    "owner": "root", 
    "size": 12, 
    "src": "/root/.ansible/tmp/ansible-tmp-1590165401.66-13836-73245737274512/source", 
    "state": "file", 
    "uid": 0
}
           

我們現在可以去檢視一下我們生成的檔案及其權限:

[[email protected] ~]# ansible all -m shell -a 'ls -l /data/'
10.0.0.137 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 5月  20 15:24 file1
-rw-r--r-- 1 root root  0 5月  20 15:24 file2
-rw-r--r-- 1 root root  0 5月  20 15:24 file3
-rw-r--r-- 1 root root 81 5月  20 15:53 for1.conf
-rw-rw-rw- 1 root root 12 5月  20 00:36 name
           

可以看出我們的name檔案已經生成,并且權限為666

3、關于覆寫

我們把檔案的内容修改一下,然後選擇覆寫備份:

[[email protected] ~]# ansible all -m copy -a 'content="Hello yanyujie\n" dest=/data/name mode=666 backup=yes'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/data/[email protected]:40:11~", 
    "changed": true, 
    "checksum": "56992803795a3a502f5448700e95385a9907f2eb", 
    "dest": "/data/name", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "858e667f63d8b6040ab71574d80cdef4", 
    "mode": "0666", 
    "owner": "root", 
    "size": 15, 
    "src": "/root/.ansible/tmp/ansible-tmp-1590165610.35-13943-170133111730692/source", 
    "state": "file", 
    "uid": 0
}
           

現在我們可以去檢視一下:

[[email protected] ~]# ansible all -m shell -a 'ls -l /data/'
10.0.0.137 | CHANGED | rc=0 >>
總用量 12
-rw-r--r-- 1 root root  0 5月  20 15:24 file1
-rw-r--r-- 1 root root  0 5月  20 15:24 file2
-rw-r--r-- 1 root root  0 5月  20 15:24 file3
-rw-r--r-- 1 root root 81 5月  20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月  23 00:40 name
-rw-rw-rw- 1 root root 10 5月  23 00:39 [email protected]:40:11~
           

可以看出,我們的源檔案已經被備份

script子產品

該子產品用于将本機的腳本在被管理端的機器上運作。

該子產品直接指定腳本的路徑即可,我們通過例子來看一看到底如何使用的:

首先,我們寫一個腳本,并給其加上執行權限:

[[email protected] ~]# vim test.sh
#!/bin/bash
date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log 
[[email protected] ~]# chmod +x test.sh
           

然後,我們直接運作指令來實作在被管理端執行該腳本:

[[email protected] ~]# ansible all -m script -a 'test.sh'
10.0.0.137 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 10.0.0.137 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 10.0.0.137 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
           

照例檢視一下檔案内容:

[[email protected] ~]#  ansible all -m shell -a 'cat /tmp/disk_total.log'
10.0.0.137 | CHANGED | rc=0 >>
2020年 05月 20日 星期三 00:32:43 CST
檔案系統                 容量  已用  可用 已用% 挂載點
/dev/mapper/centos-root   38G  3.4G   35G    9% /
devtmpfs                 978M     0  978M    0% /dev
tmpfs                    993M  144K  993M    1% /dev/shm
tmpfs                    993M  8.9M  985M    1% /run
tmpfs                    993M     0  993M    0% /sys/fs/cgroup
/dev/sr0                 4.2G  4.2G     0  100% /var/www/html/centos/6
/dev/sda1                497M  140M  357M   29% /boot
tmpfs                    199M   16K  199M    1% /run/user/0
/dev/sr1                 4.1G  4.1G     0  100% /mnt
           

可以看出已經執行成功了。

file 子產品

該子產品主要用于設定檔案的屬性,比如建立檔案、建立連結檔案、删除檔案等。

下面是一些常見的指令:

force  #需要在兩種情況下強制建立軟連結,一種是源檔案不存在,但之後會建立的情況下;另一種是目标軟連結已存在,需要先取消之前的軟鍊,然後建立新的軟鍊,有兩個選項:yes|no
group  #定義檔案/目錄的屬組。後面可以加上mode:定義檔案/目錄的權限
owner  #定義檔案/目錄的屬主。後面必須跟上path:定義檔案/目錄的路徑
recurse  #遞歸設定檔案的屬性,隻對目錄有效,後面跟上src:被連結的源檔案路徑,隻應用于state=link的情況
dest  #被連結到的路徑,隻應用于state=link的情況
state  #狀态,有以下選項:
		directory:如果目錄不存在,就建立目錄
		file:即使檔案不存在,也不會被建立
		link:建立軟連結
		hard:建立硬連結
		touch:如果檔案不存在,則會建立一個新的檔案,如果檔案或目錄已存在,則更新其最後修改時間
		absent:删除目錄、檔案或者取消連結檔案
           

用法舉例如下:

1、建立目錄

[[email protected] ~]# ansible all -m file -a 'path=/data/app state=directory'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/data/app", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
           

我們可以檢視一下:

[[email protected] ~]# ansible all -m shell -a 'ls -l /data'
10.0.0.137 | CHANGED | rc=0 >>
總用量 12
drwxr-xr-x 2 root root  6 5月  20 00:45 app
-rw-r--r-- 1 root root  0 5月  20 15:24 file1
-rw-r--r-- 1 root root  0 5月  20 15:24 file2
-rw-r--r-- 1 root root  0 5月  20 15:24 file3
-rw-r--r-- 1 root root 81 5月  20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月  20 00:40 name
-rw-rw-rw- 1 root root 10 5月  20 00:39 [email protected]:40:11~
           

可以看出,我們的目錄已經建立完成。

2、建立連結檔案

[[email protected] ~]# ansible all -m file -a 'path=/data/file1.ln src=/data/file1 state=link'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/file1.ln", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 11, 
    "src": "/data/file1", 
    "state": "link", 
    "uid": 0
}
           

我們可以去檢視一下:

[[email protected] ~]#  ansible all -m shell -a 'ls -l /data'
10.0.0.137 | CHANGED | rc=0 >>
總用量 12
drwxr-xr-x 2 root root  6 5月  23 00:45 app
-rw-r--r-- 1 root root  0 5月  20 15:24 file1
lrwxrwxrwx 1 root root 11 5月  23 00:51 file1.ln -> /data/file1
-rw-r--r-- 1 root root  0 5月  20 15:24 file2
-rw-r--r-- 1 root root  0 5月  20 15:24 file3
-rw-r--r-- 1 root root 81 5月  20 15:53 for1.conf
-rw-rw-rw- 1 root root 15 5月  23 00:40 name
-rw-rw-rw- 1 root root 10 5月  23 00:39 [email protected]:40:11~
           

我們的連結檔案已經建立成功。

3、删除檔案

[[email protected] ~]# ansible all -m file -a 'path=/data/file1 state=absent'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/file1", 
    "state": "absent"
}
           

我們可以檢視一下:

[[email protected] ~]# ansible all -m shell -a 'ls /data/file1'
10.0.0.137 | FAILED | rc=2 >>
ls: 無法通路/data/file1: 沒有那個檔案或目錄non-zero return code
           

發現已經沒有這個檔案了。

fetch 子產品

該子產品用于從遠端某主機擷取(複制)檔案到本地。

有兩個選項:

dest:用來存放檔案的目錄

src:在遠端拉取的檔案,并且必須是一個file,不能是目錄

具體舉例如下:

[[email protected] ~]#  ansible all -m fetch -a 'src=/data/name dest=/data' 
10.0.0.137 | CHANGED => {
    "changed": true, 
    "checksum": "56992803795a3a502f5448700e95385a9907f2eb", 
    "dest": "/data/10.0.0.137/data/name", 
    "md5sum": "858e667f63d8b6040ab71574d80cdef4", 
    "remote_checksum": "56992803795a3a502f5448700e95385a9907f2eb", 
    "remote_md5sum": null
}
           

我們可以在本機上檢視一下檔案是否複制成功。要注意,檔案儲存的路徑是我們設定的接收目錄下的被管制主機ip目錄下:

[[email protected] ~]# cat /data/10.0.0.137/data/name 
Hello yanyujie
           

hostname子產品

管理主機名

[[email protected] ~]# ansible all -m hostname -a 'name=node1'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "", 
        "ansible_fqdn": "node1", 
        "ansible_hostname": "node1", 
        "ansible_nodename": "node1", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "node1"
}
           

檢視主機名驗證是否修改成功

[[email protected] ~]# ansible all -m shell -a 'hostname'
10.0.0.137 | CHANGED | rc=0 >>
node1
           

cron子產品

該子產品适用于管理cron計劃任務的。

其使用的文法跟我們的crontab檔案中的文法一緻,同時,可以指定以下選項:

day= 	#日應該運作的工作( 1-31, *, */2, )
hour= 	# 小時 ( 0-23, *, */2, )
minute= 	#分鐘( 0-59, *, */2, )
month= 	# 月( 1-12, *, /2, )
weekday= 	# 周 ( 0-6 for Sunday-Saturday,, )
job= 	#指明運作的指令是什麼
name= 	#定時任務描述
reboot 	# 任務在重新開機時運作,不建議使用,建議使用special_time
special_time 	#特殊的時間範圍,參數:reboot(重新開機時),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小時)
state 	#指定狀态,present表示添加定時任務,也是預設設定,absent表示删除定時任務
user 	# 以哪個使用者的身份執行
disabled  #true禁用一條計劃任務
           

舉例如下:

1、添加計劃任務

[[email protected] ~]# ansible all -m cron -a "name=warning minute=* weekday=1,2,3,4,5 job='/usr/bin/wall warning'"
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warning"
    ]
}
           

我們可以去檢視一下:

[[email protected] ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
#Ansible: warning
 * * * * 1,2,3,4,5 /usr/bin/wall warning
           

可以看出,我們的計劃任務已經設定成功了。

2、删除計劃任務

如果我們的計劃任務添加錯誤,想要删除的話,則執行以下操作:

首先我們檢視一下現有的計劃任務:

[[email protected] ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
#Ansible: warning
 * * * * 1,2,3,4,5 /usr/bin/wall warning
           

然後執行删除操作:

[[email protected] ~]# ansible all -m cron -a 'name=warning state=absent'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}
           

删除完成後,我們再檢視一下現有的計劃任務确認一下:

[email protected] ~]# ansible all -m shell -a 'crontab -l'
10.0.0.137 | CHANGED | rc=0 >>
           

我們的删除操作已經成功。

yum子產品

用于軟體的安裝

其選項如下

name=          #所安裝的包的名稱
state=	    	#present安裝,latest安裝最新的,absent解除安裝軟體。
           

下面我們就來安裝一個包試試看:

[[email protected] ~]# ansible all -m yum -a 'name=httpd'
10.0.0.137 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "httpd-2.4.6-40.el7.centos.x86_64 providing httpd is already installed"
    ]
}
           

安裝成功。

service子產品

該子產品用于服務程式的管理。

其主要選項如下:

enabled		#設定開機啟動
name= 		#服務名稱
state= 		#有四種狀态,分别為:
			started		啟動服務
			stopped		停止服務
			restarted	重新開機服務
			reloaded	重載配置
           

1、開啟服務并設定自啟動

[[email protected] ~]# ansible all -m service -a 'name=httpd enabled=yes state=started'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "httpd", 
    "state": "started", 
    ................
        }
}
           

我們可以去檢視一下端口是否打開:

[[email protected] ~]# ansible all -m shell -a 'ss -ntl|grep 80'
10.0.0.137 | CHANGED | rc=0 >>
LISTEN     0      128          *:80                       *:*                  
LISTEN     0      128         :::8088                    :::*    
           

關閉服務

[[email protected] ~]# ansible all -m service -a 'name=httpd state=stopped'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "httpd", 
    "state": "stopped", 
    ...
            }
}
           

一樣的,我們來檢視一下端口:

[[email protected] ~]# ansible all -m shell -a 'ss -ntl|grep 80'
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
           

可以看出,我們已經沒有80端口了,說明我們的httpd服務已經關閉了。

user子產品

該子產品主要是用來管理使用者賬号。

其選項如下:

comment  # 使用者的描述資訊
createhome  # 是否建立家目錄
force  # 在使用state=absent時, 行為與userdel –force一緻.
group  # 指定基本組
groups  # 指定附加組,如果指定為(groups=)表示删除所有組
home  # 指定使用者家目錄
move_home  # 如果設定為home=時, 試圖将使用者主目錄移動到指定的目錄
name  # 指定使用者名
non_unique  # 該選項允許改變非唯一的使用者ID值
password  # 指定使用者密碼
remove  # 在使用state=absent時, 行為是與userdel –remove一緻
shell  # 指定預設shell
state  # 設定帳号狀态,不指定為建立,指定值為absent表示删除
system  # 當建立一個使用者,設定這個使用者是系統使用者。這個設定不能更改現有使用者
uid  # 指定使用者的uid
           

1、添加一個使用者并指定其 uid

[[email protected] ~]# ansible all -m user -a 'name=yyj uid=6666'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "append": false, 
    "changed": true, 
    "comment": "yyj", 
    "group": 1000, 
    "home": "/home/yyj", 
    "move_home": false, 
    "name": "yyj", 
    "shell": "/bin/bash", 
    "state": "present", 
    "uid": 6666
}
           

添加完成,我們可以去檢視一下:

[[email protected] ~]# ansible all -m shell -a 'cat /etc/passwd |grep yyj'
10.0.0.137 | CHANGED | rc=0 >>
yyj:x:6666:1000:yyj:/home/yyj:/bin/bash
           

2、删除使用者

[[email protected] ~]# ansible all -m user -a 'name=yyj state=absent'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "yyj", 
    "remove": false, 
    "state": "absent"
}
           

一樣的,删除之後,我們去看一下:

[[email protected] ~]# ansible all -m shell -a 'cat /etc/passwd |grep yyj'
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
           

發現已經沒有這個使用者了。

group子產品

該子產品主要用于添加或删除組。

常用的選項如下:

gid=  #設定組的GID号
name=  #指定組的名稱
state=  #指定組的狀态,預設為建立,設定值為absent為删除
system=  #設定值為yes,表示建立為系統組
           

1、建立組

[[email protected] ~]#  ansible all  -m group -a 'name=yyj gid=6666'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 6666, 
    "name": "yyj", 
    "state": "present", 
    "system": false
}
           

建立過後,我們來檢視一下:

[[email protected] ~]# ansible all -m shell -a 'cat /etc/group | grep 6666' 
10.0.0.137 | CHANGED | rc=0 >>
yyj:x:6666:
           

可以看出,我們的組已經建立成功了

2、删除組

[[email protected] ~]# ansible all -m group -a 'name=yyj state=absent'
10.0.0.137 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "yyj", 
    "state": "absent"
}
           

驗證一下

[[email protected] ~]# ansible all -m shell -a 'cat /etc/group | grep 6666' 
10.0.0.137 | FAILED | rc=1 >>
non-zero return code
           

發現組已經被删除

setup子產品

該子產品主要用于收集資訊,是通過調用facts元件來實作的。

  facts元件是Ansible用于采集被管機器裝置資訊的一個功能,我們可以使用setup子產品查機器的所有facts資訊,可以使用filter來檢視指定資訊。整個facts資訊被包裝在一個JSON格式的資料結構中,ansible_facts是最上層的值。

  facts就是變量,内建變量 。每個主機的各種資訊,cpu顆數、記憶體大小等。會存在facts中的某個變量中。調用後傳回很多對應主機的資訊,在後面的操作中可以根據不同的資訊來做不同的操作。如redhat系列用yum安裝,而debian系列用apt來安裝軟體。

  常用選項:

  filter=        #過濾想要的結果,支援通配符
  --tree	/path  和filter合起來用将過濾的資訊儲存在某個檔案去
           
[[email protected] ~]# ansible all -m setup -a 'filter="*vcpus*"' 
10.0.0.137 | SUCCESS => {
    "ansible_facts": {
        "ansible_processor_vcpus": 2, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
           

YAML文法簡介

  • 大小寫敏感
  • 使用縮進表示層級關系
  • 縮進時不允許使用Tab鍵,隻允許使用空格。
  • 縮進的空格數目不重要,隻要相同層級的元素左側對齊即可
  • #表示注釋,從這個字元一直到行尾,都會被解析器忽略
  • YAML 還有一個小的怪癖. 所有的 YAML 檔案(無論和 Ansible 有沒有關系)開始行都應該是

    ---

    . 這是 YAML 格式的一部分, 表明一個檔案的開始。
  • 清單中的所有成員都開始于相同的縮進級别, 并且使用一個 "- " 作為開頭(一個橫杠和一個空格)
  • 一個字典是由一個簡單的 鍵: 值 的形式組成(這個冒号後面必須是一個空格)
  • Ansible 使用 “{{ var }}” 來引用變量

Ansible playbook基礎

Ansible-playbook (劇本)執行過程:

  • 将已有編排好的任務集寫入Ansible-Playbook
  • 通過ansible-playbook指令分拆任務集至逐條ansible指令,按預定規則逐條執行
    自動化運維工具之ansibleAnsible簡述Ansible安裝Ansible配置檔案Ansible指令Ansible常用子產品詳解YAML文法簡介Ansible playbook基礎Playbook變量、handlers使用Playbook模闆templatesTemplate中for和ifPlaybook whenPlaybook字典with_ itemsAnsible Roles

playbook.yml 常包含下面幾個關鍵字:

  • hosts:執行的遠端主機清單,為主機的IP,或者主機組名,或者關鍵字all
  • remote_user: 以哪個使用者身份執行。
  • vars: 内置變量或自定義變量在playbook中調用
  • tasks: 任務集
  • Templates:模闆,可替換模闆檔案中的變量并實作一些簡單邏輯的檔案
  • 每一個task必須有一個名稱name,這樣在運作playbook時,從其輸出的任務執行資訊中可以很好的辨識出是屬于哪一個task的
  • tags标簽指定某條任務執行,用于選擇運作playbook中的部分代碼。ansible具有幂等性,是以會自動跳過沒有變化的部分,即便如此,有些代碼為測試其确實沒有發生變化的時間依然會非常地長。此時,如果确信其沒有變化,就可以通過tags跳過此些代碼片斷
  • handers:是playbook的event ,預設不會執行,在action裡觸發才會執行。多次觸發隻執行一次。Handlers和notity結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
如果指令或腳本的退出碼不為零,可以使用如下方式替代
tasks:
 - name: run this command and ignore the result
   shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors來忽略錯誤資訊:
tasks:
 - name: run this command and ignore the result
   shell: /usr/ bin/somecommand
   ignore_errors: True
           

一個簡單的示例:

---
- hosts: webservers
  remote_user: root

  tasks:
    - name: install pakeges
      yum: name=httpd
      tags: install
    - name: create user
      user: name=yanyujie uid=666 system=yes
    - name: start service
      service: name=httpd state=started
           

Playbook變量、handlers使用

變量

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

變量來源:

  • ansible setup facts遠端主機的所有變量都可直接調用
  • 在/etc/ansible/hosts中定義

    普通變量:主機組中主機單獨定義,優先級高于公共變量

    公共(組)變量:針對主機組中所有主機定義統一變量

  • 通過指令行指定變量,優先級最高

    ansible-playbook -e varname=value

  • 在playbook中定義
vars:
  - var1: value1
  - var2: value2
           
  • 在role中定義

變量的優先級

指令行定義>playbook中定義>/etc/ansible/hosts中定義

變量調用

通過{{ variable_name }} 調用變量,且變量名前後必須有空格,有時用"{{ variable_name }}”才生效

Handlers

是task清單,這些task與前述的task并沒有本質上的不同,用于當關注的資源發生變化時,才會采取一定的操作

Notify此action可用于在每個play的最後被觸發,這樣可避免多次有改變發生

時每次都執行指定的操作,僅在所有的變化發生完成後一次性地執行指定操作。在notify中列出的操作稱為handler ,也即notify中調用handler中定義的操作

一個notify可以跟多個handlers

例子:

---
- hosts: webservers
  remote_user: root
  vars: 
    - http_port: 8088

  tasks:
    - name: install pakeges
      yum: name=httpd
      tags: install
    - name: copy config file
      copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf 
      notify: restart service
    - name: start service
      service: name=httpd state=started

  handlers:
    - name: restart service
      service: name=httpd state=restarted
           

Playbook模闆templates

  • 文本檔案 ,嵌套有腳本(使用模闆程式設計語言編寫)
  • Jinja2語言,使用字面量,有下面形式

    字元串:使用單引号或雙引号

    數字:整數,浮點數

    清單: [item1, item2, …]

    元組: (item1, item2, …)

    字典: {key1:value1, key2:value2…}

    布爾型: true/false

  • 算術運算: +.-.*,/,//, %,**
  • 比較操作: ==,!=,>, >=,<, <=
  • 邏輯運算: and, or, not
  • 流表達式: For If When

templates功能:根據子產品檔案動态生成對應的配置檔案

templates檔案必須存放于templates目錄下,且命名為j2結尾

yaml/yml檔案需和templates目錄平級,目錄結構如下:

./
├── temnginx.yml
└── templates
        └── nginx.conf.j2
           

例子:

複制/etc/nginx/nginx.conf到templates目錄并命名為nginx.conf.j2,修改nginx.conf.j2 下面行為

worker_processes {{ ansible_processor_vcpus }};

---
- hosts: webservers
 remote_user: root

 tasks:
   - name: install pakeges
     yum: name=nginx
   - name: copy template file
     template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 
     notify: restart service
   - name: start service
     service: name=nginx state=started

 handlers:
   - name: restart service
     service: name=nginx state=restarted
           

效果:啟動nginx服務,每個伺服器會根據自己的CPU數來決定多少個程序

Template中for和if

for

格式:

{% for M in N %}

{% endfor %}

例子:

//劇本檔案
[[email protected] ansible]# cat testfor.yml
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - 81
      - 82
      - 83

  tasks:
    - name: copy file
      template: src=for1.conf.j2 dest=/data/for1.conf

//模闆檔案
[[email protected] ansible]# cat templates/for1.conf.j2 
{% for port in ports %}
server {
    listen {{ port }}
}
{% endfor %}

//運作劇本
[[email protected] ansible]# ansible-playbook testfor.yml 

PLAY [all] ***************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [10.0.0.137]

TASK [copy file] *********************************************************************************************************************
ok: [10.0.0.137]

PLAY RECAP ***************************************************************************************************************************
10.0.0.137                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

//檢視生成的檔案
[[email protected] ansible]# ansible all -m shell -a 'cat /data/for1.conf'
10.0.0.137 | CHANGED | rc=0 >>
server {
    listen 81
}


server {
    listen 82
}


server {
    listen 83
}
           

if

格式:

{% if M is defined %}

{% endif %}

例子:

// 劇本檔案temnginx.yml
---
- hosts: webservers
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
         listen: 8080
		 root: "/var/www/nginx/web1/"
	  - web2: 
		 listen: 8080
		 server_name: "web2.yanyujie.com"
		 root: "/var/www/nginx/web2/"
	  - web3:
  		 listen: 8080
		 server_name: "web3.yanyujie.com"
 		 root: "/var/www/nginx/web3/"

  tasks:
    - name: template config to
	  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

//模闆檔案templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
	server {
		listen {{ vhost.listen }}
		{% if vhost.server_name is defined %}
		server_name {{ vhost.server_name }}
		{% endif %}
		root {{ vhost.root }}
}
{% endfor %}

//運作生成的結果
server {
		listen 8080
		root /var/www/nginx/web1/
}
server {
		listen 8080
		server_name web2.yanyujie.com
		root /var/www/nginx/web2/
}
server {
		listen 8080
		server_name web3.yanyujie.com
		root /var/www/nginx/web3/
}

           

Playbook when

  • 條件測試:如果需要根據變量、facts或此前任務的執行結果來做為某task執行與否的前提時要用到條件測試,通過when語句實作,在task中使用, jinja2的文法格式
  • when語句
  • 在task後添加when子句即可使用條件測試; when語句支援Jinja2表達式文法
  • 示例:
tasks:
    - name: "shutdown RedHat flavored systems '
      command: /sbin/shutdown -h now
      when: ansible_OS_family == " RedHat'
           

例子:

---
- hosts: webservers
  remote_user: root
  vars: 
    - http_port: 8088

  tasks:
    - name: install pakeges
      yum: name=httpd
      tags: install
    - name: copy template file
      template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf 
      when: ansible_distribution_major_version == '7'
      notify: restart service
    - name: start service
      service: name=httpd state=started

  handlers:
    - name: restart service
      service: name=httpd state=restarted
           

Playbook字典with_ items

疊代:with_items

疊代:當有需要重複性執行的任務時,可以使用疊代機制

  • 對疊代項的引用,固定變量名為”item"
  • 要在task中使用with_items給定要疊代的元素清單
  • 清單格式:

    字元串

    字典

例子:

---
- hosts: webservers
  remote_user: root

  tasks:
    - name: create some users
      user: name={{ item }} shell=/sbin/nologin system=yes
      with_items:
        - test1
        - test2
        - test3
           

效果:test1、test2、test3都會創出

疊代嵌套子變量

分别建立g1,g2,g3三個組,建立user1,user2,user3,分别加入g1,g2,g3組裡面

---
- hosts: webservers
  remote_user: root

  tasks:
    - name: create some groups
      group: name={{ item }}
      with_items:
        - g1
        - g2
        - g3
    - name: create some users
      user: name={{ item.user }} groups={{ item.group }}
      with_items:
        - { user: 'user1',group: 'g1' }
        - { user: 'user2',group: 'g2' }
        - { user: 'user3',group: 'g3' }
           

Ansible Roles

roles

ansilbe自1.2版本引入的新特性,用于層次性、結構化地組織playbook。 roles

能夠根據層次型結構自動裝載變量檔案、tasks以及handlers等。 要使用roles隻需要在playbook中使用include指令即可。簡單來講, roles就是通過分别将變量、檔案、任務、模闆及處理器放置于單獨的目錄中,并可以便捷地include它們的一種機制。角色一般用于基于主機建構服務的場景中,但也可以是用于建構守護程序等場景中

複雜場景:建議使用roles ,代碼複用度高

  • 變更指定主機或主機組
  • 如命名不規範維護和傳承成本大
  • 某些功能需多個Playbook ,通過Includes即可實作

Roles目錄編排

自動化運維工具之ansibleAnsible簡述Ansible安裝Ansible配置檔案Ansible指令Ansible常用子產品詳解YAML文法簡介Ansible playbook基礎Playbook變量、handlers使用Playbook模闆templatesTemplate中for和ifPlaybook whenPlaybook字典with_ itemsAnsible Roles

roles目錄結構

每個角色,以特定的層級目錄結構進行組織

roles目錄結構:
./
├──playbook.yml
└──roles/
    └──project/
	  	  ├──tasks/
	  	  ├──files/
	  	  ├──vars/			不常用
	  	  ├──default/		不常用
		  ├──templates/
		  ├──handlers/
		  ├──meta/			不常用
           

各目錄作用

/roles/project/ :項目名稱,有以下子目錄

  • files/ : 存放由copy或script子產品等調用的檔案
  • templates/ : template子產品查找所需要模闆檔案的目錄
  • tasks/ :定義task,role的基本元素,至少應該包含一個名為main.yml的檔案;其它的檔案需要在此檔案中通過include進行包含
  • handlers/ :至少應該包含一個名為main.yml的檔案 ;其它的檔案需要在此檔案中通過include進行包含
  • vars/ :定義變量,至少應該包含一個名為main.yml的檔案;其它的檔案需要在此檔案中通過include進行包含
  • meta/ :定義目前角色的特殊設定及其依賴關系,至少應該包含一個名為main.yml的檔案,其它檔案需在此檔案中通過include進行包含
  • default/ :設定預設變量時使用此目錄中的main.ymI檔案

建立role的步驟

  1. 建立以roles命名的目錄
  2. 在roles目錄中分别建立以各角色名稱命名的目錄,如webservers等
  3. 在每個角色命名的目錄中分别建立files、handlers、 meta、 tasks、

    templates和vars目錄;用不到的目錄可以建立為空目錄,也可以不建立

  4. 在playbook檔案中,調用各角色

可以跨角色調用

例如:

---
- hosts: webservers
  remote_user: root
  roles:
    - role: nginx
    - role: roles/mysql/tasks/copyfile.yml
           

可以取标簽

例如:

---
- hosts: webservers
  remote_user: root
  roles:
    - { role: nginx, tags:['app','nginx'] }
    - { role: mysql, tags:['app','mysql'] }
           

ansible-playbook -t 指定标簽 role_nginx.yml

例子

//roles目錄解構
/root/ansible/
├── roles
│   ├── httpd
│   ├── memcache
│   ├── mysql
│   └── nginx
│       ├── files
│       │   └── vhosts.conf
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   ├── copyfile.yml
│       │   ├── group.yml
│       │   ├── main.yml
│       │   ├── start.yml
│       │   ├── templ.yml
│       │   ├── user.yml
│       │   └── yum.yml
│       ├── templates
│       │   └── nginx.conf.j2
│       └── vars
│           └── main.yml
└── roles_nginx.yml

//tasks目錄中檔案内容
[[email protected] ansible]# cat roles/nginx/tasks/copyfile.yml 
- name: copy file
  copy: src=vhosts.conf dest=/etc/nginx/conf.d/ owner=app
[[email protected] ansible]# cat roles/nginx/tasks/group.yml 
- name: create group
  group: name=app gid=888
[[email protected] ansible]# cat roles/nginx/tasks/user.yml 
- name: create user
  user: name=app system=yes uid=888 group=nginx shell=/sbin/nologin
[[email protected] ansible]# cat roles/nginx/tasks/main.yml 
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: copyfile.yml
- include: start.yml
[[email protected] ansible]# cat roles/nginx/tasks/start.yml 
- name: start nginx
  service: name=nginx state=started enabled=yes
  notify: restart nginx
[[email protected] ansible]# cat roles/nginx/tasks/templ.yml 
- name: copy conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[r[email protected] ansible]# cat roles/nginx/tasks/yum.yml 
- name: install packeges
  yum: name=nginx

//handlers目錄中檔案内容
[[email protected] ansible]# cat roles/nginx/handlers/main.yml 
- name: restart nginx
  service: name=nginx state=restarted

//vars目錄中檔案内容
[[email protected] ansible]# cat roles/nginx/vars/main.yml 
username: app
groupname: app

//files目錄中檔案内容
[[email protected] ansible]# cat roles/nginx/files/vhosts.conf 
[[email protected] ansible]# 

//templates目錄中檔案内容
[[email protected] ansible]# cat roles/nginx/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 {{ username  }}; //變量
worker_processes {{ ansible_processor_vcpus+2 }};  //變量
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
worker_rlimit_nofile 655350;

# 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 2048;

    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;
	server_name localhost;

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

        location / {
	root html;
	index index.html index.htm;       
	}

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

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

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        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;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

//調用
[[email protected] ansible]# cat roles_nginx.yml 
---
- hosts: webservers
  remote_user: root
  roles:
    - role: nginx

//運作結果
[[email protected] ansible]# ansible-playbook  roles_nginx.yml 

PLAY [webservers] ********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [10.0.0.137]

TASK [nginx : create group] **********************************************************************************************************
changed: [10.0.0.137]

TASK [nginx : create user] ***********************************************************************************************************
changed: [10.0.0.137]

TASK [nginx : install packeges] ******************************************************************************************************
ok: [10.0.0.137]

TASK [nginx : copy conf] *************************************************************************************************************
changed: [10.0.0.137]

TASK [nginx : copy file] *************************************************************************************************************
changed: [10.0.0.137]

TASK [nginx : start nginx] ***********************************************************************************************************
changed: [10.0.0.137]

RUNNING HANDLER [nginx : restart nginx] **********************************************************************************************
changed: [10.0.0.137]

PLAY RECAP ***************************************************************************************************************************
10.0.0.137                 : ok=8    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

//驗證結果
[[email protected] ansible]# ansible all -m shell -a 'ss -ntlp|grep 80'
10.0.0.137 | CHANGED | rc=0 >>
LISTEN     0      128          *:80                       *:*                   users:(("nginx",pid=35689,fd=6),("nginx",pid=35688,fd=6),("nginx",pid=35687,fd=6),("nginx",pid=35686,fd=6),("nginx",pid=35685,fd=6))
[[email protected] ansible]# ansible all -m shell -a 'ps -aux|grep app'
10.0.0.137 | CHANGED | rc=0 >>
root       1975  0.0  0.7 745824 14272 ?        Sl   5月22   0:00 /usr/bin/gnome-software --gapplication-service
root       2004  0.0  0.7 451704 14920 ?        Sl   5月22   0:00 abrt-applet
root       2034  0.0  0.7 1084900 14580 ?       SNl  5月22   0:00 /usr/libexec/tracker-miner-apps
app       35686  0.0  0.1 121188  3512 ?        S    04:49   0:00 nginx: worker process
app       35687  0.0  0.1 121188  3512 ?        S    04:49   0:00 nginx: worker process
app       35688  0.0  0.1 121188  3512 ?        S    04:49   0:00 nginx: worker process
app       35689  0.0  0.1 121188  3512 ?        S    04:49   0:00 nginx: worker process
root      35954  0.0  0.0 113116  1220 pts/2    S+   05:00   0:00 /bin/sh -c ps -aux|grep app
root      35956  0.0  0.0 112664   948 pts/2    S+   05:00   0:00 grep app
[[email protected] ansible]# ansible all -m shell -a 'ls -l  /etc/nginx/conf.d'
10.0.0.137 | CHANGED | rc=0 >>
總用量 0
-rw-r--r-- 1 app root 0 5月  23 04:49 vhosts.conf