波士頓動力機器狗入駐龐貝古城,還要鑽盜洞打擊違法犯罪
Ansible背景
公司的伺服器越來越多, 維護一些簡單的事情都會變得很繁瑣。用shell指令碼來管理少量伺服器效率還行, 伺服器多了之後, shell指令碼無法實現高效率運維。這種情況下,我們需要引入自動化運維工具, 對多臺伺服器實現高效運維。
任務拆解
1, 需要一臺伺服器做管理端, 來連線管理所有的應用伺服器
2, 考慮如果只針對一部分應用伺服器進行運維操作如何實現(伺服器分組)
3, 學會將平臺爛熟於心的linux操作命令轉化為自動化運維的方式(常見模組的學習)
4, 如果操作非常的冗長, 學會使用playbook和role的方式來管理
一、認識自動化運維
問題:
假設我要去1000臺服務上做一個操作(如nginx伺服器修改配置檔案裡的某一個引數), 下面兩種方法缺點明顯:
-
按傳統的方法, 一臺連著一臺伺服器的ssh上去手動操作。
缺點:
- 效率太低。
-
寫個shell指令碼來做。
缺點:
-
管理的機器平臺不一致,指令碼可能不具備通用性。
-
傳密碼麻煩(在非免密登入的環境下, 需要expect來傳密碼)
-
效率較低,迴圈1000次也需要一個一個的完成,如果用
&
-
自動化運維: 將日常IT運維中大量的重複性工作,小到簡單的日常檢查、配置變更和軟體安裝,大到整個變更流程的組織排程,由過去的手工執行轉為自動化操作,從而減少乃至消除運維中的延遲,實現“零延時”的IT運維。
自動化運維主要關注的方面
假如管理很多臺伺服器,主要關注以下幾個方面:
-
管理機與被管理機的連線(管理機如何將管理指令傳送給被管理機)
-
伺服器資訊收集 (如果被管理的伺服器有centos7.5外還有其它linux發行版,如suse,ubuntu等。當你要做的事情在不同OS上有所不同,你需要收集資訊,並將其分開處理)
-
伺服器分組(因為有些時候我要做的事情不是針對所有伺服器,可能只針對某一個分組)
-
管理內容的主要分類
-
檔案目錄管理(包括檔案的建立,刪除,修改,檢視狀態,遠端拷貝等)
-
使用者和組管理
-
cron時間任務管理
-
yum源配置與通過yum管理軟體包
-
服務管理
-
遠端執行指令碼
-
遠端執行命令
常見的開源自動化運維工具比較
-
puppet(拓展)
基於ruby語言,成熟穩定。適合於大型架構,相對於ansible和saltstack會複雜些。
-
saltstack(拓展)
基於python語言。相對簡單,大併發能力比ansible要好, 需要維護被管理端的服務。如果服務斷開,連線就會出問題。
-
ansible
基於python語言。簡單快捷,被管理端不需要啟服務。直接走ssh協議,需要驗證所以機器多的話速度會較慢。
二、ansible
ansible是一種由Python開發的自動化運維工具,集合了眾多運維工具(puppet、cfengine、chef、func、fabric)的優點,實現了批量系統配置、批量程式部署、批量執行命令等功能。
特點:
- 部署簡單
- 預設使用ssh進行管理,基於python裡的paramiko模組開發
- 管理端和被管理端不需要啟動服務
- 配置簡單,功能強大,擴充套件性強
- 能過playbook(劇本)進行多個任務的編排
ansible環境搭建
實驗準備: 三臺機器,一臺管理,兩臺被管理
- 靜態ip
- 主機名及主機名互相繫結
- 關閉防火牆, selinux
- 時間同步
- 確認和配置yum源(需要epel源)
實驗過程:
第1步: 管理機上安裝ansible,被管理節點必須開啟ssh服務.
# yum install epel-release
# yum -y install ansible
# ansible --version
ansible 2.8.4
config file = /etc/ansible/ansible.cfg # 主配置檔案(inventory配置決定了主機列表)
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, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
第2步: 實現master對agent的免密登入,只在master上做。(如果這一步不做,則在後面操作agent時都要加-k引數傳密碼;或者在主機清單裡傳密碼)
master# ssh-keygen -f /root/.ssh/id_rsa -N ''
master# ssh-copy-id -i 10.1.1.12
master# ssh-copy-id -i 10.1.1.13
第3步: 在master上定義主機組,並測試連線性
master# vim /etc/ansible/hosts
[group1]
10.1.1.12
10.1.1.13
[group2]
10.1.1.[12:13]
master# ansible -m ping group1 # -m module 模組
10.1.1.13 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.1.1.12 | SUCCESS => {
"changed": false,
"ping": "pong"
}
master# ansible -m ping all
10.1.1.13 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.1.1.12 | SUCCESS => {
"changed": false,
"ping": "pong"
}
伺服器分組
ansible通過一個主機清單功能來實現伺服器分組。
Ansible的預設主機清單配置檔案為/etc/ansible/hosts
.
示例:
[nginx] 組名
apache[1:10].aaa.com 表示apache1.aaa.com到apache10.aaa.com這10臺機器
nginx[a:z].aaa.com 表示nginxa.aaa.com到nginxz.aaa.com共26臺機器
10.1.1.[11:15] 表示10.1.1.11到10.1.1.15這5臺機器
示例:
[nginx]
10.1.1.13:2222 表示10.1.1.13這臺,但ssh埠為2222
示例: 定義10.1.1.12:2222這臺伺服器的別名為nginx1
nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222
示例: 沒有做免密登入的伺服器可以指定使用者名稱與密碼
nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"
示例: 利用別名來分組
nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"
nginx2 ansible_ssh_host=10.1.1.12
[nginx]
nginx1
nginx2
小結:
主機清單的作用: 伺服器分組。
主機清單的常見功能:
-
可以通過IP範圍來分, 主機名名字的範圍來分
-
如果ssh埠不是22的,可以傳入新的埠。
-
沒有做免密登入,可以傳密碼。
練習: 不論你用哪種環境(免密或不免密,埠是否22), 請最終將兩臺被管理機器加入到group1組即可
ansible模組
ansible是基於模組工作的,本身沒有批量部署的能力。真正具有批量部署的是ansible所執行的模組,ansible只是提供一種框架。
ansible支援的模組非常的多,我們並不需要把每個模組都記住,而只需要熟悉一些常見的模組,其它的模組在需要用到時再查詢即可。
檢視所有支援的模組
# ansible-doc -l
a10_server Manage A10 Networks AX/SoftAX...
a10_server_axapi3 Manage A10 Networks AX/SoftAX...
a10_service_group Manage A10 Networks AX/SoftAX...
a10_virtual_server Manage A10 Networks AX/SoftAX...
aci_aaa_user Manage AAA users (aaa:User)
。。。。。。
如果要檢視ping模組的用法,使用下面命令(其它模組以此類推)
# ansible-doc ping
官網模組文件地址: https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
hostname模組
hostname模組用於修改主機名(注意: 它不能修改/etc/hosts
檔案)
https://docs.ansible.com/ansible/latest/modules/hostname_module.html#hostname-module
-
將其中一遠端機器主機名修改為agent1.cluster.com
基本格式為: ansible 操作的機器名或組名 -m 模組名 -a "引數1=值1 引數2=值2" master# ansible 10.1.1.12 -m hostname -a 'name=agent1'
file模組(重點)
file模組用於對檔案相關的操作(建立, 刪除, 軟硬連結等)
https://docs.ansible.com/ansible/latest/modules/file_module.html#file-module
-
建立一個目錄
master# ansible group1 -m file -a 'path=/test state=directory'
-
建立一個檔案
master# ansible group1 -m file -a 'path=/test/111 state=touch'
-
修改檔案屬主(owner),屬組(group),許可權(mode)
master# ansible group1 -m file -a 'path=/test owner=bin group=daemon mode=1777' master# ansible group1 -m file -a 'path=/test recurse=yes owner=bin group=daemon mode=1777' # 遞迴修改 master# ansible group1 -m file -a 'path=/test state=file owner=bin group=daemon mode=1777' # 如果為連結檔案 則需要制定state型別(同時會修改原始檔)
-
刪除目錄(連同目錄裡的所有檔案)
master# ansible group1 -m file -a 'path=/test state=absent'
-
建立檔案並指定owner,group,mode等
master# ansible group1 -m file -a 'path=/tmp/111 state=touch owner=bin group=daemon mode=1777'
-
刪除檔案
master# ansible group1 -m file -a 'path=/tmp/111 state=absent'
-
建立軟連結檔案
master# ansible group1 -m file -a 'src=/etc/fstab path=/tmp/fstab state=link'
-
建立硬連結檔案
master# ansible group1 -m file -a 'src=/etc/fstab path=/tmp/fstab2 state=hard'
stat模組(瞭解)
stat模組類似linux的stat命令,用於獲取檔案的狀態資訊。
https://docs.ansible.com/ansible/latest/modules/stat_module.html#stat-module
-
獲取
/etc/fstab
檔案的狀態資訊master# ansible group1 -m stat -a 'path=/etc/fstab'
copy模組(重點)
copy模組用於對檔案的遠端拷貝操作(如把本地的檔案拷貝到遠端的機器上)
https://docs.ansible.com/ansible/latest/modules/copy_module.html#copy-module
在master上準備一個檔案,拷貝此檔案到group1的所有機器上
master# echo master > /tmp/222
master# ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/333'
注意: 如果目標檔案存在,對比md5後相同,不做操作;如果存在差異,則覆蓋
使用content引數直接往遠端檔案裡寫內容(會覆蓋原內容)
master# ansible group1 -m copy -a 'content="ha ha\n" dest=/tmp/333'
注意:ansible中-a後面的引數裡也有引號時,記得要單引雙引交叉使用,如果都為雙引會出現問題
使用force引數控制是否強制覆蓋
如果目標檔案已經存在,則不覆蓋
master# ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/333 force=no'
如果目標檔案已經存在,則會強制覆蓋
master# ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/333 force=yes'
使用backup引數控制是否備份檔案
注意: backup=yes表示如果拷貝的檔案內容與原內容不一樣,則會備份一份
注意: group1的機器上會將/tmp/333備份一份(備份檔案命名加上時間),再遠端拷貝新的檔案為/tmp/333
master# ansible group1 -m copy -a 'src=/etc/fstab dest=/tmp/333 backup=yes owner=daemon group=daemon mode=1777'
copy模組拷貝時要注意拷貝目錄後面是否帶"/"符號
注意: /etc/yum.repos.d後面不帶/符號,則表示把/etc/yum.repos.d整個目錄拷貝到/tmp/目錄下
master# ansible group1 -m copy -a 'src=/etc/yum.repos.d dest=/tmp/'
注意: /etc/yum.repos.d/後面帶/符號,則表示把/etc/yum.repos.d/目錄裡的所有檔案拷貝到/tmp/目錄下
master# ansible group1 -m copy -a 'src=/etc/yum.repos.d/ dest=/tmp/'
練習: 在master上配置好所有的yum源,然後拷貝到group1的遠端機器上(要求目錄內的內容完全一致)
master# ansible group1 -m file -a "path=/etc/yum.repos.d/ state=absent"
master# ansible group1 -m copy -a "src=/etc/yum.repos.d dest=/etc/"
練習: 使用hostname模組修改過主機名後.在master上修改/etc/hosts
檔案,並拷貝到group1的遠端機器上
先在master上修改好/etc/hosts檔案,然後使用下面命令拷貝過去覆蓋
master# ansible group1 -m copy -a "src=/etc/hosts dest=/etc/hosts"
關於DNS的補充:
-
域名為公網的唯一名字,主機名為內網的名字(可以重名,但最好不要這麼做)
-
目前自建DNS做域名解析已經很少了, 但可以通過DNS解析主機名來實現內網多臺伺服器的解析
-
現在學了ansible的hostname與copy模組,輕鬆實現N多臺伺服器的主機名管理,DNS也不需要再搭建了
template模組(拓展)
與copy模組功能幾乎一樣.
template模組首先使用變數渲染jinja2模板檔案成普通檔案,然後再複製過去.而copy模組不支援.(jinja2是一個基於python的模板引擎)
https://docs.ansible.com/ansible/latest/modules/template_module.html#template-module
master# ansible -m template group1 -a "src=/etc/hosts dest=/tmp/hosts"
template模組不能拷貝目錄
master# ansible -m template group1 -a "src=/etc/yum.repos.d/ dest=/etc/yum.repos.d/"
fetch模組
fetch模組與copy模組類似,但作用相反。用於把遠端機器的檔案拷貝到本地。
https://docs.ansible.com/ansible/latest/modules/fetch_module.html#fetch-module
第1步: 在兩臺被管理機上分別建立一個同名檔案(但內容不同)
agent1# echo agent1 > /tmp/1.txt
agent2# echo agent2 > /tmp/1.txt
第2步: 從master上fecth檔案(因為group1裡有2臺機器,為了避免同名檔案檔案衝突,它使用了不同的目錄)
master# ansible group1 -m fetch -a 'src=/tmp/1.txt dest=/tmp/'
10.1.1.12 | CHANGED => {
"changed": true,
"checksum": "d2911a028d3fcdf775a4e26c0b9c9d981551ae41",
"dest": "/tmp/10.1.1.12/tmp/1.txt", 10.1.1.12的在這裡
"md5sum": "0d59da0b2723eb03ecfbb0d779e6eca5",
"remote_checksum": "d2911a028d3fcdf775a4e26c0b9c9d981551ae41",
"remote_md5sum": null
}
10.1.1.13 | CHANGED => {
"changed": true,
"checksum": "b27fb3c4285612643593d53045035bd8d972c995",
"dest": "/tmp/10.1.1.13/tmp/1.txt", 10.1.1.13的在這裡
"md5sum": "cd0bd22f33d6324908dbadf6bc128f52",
"remote_checksum": "b27fb3c4285612643593d53045035bd8d972c995",
"remote_md5sum": null
}
第3步: 先刪除上面fetch過來的, 然後嘗試只fetch其中一臺機器的,也會使用名稱來做子目錄區分
master# rm /tmp/10.1.1.* -rf
master# ansible 10.1.1.12 -m fetch -a 'src=/tmp/1.txt dest=/tmp/'
10.1.1.12 | CHANGED => {
"changed": true,
"checksum": "d2911a028d3fcdf775a4e26c0b9c9d981551ae41",
"dest": "/tmp/10.1.1.12/tmp/1.txt", 只fetch一個,也會這樣命名
"md5sum": "0d59da0b2723eb03ecfbb0d779e6eca5",
"remote_checksum": "d2911a028d3fcdf775a4e26c0b9c9d981551ae41",
"remote_md5sum": null
}
注意: fetch模組不能從遠端拷貝目錄到本地
user模組
user模組用於管理使用者賬號和使用者屬性。
https://docs.ansible.com/ansible/latest/modules/user_module.html#user-module
建立aaa使用者,預設為普通使用者,建立家目錄
master# ansible group1 -m user -a ‘name=aaa state=present’
建立bbb系統使用者,並且登入shell環境為/sbin/nologin
master# ansible group1 -m user -a ‘name=bbb state=present system=yes shell="/sbin/nologin"’
建立ccc使用者, 使用uid引數指定uid, 使用password引數傳密碼
master# echo 123456 | openssl passwd -1 -stdin
$1$DpcyhW2G$Kb/y1f.lyLI4MpRlHU9oq0
下一句命令注意一下格式,密碼要用雙引號引起來,單引號的話驗證時會密碼不正確
master# ansible group1 -m user -a 'name=ccc uid=2000 state=present password="$1$DpcyhW2G$Kb/y1f.lyLI4MpRlHU9oq0"'
建立一個普通使用者叫hadoop,併產生空密碼金鑰對
master# ansible group1 -m user -a 'name=hadoop generate_ssh_key=yes'
刪除aaa使用者,但家目錄預設沒有刪除
master# ansible group1 -m user -a 'name=aaa state=absent'
刪除bbb使用者,使用remove=yes引數讓其刪除使用者的同時也刪除家目錄
master# ansible group1 -m user -a 'name=bbb state=absent remove=yes'
group模組
group模組用於管理使用者組和使用者組屬性。
https://docs.ansible.com/ansible/latest/modules/group_module.html#group-module
建立組
master# ansible group1 -m group -a 'name=groupa gid=3000 state=present'
刪除組(如果有使用者的gid為此組,則刪除不了)
master# ansible group1 -m group -a 'name=groupa state=absent'
cron模組
cron模組用於管理週期性時間任務
https://docs.ansible.com/ansible/latest/modules/cron_module.html#cron-module
建立一個cron任務,不指定user的話,預設就是root(因為我這裡是用root操作的)。
如果minute,hour,day,month,week不指定的話,預設都為*
master# ansible group1 -m cron -a 'name="test cron1" user=root job="touch /tmp/111" minute=*/2'
刪除cron任務
master# ansible group1 -m cron -a 'name="test cron1" state=absent'
yum_repository模組
yum_repository模組用於配置yum倉庫。
https://docs.ansible.com/ansible/latest/modules/yum_repository_module.html
增加一個/etc/yum.repos.d/local.repo
配置檔案
master# ansible group1 -m yum_repository -a "name=local description=localyum baseurl=file:///mnt/ enabled=yes gpgcheck=no"
注意:此模組只幫助配置yum倉庫,但如果倉庫裡沒有軟體包,安裝一樣會失敗。所以可以手動去掛載光碟機到/mnt目錄
# mount /dev/cdrom /mnt
刪除/etc/yum.repos.d/local.repo
配置檔案
master# ansible group1 -m yum_repository -a "name=local state=absent"
yum模組(重點)
yum模組用於使用yum命令來實現軟體包的安裝與解除安裝。
https://docs.ansible.com/ansible/latest/modules/yum_module.html#yum-module
使用yum安裝一個軟體(前提:group1的機器上的yum配置都已經OK)
master# ansible group1 -m yum -a 'name=vsftpd state=present'
使用yum安裝httpd,httpd-devel軟體,state=latest表示安裝最新版本
master# ansible group1 -m yum -a 'name=httpd,httpd-devel state=latest'
使用yum解除安裝httpd,httpd-devel軟體
master# ansible group1 -m yum -a 'name=httpd,httpd-devel state=absent'
service模組(重點)
service模組用於控制服務的啟動,關閉,開機自啟動等。
https://docs.ansible.com/ansible/latest/modules/service_module.html#service-module
啟動vsftpd服務,並設為開機自動啟動
master# ansible group1 -m service -a 'name=vsftpd state=started enabled=on'
關閉vsftpd服務,並設為開機不自動啟動
master# ansible group1 -m service -a 'name=vsftpd state=stopped enabled=false'
練習: 在group1的被管理機裡的mariadb裡建立一個abc庫
https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_db_module.html#ansible-collections-community-mysql-mysql-db-module
練習:
假設我主機清單裡定義的group1裡有多臺機器,它們現在要做一個叢集。此叢集要求實現一個名為hadoop的普通使用者之間的兩兩免密登入,如何實現(要求只在master上進行操作)?
script模組
script模組用於在遠端機器上執行本地指令碼。
https://docs.ansible.com/ansible/latest/modules/script_module.html#script-module
在master上準備一個指令碼
master# vim /tmp/1.sh
#!/bin/bash
mkdir /tmp/haha
touch /tmp/haha/{1..10}
在group1的遠端機器裡都執行master上的/tmp/1.sh指令碼(此指令碼不用給執行許可權)
master# ansible group1 -m script -a '/tmp/1.sh'
擴充套件: 使用shell指令碼實現在group1的被管理機裡的mariadb裡建立一個abc庫
#!/bin/bash
yum install mariadb-server -y &> /dev/null
systemctl start mariadb
systemctl enable mariadb
mysql << EOF
create database abc;
quit
EOF
把上面的指令碼使用script模組在group1被管理機裡執行即可
command與shell模組
兩個模組都是用於執行linux命令的,這對於命令熟悉的工程師來說,用起來非常high。
shell模組與command模組差不多(command模組不能執行一些類似$HOME,>,<,|等符號,但shell可以)
https://docs.ansible.com/ansible/latest/modules/command_module.html
https://docs.ansible.com/ansible/latest/modules/shell_module.html
master# ansible -m command group1 -a "useradd user2"
master# ansible -m command group1 -a "id user2"
master# ansible -m command group1 -a "cat /etc/passwd |wc -l" --報錯
master# ansible -m shell group1 -a "cat /etc/passwd |wc -l" --成功
master# ansible -m command group1 -a "cd $HOME;pwd" --報錯
master# ansible -m shell group1 -a "cd $HOME;pwd" --成功
注意: shell模組並不是百分之百任何命令都可以,比如vim或ll別名就不可以。不建議大家去記憶哪些命令不可以,大家只要養成任何在生產環境裡的命令都要先在測試環境裡測試一下的習慣就好。
三、playbook
playbook(劇本): 是ansible用於配置,部署,和管理被控節點的劇本。用於ansible操作的編排。
參考:https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html
使用的格式為yaml格式(saltstack,elk,docker,docker-compose,kubernetes等也都會用到yaml格式)
YMAL格式
- 以
.yaml
或.yml
結尾
- 檔案的第一行以 "---"開始,表明YMAL檔案的開始(可選的)
- 以#號開頭為註釋
- 列表中的所有成員都開始於相同的縮排級別, 並且使用一個
"- "
作為開頭(一個橫槓和一個空格) - 一個字典是由一個簡單的
鍵: 值
的形式組成(這個冒號後面必須是一個空格) - 注意: 寫這種檔案不要使用tab鍵,都使用空格
參考: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html#yaml-syntax
下面看一個官方的示例感受一下
---
# 一位職工記錄
name: Example Developer
job: Developer
skill: Elite
employed: True
foods:
- Apple
- Orange
- Strawberry
- Mango
languages:
ruby: Elite
python: Elite
dotnet: Lame
playbook例項
先直接來看一個例項
第1步: 建立一個存放playbook的目錄(路徑自定義)
master# mkdir /etc/ansible/playbook # 建議使用路徑
第2步: 準備httpd配置檔案,並修改成你想要的配置
master# yum install httpd -y
按需要修改你想要的配置(為了測試可以隨意改動標記一下)
master# vim /etc/httpd/conf/httpd.conf
第3步: 寫一個playbook檔案(字尾為.yml或.yaml)
# vim /etc/ansible/playbook/example.yaml
---
- hosts: group1
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd,httpd-devel state=latest
- name: write the apache config file
copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart apache # 呼叫handlers中的"restart apache"方法
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
第4步: 執行寫好的palybook
- 會顯示出執行的過程,並且執行的每一步都有ok,changed,failed等標識
- 執行如果有錯誤(failed)會回滾,解決問題後,直接再執行這條命令即可,並會把failed改為changed(冪等性)
# ansible-playbook /etc/ansible/playbook/example.yaml
Playbook常見語法
hosts: 用於指定要執行任務的主機,其可以是一個或多個由冒號分隔主機組.
remote_user: 用於指定遠端主機上的執行任務的使用者.
- hosts: group1
remote_user: root
tasks: 任務列表, 按順序執行任務.
- 如果一個host執行task失敗, 整個tasks都會回滾, 修正playbook 中的錯誤, 然後重新執行即可.
tasks:
- name: ensure apache is at the latest version
yum: name=httpd,httpd-devel state=latest
- name: write the apache config file
copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
handlers: 類似task,但需要使用notify通知呼叫。
- 不管有多少個通知者進行了notify,等到play中的所有task執行完成之後,handlers也只會被執行一次.
- handlers最佳的應用場景是用來重啟服務,或者觸發系統重啟操作.除此以外很少用到了.
notify:
- restart apache
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
練習: 修改httpd的埠為8080,再執行playbook測試
variables: 變數
- 定義變數可以被多次方便呼叫
master# vim /etc/ansible/playbook/example2.yaml
---
- hosts: group1
remote_user: root
vars:
- user: test1
tasks:
- name: create user
user: name={{user}} state=present
master# ansible-playbook /etc/ansible/playbook/example2.yaml
案例: playbook編排vsftpd
寫一個playbook實現
- 配置yum
- 安裝vsftpd包
- 修改配置檔案(要求拒絕匿名使用者登入)
- 啟動服務並實現vsftpd服務開機自動啟動
---
- hosts: group1
remote_user: root
tasks:
- name: rm yum repository
file: path=/etc/yum.repos.d/ state=absent
- name: 同步master上的yum源到group1
copy: src=/etc/yum.repos.d dest=/etc/
- name: ensure vsftpd is at the latest version
yum: name=vsftpd state=latest
- name: write the apache config file
copy: src=/etc/vsftpd/vsftpd.conf dest=/etc/vsftpd/vsftpd.conf
notify:
- restart vsftpd
- name: ensure vsftpd is running (and enable it at boot)
service: name=vsftpd state=started enabled=yes
handlers:
- name: restart vsftpd
service: name=vsftpd state=restarted
playbook編排多個hosts任務
--- # ---代表開始(可選項,不寫也可以)
- hosts: 10.1.1.12
remote_user: root
tasks:
- name: 建立/test1/目錄
file: path=/test1/ state=directory
# 這裡不能用---分隔,會報語法錯誤(後面課程玩k8s編排也寫YAML檔案,是可以用---來分隔段落的)
- hosts: 10.1.1.13
remote_user: root
tasks:
- name: 建立/test2/目錄
file: path=/test2/ state=directory
... # ...代表結束(可選項,不寫也可以)
案例: 編排nfs搭建與客戶端掛載
1, 在master上準備nfs配置檔案
# vim /etc/exports
/share *(ro)
2, 編寫yaml編排檔案
# vim /etc/ansible/playbook/nfs.yml
---
- hosts: 10.1.1.12
remote_user: root
tasks:
- name: 安裝nfs服務相關軟體包
yum: name=nfs-utils,rpcbind,setup state=latest
- name: 建立共享目錄
file: path=/share/ state=directory
- name: 同步nfs配置檔案
copy: src=/etc/exports dest=/etc/exports
notify: restart nfs
- name: 啟動rpcbind服務,並設定為開機自啟動
service: name=rpcbind state=started enabled=on
- name: 啟動nfs服務,並設定為開機自啟動
service: name=nfs state=started enabled=on
handlers:
- name: restart nfs
service: name=nfs state=restarted
- hosts: 10.1.1.13
remote_user: root
tasks:
- name: 安裝nfs客戶端軟體包
yum: name=nfs-utils state=latest
- name: 掛載nfs伺服器的共享
shell: mount 10.1.1.12:/share /mnt
3, 執行playbook
# ansible-playbook /etc/ansible/playbook/nfs.yaml
四、roles(難點)
roles介紹
roles(角色): 就是通過分別將variables, tasks及handlers等放置於單獨的目錄中,並可以便捷地呼叫它們的一種機制。
假設我們要寫一個playbook來安裝管理lamp環境,那麼這個playbook就會寫很長。所以我們希望把這個很大的檔案分成多個功能拆分, 分成apache管理,php管理,mysql管理,然後在需要使用的時候直接呼叫就可以了,以免重複寫。就類似程式設計裡的模組化的概念,以達到程式碼複用的效果。
建立roles的目錄結構
files:用來存放由copy模組或script模組呼叫的檔案。
tasks:至少有一個main.yml檔案,定義各tasks。
handlers:有一個main.yml檔案,定義各handlers。
templates:用來存放jinjia2模板。
vars:有一個main.yml檔案,定義變數。
meta:有一個main.yml檔案,定義此角色的特殊設定及其依賴關係。
注意: 在每個角色的目錄中分別建立files, tasks,handlers,templates,vars和meta目錄,用不到的目錄可以建立為空目錄.
通過roles實現lamp
需定製三個角色: httpd,mysql,php
第1步: 建立roles目錄及檔案,並確認目錄結構
master# cd /etc/ansible/roles/
master# mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta}
master# touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yml
master# yum install tree -y
master# tree /etc/ansible/roles/
/etc/ansible/roles/
├── httpd
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ └── vars
│ └── main.yml
├── mysql
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ └── vars
│ └── main.yml
└── php
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
└── vars
└── main.yml
第2步: 準備httpd伺服器的主頁檔案,php測試頁和配置檔案等
master# echo "test main page" > /etc/ansible/roles/httpd/files/index.html
master# echo -e "<?php\n\tphpinfo();\n?>" > /etc/ansible/roles/httpd/files/test.php
master# yum install httpd -y
按需求修改配置檔案後,拷貝到httpd角色目錄裡的files子目錄
master# vim /etc/httpd/conf/httpd.conf
master# cp /etc/httpd/conf/httpd.conf /etc/ansible/roles/httpd/files/
第3步: 編寫httpd角色的main.yml檔案
---
- name: 安裝httpd
yum: name=httpd,httpd-devel state=present
- name: 同步httpd配置檔案
copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: 同步主頁檔案
copy: src=/etc/ansible/roles/httpd/files/index.html dest=/var/www/html/index.html
- name: 同步php測試頁
copy: src=/etc/ansible/roles/httpd/files/test.php dest=/var/www/html/test.php
- name: 啟動httpd並開機自啟動
service: name=httpd state=started enabled=yes
第4步: 編寫httpd角色裡的handler
master# vim /etc/ansible/roles/httpd/handlers/main.yml
---
- name: restart httpd
service: name=httpd state=restarted
第5步: 編寫mysql角色的main.yml檔案
---
- name: 安裝mysql
yum: name=mariadb,mariadb-server,mariadb-devel state=present
- name: 啟動mysql並開機自啟動
service: name=mariadb state=started enabled=yes
第6步: 編寫php角色的main.yml檔案
master# vim /etc/ansible/roles/php/tasks/main.yml
---
- name: 安裝php及依賴包
yum: name=php,php-gd,php-ldap,php-odbc,php-pear,php-xml,php-xmlrpc,php-mbstring,php-snmp,php-soap,curl,curl-devel,php-bcmath,php-mysql state=present
notify: restart httpd
第7步:編寫lamp的playbook檔案呼叫前面定義好的三個角色
master# vim /etc/ansible/playbook/lamp.yaml
---
- hosts: group1
remote_user: root
roles:
- httpd
- mysql
- php
第8步: 執行lamp的playbook檔案
master# ansible-playbook /etc/ansible/playbook/lamp.yaml
拓展案例: 通過roles實現lamp並安裝discuz
第1步: 建立roles目錄及檔案,並確認目錄結構
master# cd /etc/ansible/roles/
master# mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta}
master# touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yml
第2步: 準備httpd相關檔案
master# ls /etc/ansible/roles/httpd/files/
Discuz_X3.2_SC_UTF8.zip Discuz相關軟體包
httpd.conf 配置好的httpd.conf配置檔案
第3步: 編寫httpd角色的main.yml檔案
master# vim /etc/ansible/roles/httpd/tasks/main.yml
- name: 安裝httpd相關軟體包
yum: name=httpd,httpd-devel state=latest
- name: 同步配置檔案
copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: 拷貝discuz壓縮包
copy: src=/etc/ansible/roles/httpd/files/Discuz_X3.2_SC_UTF8.zip dest=/tmp/
- name: 解壓並mv網站檔案到httpd家目錄
shell: rm -rf /var/www/html/* && rm -rf /test/ && mkdir -p /test/ && unzip /tmp/Discuz_X3.2_SC_UTF8.zip -d /test/ &> /dev/null && mv /test/upload/* /var/www/html/ && chown -R apache.apache /var/www/html/
# 上面的命令有點多,可以寫成指令碼,然後使用script模組來呼叫執行
- name: 啟動httpd並開機自啟動
service: name=httpd state=started enabled=on
第4步: 編寫httpd角色裡的handler
master# vim /etc/ansible/roles/httpd/handlers/main.yml
---
- name: restart httpd
service: name=httpd state=restarted
第5步: 編寫mysql角色的main.yml檔案
master# vim /etc/ansible/roles/mysql/tasks/main.yml
---
- name: 安裝mariadb相關軟體包
yum: name=mariadb-server,mariadb-devel state=latest
- name: 啟動mariadb服務並設定開機自啟動
service: name=mariadb state=started enabled=on
- name: 執行建庫指令碼
script: /etc/ansible/roles/mysql/files/create.sh
第6步: 編寫mysql的建庫指令碼
master# vim /etc/ansible/roles/mysql/files/create.sh
#!/bin/bash
mysql << EOF
create database if not exists discuz default charset=utf8;
grant all on discuz.* to 'discuz'@'localhost' identified by '123';
flush privileges;
EOF
第7步: 編寫php角色的main.yml檔案
master# vim /etc/ansible/roles/php/tasks/main.yml
---
- name: 安裝php相關軟體包
yum: name=php,php-gd,php-ldap,php-odbc,php-pear,php-xml,php-xmlrpc,php-mbstring,php-snmp,php-soap,curl,curl-devel,php-bcmath,php-mysql state=present
notify: restart httpd
第8步:編寫lamp的playbook檔案呼叫前面定義好的三個角色
master# vim /etc/ansible/playbook/lamp.yaml
---
- hosts: group1
remote_user: root
roles:
- httpd
- mysql
- php
第9步: 執行lamp的playbook檔案
master# ansible-playbook /etc/ansible/playbook/lamp.yaml
練習
請使用role來實現lnmp