Ansible Playbook

hx_ky36發表於2024-06-27

一、Host Inventory(主機清單)

Inventory支援對主機進行分組每個組內可以定義多個主機,每個主機都可以定義在任何一個或多個主機組內。

inventory 檔案

預設路徑為/etc/ansible/hosts

Ansible Inventory 檔案是一個純文字檔案,用於定義 Ansible 執行命令的目標主機和組,以及這些主機和組的變數和屬性

Inventory 檔案的構成包括:

1.主機與組

  • 主機:一個主機就是目標機器,可以是 IP 地址、域名或在 SSH 配置中定義的別名,也可以使用 ansible_host 指定。

  • 組:可以將多個主機劃分到同一個組中,並可以對組進行操作。

[WebServer]
192.168.1.10
192.168.1.11
192.168.1.12

[DatabaseServer]
192.168.1.20
192.168.1.21

2.變數

  • 主機變數:為單個主機指定變數,使用主機名或 IP 地址作為識別符號,變數可以設定為一個或多個值。

[ServerA]
192.168.1.10 http_port=80 https_port=443

[ServerB]
serverb.example.com ansible_user=admin ansible_password=1234
  • 組變數:在組名之後,使用 vars 關鍵字設定變數,可以在組間共享變數。示例:
#所有主機指定 `ansible_ssh_user` 變數,這意味著每個主機都具有該變數。
#為每個主機定義唯一的 `name` 變數。
[WebServer]
192.168.1.10 name=webserver1
192.168.1.11 name=webserver2
192.168.1.12 name=webserver3

[DatabaseServer]
192.168.1.20 name=dbserver1
192.168.1.21 name=dbserver2

[all:vars]
ansible_ssh_user=centos

3.組的巢狀

將一個組巢狀到另一個組中,在 Inventory 檔案中使用 :children 關鍵字。

[WebServer]
192.168.1.10
192.168.1.11
192.168.1.12

[DatabaseServer]
192.168.1.20

[Production:children]
WebServer
DatabaseServer

4.別名

使用 Alias(別名)來引用 Inventory 中的主機。

#為 `WebServer` 和 `DatabaseServer` 組定義別名,並將它們作為兩個分離的組 `Web` 和 `Db` 的成員
#建立了一個名為 `Production` 的組,該組由這兩個組的別名組成。
[WebServer]
192.168.1.10
192.168.1.11
192.168.1.12

[DatabaseServer]
192.168.1.20

[Web:children]
WebServer

[Db:children]
DatabaseServer

[Production]
@Web
@Db

inventory 中的變數

hosts 檔案中為主機或組定義變數,在 playbook 中可以直接呼叫變數。

Inventory變數名含義
ansible_host ansible連線節點時的IP地址
ansible_port 連線對方的埠號,ssh連線時預設為22
ansible_user 連線對方主機時使用的使用者名稱。不指定時,將使用執行ansible或ansible-playbook命令的使用者
ansible_password 連線時的使用者的ssh密碼,僅在未使用金鑰對驗證的情況下有效
ansible_ssh_private_key_file 指定金鑰認證ssh連線時的私鑰檔案
ansible_ssh_common_args 提供給ssh、sftp、scp命令的額外引數
ansible_become 允許進行許可權提升
ansible_become_method 指定提升許可權的方式,例如可使用sudo/su/runas等方式
ansible_become_user 提升為哪個使用者的許可權,預設提升為root
ansible_become_password 提升為指定使用者許可權時的密碼

二、Playbook 劇本

1.Playbook的組成部分

1)Tasks:任務,即透過 task 呼叫 ansible 的模板將多個操作組織在一個 playbook 中執行;

2)Variables:變數;

3)Templates:模板;

4)Handlers:處理器,當changed狀態條件滿足時,(notify)觸發執行的操作;

5)Roles:角色。

2.編寫Playbook

