Ansible篇-ansible-playbook inventory/roles/include用法詳解

1 引言

ansible-playbook有很多巧妙的用法,在這裏總結一下。
ansible中文權威指南:http://www.ansible.com.cn/docs/intro.html

2 yml語法簡介

2.1 ansible劇本使用的是yaml語法

  • 1)所有的 YAML 文件(無論和 Ansible 有沒有關係)開始行都應該是 —. 這是 YAML 格式的一部分, 表明一個文件的開始;
  • 2)對於 Ansible, 每一個 YAML 文件都是從一個列表開始. 列表中的每一項都是一個鍵值對, 通常它們被稱爲一個 “哈希” 或 “字典”. 所以, 我們需要知道如何在 YAML 中編寫列表和字典。一個字典是由一個簡單的 鍵: 值 的形式組成(這個冒號後面必須是一個空格):
---
#一位職工的記錄
name: Example Developer
job: Developer
skill: Elite
  • 3)需要使用引號來包裹任何包含冒號的哈希值
foo: "somebody said I should put a colon here: so I did"
  • 4)Ansible 使用 “{{ var }}” 來引用變量. 如果一個值以 “{” 開頭, YAML 將認爲它是一個字典, 所以我們必須引用它, 像這樣:
foo: "{{ variable }}"

5)把目前所學到的 YAML 例子組合在一起:

---
 - 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

2.2 playbook基礎

  • 主機與用戶

1)可以爲 playbook 中的每一個 play,個別地選擇操作的目標機器是哪些,以哪個用戶身份去完成要執行的步驟
2)hosts 行的內容是一個或多個組或主機的 patterns,以逗號爲分隔符
3)remote_user 就是賬戶名

---
- hosts: webservers
  remote_user: root

4)在每一個 task 中,可以定義自己的遠程用戶

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname

5)也支持從 sudo 執行命令

---
- hosts: webservers
  remote_user: yourname
  sudo: yes

可以僅在一個 task 中,使用 sudo 執行命令,而不是在整個 play 中使用 sudo

---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service: name=nginx state=started
      sudo: yes

也可以登陸後,sudo 到不同的用戶身份,而不是使用 root

---
- hosts: webservers
  remote_user: yourname
  sudo: yes
  sudo_user: postgres
  • Tasks列表

1)每一個 play 包含了一個 task 列表(任務列表).一個 task 在其所對應的所有主機上(通過 host pattern 匹配的所有主機)執行完畢之後,下一個 task 纔會執行.有一點需要明白的是(很重要),在一個 play 之中,所有 hosts 會獲取相同的任務指令,這是 play 的一個目的所在,也就是將一組選出的 hosts 映射到 task.
2)在運行 playbook 時(從上到下執行),如果一個 host 執行 task 失敗,這個 host 將會從整個 playbook 的 rotation 中移除. 如果發生執行失敗的情況,請修正 playbook 中的錯誤,然後重新執行即可.
3)每一個 task 必須有一個名稱 name,這樣在運行 playbook 時,從其輸出的任務執行信息中可以很好的辨別出是屬於哪一個 task 的
4)下面是一種基本的 task 的定義,service moudle 使用 key=value 格式的參數,這也是大多數 module 使用的參數格式

tasks:
  - name: make sure apache is running
    service: name=httpd state=running

5)比較特別的兩個 modudle 是 command 和 shell ,它們不使用 key=value 格式的參數,而是這樣

tasks:
  - name: disable selinux
    command: /sbin/setenforce 0

6)在 action 行中可以使用變量.假設在 ‘vars’ 那裏定義了一個變量 ‘vhost’ ,可以這樣使用它

tasks:
  - name: create a virtual host file for {{ vhost }}
    template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
  • handlers:在發生改變時執行的操作

1)Handlers 也是一些 task 的列表,通過名字來引用,它們和一般的 task 並沒有什麼區別.Handlers 是由通知者進行 notify, 如果沒有被 notify,handlers 不會執行.不管有多少個通知者進行了 notify,等到 play 中的所有 task 執行完成之後,handlers 也只會被執行一次.

#通過notify來觸發handlers
- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache
#預先配置的handlers
handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

