Ansible詳解(二)
Ansible系列命令
Ansible系列命令有如下:
ansible
:這個命令是日常工作中使用率非常高的命令之一,主要用於臨時一次性操作;ansible-doc
:是Ansible模塊文檔說明,針對每個模塊都有詳細的用法說明和應用案例介紹;ansible-galaxy
:可以簡單的理解為Github或PIP的功能,通過ansible-galaxy,我們可以下載安裝優秀個Roles;ansible-playbook
:是日常應用中使用頻率最高的命令,其工作機制是,通過讀取預先編寫好的playbook文件實現批量管理;ansible-pull
:Ansible的另一種工作模式,pull模式,ansible默認使用push模式;ansible-vault
:主要用於配置文件加密;ansible-console
:讓用戶可以在ansible-console虛擬出來的終端上像Shell一樣使用Ansible內置的各種命令;
上一篇已經介紹過ansible
和ansible-doc
的基本用法,下面再來介紹一下其他系列命令的用法。
ansible-galaxy
用法:ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [—help] [options] …
去 https://galaxy.ansible.com/ 上傳或下載優秀的Playbook(roles)
#列出所有已安裝的galaxy
ansible-galaxy list
#安裝galaxy
ansible-galaxy install geerlingguy.redis
#刪除galaxy
ansible-galaxy remove geerlingguy.redis
ansible-valut
用法:ansible-vault [create|decrypt|edit|encrypt|rekey|view] [—help] [options] vaultfile.yml
ansible-vault encrypt hello.yml # 加密 ansible-vault decrypt hello.yml # 解密 ansible-vault view hello.yml # 查看
ansible-console
[email protected] (2)[f:10] $ service name=httpd state=stopped
[email protected] (2)[f:10] $
執行用戶@當前操作的主機組 (當前組的主機數量)[f:並發數]$
設置並發數: forks n 例如: forks 10
切換組: cd groupname 例如: cd mageduweb
列出當前組主機列表: list
列出所有的內置模塊: ?
ansible-playbook
Usage: ansible-playbook playbook.yml
playbook就是一個用yaml
語法把多個模塊堆起來的一個文件而已。
1.簡介
yaml是一個可讀性高的用來表達資料序列的格式。YAML參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy d?t Net與Oren Ben-Kiki也是這語言的共同設計者。
2.特點
- YAML的可讀性好
- YAML和腳本語言的交互性好
- YAML使用實現語言的數據類型
- YAML有一個一致的信息模型
- YAML易於實現
- YAML可以基於流來處理
- YAML表達能力強,擴展性好
YAML的語法和其他高階語言類似,並且可以簡單表達清單、散列表、標量等數據結構。其結構(Structure)通過空格來展示,序列(Sequence)裏的項用”-“來代表,Map裏的鍵值對用”:”分隔。下面是一個示例。
- hosts: 10.1.0.1 #定義主機
vars: #定義變量
var1: value
var2: value
tasks: #定義任務
- name: #任務名稱。
#這裏就可以開始用模塊來執行具體的任務了。
handlers: #定義觸發通知所作的操作。裏面也是跟tasks一樣,用模塊定義任務。
- name:
remote_user: #遠程主機執行任務時的用戶。一般都是root,一般也不用指定。
- hosts: web
vars:
tasks:
handlers:
remote_user:
YAML文件擴展名通常為.yaml,如example.yaml
Playbooks
:
核心組件:
Hosts
:執行的遠程主機列表Tasks
:任務,由模塊定義的操作的列表;Varniables
:內置變量或自定義變量在playbook中調用Templates
:模板,即使用了模板語法的文本文件;Handlers
:和notify結合使用,為條件觸發操作,滿足條件方才執行,否則不執行;Roles
:角色;
* 安裝http腳本實現:
#!/bin/bash
# 安裝Apache
yum install --quiet -y httpd httpd-devel # command: yum install --quiet -y httpd httpd-devel
# 復制配置文件
cp /path/to/config/httpd.conf /etc/httpd/conf/httpd.conf -f
cp/path/to/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf -f
# 啟動Apache,並設置開機啟動
service httpd start
chkconfig httpd on
* 安裝httpd ansible-playbook實現
---
- hosts: all
tasks:
- name: "安裝Apache"
command: yum install --quiet -y httpd httpd-devel
- name: "復制配置文件"
command: cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
command: cp /tmp/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
- name: "啟動Apache,並設置開機啟動"
command: service httpd start
command: chkconfig httpd on
playbook的基礎組件:
Hosts:運行指定任務的目標主機;
remote_user:在遠程主機以哪個用戶身份執行;
sudo_user:非管理員需要擁有sudo權限;
tasks:任務列表
模塊,模塊參數:
格式:
(1) action: module arguments
(2) module: arguments
示例:
vim test.yaml,後綴也可以是.yml
- hosts: all
remote_user: root
tasks:
- name: install a group
group: name=mygrp system=true
- name: install a user
user: name=user1 group=mygrp system=true
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd
- name: start httpd service
service: name=httpd state=started
運行playbook,使用ansible-playbook命令:
檢測語法:
- ansible-playbook --syntax-check /path/to/playbook.yaml
測試運行,即不真正執行:
- ansible-playbook -C /path/to/playbook.yaml
- ansible-playbook –check /path/to/playbook.yaml
--list-hosts
--list-tasks
--list-tags
運行:
- ansible-playbook /path/to/playbook.yaml
-t TAGS, --tags=TAGS
--skip-tags=SKIP_TAGS 跳過指定的標簽
--start-at-task=START_AT 從哪個任務後執行
tags
: 標簽,給指定的任務定義一個調用標識;
- name: NAME
module: arguments
tags: TAG_ID
指定某條任務執行:ansible-playbook --tags=user useradd.yml
- hosts: mageduweb
remote_user: root
tasks:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: Start Nginx
service: name=nginx state=started enabled=yes
可以一次調用多個名稱相同的標簽。也可以調用不同的標簽用 “,” 分割。
示例:
我們把httpd的監聽端口改為8080
用playbook把這個文件傳到node3,4上
指明標簽的檢查
從標簽位置開始執行
跳過標簽
handlers 和 notify 結合使用觸發條件,讓playbook在滿足一定觸發條件時才去執行某條task
- name: TASK_NAME
module: arguments
notify: HANDLER_NAME
handlers:
- name: HANDLER_NAME
module: arguments
第一次的話都會運行,後邊如果文件內容發生改變就會觸發notify,然後會直接執行handlers的內容(這裏notify後邊的事件就都不會執行了)。估計是md5那種的校驗。刪了個#號竟然也會通知。
---
- hosts: mageduweb
remote_user: root
tasks:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/config.txt
notify:
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx Process
shell: ss -tnl | grep 80
playbook 變量使用
變量來源:
(1)ansible setup facts遠程主機的所有變量都可以用
(2)自定義變量
a. 在/etc/ansible/hosts 定義變量,在主機組中的主機單獨定義,優先級高於組中公共變量
b. 在/etc/ansible/hosts 定義變量,針對主機組中的所有主機集中定義變量
c. 通過命令行指定變量,優先級最高
在hosts Inventory(/etc/ansible/hosts)中為每個主機定義專用變量值;
[all]
172.16.47.103 aaa=nginx
172.16.47.104 aaa=httpd
###############################
- hosts: all
remote_user: root
tasks:
- name: install web package
yum: name={{ aaa }} state=latest
(a) 向不同的主機傳遞不同的變量;
IP/HOSTNAME variable_name=value
[web]
10.1.6.72 qzx=httpd
10.1.6.73 qzx=nginx
(b) 向組內的所有主機傳遞相同的變量 ;
[groupname:vars]
variable_name=value
[web:qzx]
qzx=httpd
[web]
10.1.6.72
10.1.6.73
變量調用方式:
{{ variable_name }} 通過{{ }} 調用變量,且變量和{}兩頭之間必須有空格
額外介紹的是:
在playbook中調用變量時,有時”{{ variable_name }}”需要要雙引號引起來方可生效,有時候必須不能用””引起來
d.在playbook中定義,建議使用這個!
vars:
- var_name: value
- var_name: value
e.Inventory還可以使用參數
用於定義ansible遠程連接目標主機時使用的屬性,而非傳遞給playbook的變量;
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
...
f.在角色調用時傳遞
roles:
- { role: ROLE_NAME, var: value, ...}
templates模版
文本文件,內部嵌套有模板語言腳本(使用模板語言編寫)
Jinja2 是由python編寫的。 在我們打算使用基於文本的模板語言時,jinja2是很好的解決方案。yeml
是寫playbook
,jinja2
是寫配置文件模板
的。
功能:
將模板的文件的變量值轉換成對應的本地主機的確定值。例如:ansible端寫一個內建變量{{ ansible_processor_vcpus }}
,當這個文件被復制到對應主機時會自動生成對應主機 cpu的顆數的結果替換之。
Jinja2語法:
字面量:
字符串:使用單引號或雙引號;
數字:整數、浮點數;
列表:[item1, item2, ...]
元組:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布爾型:true/false
算術運算:
+, -, *, /, //, %, **
比較操作:
==, !=, >, <, >=, <=
邏輯運算:and, or, not
執行模板文件中的腳本,並生成結果數據流,需要使用template模塊
;
template
:使用了Jinjia2格式作為文件模版,進行文檔內變量的替換的模塊。相當於copy。
將jinja2的文件模板理解並執行,轉化為各個主機間的對應值
backup 建立個包括timestamp在內的文件備份,以備不時之需.
dest 遠程節點上的絕對路徑,用於放置template文件。
group 設置遠程節點上的的template文件的所屬用戶組
mode 設置遠程節點上的template文件權限。類似Linux中chmod的用法
owner 設置遠程節點上的template文件所屬用戶
src 本地Jinjia2模版的template文件位置。
註意:此模板不能在命令行使用,而只能用於playbook;用法同copy
(1) templates文件必須存放於目錄名為templates下,且命名為 .j2 結尾
(2)yaml/yml playbook文件需和templates目錄平級,目錄結構如下:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
案例1:
// templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
// temnginx.yml
---
- hosts: mageduweb
remote_user: root
vars:
nginx_vhosts:
- web1
- web2
- web3
# nginx_vhosts:
# - listen: 8080
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
生成的結果:
server {
listen web1
}
server {
listen web2
}
server {
listen web3
}
案例2:
shell腳本與Jinja語法對比:
-- shell腳本中寫法
for i in {1..10}
do
con
done
if [ xx ];then
con
elif
con
else
con
fi
-- Jinja寫法:
// templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
* 生成的結果
server {
listen 8080
}
* playbook調用文件
// temnginx.yml
---
- hosts: mageduweb
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
* 案例3
// temnginx.yml
---
- hosts: mageduweb
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8080
server_name: "web1.magedu.com"
root: "/var/www/nginx/web1/"
- web2:
listen: 8080
server_name: "web2.magedu.com"
root: "/var/www/nginx/web2/"
- web3:
listen: 8080
server_name: "web3.magedu.com"
root: "/var/www/nginx/web3/"
## 案例1
# nginx_vhosts:
# - web1
# - web2
# - web3
## 案例2
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
// templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
server_name {{ vhost.server_name }}
root {{ vhost.root }}
}
{% endfor %}
* 生成結果:
server {
listen 8080
server_name web1.magedu.com
root /var/www/nginx/web1/
}
server {
listen 8080
server_name web2.magedu.com
root /var/www/nginx/web2/
}
server {
listen 8080
server_name web3.magedu.com
root /var/www/nginx/web3/
}
* 案例4
// templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}
root {{ vhost.root }}
}
{% endfor %}
// temnginx.yml
---
- hosts: mageduweb
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8080
#server_name: "web1.magedu.com"
root: "/var/www/nginx/web1/"
- web2:
listen: 8080
server_name: "web2.magedu.com"
root: "/var/www/nginx/web2/"
- web3:
listen: 8080
server_name: "web3.magedu.com"
root: "/var/www/nginx/web3/"
## 案例1
# nginx_vhosts:
# - web1
# - web2
# - web3
## 案例2
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
* 執行命令
ansible-playbook temnginx.yml
* 生成的結果
server {
listen 8080
root /var/www/nginx/web1/
}
server {
listen 8080
server_name web2.magedu.com
root /var/www/nginx/web2/
}
server {
listen 8080
server_name web3.magedu.com
root /var/www/nginx/web3/
}
### ansible-playbook when條件判斷
---
- hosts: mageduweb
remote_user: root
tasks:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: restart Nginx
service: name=nginx state=restarted
when: ansible_distribution_major_version == "6"
### ansible-playbook with_items 列表
---
- hosts: mageduweb
remote_user: root
tasks:
- name: create rsyncd file
copy: src={{ item }} dest=/tmp/{{ item }}
with_items:
- a
- b
- c
- d
- name: yum install httpd
yum: name={{ item }} state=present
with_items:
- apr
- apr-util
- httpd
* with_itmes 嵌套子變量
---
- hosts: mageduweb
remote_user: root
tasks:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: ‘testuser1‘ , groups: ‘wheel‘}
- { name: ‘testuser2‘ , groups: ‘root‘}
1、普通示例:
這裏/root/nginx.conf內容發生了改變。
- hosts: ngxsrvs
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=latest
- name: install conf file
template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: ngxconf
notify: reload nginx service
- name: start nginx service
service: name=nginx state=started enabled=true
handlers:
- name: reload nginx service
shell: /usr/sbin/nginx -s reload
2、條件測試:
when語句:在tasks中使用,Jinja2的語法格式;
- hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=latest
- name: start nginx service on CentOS6
shell: service nginx start
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
- name: start nginx service
shell: systemctl start nginx.service
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
3、循環:叠代,需要重復執行的任務;
對叠代項的引用,固定變量名為”item”,使用with_item屬性給定要叠代的元素; 這個是以任務為中心,圍繞每個任務來跑主機,如果中間某個任務中斷,那麽所有主機以後的任務就無法安裝。
元素:
- 列表
- 字符串
- 字典
基於字符串列表給出元素示例:
- hosts: websrvs
remote_user: root
tasks:
- name: install packages
yum: name={{ item }} state=latest
with_items:
- httpd
- php
- php-mysql
- php-mbstring
- php-gd
基於字典列表給元素示例:item.name .
後邊的表示鍵
- hosts: all
remote_user: root
tasks:
- name: create groups
group: name={{ item }} state=present
with_items:
- groupx1
- groupx2
- groupx3
- name: create users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- {name: ‘userx1‘, group: ‘groupx1‘}
- {name: ‘userx2‘, group: ‘groupx2‘}
- {name: ‘userx3‘, group: ‘groupx3‘}
角色:roles
以特定的層級目錄結構進行組織的tasks、variables、handlers、templates、files等;相當於函數的調用把各個事件切割成片段來執行。
mkdir ./{nginx,memcached,httpd,mysql}/{file,templates,vars,handlers,meta,default,tasks} -pv
role_name/
files/:存儲由copy或script等模塊調用的文件;
tasks/:此目錄中至少應該有一個名為main.yml的文件,用於定義各task;其它的文件需要由main.yml進行“包含”調用;
handlers/:此目錄中至少應該有一個名為main.yml的文件,用於定義各handler;其它的文件需要由main.yml進行“包含”調用;
vars/:此目錄中至少應該有一個名為main.yml的文件,用於定義各variable;其它的文件需要由main.yml進行“包含”調用;
templates/:存儲由template模塊調用的模板文本;
meta/:此目錄中至少應該有一個名為main.yml的文件,定義當前角色的特殊設定及其依賴關系;其它的文件需要由main.yml進行“包含”調用;
default/:此目錄中至少應該有一個名為main.yml的文件,用於設定默認變量;
在playbook中調用角色的方法:
- hosts: HOSTS
remote_user: USERNAME
roles:
- ROLE1
- ROLE2
- { role: ROLE3, VARIABLE: VALUE, ...}
- { role: ROLE4, when: CONDITION }
事例: 基於角色的方式安裝 nginx
1.創建需要的文件
mkdir ./{nginx,memcached,httpd,mysql}/{files,templates,vars,handlers,meta,default,tasks} -pv
2.復制相應的安裝包和模板到對應目錄下
3.寫tasks/下的主main.yml
- name: copy nginx package
copy: src=nginx-1.10.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.0-1.el7.ngx.x86_64.rpm
- name: install nginx package
yum: name=/tmp/nginx-1.10.0-1.el7.ngx.x86_64.rpm state=present
- name: install nginx.conf file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: ngxconf
notify: reload nginx service
- name: install default.conf file
template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
tags: ngxconf
notify: reload nginx service
- name: start nginx service
service: name=nginx enabled=true state=started
4.根據需要修改nginx的配置文件模板。(這裏改的是work進程生成數和監聽的端口)
5.寫handlers目錄和vars/下的main.yml 文件
6.寫需要運行的主yml文件
7.測試
8.運行
安裝成功
9.改端口測試,通過傳遞參數方式
修改成功!!!
Ansible詳解(二)