基本格式

  • 在單一檔案第一行,用連續三個連字號“-” 開始,還有選擇性的連續三個點號( … )用來表示檔案的結尾;
  • 次行開始正常寫Playbook的內容,一般建議寫明該Playbook的功能;
  • 使用#號註釋程式碼;
  • 縮排必須是統一的,不能空格和tab混用;
  • 縮排的級別也必須是一致的,同樣的縮排代表同樣的級別,程式判別配置的級別是透過縮排結合換行來實現的;
  • YAML檔案內容是區別大小寫的,key/value的值均需大小寫敏感;
  • 多個key/value可同行寫也可換行寫,同行使用,分隔;
  • v可是個字串,也可是另一個列表;
  • 一個完整的程式碼塊功能需最少元素需包括 name 和 task;
  • 一個name只能包括一個task;
  • YAML副檔名通常為yml或yaml
xxx.yaml/xxx.yml
--- #表示開始
- name:  #指定play的名稱
  hosts: #指定主機清單中定義的主機組名
  remote_user: #指定遠端主機的執行使用者
  grather_facts: ture|fales #指定是否要收集遠端主機的facts資訊
  vars:   #自定義變數,只能在當前play有效
    - 變數1: 值1  #格式為key: value
    - 變數2: 值2
  tasks: #定義任務列表,預設從上往下依次執行
    - name: #定義任務的名稱
      模組名: 模組引數        
      ignore errors: true  #忽略任務的失敗
    - name: #可以定義多個任務
      模組名: 模組引數  
      notify: 任務名  #如以上操作後為changed的狀態時,會透過notify指定的名稱觸發對應名稱的handlers操作
      ##條件判斷##
     - name:
       模組名: 模組引數
       when: #定義條件表示式(== != > < >= <=),條件成立時執行此task任務,否則不執行任務
       ##迴圈##
     - name:
       模組名: 模組引數={{item}}
       with_items: #定義迴圈列表
     ##tags模組,標籤## 
     - name: 
       模組名: 模組引數 
       tags:
       - 標籤1
       - 標籤2
        
  handlers: 
    - name: 任務名  #和notify中的任務名相同
      模組名: 模組引數

#無註釋版
---
- name: 
  hosts: 
  remote_user:
  grather_facts: ture|fales 
  vars:
    - 變數1: 值1
    - 變數2: 值2
  tasks:
    - name:
      模組名: 模組引數        
      ignore errors: true
    - name:
      模組名:
      notify: 任務名
     - name:
       模組名:
       when:
     - name:
       模組名: 模組引數={{item}}
       with_items:
  handlers: 
    - name: 任務名
      模組名: 模組引數

語句的橫向/縱向寫法

橫向寫法一般是陣列型別

縱向寫法一般是列表型別

task任務的模組語法格式
橫向格式:
模組名: 引數1=值 引數2={{變數名}} ...

縱向格式:
模組名:
  引數1: 值
  引數2: "{{變數名}}"
  ...
  
with_items 和 vars 的語法格式
橫向格式:
with_items: ["值1", "值2", "值3", ...]

值為物件(鍵值對欄位)時:
with_items:
- {key1: "值1", key2: "值2"}
- {key1: "值3", key2: "值4"}
...

縱向格式:
with_items:
- 值1
- 值2
- 值3
...

值為物件(鍵值對欄位)時:
with_items:
- key1: "值1"
  key2: "值2"
- key1: "值3"
  key2: "值4"
...

三、Playbook例項

1.編寫yum安裝nginx的playbook

#編寫yaml檔案,安裝nginx的劇本
vim test.yaml

---
 - name: first play
   hosts: dbservers
   remote_user: root
   gather_facts: false
   tasks:
     - name: firewalld
       service: name=firewalld state=stopped enabled=no
     - name: selinux
       command: '/usr/sbin/setenforce 0 '
       ignore_errors: true
     - name: mount
       mount: src=/dev/sr0 path=/mnt state=mounted fstype=iso9660
     - name: local.repo
       copy: src=/etc/yum.repos.d/local.repo dest=/etc/yum.repos.d/
     - name: epel.repo
       copy: src=/etc/yum.repos.d/epel.repo dest=/etc/yum.repos.d/
     - name: nginx install
       yum: name=nginx state=latest
     - name: configuration file
       copy: src=/usr/local/nginx/conf/nginx.conf dest=/etc/nginx/nginx.conf
       notify: "reload nginx"
     - name: start nginx
       service: name=nginx state=started enabled=yes
   handlers:
     - name: reload nginx
       service: name=nginx state=reloaded

2.引數補充

