ansible 核心組件介紹
Architecture Diagram
ansible core
host iventory
core modules
custom modules
playbook (yaml)
connetc plugin
ansibles 的特性
基於python語言實現,有paramiko,Pyyaml和jinjia2 三個關鍵模塊
部署簡單,agegtlees,默認使用SSH協議
基於密鑰認證
在inventory 文件中指定賬號和密碼
ansible install
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux $ sudo yum install ansible
ansible config
配置文件:/etc/ansible/ansible.cfg
inventory:/etc/ansible/hosts
定製被管理主機:
cat /etc/ansible/host [webserver] 192.168.0.101 192.168.0.102
管理master 創建ssh密鑰
root@node2 ansible]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): [root@node2 ansible]# ls /root/.ssh/ /root/.ssh/id_rsa /root/.ssh/id_rsa.pub
將公鑰複製給slave節點,並驗證ssh證書登錄是否成功。
[root@node2 ansible]#ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] [root@node2 ansible]# ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] [root@node2 ansible]# ssh [email protected] 'date' Wed Feb 3 19:53:04 CST 2016 [root@node2 ansible]# ssh [email protected] 'date' Wed Feb 3 19:53:58 CST 2016
ansible-doc - show documentation on Ansible modules
[root@node2 ansible]# ansible-doc -l cron Manage cron.d and crontab entries. crypttab Encrypted Linux block devices datadog_event Posts events to DataDog service debconf Configure a .deb package debug Print statements during execution digital_ocean Create/delete a droplet/SSH_key in DigitalOcean digital_ocean_domain Create/delete a DNS record in DigitalOcean
查看模塊說明
[root@node2 ansible]# ansible-doc -s cron
ansible命令應用基礎
語法: ansible <host-pattern> [-f forks] [-m module_name] [-a args]
-f forks:啓動的併發數
-m module_name:使用的模塊
-args:模塊特有參數
EX:使用command模塊執行date指令,ansible 默認模塊,不支持變量傳遞。
[root@node2 ansible]# ansible webserver -m command -a "date" 192.168.0.101 | success | rc=0 >> Wed Feb 3 20:06:50 CST 2016 192.168.0.102 | success | rc=0 >> Wed Feb 3 20:06:03 CST 2016 [root@node2 ansible]# ansible webserver -a "date" 192.168.0.102 | success | rc=0 >> Wed Feb 3 20:10:35 CST 2016 192.168.0.101 | success | rc=0 >> Wed Feb 3 20:11:22 CST 2016
EX:cron模塊:每十分鐘運行“hello”
state
present 添加任務 absent 刪除任務
[root@node2 ansible]# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession"'
驗證結果
[root@node2 ansible]# ansible webserver -a "crontab -l" 192.168.0.101 | success | rc=0 >> #Ansible: ansibile cron lession */10 * * * * /bin/echo hello word 192.168.0.102 | success | rc=0 >> #Ansible: ansibile cron lession */10 * * * * /bin/echo hello word
刪除一個cron任務:
[root@node2 ansible]# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession" state=absent'
創建一個mysql 系統用戶
home: Check that parent folder is missing and run
[root@node2 ansible]# ansible webserver -m user -a "name=mysql system=yes shell='/sbin/nologin' home='/date/mysql'" 192.168.0.102 | success >> { "append": false, "changed": true, "comment": "", "group": 497, "home": "/date/mysql", "move_home": false, "name": "mysql", "shell": "/sbin/nologin", "state": "present", "uid": 497 } 192.168.0.101 | success >> { "append": false, "changed": true, "comment": "", "group": 498, "home": "/date/mysql", "move_home": false, "name": "mysql", "shell": "/sbin/nologin", "state": "present", "uid": 498 }
刪除一個mysql用戶
[root@node2 ansible]# ansible webserver -m user -a "user=mysql remove='yes' state=absent" 192.168.0.102 | success >> { "changed": true, "force": false, "name": "mysql", "remove": true, "state": "absent" } 192.168.0.101 | success >> { "changed": true, "force": false, "name": "mysql", "remove": true, "state": "absent" }
EX:copy 模塊:複製文件/etc/fstab 到/tmp/fstab.ansbile,文件所有者爲root,所屬組爲roo並且文件權限爲600
[root@node2 ansible]# ansible webserver -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible owner=root group=root mode=600" 192.168.0.101 | success >> { "changed": true, "checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078", "dest": "/tmp/fstab.ansible", "gid": 0, "group": "root", "md5sum": "05e29801d839073ed23aa6164e58646f", "mode": "0600", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 779, "src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-88392224178700/source", "state": "file", "uid": 0 } 192.168.0.102 | success >> { "changed": true, "checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078", "dest": "/tmp/fstab.ansible", "gid": 0, "group": "root", "md5sum": "05e29801d839073ed23aa6164e58646f", "mode": "0600", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 779, "src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-145879281527954/source", "state": "file", "uid": 0 }
EX:生成文件/tmp/test,內容爲"hello word"
[root@node2 ansible]# ansible webserver -m copy -a "content='hello word' dest=/tmp/test " [root@node2 ansible]# ansible all -m shell -a 'cat /tmp/test' 192.168.0.102 | success | rc=0 >> hello word 192.168.0.101 | success | rc=0 >> hello word
EX:文件權限管理
[root@node2 ansible]# ansible all -m file -a 'owner=mysql group=mysql mode=600 path=/tmp/fstab.ansible'
EX:創建軟連接文件
[root@node2 ansible]# ansible all -m file -a 'path=/tmp/fstab.link src=/tmp/fstab.ansible state=link' [root@node2 ~]# ll /tmp/* lrwxrwxrwx. 1 root root18 Feb 3 21:21 /tmp/fstab.link -> /tmp/fstab.ansible
EX:service 服務管理模塊
enabled: Whether the service should start on boot
[root@node2 ~]# ansible webserver -m service -a 'enabled=true name=nginx state=started'
EX: SHELL 指令模塊,可以使用變量及參數傳遞
[root@node2 ~]# ansible all -m shell -a 'echo redhat| passwd --stdin mysql' 192.168.0.102 | success | rc=0 >> Changing password for user mysql. passwd: all authentication tokens updated successfully. 192.168.0.101 | success | rc=0 >> Changing password for user mysql. passwd: all authentication tokens updated successfully.
EX:script 在遠端執行本地腳本
[root@node2 ~]# ansible all -m script -a '/tmp/test.sh'
EX:YUM 安裝軟件
[root@node2 ~]# ansible all -m yum -a 'name=nginx'
EX: setup 收集遠程主機facts,每個被管理幾點在接受並運行管理命令之前,會將自己主機相關信息,如系統版本、IP報告給遠程的ansible主機。
[root@node2 ~]# ansible all -m setup
ansible的YAML介紹
YAML是"YAML Ain't a Markup Language"(YAML不是一種置標語言)的遞歸縮寫。 YAML是一個類似GNU的遞歸式定義。GNU對Unix說“No”,YMAL則是對XML說“No”。而在Ruby的世界裏,YAML可以說是Ruby流動的血液。YAML 之於Ruby,猶如XML之於Java。
YAML的可讀性好。
YAML和腳本語言的交互性好。
YAML使用宿主語言的數據類型。
YAML有一個一致的信息模型。
YAML實例
# MySQL (default setup). Versions 4.1 and 5.0 are recommended. # 此處省略一些註釋。 development: adapter: mysql database: demo_development username: root password: host: localhos
ansible的基礎元素、變量、組嵌套
變量
變量命名:變量名僅能由字母、數字和下劃線組成、且只能以字母開頭
facts 信息被保存在ansible變量中,可以引用使用
register:把任務的輸出定義爲變量,
實例如下
task: shell:/usr/bin/foo register:foo_result ignore_error:True
ansible playbook 介紹
playbooks 是 Ansible的配置,部署,編排語言.他們可以被描述爲一個需要希望遠程主機執行命令的方案,或者一組IT程序運行的命令集合. 如果 Ansible 模塊你是工作室中的工具,那麼 playbooks 就是你設置的方案計劃. 在基礎層面, playbooks 可以被用來管理用於部署到遠程主機的配置文件.在更高的層面上,playbooks 可以依次對多層式架構上的服務器執行上線包括滾動更新在內的操作並可以將操作委託給其他主機包括在此過程中發生的與監視服務器,負載均衡服務器的交互操作在內.
實例
- hosts: webservers vars: http_port: 80 max_clients: 200 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf notify: - restart apache - name: ensure apache is running service: name=httpd state=started handlers: - name: restart apache service: name=httpd state=restarted
ansible playbook 基礎組件
Inventor
Modules
Ad hot commands
Playbooks
Tasks:任務,及調傭模塊完成基礎操作
variables:變量
tempalates:模板
handlers:處理器。由某事件觸發執行的操作
roles:角色
主機與用戶
playbook 中的每一個 play,個別地選擇操作的目標機器是哪些,以哪個用戶身份去完成要執行的步驟。hosts 行的內容是一個或多個組或主機的 patterns,以逗號爲分隔符,
實例:
- hosts: webservers remote_user: root
Tasks 任務列表
每一個 play 包含了一個 task 列表(任務列表).一個 task 在其所對應的所有主機上(通過 host pattern 匹配的所有主機)執行完畢之後,下一個 task 纔會執行.有一點需要明白的是(很重要),在一個 play 之中,所有 hosts 會獲取相同的任務指令,這是 play 的一個目的所在,也就是將一組選出的 hosts 映射到 task
每個 task 的目標在於執行一個 moudle, 通常是帶有特定的參數來執行.在參數中可以使用變量(variables).
每個task都應該有name,用於playboo的執行結果輸出,建議其內容儘可能詳細描述任務步驟。如果未提供name,測action 的結果將用於輸出
modules 具有”冪等”性,意思是如果你再一次地執行 moudle(譯者注:比如遇到遠端系統被意外改動,需要恢復原狀),moudle 只會執行必要的改動,只會改變需要改變的地方.所以重複多次執行 playbook 也很安全.
對於 command module 和 shell module,重複執行 playbook,實際上是重複運行同樣的命令.如果執行的命令類似於 ‘chmod’ 或者 ‘setsebool’ 這種命令,這沒有任何問題.也可以使用一個叫做 ‘creates’ 的 flag 使得這兩個 module 變得具有”冪等”特性
下面是一種基本的 task 的定義,service moudle 使用 key=value 格式的參數,這也是大多數 module 使用的參數格式:
tasks: - name: make sure apache is running service: name=httpd state=running
比較特別的兩個 modudle 是 command 和 shell ,它們不使用 key=value 格式的參數,而是這樣
tasks: - name: disable selinux command: /sbin/setenforce 0
EX:
- hosts: webserver remote_user: root tasks: - name: create nginx group group: name=nginx system=yes gid=208 - name: create nginx user user: name=nginx uid=208 group=nginx system=yes - hosts: dbserver remote_user: root tasks: - name: copy file to dbserver copy: src=/etc/inittab dest=/tmp/initab.ans
handlers
用於當關注的資源發生變化時採取一定的操作。'notify'這個action可用於在每個play的最後被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之僅在所有的變化發生完成後一次性地執行操作。在‘notify’中列出的操作稱之爲handler。
EX: 步驟1,寫一個playbook 要求如下
自動部署一個httpd服務
提供一個特殊的配置文件端口監聽8080
開機自動啓動
- hosts: webserver remote_user: root tasks: - name: install httpd package yum: name=httpd state=latest - name: install congfiguration file for httpd copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: start httpd service service: enabled=true name=httpd state=started
步驟2 修改配置文件端口監聽爲80。重新執行playbook查看端口是否被修改!
- hosts: webserver remote_user: root tasks: - name: install httpd package yum: name=httpd state=latest - name: install congfiguration file for httpd copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name=httpd state=started handlers: - name: restart httpd service: name=httpd state=restarted
playbooks 變量的使用
自定變量引用
調用ansible系統變量
調用Inventor 定義的變量
EX1:自定變量引用
- hosts: webserver remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd package yum: name={{ package }} state=latest - name: install congfiguration file for httpd copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name=httpd state=restarted
EX2:調用ansible系統變量
系統變量查看
[root@node2 conf]# ansible all -m setup
調用ansible系統變量ansibleallipv4_addresses'
- hosts: webserver remote_user: root tasks: - name: copy file copy: content="{{ ansible_all_ipv4_addresses }}" dest=/tmp/ip.ans
EX3:調用Inventor 定義的變量
# Ex 1: Ungrouped hosts, specify before any group headers. [webserver] 192.168.0.101 testvar='0.101' ansible_ssh_user=root ansible_ssh_pass=redhat 192.168.0.102 testvar='0.102' [dbserver] 192.168.0.102 [root@node2 playboos]# cat vars.yml - hosts: webserver remote_user: root tasks: - name: copy file copy: content="{{ ansible_all_ipv4_addresses }}, {{ testvar }}" dest=/tmp/ip.ans
ansible之條件測試
when語句:在task後添加when子句即可使用條件測試。
EX:
tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian"
EX:2
[root@node2 playboos]# cat cond.yml - hosts: all remote_user: root vars: - username: major tasks: - name: create {{ username }} user user: name={{ username }} when: ansible_fqdn == "node3.huizhuang.com"
迭代語句 當有需要重複性執行的任務時,可以使用迭代機制。 其使用格式爲將需要迭代的內容定義爲item變量引用,並通過with_items 語句來指明迭代的元素列表即可。
EX:爲了保持簡潔,重複的任務可以用以下簡寫的方式。
` item ` 爲固定變量名
- name: add several users user: name={{ item }} state=present groups=wheel with_items: - testuser1 - testuser2
以上寫法與下面是完全等同的
- name: add user testuser1 user: name=testuser1 state=present groups=wheel - name: add user testuser2 user: name=testuser2 state=present groups=wheel
請note使用 ‘with_items’ 用於迭代的條目類型不僅僅支持簡單的字符串列表.如果你有一個哈希列表,那麼你可以用以下方式來引用子項:
- name: add several users user: name={{ item.name }} state=present groups={{ item.groups }} with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' }
ansible之tempalates 使用
要求爲webserver兩臺主機安裝httpd 服務要求如下 - 監聽端口80 - 0.101主機maxclient 值爲100 - 0.102主機maxclient 值爲200 - ServerName 爲各自主機名 定義 httpd template 模板文件httpd.conf.j2
MaxClients {{ maxclient }} Listen {{ http_port }} ServerName {{ ansible_fqdn}}:80
在Inventor hosts文件定義變量值
[root@node2 templates]# cat /etc/ansible/hosts [webserver] 192.168.0.101 http_port=80 maxclient=100 192.168.0.102 http_port=80 maxclient=200
在http.yml 引用模板變量
- hosts: webserver remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd package yum: name={{ package }} state=latest - name: install congfiguration file for httpd template: src=/root/playboos/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name=httpd state=restarted
ansible標籤 tags
如果你有一個大型的 playbook,那能夠只運行其中特定部分的配置而無需運行整個 playbook 將會很有用.
[root@node2 playboos]# cat httpd.yml - hosts: webserver remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd package yum: name={{ package }} state=latest - name: install congfiguration file for httpd template: src=/root/playboos/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf tags: - conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name=httpd state=restarted
如果你只想運行一個非常大的 playbook 中的 “conf” 你可以這樣做:
# ansible-playbook httpd.yml --tags='conf'
另一方面,如果你只想執行 playbook 中某個特定任務 之外 的所有任務,你可以這樣做:
# ansible-playbook httpd.yml --skip-tags='conf'
ansible之role運用
創建role的步驟
創建以roles命名的目錄
在roles目錄中分別創建以各個角色名稱的目錄,如webserver
在每個角色命名的目錄中分別創建files、handlers]meta、tasks、templates、vars目錄;用不到的目錄可以創建,也可以不創建。
在playbook文件中,調用各角色;
創建目錄樹
[root@node2 ~]# mkdir -pv /root/ansible_playbooks/roles/{webservs,dbservs}/{tasks,files,templates,meta,handlers,vars}
tree /root/ansible_playbooks/ roles/ ├── dbservs │ ├── files │ ├── handlers │ ├── meta │ ├── tasks │ ├── templates │ └── vars ├── site.yml └── webservs ├── files │ └── httpd.conf ├── handlers │ └── main.yml ├── meta ├── tasks │ └── main.yml ├── templates └── vars
複製httpd配置文件到files目錄
cp /etc/httpd/conf/httpd.conf files/
定義webservs tasks/main.yml
注意copy src 使用相對路徑
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/webservs/tasks/main.yml - name: install httpd package yum: name=httpd - name: install configureation file copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf tags: - conf notify: - restart httpd - name: start httpd service: name=httpd state=started定義webservs handlers/main.yml
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/webservs/handlers/main.yml - name: restart httpd service: name=httpd state=restarted
複製mysql配置文件到files目錄
[root@node2 roles]# cp /etc/my.cnf /root/ansible_playbooks/roles/dbservs/files/
定義dbservs tasks/main.yml
[root@node2 roles]# cat dbservs/tasks/main.yml - name: install mysql-server package yum: name=mysql-server state=latest - name: install configuration file copy: src=my.cnf dest=/etc/my.cnf tags: - myconf notify: - restart mysqld - name: start mysqld service service: name=mysqld enabled=true state=started
定義dbservs handlers/main.yml
- name: restart mysqld service: name=mysqld state=restarted
定義主機 site.yml
注意角色名等於roles目錄下目錄名
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/site.yml - hosts: 192.168.0.101 remote_user: root roles: - webservs - hosts: 192.168.0.102 remote_user: root roles: - dbservs