Ansible是一個簡單的自動化運維管理工具,基於Python語言實現,由Paramiko和PyYAML兩個關鍵模塊構建,可用於自動化部署應用、配置、編排task(持續交付、無宕機更新等)。html
主版本大概每2個月發佈一次。 node
Ansible官網:https://www.ansible.com/
github地址:https://github.com/Ansible
Ansible具備以下特色:
部署簡單,只需在主控端部署Ansible環境,被控端無需作任何操做;
默認使用SSH協議對設備進行管理;
主從集中化管理;
配置簡單、功能強大、擴展性強;
支持API及自定義模塊,可經過Python輕鬆擴展;
經過Playbooks來定製強大的配置、狀態管理;
對雲計算平臺、大數據都有很好的支持;
提供一個功能強大、操做性強的Web管理界面和REST API接口——AWX平臺。
Ansible無需在被控主機部署任何客戶端代理,默認直接經過SSH通道進行遠程命令執行或下發配置:具有功能強大、靈活的系統管理、狀態配置,二者都提供豐富的模板及API,對雲計算平臺、大數據都有很好的支持。python
rpm包安裝:EPEL源linux
yum install ansible
編譯安裝nginx
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto tar xf ansible-1.5.4.tar.gz cd ansible-1.5.4 python setup.py build python setup.py install mkdir /etc/ansible cp -r examples/* /etc/ansible
Git方式:git
git clone git://github.com/ansible/ansible.git --recursive cd ./ansible source ./hacking/env-setup
pip安裝: pip是安裝Python包的管理器,相似yumgithub
yum install python-pip python-devel yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel pip install --upgrade pip pip install ansible --upgrade 確認安裝: ansible --version
/etc/ansible/ansible.cfg 主配置文件,配置ansible工做特性 /etc/ansible/hosts 主機清單 /etc/ansible/roles/ 存放角色的目錄
程序web
/usr/bin/ansible 主程序,臨時命令執行工具 /usr/bin/ansible-doc 查看配置文檔,模塊功能查看工具 /usr/bin/ansible-galaxy 下載/上傳優秀代碼或Roles模塊的官網平臺 /usr/bin/ansible-playbook 定製自動化任務,編排劇本工具/usr/bin/ansible-pull 遠程執行命令的工具 /usr/bin/ansible-vault 文件加密工具 /usr/bin/ansible-console 基於Console界面與用戶交互的執行工具
在ansible的安裝目錄下有兩個比較重要的目錄,bin目錄和examples目錄,bin目錄下存放着全部的可執行命令,examples目錄是配置文件的樣板文件。正則表達式
一、編輯或建立/etc/ansible/hosts文件,添加可管理主機shell
[ansibleserver](自定義主機清單) 192.168.130.6 [testservers] (自定義主機清單) 192.168.130.7 192.168.130.8
二、配置無密碼登陸
# ssh-keygen -t rsa -p ' ' (-p指定生成密鑰密碼) # ssh-copy-id 192.168.130.6 # ssh-copy-id 192.168.130.7 # ssh-copy-id 192.168.130.8
/etc/ansible/hosts 默認主機清單文件,inventory file能夠有多個,且也能夠經過Dynamic Inventory來動態生成
Inventory文件遵循INI文件風格,中括號中的字符爲組名。能夠將同一個主機同時歸併到多個不一樣的組中;此外,當如若目標主機使用了非默認的SSH端口,還能夠在主機名稱以後使用冒號加端口號來標明。
格式1: host:[port] 格式2: [groupname] host1 host2 host3 格式3: [groupname] host[1:3]
配置文件/etc/ansible/ansible.cfg (通常保持默認)
inventory = /etc/ansible/hosts #主機清單文件 library = /usr/share/my_modules/ #庫文件存放目錄 remote_tmp = ~/.ansible/tmp #臨時py命令文件存放在遠程主機目錄 local_tmp = ~/.ansible/tmp #本機的臨時命令執行目錄 forks = 5 #默認併發數 sudo_user = root #默認sudo用戶 ask_sudo_pass = True #每次執行ansible命令是否詢問ssh密碼 remote_port = 22 #遠程主機端口號 host_key_checking = False #禁用第一次鏈接的key檢查 log_path = /var/log/ansible.log #默認ansible不記錄日誌,啓用此項開啓日誌記錄
用法:ansible <host-pattern> [-m module_name] [-a args]
選項:
host-pattern:
用法:ansible-doc [options] [module...]
選項:
從網站上下載對應的roles(https://galaxy.ansible.com)
執行.yml劇本文件
管理加密解密yml文件
ansible的交互式終端,root@all (3)[f:5]$:執行用戶@當前操做的主機組 (當前組的主機數量)[f:併發數]$
推送命令至遠程,支持直接從git下載playbook執行,須要遵循其規定的目錄格式,用處不是特別大
1)command 不支持管道、變量和管道,只支持簡單功能,須要使用shell模塊
removes=/path/file 若是文件不存在則不執行
creates=/path/file 若是文件存在則不執行
chdir=/path/file 進入指定文件夾
~]# ansible all -a 'df -h' ~]# ansible all -m command -a 'chdir=/data ls'
2)shell 和command模塊用法相同,可是支持管道、變量和管道等複雜命令
~]# ansible all -m shell -a 'echo $HOSTNAME'
3)script 在遠程主機上執行本地腳本
--some-arguments 1234 指定參數
~]# ansible all -m script -a '/root/ansible/host.sh'
4)copy 將本地文件複製至遠程主機
backup 複製覆蓋時先備份
content 指定一些內容當文件複製
dest 目標路徑
mode 權限
owner 全部者
src 源路徑
~]# ansible all -m copy -a 'src=/root/ansible/selinux dest=/etc/selinux/config backup=yes' ~]# ansible all -m copy -a 'content="hello world" dest=/data/f1'
5)fetch 從遠程主機文件複製到本地,必須是一個文件,在本地目錄下會生成主機名對應的文件夾,文件存放於文件夾中按遠程主機上的目錄結構
dest 本地的一個目錄
src 遠程主機系統上的一個文件(必須)
~]# ansible all -m fetch -a 'src=/var/log/messages dest=/data'
6)archive 打包文件
7)unarchive 解包文件
8)file 建立,刪除,設置文件屬性
state= directory | touch | link | hard | absent 目錄,空文件,軟連接,硬連接,遞歸刪除
dest | name | path= 路徑
src= 建立軟連接時的原文件
mode= 權限
owner= 所屬者
~]# ansible all -m file -a 'name=/data/testfile.ans state=touch' ~]# ansible all -m file -a 'name=/data/dir1 state=directory' ~]# ansible all -m file -a 'src=/etc/fstab dest=/data/f2 state=link'
9)hostname 設置主機名,當即生效而且同步至配置文件
name= 主機名
~]# ansible 192.168.130.11 -m hostname -a 'name=node1'
10)cron 任務計劃
name 名稱
job 做業
disabled=true | false 禁用|啓用
state=absent 刪除
day 天
hour 小時
minute 分鐘
month 月
weekday 星期
~]# ansible all -m cron -a 'minute=* weekday=1,3,5 job="/usr/bin/wall FBI warning" name=warningcron' ~]# ansible all -m cron -a 'disabled=true job="/usr/bin/wall FBI warning" name=warningcron'
11)yum 管理軟件包模塊
list=installed 列出已安裝的軟件包
name= 包名稱
state= present | absent latest 安裝 | 卸載 | 安裝最新版
disable_gpg_check=yes 臨時禁用gpg檢查
update_cache=yes 更新yum緩存
~]# ansible all -m yum -a 'name=vsftpd state=latest'
12)service 管理服務模塊
name 服務名
enabled=yes 開機啓動
state=started | stopped | restarted | reloaded 啓動 | 中止 | 重啓 | 重讀配置文件
~]# ansible all -m service -a 'name=vsftpd state=started enabled=yes'
13)user 用戶管理模塊
name= 用戶名
password= 密碼
remove= 刪除用戶及家目錄
system=yes 建立系統用戶
shell= 設置默認shell
~]# ansible all -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx groups=root,bin uid=80 comment="nginx service"' ~]# ansible all -m user -a 'name=nginx state=absent remove=yes'
14)group 組管理模塊
15)setup 獲取遠程主機的系統信息
filter=var 過濾查看變量參數
playbook是由一個或多個「play」組成的列表,play的主要功能在於將事先歸併爲一組的主機裝扮成事先經過ansible中的task定義好的角色。從根本上來說,所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中,便可以讓它們聯同起來按事先編排的機制同唱一臺大戲。
Playbook採用YAML語言編寫,YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其餘多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。
YAML Ain't Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思實際上是:"Yet Another Markup Language"(還是一種標記語言) http://www.yaml.org
基本格式:
playbook中的每個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用於指定要執行指定任務的主機,須事先定義在主機清單中。
remote_user: 可用於Host和task中。也能夠經過指定其經過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務;此外,甚至能夠在sudo時使用sudo_user指定sudo時切換的用戶
--- - hosts: all remote_user: root tasks: - name: see hostname command: hostname
...
play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的全部主機上執行,即在全部主機上完成第一個任務後再開始第二個。在運行自下而下某playbook時,若是中途發生錯誤,全部已執行任務都將回滾,所以,在更正playbook後從新執行一次便可
task的目的是使用指定的參數執行模塊,而在模塊參數中可使用變量。模塊執行是冪等的,這意味着屢次執行是安全的,由於其結果均一致
每一個task都應該有其name,用於playbook的執行結果輸出,建議其內容儘量清晰地描述任務執行步驟。若是未提供name,則action的結果將用於輸出
格式:module: arguments ,可是command模塊和shell模塊後直接寫命令
--- - hosts: websrvs
remote_user: root
tasks: #任務 - name: install httpd package #action yum: name=httpd #調用yum模塊,並向yum模塊傳遞name=httpd的參數 - name: copy configuration file for httpd copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: start httpd service service: name=httpd state=started ...
若是命令或腳本的退出碼不爲零,使用 ignore_errors:True 來忽略錯誤信息
變量名:僅能由字母、數字和下劃線組成,且只能以字母開頭
內建變量:facts,setup模塊到主機上收集的全部信息保存爲變量,能夠直接引用,列如 ansible_fqdn 變量用來保存主機名
# ansible all -m setup |grep ansible_fqdn "ansible_fqdn": "node1", "ansible_fqdn": "node2", "ansible_fqdn": "node3",
自定義變量賦值:
3.1.命令行直接賦值
ansible-playbook -e 'var=value'
3.2.在playbook中定義變量
vars:
- varname: value
3.3.在主機清單中定義變量
主機變量,直接在主機後定義,只對定義主機有效,優先級高於公共變量
host var=value
公共變量,對主機組內全部主機有效
[groupname:vars] 爲指定主機組自定義變量,vars爲關鍵字
varname=value
3.4.roles中變量在 ansible/roles/object/vars/main.yml 文件中直接定義
var:value
var2:value2
3.5.在.yml文件中直接定義,使用vars_files 關鍵字引用,例如:
# vim vars.yml var1: httpd var2: vstfpd # vim testvar.yml --- - hosts: all remote_user: root vars_files: - vars.yml tasks: - name: install package yum: name={{ var1 }} state=present - name: create file file: name=/data/{{ var2 }}.log state=touch ...
變量引用:命令行中定義的變量優先級最高
{{ varname }}
--- - hosts: websrvs remote_user: root vars: - package_name: httpd tasks: - name: install httpd package yum: name={{ package_name }} - name: copy configuration file for httpd copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: start httpd service service: name={{ package_name }} state=started ...
咱們爲了對不一樣配置的主機配置不一樣的配置,咱們不可能每次都要修改配置文件,全部就出現了模板技術,這樣咱們只要定義好一份模板,之後推送配置文件時會自動將配置文件模板中的變量替換爲目標主機的參數
templates功能:根據模塊文件動態生成對應的配置文件,ansible中模板使用jinja2語言編寫,第七節有關於jinja2的介紹
要求:
[root@centos7 ansible]# vim templates/httpd.conf.j2 ServerRoot "/etc/httpd" Listen 80 Include conf.modules.d/*.conf User apache Group apache ServerAdmin root@localhost ServerName {{ ansible_fqdn }}:80
[root@centos7 ansible]# vim temp_httpd.yml --- - hosts: all remote_user: root vars: - package_name: httpd - service_name: httpd tasks: - name: install package yum: name={{ package_name }} - name: copy config file template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: restart service - name: start service service: name={{ service_name }} state=started handlers: - name: restart service service: name={{ service_name }} state=started ...
[root@centos7 ansible]# tree . ├── temp_httpd.yml └── templates └── httpd.conf.j2
ansible_fqdn 變量表明主機名,是setup模塊返回的變量,能夠直接使用
Handlers是task列表,這些task與前述的task並無本質上的不一樣,用於當關注的資源發生變化時,纔會採起必定的操做;
notify這個action可用於在每一個play的最後被觸發,這樣能夠避免屢次有改變發生時每次都執行指定的操做,僅在全部的變化發生完成後一次性地執行指定操做。在notify中列出的操做稱爲handler,也即notify中調用handler中定義的操做。
--- - hosts: websrvs
remote_user: root tasks: - name: install httpd package yum: name=httpd - name: copy configuration file for httpd copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: restart service - name: start httpd service service: name=httpd state=started handlers: - name: restart service service: name=httpd state=restarted ...
當copy的配置文件發生改變時則執行重啓服務的功能,這是必須的
爲action打上一個標籤,可使用ansible-playbook -t 來指定標籤名,用來只執行單個action
--- - hosts: websrvs
remote_user: root tasks: - name: install httpd package yum: name=httpd - name: copy configuration file for httpd copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf tags: put_config_file - name: start httpd service service: name=httpd state=started tags: start_service ...
使用 ansible-playbook --list-tags httpd.yml 命令查看playbook中的標籤
ansilbe自1.2版本引入的新特性,用於層次性、結構化地組織playbook。roles可以根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只須要在playbook中使用include指令便可。簡單來說,roles就是經過分別將變量、文件、任務、模板及處理器放置於單獨的目錄中,並能夠便捷地include它們的一種機制。角色通常用於基於主機構建服務的場景中,但也能夠是用於構建守護進程等場景中。
建立role的步驟:
1) 建立以roles命名的目錄;
2) 在roles目錄中分別建立以各角色名稱命名的目錄,如webservers等;
3) 在每一個角色命名的目錄中分別建立files、handlers、tasks、templates和vars目錄;用不到的目錄能夠建立爲空目錄,也能夠不建立;
4) 在playbook文件中,經過Includes調用各角色。
[root@centos7 ansible3]# mkdir -p roles/project/{tasks,files,vars,templates,handlers,default,meta} [root@centos7 ansible3]# tree . └── roles └── project ├── default ├── files ├── handlers ├── meta ├── tasks ├── templates └── vars 9 directories, 0 files
各目錄做用介紹:
示例:簡單的構建一個role
1)建立目錄框架
[root@centos7 ansible]# mkdir -p roles/httpd/{tasks,templates,files,handlers} [root@centos7 ansible]# tree . └── roles └── httpd ├── files ├── handlers ├── tasks └── templates
2)編寫任務
[root@centos7 ansible]# vim roles/httpd/tasks/yum.yml - name: install httpd yum: name=httpd state=present [root@centos7 ansible]# vim roles/httpd/tasks/copy.yml - name: copy config file template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: restart service - name: copy index.html copy: src=index.html dest=/var/www/html/ owner=apache [root@centos7 ansible]# vim roles/httpd/tasks/start.yml - name: start httpd service: name=httpd state=started [root@centos7 ansible]# vim roles/httpd/tasks/main.yml - include: yum.yml - include: copy.yml - include: start.yml
3)配置模板和主頁測試文件
[root@centos7 ansible]# cp /etc/httpd/conf/httpd.conf roles/httpd/templates/httpd.conf.j2 [root@centos7 ansible]# vim roles/httpd/templates/httpd.conf.j2 ServerName www.{{ ansible_fqdn }}.com:80 [root@centos7 ansible]# vim roles/httpd/files/index.html <h1>The is a test website.</h1>
4)定義handlers,使得配置文件模板改變後能夠重啓服務
[root@centos7 ansible]# vim roles/httpd/handlers/main.yml - name: restart service service: name=httpd state=restarted
[root@centos7 ansible]# tree . └── roles └── httpd ├── files │ └── index.html ├── handlers │ └── main.yml ├── tasks │ ├── copy.yml │ ├── main.yml │ ├── start.yml │ └── yum.yml └── templates └── httpd.conf.j2
5)角色已經編寫完成,咱們只須要在roles目錄的同級目錄下編寫playbook,在playbook中直接使用角色所定義的任務
[root@centos7 ansible]# vim httpd.yml --- - hosts: websvrs remote_user: root roles: - httpd ...
6)最後,一個簡單的角色就定義完成了,接下來咱們去測試
[root@centos7 ansible]# ansible-playbook -C httpd.yml #先空跑一下,沒有問題再實際執行
[root@centos7 ansible]# ansible-playbook httpd.yml
[root@centos7 ansible]# curl 192.168.130.10 <h1>The is a test website.</h1> [root@centos7 ansible4]# curl 192.168.130.11 <h1>The is a test website.</h1>
# 和咱們所預期的操做同樣,那麼之後能夠向這個角色中添加更爲豐富的功能
字符串:使用單引號或雙引號
列表:[ item1, item2, ... ]
元組:( item1, item2, ... )
字典:{ key1:value1, key2:value2, ... }
算術運算
+ 把兩個對象加到一塊兒。一般對象是素質,可是若是二者是字符串或列表,你能夠用這 種方式來銜接它們。不管如何這不是首選的鏈接字符串的方式!鏈接字符串見 ~ 運算符。 {{ 1 + 1 }} 等於 2 - 用第一個數減去第二個數。 {{ 3 - 2 }} 等於 1 / 對兩個數作除法。返回值會是一個浮點數。 {{ 1 / 2 }} 等於 {{ 0.5 }} // 對兩個數作除法,返回整數商。 {{ 20 // 7 }} 等於 2 % 計算整數除法的餘數。 {{ 11 % 7 }} 等於 4 * 用右邊的數乘左邊的操做數。 {{ 2 * 2 }} 會返回 4 。也能夠用於重 復一個字符串屢次。 {{ ‘=’ * 80 }} 會打印 80 個等號的橫條
worker_processes {{ ansible_processor_vcpus*2 }}; #被控端的cpu核心數*2
比較操做符
== 比較兩個對象是否相等 != 比較兩個對象是否不等 > 若是左邊大於右邊,返回 true >= 若是左邊大於等於右邊,返回 true < 若是左邊小於右邊,返回 true <= 若是左邊小於等於右邊,返回 true
邏輯運算符
and 若是左操做數和右操做數同爲真,返回 true or 若是左操做數和右操做數有一個爲真,返回 true not 對一個表達式取反(見下) (expr) 表達式組
條件測試:when
條件測試:若是須要根據變量、facts或此前任務的執行結果來作爲某task執行與否的前提時要用到條件測試,經過when語句實現,在task中使用
--- - hosts: all remote_user: root vars: - package_name: httpd - service_name: httpd tasks: - name: install package yum: name={{ package_name }} - name: copy config file template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: restart service - name: start service service: name={{ service_name }} state=started when: ansible_fqdn == "node2" #只有主機名是 node2 的節點啓動web服務 handlers: - name: restart service service: name={{ service_name }} state=started
迭代:with_items
當有須要重複性執行的任務時,可使用迭代機制,要在task中使用with_items給定要迭代的元素列表。使用item變量引用列表中的變量
--- - hosts: all remote_user: root tasks: - name: create some files file: name=/data/{{ item }} state=touch with_items: - file1 - file2 - file3 - name: install some package yum: name={{ item }} with_items: - httpd - vsftpd - htop - dstat - iftop - sl - iotop - hping3 ...
迭代中嵌套子變量
- hosts: all remote_user: root tasks: - name: create some groups group: name={{item}} with_items: - g1 - g2 - g3 - name: ceate some users user: name={{item.name}} group={{item.group}} with_items: - { name: 'user1', group: 'g1' } - { name: 'user2', group: 'g2' } - { name: 'user3', group: 'g3' } ...
for循環
for語句在templates文件中使用
[root@centos7 ansible]# vim testfor.yml --- - hosts: all remote_user: root vars: ports: - 81 - 82 - 83 tasks: - name: copy config file template: src=for1.conf.j2 dest=/data/for1.conf ... [root@centos7 ansible]# vim templates/for.conf.j2 {% for p in ports %} server{ listen {{ p }} } {% endfor %}
也可使用for來遍歷列表
[root@centos7 ansible]# vim testfor2.yml --- - hosts: all remote_user: root vars: ports: - http_port: 81 - http_port: 82 - http_port: 83 tasks: - name: copy config file template: src=for2.conf.j2 dest=/data/for2.conf ... [root@centos7 ansible]# vim templates/for2.conf.j2 {% for p in ports %} server{ listen {{ p.http_port }} } {% endfor %}
以上的模板生成的結果:
server{ listen 81 } server{ listen 82 } server{ listen 83 }
if判斷
if語句在templates文件中使用
[root@centos7 ansible]# cat testif.yml --- - hosts: all remote_user: root vars: ports: - web1: port: 81 name: web1.test.com rootdir: /data/website1 - web1: port: 82 name: web2.test.com rootdir: /data/website2 - web1: #port: 83 name: web3.test.com rootdir: /data/website3 tasks: - name: copy config file template: src=if.conf.j2 dest=/data/if.conf ... [root@centos7 ansible]# cat templates/if.conf.j2 {% for i in ports %} server{ {% if i.port is defined %} #這個判斷的意思是若是變量i.port,也就是ports中的port變量,沒有配置,則這個語句塊則不生效 Listen {{ i.port }} {% endif %} ServerName {{ i.name }} Documentroot {{ i.rootdir }} } {% endfor %}