#執行playbook
ansible-playbook xx.yaml/yml [引數]
常用引數描述
--syntax-check 檢查yaml檔案的語法是否正確
--list-task 檢查tasks任務
--list-hosts 檢查生效的主機
--start-at-task=' name ' 指定從某個task開始執行 一般用於劇本較長且不想從頭重複執行的場景
-k 用來互動輸入ssh密碼 -ask-pass
-K 用來互動輸入sudo密碼 -ask-become-pass
-u 指定使用者

3.變數的定義和引用

  vars:   #自定義變數,只能在當前play有效
    - 變數1: 值1  #格式為key: value
    - 變數2: 值2
  tasks:  #在任務列表中引用變數
    -name:
     module: {{變數1}}

方式一:在yaml檔案中定義和引用

vim test2.yml

---
 - name: second play
   hosts: dbservers
   remote_user: root
   gather_facts: true
   vars: 
     - groupname: mysql 
     - username: nginx
   tasks:
     - name: create group
       group: name={{groupname}} system=yes gid=306    #使用 {{key}} 引用變數的值
     - name: create user
       user: name={{username}} uid=306 group={{groupname}} 
     - name: copy file
       copy: content="{{ansible_default_ipv4.network}}" dest=/opt/vars.txt    #在setup模組中可以獲取facts變數資訊
       
#ansible_default_ipv4為facts變數資訊中的欄位
#ansible_default_ipv4.network中的 .network表示只提取資訊中network部分
ansible-play test2.yml

方式二:在命令列定義

ansible-playbook test1.yaml -e "username=nginx"
#透過 -e 引數傳遞一個額外的變數 "username=nginx" 給 playbook
#playbook 將會使用變數 "username" 的值設定為 "nginx"

4.指定遠端主機sudo切換使用者

使用-k-K 引數實現。

編寫劇本

vim test2.yaml

---
- hosts: webservers
  remote_user: test2            
  become: yes                     #2.6版本以後的引數,之前是sudo,意思為切換使用者執行
  become_user: root              #指定sudo使用者為root
  tasks: 
    - name: ts
      command: ls ./

執行劇本

#執行playbook,加上引數-k和-K
ansible-playbook test2.yml -k -K 

5.when條件判斷

用法

在Ansible中,提供的唯一一個通用的條件判斷when指令

當when指令的值為true時,則該任務執行否則不執行該任務。

When指令一個比較常見的應用場景是實現跳過某個主機不執行任務 或者 只有滿足條件的主機執行任務。

編寫劇本,使用條件判斷語句

#如果條件判斷成功,則對應主機關機
vim test3.yaml

---
- hosts: all
  remote_user: root
  tasks:
   - name: poweroff host 
     command: /usr/sbin/poweroff -r now
     when: ansible_default_ipv4.address == "192.168.2.102"      
     #when指令中的變數名不需要手動加上 {{}}
或 
     when: inventory_hostname == "<主機名>"

執行劇本

#執行劇本
ansible-playbook test3.yaml

6.迭代(迴圈結構)

Ansible提供了很多種迴圈結構,一般都命名為with_items,作用等同於 loop 迴圈

vim test4.yaml
---
- name: play1
  hosts: dbservers
  gather_facts: false
  tasks: 
    - name: create file
      file:
        path: "{{item}}"
        state: touch
      with_items: [ /opt/a, /opt/b, /opt/c, /opt/d ]


- name: play2
  hosts: dbservers
  gather_facts: false        
  vars:
    test:
    - /tmp/test1
    - /tmp/test2
    - /tmp/test3
    - /tmp/test4
  tasks: 
    - name: create directories
      file:
        path: "{{item}}"
        state: directory
      with_items: "{{test}}"
        
- name: play3
  hosts: dbservers
  gather_facts: false
  tasks:
    - name: add users
      user: name={{item.name}} state=present groups={{item.groups}}
      with_items:
        - name: test1
          groups: wheel
        - name: test2
          groups: root
或
      with_items:
        - {name: 'test1', groups: 'wheel'}
        - {name: 'test2', goups: 'root'}


ansible-playbook test3.yaml

四、Playbook的模組

Template
tags
Roles

1.Template配置模板模組

用於生成配置模板檔案,配合hosts中定義的變數,或者劇本中定義的變數,為不同主機生成不同的配置引數。

Jinja是基於Python的模板引擎。