2)handlers 會在 ‘pre_tasks’, ‘roles’, ‘tasks’, 和 ‘post_tasks’ 之間自動執行. 如果你想立即執行所有的 handler 命令,在1.2及以後的版本,你可以這樣做:

tasks:
   - shell: some tasks go here
   - meta: flush_handlers
   - shell: some other tasks
  • 執行playbook
#-f的意思是開啓10個併發的進程
ansible-playbook playbook.yml -f 10

3 inventory

https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

  • 例1 同一功能的主機可以寫在同一組
#方括號[ ]中是組名,用於對系統進行分類,便於對不同系統進行個別的管理。
[webservers]
foo.example.com
bar.example.com

[dbservers]
one.example.com
two.example.com
three.example.com
  • 例2 一組相似的 hostname , 可簡寫
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
  • 例 3 假設你有一些靜態IP地址,希望設置一些別名,但不是在系統的 host 文件中設置,又或者你是通過隧道在連接,那麼可以設置如下:
jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50
  • 例 4 對於每一個 host,你還可以選擇連接類型和連接用戶名:
[targets]

localhost              ansible_connection=local
other1.example.com     ansible_connection=ssh        ansible_ssh_user=mpdehaan
other2.example.com     ansible_connection=ssh        ansible_ssh_user=mdehaan
  • 例 5 主機變量——分配變量給主機很容易做到,這些變量定義後可在 playbooks 中使用:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
  • 例 6 也可以定義整個組的變量
[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
  • 例 7 把一個組作爲另一個組的子成員。可以把一個組作爲另一個組的子成員,以及分配變量給整個組使用. 這些變量可以給 /usr/bin/ansible-playbook 使用,但不能給 /usr/bin/ansible 使用:
[atlanta]
host1
host2

[raleigh]
host2
host3

[southeast:children]
atlanta
raleigh

[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2

[usa:children]
southeast
northeast
southwest
northwest
  • 例 8 分文件定義Host和Group變量。在 inventory 主文件中保存所有的變量並不是最佳的方式.還可以保存在獨立的文件中,這些獨立文件與 inventory 文件保持關聯
  • 1)假設有一個主機名爲 ‘foosball’, 主機同時屬於兩個組,一個是 ‘raleigh’, 另一個是 ‘webservers’. 那麼以下配置文件(YAML 格式)中的變量可以爲 ‘foosball’ 主機所用.依次爲 ‘raleigh’ 的組變量,’webservers’ 的組變量,’foosball’ 的主機變量:
/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball

  • 2)還可以爲一個主機,或一個組,創建一個目錄,目錄名就是主機名或組名.目錄中的可以創建多個文件, 文件中的變量都會被讀取爲主機或組的變量.如下 ‘raleigh’ 組對應於 /etc/ansible/group_vars/raleigh/ 目錄,其下有兩個文件 db_settings 和 cluster_settings, 其中分別設置不同的變量:
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
  • inventory參數說明
ansible_ssh_host
      將要連接的遠程主機名.與你想要設定的主機的別名不同的話,可通過此變量設置.

ansible_ssh_port
      ssh端口號.如果不是默認的端口號,通過此變量設置.

ansible_ssh_user
      默認的 ssh 用戶名

ansible_ssh_pass
      ssh 密碼(這種方式並不安全,我們強烈建議使用 --ask-pass 或 SSH 密鑰)

ansible_sudo_pass
      sudo 密碼(這種方式並不安全,我們強烈建議使用 --ask-sudo-pass)

ansible_sudo_exe (new in version 1.8)
      sudo 命令路徑(適用於1.8及以上版本)

ansible_connection
      與主機的連接類型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默認使用 paramiko.1.2 以後默認使用 'smart','smart' 方式會根據是否支持 ControlPersist, 來判斷'ssh' 方式是否可行.

ansible_ssh_private_key_file
      ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的情況.

ansible_shell_type
      目標系統的shell類型.默認情況下,命令的執行使用 'sh' 語法,可設置爲 'csh' 或 'fish'.

ansible_python_interpreter
      目標主機的 python 路徑.適用於的情況: 系統中有多個 Python, 或者命令路徑不是"/usr/bin/python",比如  \*BSD, 或者 /usr/bin/python
      不是 2.X 版本的 Python.我們不使用 "/usr/bin/env" 機制,因爲這要求遠程用戶的路徑設置正確,且要求 "python" 可執行程序名不可爲 python以外的名字(實際有可能名爲python26).

      與 ansible_python_interpreter 的工作方式相同,可設定如 ruby 或 perl 的路徑....

