♣一:ansible的主要功能html
咱們如今的企業環境都是串聯起來提供服務能力,運行在一系列分佈式的計算資 源上並用各類不一樣的網絡協議進行通訊,當服務平臺隨着業務量增長鬚要橫向擴容的狀況下,不得不面臨一個問題就是N臺服務器的高效率服務部署和集中化的配置管理。基於此類狀況ansible就能很好解決。node
在實際的運維中咱們劃分爲6個場景:python
在上面6個場景中,ansible能很好勝任前面4個場景。mysql
在經常使用相似的自動化運維工具中ansible是有絕對優點的。linux
ansible首先基於python開發,模塊衆多,能支持二次開發,並且最重要的不須要代理服務,直接在主控端安裝便可,被控端都是基於openssh遠程來控制操做,另外支持冪等性(一個任務執行1遍和n遍效果是同樣的,不會由於執行屢次致使的意外狀況),api接口支持任何語言來寫模塊,ansible不是以傳統的服務方式運行的,不須要常駐內存等資源,只用使用ansible命令的時候纔會用到。nginx
saltstack,也是基於python開發,可是要使用必須在被操做的機器上也裝上saltstack服務,並且嚴格分主控端和被控端。git
puppet,功能強大,配置複雜,適合超大型的環境,基於的開發語言是ruby,想作二次開發難度大。github
ansible的rpm安裝,EPEL源。web
yum install ansible正則表達式
編譯安裝:
yum -y install python-jinja2 PyYAML python-paramiko python-bable python-crypto
tar -zxvf ansible1.5.4.tar.gz
cd ansible
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
git方式安裝:
git clone git://github.com/ansible/ansible.git/ansible.git --recursive(此方法安裝的版本都是最新的版本,特定版本的不建議此安裝方式)
cd ./ansible
source ./hacking/env-setup
pip安裝:
yun -y install python-pip python-devel
yum -y install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
安裝以後執行ansible --version能看到版本就爲成功。
(注:只須要安裝主控端,被控端不須要安裝,可是被控端要安裝openssh遠程服務)
[root@ansible ypc.soft]# ansible --version ansible 2.6.8 #看到版本是2.6.8 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.6/site-packages/ansible executable location = /usr/bin/ansible #依賴的python版本 python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
配置文件:
/etc/ansible/ansible.cfg (主配置文件,配置ansible的工做特性)
#inventory = /etc/ansible/hosts 主機列表清單配置文件位置 #library = /usr/share/my_modules/ 庫文件存放位置 #remote_tmp = ~/.ansible/tmp 臨時py命令存放遠程主機的目錄 ansible的工做原理是當用戶執行命令,那麼ansible會產生一個py的腳本,這個腳本里面記錄的是用戶的執行命令,而後經過ssh遠程放到被控端家目錄.ansible/tmp/下,執行完成以後.ansible/tmp就會自動刪除。 #forks = 5 默認併發數,ansible在執行一個任務的時候不是一臺機器一臺機器去執行的,是同一時間執行5臺機器,固然機器配置好的時候能夠調整至更大的指,通常默認便可 #sudo_user = root 默認sudo用戶。 #ask_sudo_pass = True 每次執行ansible命令是否詢問ssh密碼 #remote_port = 22 默認ssh遠程端口是22 log_path = /var/log/ansible.log 日誌文件,ansible默認是沒有開啓日誌記錄的,這個要取消註釋 host_key_checking = False 檢查服務的host_key,建議取消註釋
/etc/ansible/hosts (主機清單)
例如我主控端是(192.168.219.135) 我須要在主控端增長主機的ip地址 host配置以下: 192.168.219.136 192.168.219.137 在文件末尾增長兩臺被控端機器的ip,可是這種方式咱們每次執行都須要在命令行輸入兩臺機器的ip地址,十分不方便。 這個時候咱們就能夠寫成組的方式: host配置以下 [web] 192.168.219.136 192.168.219.137 在ip前面加上一個組名用中括號定義便可
/etc/ansible/roles (存放角色的目錄)
程序
/usr/bin/ansible (主程序,臨時命令執行工具)
/usr/bin/ansible-doc (查看配置文檔,模塊功能查看工具)
/usr/bin/ansible-galaxy (下載/上傳優秀代碼或roles模塊的官網平臺)
/usr/bin/ansible-playbook (定製自動化任務,編排劇本工具)
/usr/bin/ansible-vault (文件加密工具)
/usr/bin/ansible-console (基於console界面與用戶交互的執行工具)
/usr/bin/ansible-pull (遠程執行命令工具)
ansible相關命令:
ansible-doc(至關於men幫助,主要查看模塊的詳細使用方法)
ansible-doc ping (查看指定模塊的使用方法和參數) > PING (/usr/lib/python2.6/site-packages/ansible/modules/system/ping.py) [root@ansible .ssh]# ansible-doc -l (列出全部模塊) a10_server Manage A10 Networks AX... a10_server_axapi3 Manage A10 Networks AX... [root@ansible .ssh]# ansible-doc -s ping (查看指定模塊的用法,簡易模式顯示) - name: Try to connect to host, verify a usable python and return `pong' on suc ping:
ansible-playbook
ansible-vault
ansible-console
ansible-galaxy
ansible-pull
ansible的參數:
--version(顯示版本號),-v(詳細過程)-vv,-vvv(最詳細),-k輸入ssh鏈接密碼,默認key驗證,--list(顯示主機列表),-K(輸入sudo的密碼),-C(檢查並不執行),-T(執行命令超時的時間,默認10s),-u(指定用戶鏈接),-b(代替舊版本的sudo)
基本語法:
ansible (主機清單組名) -m (模塊名) -a (執行參數或命令)
ansible的主機模式:
[root@ansible .ssh]# ansible "w*" -m ping 192.168.219.137 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.219.136 | SUCCESS => { "changed": false, "ping": "pong" } [root@ansible .ssh]# [root@ansible .ssh]# ansible 192.168.219.* -m ping 192.168.219.136 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.219.137 | SUCCESS => { "changed": false, "ping": "pong" } [root@ansible .ssh]#
[root@ansible .ssh]# ansible "web:&dbserver" -m ping 192.168.219.136 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.219.137 | SUCCESS => { "changed": false, "ping": "pong" } [root@ansible .ssh]#
ansible "web:!dbserver" -m ping
固然也支持正則表達式,不過極少用。
ping模塊
[root@ansible ansible]# ansible web -m ping -k SSH password: 192.168.219.137 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.219.136 | SUCCESS => { "changed": false, "ping": "pong" } [root@ansible ansible]# web是咱們以前配置的組名 -m後面更上模塊名 -k是指定輸入ssh用戶名的密碼,固然若是是基於key驗證的ssh就不須要-k參數 能夠看到結果列出了主機名,ping以後對端迴應pong就表明執行成功了 使用ssh-keygen命令產生公鑰,使用ssh-copy-id 192.168.219.136和ssh-copy-id 192.168.219.137把公鑰傳輸到被控端便可完成基於key驗證。 [root@ansible ansible]# ansible web -m ping 192.168.219.137 | SUCCESS => { "changed": false, "ping": "pong" } 192.168.219.136 | SUCCESS => { "changed": false, "ping": "pong" } [root@ansible ansible]# -k參數就不須要加了,也不須要輸入密碼了
上面咱們說ansible是基於openssh來進行遠程操做的,若是新環境的ip第一次鏈接的話,會有提示不可鏈接的錯誤,這個是由於主控端並無和被控端進行過鏈接,在正常的狀況下若是你使用ssh遠程登陸對端機器都須要輸入下yes才能鏈接,ansible走的是ssh的遠程,因此也須要經過ssh的yes驗證以後才能不會出錯,固然這個問題的前提是沒有基於key驗證的狀況下,也就是加了-k參數的狀況下會出現,那麼咱們實際環境中確定會存在新環境接入的時候出現首次驗證的問題,咱們還能夠經過ansible的配置文件取消首次驗證基於key的驗證問題。
# uncomment this to disable SSH key host checking host_key_checking = False 將host_key_checking = False這行取消註釋
非root用戶的使用ansible操做
[root@ansible .ssh]# ansible web -m command -a 'ls /root' -u mysql 192.168.219.137 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n", "unreachable": true } 192.168.219.136 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).\r\n", "unreachable": true } 能夠看到沒有進行sudo受權的狀況下,是會報錯的,提示須要輸入sudo用戶密碼 [root@ansible .ssh]# ansible web -m command -a 'ls /root' -u mysql -k -b -K SSH password: SUDO password[defaults to SSH password]: #加上-K輸入sudo密碼 192.168.219.137 | FAILED | rc=2 >> ls: cannot open directory /root: Permission deniednon-zero return code 192.168.219.136 | FAILED | rc=2 >> ls: cannot open directory /root: Permission deniednon-zero return code 如今又會出現另一個問題就是mysql用戶沒有在控制端sudo受權過 到控制端執行visudo ## Allows people in group wheel to run all commands %wheel ALL=(ALL) ALL 把wheel這行註釋取消掉 而後在命令行執行命令,將mysql用戶加到組裏面去 [root@web1 ~]# usermod -aG wheel mysql 同時SUDO password[defaults to SSH password]:這個sudo的密碼我不想輸入,也能夠在visudo裏面取消註釋: ## Same thing without a password %wheel ALL=(ALL) NOPASSWD: ALL [root@ansible .ssh]# ansible web -m command -a 'ls /root' -u mysql -k -b SSH password: 192.168.219.137 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog Music Pictures Public Templates Videos 192.168.219.136 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog Music Pictures Public Templates Videos #能夠看到非root用戶登陸須要那些操做
ansible默認模塊是command,若是是簡單的操做不須要在-m後面指定command模塊,直接-m便可。
上面咱們已經使用過了ping模塊,因ansible模塊已經有接近2千個模塊了,並且還在增加,咱們只學一些經常使用的模塊,後續有須要用到其餘模塊直接查看幫助也能完成。
shell模塊:和command類似,用於執行shell命令。
[root@ansible ~]# ansible-doc -s shell - name: Execute commands in nodes. shell: chdir: # cd into this directory before running the command creates: # a filename, when it already exists, this step will *not* be run. executable: # change the shell used to execute the command. Should be an absolute path to the executable. free_form: # (required) The shell module takes a free form command to run, as a string. There's not an actual option named "free form". See the examples! removes: # a filename, when it does not exist, this step will *not* be run. stdin: # Set the stdin of the command directly to the specified value. warn: # if command warnings are on in ansible.cfg, do not warn about this particular line if set to no/false. [root@ansible ~]#
因shell模塊不是默認模塊,-m後面就必須指定模塊名稱了。
ansible all -m shell -a 'echo $HOSTNAME'
ansible all -m shell -a 'mkdir -r /root/ansible'
shell模塊能完成command不能完成的操做,好比特殊符號等,並且command能完成的shell模塊也能完成。
script模塊:
[root@ansible ~]# ansible-doc -s script - name: Runs a local script on a remote node after transferring it script: chdir: # cd into this directory on the remote node before running the script creates: # a filename, when it already exists, this step will *not* be run. decrypt: # This option controls the autodecryption of source files using vault. executable: # Name or path of a executable to invoke the script with free_form: # (required) Path to the local script file followed by optional arguments. There is no parameter actually named 'free form'; see the examples! removes: # a filename, when it does not exist, this step will *not* be run. [root@ansible ~]#
在傳統的模式下,咱們要在被控機執行本機(主控端)上一個寫好的腳本,及時有ansible也須要把腳本傳輸到被控機上,而後執行ansible的shell模塊來執行腳本,那麼前面的傳輸的操做就會變得有點麻煩。並且不還不能肯定全部機器傳輸的時候都能給到執行權限,這樣的狀況下,你還得給這些被控端機器上腳本執行權限。
script模塊直接在本機雲信,無需傳輸。
[root@ansible ansible.test]# pwd /home/ansible.test [root@ansible ansible.test]# cat test.sh #!/bin/bash hostname [root@ansible ansible.test]# ansible all -m script -a '/home/ansible.test/test.sh' 192.168.219.137 | SUCCESS => { "changed": true, "rc": 0, "stderr": "Shared connection to 192.168.219.137 closed.\r\n", "stderr_lines": [ "Shared connection to 192.168.219.137 closed." ], "stdout": "web2\r\n", "stdout_lines": [ "web2" ] } 192.168.219.136 | SUCCESS => { "changed": true, "rc": 0, "stderr": "Shared connection to 192.168.219.136 closed.\r\n", "stderr_lines": [ "Shared connection to 192.168.219.136 closed." ], "stdout": "web1\r\n", "stdout_lines": [ "web1" ] } [root@ansible ansible.test]#
copy模塊:
copy模塊用來批量傳輸文件,例如服務的配置文件等。
ansible db -m copy -a 'src=源路徑下文件 dest=目標路徑(路徑必須存在)'
[root@ansible ansible.test]# ansible-doc -s copy - name: Copies files to remote locations copy: 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'. backup: # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly. checksum: # SHA1 checksum of the file being transferred. Used to validate that the copy of the file was successful. If this is not provided, ansible will use the local calculated checksum of the src file. content: # When used instead of `src', sets the contents of a file directly to the specified value. For anything advanced or with formatting also look at the template module. decrypt: # This option controls the autodecryption of source files using vault. dest: # (required) Remote absolute path where the file should be copied to. If `src' is a directory, this must be a directory too. If `dest' is a nonexistent path and if either `dest' ends with "/" or `src' is a directory, `dest' is created. If `src' and `dest' are files, the parent directory of `dest' isn't created: the task fails if it doesn't already exist. directory_mode: # When doing a recursive copy set the mode for the directories. If this is not set we will use the system defaults. The mode is only set on directories which are newly created, and will not affect those that already existed. follow: # This flag indicates that filesystem links in the destination, if they exist, should be followed. force: # the default is `yes', which will replace the remote file when contents are different than the source. If `no', the file will only be transferred if the destination does not exist. group: # Name of the group that should own the file/directory, as would be fed to `chown'. local_follow: # This flag indicates that filesystem links in the source tree, if they exist, should be followed. mode: # Mode the file or directory should be. For those used to `/usr/bin/chmod' remember that modes are actually octal numbers. You must either specify the leading zero so that Ansible's YAML parser knows it is an octal number (like `0644' or `01777') or quote it (like `'644'' or `'0644'' so Ansible receives a string and can do its own conversion from string into number. Giving Ansible a number without following one of these rules will end up with a decimal number which will have unexpected results. As of version 1.8, the mode may be specified as a symbolic mode (for example, `u+rwx' or `u=rw,g=r,o=r'). As of version 2.3, the mode may also be the special string `preserve'. `preserve' means that the file will be given the same permissions as the source file. owner: # Name of the user that should own the file/directory, as would be fed to `chown'. remote_src: # If `no', it will search for `src' at originating/master machine. If `yes' it will go to the remote/target machine for the `src'. Default is `no'. Currently `remote_src' does not support recursive copying. `remote_src' only works with `mode=preserve' as of version 2.6. selevel: # Level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the `range'. `_default' feature works as for `seuser'. serole: # Role part of SELinux file context, `_default' feature works as for `seuser'. setype: # Type part of SELinux file context, `_default' feature works as for `seuser'. seuser: # User part of SELinux file context. Will default to system policy, if applicable. If set to `_default', it will use the `user' portion of the policy if available. src: # Local path to a file to copy to the remote server; can be absolute or relative. If path is a directory, it is copied recursively. In this case, if path ends with "/", only inside contents of that directory are copied to destination. Otherwise, if it does not end with "/", the directory itself with all contents is copied. This behavior is similar to Rsync. unsafe_writes: # Normally this module uses atomic operations to prevent data corruption or inconsistent reads from the target files, sometimes systems are configured or just broken in ways that prevent this. One example are docker mounted files, they cannot be updated atomically and can only be done in an unsafe manner. This boolean option allows ansible to fall back to unsafe methods of updating files for those cases in which you do not have any other choice. Be aware that this is subject to race conditions and can lead to data corruption. validate: # The validation command to run before copying into place. The path to the file to validate is passed in via '%s' which must be present as in the example below. The command is passed securely so shell features like expansion and pipes won't work. (END)
1 backup:在覆蓋以前將原文件備份,備份文件包含時間信息。有兩個選項:yes|no 2 content:用於替代"src",能夠直接設定指定文件的值 3 dest:必選項。要將源文件複製到的遠程主機的絕對路徑,若是源文件是一個目錄,那麼該路徑也必須是個目錄 4 directory_mode:遞歸的設定目錄的權限,默認爲系統默認權限 5 force:若是目標主機包含該文件,但內容不一樣,若是設置爲yes,則強制覆蓋,若是爲no,則只有當目標主機的目標位置不存在該文件時,才複製。默認爲yes 6 others:全部的file模塊裏的選項均可以在這裏使用 7 src:要複製到遠程主機的文件在本地的地址,能夠是絕對路徑,也能夠是相對路徑。若是路徑是一個目錄,它將遞歸複製。在這種狀況下,若是路徑使用"/"來結尾,則只複製目錄裏的內容,若是沒有使用"/"來結尾,則包含目錄在內的整個內容所有複製,相似於rsync。 8 validate :The validation command to run before copying into place. The path to the file to validate is passed in via '%s' which must be present as in the visudo example below.
[root@ansible ansible.test]# ansible all -m copy -a 'src=/home/ansible.test/copy_test.conf dest=/home/copy_test.conf' 192.168.219.136 | SUCCESS => { "changed": true, "checksum": "5ffd53c0987ac64d0a82a8c97978afe8f02d7b5a", "dest": "/home/copy_test.conf", "gid": 0, "group": "root", "md5sum": "40488fea7fe48f99ea02e86166a0bc9d", "mode": "0644", "owner": "root", "size": 28, "src": "/root/.ansible/tmp/ansible-tmp-1550554363.16-165811746367830/source", "state": "file", "uid": 0 } 192.168.219.137 | SUCCESS => { "changed": true, "checksum": "5ffd53c0987ac64d0a82a8c97978afe8f02d7b5a", "dest": "/home/copy_test.conf", "gid": 0, "group": "root", "md5sum": "40488fea7fe48f99ea02e86166a0bc9d", "mode": "0644", "owner": "root", "size": 28, "src": "/root/.ansible/tmp/ansible-tmp-1550554363.16-162669317189243/source", "state": "file", "uid": 0 } [root@ansible ansible.test]# ansible all -a 'ls /home' 192.168.219.136 | SUCCESS | rc=0 >> centos12 copy_test.conf mysql ypc.soft 192.168.219.137 | SUCCESS | rc=0 >> centos13 copy_test.conf mysql [root@ansible ansible.test]#
fetch模塊:
既然咱們能將主控端的文件拷貝到被控端機器上,ansible固然也提供了能夠將被控端機器上文件抓取到主控端的功能,例如咱們須要把被控端的日誌等文件抓取到主控端統一進行分析。
注:fetch模塊只能一次抓取一個文件且不能是目錄。固然不是沒有辦法,能夠經過shell模塊把被控端目錄或者多個文件進行打包在抓取過來。
[root@ansible ansible.test]# ansible-doc -s fetch - name: Fetches a file from remote nodes fetch: dest: # (required) A directory to save the file into. For example, if the `dest' directory is `/backup' a `src' file named `/etc/profile' on host `host.example.com', would be saved into `/backup/host.example.com/etc/profile' fail_on_missing: # When set to 'yes', the task will fail if the remote file cannot be read for any reason. Prior to Ansible-2.5, setting this would only fail if the source file was missing. The default was changed to "yes" in Ansible-2.5. flat: # Allows you to override the default behavior of appending hostname/path/to/file to the destination. If dest ends with '/', it will use the basename of the source file, similar to the copy module. Obviously this is only handy if the filenames are unique. src: # (required) The file on the remote system to fetch. This `must' be a file, not a directory. Recursive fetching may be supported in a later release. validate_checksum: # Verify that the source and destination checksums match after the files are fetched. [root@ansible ansible.test]#
[root@ansible ansible.test]# ansible all -m fetch -a 'src=/etc/passwd dest=/home/ansible.test/test' 192.168.219.137 | SUCCESS => { "changed": true, "checksum": "edf3216846dae3f593314cf07b8d8f328e58f067", "dest": "/home/ansible.test/test/192.168.219.137/etc/passwd", "md5sum": "86e07804c44a27941e1fc798a5779756", "remote_checksum": "edf3216846dae3f593314cf07b8d8f328e58f067", "remote_md5sum": null } 192.168.219.136 | SUCCESS => { "changed": true, "checksum": "65a433c99ff5ce054264be87594828c83989aa0e", "dest": "/home/ansible.test/test/192.168.219.136/etc/passwd", "md5sum": "891484511715765f25fd7c4fa67f8288", "remote_checksum": "65a433c99ff5ce054264be87594828c83989aa0e", "remote_md5sum": null } [root@ansible ansible.test]# tree test test ├── 192.168.219.136 │ └── etc │ └── passwd └── 192.168.219.137 └── etc └── passwd 4 directories, 2 files [root@ansible ansible.test]# cd test [root@ansible test]# ls 192.168.219.136 192.168.219.137 [root@ansible test]# cd 192.168.219.136 [root@ansible 192.168.219.136]# ls etc [root@ansible 192.168.219.136]# cd etc/ [root@ansible etc]# ls passwd [root@ansible etc]# #能夠看到在test下各自建立了一個屬於被控端機器ip的目錄,抓取的文件都放在這個目錄下面,方便區分
[root@ansible etc]# ansible all -m shell -a 'tar Jcf log.tar.xz /var/log/*.log' [WARNING]: Consider using the unarchive module rather than running tar. If you need to use command because unarchive is insufficient you can add warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this message. 192.168.219.137 | SUCCESS | rc=0 >> tar: Removing leading `/' from member names 192.168.219.136 | SUCCESS | rc=0 >> tar: Removing leading `/' from member names [root@ansible etc]# ansible all -m shell -a 'ls -h' 192.168.219.136 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos 192.168.219.137 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos [root@ansible etc]# ansible all -m shell -a 'pwd' 192.168.219.137 | SUCCESS | rc=0 >> /root 192.168.219.136 | SUCCESS | rc=0 >> /root [root@ansible etc]# ansible all -m fetch -a 'src=/root/log.tar.xz dest=/home/ansible.test/test/' 192.168.219.136 | SUCCESS => { "changed": true, "checksum": "893ff89ed3394cf7a94e6b4d2aca694a7b8f4f9e", "dest": "/home/ansible.test/test/192.168.219.136/root/log.tar.xz", "md5sum": "bc8e9ac43907b51c4e1e31b786e1e1ef", "remote_checksum": "893ff89ed3394cf7a94e6b4d2aca694a7b8f4f9e", "remote_md5sum": null } 192.168.219.137 | SUCCESS => { "changed": true, "checksum": "9662827bc0da5854fe108a9847e1df4986388cfd", "dest": "/home/ansible.test/test/192.168.219.137/root/log.tar.xz", "md5sum": "9216f8c9dd0e41058d6ef3ca77f1919e", "remote_checksum": "9662827bc0da5854fe108a9847e1df4986388cfd", "remote_md5sum": null } [root@ansible ansible.test]# tree test test ├── 192.168.219.136 │ ├── etc │ │ └── passwd │ └── root │ └── log.tar.xz └── 192.168.219.137 ├── etc │ └── passwd └── root └── log.tar.xz 6 directories, 4 files [root@ansible ansible.test]# 能夠看到多個文件已經被抓取過來了
cron模塊:計劃任務模塊
cron模塊格式:
ansible 主機清單名 -m cron -a 'minute="分鐘" hour="時" day="日" month="月" weekday="周" job="計劃任務內容" name="計劃任務名稱(必填)" state="添加(present默認)和absent(移除)"'
[root@ansible ~]# ansible-doc -s cron - name: Manage cron.d and crontab entries cron: backup: # If set, create a backup of the crontab before it is modified. The location of the backup is returned in the `backup_file' variable by this module. cron_file: # If specified, uses this file instead of an individual user's crontab. If this is a relative path, it is interpreted with respect to /etc/cron.d. (If it is absolute, it will typically be /etc/crontab). Many linux distros expect (and some require) the filename portion to consist solely of upper- and lower-case letters, digits, underscores, and hyphens. To use the `cron_file' parameter you must specify the `user' as well. day: # Day of the month the job should run ( 1-31, *, */2, etc ) disabled: # If the job should be disabled (commented out) in the crontab. Only has effect if `state=present'. env: # If set, manages a crontab's environment variable. New variables are added on top of crontab. "name" and "value" parameters are the name and the value of environment variable. hour: # Hour when the job should run ( 0-23, *, */2, etc ) insertafter: # Used with `state=present' and `env'. If specified, the environment variable will be inserted after the declaration of specified environment variable. insertbefore: # Used with `state=present' and `env'. If specified, the environment variable will be inserted before the declaration of specified environment variable. job: # The command to execute or, if env is set, the value of environment variable. The command should not contain line breaks. Required if state=present. minute: # Minute when the job should run ( 0-59, *, */2, etc ) month: # Month of the year the job should run ( 1-12, *, */2, etc ) name: # Description of a crontab entry or, if env is set, the name of environment variable. Required if state=absent. Note that if name is not set and state=present, then a new crontab entry will always be created, regardless of existing ones. reboot: # If the job should be run at reboot. This option is deprecated. Users should use special_time. special_time: # Special time specification nickname. state: # Whether to ensure the job or environment variable is present or absent. user: # The specific user whose crontab should be modified. weekday: # Day of the week that the job should run ( 0-6 for Sunday-Saturday, *, etc ) [root@ansible ~]# 1 backup:對遠程主機上的原任務計劃內容修改以前作備份 2 cron_file:若是指定該選項,則用該文件替換遠程主機上的cron.d目錄下的用戶的任務計劃 3 day:日(1-31,*,*/2,……) 4 hour:小時(0-23,*,*/2,……) 5 minute:分鐘(0-59,*,*/2,……) 6 month:月(1-12,*,*/2,……) 7 weekday:周(0-7,*,……) 8 job:要執行的任務,依賴於state=present 9 name:該任務的描述 10 special_time:指定何時執行,參數:reboot,yearly,annually,monthly,weekly,daily,hourly 11 state:確認該任務計劃是建立仍是刪除 12 user:以哪一個用戶的身份執行
[root@ansible ~]# ansible all -m cron -a 'minute="*/1" job="/bin/echo hello ansible" name="test cron job" state="present"' 192.168.219.137 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "kk", "test cron job" ] } 192.168.219.136 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "kk", "test cron job" ] } [root@ansible ~]# 136: [root@web1 ~]# crontab -l #Ansible: test cron job */1 * * * * /bin/echo hello ansible [root@web1 ~]# 137: #Ansible: test cron job */1 * * * * /bin/echo hello ansible You have new mail in /var/spool/mail/root [root@web2 ~]#
[root@ansible ~]# ansible all -m cron -a 'minute="*/1" job="/bin/echo hello ansible" name="test cron job" state="absent"' 192.168.219.137 | SUCCESS => { "changed": true, "envs": [], "jobs": [] } 192.168.219.136 | SUCCESS => { "changed": true, "envs": [], "jobs": [] } [root@ansible ~]# 136: [root@web1 ~]# crontab -l You have new mail in /var/spool/mail/root [root@web1 ~]# [root@web2 ~]# crontab -l You have new mail in /var/spool/mail/root [root@web2 ~]#
[root@ansible ~]# ansible all -m cron -a 'disabled=yes job="/usr/bin/wall FBI warning" name=kk' 192.168.219.136 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "test cron job", "kk" ] } 192.168.219.137 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "test cron job", "kk" ] } [root@ansible ~]# ansible all -m shell -a 'crontab -l' 192.168.219.136 | SUCCESS | rc=0 >> #Ansible: test cron job */1 * * * * /bin/echo hello ansible #Ansible: kk #* * * * * /usr/bin/wall FBI warning 192.168.219.137 | SUCCESS | rc=0 >> #Ansible: test cron job */1 * * * * /bin/echo hello ansible #Ansible: kk #* * * * * /usr/bin/wall FBI warning 發現新加的計劃任務就是註釋的
[root@ansible ~]# ansible all -m cron -a 'disabled=no job="/usr/bin/wall FBI warning" name=kk' 192.168.219.136 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "test cron job", "kk" ] } 192.168.219.137 | SUCCESS => { "changed": true, "envs": [], "jobs": [ "test cron job", "kk" ] } [root@ansible ~]# ansible all -m shell -a 'crontab -l' 192.168.219.136 | SUCCESS | rc=0 >> #Ansible: test cron job */1 * * * * /bin/echo hello ansible #Ansible: kk * * * * * /usr/bin/wall FBI warning 192.168.219.137 | SUCCESS | rc=0 >> #Ansible: test cron job */1 * * * * /bin/echo hello ansible #Ansible: kk * * * * * /usr/bin/wall FBI warning 能夠看到計劃任務註釋取消掉了,disable後面能夠接yes/no,還能夠是ture和flase
yum模塊:
批量經過yum安裝服務便可使用yum模塊。
[root@ansible ~]# ansible-doc -s yum - name: Manages packages with the `yum' package manager yum: allow_downgrade: # Specify if the named package and version is allowed to downgrade a maybe already installed higher version of that package. Note that setting allow_downgrade=True can make this module behave in a non-idempotent way. The task could end up with a set of packages that does not match the complete list of specified packages to install (because dependencies between the downgraded package and others can cause changes to the packages which were in the earlier transaction). bugfix: # If set to `yes', and `state=latest' then only installs updates that have been marked bugfix related. conf_file: # The remote yum configuration file to use for the transaction. disable_gpg_check: # Whether to disable the GPG checking of signatures of packages being installed. Has an effect only if state is `present' or `latest'. disable_plugin: # `Plugin' name to disable for the install/update operation. The disabled plugins will not persist beyond the transaction. disablerepo: # `Repoid' of repositories to disable for the install/update operation. These repos will not persist beyond the transaction. When specifying multiple repos, separate them with a ",". enable_plugin: # `Plugin' name to enable for the install/update operation. The enabled plugin will not persist beyond the transaction. enablerepo: # `Repoid' of repositories to enable for the install/update operation. These repos will not persist beyond the transaction. When specifying multiple repos, separate them with a ",". exclude: # Package name(s) to exclude when state=present, or latest installroot: # Specifies an alternative installroot, relative to which all packages will be installed. list: # Package name to run the equivalent of yum list <package> against. In addition to listing packages, use can also list the following: `installed', `updates', `available' and `repos'. name: # A package name or package specifier with version, like `name-1.0'. If a previous version is specified, the task also needs to turn `allow_downgrade' on. See the `allow_downgrade' documentation for caveats with downgrading packages. When using state=latest, this can be '*' which means run `yum -y update'. You can also pass a url or a local path to a rpm file (using state=present). To operate on several packages this can accept a comma separated list of packages or (as of 2.0) a list of packages. security: # If set to `yes', and `state=latest' then only installs updates that have been marked security related. skip_broken: # Resolve depsolve problems by removing packages that are causing problems from the trans‐ action. 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. update_cache: # Force yum to check if cache is out of date and redownload if needed. Has an effect only if state is `present' or `latest'. update_only: # When using latest, only update installed packages. Do not install packages. Has an effect only if state is `latest' validate_certs: # This only applies if using a https url as the source of the rpm. e.g. for localinstall. If set to `no', the SSL certificates will not be validated. This should only set to `no' used on personally controlled sites using self-signed certificates as it avoids verifying the source site. Prior to 2.1 the code worked as if this was set to `yes'. (END)
name參數:必須參數,用於指定要操做的惟一的倉庫ID,也就是」.repo」配置文件中每一個倉庫對應的」中括號」內的倉庫ID。
baseurl參數:此參數用於設置 yum 倉庫的 baseurl。
description參數:此參數用於設置倉庫的註釋信息,也就是」.repo」配置文件中每一個倉庫對應的」name字段」對應的內容。
file參數:此參數用於設置倉庫的配置文件名稱,即設置」.repo」配置文件的文件名前綴,在不使用此參數的狀況下,默認以 name 參數的倉庫ID做爲」.repo」配置文件的文件名前綴,同一個」.repo」 配置文件中能夠存在多個 yum 源。
enabled參數:此參數用於設置是否激活對應的 yum 源,此參數默認值爲 yes,表示啓用對應的 yum 源,設置爲 no 表示不啓用對應的 yum 源。
gpgcheck參數:此參數用於設置是否開啓 rpm 包驗證功能,默認值爲 no,表示不啓用包驗證,設置爲 yes 表示開啓包驗證功能。
gpgcakey參數:當 gpgcheck 參數設置爲 yes 時,須要使用此參數指定驗證包所需的公鑰。
state參數:默認值爲 present,當值設置爲 absent 時,表示刪除對應的 yum 源。
卸載httpd服務 [root@ansible ~]# ansible all -m yum -a 'state=removed name=httpd' 192.168.219.136 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Remove Process\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.2.15-69.el6.centos will be erased\n--> Processing Dependency: httpd >= 2.2.0 for package: gnome-user-share-2.28.2-3.el6.x86_64\n--> Running transaction check\n---> Package gnome-user-share.x86_64 0:2.28.2-3.el6 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nRemoving:\n httpd x86_64 2.2.15-69.el6.centos\n @base 3.0 M\nRemoving for dependencies:\n gnome-user-share\n x86_64 2.28.2-3.el6 @anaconda-CentOS-201508042137.x86_64/6.7 1.1 M\n\nTransaction Summary\n================================================================================\nRemove 2 Package(s)\n\nInstalled size: 4.1 M\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Erasing : gnome-user-share-2.28.2-3.el6.x86_64 1/2 \n\r Erasing : httpd-2.2.15-69.el6.centos.x86_64 2/2 \n\r Verifying : gnome-user-share-2.28.2-3.el6.x86_64 1/2 \n\r Verifying : httpd-2.2.15-69.el6.centos.x86_64 2/2 \n\nRemoved:\n httpd.x86_64 0:2.2.15-69.el6.centos \n\nDependency Removed:\n gnome-user-share.x86_64 0:2.28.2-3.el6 \n\nComplete!\n" ] } 192.168.219.137 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Remove Process\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.2.15-69.el6.centos will be erased\n--> Processing Dependency: httpd >= 2.2.0 for package: gnome-user-share-2.28.2-3.el6.x86_64\n--> Running transaction check\n---> Package gnome-user-share.x86_64 0:2.28.2-3.el6 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nRemoving:\n httpd x86_64 2.2.15-69.el6.centos\n @base 3.0 M\nRemoving for dependencies:\n gnome-user-share\n x86_64 2.28.2-3.el6 @anaconda-CentOS-201508042137.x86_64/6.7 1.1 M\n\nTransaction Summary\n================================================================================\nRemove 2 Package(s)\n\nInstalled size: 4.1 M\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Erasing : gnome-user-share-2.28.2-3.el6.x86_64 1/2 \n\r Erasing : httpd-2.2.15-69.el6.centos.x86_64 2/2 \n\r Verifying : gnome-user-share-2.28.2-3.el6.x86_64 1/2 \n\r Verifying : httpd-2.2.15-69.el6.centos.x86_64 2/2 \n\nRemoved:\n httpd.x86_64 0:2.2.15-69.el6.centos \n\nDependency Removed:\n gnome-user-share.x86_64 0:2.28.2-3.el6 \n\nComplete!\n" ] } [root@ansible ~]# ansible all -m shell -a 'httpd -v' 192.168.219.137 | FAILED | rc=127 >> /bin/sh: httpd: command not foundnon-zero return code 192.168.219.136 | FAILED | rc=127 >> /bin/sh: httpd: command not foundnon-zero return code 安裝httpd服務 [root@ansible ~]# ansible all -m yum -a 'state=present name=httpd' 192.168.219.137 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Install Process\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * epel: mirrors.huaweicloud.com\n * extras: mirrors.cn99.com\n * updates: mirror.bit.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.2.15-69.el6.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.2.15-69.el6.centos base 836 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package(s)\n\nTotal download size: 836 k\nInstalled size: 3.0 M\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Installing : httpd-2.2.15-69.el6.centos.x86_64 1/1 \n\r Verifying : httpd-2.2.15-69.el6.centos.x86_64 1/1 \n\nInstalled:\n httpd.x86_64 0:2.2.15-69.el6.centos \n\nComplete!\n" ] } 192.168.219.136 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Install Process\nLoading mirror speeds from cached hostfile\n * base: mirrors.cqu.edu.cn\n * epel: mirrors.yun-idc.com\n * extras: mirrors.cqu.edu.cn\n * updates: mirrors.cqu.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.2.15-69.el6.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.2.15-69.el6.centos base 836 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package(s)\n\nTotal download size: 836 k\nInstalled size: 3.0 M\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Installing : httpd-2.2.15-69.el6.centos.x86_64 1/1 \n\r Verifying : httpd-2.2.15-69.el6.centos.x86_64 1/1 \n\nInstalled:\n httpd.x86_64 0:2.2.15-69.el6.centos \n\nComplete!\n" ] } [root@ansible ~]# ansible all -m shell -a 'httpd -v' 192.168.219.137 | SUCCESS | rc=0 >> Server version: Apache/2.2.15 (Unix) Server built: Jun 19 2018 15:45:13 192.168.219.136 | SUCCESS | rc=0 >> Server version: Apache/2.2.15 (Unix) Server built: Jun 19 2018 15:45:13
[root@ansible ansible.test]# ansible all -m file -a 'name=/home/soft state=directory' 192.168.219.137 | SUCCESS => { "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/home/soft", "size": 4096, "state": "directory", "uid": 0 } 192.168.219.136 | SUCCESS => { "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/home/soft", "size": 4096, "state": "directory", "uid": 0 } [root@ansible ansible.test]# ansible all -m copy -a 'src=/home/ansible.test/htop-1.0.3-1.el6.rf.x86_64.rpm dest=/home/soft' 192.168.219.137 | SUCCESS => { "changed": true, "checksum": "2deed7a9030c2963c677cce6ecaccb4750106052", "dest": "/home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm", "gid": 0, "group": "root", "md5sum": "683cc37192a76556c0847aaf93459abf", "mode": "0644", "owner": "root", "size": 88608, "src": "/root/.ansible/tmp/ansible-tmp-1550738545.61-57323277206137/source", "state": "file", "uid": 0 } 192.168.219.136 | SUCCESS => { "changed": true, "checksum": "2deed7a9030c2963c677cce6ecaccb4750106052", "dest": "/home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm", "gid": 0, "group": "root", "md5sum": "683cc37192a76556c0847aaf93459abf", "mode": "0644", "owner": "root", "size": 88608, "src": "/root/.ansible/tmp/ansible-tmp-1550738545.6-127862535278548/source", "state": "file", "uid": 0 } [root@ansible ansible.test]# ansible all -m shell -a 'ls -h /home/soft' 192.168.219.136 | SUCCESS | rc=0 >> htop-1.0.3-1.el6.rf.x86_64.rpm 192.168.219.137 | SUCCESS | rc=0 >> htop-1.0.3-1.el6.rf.x86_64.rpm [root@ansible ansible.test]# ansible all -m yum -a 'name=/home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm' 192.168.219.137 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Install Process\nExamining /home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm: htop-1.0.3-1.el6.rf.x86_64\nMarking /home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm to be installed\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * epel: mirrors.aliyun.com\n * extras: mirrors.163.com\n * updates: ftp.sjtu.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:1.0.3-1.el6.rf will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n htop x86_64 1.0.3-1.el6.rf /htop-1.0.3-1.el6.rf.x86_64 209 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package(s)\n\nTotal size: 209 k\nInstalled size: 209 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Installing : htop-1.0.3-1.el6.rf.x86_64 1/1 \n\r Verifying : htop-1.0.3-1.el6.rf.x86_64 1/1 \n\nInstalled:\n htop.x86_64 0:1.0.3-1.el6.rf \n\nComplete!\n" ] } 192.168.219.136 | SUCCESS => { "changed": true, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror, refresh-packagekit, security\nSetting up Install Process\nExamining /home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm: htop-1.0.3-1.el6.rf.x86_64\nMarking /home/soft/htop-1.0.3-1.el6.rf.x86_64.rpm to be installed\nLoading mirror speeds from cached hostfile\n * base: centos.ustc.edu.cn\n * epel: mirror.premi.st\n * extras: mirrors.163.com\n * updates: mirrors.tuna.tsinghua.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package htop.x86_64 0:1.0.3-1.el6.rf will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n htop x86_64 1.0.3-1.el6.rf /htop-1.0.3-1.el6.rf.x86_64 209 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package(s)\n\nTotal size: 209 k\nInstalled size: 209 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r Installing : htop-1.0.3-1.el6.rf.x86_64 1/1 \n\r Verifying : htop-1.0.3-1.el6.rf.x86_64 1/1 \n\nInstalled:\n htop.x86_64 0:1.0.3-1.el6.rf \n\nComplete!\n" ] } [root@ansible ansible.test]# ansible all -m shell -a 'htop -v' 192.168.219.136 | SUCCESS | rc=0 >> htop 1.0.3 - (C) 2004-2012 Hisham Muhammad Released under the GNU GPL. 192.168.219.137 | SUCCESS | rc=0 >> htop 1.0.3 - (C) 2004-2012 Hisham Muhammad Released under the GNU GPL. [root@ansible ansible.test]# 能夠看到服務都已經安裝成功了
service模塊:
當咱們要批量啓動或關閉n臺機器上的服務的時候,ansible也能經過很簡單的操做就能夠完成。
[root@ansible ~]# ansible-doc -s service - name: Manage services service: arguments: # Additional arguments provided on the command line enabled: # Whether the service should start on boot. *At least one of state and enabled are required.* name: # (required) Name of the service. pattern: # If the service does not respond to the status command, name a substring to look for as would be found in the output of the `ps' command as a stand-in for a status result. If the string is found, the service will be assumed to be running. runlevel: # For OpenRC init scripts (ex: Gentoo) only. The runlevel that this service belongs to. sleep: # If the service is being `restarted' then sleep this many seconds between the stop and start command. This helps to workaround badly behaving init scripts that exit immediately after signaling a process to stop. state: # `started'/`stopped' are idempotent actions that will not run commands unless necessary. `restarted' will always bounce the service. `reloaded' will always reload. *At least one of state and enabled are required.* Note that reloaded will start the service if it is not already started, even if your chosen init system wouldn't normally. use: # The service module actually uses system specific modules, normally through auto detection, this setting can force a specific module. Normally it uses the value of the 'ansible_service_mgr' fact and falls back to the old 'service' module when none matching is found. [root@ansible ~]#
[root@ansible ~]# ansible all -m shell -a 'httpd -v' 192.168.219.137 | SUCCESS | rc=0 >> Server version: Apache/2.2.15 (Unix) Server built: Jun 19 2018 15:45:13 192.168.219.136 | SUCCESS | rc=0 >> Server version: Apache/2.2.15 (Unix) Server built: Jun 19 2018 15:45:13 [root@ansible ~]# ansible all -m service -a 'name=httpd state=restarted enabled=yes' 192.168.219.137 | SUCCESS => { "changed": true, "enabled": true, "name": "httpd", "state": "started" } 192.168.219.136 | SUCCESS => { "changed": true, "enabled": true, "name": "httpd", "state": "started" } [root@ansible ~]# ansible all -m shell -a 'ps -aux | grep http' 192.168.219.137 | SUCCESS | rc=0 >> root 3342 0.0 0.3 183896 3816 ? Ss 13:16 0:00 /usr/sbin/httpd apache 3345 0.0 0.2 184028 2500 ? S 13:16 0:00 /usr/sbin/httpd apache 3346 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3347 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3348 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3349 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3350 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3351 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3352 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd root 3389 0.0 0.1 106096 1120 pts/1 S+ 13:17 0:00 /bin/sh -c ps -aux | grep http root 3391 0.0 0.0 103312 860 pts/1 S+ 13:17 0:00 grep httpWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ 192.168.219.136 | SUCCESS | rc=0 >> root 3323 0.0 0.3 183896 3824 ? Ss 13:16 0:00 /usr/sbin/httpd apache 3326 0.0 0.2 184028 2500 ? S 13:16 0:00 /usr/sbin/httpd apache 3327 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3328 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3329 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3330 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3331 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3332 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd apache 3333 0.0 0.2 184028 2476 ? S 13:16 0:00 /usr/sbin/httpd root 3370 0.0 0.1 106096 1128 pts/1 S+ 13:17 0:00 /bin/sh -c ps -aux | grep http root 3372 0.0 0.0 103312 856 pts/1 S+ 13:17 0:00 grep httpWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ [root@ansible ~]# ansible all -m shell -a 'netstat -anptu | grep 80' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::80 :::* LISTEN 3342/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::80 :::* LISTEN 3323/httpd [root@ansible ~]# ansible all -m shell -a 'chkconfig httpd --list' 192.168.219.137 | SUCCESS | rc=0 >> httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off 192.168.219.136 | SUCCESS | rc=0 >> httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off [root@ansible ~]#
file模塊:
設置文件的屬性,所屬組等,軟鏈接,建立空目錄,遞歸刪除等。
[root@ansible ansible.test]# ansible all -m file -a 'name=/root/date state=touch' 192.168.219.137 | SUCCESS => { "changed": true, "dest": "/root/date", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "size": 0, "state": "file", "uid": 0 } 192.168.219.136 | SUCCESS => { "changed": true, "dest": "/root/date", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "size": 0, "state": "file", "uid": 0 } [root@ansible ansible.test]# ansible all -m shell -a 'ls -h date' 192.168.219.137 | SUCCESS | rc=0 >> date 192.168.219.136 | SUCCESS | rc=0 >> date [root@ansible ansible.test]#
[root@ansible ansible.test]# ansible all -m shell -a 'ls -l date' 192.168.219.137 | SUCCESS | rc=0 >> -rw-r--r-- 1 root root 0 Feb 20 13:17 date 192.168.219.136 | SUCCESS | rc=0 >> -rw-r--r-- 1 root root 0 Feb 20 13:17 date [root@ansible ansible.test]# ansible all -m file -a 'name=/root/date state=absent' 192.168.219.136 | SUCCESS => { "changed": true, "path": "/root/date", "state": "absent" } 192.168.219.137 | SUCCESS => { "changed": true, "path": "/root/date", "state": "absent" } [root@ansible ansible.test]# ansible all -m shell -a 'ls' 192.168.219.137 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos 192.168.219.136 | SUCCESS | rc=0 >> anaconda-ks.cfg Desktop Documents Downloads install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos [root@ansible ansible.test]# 能夠看到date目錄已經刪除了
[root@ansible ansible.test]# ansible all -m file -a 'name=/root/file123/file321 state=directory' 192.168.219.137 | SUCCESS => { "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/root/file123/file321", "size": 4096, "state": "directory", "uid": 0 } 192.168.219.136 | SUCCESS => { "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/root/file123/file321", "size": 4096, "state": "directory", "uid": 0 } [root@ansible ansible.test]# ansible all -m shell -a 'ls -l file123' 192.168.219.137 | SUCCESS | rc=0 >> total 4 drwxr-xr-x 2 root root 4096 Feb 20 13:27 file321 192.168.219.136 | SUCCESS | rc=0 >> total 4 drwxr-xr-x 2 root root 4096 Feb 20 13:27 file321 [root@ansible ansible.test]# 能夠看到遞歸建立成功了
[root@ansible ansible.test]# ansible all -m file -a 'src=/etc/passwd name=/root/file123/passwd.link state=link' 192.168.219.137 | SUCCESS => { "changed": true, "dest": "/root/file123/passwd.link", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 11, "src": "/etc/passwd", "state": "link", "uid": 0 } 192.168.219.136 | SUCCESS => { "changed": true, "dest": "/root/file123/passwd.link", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 11, "src": "/etc/passwd", "state": "link", "uid": 0 } [root@ansible ansible.test]# ansible all -m shell -a 'ls -l /root/file123/passwd.link' 192.168.219.136 | SUCCESS | rc=0 >> lrwxrwxrwx 1 root root 11 Feb 20 13:33 /root/file123/passwd.link -> /etc/passwd 192.168.219.137 | SUCCESS | rc=0 >> lrwxrwxrwx 1 root root 11 Feb 20 13:33 /root/file123/passwd.link -> /etc/passwd [root@ansible ansible.test]# 軟鏈接建立成功 刪除軟鏈接 [root@ansible ansible.test]# ansible all -m file -a 'name=/root/file123/passwd.link state=absent' [WARNING]: The src option requires state to be 'link' or 'hard'. This will become an error in Ansible 2.10 192.168.219.137 | SUCCESS => { "changed": true, "path": "/root/file123/passwd.link", "state": "absent" } 192.168.219.136 | SUCCESS => { "changed": true, "path": "/root/file123/passwd.link", "state": "absent" } [root@ansible ansible.test]# ansible all -m shell -a 'ls -l /root/file123/passwd.link'
因模塊不少,本篇不作過多的介紹,須要查找能夠經過ansible的官方手冊:https://docs.ansible.com/ansible/latest/modules/modules_by_category.html來進行查找。
ansible-galaxy是連接https://galaxy.ansible.com/下載相應的roles(角色),以前咱們是歇學的單條ansible的命令,可是要把不少單條的命令組合起來就須要playbook(劇本),那麼把playbook組合起來的就是roles(角色),把衆多的playbook組合起來造成一個完整的文件夾,就是角色,你也能夠經過提供的網站去網上下載一些人編寫的一些實用的角色,能夠下載下來使用。
保證服務器能訪問互聯網的狀況下 ansible-galaxy install geerlingguy.nginx 直接使用ansible-galaxy命令安裝網站的角色名就能夠
把主控端的命令推送到被控端去執行,能提高執行的效率,在實際生產中用到不多。
ansible-playbook命令的簡單實用:
playbook只是把衆多的模塊寫成了一個腳本的形式在執行,寫成腳本無非是能重複使用,提升工做效率,固然playbook也是有本身的語法和格式的,playbook是使用yml語法寫的,因此playbook的文件也是yml爲後綴的。
[root@ansible playbook]# cat playbook.test.yml --- #三橫槓是表明劇本編寫的開始,不用寫也沒有關係,語法上也是沒有錯誤的。 - hosts: web #- hosts指定主機清單,就是組名,必須有空格 remote_user: root #remote_user表明我接下的劇本是以什麼身份運行的 tasks: #接下來就爲劇本的命令內容 - name: test #給我接下來的命令取一個名字 shell: 'hostname' #指定模塊,後面接操做的命令便可,-a就不須要了 這就是一個簡單的playbook的語法和基本格式。
[root@ansible playbook]# ansible-playbook playbook.test.yml PLAY [web] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [test] ********************************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# 能夠看到劇本在被控端確實執行成功了,可是沒有獲得咱們想要的結果。
第一個劇本編寫成功了,可是執行以後沒有獲得咱們想要的結果,咱們接着看下playbook的其它命令,不斷的去解決這個問題。
爲何要對playbook進行加密是由於playbook裏面可能存在一些敏感信息,好比密碼等,那就須要對playbook進行加密。
ansible-vault【create,decrypt,edit,encrypt,rekey,view】
ansible-vault encrypt 後面是playbook的腳本 【加密】
[root@ansible playbook]# ansible-vault encrypt playbook.test.yml New Vault password: Confirm New Vault password: Encryption successful [root@ansible playbook]# cat playbook.test.yml $ANSIBLE_VAULT;1.1;AES256 30666539373365363535623538663639366633303138333730656264333935636531626537623665 3032393434646461613334393739636362653035376131610a333463343461353538373038303765 30323861353330666135313038353966366635386338643434376232643062373165343361316432 3231316430643036660a353730623063353031626634663538333565633130613637353232313361 36383762653337303133303932333631633538666430313465653934636432643732613835643663 35626535623631613937616266343366353730663662343961353164343330666538346162663138 39333432303631643465396265386430653834363233626137356632383739383935393430343935 34326666323132343461643765616537376337376533653933663764306435663233393833366361 34366232346663666362316565363264373261353063643965313863333330393365373233623032 39623163623936343762666537613439376439313564616438383930313233623931653331396663 66613436646661306531363362663539316532326561363633646437376134396337363139316361 32663038653733343739306233643636653237333364313833386330666434623331636363393965 63623338373730346431613065666561303338393538646133346636306531306566363639333331 32646435613565613861396135313862313331653432323339636636323237323865313335326164 33613432396539636637356263656466633036616232616238393462363030616336343037373566 61353738343435623138336432376534393061393232356438396130643738633233633862626565 65393764323234353238623934343635326364333565643132363963323865633265343533313764 62336438313637623833643735623933353639643064356631323963316265303566333437383736 35323565613532616363303937623539376535396162643864396337393366366463323535346538 33393062653338303234346165633434616132333961613463393136633161353765313838646338 61353566666430353161323136383230303361396336653064653638656134396265613636636639 33633066623165333337363233646232366663613939613066386338636665646333353039386439 61336633626531333961663861303064663065353732353139363934333361396236613330306632 36363564373264616233626530373062656133633130633835626632393232613639353263643633 62653565313361386538386162356565383762666138643139323265613734373565643363373661 62383037356664343063393434633766333734343261306563333365653737323533323238383538 39646338613536313831303266653239663933366531363863353136323135363466303636636531 34393931333930383035 [root@ansible playbook]# 能夠看到加密以後的劇本咱們就不能經過正常的方式查看了,並且使用的是AES的加密算法。 [root@ansible playbook]# ansible-playbook playbook.test.yml ERROR! Attempting to decrypt but no vault secrets found [root@ansible playbook]# 加密狀態下劇本是沒法執行的
ansible-vault decrypt 後面是playbook的腳本 【解密】
[root@ansible playbook]# ansible-vault decrypt playbook.test.yml Vault password: Decryption successful 解密是須要輸入加密以後的口令的。 [root@ansible playbook]# cat playbook.test.yml --- #三橫槓是表明劇本編寫的開始,不用寫也沒有關係,語法上也是沒有錯誤的。 - hosts: web #- hosts指定主機清單,就是組名,必須有空格 remote_user: root #remote_user表明我接下的劇本是以什麼身份運行的 tasks: #接下來就爲劇本的命令內容 - name: test #給我接下來的命令取一個名字 shell: 'init 0' #指定模塊,後面接操做的命令便可,-a就不須要了 [root@ansible playbook]# ansible-playbook playbook.test.yml PLAY [web] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [test] ***************************************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# 加密文件要執行必須解密才能繼續使用
ansible-vault view 後面是playbook的腳本 【查看】
[root@ansible playbook]# ansible-vault encrypt playbook.test.yml New Vault password: Confirm New Vault password: Encryption successful [root@ansible playbook]# ansible-vault view playbook.test.yml Vault password: --- #三橫槓是表明劇本編寫的開始,不用寫也沒有關係,語法上也是沒有錯誤的。 - hosts: web #- hosts指定主機清單,就是組名,必須有空格 remote_user: root #remote_user表明我接下的劇本是以什麼身份運行的 tasks: #接下來就爲劇本的命令內容 - name: test #給我接下來的命令取一個名字 shell: 'init 0' #指定模塊,後面接操做的命令便可,-a就不須要了 [root@ansible playbook]# 若是我只是想看看playbook腳本,也可使用view參數去查看,仍是須要輸入口令。
ansible-vault edit 後面是playbook的腳本 【編輯加密文件】
[root@ansible playbook]# ansible-vault edit playbook.test.yml Vault password: [root@ansible playbook]# 若是不想解密就把文件內容直接調整了,就可使用edit參數。輸入口令就能調整了
ansible-vault rekey 後面是playbook的腳本 【修改口令】
[root@ansible playbook]# ansible-vault rekey playbook.test.yml Vault password: 輸入老密碼以後 New Vault password: 提示輸入新密碼 Confirm New Vault password: Rekey successful [root@ansible playbook]# 直接修改老的密碼,
ansible-vault create 後面是新playbook的腳本 【建立新文件】
[root@ansible playbook]# ansible-vault create playbook.test011.yml New Vault password: Confirm New Vault password: [root@ansible playbook]# ls playbook.test011.yml playbook.test.retry playbook.test.yml [root@ansible playbook]# 若是想在編寫playbook的時候就把文件加密了,就可使用create參數,進去劇本直接編寫。
直接提供一個控制檯,用戶在控制檯進行操做,能支持tab補全
[root@ansible playbook]# ansible-console Welcome to the ansible console. Type help or ? to list commands. root@all (2)[f:5]$ root表明操做用戶,all表明主機清單裏面的全部機器,2表明主機清單的數量,f:5表明併發請求的數量是5 可是一下操做全部主機確定不是經常使用的,經常使用的狀況下仍是按照咱們的分組來控制,執行相關的命令 root@all (2)[f:5]$ cd web root@web (2)[f:5]$ 直接執行cd (主機清單組的名字),就能切換控制對象 併發數過小,咱們調大一點 root@web (2)[f:5]$ forks 10 root@web (2)[f:10]$ 執行forks 數量就能快速調整併發數 前面已經把主機清單和執行的用戶定義好了,咱們執行就只須要接模塊和須要執行的命令便可,並且模塊名記不住沒關係,支持tab補全。 root@web (2)[f:10]$ shell hostname -a和引號都不須要 192.168.219.136 | SUCCESS | rc=0 >> web1 192.168.219.137 | SUCCESS | rc=0 >> web2 root@web (2)[f:10]$ shell df -h 192.168.219.136 | SUCCESS | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/sda2 18G 2.7G 14G 16% / tmpfs 491M 72K 491M 1% /dev/shm /dev/sda1 283M 37M 232M 14% /boot 192.168.219.137 | SUCCESS | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/sda2 18G 2.6G 14G 16% / tmpfs 491M 72K 491M 1% /dev/shm /dev/sda1 283M 36M 232M 14% /boot root@web (2)[f:10]$
在ansible-console控制檯下,須要注意的是一些帶有風險的操做是對全部被控機器執行仍是單臺機器執行,避免形成不可逆的操做,控制檯的形式也能讓咱們臨時去進行測試。
使用playbook須要記住兩點,1:playbook實用yaml語言編寫,文件後綴必須是yml,2:playbook的編寫格式有必定要求。
劇本在舞臺上使用的時候,能夠想到是由多個演員按照預先規劃好的時間軸依次出廠和退場,共同的來完成一場演出,那麼playbook也是如此,例如我是否是須要驗證機器服務有沒有裝,有沒有啓動,有沒有開機自啓,其次是否是要裝包,下發配置文件,起服務,加入開機自啓,最後是否是要驗證啓動狀況,端口監聽是否正常等。都是須要按照時間排列好的形式來編寫playbook,這個就很像編劇的職務。
playbook的核心元素:
hosts 主機列表
tasks 任務集
varbiables 內置變量或自定義變量在playbook中的調用
tempates 模板,看替換模板文件中的變量並實現一些簡單邏輯的文件
handlers 和notity結合使用,由特定條件觸發,知足則執行,不然不執行
tags 標籤
[root@ansible playbook]# ansible-playbook -C playbook.test.yml 在執行腳本的時候加上-C就能查看腳本是否有錯誤 PLAY [web] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [test] ***************************************************************************************************************** skipping: [192.168.219.136] skipping: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=1 changed=0 unreachable=0 failed=0 192.168.219.137 : ok=1 changed=0 unreachable=0 failed=0 [root@ansible playbook]#
在ansible裏面咱們一般要控制幾十上百臺機器,不少狀況下咱們不能保證每臺機器的目錄是否存在,命令執行錯誤等狀況,這種狀況下,playbook就可能由於錯誤不執行結束了,那不少狀況下咱們都但願無論錯誤繼續執行剩下的操做,這個時候就須要在操做後面加上一個||/bin/true
還有狀況下,例如我就想在單臺機器上把我剛纔寫的playbook先跑下,不想一下把全部的機器都跑了,也能夠經過--limit 後面跟上ip地址便可。
[root@ansible playbook]# ansible-playbook playbook.test.yml --list-hosts playbook: playbook.test.yml play #1 (web): web TAGS: [] pattern: [u'web'] hosts (2): 192.168.219.136 192.168.219.137 [root@ansible playbook]# ansible-playbook playbook.test.yml --limit 192.168.219.136 PLAY [web] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.136] TASK [test] ***************************************************************************************************************** changed: [192.168.219.136] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]#
腳本寫好了,跑的過程我想知道也能夠在執行的時候末尾加上-v -vv -vvv來看不一樣詳細的運行過程信息。
task重複執行的問題:
若是我一個模塊裏面執行了兩條操做,這個時候playbook不會報錯,可是隻會執行命令裏面的最後一個操做。
[root@ansible playbook]# cat playbook.test.yml --- -hosts: all remote_user: root tasks: -name: copy file copy: src=/home/ansible.test/playbook/11.sh dest=/home/ansible/ copy: src=/home/ansible.test/playbook/22.sh dest=/home/ansible/ [root@ansible playbook]# 能夠看到copy的操做有兩個 [root@ansible playbook]# ansible-playbook playbook.test.yml [WARNING]: While constructing a mapping from /home/ansible.test/playbook/playbook.test.yml, line 6, column 6, found a duplicate dict key (copy). Using last defined value only. PLAY [all] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [copy file] ************************************************************************************************************ changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'ls /home/ansible' 192.168.219.136 | SUCCESS | rc=0 >> 22.sh 192.168.219.137 | SUCCESS | rc=0 >> 22.sh [root@ansible playbook]# 能夠看到就拷貝了22.sh,這個就說明在tasks裏面一個模塊只能對應一個name,一個name也只能對應一個操做。
上面咱們執行的時候都是按照流程去操做的,不存在判斷的過程,這個我要判斷機器的httpd服務是否裝了,裝了就沒必要要從新裝,不然就安裝。
handlers和notify配合使用:
這個時候就須要handlers(觸發器),handlers能夠監控tasks裏面的每個操做,當一個操做執行了,那麼就會觸發handlers後面定義的一些命令,那麼handlers是怎麼被觸發的了,配合handlers作觸發的是notity,當操做執行以後notity就會通知handlers來執行相應的命令。
[root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install httpd service yum: name=httpd - name: start service service: name=httpd state=started enabled=yes [root@ansible playbook]# ansible-playbook playbook.test.yml PLAY [all] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [install httpd service] ************************************************************************************************ ok: [192.168.219.136] ok: [192.168.219.137] TASK [start service] ******************************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=3 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=1 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep 80' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::80 :::* LISTEN 5631/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::80 :::* LISTEN 4599/httpd 能夠看到httpd服務已經裝好了,可是這個時候我要把默認的80端口改爲8088的話,那麼更新我本地的配置文件同步到備機,配置文件變更過,服務就須要重啓才能生效。 咱們在本地將修改httpd的配置文件 [root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install httpd service yum: name=httpd - name: start service service: name=httpd state=started enabled=yes - name: copy conf file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart service #這個notify就要寫handiers後面定義的名字 handlers: - name: restart service service: name=httpd state=restarted #當監控有變更以後handlers須要作什麼操做 [root@ansible playbook]# ansible-playbook playbook.test.yml PLAY [all] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [install httpd service] ************************************************************************************************ ok: [192.168.219.136] ok: [192.168.219.137] TASK [start service] ******************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [copy conf file] ******************************************************************************************************* changed: [192.168.219.137] changed: [192.168.219.136] RUNNING HANDLER [restart service] ******************************************************************************************* changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=5 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=5 changed=2 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep 8088' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::8088 :::* LISTEN 6045/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::8088 :::* LISTEN 5016/httpd [root@ansible playbook]# 執行以後就能夠看到服務重啓成功了,並且8088端口修改也生效了
notify能夠通知多個handlers的操做:
notify: - 空格以後接第一個handlers的名字 - 空格以後接第二個handlers的名字
tags:標籤
加標籤的目的是,後面咱們能夠調用標籤裏面的內容,如上面重啓httpd的案例同樣,我不須要每次都把這個playbook都完完整整的執行一遍,我只須要在httpd重啓的地方打上一個標籤,後面咱們在執行的時候就選擇這個標籤來執行便可。
[root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install httpd service yum: name=httpd - name: start service service: name=httpd state=started enabled=yes tags: rehttpd #在此位置加一個tags的標籤,後面寫上標籤名,標籤名要有意義且簡單,最好加上註釋。 - name: copy conf file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart service handlers: - name: restart service service: name=httpd state=restarted [root@ansible playbook]# ansible all -m shell -a 'ps -aux | grep httpd' 192.168.219.136 | SUCCESS | rc=0 >> root 5969 0.0 0.1 106096 1128 pts/1 S+ 06:12 0:00 /bin/sh -c ps -aux | grep httpd root 5971 0.0 0.0 103308 852 pts/1 S+ 06:12 0:00 grep httpdWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ 192.168.219.137 | SUCCESS | rc=0 >> root 6998 0.0 0.1 106096 1120 pts/1 S+ 06:12 0:00 /bin/sh -c ps -aux | grep httpd root 7000 0.0 0.0 103308 848 pts/1 S+ 06:12 0:00 grep httpdWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ 能夠看到httpd服務是沒有啓動的 [root@ansible playbook]# ansible-playbook -t rehttpd playbook.test.yml -t 指定標籤名執行playbook PLAY [all] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [start service] ******************************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'ps -aux | grep httpd' 192.168.219.136 | SUCCESS | rc=0 >> root 6101 0.0 0.3 183896 3832 ? Ss 06:12 0:00 /usr/sbin/httpd apache 6104 0.0 0.2 184028 2508 ? S 06:12 0:00 /usr/sbin/httpd apache 6105 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6106 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6107 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6108 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6109 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6110 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd apache 6111 0.0 0.2 184028 2484 ? S 06:12 0:00 /usr/sbin/httpd root 6143 0.0 0.1 106096 1128 pts/1 S+ 06:12 0:00 /bin/sh -c ps -aux | grep httpd root 6145 0.0 0.0 103312 860 pts/1 S+ 06:12 0:00 grep httpdWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ 192.168.219.137 | SUCCESS | rc=0 >> root 7130 0.0 0.3 183896 3824 ? Ss 06:12 0:00 /usr/sbin/httpd apache 7133 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7134 0.0 0.2 184028 2500 ? S 06:12 0:00 /usr/sbin/httpd apache 7135 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7136 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7137 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7138 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7139 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd apache 7140 0.0 0.2 184028 2476 ? S 06:12 0:00 /usr/sbin/httpd root 7172 0.0 0.1 106096 1124 pts/1 S+ 06:12 0:00 /bin/sh -c ps -aux | grep httpd root 7174 0.0 0.0 103312 856 pts/1 S+ 06:12 0:00 grep httpdWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ [root@ansible playbook]# 能夠看到httpd服務就啓動了
[root@ansible conf]# ansible all -m shell -a 'netstat -anptu | grep 8088' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::8088 :::* LISTEN 7130/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::8088 :::* LISTEN 6101/httpd 能夠看到服務端口是8088 咱們把配置文件改9099,並執行在copy位置加的標籤 [root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install httpd service yum: name=httpd - name: start service service: name=httpd state=started enabled=yes tags: rehttpd - name: copy conf file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart service tags: cohttpd #在此處加了標籤 handlers: - name: restart service service: name=httpd state=restarted [root@ansible playbook]# ansible-playbook -t cohttpd playbook.test.yml PLAY [all] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [copy conf file] ******************************************************************************************************* changed: [192.168.219.137] changed: [192.168.219.136] RUNNING HANDLER [restart service] ******************************************************************************************* changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=3 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=2 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep 9099' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::9099 :::* LISTEN 7464/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::9099 :::* LISTEN 6435/httpd [root@ansible playbook]# 能夠看到端口是9099,咱們執行了copy的配置文件下發同時也觸發了重啓任務的操做。
[root@ansible playbook]# ansible all -m shell -a 'httpd -v' 192.168.219.136 | FAILED | rc=127 >> /bin/sh: httpd: command not foundnon-zero return code 192.168.219.137 | FAILED | rc=127 >> /bin/sh: httpd: command not foundnon-zero return code [root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install httpd service yum: name=httpd tags: inhttpd #在此處我加了一個安裝httpd服務的標籤 - name: start service service: name=httpd state=started enabled=yes - name: copy conf file copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/ backup=yes notify: restart service tags: cohttpd #增長了該端口配置的標籤 handlers: - name: restart service service: name=httpd state=restarted [root@ansible playbook]# ansible-playbook -t inhttpd,cohttpd playbook.test.yml 在-t指定標籤執行的時候我能夠選擇多個標籤進行執行,中間逗號區分便可 PLAY [all] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [install httpd service] ***************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] TASK [copy conf file] ************************************************************************************************************************************ changed: [192.168.219.136] changed: [192.168.219.137] RUNNING HANDLER [restart service] ************************************************************************************************************************ changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=4 changed=3 unreachable=0 failed=0 192.168.219.137 : ok=4 changed=3 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep 1234' 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::1234 :::* LISTEN 7152/httpd 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::1234 :::* LISTEN 8120/httpd [root@ansible playbook]#
tags還支持多個操做共用一個標籤
playbook使用變量:
playbook的變量和大多數變量定義規則同樣,字母下劃線和數字組成且只能以字母開頭
setup模塊:
setup自帶了系統中的變量
ansible 機器ip -m setup 能獲取被控端機器的全部信息,磁盤大小,主機名,內核版本等等信息,有時候咱們想經過命令獲取機器的信息的時候須要重複執行不少命令,這個時候setup就頗有用,直接查詢出來進行過濾便可。
[root@ansible playbook]# ansible 192.168.219.136 -m setup | grep 'ansible_kernel' "ansible_kernel": "2.6.32-573.el6.x86_64", [root@ansible playbook]# ansible 192.168.219.136 -m setup -a 'filter=ansible_kernel' 192.168.219.136 | SUCCESS => { "ansible_facts": { "ansible_kernel": "2.6.32-573.el6.x86_64" }, "changed": false } [root@ansible playbook]# 兩種方式均可以,可是你要寫到playbook裏面的grep命令可能會出問題,仍是使用推薦的命令,這個setup過濾出來的數值咱們到時候就能夠進行調用,以知足其餘的需求。
playbook腳本使用變量案例:
[root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root tasks: - name: install soft yum: name={{ deploy }} #在安裝的名字的位置使用變量名,格式就是兩組花括號,先後留有空格不是強制要求,只是爲了更加簡潔易讀 - name: start service service: name={{ deploy }} state=started enabled=yes #一樣在只要使用到包名的位置都要替換成變量 [root@ansible playbook]# ansible-playbook -e 'deploy=vsftpd' playbook.test.yml #在執行的時候跟上-e參數,後面的變量直接指定實際要安裝的程序名便可 PLAY [all] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [install soft] ***************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] TASK [start service] ************************************************************************************************************************************* changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=3 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=2 unreachable=0 failed=0 能夠看到ftp程序安裝成,咱們進行檢查,看下服務是否啓動 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep 21' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 2906/vsftpd tcp 0 0 192.168.219.137:22 192.168.219.135:38357 ESTABLISHED 2928/sshd tcp 0 0 192.168.219.137:22 192.168.219.1:50993 ESTABLISHED 2679/sshd tcp 0 0 192.168.219.137:22 192.168.219.1:50994 ESTABLISHED 2681/sshd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 2936/vsftpd tcp 0 0 192.168.219.136:22 192.168.219.1:50861 ESTABLISHED 2640/sshd tcp 0 0 192.168.219.136:22 192.168.219.135:34572 ESTABLISHED 2954/sshd tcp 0 0 192.168.219.136:22 192.168.219.1:50865 ESTABLISHED 2642/sshd [root@ansible playbook]# 能夠看到21端口啓用了,ftp程序安裝並啓動成功。
在腳本里面使用變量可使得腳本更加靈活,固然playbook也是支持多個變量的,指須要在-e後面分別賦值便可,例如ansible-playbook -e 'deploy=vsftpd deploy1=httpd' 腳本名
[root@ansible playbook]# cat playbook.test.yml --- - hosts: all remote_user: root vars: - deploy1: redis #在腳本里面就把變量進行賦值 - deploy2: subversion tasks: - name: install soft yum: name={{ deploy1 }} - name: install soft yum: name={{ deploy2 }} [root@ansible playbook]# ansible-playbook playbook.test.yml #執行的時候就不須要在給變量傳參 PLAY [all] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [install soft] ************************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] TASK [install soft] ************************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=3 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=2 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'rpm -qa redis' [WARNING]: Consider using the yum, dnf or zypper module rather than running rpm. If you need to use command because yum, dnf or zypper is insufficient you can add warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this message. 192.168.219.136 | SUCCESS | rc=0 >> redis-3.2.12-2.el6.x86_64 192.168.219.137 | SUCCESS | rc=0 >> redis-3.2.12-2.el6.x86_64 [root@ansible playbook]# ansible all -m shell -a 'rpm -qa subversion' [WARNING]: Consider using the yum, dnf or zypper module rather than running rpm. If you need to use command because yum, dnf or zypper is insufficient you can add warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this message. 192.168.219.137 | SUCCESS | rc=0 >> subversion-1.6.11-15.el6_7.x86_64 192.168.219.136 | SUCCESS | rc=0 >> subversion-1.6.11-15.el6_7.x86_64 能夠看到都安裝成功
也能夠在腳本里面把變量進行賦值,在執行的時候就直接執行,無需在執行的時候給參數。
在/etc/ansible/hosts裏面使用變量,例如我被控端機器太多,我就算用組名來區分仍是不夠細緻,若是我有幾十臺http的服務器,可是裏面機器的端口不同,這個時候變量就能很好的解決此問題。
## db-[99:101]-node.example.com [web] 192.168.219.136 httpd_server=8080 192.168.219.137 httpd_server=9090 在組所屬的ip後面在加以區分,至關於標記,不竟能在第一時間查看到機器服務還能看到端口 [root@ansible playbook]# cat playbook.test.yml --- - hosts: web remote_user: root tasks: - name: mod hostname hostname: name=www.{{http_server}}.http.com #在腳本里面調用變量進行主機名批量修改 [root@ansible playbook]# cat playbook.test.yml --- - hosts: web remote_user: root tasks: - name: set server hostname: name=www{{http_server}}.http.com [root@ansible playbook]# vim playbook.test.yml [root@ansible playbook]# ansible-playbook -C playbook.test.yml PLAY [web] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [set server] **************************************************************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# cat playbook.test.yml --- - hosts: web remote_user: root tasks: - name: set server hostname: name=www{{httpd_server}}.http.com [root@ansible playbook]# ansible-playbook playbook.test.yml PLAY [web] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [set server] **************************************************************************************************************************************** changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# ansible web -a 'hostname' 192.168.219.137 | SUCCESS | rc=0 >> www9090.http.com 192.168.219.136 | SUCCESS | rc=0 >> www8080.http.com [root@ansible playbook]# 能夠看到主機名修改爲hosts裏面事先定義好了的端口
[web:vars] #也能夠在組裏面使用變量,指須要在組名後面添加vars便可 name1=www name2=httpd.com 在 hostname: name={{name1}}{{httpd_server}}.{{name2}}位置使用變量,也能夠
在變量使用中,普通變量(單條命令)比公共組(hosts)裏面的優先級要高。
在指定的路徑下編寫yml文件,將變量定義成共用的變量,方便不一樣的運維上來無需在進行變量的聲明和定義,直接調用已經編寫好的yml文件裏面的變量進行操做,這樣的好處就是避免每人運維上來都要對playbook進行變量的聲明,若是是沒有提早規劃,這些變量名將變得雜亂無章。
[root@ansible playbook]# cat vars.yml db_backup: dbbackup time: date +%Y%m%d [root@ansible playbook]# 建立一個vars.yml的文件,把須要定義的變量和指實現寫好 [root@ansible playbook]# cat backup.yml --- - hosts: web remote_user: root vars_files: - vars.yml tasks: - name: create flie file: name=/root/{{ db_backup }} state=touch [root@ansible playbook]# 在playbook裏面指定變量使用vars文件來定義,下面要使用變量的部分直接使用vars裏面的變量便可 [root@ansible playbook]# ansible web -m shell -a 'ls -h /root' 192.168.219.137 | SUCCESS | rc=0 >> anaconda-ks.cfg dbbackup Desktop Documents Downloads file123 install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos 192.168.219.136 | SUCCESS | rc=0 >> anaconda-ks.cfg dbbackup Desktop Documents Downloads file123 install.log install.log.syslog log.tar.xz Music Pictures Public Templates Videos 能夠看到建立成功
注:playbook腳本在哪一個路徑下,vars.yml文件就要在相應的路徑下
實際生產中,咱們會遇到不少須要下發配置文件的操做,可是配置文件不可能每套環境都是使用的同樣的,這個時候有差別咱們若是還使用前面的ansible操做就會不適用,因此咱們須要藉助ansible的templates模板來完成和機器相匹配的配置文件下發。
templates使用的jinja2語言,能支持整數,浮點數,列表,元祖,字典,布爾值,算數運算符,邏輯表達式,流表達式(for if when)這個是比較特殊的表達式,它的含義是當什麼知足條件的時候才執行相應的操做。
template自己就是一個模塊,並且這個模塊比較特殊,他只能用於playbook。
咱們將服務的配置文件拷貝一份放到創建好的路徑下,並修改爲.j2結尾的文件 [root@ansible templates]# pwd /home/ansible.test/templates [root@ansible templates]# ls httpd.conf.j2 templates.retry templates.yml 修改hosts文件以下: ## db-[99:101]-node.example.com [web] 192.168.219.136 httpd_server=1010 在hosts文件夾定義好變量 192.168.219.137 httpd_server=2020 在httpd.conf裏面使用該變量 #Listen 12.34.56.78:80 Listen {{httpd_server}} [root@ansible templates]# cat templates.yml --- - hosts: web remote_user: root tasks: - name: copy httpd template: src=/home/ansible.test/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: service restart handlers: - name: service restart service: name=httpd state=restarted [root@ansible templates]# ansible-playbook templates.yml PLAY [web] *********************************************************************************************************************************************** TASK [Gathering Facts] *********************************************************************************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [copy httpd] **************************************************************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] RUNNING HANDLER [service restart] ************************************************************************************************************************ changed: [192.168.219.137] changed: [192.168.219.136] PLAY RECAP *********************************************************************************************************************************************** 192.168.219.136 : ok=3 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=2 unreachable=0 failed=0 [root@ansible templates]# ansible all -m shell -a 'netstat -anptu | grep httpd' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::2020 :::* LISTEN 5710/httpd udp 0 0 192.168.219.137:53613 192.168.219.2:53 ESTABLISHED 5710/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::1010 :::* LISTEN 5704/httpd udp 0 0 192.168.219.136:37088 192.168.219.2:53 ESTABLISHED 5704/httpd [root@ansible templates]# 能夠看到兩臺機器的ip都按照設定的下發了不一樣端口的配置文件並重啓生效了
template的還能完成根據機器的資源配置下發與機器相關匹配的配置文件。
變量的優先級是命令行裏面的-e參數指定的變量,其實playbook裏面定義的變量,最後是主機清單裏面的變量。
template裏面when的用法
[root@ansible templates]# cat templates.yml --- - hosts: web remote_user: root tasks: - name: copy httpd service: name=httpd state=statred notify: service restart when: httpd_server == "1010" handlers: - name: service restart service: name=httpd state=stoped [root@ansible templates]# 例如我判斷端口等於1010的纔會關閉httpd服務
迭代:with_items:
當咱們須要重複執行某一個操做的時候,就須要迭代運行的機制。在ansible裏面迭代的引用固定變量名爲「item」,在task中使用with_items給須要迭代的定義元素列表,支持字符串和字典。
[root@ansible playbook]# cat item.yml --- - hosts: web remote_user: root tasks: - name: create file file: name=/root/{{ item }} state=touch #這個item在此處比較特殊,它表明了下面with_items裏面的每個元素 with_items: #在with_items裏面定義沒一個元素,讓上面的item變量來迭代使用 - file1 - file2 - file3 [root@ansible playbook]# ansible-playbook item.yml PLAY [web] **************************************************************************** TASK [Gathering Facts] **************************************************************** ok: [192.168.219.136] ok: [192.168.219.137] TASK [create file] ******************************************************************** changed: [192.168.219.136] => (item=file1) changed: [192.168.219.137] => (item=file1) changed: [192.168.219.136] => (item=file2) changed: [192.168.219.137] => (item=file2) changed: [192.168.219.136] => (item=file3) changed: [192.168.219.137] => (item=file3) PLAY RECAP **************************************************************************** 192.168.219.136 : ok=2 changed=1 unreachable=0 failed=0 192.168.219.137 : ok=2 changed=1 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'ls /root/ -l' 192.168.219.137 | SUCCESS | rc=0 >> total 156 -rw-------. 1 root root 3341 Feb 14 01:57 anaconda-ks.cfg -rw-r--r-- 1 root root 0 Feb 25 06:09 dbbackup drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Desktop drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Documents drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Downloads -rw-r--r-- 1 root root 0 Feb 27 01:48 file1 drwxr-xr-x 3 root root 4096 Feb 20 13:35 file123 -rw-r--r-- 1 root root 0 Feb 27 01:48 file2 -rw-r--r-- 1 root root 0 Feb 27 01:48 file3 -rw-r--r--. 1 root root 41800 Feb 14 01:57 install.log -rw-r--r--. 1 root root 9154 Feb 14 01:54 install.log.syslog -rw-r--r-- 1 root root 55144 Feb 20 13:05 log.tar.xz drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Music drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Pictures drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Public drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Templates drwxr-xr-x. 2 root root 4096 Feb 14 02:02 Videos 192.168.219.136 | SUCCESS | rc=0 >> total 156 -rw-------. 1 root root 3341 Feb 14 01:56 anaconda-ks.cfg -rw-r--r-- 1 root root 0 Feb 25 06:09 dbbackup drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Desktop drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Documents drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Downloads -rw-r--r-- 1 root root 0 Feb 27 01:48 file1 drwxr-xr-x 3 root root 4096 Feb 20 13:35 file123 -rw-r--r-- 1 root root 0 Feb 27 01:48 file2 -rw-r--r-- 1 root root 0 Feb 27 01:48 file3 -rw-r--r--. 1 root root 41800 Feb 14 01:56 install.log -rw-r--r--. 1 root root 9154 Feb 14 01:53 install.log.syslog -rw-r--r-- 1 root root 55452 Feb 20 13:05 log.tar.xz drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Music drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Pictures drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Public drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Templates drwxr-xr-x. 2 root root 4096 Feb 14 02:01 Videos [root@ansible playbook]# 能夠看到迭代幫忙建立的空的目錄
迭代嵌套子變量:
若是想重複完成多件事情,單純的嵌套寫起來會比較麻煩。
[root@ansible playbook]# cat item2.yml --- - hosts: all remote_user: root tasks: - name: create groups group: name={{ item }} state=present 在建立組的時候使用變量的格式 with_items: - group1 - group2 - group3 - name: add users user: name={{ item.name }} group={{ item.group }} state=present #在建立用戶的時候把屬組參數調用上面定義好的變量 with_items: - { name: 'user1',group: 'group1' } #在with_items下面以字典的格式記錄數據 - { name: 'user2',group: 'group2' } - { name: 'user3',group: 'group3' } [root@ansible playbook]# ansible all -m shell -a 'getent passwd' 192.168.219.137 | SUCCESS | rc=0 >> 。。。。。。。 user1:x:502:502::/home/user1:/bin/bash user2:x:503:503::/home/user2:/bin/bash user3:x:504:504::/home/user3:/bin/bash [root@ansible playbook]# ansible all -m shell -a 'getent group' 192.168.219.137 | SUCCESS | rc=0 >> 。。。。。 group1:x:502: group2:x:503: group3:x:504: 能夠看到建立的用戶和所屬組的關係是咱們上面定義好的形式
playbook中template的for if:
for和endfor造成一對兒。
{% for pote in nginx_pote %} server{ } {% if server_name is defined %} server name {{}} {% endif %} ......
迭代是咱們定義好的參數,可是若是是想要產出的數字有規律且不少的狀況下迭代很顯然就不適合了,就須要使用循環來處理。
[root@ansible playbook]# cat for.yml --- - hosts: all remote_user: root vars: ports: #在此處定義一個元素列表 - 81 - 82 - 83 tasks: - name: copy conf template: src=/home/ansible.test/playbook/for.conf.j2 dest=/root/file123/for.conf #在拷貝的時候運用模板功能拷貝相應的文件 [root@ansible playbook]# cat for.conf.j2 #建立模板文件。 {% for port in ports %} #此處須要注意的就是ports,這個ports是playbook裏面定義好的元素列表名 server{ listen {{ port }} #用for後面的port去拿ports裏面的數據,不斷賦值給此處的變量port,直到ports裏面的數據取完爲止 } {% endfor %} [root@ansible playbook]# 運行playbook腳本 [root@ansible playbook]# ansible all -m shell -a 'cat /root/file123/for.conf' 192.168.219.137 | SUCCESS | rc=0 >> server{ listen 81 } server{ listen 82 } server{ listen 83 } 192.168.219.136 | SUCCESS | rc=0 >> server{ listen 81 } server{ listen 82 } server{ listen 83 } 能夠看到for.conf文件取到的指就是ports被模板循環賦值的結果。
[root@ansible playbook]# cat for.yml --- - hosts: all remote_user: root vars: ports: #咱們把ports裏面的數據定義成字典的形式 - licent: 85 - licent: 86 - licent: 87 tasks: - name: copy conf template: src=/home/ansible.test/playbook/for.conf.j2 dest=/root/file123/for.conf [root@ansible playbook]# cat for.conf.j2 {% for port in ports %} server{ listen {{ port.licent }} #變量的位置就須要用到字典的鍵名 } {% endfor %} [root@ansible playbook]# ansible all -m shell -a 'cat /root/file123/for.conf' 192.168.219.137 | SUCCESS | rc=0 >> server{ listen 85 } server{ listen 86 } server{ listen 87 } 192.168.219.136 | SUCCESS | rc=0 >> server{ listen 85 } server{ listen 86 } server{ listen 87 } [root@ansible playbook]#
字典的好處就是我能在playbook裏面定義多個鍵值對,這樣我在模板裏面直接取變量名便可。
[root@ansible playbook]# cat for.yml --- - hosts: all remote_user: root vars: ports: #ports裏面我定義多個鍵值對 - licent: 88 name: www.88.com - licent: 89 name: www.89.com - licent: 90 name: www.90.com tasks: - name: copy conf template: src=/home/ansible.test/playbook/for.conf.j2 dest=/root/file123/for.conf [root@ansible playbook]# cat for.conf.j2 {% for port in ports %} server{ listen {{ port.licent }} server {{ port.name }} #在模板裏面我只須要調用playbook裏面定義好的變量便可 } {% endfor %} [root@ansible playbook]# ansible all -m shell -a 'cat /root/file123/for.conf' 192.168.219.136 | SUCCESS | rc=0 >> server{ listen 88 server www.88.com } server{ listen 89 server www.89.com } server{ listen 90 server www.90.com } 192.168.219.137 | SUCCESS | rc=0 >> server{ listen 88 server www.88.com } server{ listen 89 server www.89.com } server{ listen 90 server www.90.com } [root@ansible playbook]#
template增長if判斷條件:
[root@ansible playbook]# cat for.conf.j2 {% for port in ports %} server{ listen {{ port.licent }} {% if port.name is defined %} #增長判斷,判斷下name是否有指,有指我才執行下面的語句 server {{ port.name }} {% endif %} } {% endfor %} [root@ansible playbook]# cat for.yml --- - hosts: all remote_user: root vars: ports: - licent: 91 # name: www.91.com #將91的name註釋掉,讓其檢查的時候判斷爲沒有指 - licent: 92 name: www.92.com - licent: 93 name: www.93.com tasks: - name: copy conf template: src=/home/ansible.test/playbook/for.conf.j2 dest=/root/file123/for.conf [root@ansible playbook]# ansible all -m shell -a 'cat /root/file123/for.conf' 192.168.219.137 | SUCCESS | rc=0 >> server{ listen 91 } server{ listen 92 server www.92.com } server{ listen 93 server www.93.com } 192.168.219.136 | SUCCESS | rc=0 >> server{ listen 91 } server{ listen 92 server www.92.com } server{ listen 93 server www.93.com } 能夠看到所屬的91是沒有建立name的
在實際工做中,咱們須要管理N臺服務器,這個時候由於機器部署的環境,機器的配置,是不是雲主機等致使ansible在使用的時候簡單的playbook已經不能知足所要處理的任務了,咱們須要層次型結構自動裝載變量文件,task以及handlers等,這樣咱們只須要在playbook裏面使用include指令便可。
roles能完成更加靈活的場景,代碼的複用度也大大增長,能夠經過簡單的include靈活調取所要執行的任務。
咱們在安裝ansible的時候在/etc/ansibe下已經給咱們建立好了roles目錄,咱們只須要在這個目下建立層級結構目錄和文件便可,固然還可使用自定義的目錄。
咱們經過上圖相似的層級結構,這樣我每一個文件的功能雖然單一,可是文件的功能性更加全面,能夠很好的保證代碼的複用度。
建立roles目錄和相應的工程目錄
mkdir -p roles/{nginx,mysql,httpd} [root@ansible playbook]# tree roles/ roles/ ├── httpd ├── mysql └── nginx 3 directories, 0 files
調用roles角色的劇本須要放在roles相同層級的目錄下
roles層級下目錄和各目錄的做用;
files:存放由shell或者yum等模塊調用的文件;
templates:模塊須要查找所需的模板文件;
tasks:定義tasks,role的基本元素,至少包含一個名爲main.yml的文件;
handlers:至少包含一個main.yml文件;
vars:定義變量,至少包含一個main.yml文件;
meta:定義當前角色的特殊設定及依賴關係,至少包含一個main.yml文件;
default:設定默認變量時使用此目錄中的main.yml文件。
[root@ansible playbook]# tree roles/ roles/ ├── httpd │ ├── tasks #分別在tasks目錄下建立相應的操做劇本 │ │ ├── copy.yml #這每個劇本只作一件事情,例如copy就作配置文件的拷貝 │ │ ├── group.yml #建立組 │ │ ├── main.yml #這個劇本的名字是固定的,用來規定這全部劇本的執行順序 │ │ ├── restart.yml #重啓 │ │ ├── start.yml #啓動 │ │ ├── user.yml #建立用戶 │ │ └── yum.yml #安裝包 │ └── templates │ └── httpd.conf.j2 ├── mysql └── nginx directories, 8 files [root@ansible tasks]# cat copy.yml - name: copy httpd.conf template:src=/home/ansible.test/playbook/roles/httpd/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf [root@ansible tasks]# cat group.yml - name: create group #因是roles形式就不須要在單個劇本定義hosts了,在總運行的劇本里面定義便可 group: name=httpd [root@ansible tasks]# cat restart.yml - name: restart server service: name=hhtpd state=restarted [root@ansible tasks]# cat start.yml - name: start server service: name=httpd state=started enabled=yes [root@ansible tasks]# cat user.yml - name: create user user: name=httpd group=httpd system=yes shell=/sbin/nologin [root@ansible tasks]# cat yum.yml - name: install yum: name=httpd 用main.yml來規定這些劇本的執行順序 [root@ansible tasks]# cat main.yml - include: group.yml - include: user.yml - include: yum.yml - include: copy.yml - include: start.yml #include是固定詞 [root@ansible tasks]# [root@ansible templates]# cat httpd.conf.j2 | grep httpd_server Listen {{ httpd_server }} [root@ansible templates]# 定義模板,端口在hosts裏面提早定義 [root@ansible playbook]# cat httpd.yml --- - hosts: web remote_user: root roles: #用關鍵字來調用roles角色下面的httpd,一層層的執行劇本。 - role: httpd 在roles平級的目錄下寫一個總調用的劇本 [root@ansible playbook]# ansible-playbook httpd.yml PLAY [web] ****************************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************** ok: [192.168.219.137] ok: [192.168.219.136] TASK [httpd : copy httpd.conf] ********************************************************************************************** changed: [192.168.219.136] changed: [192.168.219.137] TASK [httpd : start server] ************************************************************************************************* changed: [192.168.219.136] changed: [192.168.219.137] PLAY RECAP ****************************************************************************************************************** 192.168.219.136 : ok=3 changed=2 unreachable=0 failed=0 192.168.219.137 : ok=3 changed=2 unreachable=0 failed=0 [root@ansible playbook]# ansible all -m shell -a 'netstat -anptu | grep httpd' 192.168.219.137 | SUCCESS | rc=0 >> tcp 0 0 :::9090 :::* LISTEN 3560/httpd 192.168.219.136 | SUCCESS | rc=0 >> tcp 0 0 :::8080 :::* LISTEN 3382/httpd [root@ansible playbook]# 這樣咱們經過roles把流程規劃的很清晰,不會再出現單一playbook出現的問題而難以調整或者複用的問題
[root@ansible ansible.test]# tree roles roles ├── keepalived │ ├── handlers │ │ └── restart.yml │ ├── tasks │ │ ├── copy.yml │ │ ├── main.yml │ │ ├── start.yml │ │ └── yum.yml │ ├── templates │ │ └── keepalived.conf.j2 │ └── vars │ └── main.yml ├── nginx │ ├── handlers │ ├── tasks │ │ ├── copy.yml │ │ ├── main.yml │ │ ├── start.yml │ │ └── yum.yml │ ├── templates │ │ └── nginx.conf.j2 │ └── vars └── redis ├── handlers ├── tasks ├── templates └── vars 15 directories, 12 files [root@ansible ansible.test]# cat roles/keepalived/vars/main.yml ip_addr: 192.168.219.130/24 把keep須要的虛擬ip經過變量存在vars裏面 [root@ansible ansible.test]# cat roles/keepalived/templates/keepalived.conf.j2 vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority {{ vrrp }} advert_int 210 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { {{ ip_addr }} } } [root@ansible ansible.test]# cat setup.yml --- - hosts: all remote_user: root roles: - { role: keepalived,tags: ['keepalived','web'],when:ansible_nodename == "www8080.http.com"} - { role: nginx,tags: ['nginx','web']} [root@ansible ansible.test]# 在總控制的劇本里面加入tags標籤,並加入判斷,當主機名等於指定的名稱以後才裝keep。 ansible-playbook --tags="keepalived" setup.yml 在執行的時候加上標籤來執行 [root@ansible ansible.test]# ansible all -m shell -a 'ps -aux | grep keepalived' 192.168.219.137 | SUCCESS | rc=0 >> root 8382 0.0 0.1 106096 1128 pts/1 S+ 08:24 0:00 /bin/sh -c ps -aux | grep keepalived root 8384 0.0 0.0 103308 852 pts/1 S+ 08:24 0:00 grep keepalivedWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ 192.168.219.136 | SUCCESS | rc=0 >> root 10398 0.0 0.1 110276 1088 ? Ss 08:23 0:00 /usr/sbin/keepalived -D root 10400 0.0 0.2 114584 2944 ? S 08:23 0:00 /usr/sbin/keepalived -D root 10401 0.0 0.2 114452 2024 ? S 08:23 0:00 /usr/sbin/keepalived -D root 10440 0.0 0.1 106096 1128 pts/1 S+ 08:24 0:00 /bin/sh -c ps -aux | grep keepalived root 10442 0.0 0.0 103308 856 pts/1 S+ 08:24 0:00 grep keepalivedWarning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ [root@ansible ansible.test]# ansible all -m shell -a 'hostname' 192.168.219.137 | SUCCESS | rc=0 >> www9090.http.com 192.168.219.136 | SUCCESS | rc=0 >> www8080.http.com 能夠看到總程序能自動判斷並安裝相應的程序