Template類是Jinja的一個重要元件,可以看作是一個編譯過的模板檔案,用來產生目標文字,傳遞Python的變數給模板去替換模板中的標記。

怎麼使用

1)先準備一個xxx.j2配置模板檔案,在檔案中使用{{變數名}} 引用主機變數或者vars欄位自定義的變數 以及 facts資訊欄位做變數的值;

2)在playbook劇本中的task任務定義template模組配置。

template: src--xxx.j2 檔案路徑 dest-遠端主機檔案路徑

例項

1)先準備一個以 .j2 為字尾的 template 模板檔案,設定引用的變數

mkdir /etc/ansible/playbook
cp /etc/nginx/nginx.conf /etc/ansible/playbook/nginx.conf.j2

2)修改主機清單檔案,使用主機變數定義一個變數名相同,而值不同的變數

#在Template 模板中定義的變數

vim /etc/ansible/hosts [webservers] 192.168.100.102 http_port=192.168.100.102:80 server_name=www.test1.com:80 root_dir=/var/www/html 192.168.100.103 http_port=192.168.100.103:80 server_name=www.test2.com:80 root_dir=/var/www/html [dbservers] 192.168.100.106 http_port=192.168.100.103:80 server_name=www.test3.com:80 root_dir=/var/www/html

3)編寫 playbook並執行

#編寫劇本
vim nginx1.yaml
---
- name: new play
  hosts: webservers:dbservers
  remote_user: root
  gather_facts: yes
  tasks:
  - name: disable firewalld
    systemd:
      name: firewalld
      state: stopped
      enabled: no
  - name: disable selinux
    command: '/usr/sbin/setenforce 0'
    ignore_errors: true
  - name: copy local repo file
    copy:
      src: /etc/yum.repos.d/repo.bak/local.repo
      dest: /etc/yum.repos.d/
  - name: mount cdrom
    mount: src=/dev/sr0 path=/mnt state=mounted fstype=iso9660
  - name: install dependent packages
    with_items:
    - gcc
    - gcc-c++
    - make
    - pcre-devel
    - zlib-devel
    - openssl-devel
    yum: name={{item}} state=present
      #name: "gcc,gcc-c++,make,pcre-devel,zlib-devel,openssl-devel"
      #state: present
  - name: unarchive nginx package
    unarchive: copy=yes src=/opt/nginx-1.24.0.tar.gz dest=/opt/
  - name: install nginx
    shell: chdir=/opt/nginx-1.24.0/ ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module && make && make install
  - name: copy nginx config file
    template: src=/etc/ansible/playbook/nginx.conf.j2 dest=/usr/local/nginx/conf/nginx.conf
    notify: "reload nginx"
  - name: copy nginx systemd control script
    copy: src=/etc/ansible/playbook/nginx.service dest=/usr/lib/systemd/system/
  - name: create nginx user
    user: name=nginx shell=/sbin/nologin create_home=no
  - name: start nginx
    service: name=nginx state=started enabled=yes
  - name: create root dir
    file: path={{root_dir}} state=directory
  - name: create index.html for 2.102
    copy: content="this is test1" dest={{root_dir}}/index.html
    when: ansible_default_ipv4.address == "192.168.2.102"
  - name: create index.html for 2.103
    copy: content="this is test2" dest={{root_dir}}/index.html
    when: ansible_default_ipv4.address == "192.168.2.103"
  - name: create index.html for 2.106
    copy: content="this is test3" dest={{root_dir}}/index.html
    when: ansible_default_ipv4.address == "192.168.2.106"
  handlers:
  - name: reload nginx
    service: name=nginx state=reloaded

#執行劇本
ansible-playbook nginx1.yaml

2.tags模組

可以在一個playbook中為某個或某些任務定義“標籤”,在執行此playbook時透過ansible-playbook命令使用–tags選項能實現僅執行指定的tasks。

playbook還提供了一個特殊的tags為always。

作用就是當使用always作為tags的task時,無論執行哪一個tags時,定義有always的tags都會執行。

3.roles模組

Roles用於層次性、結構化地組織playbook,適用於程式碼複用度較高的場景。

roles模組的作用(重要)

將playbook劇本中的各個play視作一個角色,將各個角色的tasks任務vars變數templates模板files檔案等內容放置在指定角色的目錄中統一管理。