4 roles和include

4.1 include

  • 在多個 play 或者多個 playbook 中重用同一個 task 列表,可以使用 include files 做到這一點。
tasks:
  - include: tasks/foo.yml

//或者還可以給include傳遞變量,即參數化的 include
tasks:
  - include: wordpress.yml wp_user=timmy
  - include: wordpress.yml wp_user=alice
  - include: wordpress.yml wp_user=bob
 
//1.0版之後支持結構化的變量
tasks:
  - include: wordpress.yml
    vars:
        wp_user: timmy
        some_list_variable:
          - alpha
          - beta
          - gamma

  • 也可用來將一個 playbook 文件導入另一個 playbook 文件
- name: this is a play at the top level of a file
  hosts: all
  remote_user: root

  tasks:

  - name: say hi
    tags: foo
    shell: echo "hi..."

- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml

4.2 roles

roles是組織 playbook的最好的方式!Roles 基於一個已知的文件結構,去自動的加載某些 vars_files,tasks 以及 handlers。基於 roles 對內容進行分組,使得我們可以容易地與其他用戶分享 roles 。

  • 項目的結構舉例如下,(當然,也可以不按照這種結構對playbook進行管理,但是極力推薦使用這種方式)
site.yml
webservers.yml
fooservers.yml
roles/
   common/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/
   webservers/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/

該項目結構對應的一個playbook可能是這樣的:

---
- hosts: webservers
  roles:
     - common
     - webservers

這個 playbook 爲一個角色 ‘x’ 指定了如下的行爲:
如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 將被添加到 play 中
如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 將被添加到 play 中
如果 roles/x/vars/main.yml 存在, 其中列出的 variables 將被添加到 play 中
如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依賴” 將被添加到 roles 列表中 (1.3 and later)
所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路徑。
所有 script tasks 可以引用 roles/x/files/ 中的腳本,不需要指明文件的路徑。
所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路徑。
所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路徑。

  • 也可以使用參數化的 roles,這種方式通過添加變量來實現,比如:
---
- hosts: webservers
  roles:
    - common
    - { role: foo_app_instance, dir: '/opt/a',  port: 5000 }
    - { role: foo_app_instance, dir: '/opt/b',  port: 5001 }
  • 當一些事情不需要頻繁去做時,你也可以爲 roles 設置觸發條件,像這樣:
---

- hosts: webservers
  roles:
    - { role: some_role, when: "ansible_os_family == 'RedHat'" }
  • 如果你希望定義一些 tasks,讓它們在 roles 之前以及之後執行,你可以這樣做:
---

- hosts: webservers

  pre_tasks:
    - shell: echo 'hello'

  roles:
    - { role: some_role }

  tasks:
    - shell: echo 'still busy'

  post_tasks:
    - shell: echo 'goodbye'
  • 角色默認變量:要創建默認變量,只需在 roles 目錄下添加 defaults/main.yml 文件。這些變量在所有可用變量中擁有最低優先級,可能被其他地方定義的變量(包括 inventory 中的變量)所覆蓋。
  • 角色依賴:你可以自動地將其他 roles 拉取到現在使用的 role 中。”角色依賴” 保存在 roles 目錄下的 meta/main.yml 文件中。這個文件應包含一列 roles 和 爲之指定的參數,下面是在 roles/myapp/meta/main.yml 文件中的示例:
---
dependencies:
  - { role: common, some_parameter: 3 }
  - { role: apache, port: 80 }
  - { role: postgres, dbname: blarg, other_parameter: 12 }

5 變量的優先級

  • extra vars (在命令行中使用 -e)優先級最高
  • 然後是在inventory中定義的連接變量(比如ansible_ssh_user)
  • 接着是大多數的其它變量(命令行轉換,play中的變量,included的變量,role中的變量等)
  • 然後是在inventory定義的其它變量
  • 然後是由系統發現的facts
  • 然後是 “role默認變量”, 這個是最默認的值,很容易喪失優先權
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章