一,ansible簡介
ansible是新出現的自動化運維工具,基於Python開發,集合了衆多運維工具(puppet、cfengine、chef、func、fabric)的優勢,其批量系統配置、批量程序部署、批量運行命令等功能配置起來十分簡單。ansible是基於模塊工做的,自己沒有批量部署的能力。真正具備批量部署的是ansible所運行的模塊,ansible只是提供一種框架。主要包括:node
- <code>
- (1)、鏈接插件connection plugins:負責和被監控端實現通訊;
-
- (2)、host inventory:指定操做的主機,是一個配置文件裏面定義監控的主機;
-
- (3)、各類模塊核心模塊、command模塊、自定義模塊;
-
- (4)、藉助於插件完成記錄日誌郵件等功能;
-
- (5)、playbook:劇本執行多個任務時,非必需可讓節點一次性運行多個任務。
- </code>
ansible是我使用的第一個自動化運維工具,上手感受很是簡單,其設計原則以下:python
- <code>
- 安裝過程簡單;
- 運行速度較快;
- 不須要服務器或客戶端程序,利用現有的sshd服務;
- 使用一種人機友好的語言;
- 注重安全;
- 能快速管理遠程機器,不用引導;
- 基於模塊工做,可以使用任意語言開發模塊;
- 可做爲非root使;
- 永遠是最容易使用的自動化系統。
- </code>
2、安裝
2.1 編譯安裝mysql
- <code>
- [root@node1 ansible]# yum install -y PyYAML python-crypto2.6 python-httplib2 python-jinja2 python-keyczar python-paramiko python-setuptools python-simplejson #解決依賴關係
- [root@node1 ansible]# tar xf ansible-1.5.4.tar.gz
- [root@node1 ansible]# cd ansible-1.5.4
- [root@node1 ansible]# python setup.py build
- [root@node1 ansible]# python setup.py install
- [root@node1 ansible]# mkdir /etc/ansible
- [root@node1 ansible]# cp -r examples/* /etc/ansible
- </code>
2.2 rpm包安裝linux
下面使用rpm包安裝做爲實例,使用ansible-1.9.2-1.el6.noarch.rpm!web
- <code>
- [root@sta ansible]# yum install -y PyYAML python-crypto2.6 python-httplib2 python-jinja2 python-keyczar python-paramiko python-setuptools python-simplejson #解決依賴關係
- [root@node1 ansible]# rpm -ivh ansible-1.9.2-1.el6.noarch.rpm
- [root@node1 ansible]# cd /etc/ansible/
- [root@node1 ansible]# ls
- ansible.cfg hosts roles
- </code>
2.3 定義主機與組sql
- <code>
- [root@node1 ansible]# vim hosts #在hosts文件中定義主機與組
- :.,$s/^\([^[:space:]#]\)/#/g ------》在末行模式下,使用如下命令註釋掉全部的行
- [webservers] ---------》在文件末添加一個webservers組
- node1.feiyu.com
- node2.feiyu.com
- </code>
Ansible內置了一些關於鏈接主機的變量,設置如下變量控制ansible與遠程主機:shell
- <code>
- ansible_ssh_host:ansible經過ssh鏈接的主機地址。
- ansible_ssh_port:SSH鏈接主機的默認端口。
- ansible_ssh_user:默認SSH鏈接的用戶。
- ansible_ssh_pass:SSH鏈接的密碼(這是不安全的,ansible極力推薦使用--ask-pass選項或使用SSH keys)。
- ansible_sudo_pass:sudo用戶的密碼。
- ansible_connection:SSH鏈接的類型,能夠是 local,ssh,paramiko,在ansible 1.2以前默認是paramiko,後來智能選擇,優先使用基於ControlPersist的ssh(支持的前提)。
- ansible_ssh_private_key_file:SSH鏈接的公鑰文件。
- ansible_shell_type:指定主機所使用的shell解釋器,默認是sh,你能夠設置成csh, fish等shell解釋器。
- ansible_python_interpreter:用來指定python解釋器的路徑。
- ansible\_\*\_interpreter:用來指定主機上其餘語法解釋器的路徑,例如ruby,perl等其餘解釋器。
- </code>
例如:apache
- <code>
- feiyu ansible_ssh_port=2222 ansible_ssh_user=manager
- my_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
- freebsd_host ansible_python_interpreter=/usr/local/bin/python
- ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
- </code>
組成員也支持正則表述:json
- <code>
- [webserver]
- www[01-50].tianfeiyu.com
-
- [databases]
- db-[a:f].example.com
- </code>
3、簡單應用
ansible經過ssh實現配置管理、應用部署、任務執行等功能,所以,須要事先配置ansible端能基於密鑰認證的方式聯繫各被管理節點。vim
語法格式爲:
- <code>
- ansible [-f forks] [-m module_name] [-a args]
- -m module:默認爲command
- </code>
1,使用ping模塊
- <code>
- [root@node1 ansible]# ansible all -m ping #-m指定模塊,通常執行成功顯示爲黃色或綠色,失敗爲紅色
- node1.feiyu.com | success >> {
- "changed": false,
- "ping": "pong"
- }
-
- node2.feiyu.com | success >> {
- "changed": false,
- "ping": "pong"
- }
-
- [root@node1 ansible]# ansible all -a 'date' #-a表示使用命令,沒指定模塊表示使用默認模塊,-m command
- node1.feiyu.com | success | rc=0 >>
- Tue Aug 18 03:48:32 PDT 2015
-
- node2.feiyu.com | success | rc=0 >>
- Tue Aug 18 03:48:32 PDT 2015
-
- [root@node1 ansible]# ansible all -a 'service httpd status'
- node1.feiyu.com | FAILED | rc=3 >>
- httpd is stopped
-
- node2.feiyu.com | FAILED | rc=3 >>
- httpd is stopped
- </code>
注意:其不支持管道的方式!!!
- <code>
- [root@node1 ansible]# ansible-doc -l #列出全部模塊
- </code>
2,使用copy模塊
- <code>
- [root@node1 ansible]# ansible-doc -s copy #查看copy模塊的用法
- </code>
## 複製文件到遠程主機
相關選項以下:
- <code>
- backup:在覆蓋以前,將源文件備份,備份文件包含時間信息。有兩個選項:yes|no
- content:用於替代「src」,能夠直接設定指定文件的值
- dest:必選項。要將源文件複製到的遠程主機的絕對路徑,若是源文件是一個目錄,那麼該路徑也必須是個目錄
- directory_mode:遞歸設定目錄的權限,默認爲系統默認權限
- force:若是目標主機包含該文件,但內容不一樣,若是設置爲yes,則強制覆蓋,若是爲no,則只有當目標主機的目標位置不存在該文件時,才複製。默認爲yes
- others:全部的file模塊裏的選項均可以在這裏使用
- src:被複制到遠程主機的本地文件,能夠是絕對路徑,也能夠是相對路徑。若是路徑是一個目錄,它將遞歸複製。在這種狀況下,若是路徑使用「/」來結尾,則只複製目錄裏的內容,若是沒有使用「/」來結尾,則包含目錄在內的整個內容所有複製,相似於rsync。
- [root@node1 ansible]# ansible webservers -m copy -a "src=/etc/fstab dest=/tmp "
- node1.feiyu.com | success >> {
- "changed": true,
- "checksum": "bea5bff6ef922e8e603fc5714edbbf6fc613e321",
- "dest": "/tmp/fstab",
- "gid": 0,
- "group": "root",
- "md5sum": "87e134fd31b425a1d4f8fe43ade63a51",
- "mode": "0644",
- "owner": "root",
- "secontext": "unconfined_u:object_r:admin_home_t:s0",
- "size": 805,
- "src": "/root/.ansible/tmp/ansible-tmp-1439895335.38-56321228265546/source",
- "state": "file",
- "uid": 0
- }
-
- node2.feiyu.com | success >> {
- "changed": true,
- "checksum": "bea5bff6ef922e8e603fc5714edbbf6fc613e321",
- "dest": "/tmp/fstab",
- "gid": 0,
- "group": "root",
- "md5sum": "87e134fd31b425a1d4f8fe43ade63a51",
- "mode": "0644",
- "owner": "root",
- "secontext": "unconfined_u:object_r:admin_home_t:s0",
- "size": 805,
- "src": "/root/.ansible/tmp/ansible-tmp-1439895335.39-253641776148808/source",
- "state": "file",
- "uid": 0
- }
- </code>
3,使用cron模塊
- <code>
- [root@node1 ansible]# ansible all -m cron -a 'name="cron job" minute=*/3 hour=* day=* month=* weekday=* job="/usr/sbin/ntpdate 192.168.1.1"'
- node1.feiyu.com | success >> {
- "changed": true,
- "jobs": [
- "cron job"
- ]
- }
-
- node2.feiyu.com | success >> {
- "changed": true,
- "jobs": [
- "cron job"
- ]
- }
-
- [root@node1 ansible]# ansible all -a "crontab -l" #查看
- #Ansible: cron job
- */3 * * * * /usr/sbin/ntpdate 192.168.1.1
-
- #Ansible: cron job
- */3 * * * * /usr/sbin/ntpdate 192.168.1.1
- </code>
4,使用group模塊
- <code>
- [root@node1 ansible]# ansible all -m group -a "gid=306 system=yes name=mysql" #添加組,並建立爲系統用戶
- node1.feiyu.com | success >> {
- "changed": true,
- "gid": 306,
- "name": "mysql",
- "state": "present",
- "system": true
- }
-
- node2.feiyu.com | success >> {
- "changed": true,
- "gid": 306,
- "name": "mysql",
- "state": "present",
- "system": true
- }
- </code>
5,使用service模塊
- <code>
- [root@node1 ansible]# ansible all -m service -a "state=started name=httpd enabled=yes"
- node2.feiyu.com | success >> {
- "changed": true,
- "enabled": true,
- "name": "httpd",
- "state": "started"
- }
-
- node1.feiyu.com | success >> {
- "changed": true,
- "enabled": true,
- "name": "httpd",
- "state": "started"
- }
- </code>
6,file模塊
## 設置文件的屬性
相關選項以下:
- <code>
- force:須要在兩種狀況下強制建立軟連接,一種是源文件不存在,但以後會創建的狀況下;另外一種是目標軟連接已存在,須要先取消以前的軟鏈,而後建立新的軟鏈,有兩個選項:yes|no
- group:定義文件/目錄的屬組
- mode:定義文件/目錄的權限
- owner:定義文件/目錄的屬主
- path:必選項,定義文件/目錄的路徑
- recurse:遞歸設置文件的屬性,只對目錄有效
- src:被連接的源文件路徑,只應用於state=link的狀況
- dest:被連接到的路徑,只應用於state=link的狀況
- state:
- directory:若是目錄不存在,就建立目錄
- file:即便文件不存在,也不會被建立
- link:建立軟連接
- hard:建立硬連接
- touch:若是文件不存在,則會建立一個新的文件,若是文件或目錄已存在,則更新其最後修改時間
- absent:刪除目錄、文件或者取消連接文件
-
- [root@node1 tmp]# ansible all -m file -a "src=/etc/inittab dest=/tmp/a state=link" #建立連接
- </code>
4、YAML
4.1 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」(還是一種標記語言)。其特性:
- <code>
- YAML的可讀性好
- YAML和腳本語言的交互性好
- YAML使用實現語言的數據類型
- YAML有一個一致的信息模型
- YAML易於實現
- YAML能夠基於流來處理
- YAML表達能力強,擴展性好
- </code>
更多的內容及規範參見http://www.yaml.org。
4.2 YAML語法
YAML的語法和其餘高階語言相似,而且能夠簡單表達清單、散列表、標量等數據結構。其結構(Structure)經過空格來展現,序列(Sequence)裏的項用」-「來表明,Map裏的鍵值對用」:」分隔。下面是一個示例。
- <code>
- name: John Smith
- age: 41
- gender: Male
- spouse:
- name: Jane Smith
- age: 37
- gender: Female
- children:
- - name: Jimmy Smith #定義任務的說明
- age: 17
- gender: Male
- - name: Jenny Smith
- age 13
- gender: Female
- </code>
YAML文件擴展名一般爲.yaml,如example.yaml。
5、ansible playbooks
playbook是由一個或多個「play」組成的列表。play的主要功能在於將事先歸併爲一組的主機裝扮成事先經過ansible中的task定義好的角色。從根本上來說,所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中,便可以讓它們聯同起來按事先編排的機制同唱一臺大戲。下面是一個簡單示例。
- <code>
- - hosts: webnodes
- vars:
- http_port: 80
- max_clients: 256
- remote_user: root
- tasks:
- - name: ensure apache is at the latest version
- yum: name=httpd state=latest
- - name: ensure apache is running
- service: name=httpd state=started
- handlers:
- - name: restart apache
- service: name=httpd state=restarted
- </code>
5.1 playbook基礎組件
5.1.1 Hosts和Users
playbook中的每個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用於指定要執行指定任務的主機,其能夠是一個或多個由冒號分隔主機組;remote_user則用於指定遠程主機上的執行任務的用戶。如上面示例中的
- <code>
- -hosts: webnodes
- remote_user: root
- </code>
不過,remote_user也可用於各task中。也能夠經過指定其經過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務;此外,甚至能夠在sudo時使用sudo_user指定sudo時切換的用戶。
- <code>
- - hosts: webnodes
- remote_user: feiyu
- tasks:
- - name: test connection
- ping:
- remote_user: feiyu
- sudo: yes
- </code>
5.1.2 任務列表和action
play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的全部主機上執行,即在全部主機上完成第一個任務後再開始第二個。在運行自下而下某playbook時,若是中途發生錯誤,全部已執行任務都將回滾,所以,在更正playbook後從新執行一次便可。
task的目的是使用指定的參數執行模塊,而在模塊參數中可使用變量。模塊執行是冪等的,這意味着屢次執行是安全的,由於其結果均一致。
每一個task都應該有其name,用於playbook的執行結果輸出,建議其內容儘量清晰地描述任務執行步驟。若是未提供name,則action的結果將用於輸出。
定義task的可使用「action: module options」或「module: options」的格式,推薦使用後者以實現向後兼容。若是action一行的內容過多,也中使用在行首使用幾個空白字符進行換行。
- <code>
- tasks:
- - name: make sure apache is running
- service: name=httpd state=running
- </code>
在衆多模塊中,只有command和shell模塊僅須要給定一個列表而無需使用「key=value」格式,例如:
- <code>
- tasks:
- - name: disable selinux
- command: /sbin/setenforce 0
- </code>
若是命令或腳本的退出碼不爲零,可使用以下方式替代:
- <code>
- tasks:
- - name: run this command and ignore the result
- shell: /usr/bin/somecommand || /bin/true
- </code>
或者使用ignore_errors來忽略錯誤信息:
- <code>
- tasks:
- - name: run this command and ignore the result
- shell: /usr/bin/somecommand
- ignore_errors: True
- </code>
5.1.3 handlers
用於當關注的資源發生變化時採起必定的操做。
「notify」這個action可用於在每一個play的最後被觸發,這樣能夠避免屢次有改變發生時每次都執行指定的操做,取而代之,僅在全部的變化發生完成後一次性地執行指定操做。在notify中列出的操做稱爲handler,也即notify中調用handler中定義的操做。
- <code>
- - name: template configuration file
- template: src=template.j2 dest=/etc/foo.conf
- notify:
- - restart memcached
- - restart apache
- </code>
handler是task列表,這些task與前述的task並無本質上的不一樣。
- <code>
- handlers:
- - name: restart memcached
- service: name=memcached state=restarted
- - name: restart apache
- service: name=apache state=restarted
- </code>
案例:
- <code>
- heartbeat.yaml
- - hosts: hbhosts
- remote_user: root
- tasks:
- - name: ensure heartbeat latest version
- yum: name=heartbeat state=present
- - name: authkeys configure file
- copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
- - name: authkeys mode 600
- file: path=/etc/ha.d/authkeys mode=600
- notify:
- - restart heartbeat
- - name: ha.cf configure file
- copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
- notify:
- - restart heartbeat
- handlers:
- - name: restart heartbeat #與notify保持一致
- service: name=heartbeat state=restarted
-
- </code>