我們已經知道,基于集群可實現服務器橫向擴展slace out。可是,當上百臺主機集合成共同為一個站點提供web頁面訪問的形式時,怎么管理整個集群體呢?
一些小伙伴大概聽說過pxe等可實現自動安裝系統。可是,要我們一臺一臺主機的開機,一個個的載入引導文件,當這個主機基數足夠龐大時,那也著實不是一件輕松的事情。這樣的工作做上個個把月,也就不用在運維界混了。
誒,不要慫。阿拉今天這不就要介紹這么一個可以幫我們實現批量化主機命令管理的工具了嘛!
試想一下,ansible用在年底擴容促銷時簡直無疑與一件大殺器。
但是,這樣個玩意,也是有使用前提的。拿尼,只是運維界的業內規范而已————標準化、自動化、架構優化、過程優化。
哈哈,理想狀態下的運維部門果然應該是如下的形式吧!
理想狀態下的運維部門:
1、只有少數類型的硬件,便于管理
2、系統版本統一
3、目錄結構規范
4、運維工程師水平層次高
5、無歷史包袱
6、同一軟件只有單一版本
7、同一類操作可自動化批量執行
8、工作效率高,無大量重復機械化操作
9、開發自己上線,運維比較輕松
然而,現實往往是只會讓人吐血。不過還是暫行鎮靜,身體是自己的,且行且珍惜。所以,遇到下面的情形時,一定要平靜心緒,摒棄興奮,告訴自己憋激動。挑戰即機遇,不過咱也得先做好不是!
目前多數公司遇到的運維問題現狀:
1、硬件選型多樣化?
2、系統多版本并存
3、目錄結構混亂
4、運維人員水平參差不齊
5、歷史遺留問題多
6、同一軟件出現多個版本
7、無法批量化操作
8、工作效率低,故障率高
9、項目上線操作繁瑣
至于大施拳腳的方式,那就仁者見仁智者見智了。各位都是運維界的精英,到時候說不定阿拉還有求到各位的地方,就希望大佬們到時候不吝賜教啦!
說起來以上也差不多就是咱運維的工作內容了,嗯,列舉出來就是:
日常運維工作中的重要事件:
1、添加監控,收集系統指標
2、對日志進行歸檔以及管理
3、數據備份于恢復
4、對計劃任務進行管理
5、對軟件包進行部署和管理
6、對腳本進行批量執行
7、對文件進行批量復制和移動
8、設置文件或者目錄對應的權限
9、關閉和啟動服務
10、對代碼程序進行上下線
企業里,在日常工作中不斷優化系統架構和部署的合理性是一項長期而持續的工作。嗯,與諸君共勉!
生活真是不易又刺激啊!嘛,阿拉現在要說的,是基于標準化之后的系統環境之后的部分。哈哈。
ansible簡介
安裝
這個簡單。配置好epel源的話直接yum install ansible就哦了。
另外ansible是python編寫的。如果沒pip,需先安裝pip.yum可直接安裝:yum install python-pip。
操作方式
Ansible系統由控制主機對被管節點的操作方式可分為兩類,即ad-hoc和playbook。簡單來說,ad-hoc是命令行管理,實現功能單一。playbook類似腳本,可通過ad-hoc命令堆砌的形式實現整體的功能,嘛,當成腳本理解是沒錯的。要說不同,就是這個命令行和腳本的語法有點怪了。
主配置文件
[root@cet7 ansible]# ls /etc/ansible -l
-rw-r--r-- 1 root root 14420 Dec 4 14:30 ansible.cfg
-rw-r--r-- 1 root root 1057 Dec 4 11:57 hosts
drwxr-xr-x 2 root root 6 Jan 17 2017 roles
- [ ] 主配置文件里的日志開啟下就可以直接使用了。
- [ ] hoste文件定義主機,即ansible服務器所轄的節點。可按其功能定義不同的組,通過組來發出命令。
- [ ] roles文件夾以結構化的形式定義出ansible執行命令所需的各因素。
- [ ] 可以直接在此目錄下定義.yml的獨立playbook文件。也可與roles下定義的變量等相關聯。
配置的詳細信息下面還有專門的介紹。
命令執行過程
1、加載自己的配置文件 默認/etc/ansible/ansible.cfg
2、查找對應的主機配置文件,如hosts,找到要執行的主機或者組
3、加載自己對應的模塊文件,如command
4、通過ansible將模塊或命令生成對應的臨時py文件(python格式),并將該文件傳輸至遠程服務器
5、對應執行用戶的家目錄下的.ansible/tmp/XXX/XXX.PY文件
6、給文件+x執行
7、執行并返回結果
8、刪除臨時py文件,sleep 0退出
Ansible配置
主配置文件ansible.cfg
ansible有許多參數,下面列出常用的參數:
1.inventory
這個參數表示資源清單inventory文件的位置,資源清單就是一些Ansible需要連接管理的主機列表。這個參數的配置實例如下:
inventory = /etc/ansible/hosts
2.library
Ansible的操作動作,無論是本地或遠程,都使用一小段代碼來執行,這小段代碼稱為模塊,這個library參數就是指向存放Ansible模塊的目錄。配置實例如下:
library = /usr/share/ansible
Ansible支持多個目錄方式,只要用冒號(:)隔開就可以,同時也會檢查當前執行playbook位置下的./library目錄。
3.forks
設置默認情況下Ansible最多能有多少個進程同時工作, 從Ansible 1.3開始,fork數量默認
自動設置為主機數量或者潛在的主機數量,默認設置最多5個進程并行處理。具體需要設置多少個,可以根據控制主機的性能和被管節點的數量來確定,可能是50或100。默認值5是非常保守的值,配置實例如下:
forks = 5
4.sudo_user
這是設置默認執行命令的用戶,也可以在playbook中重新設置這個參數。配置實例如下:
sudo_user = root
5.remote_port
這是指定連接被管節點的管理端口,默認是22。除非設置了特殊的SSH端口,不然這個參數一般是 不需要修改的。配置實例如下:
remote_port = 22
6.host_key_checking
這是設置是否檢查SSH主機的密鑰。可以設置為True或False,關閉后第一次連接沒有提示。配置實例:
host_key_checking = False
7.timeout
這是設置SSH連接的超時間隔,單位是秒。配置實例如下:
timeout = 60
8.log_path
Ansible系統默認是不記錄日志的,如果想把Ansible系統的輸出記錄到日志文件中,需要設置log_path來指定一個存儲Ansible日志的文件。配置實例如下:
log_path = /var/log/ansible.log
另外需要注意,執行Ansible的用戶需要有寫入日志的權限,模塊將會調用被管節點的syslog來記錄
主機清單設置文件hosts
/etc/ansible/hosts定義方式:
1、直接指明主機地址或主機名:
green.example.com
blue.example.com
192.168.100.1
192.168.100.10
2、定義一個主機組[組名]把地址或主機名加進去
[web]
node1.magedu.com
node2.magedu.com
#組成員可以使用通配符來匹配,如172.17.7.[101:1066]表示匹配從172.17.30.101——172.17.30.106的主機
Ansible命令集
1.ansible: Ansibe AD-Hoc臨時命令執行工具,常用于臨時命令的執行
命令格式:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
-a 跟模塊的參數,如果執行默認COMMAND的模塊,即是命令參數
-C 只是測試一下會改變什么內容,不會真正去執行
-f 并行任務數。需指定為一個整數,默認是5
-i 指定庫存主機文件的路徑,默認為/etc/ansible/hosts
-m 指定執行模塊的名字,默認使用 command 模塊
-S su,用 su 命令
-R 指定SU的用戶,默認是root用戶
-s sudo
-U sudo到哪個用戶,默認為 root
-T 指定SSH默認超時時間,默認是10S
-t 將日志內容保存在該輸出目錄,結果保存在一個文件中在每臺主機上
-u 遠程用戶,默認是root用戶
-v,-vv,-vvv 輸出ansible的版本及詳細信息
2.ansible-doc: Ansible模塊功能查看工具
-l: 獲取模塊信息
-s: MOD_NAME 獲取指定模塊的使用幫助
-v: 顯示ansible-doc的版本號查看模塊列表
3.ansible-galaxy: 下載/上傳優秀代碼或Roles模塊的官網平臺,基于網絡的
4.ansible-playbook: Ansible定制自動化的任務集編排工具
5.ansible-pull: Ansible遠程執行命令的工具,拉取配置而非推送配置(使用較少,海量機器時使用,對運維的架構能力要求較高)
6.ansible-vault: Ansible 文件加密工具
7.ansible-console: Ansible基于Linux Consoble界面可與用戶交互的命令執行工具
Ansible使用
Ansible配置公私鑰
雖然ansible支持其他主機認證方式,但是我們最常用的的還是基于秘鑰的認證:
1、首先生成秘鑰
ssh-keygen -t rsa -P ''
2、然后向主機分發秘鑰:
ssh-copy-id root@ #@后面跟主機名或者IP地址
3、如果出現以下情況:
# ssh-copy-id -i ~/.ssh/id_rsa.pub 10.1.6.72
-bash: ssh-copy-id: command not found
請嘗試:
yum -y install openssh-clientsansible
Ansible常用模塊
1.ping:主機連通性測試:
[root@desperadochn ~]# ansible all -m ping
192.168.253.138 | SUCCESS => { “changed”: false, “ping”: “pong” }
192.168.253.137 | SUCCESS => { "changed": false, "ping":
2.command:在遠程主機執行命令;不支持|管道命令
- [ ] 命令模塊接受命令名稱,后面是空格分隔的列表參數。給定的命令將在所有選定的節點上執行。它不會通過shell進行處理,比如$HOME和操作符如”小于”<“,”>”, “|”, “;”,”&”‘ 工作(需要使用(shell)模塊實現這些功能)。
- [ ] 該模塊可使用的子選項如下(定義在-a后):
chdir # 在執行命令之前,先切換到該目錄
creates # 一個文件名,當這個文件存在,則該命令不執行,可以用來做判斷
executable # 切換shell來執行命令,需要使用命令的絕對路徑
free_form # 要執行的Linux指令,一般使用Ansible的-a參數代替。
removes # 一個文件名,這個文件不存在,則該命令不執行,與creates相反的判斷
[root@cet7 ansible]# ansible web -m command -a 'ls'
node1.magedu.com | SUCCESS | rc=0 >>
172.17.30.102
5
anaconda-ks.cfg
bin
hello.jpg
initial-setup-ks.cfg
mha4mysql-manager-0.56-0.el6.noarch.rpm
mha4mysql-node-0.56-0.el6.noarch.rpm
nohup.outnode2.magedu.com | SUCCESS | rc=0 >>
anaconda-ks.cfg
bin
crontab
FLUSH
initial-setup-ks.cfg
mha4mysql-manager-0.56-0.el6.noarch.rpm
mha4mysql-node-0.56-0.el6.noarch.rpm
UNLOCK[root@cet7 ansible]# ansible web -m command -a 'chdir=/app ls'
node1.magedu.com | SUCCESS | rc=0 >>
fastdfs
mogilefs
zabbix-release-3.4-1.el7.centos.noarch.rpmnode2.magedu.com | SUCCESS | rc=0 >>
fastdfs
zabbix
zabbix-release-3.4-1.el7.centos.noarch.rpm
3、shell模塊在遠程主機上調用shell解釋器運行命令,支持shell的各種功能,例如管道等
[root@cet7 ansible]# ansible web -m shell -a 'cat /etc/passwd|grep "root"'
node1.magedu.com | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologinnode2.magedu.com | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
4.copy:復制文件到遠程主機,可以改權限等
相關選項如下:
backup:在覆蓋之前,將源文件備份,備份文件包含時間信息。有兩個選項:yes|no
content:用于替代“src”,可以直接設定指定文件的值
dest:必選項。要將源文件復制到的遠程主機的絕對路徑,如果源文件是一個目錄,那么該路徑也必須是個目錄
directory_mode:遞歸設定目錄的權限,默認為系統默認權限
force:如果目標主機包含該文件,但內容不同,如果設置為yes,則強制覆蓋,如果為no,則只有當目標主機的目標位置不存在該文件時,才復制。默認為yes
others:所有的file模塊里的選項都可以在這里使用
src:被復制到遠程主機的本地文件,可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,它將遞歸復制。在這種情況下,如果路徑使用“/”來結尾,則只復制目錄里的內容,如果沒有使用“/”來結尾,則包含目錄在內的整個內容全部復制,類似于rsync。
用法:
(1) 復制文件
-a "src= dest= "
[root@cet7 ansible]# ansible web -m copy -a 'dest=/etc/nginx/nginx.conf src=/tmp/nginx.conf backup=yes'
node1.magedu.com | SUCCESS => {"backup_file": "/etc/nginx/nginx.conf.98474.2017-12-05@19:08:38~", "changed": true, "checksum": "c5001a957cc53286f448b5519183f21c3ac82a90", "dest": "/etc/nginx/nginx.conf", "gid": 0, "group": "root", "md5sum": "2ca5097c8b871a904650b483da85cc65", "mode": "0644", "owner": "root", "size": 2466, "src": "/root/.ansible/tmp/ansible-tmp-1512472114.1-112119450637656/source", "state": "file", "uid": 0
}
node2.magedu.com | SUCCESS => {"backup_file": "/etc/nginx/nginx.conf.126834.2017-12-05@19:08:39~", "changed": true, "checksum": "c5001a957cc53286f448b5519183f21c3ac82a90", "dest": "/etc/nginx/nginx.conf", "gid": 0, "group": "root", "md5sum": "2ca5097c8b871a904650b483da85cc65", "mode": "0644", "owner": "root", "secontext": "system_u:object_r:httpd_config_t:s0", "size": 2466, "src": "/root/.ansible/tmp/ansible-tmp-1512472118.6-139130457070354/source", "state": "file", "uid": 0
}
(2) 給定內容生成文件
-a "content= dest= "
[root@cet7 ansible]# ansible web -m copy -a 'content="hello jone" dest=/root/a.txt backup=yes'
node1.magedu.com | SUCCESS => {"changed": true, "checksum": "dc302a377c9890ad3ea20b0d252d8c06e437ff97", "dest": "/root/a.txt", "gid": 0, "group": "root", "md5sum": "de66aa1fe06344d982e2e7448cbdfb20", "mode": "0644", "owner": "root", "size": 10, "src": "/root/.ansible/tmp/ansible-tmp-1512472257.6-80857257348609/source", "state": "file", "uid": 0
}
node2.magedu.com | SUCCESS => {"changed": true, "checksum": "dc302a377c9890ad3ea20b0d252d8c06e437ff97", "dest": "/root/a.txt", "gid": 0, "group": "root", "md5sum": "de66aa1fe06344d982e2e7448cbdfb20", "mode": "0644", "owner": "root", "secontext": "system_u:object_r:admin_home_t:s0", "size": 10, "src": "/root/.ansible/tmp/ansible-tmp-1512472258.3-112721288787897/source", "state": "file", "uid": 0
}
[root@cet7 ansible]# ansible web -m shell -a 'cat /root/a.txt'
node1.magedu.com | SUCCESS | rc=0 >>
hello jonenode2.magedu.com | SUCCESS | rc=0 >>
hello jone
5、其他模塊
(1) file模塊: Sets attributes of files
用法:
<1> 創建鏈接文件:*path= src= state=link
<2> 修改屬性:path= owner= mode= group=?
<3> 創建目錄:path= state=directory
注意:state屬性的可用值:file,directory,link,hard,touch,absent
(2) get_url模塊: Downloads files from HTTP, HTTPS, or FTP to node
*url=
*dest=
sha256sum=
owner, group, mode
(3) git模塊:Deploy software (or files) from git checkouts
repo=dest=version=
(4) deploy_helper模塊:Manages some of the steps common in deploying projects.
(5) haproxy模塊:Enable, disable, and set weights for HAProxy backend servers using socket commands.
backend=
host=
state=
weight=
(6) cron 模塊:Manage cron.d and crontab entries.
minute=
day=
month=
weekday=
hour=
job=
*name=
state=(present:創建\|absent:刪除)
(7) hostname模塊:Manage hostname
name=
(8) pip模塊:Manages Python library dependencies.
name=
state=
version=
(9) npm模塊:Manage node.js packages with npm
name=
state=
version=
(10) yum模塊:Manages packages with the `yum' package manager
name=(程序包名稱,可以帶版本號)
state=present, latest, installedabsent, removed
- [ ] 其它的包管理工具:apt(debian), zypper(suse), dnf(fedora), rpm, dpkg, ...
(11) service模塊:管理服務
*name=
state=startedstoppedrestarted
enabled=
runlevel=
(12) setup模塊:獲取facters,即獲取系統相關的各項參數
Playbook
Playbook是YAML語言寫成的劇本,但其本質仍是模板調用。劇本用來執行一系列命令,類似腳本。
YAML語言以縮進區分級別,以-區分鍵值,所以次語言對格式要求很高。
比如以下:
用命令行寫的遠程安裝redis的命令轉化為playbook的格式即是:
ansible node1.magedu.com -m yum -a "name=redis state=latest"
vim first.yaml
---
- hosts: node1.magedu.comremote_user: roottasks: - name: install redisyum: name=redis state=latest
hosts: 后跟的主機,需在/etc/ansible/hosts里事先定義;
remote_user: 遠程主機執行命令的用戶身份;
tasks: 顧名思義,任務列表;
name: 一個name代表一個任務,后跟任務名,實際作用為區分所執行的任務;
yum: 調用的模塊。后跟的內容對應命令行-a后的內容。
單個任務而言顯然是命令行更高效。單要是一長串的任務playbook的優勢就明顯了。比如安裝后啟動redis。
vim second.yaml
---
- hosts: node1.magedu.comremote_user: roottasks: - name: install redisyum: name=redis state=latest- name: start redisservice: name=redis start=started
一個稍微全面的playbook如下,里面還有我們尚未提及的內容:
vim third.yaml
---
- hosts: allremote_user: roottasks: - name: install redisyum: name=redis state=latest- name: copy config filecopy: src=/root/playbook/redis.conf dest=/etc/redis.conf owner=redisnotify: restart redistags: configfile- name: start redisservice: name=redis start=startedhandlers: - name: restart redisservice: name=redis state=restarted
notify: 定義觸發任務。這里指copy config file任務執行成功會觸發執行restart redis任務;
handlers: 由特定條件觸發才會執行相對應的任務;
tags: 為任務添加標簽,可調用單獨執行一個命令,如: ansible-playbook -t configfile third.yaml,意為只執行標簽為configfile的任務,即只拷貝redis的配置文件。
對應此,我們詳細說下playbook。
運行playbook的方式:
(1) 測試
- [ ] ansible-playbook --check: 只檢測可能會發生的改變,但不真正執行操作;
- [ ] ansible-playbook --list-hosts: 列出運行任務的主機;
- [ ] ansible-playbook --list-tasks: 列出要運行的任務列表
- [ ] ansible-playbook --syntax-check: 語法檢查
(2) 運行
- [ ] ansible-playbook xx.yaml
playbook的基礎組件:
Hosts:運行指定任務的目標主機;
remoute_user: 在遠程主機上執行任務的用戶;sudo_user:
tasks:任務列表模塊,模塊參數;格式:(1) action: module arguments(2) module: arguments注意:shell和command模塊后面直接跟命令,而非key=value類的參數列表;(1) 某任務的狀態在運行后為changed時,可通過“notify”通知給相應的handlers;(2) 任務可以通過"tags"打標簽,而后可在ansible-playbook命令上使用-t指定進行調用;handlers:任務,在特定條件下觸發;接收到其它任務的通知時被觸發;
notify: HANDLER TASK NAMEvariables:(1) facts:可直接調用;注意:可使用setup模塊直接獲取目標主機的facters;(2) 用戶自定義變量:(a) ansible-playbook命令的命令行中的-e VARS, --extra-vars=VARS (b) 在playbook中定義變量的方法:vars:- var1: value1- var2: value2變量引用:{{ variable }}(3) 通過roles傳遞變量;(4) Host Inventory(a) 用戶自定義變量(i) 向不同的主機傳遞不同的變量;IP/HOSTNAME varaiable=value var2=value2(ii) 向組中的主機傳遞相同的變量;[groupname:vars]variable=value(b) invertory參數用于定義ansible遠程連接目標主機時使用的參數,而非傳遞給playbook的變量;ansible_ssh_hostansible_ssh_portansible_ssh_useransible_ssh_passansbile_sudo_pass...補充模塊:setup模塊:template模塊:基于模板方式生成一個文件復制到遠程主機*src=*dest=owner=group=mode=模板:templates文本文件,嵌套有腳本(使用模板編程語言編寫)Jinja2:字面量:字符串:使用單引號或雙引號;數字:整數,浮點數;列表:[item1, item2, ...]元組:(item1, item2, ...)字典:{key1:value1, key2:value2, ...}布爾型:true/false算術運算:+, -, *, /, //, %, **比較操作:==, !=, >, >=, <, <=邏輯運算:and, or, not 示例: - hosts: websrvsremote_user: roottasks:- name: install nginxyum: name=nginx state=present- name: install conf filetemplate: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.confnotify: restart nginxtags: instconf- name: start nginx serviceservice: name=nginx state=startedhandlers:- name: restart nginxservice: name=nginx state=restarted 模板配置文件 :nginx.conf.j2worker_processes {{ ansible_processor_vcpus - 1 }};listen {{ http_port }};server_name 條件測試:when語句:在task中使用,jinja2的語法格式tasks: - name: install conf file to centos7template: src=files/nginx.conf.c7.j2when: ansible_distribution_major_version == "7"- name: install conf file to centos6template: src=files/nginx.conf.c6.j2when: ansible_distribution_major_version == "6" 循環:迭代,需要重復執行的任務;對迭代項的引用,固定變量名為”item“而后,要在task中使用with_items給定要迭代的元素列表;列表方法:字符串字典- name: install some packagesyum: name={{ item }} state=presentwith_items:- nginx- memcached- php-fpm- name: add some groupsgroup: name={{ item }} state=presentwith_items:- group11- group12- group13- name: add some usersuser: name={{ item.name }} group={{ item.group }} state=presentwith_items:- { name: 'user11', group: 'group11' }- { name: 'user12', group: 'group12' }- { name: 'user13', group: 'group13' }角色(roles):角色集合:roles/mysql/httpd/nginx/memcached/每個角色,以特定的層級目錄結構進行組織:mysql/files/ :存放由copy或script模塊等調用的文件;templates/:template模塊查找所需要模板文件的目錄;tasks/:至少應該包含一個名為main.yml的文件;其它的文件需要在此文件中通過include進行包含;handlers/:至少應該包含一個名為main.yml的文件;其它的文件需要在此文件中通過include進行包含;vars/:至少應該包含一個名為main.yml的文件;其它的文件需要在此文件中通過include進行包含;meta/:至少應該包含一個名為main.yml的文件,定義當前角色的特殊設定及其依賴關系;其它的文件需要在此文件中通過include進行包含;default/:設定默認變量時使用此目錄中的main.yml文件;在playbook調用角色方法1:- hosts: websrvsremote_user: rootroles:- mysql- memcached- nginx在playbook調用角色方法2:傳遞變量給角色- hosts: remote_user:roles:- { role: nginx, username: nginx }鍵role用于指定角色名稱;后續的k/v用于傳遞變量給角色;還可以基于條件測試實現角色調用;roles:- { role: nginx, when: "ansible_distribution_major_version == '7' " }ansible-vcs:https://github.com/andrewrothstein/ansible-vcs本文轉自阿拉杜美美51CTO博客,原文鏈接:http://blog.51cto.com/amelie/2049108 ,如需轉載請自行聯系原作者