Ansible
ansible部署{keepalived+nginx{httpd, mysql, php}}
ansible簡介
Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine.
Ansible是一款輕量級自動化運維工具,由Python語言開發,結合了多種自動化運維工具的特性,實現了批量系統配置、批量應用部署、批量命令執行等功能;ansible是基于模塊化實現批量操作的。
ansible特點:
模塊化、部署簡單、工作于agentless模式、默認使用ssh協議、支持自定義模塊、支持Palybook等
-
Ansible: 核心程序;
-
Modules: 包括 Ansible 自帶的核心模塊及自定義模塊;
-
Plugins: 完成模塊功能的補充,包括連接插件、郵件插件等;
-
Playbooks: 網上很多翻譯為劇本,個人覺得理解為編排更為合理;定義 Ansible 多任務配置文件,有 Ansible 自動執行;
-
Host Inventory: 定義 Ansible 管理主機的清單,ansible只能管理Inventory中定義的主機
使用Paramiko,PyYAML和Jinja2三個Python的核心庫實現
部署簡單:agentless;
支持自定義模塊,使用任意語言編寫
問題:不同環境的目標系統如何對相同服務定制不同配置
如讓httpd偵聽在不同的端口之上。
安裝ansible
解決依賴關系
1.yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
ansible程序包被Fedora-epel所收入,因此安裝前需配置好epel倉庫的yum源;
1.yum install ansible
使用ansible前提條件
ansible基于SSH連接至host,因此有必要讓ansible通過ssh-key連接主機。為了避免Ansible下發指令時輸入目標主機密碼,通過證書簽名達到SSH無密碼是一個好的方案,推薦使用ssh-keygen與ssh- copy-id來實現快速證書的生成和公鑰下發,其中ssh-keygen生成一對密鑰,使用ssh-copy-id來下發生成的公鑰。具體操作如下:
-
生成 SSH公玥和私鑰文件
ssh-kengen -t rsa -P ' '
-
拷貝公玥文件到目標主機的ssh認證文件中
ssh-copy-id -i ~/.ssh/id_rsa.pub root@HostIP
-
連接測試
ssh root@HostIP
注意: 如果不配置主機免密鑰登錄,可以在/etc/ansible/hosts中定義用戶和密碼,主機ip地址,和ssh端口,這樣也可以進行免密碼訪問,但是這個/hosts文件要保護好。
主要文件
程序:/usr/bin/ansible
, /usr/bin/ansible-playbook
, /usr/bin/ansible-doc
配置文件:/etc/ansible/ansible.cfg
主機清單:/etc/ansible/hosts
插件目錄:/usr/share/ansible_plugins
配置文件
Host Inventory
Inventory是一個簡單的從外部資源尋找主機,主機組的成員,和變量信息的程序 – 可以是個 SQL 數據庫,一個 CMDB 解決方案,或者是 LDAP。這個概念來自 Puppet (叫”External Nodes Classifier”),工作方式也是類似的。
Ansible 通過讀取默認的主機清單配置/etc/ansible/hosts,可以同時連接到多個遠程主機上執行任務,默認路徑可以通過修改 ansible.cfg 的 hostfile 參數指定路徑。
在主機清單文件中定義host組,便于執行命令時指定在哪些主機使用,也可在palybook文件調用這些定義好的主機名稱。
1.[dbserver] []表示主機的分組名,可以按照功能,系統進行分類,便于進行操作
2.192.168.10.2
3.one.example.com
4.www.bds.com:5309 #支持指定ssh端口5309
5.jumper ansible_ssh_port=5309 ansible_ssh_host=192.168.10.2 #設置主機別名為jumper
6.www[01:50].bds.com #支持通配符匹配www01.bds.com www02.bds.com
7.[web] #提醒下這里面字母是隨便定義的
8.web-[a:f].bds.com #支持字母匹配 web-a.bds.com ..web-f.bds.com
9.
10.# 為主機指定類型和連接用戶
11.[bds]
12.Localhost ansible_connection=local
13.other1.example.com ansible_connection=ssh ansible_ssh_user=deploy
14.other2.example.com ansible_connection=ssh ansible_ssh_user=deploy
15.ansible hosts配置文件中支持指令等
1, ansible_ssh_host :
指定主機別名對應的真實 IP,如:100 ansible_ssh_host=192.168.1.100,隨后連接該主機無須指定完整 IP,只需指定 100 即可
2, ansible_ssh_port :
指定連接到這個主機的 ssh 端口,默認 22
3, ansible_ssh_user:
連接到該主機的 ssh 用戶
4, ansible_ssh_pass:
連接到該主機的 ssh 密碼(連-k 選項都省了),安全考慮還是建議使用私鑰或在命令行指定-k 選項輸入
5, ansible_sudo_pass: sudo 密碼
6, ansible_sudo_exe: sudo 命令路徑
7, ansible_connection :
連接類型,可以是 local、ssh 或 paramiko,ansible1.2 之前默認為 paramiko
8, ansible_ssh_private_key_file : 私鑰文件路徑
9, ansible_shell_type :
目標系統的 shell 類型,默認為 sh,如果設置 csh/fish,那么命令需要遵循它們語法
10, ansible_python_interpreter :
python 解釋器路徑,默認是/usr/bin/python,但是如要要連BSD系統的話,就需要該指令修改 python 路徑
11, ansible__interpreter :
這里的”*”可以是 ruby 或 perl 或其他語言的解釋器,作用和 ansible_python_interpreter 類似
ansible.cfg
默認的forks=5,即一次fork 5個ansible進程與目標主機通信,fact緩存路徑等
如:
1.[defaults]
2.gathering = smart
3.fact_caching = redis
4.fact_caching_timeout = 86400
5.# seconds
命令使用
ansible
1.ansible <host-pattern> [-f forks] [-m module_name] [-a "args"]
2. -m MODULE_NAME # 默認為command,可省略
3. -a MODULE_ARGS, --args=MODULE_ARGS # 除了shell和command以為的模塊都有內置的Args
4. -k,-ask-pass # 提示輸入ssh的密碼,而不是使用基于ssh的密鑰認證
5. -sudo # 指定使用sudo獲得root權限
6. -K,-ask-sudo-pass # 提示輸入sudo密碼,與–sudo一起使用
7. -C,-check # 測試此命令執行會改變什么內容,不會真正的去執行
ansible-doc
Show Ansible module documentation
1.ansible-doc -h
2.ansible-doc -l # List available modules
3.ansible-doc -s module_name # Show playbook snippet for specified module(s)
ansible-playbook
1.ansible-playbook [options] <filename.yml>
2.
3.#tags指定與查看
4. --list-tags
5. -t, TAGS_NAME, --tags=TAGS
6. --skip-tags=SKIP_TAGS
7. --start-at-task=START_AT
8.
9.#測試執行
10. --list-hosts # 受影響的host
11. --list-tasks # 會執行的tasks
12.
13.#傳遞變量
14. -e VARNAME=VALUE, --extra-vars=VARS #內部預制變量可被-e覆蓋
15.
16.#額外的主機清單、fork進程數
17. -i PATH, --inventory=PATH
18. -f NUM, --forks=NUM
19.
20.#檢查語法,模擬執行
21. --syntax-check # perform a syntax check on the playbook
22. -C, --check # don't make any changes; instead, try to predict some of the changes that may occur
常用模塊
-
ping:探測目標主機是否存活;
-
command:在遠程主機執行命令;默認的module
ansible all -m command -a "hostname "
-
shell:在遠程主機上調用shell解釋器運行命令,支持shell的各種功能,例如管道等 ;
ansible all -m shell -a "cat /etc/passwd| grep root "
注意:command和shell模塊的核心參數直接為命令本身;而其它模塊的參數通常為“key=action”格式; -
copy: C o p i e s f i l e s t o r e m o t e l o c a t i o n s .
用法:
(1) 復制文件:-a “src= dest= ”
(2) 給定內容生成文件:-a “content= dest= ”
其它參數:mode, owner, group, … -
file:S e t s a t t r i b u t e s o f f i l e s
用法:
(1) 創建目錄:-a “path= state=directory”
(2) 創建鏈接文件:-a “path= src= state=link”
(3) 刪除文件:-a “path= state=absent“ -
fetch:F e t c h e s a f i l e f r o m r e m o t e n o d e s
-
cron:M a n a g e c r o n . d a n d c r o n t a b e n t r i e s .
-a ” ”
minute=
hour=
day=
month=
weekday=
job=
name=
user=
state={present|absent} -
hostname:M a n a g e h o s t n a m e
name= -
yum:M a n a g e s p a c k a g e s w i t h t h e I ( y u m ) p a c k a g e m a n a g e r
(1) name= state={present|latest}
(2) name= state=absent -
service:M a n a g e s e r v i c e s .
name=
state={started|restarted|stoped|reloaded}
started
stopped
restarted
enabled=
runlevel= -
group: A d d o r r e m o v e g r o u p s
name=
state=
system=
gid=
state={present|absent}ansible db -m group -a 'name=test gid=1000'
-
user:M a n a g e u s e r a c c o u n t s
name=
group=
groups=
comment=
uid=
system=
shell=
expires=
home=
state={present|absent}ansible all -m user -a 'name=DBA uid=505 home=/Data/dba shell=/sbin/nologin'
ansible db -m user -a 'name=budongshu uid=506 state=absent'
-
setup:G a t h e r s f a c t s a b o u t r e m o t e h o s t s
收集系統信息,作為可用的變量:
“device”: “eno16777736”
“address”: “10.1.22.106”
“ansible_distribution”: “CentOS”
“ansible_distribution_major_version”: “7”
“ansible_fqdn”: “localhost.localdomain”,
“ansible_hostname”: “cent6”,
“ansible_interfaces”: [
“lo”,
“eth1”,
“eth0”
],
……
結構體類型的fact引用:
{{ ansible_eth0.ipv4.address }}
{{ ansible_eth0[“ipv4”][“address”] }}
{{ ansible_all_ipv4_addresses[0] }} -
template
template使用了Jinjia2格式作為文件模板,進行文檔內變量的替換的模塊。他的每次使用都會被ansible標記為changed狀態。 -
script:自動復制腳本到遠程節點,并運行
ansible all -m script -a 'ansible_test.sh'
ansible各模塊簡單示例
1.ansible websrv -m ping
2.ansible all -m command -a "ifconfig"
3.ansible all -m shell -a "echo alice|passwd --stdin alice"
4.ansible all -m copy -a "content='hello\n1' dest=/tmp/test.ansible mode=640"
5.
6.ansible all -m file -a "path=/tmp/test.ansible mode=777"
7.ansible all -m file -a "path=/tmp/test.ansible state=absent"
8.ansible all -m file -a "path=/tmp/testdir state=directory"
9.ansible all -m file -a "path=/tmp/test.ansible.link src=/tmp/test.ansible state=link"
10.
11.ansible all -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 10.1.0.1 &> /dev/null' name=ntptime"
12.ansible all -m cron -a "name=ntptime state=absent"
13.
14.ansible all 10.1.0.68 -m setup
15.
16.ansible websrv -m yum -a "name=httpd state=present"
17.
18.ansible websrv -m service -a "name=httpd state=started enabled=true"
ansible playbooks
playbook是由一個或多個“play”組成的列表。play的主要功能在于將事先歸并為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講,所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中,即可以讓它們聯同起來按事先編排的任務一項一項執行,一項task可能指定了多個host,且默認并行執行5個fork進程。
playbook內容組成
-
核心元素:
-
tasks:任務,有模塊定義的操作列表
-
vas:變量
-
tempaltes:模板,使用了Jinjia2格式作為文件模板
-
handlers:由特定條件觸發的Tasks;
-
roles:角色
-
基本組件
-
Hosts:指定目標主機
-
remote_user:在遠程主機上以哪個用戶身份執行;
sudo_user:非管理員需要用于sudo權限 -
tasks:任務列表
模塊:模塊參數
格式:
(1)action: module arguments
如: name、tags、with_items、notify、when、……
(2)module: arguments
如: yum、copy、template、service、command、shell、……
host、user
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用于指定要執行指定任務的主機,其可以是一個或多個由冒號分隔主機組;remote_user則用于指定遠程主機上的執行任務的用戶,如
1.- hosts: webnodes
2. remote_user: root
remote_user也可用于各task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務,其可用于play全局或某任務;此外,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶。
1.- hosts: webnodes
2. remote_user: root
3. tasks:
4. - name: test connection
5. ping:
6. remote_user: alice
7. sudo: yes
vars
和 Facts 相反, 變量是一些值,或字典,列表的名稱(可以是標量值–整數,布爾型,或字符串,字典,列表),然后變量可以應用在模板和劇本里面。他們是聲明的東西,不是獲取遠程系統的當前狀態或性質(這是Facts)
(1) 內置的facts變量通過 setup 模塊獲??;
(2) 自定義變量:
-
命令行傳遞;
1.ansible-playbook -e VAR=VALUE playbook.yml
-
Inventory還可以使用參數:
用于定義ansible遠程連接目標主機時使用的屬性,而非傳遞給playbook的變量;
1. ansible_ssh_host
2. ansible_ssh_port
3. ansible_ssh_user
4. ansible_ssh_pass
5. ansible_sudo_pass
6. ...
-
在playbook中定義變量
1. - hosts: webservers
2. vars:
3. http_port: 80
-
在hosts Inventory中為每個主機定義專用變量值;
(a) 向不同的主機傳遞不同的變量 ;IP/HOSTNAME variable_name=value
(b) 向組內的所有主機傳遞相同的變量 ;[groupname:vars]
variable_name=value
-
在角色調用時傳遞
1.roles:
2.- { role: ROLE_NAME, var: value, ...}
-
調用方式:
{{ var_name }} -
結構體類型的fact變量引用:
{{ ansible_eth0.ipv4.address }}
{{ ansible_eth0[“ipv4”][“address”] }}
{{ ansible_all_ipv4_addresses[0] }} -
變量優先級總結:
命令行傳遞的外部變量優先級高;vars定義的變量優先級大于host Iventroy傳遞的變量,具體如下: -
extra vars (在命令行中使用 -e)優先級最高
-
然后是在inventory中定義的連接變量(比如ansible_ssh_user)
-
接著是大多數的其它變量(命令行轉換,play中的變量,included的變量,role中的變量等)
-
然后是在inventory定義的其它變量
-
然后是由系統發現的facts
-
然后是 “role默認變量”, 這個是最默認的值,很容易喪失優先權
命令行傳遞變量
1.- hosts: websrv
2. remote_user: root
3. tasks:
4. - name: install rpm
5. yum: name={{ rpmName }} state=
6.
7.ansible-playbook -C -e rpmName=vsftpd web.yml
playbook文件定義變量
1.- hosts: websrv
2. remote_user: root
3. vars:
4. - rpmName=memcached
5. - rpmName=mysql
6. tasks:
7. - name: install rpm
8. yum: name={{ rpmName }}
hosts Inventory傳遞變量
1.[websrv]
2.10.1.0.6 rpmName=httpd
3.10.1.0.7 rpmName=nginx
Inventory組共用變量
1.[websrv]
2.10.1.0.6 rpmName=httpd
3.10.1.0.7 rpmName=nginx
4.
5.[websrv:vars]
6.rpmName=nginx
用于定義ansible遠程連接目標主機時使用的屬性,而非傳遞給playbook的變量
1.[websrv]
2.10.1.0.6 ansible_ssh_user= ansible_ssh_pass= ansible_sudo_pass=
3.10.1.0.7 rpmName=nginx
調用role時傳遞變量
1.roles:
2. - { role: apache, http_port: 8080 }
3. - { role: app_user, name: Terry }
4. - { role: app_user, name: John }
handlers
用于當關注的資源發生變化時采取一定的操作?!皀otify”這個action可用于在每個play的最后被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之,僅在所有的變化發生完成后一次性地執行指定操作。在notify中列出的操作稱為handler,也即notify中調用handler中定義的操作。這意味著服務可以被反彈僅僅他們需要重啟的時候。Handler 不僅僅可以用于重啟服務,但是重啟服務是最通用的用法。
1.- name: template configuration file
2. template: src=template.j2 dest=/etc/foo.conf
3. notify:
4. - restart memcached
5. - restart apache
6.
7.#handler是task列表,這些task與前述的task并沒有本質上的不同。
8. handlers:
9. - name: restart memcached
10. service: name=memcached state=restarted
11. - name: restart apache
12. service: name=apache state=restarted
tasks
play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務后再開始第二個。在運行自下而下某playbook時,如果中途發生錯誤,所有已執行任務都將回滾,因此,在更正playbook后重新執行一次即可。
task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致。
每個task都應該有其name,用于playbook的執行結果輸出,建議其內容盡可能清晰地描述任務執行步驟。如果未提供name,則action的結果將用于輸出。
Tags
Ansible 允許給playbook里面的資源通過自定義的關鍵字打上標簽,然后只運行與關鍵字一致的部分代碼。 例如,可能有個完成的 OS 配置,然后特定的步驟標記為 “ntp” ,然后運行 “ntp” 步驟來重新配置時間服務器信息。
1.tasks:
2. tags: ntp
template
Ansible 很容易的傳輸文件到遠端系統上面,但是它經常需要替換一些變量在其它的文件里面。變量可以來自 清單文件,Host Vars, Group Vars,或者 Facts。Templates 使用 Jinja2 模板引擎同樣可以包含邏輯控制像循環和 if 語句。
Jinja2 is a template engine written in pure Python. It provides a Django inspired non-XML syntax but supports inline expressions and an optional sandboxed environment.
Jinja2語法介紹:
-
字面量:
字符串:使用單引號或雙引號;
數字:整數、浮點數;
列表:[item1, item2, …]
元組:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布爾型:true/false -
算術運算:
+, -, , /, //, %, * -
比較操作:
==, !=, >, <, >=, <= -
邏輯運算:and, or, not
執行模板文件中的腳本,并生成結果數據流,需要使用template模塊;
1.template:
2. src=
3. dest=
4. mode=
5. onwer=
6. group=
此外,template模塊只能在playbook文件中使用,不能在命令行調用
【nothing】ansible websrvs -m copy -a “src=/root/nginx.conf dest=/tmp/nginx.conf”
【error】ansible websrvs -m template -a “src=/root/nginx.conf dest=/tmp/nginx.conf”
例:在nginx配置文件中使用模板變量
1.- hosts: wevsrv
2. remote_user: root
3. tasks:
4. - name: install rpm
5. yum: name=nginx state=latest
6. template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
7. tags: newconf
8. notify: reload nginx
9. - name: start nginx
10. service: name=nginx state=started enabled=true
11. handlers:
12. - name: relaod nginx
13. shell: /usr/sbin/nginx -s reload
14.
15.vi nginx.conf
16. worker_processes {{ ansible_process_vcpus }}
when條件測試
一個可選的關鍵字來決定這個任務是不是應該指向,如果再 “when:” 關鍵字這里的表達式是是不正確的,這個任務會被忽略。When語句包含Jinja2表達式。
1.tasks:
2. - name:
3. when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
4.
5.tasks:
6. - command: echo {{ item }}
7. with_items: [ 0, 2, 4, 6, 8, 10 ]
8. when: item > 5
9.
10.roles:
11. - { role: amp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
item循環
需要重復執行的任務,如同時安裝一組程序或者重復一個輪詢步驟直到收到某個特定結果。
對迭代項的引用,固定變量名為”item”,使用with_item屬性給定所有的元素列表:
-
元素列表:字符串,字典
(1)基于字符串的循環列表(行值)
1. - hosts: wevsrv
2. remote_user: root
3. tasks:
4. - name: install rpm
5. yum: name={{ item }} state=latest
6. with_items:
7. - httpd
8. - php
9. - php-mysql
10. - php-mbstring
11. - php-gd
12. - mysql-server
13. - mysql
(2) 基于字典的循環列表
相當于給同一個action設定不同的值(列值)
1. - hosts: all
2. remote_user: root
3. tasks:
4. - name: create groups
5. yum: name={{ item }} state=present
6. with_items:
7. - ops1
8. - ops2
9. - name: create users
10. user: name={{ item.name }} group={{ item.group }} state=present
11. with_items:
12. - { name: 'h1', group: 'ops1' }
13. - { name: 'h2', group: 'ops2' }
PyYAML庫
YAML is a data serialization format designed for human readability and interaction with scripting languages.
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”(仍是一種標記語言)。其特性有:
YAML的可讀性好
YAML和腳本語言的交互性好
YAML使用實現語言的數據類型
YAML有一個一致的信息模型
YAML易于實現
YAML可以基于流來處理
YAML表達能力強,擴展性好
更多的內容及規范參見:http://www.yaml.org
YAML語法
YAML的語法和其他高階語言類似,并且可以簡單表達清單、散列表、標量等數據結構。其結構(Structure)通過空格來展示,序列(Sequence)里的項用”-“來代表,Map里的鍵值對用”:”分隔。下面是一個示例:
1. - hosts:
2. remote_user:root
3. vars:
4. var_name: value
5. http_port: 80
6. max_clients: 256
7. ……
8. tasks:
9. - name: ensure apache is at the latest version
10. yum: name=httpd state=latest
11. tags: tag_name
12. notify: handler_name
13. - name:
14. ……
15. handlers:
16. - name: handler_name
17. MODULE
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用于指定要執行指定任務的主機,其可以是一個或多個由冒號分隔主機組;remote_user則用于指定遠程主機上的執行任務的用戶。
YAML文件擴展名通常為.yaml,如example.yaml或main.yml;
YAML坑
YAML語法要求如果值以{{ foo }}開頭的話我們需要將整行用雙引號包起來.
錯誤:
1.- hosts: app_servers
2. vars:
3. app_path: {{ base_path }}/22
正確:
1.- hosts: app_servers
2. vars:
3. app_path: "{{ base_path }}/22"
palybook文件示例
(1)增加用戶并指定組
1.vi addgrp.yml
2.- hosts:websrv
3. remote_user:root
4. tasks:
5. - name: create group ops
6. group: name=ops system=true
7. - name: create user alice
8. user: name=alice group=ops system
(2)安裝httpd程序
1.vi httpd.yml
2.- hosts: websrv
3. remote_user: root
4. tasks:
5. - name: install httpd.
6. yum: name=httpd
7. - name: conf
8. copy: src=./src/httpd.conf dest=/etc/httpd/conf/httpd.conf
9. tages: newconf
10. notify: restart httpd..
11. - name: start
12. service: name=httpd state=started
13. handlers:
14. - name: restart httpd..
15. service: name=httpd state=restarted
16. handlers:
17. - name: reload httpd..
18. shell: /usr/sbin/service httpd reload
roles
一個 Role 可以包含特定的變量值,特定的任務,特定的觸發器等東西。因為 Role 的文件結構,roles 可以是再次利用的單元,可以讓你在其它 playbooks 中共享一些行為。
一個完整的role以特定的層級目錄結構進行組織的tasks、variables、handlers、templates、files等;
role_struct:
files/:存放有copy或script等模塊調用的文件;
tasks/:至少有一個main.yml用于定義主task,其他文件應被main.yml包含調用;
handlers/:至少有一個main.yml用于定義主handler,其他文件應被main.yml包含調用;
templates/:存放有template模塊調用的模板文件;
meta/:至少有一個main.yml用于定義當前role的特殊設定及依賴關系,其他文件應被main.yml包含調用
default/:至少有一個main.yml用于定義默認的變量;
簡單的role示例
-
創建roles目錄結構
mkdri -p /etc/ansible/roles/{nginx,mysql,httpd}/{files,tasks,handlers,vars,templates,meta,default}
-
編輯任務文件:vi /nginx/tasks/main.yml
1.- name: copy nginx
2. copy: src=nginx-1.10 dest=/tmp/
3.- name: install nginx
4. yum: name=/tmp/nginx-1.10
5.- name: install conf file
6. template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
7. tags: newconf
8. notify: reload nginx
9.- name: install conf file
10. template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
11. tags: newconf
12. notify: reload nginx
13.- name: start nginx
14. service: name=nginx state=started
-
編輯關聯任務:vi /nginx/handlers/main.yml
1.- name: reload nginx
2. shell: nginx -s reload
-
編輯playbook變量:vi vars/main.yml
1.nginxport: "8080"
-
編輯模板文件:vi nginx.conf.j2 default.conf.j2
cp /etc/nginx/nginx.conf roles/nginx/templates/nginx.conf.j2
cp /etc/nginx/conf.d/default.conf roles/nginx/templates/default.conf.j2
1.worker_processes {{ ansible_processor_vcpus }};
2.listen {{ ngxport }};
-
編輯role調用文件:vi palynginx.yml
1.- hosts: websrv
2. remote_user: root
3. roles:
4. - { playnginx, var_name:value,…… }
5. - memcache
-
檢查整個role語法、測試執行
ansible-playbook --syntax-check playnginx.yml
ansible-playbook -C playnginx.yml
-
調用執行playbook文件
ansible-playbook playnginx.yml
總結
ansible作為運維工具中遠程命令執行工具,能夠實現:批量部署應用程序、系統配置、批量命令執行等功能,是一款較輕量化的Python程序。ansible經過不斷的發展,具有模塊化、部署簡單、工作于agentless模式、使用ssh協議、支持自定義模塊、支持Palybook等特點。
Playbooks 可用于收集主機配置信息,更強大的地方在于 playbooks 中可以編排有序的任務執行過程,甚至于做到在多組機器間來回有序的執行指定步驟任務,且可以同步或異步的發起任務。
更多信息:http://www.ansible.com.cn/docs/
ansible部署{keepalived+nginx+{httpd, mysql, php}}
ansible部署AMP環境
同時兼容CentOS 6 與Cent OS 7系統
目錄結構
1./etc/ansible/roles/lamp/
2.├── default
3.├── files
4.├── handlers
5.│ └── main.yml
6.├── meta
7.├── tasks
8.│ └── main.yml
9.├── templates
10.│ ├── httpd-2.2.conf.j2
11.│ └── httpd-2.4.conf.j2
12.└── vars
13. └── main.yml
tasks/main.yml
-
使用yum模塊安裝httpd、php、php-mysql
-
根據
DBName
變量安裝mysql程序 -
根據
HttpConf
變量并使用模板向httpd.conf文件傳遞變量,同時觸發重載httpd服務 -
啟動httpd服務(省略php.ini文件的復制)
-
根據
DBService
變量啟動mysql服務 -
根據fact變量定制每臺web服務器的index.html
-
創建測試數據庫,授權
LocalIP
變量,即ansible主機的變量
1.- name: install httpd php
2. yum: name={{ item }} state=present
3. with_items:
4. - httpd
5. - php
6. - php-mysql
7.- name: install mysql
8. yum: name={{ DBName }}-server state=present
9.- name: copy httpd.conf
10. template: src={{ HttpConf }} dest=/etc/httpd/conf/httpd.conf
11. tags: NewHttpConf
12. notify: reload httpd
13.- name: start httpd
14. command: /usr/sbin/apachectl start
15.- name: start mysql
16. service: name={{ DBService }} state=started
27.- name: create index.html
28. copy: content='<h1> Web Servers in {{ ansible_hostname }}, Host IP is {{ ansible_all_ipv4_addresses[0] }}, System Version is {{ ansible_distribution }} {{ ansible_distribution_version }} </h1>' dest=/var/www/html/index.html
31.- name: create testdb
32. command: mysql -e 'CREATE DATABASE testdb;GRANT ALL ON testdb.* TO "testuser"@"{{ LocalIP }}" IDENTIFIED BY "mage";FLUSH PRIVILEGES'
handlers/main.yml
1.- name: reload httpd
2. service: name=httpd state=reloaded
vars/main.yml
1.htport: 80
templates/
-
vi httpd-2.2.conf.j2
1.Listen {{ htport }};
-
vi httpd-2.4.conf.j2
1.Listen {{ htport }};
host iventory
/etc/ansible/hosts
1.[websrv]
2.10.1.22.105
3.10.1.22.100
4.
5.[websrv:vars]
6.LocalIP=10.1.253.29
roles調用
ngxproxy.yml
1.- hosts: websrv
2. remote_user: root
3. tags: amp
4. roles:
5. - { role: lamp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
6. - { role: lamp, DBName: mariadb, DBService: mariadb, HttpConf: httpd-2.4.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
7.# - { role: httpd, tags: start mysql, DBName: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
play and check
執行playbook
訪問we1和web2
訪問測試數據庫
ansible部署nginx反代服務器
同時兼容 CentOS 6 與 CentOS 7 系統
目錄結構
1./etc/ansible/roles/ngxproxy/
2.├── default
3.├── files
4.│ ├── nginx-1.10.0-1.el7.ngx.x86_64.rpm
5.│ └── nginx-1.10.2-1.el6.ngx.x86_64.rpm
6.├── handlers
7.│ └── main.yml
8.├── meta
9.├── tasks
10.│ └── main.yml
11.├── templates
12.│ ├── default.conf.j2
13.│ └── nginx.conf.j2
14.└── vars
15. └── main.yml
tasks/main.yml
-
根據
rpmName
變量復制nginx程序包到目標主機 -
根據
rpmName
安裝nginx程序包 -
基于模板復制nginx.conf和default.conf文件到目標主機,并觸發重載nginx服務,且已經配置好upstrem server
-
啟動nginx服務
1.- name: copy nginx rpm
2. copy: src={{ rpmName }} dest=/tmp
3.- name: install nginx
4. yum: name=/tmp/{{ rpmName }} state=present
5. tags: copyrpm
6. notify: remove rpm
9.
- name: install conf
10. template: src={{ item.src }} dest={{ item.dest }}
12.
notify: nginx reload
13. with_items:
14. - { src: 'nginx.conf.j2', dest: '/etc/nginx/nginx.conf' }
15. - { src: 'default.conf.j2', dest: '/etc/nginx/conf.d/default.conf' }
16.- name: start nginx
17. service: name=nginx state=started
handlers/main.yml
1.- name: nginx reload
2. shell: "/usr/sbin/nginx -s reload"
3.- name: remove rpm
4. shell: "/bin/rm /tmp/{{ rpmName }}"
vars/main.yml
1.ngxport: 80
templates/
-
vi default.conf.j2
1.listen {{ ngxport }};
2.location / {
3. #root /usr/share/nginx/html;
4. index index.html index.htm;
5. proxy_pass http://websrv;
6.}
-
vi nginx.conf.j2
1.worker_processes {{ ansible_processor_vcpus }};
2.http{
3. upstream websrv {
4. server 10.1.22.105;
5. server 10.1.22.100;
6. }
7.}
files/
-
nginx-1.10.0-1.el7.ngx.x86_64.rpm
-
nginx-1.10.2-1.el6.ngx.x86_64.rpm
host iventory
/etc/ansible/hosts
1.[ngxproxy]
2.10.1.253.66 rpmName=nginx-1.10.2-1.el6.ngx.x86_64.rpm
3.10.1.22.106 rpmName=nginx-1.10.0-1.el7.ngx.x86_64.rpm
roles調用
ngxproxy.yml
1.- hosts: ngxproxy
2. remote_user: root
3. tags: ngxproxy
4. roles:
5. - ngxproxy
play and check
執行playbook
訪問兩臺代理服務器均能輪詢web1、web2
ansible部署keepalived
同時兼容 CentOS 6 與 CentOS 7 系統,采用雙主模型的keepalived配置高可用nginx代理服務器。
目錄結構
1./etc/ansible/roles/keepalived/
2.├── default
3.├── files
4.├── handlers
5.│ └── main.yml
6.├── meta
7.├── tasks
8.│ └── main.yml
9.├── templates
10.│ ├── keepalived.conf.j2
11.│ └── notify.sh
12.└── vars
tasks/main.yml
-
使用yum安裝keepalivcd
-
基于模板復制keepalived.conf和notify.sh腳本到目標主機,并觸發重載keepalived服務,且已經配置好了雙主模型的keepalived
-
啟動keepalived服務
1.- name: install keepalived
2. yum: name=keepalived state=present
3.- name: copy keepalived.conf,notify script
4. template: src={{ item.src }} dest=/etc/keepalived/{{ item.dest }}
5. tags: NewConf
6. notify: reload keepalived
7. with_items:
8. - { src: keepalived.conf.j2, dest: keepalived.conf }
9. - { src: notify.sh, dest: notify.sh }
10.- name: start keepalived
11. service: name=keepalived state=started
handlers/main.yml
1.- name: reload keepalived
2. service: name=keepalived state=reloaded
templates/
-
vi keepalived.conf.j2
1.! Configuration File for keepalived
2.
3.global_defs {
4. notification_email {
5. root@localhost
6. }
7. notification_email_from keepalived@jasonmc.com
8. smtp_server localhost
9. smtp_connect_timeout 30
10. router_id node1
11. vrrp_mcast_group4 224.22.29.1
12.}
13.vrrp_script chk_down {
14. script "[[ -f /etc/keepalived/down ]]&& exit 1 || exit 0"
15. interval 1
16. weight -5
17.}
18.vrrp_script chk_nginx {
19. script "killall -0 nginx && exit 0 || exit 1"
20. interval 1
21. weight -5
22.}
23.
24.vrrp_instance VI_1 {
25. state {{ VI_1 }}
26. interface {{ IFACE }}
27. virtual_router_id 10
28. priority 96
29. advert_int 10
30. authentication {
31. auth_type PASS
32. auth_pass 1a7b2ce6
33. }
34. virtual_ipaddress {
35. 10.1.253.11 dev {{ IFACE }}
36. }
37. track_script {
38. chk_down
39. chk_nginx
40. }
41. notify_master "/etc/keepalived/notify.sh master"
42. notify_backup "/etc/keepalived/notify.sh backup"
43. notify_fault "/etc/keepalived/notify.sh fault"
44.}
45.
46.vrrp_instance VI_2 {
47. state {{ VI_2 }}
48. interface {{ IFACE }}
49. virtual_router_id 11
50. priority 100
51. advert_int 11
52. authentication {
53. auth_type PASS
54. auth_pass a3d1e9b0
55. }
56. virtual_ipaddress {
57. 10.1.253.12 dev {{ IFACE }}
58. }
59. track_script {
60. chk_down
61. chk_nginx
62. }
63. notify_master "/etc/keepalived/notify.sh master"
64. notify_backup "/etc/keepalived/notify.sh backup"
65. notify_fault "/etc/keepalived/notify.sh fault"
66.}
-
vi notify.sh
1.#!/bin/bash
2.#
3.receiver='root@localhost'
4.notify() {
5. mailsubject="$(hostname) to $1,vip floating."
6. content="$(date '+%F %T') vrrp state transion, $(hostname) changed to be $1"
7. echo "$content" | mail -s "$mailsubject" $receiver
8.}
9.case $1 in
10. master)
11. notify master
12. ;;
13. backup)
14. notify backup
15. ;;
16. fault)
17. notify fault
18. ;;
19. *)
20. echo "Usage $(basename $0) {master|backup|fault}"
21. exit 1
22. ;;
23.esac
host iventory
/etc/ansible/hosts
1.[ngxproxy]
2.10.1.253.66
3.10.1.22.106
roles調用
ngxproxy.yml
1.- hosts: ngxproxy
2. remote_user: root
3. tags: ngxproxy
4. roles:
5. - { role: keepalived, VI_1: MASTER, VI_2: BACKUP, IFACE: eno16777736, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
6. - { role: keepalived, VI_1: BACKUP, VI_2: MASTER, IFACE: eth0, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
play and check
執行playbook
訪問VIP1與VIP2均能輪詢web1、web2
合并調用roles的palybook
hosts
1.[ngxproxy]
2.10.1.253.66 rpmName=nginx-1.10.2-1.el6.ngx.x86_64.rpm
3.10.1.22.106 rpmName=nginx-1.10.0-1.el7.ngx.x86_64.rpm
4.
5.[websrv]
6.10.1.22.105
7.10.1.22.100
8.
9.[websrv:vars]
10.LocalIP=10.1.253.29
keneweb.yml
1.- hosts: websrv
2. remote_user: root
3. tags: amp
4. roles:
5. - { role: lamp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
6. - { role: lamp, DBName: mariadb, DBService: mariadb, HttpConf: httpd-2.4.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
7.# - { role: httpd, tags: start mysql, DBName: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
8.
9.- hosts: ngxproxy
10. remote_user: root
11. tags: ngxproxy
12. roles:
13. - ngxproxy
14. - { role: keepalived, VI_1: MASTER, VI_2: BACKUP, IFACE: eno16777736, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
15. - { role: keepalived, VI_1: BACKUP, VI_2: MASTER, IFACE: eth0, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
原創文章,作者:helloc,如若轉載,請注明出處:http://www.www58058.com/58041