需要的時候可以在playbook中使用roles角色直接呼叫,即roles角色可以在playbook中實現程式碼的複用

roles 的目錄結構

cd /etc/ansible/
tree roles/
roles/
├── web/    #相當於 playbook 中的 每一個 play 主題
│   ├── files/
│   ├── templates/
│   ├── tasks/
│   ├── handlers/
│   ├── vars/
│   ├── defaults/
│   └── meta/
└── db/
    ├── files/
    ├── templates/
    ├── tasks/
    ├── handlers/
    ├── vars/
    ├── defaults/
    └── meta/

roles 內各目錄含義解釋

目錄含義
files 用來存放由 copy 模組或 script 模組呼叫的檔案
templates 用來存放 jinjia2 模板,template 模組會自動在此目錄中尋找 jinjia2 模板檔案
tasks 此目錄應當包含一個 main.yml 檔案,用於定義此角色的任務列表,此檔案可以使用 include 包含其它的位於此目錄的 task 檔案
handlers 此目錄應當包含一個 main.yml 檔案,用於定義此角色中觸發條件時執行的動作
vars 此目錄應當包含一個 main.yml 檔案,用於定義此角色用到的變數
defaults

此目錄應當包含一個 main.yml 檔案,用於為當前角色設定預設變數。

這些變數具有所有可用變數中最低的優先順序,並且可以很容易地被任何其他變數覆蓋。所以生產中我們一般不在這裡定義變數

meta 此目錄應當包含一個 main.yml 檔案,用於定義此角色的後設資料資訊及其依賴關係

在一個 playbook 中使用 roles 的步驟

1)建立以 roles 命名的目錄;

#舉個例子
mkdir /etc/ansible/roles/ -p    #yum裝完預設就有

2)建立全域性變數目錄(可選);

#舉個例子
mkdir /etc/ansible/group_vars/ -p
touch /etc/ansible/group_vars/all     #檔名自己定義,引用的時候注意

3)在 roles 目錄中分別建立以各角色名稱命名的目錄,如 httpd、mysql;

#舉個例子
mkdir /etc/ansible/roles/httpd
mkdir /etc/ansible/roles/mysql

4)在每個角色命名的目錄中分別建立files、handlers、tasks、templates、meta、defaults和vars目錄,用不到的目錄可以建立為空目錄,也可以不建立;

#舉個例子
mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta}
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}

5)在每個角色的 handlers、tasks、meta、defaults、vars 目錄下建立 main.yml 檔案,千萬不能自定義檔名

#舉個例子
touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml

6)修改 site.yml 檔案,針對不同主機去呼叫不同的角色;

#舉個例子
vim /etc/ansible/site.yml
---
- hosts: webservers
  remote_user: root
  roles:
     - httpd
- hosts: dbservers
  remote_user: root
  roles:
     - mysql

7)ansible-playbook執行劇本。

#舉個例子
cd /etc/ansible
ansible-playbook site.yml

例項

1) 建立各角色的目錄和main.yaml檔案

mkdir /etc/ansible/roles/httpd/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta} -p
mkdir /etc/ansible/roles/php/{files,templates,tasks,handlers,vars,defaults,meta} -p

touch /etc/ansible/roles/httpd/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml
touch /etc/ansible/roles/php/{defaults,vars,tasks,meta,handlers}/main.yml

2)編寫httpd模組

vim /etc/ansible/roles/mysql/tasks/main.yml
- name: install mysql
  yum: name={{pkg}} state=latest
- name: start mysql
  service: enabled=true name={{svc}} state=started
  
vim /etc/ansible/roles/mysql/vars/main.yml
pkg:
  - mariadb
  - mariadb-server
svc: mariadb

4)編寫php模組

vim /etc/ansible/roles/php/tasks/main.yml
- name: install php
  yum: name={{pkg}} state=latest
- name: start php-fpm
  service: enabled=true name={{svc}} state=started

vim /etc/ansible/roles/php/vars/main.yml
pkg:
  - php
  - php-fpm
svc: php-fpm

5)編寫roles示例

vim /etc/ansible/site.yml
---
- hosts: webservers
  remote_user: root
  roles:
   - httpd
   - mysql
   - php
cd /etc/ansible
ansible-playbook site.yml

相關文章