Ansible
ansible是個(gè)什么東西呢命浴?官方的title是“Ansible is Simple IT Automation”——簡(jiǎn)單的自動(dòng)化IT工具娄猫。這個(gè)工具的目標(biāo)有這么幾項(xiàng):自動(dòng)化部署APP;自動(dòng)化管理配置項(xiàng)生闲;自動(dòng)化的持續(xù)交互媳溺;自動(dòng)化的(AWS)云服務(wù)管理。所有的這幾個(gè)目標(biāo)從本質(zhì)上來(lái)說(shuō)都是在一個(gè)臺(tái)或者幾臺(tái)服務(wù)器上碍讯,執(zhí)行一系列的命令而已悬蔽。通俗的說(shuō)就是批量的在遠(yuǎn)程服務(wù)器上執(zhí)行命令 。當(dāng)然捉兴,最主要的是它是基于 paramiko 開(kāi)發(fā)的蝎困。這個(gè)paramiko是什么呢?它是一個(gè)純Python實(shí)現(xiàn)的ssh協(xié)議庫(kù)倍啥。因此fabric和ansible還有一個(gè)共同點(diǎn)就是不需要在遠(yuǎn)程主機(jī)上安裝client/agents禾乘,因?yàn)樗鼈兪腔趕sh來(lái)和遠(yuǎn)程主機(jī)通訊的。簡(jiǎn)單歸納一下:
Ansible:—基于 Python paramiko 開(kāi)發(fā)虽缕,分布式始藕,無(wú)需客戶端,輕量級(jí)氮趋,配置語(yǔ)法使用 YMAL 及 Jinja2模板語(yǔ)言伍派,更強(qiáng)的遠(yuǎn)程命令執(zhí)行操作
類似的自動(dòng)化運(yùn)維工具有很多常用的還有:
Puppet
—基于 Ruby 開(kāi)發(fā),采用 C/S 架構(gòu)剩胁,擴(kuò)展性強(qiáng)诉植,基于 SSL,遠(yuǎn)程命令執(zhí)行相對(duì)較弱
由上面的圖可以看到 Ansible 的組成由 5 個(gè)部分組成:
Ansible: 核心
Modules: 包括 Ansible 自帶的核心模塊及自定義模塊
Plugins: 完成模塊功能的補(bǔ)充摧冀,包括連接插件倍踪、郵件插件等
Playbooks: 劇本(編排好一步一步的執(zhí)行)系宫;定義 Ansible 多任務(wù)配置文件,有 Ansible 自動(dòng)執(zhí)行
Inventory: 定義 Ansible 管理主機(jī)的清單
一建车、ansible的安裝
一是從官網(wǎng)下載最新的版本編譯安裝扩借,一是直接從配好的yum 倉(cāng)庫(kù)安裝。如果不追求新功能缤至,要求穩(wěn)定潮罪,一般我們直接從yum倉(cāng)庫(kù)安裝即可。
這里的實(shí)驗(yàn)環(huán)境為centos7.3主機(jī)
[root@centos7 ~]#yum info ansible #這里顯示的版本為3.6.1
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
Installed Packages
Name : ansible
Arch : noarch
Version : 2.3.1.0
Release : 1.el7
Size : 27 M
......
安裝部署ansible
ansible是基于ssh協(xié)議的首先讓ansible主機(jī)能通過(guò)ssh密鑰連接各主機(jī)
1.安裝
[root@centos7 ~]#yum -y install ansible
1.創(chuàng)建ssh密鑰連接
[root@centos7 ~]# ssh-keygen -t rsa -P "" #生成私鑰
2.傳遞給后端目標(biāo)主機(jī)
[root@centos7 ~]#ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.18.97
[root@centos7 ~]#ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.18.98
[root@centos7 ~]#vim /etc/ansible/hosts #編輯添加ansible的hosts配置文件
[websrvs] #添加兩個(gè)后端web服務(wù)主機(jī)
192.168.18.97
192.168.18.98
2.探測(cè)是否能通
[root@centos7 ansible]#ansible all -m ping #這里的all是定義的所有主機(jī)领斥,也可以寫(xiě)自己在hosts的組名websrvs
192.168.18.98 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.18.97 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ansible命令參數(shù)介紹
[root@centos7 ansible]#ansible --help #這里常用命令的介紹
-v,–verbose # 詳細(xì)模式嫉到,如果命令執(zhí)行成功,輸出詳細(xì)的結(jié)果(-vv –vvv -vvvv)
-i PATH,–inventory=PATH #指定host文件的路徑月洛,默認(rèn)是/etc/ansible/hosts
-f NUM,–forks=NUM # NUM是指定一個(gè)整數(shù)何恶,默認(rèn)是5,指定fork開(kāi)啟同步進(jìn)程的個(gè)數(shù)嚼黔。
-m NAME,–module-name=NAME #指定使用的module名稱细层,默認(rèn)是command
-m DIRECTORY,–module-path=DIRECTORY #指定module的目錄來(lái)加載module,默認(rèn)是/usr/share/ansible,
-a,MODULE_ARGS #指定module模塊的參數(shù)
-k,–ask-pass # 提示輸入ssh的密碼唬涧,而不是使用基于ssh的密鑰認(rèn)證
–sudo # 指定使用sudo獲得root權(quán)限
-K,–ask-sudo-pass #提示輸入sudo密碼疫赎,與–sudo一起使用
-u USERNAME,–user=USERNAME # 指定移動(dòng)端的執(zhí)行用戶
-C,–check #測(cè)試此命令執(zhí)行會(huì)改變什么內(nèi)容,不會(huì)真正的去執(zhí)行
ansible幾個(gè)常用模塊介紹及使用
[root@centos7 ansible]#ansible-doc -l #列出模塊
1.group :組
[root@centos7 ansible]#ansible-doc -s group 查看組
- name: Add or remove groups
action: group
gid # 組gid
name= # Name 組名.
state # present :創(chuàng)建 absent :刪除
system #默認(rèn)系統(tǒng)組no碎节,
創(chuàng)建組:
[root@centos7 ansible]#ansible all -m group -a "gid=3000 name=mygrp state=present system=no" #創(chuàng)建組
192.168.18.98 | SUCCESS => {
"changed": true,
"gid": 3000,
"name": "mygrp",
"state": "present",
"system": false
}
192.168.18.97 | SUCCESS => {
"changed": true,
"gid": 3000,
"name": "mygrp",
"state": "present",
"system": false
}
192.168.18.97 ,192.168.18.98主機(jī)上查看
[root@centos7 ~]#tail -1 /etc/group
mygrp:x:3000: #都創(chuàng)建成功
刪除組:
[root@centos7 ansible]#ansible all -m group -a "gid=3000 name=mygrp state=absent" #刪除組
2.user:用戶
[root@centos7 ansible]#ansible-doc -s user #用戶
name= #名字
comment: #注釋信息
expires #過(guò)期時(shí)間
group #基本組
groups #附加組
home #家目錄路徑
move_home #原來(lái)家目錄及文件是否移動(dòng)過(guò)來(lái)
passwd #定義密碼
shell #選擇shell
state # 創(chuàng)建
system #系統(tǒng)用戶
uid #uid
創(chuàng)建用戶
[root@centos7 ansible]#ansible all -m user -a"uid=5000 name=testuser state=present groups=mygrp shell=/bin/tcsh" #創(chuàng)建用戶
192.168.18.98 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 5000,
"groups": "mygrp",
"home": "/home/testuser",
"name": "testuser",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 5000
}
192.168.18.97 | SUCCESS => {
捧搞。。狮荔。胎撇。
}
刪除
ansible all -m user -a "name=testuser state=absent"
3.copy:
[root@centos7 ansible]#ansible-doc -s copy #拷貝
dest= #目標(biāo)路徑
src #源 路徑 是目錄:做遞歸 如果帶/復(fù)制目錄里面內(nèi)容,不帶/復(fù)制目錄和文件
mode #權(quán)限
content #生成文件
簡(jiǎn)單復(fù)制文件
[root@centos7 ~]#ansible all -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible mode=600"
[root@centos7 ~]#ansible all -m copy -a "src=/etc/pam.d/ dest=/tmp/" #只復(fù)制里面內(nèi)容
[root@centos7 ~]#ansible all -m copy -a "src=/etc/pam.d dest=/tmp/" #復(fù)制目錄及內(nèi)容
[root@centos7 ~]#ansible all -m copy -a "content='hi there' dest=/tmp/ansib.txt" #生成內(nèi)容為hi there 的ansible.txt文件
[root@centos7 ~]#ansible all -m copy -a "content='hi there' dest=/tmp/ansib.txt owner=testuser group=mygrp" #改屬主屬組
4.command :
[root@centos7 ~]#ansible-doc -s command #執(zhí)行命令
chdir #切換目錄執(zhí)行
executable #不適應(yīng)默認(rèn)shell使用此項(xiàng)
free_form= #自由格式執(zhí)行
[root@centos7 ~]#ansible all -m command -a "ifconfig" #使用命令轴合,
[root@centos7 ~]#ansible all -m command -a "chdir=/var/tmp mkdir hi.dir" #創(chuàng)建一個(gè)目錄
[root@centos7 ~]#ansible all -m command -a "echo jie |passwd --stdin testuser" #command本身不理解這種形式的操作
192.168.18.97 | SUCCESS | rc=0 >>
jie |passwd --stdin testuser
[root@centos7 ~]#ansible all -m shell -a "echo jie |passwd --stdin testuser" #做命令行展開(kāi)创坞,使用shell命令
192.168.18.98 | SUCCESS | rc=0 >>
Changing password for user testuser.
passwd: all authentication tokens updated successfully.
5.file:
[root@centos7 ~]#ansible-doc -s file #文件
path= #目標(biāo)路徑
start #創(chuàng)建文件 directory目錄 file 文件
src #符號(hào)鏈接
mode #屬主屬組
[root@centos7 ~]#ansible all -m file -a "path=/var/tmp/hello.dir state=directory" #目錄不存在創(chuàng)建
[root@centos7 ~]#ansible all -m file -a "src=/var/tmp/fstab.ansible path=/var/tmp/fstable.link state=link" #創(chuàng)建連接
6.cron:
[root@centos7 ~]#ansible-doc -s cron #創(chuàng)建任務(wù)計(jì)劃
day #天
hour #小時(shí)
job #任務(wù)
name #任務(wù)名稱
state #present 添加 absent 刪除
[root@centos7 ~]#ansible all -m cron -a "minute=*/3 job='usr/sbin/update 172.16.0.1 &> /dev/nul' name=renwu" #創(chuàng)建任務(wù) 同步時(shí)間
[root@centos7 tmp]#crontab -l
#Ansible: renwu
*/3 * * * * usr/sbin/update 172.16.0.1 &> /dev/nul
[root@centos7 ~]#ansible all -m cron -a "minute=*/3 job='usr/sbin/update 172.16.0.1 &> /dev/nul' name=renwu state=absent" #刪除任務(wù) 注意如果創(chuàng)建時(shí)沒(méi)有寫(xiě)上name時(shí)碗短,刪除帶上name=None
7.yum :
[root@centos7 ~]#ansible-doc -s yum #安裝程序包
state #安裝( present或installed或latest) 卸載(absent或removed)
disablerepo #禁用某個(gè)倉(cāng)庫(kù)
enablerepo #啟用某個(gè)倉(cāng)庫(kù)
disable_gpg_check #禁用gpg檢測(cè)
[root@centos7 ~]#ansible all -m yum -a "name=nginx state=installed" #安裝程序
8.service:
[root@centos7 ~]#ansible-doc -s service #服務(wù)
enabled #開(kāi)機(jī)啟用
name= #服務(wù)名稱
pattern #過(guò)濾字符
runlevel #哪個(gè)級(jí)別啟用
state # started 啟動(dòng) stopped停止 restarted 重啟 reloaded重載
[root@centos7 ~]#ansible all -m service -a "name=nginx state=started" #啟動(dòng)服務(wù)
[root@centos7 ~]#ansible all -m service -a "name=nginx state=stopped" #服務(wù)停止
9.script
[root@centos7 ~]#ansible-doc -s script #腳本
[root@centos7 ~]#vim /tmp/test.sh
#!/bin/bash
echo "test script" > /tmp/1.txt
[root@centos7 ~]#ansible all -m script -a "/tmp/test.sh" #執(zhí)行腳本
Playbook:
Playbooks 是 一個(gè)不同于使用Ansible命令行執(zhí)行方式的模式受葛,其功能更強(qiáng)大靈活。簡(jiǎn)單來(lái)說(shuō)偎谁,playbook是一個(gè)非常簡(jiǎn)單的配置管理和多主機(jī)部署系統(tǒng)总滩,不同于任何已經(jīng)存在的模式,可作為一個(gè)適合部署復(fù)雜應(yīng)用程序的基礎(chǔ)巡雨。Playbook可以定制配置闰渔,可以按照指定的操作步驟有序執(zhí)行,支持同步和異步方式铐望。值得注意的是playbook是通過(guò)YAML格式來(lái)進(jìn)行描述定義的冈涧。
yaml用法:可參考維基百科 或官網(wǎng)文檔http://docs.ansible.com/ansible/latest/YAMLSyntax.html
Playbook的核心元素:
Hosts:主機(jī)
Tasks:任務(wù)列表
Variables:變量
Templates:包含了模板語(yǔ)法的文本文件茂附;
Handlers:由特定條件觸發(fā)的任務(wù);
1.創(chuàng)建playbook
[root@centos7 ansible]#mkdir playbooks #創(chuàng)建劇本
[root@centos7 ansible]#cd playbooks
[root@centos7 playbooks]#vim 1.yaml
- host: 192.168.18.97 #主機(jī)
#也可以寫(xiě)成- hosts: all 或 - hosts: websrvs
remote_user: root #使用的用戶
tasks: #任務(wù)
- name: install redis #任務(wù)名稱1
yum: name=redis state=latest
- name: start redis #任務(wù)名稱2
service: name=redis state=started
[root@centos7 playbooks]#ansible-playbook --syntax-check 1.yaml #語(yǔ)法檢查
[root@centos7 playbooks]#ansible-playbook -C 1.yaml #測(cè)試安裝
#paly 讓哪臺(tái)主機(jī)執(zhí)行
PLAY [all] *********************************************************************
#收集信息在ansible
TASK [setup] *******************************************************************
#安裝Redis
TASK [install redis] ***********************************************************
#啟動(dòng)Redis
TASK [start redis] *************************************************************
to retry, use: --limit @/root/playbooks/1.retry
#結(jié)果
PLAY RECAP *********************************************************************
注意:按每項(xiàng)任務(wù)執(zhí)行督弓,不是每個(gè)主機(jī)執(zhí)行完才執(zhí)行另外主機(jī)营曼!
2.對(duì)配置文件的修改
如不使用Redis的默認(rèn)配置文件,自己修改愚隧〉仝澹可從別機(jī)考一份配置文件過(guò)來(lái)做修改,然后利用ansible部署狂塘。
從單臺(tái)主機(jī)拷貝源文件到ansible主機(jī)
ansible 192.168.18.97 -m fetch -a "src=/etc/redis.conf dest=./"
編輯playbook里的1.yaml,假設(shè)redis.conf已修改好(修改的是bind 端口)录煤。
[root@centos7 playbooks]#vim 1.yaml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=latest
- name: copy config file
copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis
- name: start redis
service: name=redis state=started
[root@centos7 playbooks]#ansible-playbook --syntax-check 1.yaml #檢查語(yǔ)法
[root@centos7 playbooks]#ansible-playbook -C 1.yaml #測(cè)試安裝
[root@centos7 playbooks]#ansible-playbook 1.yaml #安裝
此時(shí)后端主機(jī)配置文件改變,但服務(wù)狀態(tài)重啟荞胡,還是原來(lái)的狀態(tài)妈踊,端口沒(méi)有變化
3.此時(shí)用到handlers:由特定條件觸發(fā)的任務(wù);
handlers:
任務(wù)泪漂,在特定條件下觸發(fā)响委;
接收到其它任務(wù)的通知時(shí)被觸發(fā);
notify: HANDLER TASK NAME
[root@centos7 playbooks]#cp 1.yaml 2.yaml
[root@centos7 playbooks]#vim 2.yaml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=latest
- name: copy config file
copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis
notify: restart redis
- name: start redis
service: name=redis state=started
handlers: #接收到其它任務(wù)的通知時(shí)被觸發(fā)窖梁;
- name: restart redis
service: name=redis stat=restarted
[root@centos7 playbooks]#ansible-playbook --syntax-check 2.yaml
[root@centos7 playbooks]#ansible-playbook -C 2.yaml
[root@centos7 playbooks]#ansible-playbook 2.yaml
改變的配置文件赘风,觸發(fā)重啟服務(wù)
4..tags: 標(biāo)簽
做標(biāo)簽:只對(duì)有標(biāo)簽項(xiàng)作出操作,則可繼續(xù)修改
[root@centos7 playbooks]#vim 2.yaml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=latest
- name: copy config file
copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis
notify: restart redis
tags: configfile
- name: start redis
service: name=redis state=started
handlers:
- name: restart redis
service: name=redis state=restarted
[root@centos7 playbooks]#ansible-playbook --syntax-check 2.yaml
[root@centos7 playbooks]#ansible-playbook -C 2.yaml
[root@centos7 playbooks]#ansible-playbook -t configfile 2.yaml #對(duì)標(biāo)簽操作
5.variables
(1) facts:可直接調(diào)用;
注意:可使用setup模塊直接獲取目標(biāo)主機(jī)的facters纵刘;
(2) 用戶自定義變量:
(a) ansible-playbook命令的命令行中的
-e VARS, --extra-vars=VARS
(b) 在playbook中定義變量的方法:
vars:
- var1: value1
- var2: value2
變量引用:{{ variable }}
(3) 通過(guò)roles傳遞變量邀窃;
(4) Host Inventory
(a) 用戶自定義變量
(i) 向不同的主機(jī)傳遞不同的變量;
IP/HOSTNAME varaiable=value var2=value2
(ii) 向組中的主機(jī)傳遞相同的變量假哎;
[groupname:vars]
variable=value
(b) invertory參數(shù)
用于定義ansible遠(yuǎn)程連接目標(biāo)主機(jī)時(shí)使用的參數(shù)瞬捕,而非傳遞給playbook的變量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansbile_sudo_pass
...
6.templates:模板
文本文件舵抹,嵌套有腳本(使用模板編程語(yǔ)言編寫(xiě))
Jinja2:
字面量:
字符串:使用單引號(hào)或雙引號(hào)肪虎;
數(shù)字:整數(shù),浮點(diǎn)數(shù)惧蛹;
列表:[item1, item2, ...]
元組:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布爾型:true/false
算術(shù)運(yùn)算:
+, -, *, /, //, %, **
比較操作:
==, !=, >, >=, <, <=
邏輯運(yùn)算:
and, or, not
列1.
模板配置文件 :
nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
listen {{ http_port }};
- hosts: websrvs
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: install conf file
template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
tags: instconf
- name: start nginx service
service: name=nginx state=started
handlers:
- name: restart nginx
service: name=nginx state=restarted
例2
模板配置文件 :
cp /root/playbook/redis.conf{,.j2}
vim /etc/playbook/redis.conf.j2
bind {{ ansible_ens33.ipv4.address }} //調(diào)用網(wǎng)卡
- hosts: all
remote_user: root
tasks:
- name: install config file
template: src=/root/playbooks/redis.conf.j2 dest=/tmp/redis.conf
7.條件測(cè)試和循環(huán)(迭代扇救,需要重復(fù)執(zhí)行的任務(wù))
[root@centos7 playbooks]#vim os.yaml
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd state=latest
when: ansible_os_family == "RedHat"
- name: install apache2
apt: name=apache2 state=latest
when: ansible_os_family == "Debian"
[root@centos7 playbooks]#ansible-playbook --syntax-check os.yaml
迭代安裝:
[root@centos7 playbooks]#vim 8.yaml
- hosts: websrvs
remote_user: root
tasks:
- name: install {{ item }} package
yum: name={{ item }} state=latest
with_items:
- nginx
- tomcat
- mariadb-server
- redis
[root@centos7 playbooks]#ansible-playbook --syntax-check 8.yaml
[root@centos7 playbooks]#ansible-playbook -C 8.yaml
8.角色(roles):
每個(gè)角色,以特定的層級(jí)目錄結(jié)構(gòu)進(jìn)行組織:
如:nginx/
files/ :存放由copy或script模塊等調(diào)用的文件香嗓;
templates/:template模塊查找所需要模板文件的目錄迅腔;
tasks/:至少應(yīng)該包含一個(gè)名為main.yml的文件;其它的文件需要在此文件中通過(guò)include進(jìn)行包含靠娱;
handlers/:至少應(yīng)該包含一個(gè)名為main.yml的文件沧烈;其它的文件需要在此文件中通過(guò)include進(jìn)行包含;
vars/:至少應(yīng)該包含一個(gè)名為main.yml的文件像云;其它的文件需要在此文件中通過(guò)include進(jìn)行包含锌雀;
meta/:至少應(yīng)該包含一個(gè)名為main.yml的文件蚂夕,定義當(dāng)前角色的特殊設(shè)定及其依賴關(guān)系;其它的文件需要在此文件中通過(guò)include進(jìn)行包含腋逆;
default/:設(shè)定默認(rèn)變量時(shí)使用此目錄中的main.yml文件双抽;
在playbook調(diào)用角色方法1:
- hosts: websrvs
remote_user: root
roles:
- mysql
- memcached
- nginx
在playbook調(diào)用角色方法2:傳遞變量給角
- hosts:
remote_user: root
roles:
- { role: nginx, username: nginx }
鍵role用于指定角色名稱;后續(xù)的k/v用于傳遞變量給角色闲礼;
安裝Nginx:
[root@centos7 ~]#vim /root/nginx.yml #角色配置文件
- hosts: websrvs
remote_user: root
roles:
- nginx
[root@centos7 ~]#ansible-playbook --syntax-check /root/nginx.yml
[root@centos7 ~]#ansible-playbook -C /root/nginx.yml
提供配置文件等:
[root@centos7 roles]#vim nginx/tasks/main.yml
- name: install nginx
yum: name=nginx state=latest
when: ansible_os_family == "RedHat"
[root@centos7 roles]#vim /nginx/templates/vhost1.conf.j2
server {
listen 80;
server_name {{ ansible_fqdn }};
location / {
root "/ngxdata/vhost1";
[root@centos7 roles]#vim nginx/tasks/main.yml
- name: install nginx
yum: name=nginx state=latest
when: ansible_os_family == "RedHat"
- name: install conf
template: src=vhost1.conf.j2 dest=/etc/nginx/conf.d/vhost1.conf
tags: conf
notify: restart nginx
- name: install site home directory
file: path={{ ngxroot }} state=directory
- name: install index page
copy: src=index.html dest={{ ngxroot }}/
- name: start nginx
service: name=nginx state=started
[root@centos7 roles]#vim nginx/handlers/main.yml
- name: restart nginx
service: name=nginx state=restarted
[root@centos7 roles]#vim nginx/vars/main.yml
ngxroot: /ngxdata/vhost1 #變量字典不需加-
[root@centos7 roles]#vim nginx/files/index.html
Nginx page
[root@centos7 playbooks]#ansible-playbook -C /root/nginx.yml
[root@centos7 playbooks]#ansible-playbook /root/nginx.yml