ansible 系列教程

ansible 核心組件介紹

Architecture Diagram

  • ansible core

  • host iventory

  • core modules

  • custom modules

  • playbook (yaml)

  • connetc plugin XKdbuDf.jpg

ansibles 的特性

  • 基於python語言實現,有paramiko,Pyyaml和jinjia2 三個關鍵模塊

  • 部署簡單,agegtlees,默認使用SSH協議

  1. 基於密鑰認證

  2. 在inventory 文件中指定賬號和密碼

支持playbook基於”模塊“完成各種任務

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的步驟

  1. 創建以roles命名的目錄

  2. 在roles目錄中分別創建以各個角色名稱的目錄,如webserver

  3. 在每個角色命名的目錄中分別創建files、handlers]meta、tasks、templates、vars目錄;用不到的目錄可以創建,也可以不創建。

  4. 在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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章