# Ansible 簡介
Ansible 類似於Saltstack,是一種集成IT系統的配置管理、應用部署、執行特定任務的開源平台。Ansible基於Python語言實現,由Paramiko和PyYAML兩個關鍵模塊構建。Ansible具有以下特點:
- 部署簡單,只需要在主控端部署Ansible環境,被控端無需做任何操作;
- 默認使用SSH(Secure SHell)協議對設備進行管理;
- 主從集中化管理;
- 配置簡單、功能強大、擴展性強;
- 支持API及自定義模塊,可通過Python輕松擴展;
- 通過Playbooks來定制強大的配置、狀態管理;
- 對雲計算平台、大數據都有很好的支持;
- 提供一個功能強大、操作性強的Web管理界面和REST API接口——AWX平台;
- 冪等性:一種操作重復多次結果相同。
Ansible與Saltstack最大的區別是Ansible無需在被控主機部署任何客戶端代理,默認直接通過SSH通道進行遠程命令執行或下發配置;相同點是都具備功能強大、靈活的系統管理、狀態配置,都使用YAML格式來描述配置,兩者都提供豐富的模板及API,對雲計算平台、大數據都有很好的支持。Ansible在GitHub上的地址為https://github.com/ansible/,可參考其中的配置。
# Ansible 安裝及配置
Ansible只需在管理端部署環境即可,建議采用yum源方式來實現部署,需要安裝epel擴展源。我的測試環境為:CentOS release 6.6,自帶Python 2.6.6。
# rpm -ivh https://mirrors.ustc.edu.cn/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install ansible
ansible 配置及測試
在ansible的配置文件中添加主機信息,即可與目標主機進行通信,配置文件位置/etc/ansible/hosts,其中,[webservers]為主機組,可以批量控制主機組里面的所有主機,一個主機可以添加到多個組。
【 /etc/ansible/hosts 】
## green.example.com ## blue.example.com ## 192.168.100.1 ## 192.168.100.10 192.168.1.74 192.168.1.75 [webservers] ## alpha.example.org ## beta.example.org ## 192.168.1.100 ## 192.168.1.110 192.168.1.74 192.168.1.75
通過ping模塊測試主機的連通性,出現下面的結果表示安裝、測試成功。(需要配置主控機無密碼SSH訪問)
[root@CentOS6 ~]# ansible 192.168.1.75 -m ping 192.168.1.75 | SUCCESS => { "changed": false, "ping": "pong" }
ansible 命令集:
/usr/bin/ansible: # Ansibe AD-Hoc 臨時命令執行工具,常用於臨時命令的執行
/usr/bin/ansible-doc: # Ansible 模塊功能查看工具
/usr/bin/ansible-galaxy: # 下載/上傳優秀代碼或Roles模塊的官網平台,基於網絡的
/usr/bin/ansible-playbook: # Ansible 定制自動化的任務集編排工具
/usr/bin/ansible-pull: # Ansible遠程執行命令的工具(使用較少,海量機器時使用,對運維的架構能力要求較高)
/usr/bin/ansible-vault: # Ansible 文件加密工具
/usr/bin/ansible-console: # Ansible基於Linux Consoble界面可與用戶交互的命令執行工具
/etc/ansible/ansible.cfg:配置文件
/etc/ansible/hosts:主機清單
ansible 參數:
[root@node2 ~/.ssh]# ansible -h Usage: ansible <host-pattern> [options] Options: -a MODULE_ARGS, --args=MODULE_ARGS #模塊的參數,如果執行默認COMMAND的模塊,即是命令參數,如:“date”,"pwd"等等 module arguments #模塊參數 --ask-become-pass ask for privilege escalation password # Ansible su切換用戶的時候使用該參數輸入密碼 -k, --ask-pass ask for SSH password #登錄密碼,提示輸入SSH密碼而不是假設基於密鑰的驗證 --ask-su-pass ask for su password #su切換密碼 -K, --ask-sudo-pass ask for sudo password #提示密碼使用sudo,sudo表示提權操作 --ask-vault-pass ask for vault password # ansible-valut 加密文件 -B SECONDS, --background=SECONDS #后台運行超時時間 run asynchronously, failing after X seconds (default=N/A) -C, --check don't make any changes; instead, try to predict some #只是測試一下會改變什么內容,不會真正去執行;相反,試圖預測一些可能發生的變化 of the changes that may occur -c CONNECTION, --connection=CONNECTION 連接類型使用。可能的選項是paramiko(SSH),SSH和地方。當地主要是用於crontab或啟動。 connection type to use (default=smart) -e EXTRA_VARS, --extra-vars=EXTRA_VARS # 調用外部變量 -f FORKS, --forks=FORKS # Ansible一次命令執行並發的線程數,默認是5 specify number of parallel processes to use (default=5) -h, --help show this help message and exit #打開幫助文檔API -i INVENTORY, --inventory-file=INVENTORY #指定庫存主機文件的路徑,默認為/etc/ansible/hosts specify inventory host file (default=/etc/ansible/hosts) -l SUBSET, --limit=SUBSET #進一步限制所選主機/組模式 --limit=192.168.91.135 只對這個ip執行 further limit selected hosts to an additional pattern --list-hosts outputs a list of matching hosts; does not execute anything else -m MODULE_NAME, --module-name=MODULE_NAME #執行模塊的名字,默認使用 command 模塊,所以如果是只執行單一命令可以不用 -m參數 module name to execute (default=command) -M MODULE_PATH, --module-path=MODULE_PATH #要執行的模塊的路徑,默認為/usr/share/ansible/ specify path(s) to module library (default=/usr/share/ansible/) -o, --one-line condense output #壓縮輸出,摘要輸出.嘗試一切都在一行上輸出。 -P POLL_INTERVAL, --poll=POLL_INTERVAL #調查背景工作每隔數秒。需要- b set the poll interval if using -B (default=15) --private-key=PRIVATE_KEY_FILE #私鑰路徑,使用這個文件來驗證連接 use this file to authenticate the connection -S, --su run operations with su 用 su 命令 -R SU_USER, --su-user=SU_USER #指定SU的用戶,默認是root用戶 run operations with su as this user (default=root) -s, --sudo run operations with sudo (nopasswd) -U SUDO_USER, --sudo-user=SUDO_USER #sudo到哪個用戶,默認為 root desired sudo user (default=root) -T TIMEOUT, --timeout=TIMEOUT #指定SSH默認超時時間, 默認是10S override the SSH timeout in seconds (default=10) -t TREE, --tree=TREE log output to this directory 將日志內容保存在該輸出目錄,結果保存在一個文件中在每台主機上。 -u REMOTE_USER, --user=REMOTE_USER 遠程用戶, 默認是root用戶 connect as this user (default=root) --vault-password-file=VAULT_PASSWORD_FILE vault password file -v, --verbose verbose mode (-vvv for more, -vvvv to enable 詳細信息 connection debugging) --version show program's version number and exit 輸出ansible的版本
# Ansible 模塊
1. 遠程命令模塊
(1)功能
包括 command、script、shell,都可以實現遠程shell命令運行。command作為Ansible的默認模塊,可以運行遠程權限范圍所有的shell命令;script功能是在遠程主機執行主控端存儲的shell腳本文件,相當於scp+shell組合;shell功能是執行遠程主機的shell腳本文件。
(2)實例
# ansible webservers -m command -a "free -m" # ansible webservers -m script -a "/home/local.sh 11 22" # ansible webservers -m shell -a "/home/remote.sh"
2. copy 模塊
(1)功能
實現主控向目標主機拷貝文件,類似於scp功能。
##相關選項如下:
backup:在覆蓋之前,將源文件備份,備份文件包含時間信息。有兩個選項:yes|no
content:用於替代“src”,可以直接設定指定文件的值
dest:必選項。要將源文件復制到的遠程主機的絕對路徑,如果源文件是一個目錄,那么該路徑也必須是個目錄
directory_mode:遞歸設定目錄的權限,默認為系統默認權限
force:如果目標主機包含該文件,但內容不同,如果設置為yes,則強制覆蓋,如果為no,則只有當目標主機的目標位置不存在該文件時,才復制。默認為yes
others:所有的file模塊里的選項都可以在這里使用
src:被復制到遠程主機的本地文件,可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,它將遞歸復制。在這種情況下,如果路徑使用“/”來結尾,則只復制目錄里的內容,如果沒有使用“/”來結尾,則包含目錄在內的整個內容全部復制,類似於rsync。
(2)實例
以下示例實現拷貝 /root/install.log 文件至webservers組目標主機的 /tmp 目錄下,並更新屬組及權限(也可單獨使用 file模塊 實現權限的修改)。
[root@CentOS6 ~]# ansible webservers -m copy -a "src=/root/install.log dest=/tmp owner=root group=root mode=0744" 192.168.1.75 | SUCCESS => { "changed": true, "checksum": "efb252eb1008f522d1fad42ffac6814ff9866eb5", "dest": "/tmp/install.log", "gid": 0, "group": "root", "md5sum": "ddd53a3a0d28f1709d5ed708cb400370", "mode": "0744", "owner": "root", "size": 41433, "src": "/root/.ansible/tmp/ansible-tmp-1502165638.76-4541476614641/source", "state": "file", "uid": 0 } 192.168.1.74 | SUCCESS => { "changed": true, "checksum": "efb252eb1008f522d1fad42ffac6814ff9866eb5", "dest": "/tmp/install.log", "gid": 0, "group": "root", "md5sum": "ddd53a3a0d28f1709d5ed708cb400370", "mode": "0744", "owner": "root", "size": 41433, "src": "/root/.ansible/tmp/ansible-tmp-1502165638.84-37324169377020/source", "state": "file", "uid": 0 }
3. stat 模塊
(1)功能
獲取遠程文件狀態信息,包括 atime、ctime、mtime、md5、uid、gid 等信息。
(2)實例
[root@CentOS6 ~]# ansible webservers -m stat -a "path=/tmp/install.log" 10.10.11.75 | SUCCESS => { "changed": false, "stat": { "atime": 1502219654.9290881, "attr_flags": "e", "attributes": [ "extents" ], …………
4. get_url 模塊
(1)功能
實現在遠程主機下載指定url到本地,支持sha256sum文件校驗。
(2)實例
[root@CentOS6 ~]# ansible webservers -m get_url -a "url=http://www.baidu.com dest=/tmp/index.html mode=0440 force=yes" 192.168.1.75 | SUCCESS => { "changed": true, "checksum_dest": null, "checksum_src": "9f661ef8555e303006ea9c7692c9186168912e6d", "dest": "/tmp/index.html", "gid": 0, "group": "root", "md5sum": "e4af2a89c405cae44bffd9f92e2cc7ef", "mode": "0440", "msg": "OK (unknown bytes)", "owner": "root", "size": 111526, "src": "/tmp/tmpN6LWN0", "state": "file", "status_code": 200, "uid": 0, "url": "http://www.baidu.com" } 192.168.1.74 | SUCCESS => { "changed": true, "checksum_dest": null, "checksum_src": "445cac70d434f7be0e9b12ed0cddf83ddbf20e4c", "dest": "/tmp/index.html", "gid": 0, "group": "root", "md5sum": "50b12aa7c56492c743a963be5d44b16a", "mode": "0440", "msg": "OK (unknown bytes)", "owner": "root", "size": 111457, "src": "/tmp/tmpJzSkLM", "state": "file", "status_code": 200, "uid": 0, "url": "http://www.baidu.com" }
5. yum 模塊
(1)功能
Linux平台軟件包管理操作,常見的有yum、apt管理方式。
##相關選項如下:
conf_file #設定遠程yum安裝時所依賴的配置文件。如配置文件沒有在默認的位置。
disable_gpg_check #是否禁止GPG checking,只用於`present' or `latest'。
disablerepo #臨時禁止使用yum庫。 只用於安裝或更新時。
enablerepo #臨時使用的yum庫。只用於安裝或更新時。
name= #所安裝的包的名稱
state #present安裝, latest安裝最新的, absent 卸載軟件。
update_cache #強制更新yum的緩存。
(2)實例
##在遠程主機安裝 lftp
[root@CentOS6 ~]# ansible webservers -m apt -a "pkg=lftp state=latest" [root@CentOS6 ~]# ansible webservers -m yum -a "pkg=lftp state=latest"
6. cron 模塊
(1)功能
遠程主機crontab配置。
(2)實例
[root@CentOS6 ~]# ansible webservers -m cron -a "name='check dirs' hour='5,2' job='ls -alh>/dev/null'" ##遠程機結果如下: [root@db_server ~]# crontab -e #Ansible: check dirs * 5,2 * * * ls -alh>/dev/null
7. mount 模塊
(1)功能
遠程主機分區掛載。
(2)實例
[root@CentOS6 ~]# ansible webservers -m mount -a "name=/mnt/data src=/dev/sd0 fstype=ext4 opts=ro state=present"
8. service 模塊
(1)功能
遠程主機系統服務管理。
##相關選項如下:
arguments #命令行提供額外的參數
enabled #設置開機啟動。
name= #服務名稱
runlevel #開機啟動的級別,一般不用指定。
sleep #在重啟服務的過程中,是否等待。如在服務關閉以后等待2秒再啟動。
state #started啟動服務, stopped停止服務, restarted重啟服務, reloaded重載配置
(2)實例
[root@CentOS6 ~]# ansible webservers -m service -a "name=nginx state=stopped" [root@CentOS6 ~]# ansible webservers -m service -a "name=nginx state=restarted" [root@CentOS6 ~]# ansible webservers -m service -a "name=nginx state=reloaded"
9. sysctl 包管理模塊
(1)功能
遠程Linux主機sysctl配置。
(2)實例
sysctl: name=kernel.panic value=3 sysctl_file=/etc/sysctl.conf checks=before reload=yessalt '*' pkg.upgrade
10. user 服務模塊
(1)功能
遠程主機系統用戶管理。
-a ""
action: user
comment # 用戶的描述信息
createhom # 是否創建家目錄
force # 在使用`state=absent'是, 行為與`userdel --force'一致.
group # 指定基本組
groups # 指定附加組,如果指定為('groups=')表示刪除所有組
home # 指定用戶家目錄
login_class #可以設置用戶的登錄類 FreeBSD, OpenBSD and NetBSD系統.
move_home # 如果設置為`home='時, 試圖將用戶主目錄移動到指定的目錄
name= # 指定用戶名
non_unique # 該選項允許改變非唯一的用戶ID值
password # 指定用戶密碼
remove # 在使用 `state=absent'時, 行為是與 `userdel --remove'一致.
shell # 指定默認shell
state #設置帳號狀態,不指定為創建,指定值為absent表示刪除
system # 當創建一個用戶,設置這個用戶是系統用戶。這個設置不能更改現有用戶。
uid #指定用戶的uid
update_password # 更新用戶密碼
expires #指明密碼的過期時間
# ansible all -m user -a 'name=magedu home=/tmp/magedu/ shell=/bin/bash uid=2000 comment="test user" group=root'
(2)實例
[root@CentOS6 ~]# ansible webservers -m user -a "name=wayne comment='Hello World'" [root@CentOS6 ~]# ansible webservers -m user -a "name=wayne state=absent remove=yes"
11. file 模塊
(1)功能
設置文件屬性。
##相關選項如下:
force:需要在兩種情況下強制創建軟鏈接,一種是源文件不存在,但之后會建立的情況下;另一種是目標軟鏈接已存在,需要先取消之前的軟鏈,然后創建新的軟鏈,有兩個選項:yes|no
group:定義文件/目錄的屬組
mode:定義文件/目錄的權限
owner:定義文件/目錄的屬主
path:必選項,定義文件/目錄的路徑
recurse:遞歸設置文件的屬性,只對目錄有效
src:被鏈接的源文件路徑,只應用於state=link的情況
dest:被鏈接到的路徑,只應用於state=link的情況
state:
directory:如果目錄不存在,就創建目錄
file:即使文件不存在,也不會被創建
link:創建軟鏈接
hard:創建硬鏈接
touch:如果文件不存在,則會創建一個新的文件,如果文件或目錄已存在,則更新其最后修改時間
absent:刪除目錄、文件或者取消鏈接文件
(2)案例
-a "path=PATH state=directory" # 創建目錄 [root@CentOS6 ~]# ansible all -m file -a "path=/tmp/hehe state=directory" -a "path=PATH src=FILE state=link" #創建鏈接文件 [root@CentOS6 ~]# ansible all -m file -a "path=/root/haha src=/tmp/hehe state=link" -a "path=PATH state=absent" #刪除文件 [root@CentOS6 ~]# ansible all -m file -a "path=/root/haha state=absent"
12. fetch 模塊
功能:從遠程服務器拉取文件至本機,只能fetch文件,不能fetch目錄。如果拉目錄,先 tar/zip 再拉到本機即可。
[root@CentOS6 ~]# ansible all -m fetch -a "src=/tmp/txt dest=/root/txt.txt"
13. group 模塊
功能:組管理。
[root@CentOS6 ~]# ansible-doc -s group - name: 添加或刪除組 action: group gid # 設置組的GID號 name= # 管理組的名稱 state # 指定組狀態,默認為創建,設置值為absent為刪除 system # 設置值為yes,表示為創建系統組
14. setup 模塊
收集遠程主機的系統景況。調用后返回很多對應主機的信息,在后面的操作中可以根據不同的信息來做不同的操作。如redhat系列用yum安裝,而debian系列用apt來安裝軟件。
[root@CentOS6 ~]# ansible 10.10.11.75 -m setup 10.10.11.75 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "10.10.11.75" ], "ansible_all_ipv6_addresses": [ "fe80::20c:29ff:feb1:73f4" ], "ansible_apparmor": { "status": "disabled" }, "ansible_architecture": "x86_64", "ansible_bios_date": "07/02/2015", ……
15. selinux 模塊
管理selinux。
conf #指定應用selinux的配置文件。 state=enforcing|permissive|disabled #對應於selinux配置文件的SELINUX。 policy=targeted|minimum|mls #對應於selinux配置文件的SELINUXTYPE ##關閉selinux # ansible all -m selinux -a 'state=disabled'
待續……
# playbook 介紹
playbook 是一個不同於使用 ansible 命令行執行方式的模式,其功能更強大靈活。簡單來說,playbook是一個非常簡單的配置管理和多主機部署系統,不同於任何已經存在的模式,可作為一個適合部署復雜應用程序的基礎。playbook可以定制配置,可以按指定的操作步驟有序執行,支持同步及異步方式。可以在 https://github.com/ansible/ansible-examples 找到大量的例子。playbook是通過YAML格式來進行描述定義的,可以實現多台主機應用的部署,定義在webservers及dbservers組上執行特定指令步驟。下面介紹一個基本的playbook實例:
【 /home/ansible/playbook/nginx.yml 】 --- - hosts: webservers vars: worker_processes: 4 num_cups: 4 max_open_file: 65506 root: /data remote_user: root tasks: - name: ensure nginx is at the latest version yum: pkg=nginx state=latest - name: write the nginx config file template: src=/home/ansible/nginx/nginx2.conf dest=/etc/nginx/nginx.conf notify: - restart nginx - name: ensure nginx is running service: name=nginx state=started handlers: - name: restart nginx service: name=nginx state=restarted
其中,
- hosts 定義主機與用戶,指定了webservers組定義的主機,並定義了相關變量,變量的作用域只限於webservers組下的主機。通過 vars 參數定義了4個變量(配置模板用到),remote_user為指定遠程操作的用戶名,默認為root賬號,支持sudo方式,通過添加sudo: yes即可。
tasks 任務列表
所有的任務列表,playbook將按定義的配置文件自上而下的順序執行,定義的主機都將得到相同的任務,但執行的結果不一定相同,這取決於主機的環境及程序包的狀態。playbook可以通過template模塊對本地配置模板文件進行渲染並同步到目標主機。以nginx配置文件為例,定義如下:
tasks:
- name: write the nginx config file
template: src=/home/ansible/nginx/nginx2.conf dest=/etc/nginx/nginx.conf
notify:
- restart nginx
其中,src=/home/ansible/nginx/nginx2.conf 為管理端模板文件存放位置,dest=/etc/nginx/nginx.conf 為目標主機nginx配置文件位置。下面用一個例子來了解一下什么是模板。
【 /home/ansible/nginx/nginx2.conf 】
user nginx
worker_processes {{ worker_processes }};
{% if num_cups == 2 %}
worker_cpu_affinity 01 10;
{% elif num_cups >= 4 %}
worker_cpu_affinity 1000 0100 0010 0001;
{% else %}
worker_cpu_affinity 1000 0100 0010 0001;
{% endif %}
worker_rlimit_nofile {{ max_open_file }};
… …
Ansible 會根據定義好的模板渲染成真實的配置文件,模板用YAML語法,最終生成的nginx配置如下:
【 /etc/nginx/nginx.conf 】
user nginx
worker_processes 4;
worker_cpu_affinity 1000 0100 0010 0001;
worker_rlimit_nofile 65506;
… …
當目標主機配置文件發生變化后,通知處理程序(Handlers)來觸發后續的動作,比如重啟nginx服務。觸發是通過Handlers定義的name標簽來識別的,比如下面notify中的“restart nginx” 與 handlers中的“name: restart nginx” 保持一致。
notify:
- restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
執行playbook
Syntax:
ansible-playbook [options] PLAYBOOK.yml
options:
-C, --check: 測試模式, 不做任何更改, 而是嘗試運行, 進行檢查;
-i INVENTORY, --inventory-file=INVENTORY specify inventory host path(default=/etc/ansible/hosts) or comma separated host list. 指定主機配置文件路徑;
-u REMOTE_USER, --user=REMOTE_USER:手工指定遠程執行playbook的系統用戶;
--list-hosts: 輸出匹配的主機列表, 不執行其他操作;
--list-tags : 列出所有可用的標簽;
--list-tasks: 列出所有將要執行的任務;
-t TAGS, --tags=TAGS : 只運行tags標識的任務;
--skip-tags=SKIP-TAGS : 只運行tags沒有標記的任務;
--syntax-check: 對劇本執行語法檢查, 但是不執行;
更多參數說明請運行 ansible-playbook --help 。
忽略錯誤的命令
- name: this will not be counted as a failure
command: /bin/false
ignore_errors: yes
僅執行某些t ags
ansible-playbook install_io_server.yml --tags="copyconfig" -i install_io_server_ansible.txt --step --limit io_game_server
注意:本文中的一些案列摘自劉天斯《Python自動化運維》
