一、Ansible 基礎
1.Ansible基礎概述
1.1 什么是Ansible
Ansible是一個IT自動化的配置管理工具,自動化主要體現在Ansible集成了豐富模塊,豐富的功能組件,可以
通過一個命令行完成一系列的操作。進而能減少我們重復性的工作和維護成本,以提高工作的效率。
1.2 Ansible可以完成哪些功能呢
1)批量執行遠程命令,可以對N多台主機同時進行命令的執行
2)批量配置軟件服務,可以進行自動化的方式配置和管理服務。
3)實現軟件開發功能,jumpserver底層使用ansble來實現的自動化管理0
4)編排高級的IT任務,Ansible的playbook是一門編程語言,可以用來描繪一套IT架構。
1.3 Ansible的特點
1.容易學習,無代理模式,不像saltstack既要學服務端又要學習客戶端,還要學習服務端與客戶端之間的通訊協議
2.操作靈活,體現在Ansible有較多的模塊,提供了豐富的功能,playbook則提供了類似於編程語言的復雜功能
3.簡單易用,體現在Ansible —個命令可以完成很多事情
4.安全可靠,因為Ansible使用了SSH協議進行通汛,既穩定又安全
5.可移植性高,可以將寫好的playbook拷貝至任意機器進行執行
4.Ansible架構中的控制節點、被控制節點、inventroy, ad-hoc、playbook、連接協議是什么?
2.Ansible的安全配置
2.1.Ansible安裝
外網地址 | 內網地址 | 角色 |
---|---|---|
10.0.0.61 | 172.16.1.61 | Ansible控制端 |
10.0.0.7 | 172.16.1.7 | Ansible被控端 |
10.0.0.8 | 172.16.1.8 | Ansible被控端 |
1.先安裝epel源(提供最新的ansible)
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
2.安裝Ansible
yum install ansible -y
查看ansible的版本
[root@m01 ~]# ansible --version
ansible 2.7.7
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, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
3.Ansible的配置文件,配置文件可以隨意放,但有查找順序
$ANSIBLE_CONFIG
ansible.cfg #當前目錄下面查找
.ansible.cfg #當前用戶的家目錄下查找
/etc/ansible/ansible.cfg
[root@m01 ~]# cat /etc/ansible/ansible.cfg
#inventory = /etc/ansible/hosts #主機列表配置文件
#library = /usr/share/my_modules/ #庫文件存放目錄
#remote_tmp = ~/.ansible/tmp #臨時py文件存放在遠程主機目錄
#local_tmp = ~/.ansible/tmp #本機的臨時執行目錄
#forks = 5 #默認並發數
#sudo_user = root #默認sudo用戶
#ask_sudo_pass = True #每次執行是否詢問sudo的ssh密碼
#ask_pass = True #每次執行是否詢問ssh密碼
#remote_port = 22 #遠程主機端口
host_key_checking = False #跳過檢查主機指紋
log_path = /var/log/ansible.log #ansible日志
[privilege_escalation] #如果是普通用戶則需要配置提權
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False
二、Ineventory主機清單
1.場景一、基於密碼連接
[root@oldboy.com ~]# cat /etc/ansible/hosts
#方式一、主機+端口+密碼
[webservers]
172.16.1.7 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'
172.16.1.8 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'
#方式二、主機+端口+密碼
[webservers]
web[1:2].oldboy.com ansible_ssh_pass='123456'
#方式三、主機+端口+密碼
[webservers]
web[1:2].oldboy.com
[webservers:vars]
ansible_ssh_pass='123456'
2.場景二、基於密鑰連接,需要先創建公鑰和私鑰,並下發公鑰至被控端
[root@m01 ~]# ssh-keygen
[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.7
[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.1.8
-----------------------------------------------------------
[root@m01 ~]# cat hosts
#方式一、主機+端口+密鑰
[webservers]
172.16.1.7
172.16.1.8
[root@m01 ~]# ansible webservers -m ping -i ./hosts
172.16.1.8 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.1.7 | SUCCESS => {
"changed": false,
"ping": "pong"
}
-----------------------------------------------------------
[root@m01 ~]# cat hosts
#方式二、別名+主機+端口+密鑰
[webservers]
web01 ansible_ssh_host=172.16.1.7 ansible_ssh_port=22
web02 ansible_ssh_host=172.16.1.8
[root@m01 ~]# ansible webservers -m ping -i ./hosts
web02 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web01 | SUCCESS => {
"changed": false,
"ping": "pong"
}
3.場景三、主機組使用方式
#1.定義兩個組
[lbservers]
172.16.1.5
172.16.1.6
[webservers]
172.16.1.7
172.16.1.8
#2.servers組包括兩個子組[lbservers,webserver]
[servers:children]
[lbservers]
[webserver]
#列出當前某個組有多少台主機
[root@m01 ~]# ansible lbservers -m ping -i ./hosts --list-hosts
hosts (1):
web01
[root@m01 ~]# ansible webservers -m ping -i ./hosts --list-hosts
hosts (1):
web02
[root@m01 ~]# ansible servers -m ping -i ./hosts --list-hosts
hosts (2):
web01
web02
[root@m01 ~]# ansible all -m ping -i ./hosts --list-hosts
hosts (3):
web03
web02
web01
注意:
如果控制端和被控制端第一次通訊,需要先添加指紋信息,那如果機器特別多少的情況下怎么辦?
僅需開啟ansible中的 host_key_checking = False
三、Ad-Hoc
1.常用模塊
command 執行shell命令(不支持管道等特殊字符)
shell 執行shell命令
scripts 執行shell腳本
yum_repository 配置yum倉庫
get_url 聯網下載
yum 安裝
copy 配置
service、systemd 啟動
user、group 創建用戶與組
file 授權
crond 定時任務
mount 掛載
firewalld firewall
selinux selinux
2..使用過程中需要先了解ansible-doc幫助手冊
[root@m01 ~]# ansible-doc -l # 查看所有模塊說明
[root@m01 ~]# ansible-doc copy # 表示指定模塊方法
[root@m01 ~]# ansible-doc -s copy # 表示指定模塊參數
3..command默認執行bash命令模塊,模塊不支持重定向或管道
[root@m01 ~]# ansible oldboy -a "hostname"
4..shell模塊,如果需要一些管道操作,則使用shell
[root@m01 ~]# ansible oldboy -m shell -a "ifconfig|grep eth0" -f 50
5..script腳本模塊
[root@m01 ~]# cat yum.sh
#!/usr/bin/bash
yum install -y iftop
#在本地運行模塊,等同於在遠程執行,不需要將腳本文件進行推送目標主機執行
[root@m01 ~]# ansible oldboy -m script -a "/server/scripts/yum.sh"
6..yum安裝軟件模塊
[root@m01 ~]# ansible oldboy -m yum -a "name=httpd state=installed"
name
httpd #指定要安裝的軟件包名稱
file:// #指定從本地哪個目錄安裝rpm
http:// #指定從哪個網站安裝rpm包
state #指定使用yum的方法
present #安裝軟件包
absent #移除軟件包
latest #安裝最新軟件包
list=ansible #列出當前倉庫可用的軟件包
disablerepo="epel,ol7_latest" #安裝軟件時,不從哪些倉庫獲取
download_only=true #僅下載軟件包,不安裝
7.copy文件拷貝模塊
#1.拷貝文件文件至被控節點
[root@m01 ~]# ansible oldboy -m copy -a "src=/etc/hosts dest=/tmp/test.txt"
#2.對遠端已有文件進行備份,按照時間信息備份
[root@m01 ~]# ansible oldboy -m copy -a "src=/etc/hosts dest=/tmp/test.txt backup=yes"
#3.向被控端主機寫入數據,並且會覆蓋遠端文件內原有數據信息
[root@m01 ~]# ansible oldboy -m copy -a "content='bgx' dest=/tmp/oldboy"
src #推送數據的源文件信息
dest #推送數據的目標路徑
backup #對推送傳輸過去的文件,進行備份
content #直接批量在被管理端文件中添加內容
group #將本地文件推送到遠端,指定文件屬組信息
owner #將本地文件推送到遠端,指定文件屬主信息
mode #將本地文件推送到遠端,指定文件權限信息
8..file文件創建模塊
1.直接修改被控端的權限
[root@m01 ~]# ansible web01 -m file -a "path=/opt mode=0400" -i ./hosts
2.在被控端創建目錄
[root@m01 ~]# ansible oldboy -m file -a "path=/tmp/oldboy state=directory"
3.在被控端創建文件
[root@m01 ~]# ansible oldboy -m file -a "path=/tmp/tt state=touch mode=555 owner=root group=root"
4.遞歸授權目錄權限
[root@m01 ~]# ansible oldboy -m file -a "path=/data owner=bgx group=bgx recurse=yes"
path #指定遠程主機目錄或文件
recurse #遞歸授權
state #狀態
directory #在遠端創建目錄
touch #在遠端創建文件
link #創建鏈接文件
absent #表示刪除文件或目錄
mode #設置文件或目錄權限
owner #設置文件或目錄屬主
group #設置文件或目錄屬組
9..get_url文件下載模塊
1.通過get_url下載文件或者軟件
[root@m01 ~]# ansible webservers -m get_url -a "url=http,https dest=/opt mode=0777" -i ./hosts
2.下載一個文件前先進行md5校驗,通過則下載,不通過則失敗
ansible webservers -m get_url -a "url=http,https dest=/opt mode=0777 checksum=md5:76eb3af80ffd" -i ./hosts
url #文件在網絡上的具體位置
dest #下載到被控端的哪個目錄下
checksum #校驗(md5 sha256)
10.ansible管理服務的啟動與停止,使用service、systemd
#1.啟動crond服務,並加入開機自啟
[root@m01 ~]# ansible webservers -m service -a "name=crond state=started enabled=yes"
#2.停止crond服務,並刪除開機自啟
[root@m01 ~]# ansible webservers -m service -a "name=crond state=stopped enabled=no"
#3.重啟crond服務
[root@m01 ~]# ansible webservers -m service -a "name=crond state=restarted"
#4.重載crond服務
[root@m01 ~]# ansible webservers -m service -a "name=crond state=reloaded"
name # 定義要啟動服務的名稱
state # 指定服務狀態
started #啟動服務
stopped #停止服務
restarted #重啟服務
reloaded #重載服務
enabled #開機自啟
11.group組模塊
[root@m01 ~]# ansible webservers -m group -a "name=oldgirl gid=888"
name #指定創建的組名
gid #指定組的gid
state
absent #移除遠端主機的組
present #創建遠端主機的組(默認)
12.user模塊
1.創建用戶指定uid和gid,不創建家目錄也不允許登陸
[root@m01 ~]# ansible oldboy -m user -a "name=oldgirl uid=888 group=888 shell=/sbin/nologin create_home=no"
2.刪除用戶
[root@m01 ~]# ansible webservers -m user -a "name=tmd state=absent" -i ./hosts
3.給新創建的用戶生成ssh密鑰對
[root@m01 ~]# ansible webservers -m user -a "name=oo uid=6677 group=adm generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa" -i ./hosts
4.將明文密碼進行hash加密,然后進行用戶創建
[root@m01 ~]# ansible localhost -m debug -a "msg={{ '123456' | password_hash('sha512', 'salt') }}"
localhost | SUCCESS => {
"msg": "$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w.igcOo1R7vBYR65JquIQ/7siC7VRpmteKvZmfSkNc69."
}
[root@m01 ~]# ansible webservers -m user -a 'name=xlw password=$6$salt$MktMKPZJ6t59GfxcJU20DwcwQzfMvOlHFVZiOVD71w.igcOo1R7vBYR65JquIQ/7siC7VRpmteKvZmfSkNc69. create_home=yes shell=/bin/bash' -i ./hosts
uid #指定用戶的uid
group #指定用戶組名稱
groups #指定附加組名稱
password #給用戶添加密碼(記得單引號)
shell #指定用戶登錄shell
create_home #是否創建家目錄
13.crond定時任務模塊
# 正常使用crond服務(默認沒寫的時間都算*表示)
[root@m01 ~]# crontab -l
* * * * * /bin/sh /server/scripts/yum.sh
# 使用ansible添加一條定時任務
[root@m01 ~]# ansible webservers -m cron -a "minute=* hour=* day=* month=* weekday=* job='/bin/sh test.sh'"
[root@m01 ~]# ansible webservers -m cron -a "job='/bin/sh /server/scripts/test.sh'"
# 設置定時任務注釋信息,防止重復,name設定
[root@m01 ~]# ansible webservers -m cron -a "name='cron01' job='/bin/sh /server/scripts/test.sh'"
# 刪除相應定時任務
[root@m01 ~]# ansible webservers -m cron -a "name='ansible cron02' minute=0 hour=0 job='/bin/sh test.sh' state=absent"
# 注釋相應定時任務,使定時任務失效
[root@m01 scripts]# ansible oldboy -m cron -a "name='ansible cron01' minute=0 hour=0 job='/bin/sh test.sh' disabled=yes"
14..mount掛載模塊7 nfs 8客戶端掛載
[root@m01 ~]# ansible web01 -m yum -a 'name=nfs-utils state=present' -i ./hosts
[root@m01 ~]# ansible web01 -m file -a 'path=/data state=directory' -i ./hosts
[root@m01 ~]# ansible web01 -m copy -a 'content="/data 172.16.1.0/24(rw,sync,no_all_squash)" dest=/etc/exports' -i ./hosts
[root@m01 ~]# ansible web01 -m systemd -a "name=nfs state=started enabled=yes" -i ./hosts
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=present"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=mounted"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=unmounted"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=absent"
present # 開機掛載,僅將掛載配置寫入/etc/fstab
mounted # 掛載設備,並將配置寫入/etc/fstab
unmounted # 卸載設備,不會清除/etc/fstab寫入的配置
absent # 卸載設備,會清理/etc/fstab寫入的配置
15.防火牆管理模塊
Selinux模塊
[root@m01 ~]# ansible webservers -m selinux -a "state=disabled" -i ./hosts
firewalld模塊
[root@m01 ~]# ansible webservers -m systemd -a "name=firewalld state=started" -i ./hosts
[root@m01 ~]# ansible webservers -m firewalld -a "service=http immediate=yes permanent=yes state=enabled" -i ./hosts
[root@m01 ~]# ansible webservers -m firewalld -a "port=8080-8090/tcp immediate=yes permanent=yes state=enabled" -i ./hosts
service #指定開放或關閉的服務名稱
port #指定開放或關閉的端口
masquerade #開啟地址偽裝
immediate #臨時生效
permanent #是否添加永久生效
state #開啟或是關閉
zone #指定配置某個區域
rich_rule #配置富規則
source #指定來源IP
四、Playbook
1.Ansible Playbook基本概述
1.什么是playbook,playbook翻譯過來就是“劇本' 那么playbook組成如下
playbook:定義一個文本文件,以yml為后綴結尾(翻譯:我有一個劇本)
play:定義的是主機的角色(翻譯:找哪個大腕明星)
task:定義的是具體執行的任務(翻譯:大腕每一集拍什么)
總結:playbook是由一個或多個play組成,一個play可以包含多個task任務。
可以理解為:使用不同的模塊來共同完成一件事情。
2.Ansible playbook與AD-Hoc的關系
- playbook是對AD-Hoc的一種編排方式。
- playbook可以持久運行,而Ad-Hoc只能臨時運行。
- playbook適合復雜的任務,而Ad-Hoc適合做快速簡單的任務。
- playbook能控制任務執行的先后順序,以及互相依賴的關系。
3.Ansible Playbook書寫格式
playbook是由yml語法書寫,結構清晰,可讀性強,所以必須掌握yml基礎語法
語法 | 描述 |
---|---|
縮進 | YAML使用固定的縮進風格表示層級結構,每個縮進由兩個空格組成,不能使用Tab |
冒號 | 以冒號結尾的除外,其他所有冒號后面所有必須有空格。 |
短橫線 | 表示列表項,使用一個短橫杠加一個空格。多個項使用同樣的縮進級別作為同一列表。 |
3.1.下面我們一起來編寫一個playbook文件,playbook起步
host:對哪些主機進行操作
remote_user:我要使用什么用戶執行
tasks: 具體執行什么任務
[root@m01 ~]# cat f1.yml
#play
- hosts: webservers
tasks:
- name: Installed Httpd Server
yum:
name: httpd
state: present
- name: Start Httpd Server
systemd:
name: httpd
state: started
enabled: yes
2.檢查語法,只檢查是否是yaml語法格式。並不做邏輯校驗。
[root@m01 project1]# ansible-playbook --syntax-check p1.yml
playbook: p1.yml
3.模擬執行(不是真的執行)
[root@m01 project1]# ansible-playbook -C p1.yml
4.真實的描述狀態(被控端的狀態必須與控制端描述的狀態一致)
[root@m01 project1]# ansible-playbook p1.yml
3.2.多paly語法示例
ansible安裝並配置httpd服務,根據不同的主機配置不同的網站。(多個play的使用方式,但不是生產推薦,了解項,生產推薦使用循環方式)
[root@m01 project1]# cat p1.yml
---
#play
- hosts: webservers
tasks:
- name: Installed Httpd Server
yum: name=httpd state=present
- name: Start Httpd Server
systemd: name=httpd state=started enabled=yes
- name: Start Firewalld Server
systemd: name=firewalld state=started enabled=yes
- name: Configure Firewalld Server
firewalld: service=http immediate=yes permanent=yes state=enabled
- hosts: web01
tasks:
- name: Configure web01 Website
copy: content='This is Web01' dest=/var/www/html/index.html
- hosts: web02
tasks:
- name: Cofnigure webi-2 weisite
copy: content='This is Web02' dest=/var/www/html/index.html
3.3.安裝nfs服務
1.安裝
2.配置
用戶
/data
3.啟動
#記得重啟你的nfs
[root@m01 project1]# cat nfs.yml
- hosts: web01
tasks:
- name: Install NFS-utils Server
yum: name=nfs-utils state=present
- name: Configure Nfs-utils Server
copy: src=./exports.j2 dest=/etc/exports owner=root group=root mode=0644
- name: Create NFS Group
group: name=www gid=666
- name: Create NFS User
user: name=www uid=666 group=www create_home=no shell=/sbin/nologin
- name: Create Data Directory
file: path=/data state=directory owner=www group=www mode=0755 recurse=yes
- name: Start NFS Server
systemd: name=nfs state=started enabled=yes
- hosts: web02
tasks:
- name: Mount NFS Server
mount: path=/opt src=172.16.1.7:/data fstype=nfs opts=defaults state=mounted
3.4.使用AnsiblePlaybook方式構建LAMP架構,具體操作步驟如下:
1.使用yum安裝 httpd、php、php-mysql、mariadb、firewalld等
2.啟動httpd、firewalld、mariadb等服務
3.添加防火牆規則,放行http的流量,並永久生效
4.使用get_url下載 http://fj.xuliangwei.com/public/index.php 文件
[root@m01 project1]# cat lamp.yml
#- hosts: webservers
- hosts: otherservers
tasks:
- name: Installed Web Packages
yum: name=httpd,mariadb-server,php,php-mysql,php-pdo state=present
- name: Start Web Serivce
service: name=httpd state=started
- name: Start Mariadb Service
service: name=mariadb state=started
- name: Get Wordpress
unarchive: src=./wordpress-5.0.3-zh_CN.tar.gz dest=/var/www/html/ copy=yes mode=0755
# - name: Copy Index.php
# copy: src=./index.php.j2 dest=/var/www/html/index.php
# - name: Get Url index.php
# get_url: url="http://fj.xuliangwei.com/public/index.php" dest=/var/www/html/index.php
4.Ansible Playbook變量解析
1 .變量概述
變量提供了便捷的方式來管理ansible項目中的動態值。比女Ozabbix-3.4.15,可能后期會反復的使用到這個版本的值,那么如果將此值設置掃變量,后續使用和修改都將變得非常方便。這樣可以簡化項目的創建和維護
定義變量分為如下三種方式
1)通過命令行進行變量定義
2)在play文件中進行定義變量
3)通過inventory在主機組或單個主機中設置變量
如果定義的變量出現重復,且造成沖突,優先級如下:
1.命令行定義的變量-高於->play文件定義的變量-高於->inventory文件定義的變量。
2.變量的定義
2.1.playbook變量可以通過多種方式進行定義,最簡單的方式就是在playbook的開頭通過vars進行定義
#安裝兩個軟件包使用變量方式
[root@m01 project1]# cat p2.yml
- hosts: webservers
vars:
- web_package: httpd
- ftp_package: vsftpd
tasks:
- name: Installed Packages
yum:
name:
- "{{ web_package }}"
- "{{ ftp_package }}"
state: present
2.2.也可以在playbook中使用vars_files指定文件作為變量文件,好處就是其他的playbook也可以調
[root@m01 project1]# cat vars.yml
web_package: httpd
ftp_package: vsftpd
[root@m01 project1]# cat p2.yml
- hosts: webservers
vars_files: ./vars.yml
tasks:
- name: Installed Packages
yum:
name:
- "{{ web_package }}"
- "{{ ftp_package }}"
state: present
2.3.在inventory中定義變量,主機變量優先級高於主機組變量(不推薦,容易將環境弄的特別亂)
[root@m01 project1]# vim /etc/ansible/hosts
[webservers]
web01 ansible_ssh_host=172.16.1.7
web02 ansible_ssh_host=172.16.1.8
[webservers:vars]
filename=group_vars
[root@m01 project1]# cat p3.yml
- hosts: webservers
tasks:
- name: Create File
file: path=/tmp/{{ filename }} state=touch
2.4.更好的方式是在ansible的項目目錄中創建額外的兩個變量目錄,分別是host_vars和group_vars
group_vars目錄下必須存放和inventory清單文件中定義的組名一致,如下
[root@m01 project1]# cat /etc/ansible/hosts
[webservers]
web01 ansible_ssh_host=172.16.1.7
web02 ansible_ssh_host=172.16.1.8
[root@m01 project1]# cat group_vars/webservers
web_package: httpd
ftp_package: vsftpd
注意:系統提供了特殊的組,all,也就說在group_vars目錄下創建一個all文件,定義變量對所有的主機都生效
[root@m01 project1]# cat host_vars/web01
web_package: zlib-static
ftp_package: zmap
[root@m01 project1]# cat group_vars/webservers
web_package: httpd
ftp_package: vsftpd
[root@m01 project1]# cat p4.yml
- hosts: webservers
#- hosts: otherservers
tasks:
- name: Installed Packages
yum:
name:
- "{{ web_package }}"
- "{{ ftp_package }}"
state: present
[root@m01 project1]# ansible-playbook p4.yml
PLAY [webservers] ********************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************
ok: [web02]
ok: [web01]
TASK [Installed Packages] ************************************************************************************************
ok: [web02]
changed: [web01]
PLAY RECAP ***************************************************************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0
web02 : ok=2 changed=0 unreachable=0 failed=0
2.5.通過命令行覆蓋變量,inventory的變量會被playbook文件中覆蓋,這兩種方式的變量都會被命
令行直接指定變量所覆蓋。使用--extra-vars或-e設定變量。
[root@m01 project1]# ansible-playbook p4.yml -e "web_package=zarafa-devel" -e "ftp_package=zarafa-utils"
2.6.變量優先級測試
命令行變量--->play中的vars_files--->play中的vars變量-->host_vars中定義的變量--->group_vars/組--->group_vars/all
[root@m01 project1]# cat p5.yml
- hosts: webservers
# vars:
# filename: play_vars
# vars_files:
# - ./vars.yml
tasks:
- name: Create
shell: mkdir -pv /tmp/{{ filename }}
register: mk_test
- name: debug
debug: msg={{ mk_test }}
2.7.變量注冊register
- hosts: webservers
tasks:
- name: Get Network Port Status
shell: netstat -lntp
register: net_port
- name: OutPut Network Port Status
debug:
msg: "{{ net_port.stdout_lines }}"
2.8.變量也支持層級定義,使用"."可能會有問題,建議使用"[]"代替。
[root@m01 project1]# cat vars1.yml
rainbow:
web:
web_package: httpd
db_package: mariadb
code:
web:
filename: code_web_filename
[root@m01 project1]# cat p8.yml
- hosts: webservers
vars_files: ./vars1.yml
tasks:
- name: Install Package
yum: name= "{{ rainbow['web']['web_package'] }}"
- name: create filename
file:
path: /tmp/{{ code.web.filename }}
state: touch
2.9.facts變量 (setup模塊)
Ansible facts是在被管理主機上通過ansible自動采集發現的變量。facts包含每台特定的主機信息。比如:被控端主機的主機名、IP地址、系統版本、CPU數量、內存狀態、磁盤狀態等等。
facts使用場景
1.通過facts檢查CPU,來生成對應的Nginx配置文件
2.通過facts檢查主機名信息,來生成不同的Zabbix配置文件
3.通過fact檢索的內存情況來自定義mysql的配置文件
1.facts基本用法,比如獲取被控端的主機名與IP地址
[root@m01 〜]# cat facts.yml
-hosts: web
tasks:
-name: Output variables ansible facts
debug:
msg: >
this default IPv4 address "{{ ansible_fqdn}}" is "{{ ansible_default_ipv4.address}}"
2.使用facts模擬批量修改zabbix配置文件,template和copy用法差不多,但template支持解析變量
[root@m01 project1]# cat p10.yml
- hosts: webservers
#gather_facts: no 關閉facts采集
vars:
- zabbix_server: 172.16.1.71
tasks:
- name: Copy Zabbix Agent Configure
template: src=./zabbix_agentd.conf dest=/tmp/zabbix_agent.conf
- facts開啟后會影響Ansible主機的性能,如果沒有采集被控端主機需求可選擇關閉
[root@m01 project1]# cat p10.yml
- hosts: webservers
#gather_facts: no 關閉facts采集
vars:
- zabbix_server: 172.16.1.71
tasks:
- name: Copy Zabbix Agent Configure
template: src=./zabbix_agentd.conf dest=/tmp/zabbix_agent.conf
4.使用setup模塊獲取采集的值
ansible web01 -m setup -i ./hosts
5.playbook安裝一個memcached,利用了facts變量
[root@m01 project1]# cat memcached.j2
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="{{ ansible_memtotal_mb //2 }}"
OPTIONS=""
[root@m01 project1]# cat p11.yml
- hosts: webservers
tasks:
- name: Installed Memcached
yum: name=memcached state=present
- name: Configure Memcached
template: src=./memcached.j2 dest=/etc/sysconfig/memcached
- name: Start Memcached
service: name=memcached state=started enabled=yes
2.10.批量修改主機名
解法一、web_隨機數的解法
[root@m01 ~]# cat te.yaml
- hosts: all
tasks:
- name: 打印facts變量的內容
debug: msg={{ ansible_default_ipv4.address }}
- name: 使用hostname模塊將主機名修改為web_ip
hostname: name=web_{{ ansible_default_ipv4.address }}
解法二、web_隨機數的解法
[root@m01 ~]# cat te_2.yaml
- hosts: all
tasks:
- name: 定義一個隨機數,設定為變量,然后后續調用
shell: echo $((RANDOM%200))
register: System_SJ
- name: 使用debug輸出變量結果,這樣好知道需要提取的關鍵值
debug: msg={{ System_SJ }}
- name: 使用hostname模塊將主機名修改為web_隨機數
hostname: name=web_{{ System_SJ.stdout }}
解法三、隨機數+時間戳的解法
[root@m01 project1]# cat vars_14.yml
- hosts: oldboy
tasks:
- name: SHell
shell: echo $RANDOM|md5sum |cut -c 5-10
register: get_random
- name: Get Facts
debug:
msg: "{{ ansible_date_time.epoch }}"
- name: Hostname
hostname: name={{ get_random.stdout }}_{{ ansible_date_time.epoch }}
5.Playbook條件語句
判斷在Ansible任務中_吏用頻率非常高。比如yum模塊可以檢測軟件包是否已被安裝,而在這個過程中我們不用做太多的人工干預。
但是也有部分任務需要進行判斷,比如:web服務器角色都需要安裝nginx倉庫,但其他的服務器角色並不需要,此時就會用到when判斷。
比如:Centos與Ubuntu系統都需要安裝httpd服務,那么就需要使用when判斷主機系統,然后調用不同的模塊執行。
實踐案例一、根據不同操作系統,安裝相同的軟件包
Centos:httpd
Ubuntu:httpd2
[root@m01 project2]# cat when.yml
- hosts: webservers
tasks:
- name: Install httpd Server
yum: name=httpd state=present
when: ansible_distribution == "CentOS"
- name: Install httpd Server
apt: name=httpd2 state=present
when: ansible_distribution == "Ubuntu"
實踐案例二、所有為web主機名的添加nginx倉庫,其余的都跳過添加
1.如何添加yum倉庫
2.如何判斷,判斷什么內容
---
- hosts: all
tasks:
- name: Add Nginx Repos
yum_repository:
name: nginx_tet
description: Nginx YUM repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
when: (ansible_hostname is match ("web*")) or (ansible_hostname is match ("lb*"))
1.通過register將命令執行結果保存至變量,然后通過when語句進行判斷
- hosts: webservers
tasks:
- name: Check Httpd Server
command: systemctl is-active httpd
ignore_errors: yes
register: check_httpd
#- name: debug outprint #僅僅只是輸出結果
# debug: var=check_httpd
- name: Httpd Restart
service: name=httpd state=restarted
when: check_httpd.rc == 0
6.Playbook循環語句
有時候我們寫playbook的時候發現了很多task都要重復引用某個模塊,比如一次啟動10個服務,或者一次拷貝10個文件,如果按照傳統的寫法最少要寫10次,這樣會顯得playbook很臃腫。如果使用循環的方式來編寫playbook,這樣可以減少重復使用某個模塊。
實踐案例一、使用循環啟動多個服務
[root@m01 project2]# cat with.yml
- hosts: webservers
tasks:
- name: Start httpd mariadb
systemd: name={{ item }} state=started
with_items:
- httpd
- mariadb
案例二、使用定義變量方式循環安裝軟件包。
- hosts: webservers
tasks:
- name: ensure a list of packages installed
yum: name= "{{ packages }}" state=present
vars:
packages:
- httpd
- httpd-tools
#棄用的方式
- hosts: webservers
tasks:
- name: ensure a list of packages installed
yum: name= "{{ item }}" state=present
with_items:
- httpd
- httpd-tools
實踐案例三、使用字典循環方式創建用戶和批量拷貝文件
1.批量創建用戶,使用字典的key value的方式
[root@manager ~]# cat loop-user.yml
- hosts: webservers
tasks:
- name: Add Users
user: name={{ item.name }} groups={{ item.groups }} state=present
with_items:
- { name: 'testuser1', groups: 'bin' }
- { name: 'testuser2', groups: 'root' }
2.使用字典循環批量拷貝文件
[root@m01 project2]# cat with4.yml
- hosts: webservers
tasks:
- name: Copy Rsync configure and Rsync passwd
copy: src={{ item.src }} dest={{ item.dest }} mode={{ item.mode }}
with_items:
- { src: "./rsyncd.conf", dest: "/etc/rsyncd.conf", mode: "0644" }
- { src: "./rsync.passwd", dest: "/tmp/rsync.passwd", mode: "0600" }
7.handlers觸發器
1.當配置發生改變,重啟服務
[root@m01 project2]# cat han.yml
- hosts: webservers
vars:
- http_port: 8083
tasks:
- name: Install Http Server
yum: name=httpd state=present
- name: configure httpd server
template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- Restart Httpd Server
- Restart PHP Server
- name: start httpd server
service: name=httpd state=started enabled=yes
handlers:
- name: Restart Httpd Server
systemd: name=httpd state=restarted
- name: Restart PHP Server
systemd: name=php-fpm state=restarted
2.handlers注意事項
- 1.無論多少個task通知了相同的handlers,handlers僅會在所有tasks結束后運行一次。
- 2.只有task發生改變了才會通知handlers,沒有改變則不會觸發handlers
- 3.不能使用handlers替代tasks
8.Playbook tag標記(用於調試的場景下)
默認情況下,Ansible在執行一個playbook時,會執行playbook中定義的所有任務。Ansible的標簽(Tags)功能可以給單獨任務甚至整個playbook打上標簽,然后利用這些標簽來指定要運行playbook中的個別任務,或不執行指定的任務。
1.打標簽的方式有幾種,比如:
對一個task打一個標簽、對一個task打多個標簽、對多個task打一個標簽
2、對task打完標簽應該如何使用
-t:執行指定的tag標簽任務
-skip-tags:執行-skip-tags之外的標簽任務
[root@m01 project2]# cat tag.yml
- hosts: webservers
vars:
- http_port: 8083
tasks:
- name: Install Http Server
yum: name=httpd state=present
tags:
- install_httpd
- httpd_server
- name: configure httpd server
template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: Restart Httpd Server
tags:
- confiure_httpd
- httpd_server
- name: start httpd server
service: name=httpd state=started enabled=yes
tags: service_httpd
handlers:
- name: Restart Httpd Server
systemd: name=httpd state=restarted
[root@m01 project2]# ansible-playbook tag.yml --list-tags #查看所有標簽
[root@m01 project2]# ansible-playbook tag.yml -t httpd_server #運行指定的標簽
[root@m01 project2]# ansible-playbook tag.yml -t install_httpd,confiure_httpd #運行指定的多個標簽
[root@m01 project2]# ansible-playbook tag.yml --skip-tags httpd_server #跳過指定的標簽
9.Playbook 文件復用(include)
include用來動態的包含tasks任務列表include_tasks新版/include老版
include包含
include(import_playbook)此為包含完整的文件
include_tasks 此為包含任務
#主入口文件
[root@m01 project2]# cat task.yml
- hosts: webservers
vars:
- http_port: 801
tasks:
- include_tasks: task_install.yml
- include_tasks: task_configure.yml
- include_tasks: task_start.yml
handlers:
- name: Restart Httpd Server
systemd: name=httpd state=restarted
#任務文件
[root@m01 project2]# cat task_install.yml
- name: Install Http Server
yum: name=httpd state=present
[root@m01 project2]# cat task_configure.yml
- name: configure httpd server
template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: Restart Httpd Server
[root@m01 project2]# cat task_start.yml
- name: start httpd server
service: name=httpd state=started enabled=yes
10.Playbook忽略錯誤(ignore_errors)
默認Playbook會偷asks執行的返囪狀態,如遇到鍺誤則會立即終止playbook的后續的tasks執行。然而有些時候palybook即使執行鍺誤了也要讓其繼續執行
加入參數:ignore_errors: yes忽略錯誤
編寫playbook,當有task執行失敗則會立即終止后續task運行
[root@manager ~]# cat f9.yml
---
- hosts: webservers
tasks:
- name: Ignore False
command: /bin/false
ignore_errors: yes
- name: touch new file
file: path=/tmp/bgx_ignore state=touch
11.Playbook異常處理
通常情況下,當task失敗后,play將會終止,任何在前面已經被tasks notify的handlers都不會被執行。如果你在play中設置了force_handlers: yes參數,被通知的handlers就會被強制執行。(有些特殊場景可能會使用到)
force_handlers: yes 強制調用handlers (寫到play里)
changed_when: false 被管理主機沒有發生變化,可以使用參數將change狀態改為ok
changed_when: httpd_check.stdout.find('OK') #查看變量中的某個字符串
[root@m01 project2]# cat changed_when.yml
- hosts: webservers
vars:
- http_port: 8083
tasks:
- name: configure httpd server
template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: Restart Httpd Server
- name: Check HTTPD
shell: /usr/sbin/httpd -t
register: httpd_check
changed_when:
- httpd_check.stdout.find('OK')
- false
- name: start httpd server
service: name=httpd state=started enabled=yes
handlers:
- name: Restart Httpd Server
systemd: name=httpd state=restarted
failed_when
命令不依賴返回狀態碼來判定是否執行失敗,而是要查看命令返回內容來決定,比如返回內容中包括 failed 字符串,則判定為失敗。示例如下:
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
五、Ansible加密模塊
1.Ansible Vault 概述
Ansible Vault作為ansible的一項新功能可將例如passwords,keys等感數據文件逬行加密,而非存放在明文的playbooks或roles中。
2.Ansible Vault實踐
ansible加密使用的是ansible-vault命令進行加密,語法示例
[root@m01 project2]# ansible-vault --help
Usage: ansible-vault [create|decrypt(解密)|edit|encrypt(加密)|encrypt_string|rekey(修改密碼)|view(查看)] [options] [vaultfile.yml]
加密一個文件
ansible-vault encrypt include.yml
查看一個文件
[root@m01 project2]# ansible-vault view include.yml
Vault password:
- import_playbook: han.yml
- import_playbook: when2.yml
修改加密的文件內容
[root@m01 project2]# ansible-vault edit include.yml
rekey 修改密碼
[root@m01 project2]# ansible-vault rekey include.yml
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful
執行加密的playbook
echo "1" >pass
chmod 600 pass
ansible-playbook include.yml --vault-password-file=pass
六、jinja模板
1.Ansible Jinja2模板概述
1.1.什么是Jinja2
Jinja2是Python的全功能模板引擎
1.2.Jinja2橫板與Anslble有什么關系
Ansible通常會使用Jinja2模板來修改被管理主機的配置文件。例如給10台遠程主機都裝上httpd服務,但是要求每個服務器的端口不一樣,如何解決?
1.3.Anslble如何使用Jinja2模板
使用ansible的jinja2模板,也就是template模板。該模塊和copy模塊一樣,都是將文件復制到遠端主機上去,但是區別在於template模板可以獲取要復制的文件中變量的值,而copy則是原封不動的把文件內容復制過去,比如:針對不同的主機定義不同的變量, template會在將配置文件分發出去前讀取變量到iinja2模板.然后分發到不同的被管理主機上。
Ansible 使用Jinja2模板注意事項:
Ansible允許Jinja2模板中使用條件判斷和循環.但是不允許在playbook中使用。
注悤:不是每個管理員都需要這個特性,但屋有些時候jinja2模板能大大提高效率。
2.Ansible Jinja2的基本使用
2.1.jinja模板基本語法
{{EXPR}}輸出變量的值(會輸出自定義變量的值或fact}
1)playbook文件使用template 參數
2)模板文件里面變量使用{{名稱}},比如{{PORT}}或使用facts.
2.2.Jinja模板邏輯關系
{% for i in EXPR %}...{% endfor%}作為循環表達式
{% if EXPR %}...{% elif EXPR %}...{% endif%}作為條件判斷
{# COMMENT #}表示注釋
2.3.jinja模板使用示例,使用fact變量的示例
1)使用Playbook推送文件
[root@m01 playbook ]# cat jinja2.yml
- hosts: web
tasks:
- name: Copy Template File /etc/motd
template: src=./motd.j2 dest=/etc.motd
2)准備motd.j2文件
[root@m01 playbook]# cat motd.j2
Welcome to {{ ansible_hostname }}
This system total Memory is: {{ ansible_memtotal_mb }} MB
This system free Memory is: {{ ansible_memfree_mb }} MB
3)執行Playbook
[root@m01 playbook]# ansible-playbook -i hosts jinja2.yml
3.Ansible Jinja2管理Nginx
ansible 使用jinja2的for循環表達式渲染出nginx負載均衡的配置文件
1)使用Playbook推送nginx配置文件
[root@m01 project2]# cat jinja_nginx.yml
- hosts: webservers
vars:
- http_port: 80
- server_name: www.oldboyedu.com
tasks:
- name: Copy Nginx COnfigure
template: src=./oldboyedu.conf.j2 dest=/etc/nginx/conf.d/oldboyedu_proxy.conf
2)准備proxy.conf.j2配置文件
[root@m01 project2]# cat proxy.conf.j2
upstream {{ server_name }} {
{% for i in range(1,20) %}
server 172.16.1.{{i}}:{{http_port}};
{%endfor%}
}
server {
listen {{ http_port }};
server_name {{ server_name }};
location / {
proxy_pass http://{{ server_name }};
proxy_set_header Host $http_host;
}
}
循環的高級用法:
讀取主機清單中的組(inventory)
upstream {{ server_name }} {
{% for i in groups['webserver'] %}
server {{i}}:{{http_port}} weight=2;
{% endfor %}
4.Ansible Jinja2管理Keepalived
ansible 使用jinja2的if判斷表達式渲染出Keepalived高可用配置文件,並推送到lb組
1)使用Playbook推送Keepalived配置文件
[root@m01 project2]# cat jinja_keepalived.yml
- hosts: webservers
tasks:
- name: Copy Keepalived Configure
template: src=./kee.conf.j2 dest=/tmp/keepalived.conf
2)准備kee.conf.j2 配置文件
[root@m01 project2]# cat kee.conf.j2
global_defs {
router_id {{ ansible_hostname }}
}
vrrp_instance VI_1 {
{%if ansible_hostname =="web01" %}
state MASTER
priority 150
{%elif ansible_hostname == "web02" %}
state BACKUP
priority 100
{%endif%}
interface eth0
virtual_router_id 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3
}
}
5.Ansible Jinja2 IF 管理mysql
1)使用Playbook推送mysql配置文件
[root@m01 project2]# cat jinja_mysql.yml
- hosts: webservers
gather_facts: no
vars:
PORT: 13306
# PORT: false #相當於開關
tasks:
- name: Copy MySQL Configure
template: src=./my.cnf.j2 dest=/tmp/my.cnf
2)准備my.cnf.j2 配置文件
[root@m01 project2]# cat my.cnf.j2
{% if PORT %}
bind-address=0.0.0.0:{{ PORT }}
{% else %}
bind-address=0.0.0.0:3306
{%endif%}
七、Ansible Rose角色
1.Ansible Rose基本概述
前面已經學過tasks和handles,那怎樣組織playbook才是最好的方式呢?簡單的回答就是:使用Roles! Roles基於一個已知的文件結構,去自動的加載某些vars_files, tasks以及handlers。
以便pkaybook更好的調用。相比playbook, roles的結構更加的清晰有層次。
例如:我們無論安裝什么軟件都會安裝時間同步服務,那么每個playbook都要編寫時間同步服務的task。此時我們可以將時間同步服務task寫好,等到用的時候再調用就行了。
Ansible注意事項:在編寫roles的時候,最好能夠將一個task拆分為一個文件,方便后續復用。(徹底的打散)
2.Ansible Rose目錄結構
1.rose官方目錄的結構,必須那么定義
[root@m01 ~]# cd /etc/ansible/roles/
[root@m01 roles]# mkdir -p {nfs,rsync,web}/{vars,tasks,templates,handlers,files,meta}
[root@m01 roles]# tree
.
├── nfs
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
├── rsync
│ ├── files
│ ├── handlers
│ ├── meta
│ ├── tasks
│ ├── templates
│ └── vars
└── web
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars
21 directories, 0 files
3.Ansible Rose依賴關系
roles允許您在使用role時自動引入其他role。role依賴關系存儲在role目錄中meta/main.yml文件中。
例如:安裝wordpress需要先確保nginx與php都能正常運行,此時可以在wordpress的role中定義,依賴nginx與php-fpm的roles
[root@m01 playbook]# cat /root/roles/wordpress/meta/main.yml
---
dependencies:
- { role: nginx }
- { role: php-fpm }
此時wordpress的role會先執行nginx的role,然后再執行php-fpm的role,最后再執行wordpress本身的role。
4.Ansible Rose案例實戰
Roles小技巧:
1.創建role 目錄結構,手動或使用ansible-galaxy init test roles
2.編寫role功能內容。
3.在playbook中引用
案例一、Ansible Roles重構NFS服務
1.安裝nfs的task任務
[root@m01 roles]# cat nfs/tasks/install.yml
- name: Install NFS-utils Server
yum: name=nfs-utils state=present
2.配置nfs的task任務
[root@m01 roles]# cat nfs/tasks/config.yml
- name: Configure Nfs-utils Server
template: src=./exports.j2 dest=/etc/exports owner=root group=root mode=0644
notify: Restart NFS Server
3.啟動fs的task任務
[root@m01 roles]# cat nfs/tasks/start.yml
- name: Start NFS Server
systemd: name=nfs state=started enabled=yes
4.包含nfs的安裝、配置、啟動的task任務
[root@m01 roles]# cat nfs/tasks/main.yml
- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: start.yml
5.客戶端掛載nfs的task任務
[root@m01 roles]# cat nfs-client/tasks/main.yml
- name: Mount NFS Server
mount: path=/opt src=172.16.1.7:/data fstype=nfs opts=defaults state=mounted
6.執行所有tasks的roles主配置文件
[root@m01 roles]# cat site.yml
- hosts: web01
roles:
- nfs
- hosts: web02
roles:
- nfs-client
5.Ansible Galaxy
Galaxy是一個免費網站,類似於github網站,網站上基本都是共享的roles角色。從Galaxy下載roles角色是快速啟動自動化項目方式之一。galaxy官網
Ansible提供了一個ansible-galaxy 命令行工具,可以用來init(初始化)、search(查找)、install(安裝)、remove(移除)等操作。
1.如何使用ansible-galaxy 搜索一個項目
2.查看詳細信息
3.客戶端搜索項目,直接安裝