一、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的模組
Templatetags
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