ansible 的配置文件有多個位置,查找順序以下:html
環境變量 ANSIBLE_CONFIG 所指向的位置python
inventory = ~/ansible_hosts #這個參數表示主機清單 inventory 文件的位置 forks = 5 #併發鏈接數,默認爲5 sudo_user = root #設置默認執行命令的用戶 remote_port = 22 #指定鏈接被管節點的管理端口,默認爲22端口,建議修改,可以更加安全 host_key_checking = False #設置是否檢查SSH主機的密鑰,值爲True/False。關閉後第一次鏈接不會提示配置實例 timeout = 60 #設置SSH鏈接的超時時間,單位爲秒 log_path = /var/log/ansible.log #指定一個存儲ansible日誌的文件(默認不記錄日誌)
更爲詳細的配置參數詳見git
ansible 詳細配置文件http://link.zhihu.com/?target=https%3A//raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfggithub
Ansible 可同時操做屬於一個組的多臺主機,組和主機之間的關係經過 inventory 文件配置. 默認的文件路徑爲 /etc/ansible/hosts,咱們也能夠經過 ansible 的配置文件來指定 inventory 文件位置。
除默認文件外,你還能夠同時使用多個 inventory 文件,也能夠從動態源,或雲上拉取 inventory 配置信息。web
一個簡單的 Inventory文件示例shell
192.168.0.111
也能夠對主機進行分組json
mail.example.com [webservers] foo.example.com bar.example.com [dbservers] one.example.com two.example.com three.example.com
方括號[]中是組名,用於對系統進行分類,便於對不一樣系統進行個別的管理。一個系統能夠屬於不一樣的組,好比一臺服務器能夠同時屬於 webserver 組和 dbserver 組。這時屬於兩個組的變量均可覺得這臺主機所用。ubuntu
主機變量前面已經提到過,分配變量給主機很容易作到,這些變量定義後可在 playbooks 中使用:vim
[atlanta] host1 http_port=80 maxRequestsPerChild=808 host2 http_port=303 maxRequestsPerChild=909
組的變量也能夠定義屬於整個組的變量:安全
[atlanta] host1 host2 [atlanta:vars] ntp_server=ntp.atlanta.example.com proxy=proxy.atlanta.example.com
把一個組做爲另外一個組的子成員
能夠把一個組做爲另外一個組的子成員,以及分配變量給整個組使用. 這些變量能夠給 /usr/bin/ansible-playbook 使用,但不能給 /usr/bin/ansible 使用:
[atlanta] host1 host2 [raleigh] host2 host3 [southeast:children] atlanta raleigh [southeast:vars] some_server=foo.southeast.example.com halon_system_timeout=30 self_destruct_countdown=60 escape_pods=2 [usa:children] southeast northeast southwest northwest
對於每個 host,你還能夠選擇鏈接類型和鏈接用戶名:
[targets] localhost ansible_connection=local other1.example.com ansible_connection=ssh ansible_ssh_user=mpdehaan other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
如同前面提到的,經過設置下面的參數,能夠控制 ansible 與遠程主機的交互方式,以下:
ansible_ssh_host 將要鏈接的遠程主機名.與你想要設定的主機的別名不一樣的話,可經過此變量設置. ansible_ssh_port ssh端口號.若是不是默認的端口號,經過此變量設置. ansible_ssh_user 默認的 ssh 用戶名 ansible_ssh_pass ssh 密碼(這種方式並不安全,咱們強烈建議使用 --ask-pass 或 SSH 密鑰) ansible_sudo_pass sudo 密碼(這種方式並不安全,咱們強烈建議使用 --ask-sudo-pass) ansible_sudo_exe (new in version 1.8) sudo 命令路徑(適用於1.8及以上版本) ansible_connection 與主機的鏈接類型.好比:local, ssh 或者 paramiko. Ansible 1.2 之前默認使用 paramiko.1.2 之後默認使用 'smart','smart' 方式會根據是否支持 ControlPersist, 來判斷'ssh' 方式是否可行. ansible_ssh_private_key_file ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的狀況. ansible_shell_type 目標系統的shell類型.默認狀況下,命令的執行使用 'sh' 語法,可設置爲 'csh' 或 'fish'. ansible_python_interpreter 目標主機的 python 路徑.適用於的狀況: 系統中有多個 Python, 或者命令路徑不是"/usr/bin/python",好比 \*BSD, 或者 /usr/bin/python 不是 2.X 版本的 Python.咱們不使用 "/usr/bin/env" 機制,由於這要求遠程用戶的路徑設置正確,且要求 "python" 可執行程序名不可爲 python之外的名字(實際有可能名爲python26). 與 ansible_python_interpreter 的工做方式相同,可設定如 ruby 或 perl 的路徑....
一個主機文件的例子
some_host ansible_ssh_port=2222 ansible_ssh_user=manager aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem freebsd_host ansible_python_interpreter=/usr/local/bin/python ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
接下來咱們展現如何 ansible 命令,配置文件以下所示:
(py37env) aaron@ubuntu:~$ cat ~/.ansible.cfg [defaults] inventory = ~/ansible_hosts
inventory 文件以下所示:
(py37env) aaron@ubuntu:~$ cat ~/ansible_hosts [master] localhost ansible_connection=local ansible_ssh_user=aaron 192.168.0.111 ansible_ssh_user=aaron [slave] 192.168.0.112 ansible_ssh_user=aaron
可能每臺機器登錄的用戶名都不同,這裏我指明瞭每臺機器鏈接的 ssh 登錄用戶名,在執行 ansible 命令時就不須要再指定用戶名,若是不指定用戶名,andible 則嘗試使用本機已登錄的用戶去登錄遠程主機。
使用 ansible 命令的幫助
(py37env) aaron@ubuntu:~$ ansible -help Usage: ansible <host-pattern> [options] Define and run a single task 'playbook' against a set of hosts Options: -a MODULE_ARGS, --args=MODULE_ARGS module arguments --ask-vault-pass ask for vault password -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 -D, --diff when changing (small) files and templates, show the differences in those files; works great with --check -e EXTRA_VARS, --extra-vars=EXTRA_VARS set additional variables as key=value or YAML/JSON, if filename prepend with @ -f FORKS, --forks=FORKS specify number of parallel processes to use (default=5) -h, --help show this help message and exit -i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated -l SUBSET, --limit=SUBSET further limit selected hosts to an additional pattern --list-hosts outputs a list of matching hosts; does not execute anything else ......
全部的命令參數均可以從 ansible -h 找到,接下接讓咱們列出主機列表
(py37env) aaron@ubuntu:~$ ansible all --list-host hosts (3): 192.168.0.112 localhost 192.168.0.111 (py37env) aaron@ubuntu:~$ ansible master --list-host hosts (2): localhost 192.168.0.111
執行第一條 ansible 命令
能夠看出 ansible 命令後跟的是主機的組的名稱,all 表明全部的主機。
接下來讓咱們執行第一條 ansible 命令.
ping 全部主機
(py37env) aaron@ubuntu:~$ ansible all -m ping localhost | SUCCESS => { "changed": false, "ping": "pong" } 192.168.0.112 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n", "unreachable": true } 192.168.0.111 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n", "unreachable": true }
能夠看出 ansible 返回的類型是一個鍵值對的 json 格式的數據,其中 localhost 成功,其餘兩個主機均失敗了,緣由是 ssh 是一個安全的協議,若是不提供用戶名密碼就能夠隨便鏈接,會出大問題的。
咱們使用密碼來執行 ansible 的 ping 命令:
(py37env) aaron@ubuntu:~$ ansible all -m ping --ask-pass SSH password: localhost | SUCCESS => { "changed": false, "ping": "pong" } 192.168.0.111 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.0.112 | SUCCESS => { "changed": false, "ping": "pong" }
輸入密碼後(若是每臺機器密碼相同,則只須要執行一次命令,輸入一次密碼,若不一樣,須要屢次執行命令,每次輸入不一樣的密碼),命令被成功執行,在一些機器上你會須要安裝 sshpass 或者指定 -c paramiko。
從運行結果能夠看出,都是 ping 通的,返回結果爲 "pong", changed 是 false 表示未改變遠程主機任何文件。
這樣一指令就分別發送到 3 臺主機進行執行,是否是很高效?短期內無需再重複輸入密碼。
那麼問題來了,每次都輸入密碼太煩了,有沒有不輸入密碼的方法呢?固然有了,ansible 使用 ssh 協議登錄遠程主機,接下來咱們使用 ansible 將 localhost 的公鑰複製到遠程主機的 authorized_keys
首先檢查本機是否已生成公鑰,若是沒有則在 shell 中執行 ssh-keygen 命令後一直回車便可。
(py37env) aaron@ubuntu:~$ ls -ltr ~/.ssh total 12 -rw-r--r-- 1 aaron aaron 394 Aug 2 21:39 id_rsa.pub -rw------- 1 aaron aaron 1679 Aug 2 21:39 id_rsa -rw-r--r-- 1 aaron aaron 666 Aug 4 09:11 known_hosts
若是有 id_rsa.pub 則說明已經生成了公鑰
接下來咱們使用 ansible 將公鑰文件的內容複製到遠程主機的 authorized_keys 裏去。
ansible 批量執行 ssh 授信
(py37env) aaron@ubuntu:~/.ssh$ ansible all -m authorized_key -a "user=aaron key='{{ lookup('file', '/home/aaron/.ssh/id_rsa.pub') }}' path=/home/aaron/.ssh/authorized_keys manage_dir=yes" --ask-pass SSH password: localhost | SUCCESS => { "changed": true, "comment": null, "exclusive": false, "gid": 1001, "group": "aaron", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjf6e7DpOI/7eARUNvo7xD51X1fp9/am1hYn2aCkZyhPWRKUYiJQHm7JtPJQAV2o6LyAaZxcksLEbRD2bOHjTyu9uV2y8dfmejG7ISn/jOWXLQ+mjgtxxOKUj+0Hu5vRbv1zi7ggfHsZc2l+7Zgpc3XHoCPXM/E514TE6OPt1+5l4IdZWErNX255dXDqrCmd7VEvSTvvI1K/tkSY8oTBEg87TRscrgmsQyLyOoSswvCqWpvy+VrTfSoabZzVb1XvCH+apA41wHN4BnQYsQzk2sdl75rsn8rhzGiZUWc67K4nqbMbqs1Dxek3u2enFRQlVHbs8xHuBvcqwk5XRkkiCp aaron@ubuntu", "key_options": null, "keyfile": "/home/aaron/.ssh/authorized_keys", "manage_dir": true, "mode": "0600", "owner": "aaron", "path": "/home/aaron/.ssh/authorized_keys", "size": 394, "state": "file", "uid": 1001, "unique": false, "user": "aaron", "validate_certs": true } 192.168.0.111 | SUCCESS => { "changed": true, "comment": null, "exclusive": false, "gid": 1000, "group": "aaron", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjf6e7DpOI/7eARUNvo7xD51X1fp9/am1hYn2aCkZyhPWRKUYiJQHm7JtPJQAV2o6LyAaZxcksLEbRD2bOHjTyu9uV2y8dfmejG7ISn/jOWXLQ+mjgtxxOKUj+0Hu5vRbv1zi7ggfHsZc2l+7Zgpc3XHoCPXM/E514TE6OPt1+5l4IdZWErNX255dXDqrCmd7VEvSTvvI1K/tkSY8oTBEg87TRscrgmsQyLyOoSswvCqWpvy+VrTfSoabZzVb1XvCH+apA41wHN4BnQYsQzk2sdl75rsn8rhzGiZUWc67K4nqbMbqs1Dxek3u2enFRQlVHbs8xHuBvcqwk5XRkkiCp aaron@ubuntu", "key_options": null, "keyfile": "/home/aaron/.ssh/authorized_keys", "manage_dir": true, "mode": "0600", "owner": "aaron", "path": "/home/aaron/.ssh/authorized_keys", "size": 394, "state": "file", "uid": 1000, "unique": false, "user": "aaron", "validate_certs": true } 192.168.0.112 | SUCCESS => { "changed": true, "comment": null, "exclusive": false, "gid": 1000, "group": "aaron", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjf6e7DpOI/7eARUNvo7xD51X1fp9/am1hYn2aCkZyhPWRKUYiJQHm7JtPJQAV2o6LyAaZxcksLEbRD2bOHjTyu9uV2y8dfmejG7ISn/jOWXLQ+mjgtxxOKUj+0Hu5vRbv1zi7ggfHsZc2l+7Zgpc3XHoCPXM/E514TE6OPt1+5l4IdZWErNX255dXDqrCmd7VEvSTvvI1K/tkSY8oTBEg87TRscrgmsQyLyOoSswvCqWpvy+VrTfSoabZzVb1XvCH+apA41wHN4BnQYsQzk2sdl75rsn8rhzGiZUWc67K4nqbMbqs1Dxek3u2enFRQlVHbs8xHuBvcqwk5XRkkiCp aaron@ubuntu", "key_options": null, "keyfile": "/home/aaron/.ssh/authorized_keys", "manage_dir": true, "mode": "0600", "owner": "aaron", "path": "/home/aaron/.ssh/authorized_keys", "size": 394, "state": "file", "uid": 1000, "unique": false, "user": "aaron", "validate_certs": true }
咱們利用 ansible 有一個更加方便的內置 SSH 密鑰管理支持來執行咱們的任務,輸入密碼後,獲得以上運行結果說明成功執行。若是兩臺 遠程主機的密碼不相同,執行兩次命令,分別輸入不一樣的密碼便可。
注意 ssh 對 authorized_keys 的權限要求比較嚴格,僅所屬用戶纔有讀寫權限(600)時才生效
到目前爲止 ssh 授信成功了,後續能夠免密碼執行命令了,下面驗證下。
獲取被管理機器的當前時間
(py37env) aaron@ubuntu:~/.ssh$ ansible all -a "date +'%Y-%m-%d %T'" localhost | SUCCESS | rc=0 >> 2018-08-04 15:04:55 192.168.0.111 | SUCCESS | rc=0 >> 2018-08-04 00:04:57 192.168.0.112 | SUCCESS | rc=0 >> 2018-08-04 00:04:57
如今,不須要輸入密碼,便可同時獲取三臺主機的時間,主機的時鐘可能不一致,這是正常現象。
使用 ansible 批量傳文件。
將一個文本文件上傳至遠程主機的用戶 home 目錄中。
先查看遠程主機上用戶 home 目錄上的文件
(py37env) aaron@ubuntu:~$ ansible all -m shell -a "ls ~/*.*" localhost | SUCCESS | rc=0 >> /home/aaron/030303.mp4 /home/aaron/aaa.py /home/aaron/dfasdfasdfad.py /home/aaron/examples.desktop /home/aaron/hello.py /home/aaron/new.py /home/aaron/playbook.retry /home/aaron/playbook.yaml /home/aaron/setting.py /home/aaron/test.py /home/aaron/vimrc.bak_20180719 /home/aaron/你好.txt 192.168.0.111 | SUCCESS | rc=0 >> /home/aaron/examples.desktop 192.168.0.112 | SUCCESS | rc=0 >> /home/aaron/examples.desktop
將 "你好.txt" 上傳至另外兩臺服務器
(py37env) aaron@ubuntu:~$ ansible all -m copy -a "src=/home/aaron/你好.txt dest=/home/aaron" localhost | SUCCESS => { "changed": false, "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/home/aaron/你好.txt", "gid": 1001, "group": "aaron", "mode": "0664", "owner": "aaron", "path": "/home/aaron/你好.txt", "size": 0, "state": "file", "uid": 1001 } 192.168.0.112 | SUCCESS => { "changed": true, "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/home/aaron/你好.txt", "gid": 1000, "group": "aaron", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "mode": "0664", "owner": "aaron", "size": 0, "src": "/home/aaron/.ansible/tmp/ansible-tmp-1533367280.2415307-170986393705436/source", "state": "file", "uid": 1000 } 192.168.0.111 | SUCCESS => { "changed": true, "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", "dest": "/home/aaron/你好.txt", "gid": 1000, "group": "aaron", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "mode": "0664", "owner": "aaron", "size": 0, "src": "/home/aaron/.ansible/tmp/ansible-tmp-1533367280.2476053-270780127291475/source", "state": "file", "uid": 1000 }
能夠看出,localhost 本就有 "你好.txt" 默認不會被覆蓋。從新執行第一條命令驗證。
(py37env) aaron@ubuntu:~$ ansible all -m shell -a "ls ~/*.*" localhost | SUCCESS | rc=0 >> /home/aaron/030303.mp4 /home/aaron/aaa.py /home/aaron/dfasdfasdfad.py /home/aaron/examples.desktop /home/aaron/hello.py /home/aaron/new.py /home/aaron/playbook.retry /home/aaron/playbook.yaml /home/aaron/setting.py /home/aaron/test.py /home/aaron/vimrc.bak_20180719 /home/aaron/你好.txt 192.168.0.112 | SUCCESS | rc=0 >> /home/aaron/examples.desktop /home/aaron/你好.txt 192.168.0.111 | SUCCESS | rc=0 >> /home/aaron/examples.desktop /home/aaron/你好.txt
能夠看出文件已經上傳成功了。
一個優秀的工具必定有着便捷的幫助文檔,ansible 也不例外,前述操做,使用了 ansible 的模塊有 ping,authorized_key,copy,shell等模塊。
若是想知道這些模塊的詳細說明,只須要執行 ansible-doc 模塊名便可。
(py37env) aaron@ubuntu:~$ ansible-doc copy > COPY (/home/aaron/py37env/lib/python3.7/site-packages/ansible/modules/files/copy.py) The `copy' module copies a file from the local or remote machine to a location on the remote machine. Use the [fetch] module to copy files from remote locations to the local box. If you need variable interpolation in copied files, use the [template] module. For Windows targets, use the [win_copy] module instead. * note: This module has a corresponding action plugin. OPTIONS (= is mandatory): - attributes Attributes the file or directory should have. To get supported flags look at the man page for `chattr' on the target system. This string should contain the attributes in the same order as the one displayed by `lsattr'. (Aliases: attr)[Default: (null)] version_added: 2.3 - backup Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly. [Default: no] type: bool version_added: 0.7 ......
ansible 經常使用的模塊及介紹以下:
ping: 主機連通性測試。 command: 在遠程主機上執行命令,並將結果返回。 shell: 在遠程主機上調用 shell 解釋器運行命令,支持 shell 的各類功能。 copy: 將文件複製到遠程主機,同時支持給定內容生成文件和修改權限等. file: 設置文件的屬性,好比建立文件、建立連接文件、刪除文件等。 fetch: 從遠程主機獲取文件到本地。 cron: 管理遠程主機的 crontab 計劃任務。 yum: 用於軟件的安裝。 service: 用於服務程序的管理。 user: 用來管理遠程主機的用戶帳號。 group: 用於在添加或刪除組。 script: 用於將本機的腳本在被管理端的機器上運行. setup: 主要用於收集信息,是經過調用facts組件來實現的.
前述操做對遠程執行的命令都是相同的,那麼能夠同時對不一樣的主機執行不一樣的指令嗎,當讓能夠,這就是 Plakbooks。
借用官方的描述,Playbooks 是 Ansible的配置,部署,編排的語言.他們能夠被描述爲一個須要但願遠程主機執行命令的方案,或者一組IT程序運行的命令集合.若是 Ansible 模塊你是工做室中的工具,那麼 playbooks 就是你設置的方案計劃.
首先查看 ansible-playbook 的幫助命令
(py37env) aaron@ubuntu:~$ ansible-playbook -h Usage: ansible-playbook [options] playbook.yml [playbook2 ...] Runs Ansible playbooks, executing the defined tasks on the targeted hosts. Options: --ask-vault-pass ask for vault password個 -C, --check don't make any changes; instead, try to predict some of the changes that may occur -D, --diff when changing (small) files and templates, show the differences in those files; works great with --check ......
發現,ansible-playbook 須要一個 plauybook.yml 的文件。
yml 文件是 yaml語法格式的文件,咱們使用 YAML 是由於它像 XML 或 JSON 是一種利於人們讀寫的數據格式。此外在大多數變成語言中有使用 YAML 的庫。
對於 Ansible, 每個 YAML 文件都是從一個列表開始。 列表中的每一項都是一個鍵值對, 一般它們被稱爲一個 「哈希」 或 「字典」。 因此, 咱們須要知道如何在 YAML 中編寫列表和字典。
如今 讓咱們寫一個簡單的 playbook
文件名 myplaybook.yml
--- - hosts: master remote_user: aaron tasks: - name: read sys time shell: echo "`date +'%Y-%m-%d %T'`">time.txt - hosts: slave remote_user: aaron tasks: - name: list file shell: ls -ltr>list.txt
上述 yaml 文件分別定義了對兩組主機執行不一樣的 task ,注意縮進格式。
執行 ansible-playbook myplaybook.yml 結果以下:
(py37env) aaron@ubuntu:~$ ansible-playbook myplaybook.yml PLAY [master] ************************************************************************************** TASK [Gathering Facts] ***************************************************************************** ok: [localhost] ok: [192.168.0.111] TASK [read sys time] ******************************************************************************* changed: [localhost] changed: [192.168.0.111] PLAY [slave] *************************************************************************************** TASK [Gathering Facts] ***************************************************************************** ok: [192.168.0.112] TASK [list file] *********************************************************************************** changed: [192.168.0.112] PLAY RECAP ***************************************************************************************** 192.168.0.111 : ok=2 changed=1 unreachable=0 failed=0 192.168.0.112 : ok=2 changed=1 unreachable=0 failed=0 localhost : ok=2 changed=1 unreachable=0 failed=0
說明3臺主機上的任務已成功執行。
當有許多主機許多任務要執行時,能夠指定併發進程數
ansible-playbook myplaybook.yml -f 10 # 表示由 10 個併發的進程來執行任務
上述僅爲 ansible-playbook 的冰山一角,ansible-playbook 還能夠實現 Handlers,當在發生改變時執行的相應的操做,最佳的應用場景是用來重啓服務,或者觸發系統重啓操做。
配置的 yaml 文件支持 Ansible-Pull 進行拉取配置等。
詳見 官方文檔 http://www.ansible.com.cn/docs/playbooks_intro.html
THE END