1. 概述
Ansible是新出現的自動化運維工具,基於Python開發,集合了眾多運維工具(puppet、cfengine、chef、func、fabric)的優點,實現了批量系統配置、批量程序部署、批量運行命令等功能。Ansible是一個批量的自動化部署工具。
ansible:
模塊:
1) yaml 用來編寫yaml腳本的語言
2) paramiko 模擬ssh協議連接linux客戶端
3) jinja2 模板語言
工作原理:
ansible通過hosts文件和免秘鑰(配置文件用戶名密碼端口號)來實現批量管理主機。
Ansible是基於模塊工作的,本身沒有批量部署的能力。真正具有批量部署的是ansible所運行的模塊,ansible只是提供一種框架。主要包括:
1> Ansible:Ansible的核心程序;
2> connection plugins:連接插件,負責和被監控端實現通信,即Ansible和host的通信;
3> Host inventory:指定操作的主機,是一個配置文件里面定義監控的主機;
4> Core Modules:核心模塊,Ansible執行任何管理任務都不是由Ansible自己完成,而是由核心模塊完成;Ansible管理主機之前,先調用core Modules中的模塊,然后指明管理Host Lnventory中的主機,就可以完成管理主機。
5> Custom Modules:自定義模塊,完成Ansible核心模塊無法完成的功能,此模塊支持任何語言編寫。
Ansible將很多命令集成為模塊調用。
6> Playbook:YAML格式文件,多個任務定義在一個文件中,使用時可以統一調用,“劇本”用來定義那些主機需要調用那些模塊來完成的功能。劇本執行多個任務時,非必需可以讓節點一次性運行多個任務。
簡而言之ansible有如下的特點:
- Stupied Simple ,上手簡單,學習曲線平滑
- SSH by default ,安全,無需安裝客戶端(agent)
- 配置簡單、功能強大、擴展性強
- 支持API及自定義模塊,可通過Python輕松擴展
- 通過Playbooks來定制強大的配置、狀態管理
- 提供一個功能強大、操作性強的Web管理界面和REST API接口——AWX平台(web界面很少用)
- 冪等性:一種操作重復多次結果相同
2. Ansible的安裝
三台主機,192.168.16.4為服務機,.5、.6為服務機
Ansible安裝需要用到擴展源(epel源),擴展源配置完成即可用yum進行下載
在.3上下載安裝
[root@localhost ~]# yum install ansible -y
稍等……..
Complete!
Ansible的配置文件
/etc/ansible/ansible.cfg
/etc/ansible/hosts
3. Ansible客戶端配置
有兩種方法
1> 進入服務端配置文件進行配置
#在文件末尾寫入配置 [root@localhost ~]# vim /etc/ansible/hosts [zxj] #組名 192.168.16.5 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=zxjwrl 192.168.16.6 ansible_ssh_user=root ansibel_ssh_port=22 ansible_ssh_pass=zxjwrl #遠程節點主機 用戶 端口 密碼 [root@localhost ~]# vim /etc/ansible/ansible.cfg host_key_checking = False #進入配置文件,關掉檢查
2> 免秘鑰登錄
sshd服務
配置完成后,查看Ansible是否與管理節點通
[root@localhost ~]# ansible zxj -m ping #主機組名可以替換為單獨的節點ip或者直接改為all,all表示所有主機,ip表示組名下單獨的一個節點 192.168.16.6 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.16.5 | SUCCESS => { "changed": false, "ping": "pong" }
4. Ansible支持的模塊
查看Ansible的模塊
[root@localhost ~]# ansible-doc -l
常用的模塊
ping 模塊: 嘗試連接主機,如果測試成功會返回‘pong’
command模塊: 在遠程節點執行命令
yum模塊: 使用yum軟件包管理工具管理軟件包
shell模塊: 和command模塊類似,執行命令,支持變量等符號
cron模塊 : 管理定時任務,計划任務
service模塊: 管理程序服務
file模塊: 設置文件屬性
copy模塊: 復制本地文件到遠程主機
script模塊: 傳送本地的一個腳本並在遠程主機上執行
setup模塊: 獲取遠程主機的參數信息
user模塊: 管理用戶賬戶
group模塊: 添加或者刪除用戶組
查看具體模塊的用法,以yum模塊為例
[root@localhost ~]# ansible-doc -s yum - name: Manages packages with the `yum' package manager yum: allow_downgrade: # Specify if the named ……. state: # Whether to install (`present' or `installed', `latest'), or remove (`absent' or `removed') a package. `present' and `installed' will simply ensure that a desired package is installed. `latest' will update the specified package if it's not of the latest available version. `absent' and `removed' will remove the specified package. Default is `None', however in effect the default action is `present' unless the `autoremove' option is¬ enabled for this module, then `absent' is inferred.
5. Ansible常用命令相關概念
協程:線程的處理單元;
線程:最小的調度單位;
進程:是最小的管理單元;
一個進程里面至少1個線程,一個線程或者多個線程可以在一個進程里面。
hoc命令行下的命令:
ansible-doc -l |
查看支持的模塊 |
ansible-doc -s MODEL_NAME |
查看模塊的用法 |
-f forks |
指定啟動並發線程數以減少服務器壓力,如ansible -f 5 表示啟動五個線程 |
-m model_name |
要使用的模塊 |
-a args1 |
特有的參數,即調用的模塊里面的參數,使用-a調用 |
ansible all -m ping |
查看client端是否正常ping通 |
通過調用來執行命令舉例詳解
格式: ansible 組名 -m model_name -a 執行命令
#查看客戶端信息 [root@localhost ~]# ansible zxj -m setup …….. #復制文件 #復制並改名 [root@localhost ~]# ansible zxj -m copy -a "src=/root/zxj.txt dest=/root/wrl.txt" 192.168.16.6 | CHANGED => { #源文件 目標文件 "changed": true, #注意冪等性 "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/root/wrl.txt", "gid": 0, "group": "root", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "mode": "0644", "owner": "root", "secontext": "system_u:object_r:admin_home_t:s0", "size": 0, "src": "/root/.ansible/tmp/ansible-tmp-1557345658.29-197424182241042/source", "state": "file", "uid": 0 } 192.168.16.5 | CHANGED => { "changed": true, "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/root/wrl.txt", "gid": 0, "group": "root", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "mode": "0644", "owner": "root", "secontext": "system_u:object_r:admin_home_t:s0", "size": 0, "src": "/root/.ansible/tmp/ansible-tmp-1557345658.28-200767865941415/source", "state": "file", "uid": 0 } #在客戶機下查看 .5: [root@localhost ~]# ls anaconda-ks.cfg wrl.txt .6: [root@localhost ~]# ls \anaconda-ks.cfg wrl.txt #command命令 [root@localhost ~]# ansible zxj -m command -a 'date' #-a后面的引號內可以加任何正確的命令 192.168.16.6 | CHANGED | rc=0 >> Thu May 9 03:52:53 CST 2019 192.168.16.5 | CHANGED | rc=0 >> Thu May 9 03:52:53 CST 2019 #command命令會進行警告。進入配置文件/etc/ansible/ansible.cfg改command_warnings = False #創建、刪除用戶 [root@localhost ~]# ansible zxj -m user -a "name=zxj state=present" #user模塊 用戶名 執行狀態(此處為別名) [root@localhost ~]# ansible zxj -m user -a "name=zxj state=absent" #安裝、卸載軟件 [root@localhost ~]# ansible zxj -m yum -a "name=httpd state=latest" [root@localhost ~]# ansible zxj -m yum -a "name=httpd state=absent" #如果用install、remove等必須寫成單詞的過去式 #注意:yum模塊和yum命令同名,因此執行時會警告,進入配置文件/etc/ansible/ansible.dfg改deprecation_warnings = False #啟動apache服務 [root@localhost ~]# ansible zxj -m service -a "name=httpd state=started" #stopped、restarted、started等均為過去式,ansible不支持systemctl,用centos6及以前版本的service代替 #運行腳本 [root@localhost ~]# ansible zxj -m script -a "/tmp/test.sh" #為腳本絕對路徑 等等
6. Playbook
一個任務為play,多個任務為playbooks
6.1 yaml(yml)
yaml是一個可讀性高的用來表達資料序列的格式,yaml參考了其他多種語言,包括:xml,c語言,python,perl以及電子郵件格式RFC2822等,ClarkEvans在2001年在首次發表了這種語言。
yaml的可讀性好
yaml和腳本語言的交互性好
yaml使用實現語言的數據類型
yaml有一個一致的信息模型
yaml易於實現
yaml可以基於流程來處理
yaml表達能力強,擴展性好
6.2 playbook下的5種模塊
tasks:主程序;
variables:變量,以變量形式傳參;
templates:模板;
handlers:觸發器;
roles:角色。
6.3 playbook書寫規范
腳本名以 .yaml或yml結尾;
一定不能使用tab鍵,yaml有嚴格的縮進要求;
每個冒號:后面必須有空格;
注意:
1)以冒號結尾不需要空格
2)表示文件路徑的模版可以不需要空格
想要表示列表項,使用一個短橫杠加一個空格。多個項使用同樣的縮進級別作為同一個列表的一部。
6.4 ansiblb-playbook常用命令
1)對劇本語法檢測
ansible-playbook --syntax-check /root/ansible/httpd.yaml
2)-C模擬執行劇本
ansible-playbook -C /root/ansible/httpd.yaml
3)執行劇本
ansible-playbook /root/ansible/httpd.yaml
6.5 ansible實例詳解
#創建實例文件 [root@localhost ~]# vim example.yaml # 以yaml或者yml - hosts: zxj # - 必須頂格寫,后面必須加空格,hosts:表示定義主機組,冒號后面必須加空格,后面跟的內容可以是all、ip或主機名 remote_user: root # 指定遠程用戶,以root運行,remote必須和host對齊,冒號后面必須加空格 tasks: # 調用任務模塊,tasks必須與remote對齊,在tasks下面開始寫命令 - name: create userzxj # 橫桿和task對齊,與name之間必須有空格,冒號后面必須加空格,后面定義任務名 user: name=userzxj # 調用user模塊,user必須與name對齊,冒號后面必須加空格。一個任務已經完成,可以繼續往下添加任務,格式一致 #如添加復制任務 - name: copy httpd.conf copy: src=/etc/httpd/conf/httpd.conf dest=/root/test/httpd.conf
#或者定義變量,通過jinjia2里的模板語言{{ }}來引用變量執行 - hosts: zxj remote_user: root vars: #定義變量 - p: httpd.conf #p為變量名,與橫杠間必須有空格,http為變量值 tasks: - name: create userzxj user: name=userzxj - name: copy httpd.conf copy: src=/etc/httpd/conf/{{ p }} dest=/root/test/{{ p }} #引用變量 #再定義觸發器,觸發器僅由相鄰的上一個任務觸發,上一個任務執行成功才觸發執行 - hosts: zxj remote_user: root vars: - p: httpd.conf tasks: - name: create userzxj user: name=userzxj - name: copy httpd.conf copy: src=/etc/httpd/conf/{{ p }} dest=/root/test/{{ p }} notify: #申明定義觸發器 - service httpd restarted #定義觸發器名字 handlers: #定義觸發器,必須在最后,必須與hosts對齊 - name: service httpd restarted #定義任務名,必須與觸發器名字相同 service: name=httpd state=restarted #調用service模塊,執行命令
:wq #執行yaml文件用命令ansible-playbook [root@localhost ~]# ansible-playbook example.yaml PLAY [zxj] ********************************************************
TASK [Gathering Facts] ********************************************** #測試ansible是否與客戶端連通,該任務自動執行 ok: [192.168.16.5] #冪等性,由於先前執行過,並沒有改變,但該命令執行成功 ok: [192.168.16.6]
TASK [create userzxj] ********************************************* #執行第一個任務 ok: [192.168.16.6] ok: [192.168.16.5] TASK [copy httpd.conf] ********************************************** #執行第二個任務 changed: [192.168.16.5] #冪等性,由於先前並沒有執行過,因此改變,任務執行成功 changed: [192.168.16.6] RUNNING HANDLER [service httpd restarted] ************************* #第二個命令執行成功自動觸發 changed: [192.168.16.6] changed: [192.168.16.5] PLAY RECAP ***************************************************** 192.168.16.5 : ok=4 changed=2 unreachable=0 failed=0 192.168.16.6 : ok=4 changed=2 unreachable=0 failed=0 #服務端查看httpd啟動 #.5: [root@localhost ~]# ss -tnl LISTEN 0 128 :::80 :::* .6 [root@localhost ~]# ss -tnl LISTEN 0 128 :::80 :::* #端口前的星號表示ipv4,冒號表示ipv6和ipve4 #可以創建多個觸發器,依托於上一個任務
#還可以進行迭代創建 - hosts: zxj remote_user: root vars: - p: httpd.conf tasks: - name: create many users user: name={{ item }} #進行迭代創建 with_items: #使用迭代 - zxj1 #創建多個用戶 - zxj2 - zxj3 #模塊均可進行迭代執行 #對於模板模塊template,在配置文件里寫入對應模板,yaml文件在執行命令模塊的時候調用模板模塊就可以了,如: #要執行復制http文件任務,進入httpd配置文件,將監聽端口改為jinjia2的模板文件,緊接着修改ansible的配置文件 [root@localhost ~]# vim /etc/httpd/conf/httpd.conf #Listen 12.34.56.78:80 Listen {{ port }} # 變量名可以任意取 [root@localhost ~]# vim example.yaml - name: copy httpd.conf template: src=/etc/httpd/conf/{{ p }} dest=/root/test/{{ p }} [root@localhost ~]# vim /etc/ansible/hosts ## db-[99:101]-node.example.com [zxj] 192.168.16.5 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=zxjwrl port=5000 #寫入端口,寫入變量 192.168.16.6 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=zxjwrl port=6000 #引用多個模板文件時可以在該配置文件后面空格后繼續寫
7. Roles
什么情況下用到roles:
假如現在有3個被管理主機,第一個要配置成httpd,第二個要配置成php服務器,第三個要配置成MySQL服務器。要如何來定義playbook?
第一個play用到第一個主機上,用來構建httpd,第二個play用到第二個主機上,用來構建php,第三個play用到第三個主機上,用來構建MySQL。這些個play定義在playbook中比較麻煩,將來也不利於模塊化調用,不利於多次調用。比如說后來又加進來一個主機,這個第4個主機既是httpd服務器,又是php服務器,只能寫第4個play,上面寫上安裝httpd和php。這樣playbook中的代碼就重復了。這時我們可以通過roles來實現,將各個模塊命令集成在roles下的服務里面,直接調用服務即可。
Roles實例詳解
使用目錄代替命令,各個目錄如下:
files:定義src(源)文件
handlers:定義觸發器
tasks:定義任務
templates:定義模板文件
vars:定義變量
各個目錄寫入文件后放入server目錄,執行時直接調用目錄。
#1 創建級聯目錄 [root@localhost ~]#mkdir-p playbooks/roles/{webservers,dbservers}/{files,handlers,tasks,templates,vars} [root@localhost ~]# tree playbooks/ #查看定義的roles樹 playbooks/ └── roles ├── dbservers #角色 │ ├── files │ ├── handlers │ ├── tasks │ ├── templates │ └── vars └── webservers #角色 ├── files ├── handlers ├── tasks ├── templates └── vars #2. 編輯命令 [root@localhost ~]# vim playbooks/roles/webservers/tasks/main.yml #文件名必須是main.yaml或者main.yml在創建的文件里直接寫任務,不必再聲明組名等信息 - name: create user userzxj #寫入多個命令 user: name=userzxj - name: service httpd start service: name=httpd state=started :wq #3. 創建與roles同等級別的site(站點)文件 [root@localhost ~]# cd playbooks/ [root@localhost playbooks]# vim site.yml #文件名必須為site - hosts: zxj #定義組名和遠程用戶 remote_user: root roles: #調用roles - webservers #寫入角色,執行角色下的任務 - dbservers :wq #4. 執行任務 [root@localhost playbooks]# ansible-playbook site.yml #執行site文件 PLAY [zxj] ********************************************************* TASK [Gathering Facts]*********************************************** ok: [192.168.16.6] ok: [192.168.16.5] TASK [webservers : create user userzxj]********************************** changed: [192.168.16.6] changed: [192.168.16.5] TASK [webservers : service httpd start]************************************ changed: [192.168.16.6] changed: [192.168.16.5] PLAY RECAP ******************************************************* 192.168.16.5 : ok=3 changed=2 unreachable=0 failed=0 192.168.16.6 : ok=3 changed=2 unreachable=0 failed=0 #執行成功
files目錄:定義roles后scr(源文件)不需要寫絕對路徑,只聲明路徑即可
#1. 准備實驗文件 [root@localhost playbooks]# cp /etc/httpd/conf/httpd.conf roles/webservers/files/ #2. 寫入任務目錄 [root@localhost playbooks]# vim roles/webservers/tasks/main.yml - name: copy httpd copy: src=httpd.conf dest=/root/test/httpd.conf #scr不需要再寫絕對路徑 :wq #3. 執行site.yml [root@localhost playbooks]# ansible-playbook site.yml …… 192.168.16.5 : ok=2 changed=1 unreachable=0 failed=0 192.168.16.6 : ok=2 changed=1 unreachable=0 failed=0
handlers目錄,觸發任務
#1. 寫入任務文件,不需要以handlers結尾 [root@localhost playbooks]# vim roles/webservers/tasks/main.yml - name: copy httpd copy: src=httpd.conf dest=/root/test/httpd.conf notify: #聲明觸發 - restart httpd #定義名稱,不需要再以handlers結尾 #2. 寫入handlers下的main.yml [root@localhost playbooks]# vim roles/webservers/handlers/main.yml - name: restart httpd service: name=httpd state=restarted #3. 執行site.yml [root@localhost playbooks]# ansible-playbook site.yml PLAY [zxj] *************** TASK [Gathering Facts] ********* ok: [192.168.16.5] ok: [192.168.16.6] TASK [webservers : copy httpd] ************** changed: [192.168.16.5] changed: [192.168.16.6] RUNNING HANDLER [webservers : restart httpd] ************* #觸發 changed: [192.168.16.6] changed: [192.168.16.5] PLAY RECAP ************ 192.168.16.5 : ok=3 changed=2 unreachable=0 failed=0 192.168.16.6 : ok=3 changed=2 unreachable=0 failed=0
template目錄,執行copy命令時調用定義的模板參數
#1. 寫入任務文件 [root@localhost playbooks]# vim roles/webservers/tasks/main.yml - name: copy httpd template: src=httpd.conf dest=/root/test/httpd.conf #src不寫絕對路徑 notify: - restart httpd #2. 定義模板參數 [root@localhost playbooks]# cp roles/webservers/files/httpd.conf roles/webservers/templates/httpd.conf [root@localhost playbooks]# vim roles/webservers/templates/httpd.conf #Listen 12.34.56.78:80 Listen {{ port }} #更改監聽端口為模板參數 #3. 更改配置文件 [root@localhost ~]# vim /etc/ansible/hosts [zxj] 192.168.16.5 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=zxjwrl port=5000 #寫入參數 192.168.16.6 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=zxjwrl port=6000 #寫入參數 #4. 執行site.yml文件 [root@localhost playbooks]# ansible-playbook site.yml PLAY [zxj]……. TASK [webservers : copy httpd] * changed: [192.168.16.5] changed: [192.168.16.6] RUNNING HANDLER [webservers : restart httpd] changed: [192.168.16.6] changed: [192.168.16.5] PLAY RECAP *************** changed: [192.168.16.6] changed: [192.168.16.5] PLAY RECAP *************** 192.168.16.5 : ok=3 changed=2 unreachable=0 failed=0 192.168.16.6 : ok=3 changed=2 unreachable=0 failed=0
var目錄,定義參數
#1. 定義var的main.yml [root@localhost playbooks]# vim roles/webservers/vars/main.yml p: httpd.conf #定義變量p,變量值為httpd.conf
#2. 修改任務變量 [root@localhost playbooks]# vim roles/webservers/tasks/main.yml - name: copy httpd template: src={{ p }} dest=/root/test/{{ p }} notify: - restart httpd
#3. 執行site.yml
roles下的角色,如webserver、dbserver等可以並排寫入與roles同級的site.yml文件,執行多個角色,每個角色都可以寫入多個任務,實現不同量的批量部署。