做品牌網(wǎng)站哪個好用北大青鳥職業(yè)技術(shù)學(xué)院簡介
17.RedHat認證-Ansible自動化運維(下)
這個章節(jié)講ansible的變量,包括變量的定義、變量的規(guī)則、變量范圍、變量優(yōu)先級、變量練習(xí)等。
以及對于tasks的控制,主要有l(wèi)oop循環(huán)作業(yè)、條件判斷等
變量
介紹
Ansible支持變量功能,能將value存儲到變量中,這樣就能在Ansible項目中重復(fù)使用,這樣就可以簡化項目的創(chuàng)建和維護,減少錯誤率。
變量提供了一個變量提供了一種方便的方法來管理ansible項目中給定環(huán)境的動態(tài)值。 變量可以是要創(chuàng)建的用戶,要安裝的包,要啟動的服務(wù),要刪除的文件,要從互聯(lián)網(wǎng)下載的文件等等
規(guī)則
變量由必須以字母開頭的字符串組成,并且只能包含字母,數(shù)字和下劃線組成。
無效變量 | 有效變量 |
---|---|
web server | web_server |
remote.file | remote_file |
1st file | file_1或file1 |
remoteserver$1 | remote_server_1或remote_server1 |
定義變量
變量幾乎可以定義在ansible項目中的任意位置。然而這有三種基本的范圍級別:
1.Globe scope:從命令行設(shè)置變量或Ansible配置文件中設(shè)置變量
2.play scope: 在play和相關(guān)結(jié)構(gòu)中設(shè)置變量
3.host scope: 通過inventory在主機組或單個主機中設(shè)置變量,fact采集變量或者register
如果在一個級別上定義了名字相同的兩個變量,會選擇先定義的那個。 在inventory中定義的變量會被
playbook中定義的覆蓋,playbook中定義的變量會被命令行定義的變量覆蓋。
http://docs.ansible.com/ansible/playbooks_variables.html 變量說明詳細文檔
playbook中定義變量
當寫playbook時,管理員可以在task中使用它們自己定義的變量。例如一個叫做web_package的變量可以
被被定義為httpd,然后使用yum模塊來調(diào)用這個變量,進而安裝httpd包
聲明定義
playbook變量可以通過多種方式進行定義。一個最簡單的方式就是在playbook的開頭通過vars定義,例如
文件定義
也可以在playbook中通過指定外部文件作為變量文件
主機變量和組變量
inventory變量直接應(yīng)用到被管理主機有兩種方式:
1.應(yīng)用到特定主機
2.應(yīng)用到特定組
主機變量優(yōu)先級高于組變量,但是在playbook中定義的主機變量優(yōu)于這兩種方式
變量定義
這種定義變量的方式讓inventory的管理更復(fù)雜了。因為在同一個文件中包含了主機和變量,并且使用了不同的語法。
將變量的定義放在一個文件中,例如放在當前的目錄下的var目錄下的vars.yml
[student@workstation playbook-review]$ vim test.yml
- name: this is a var testhosts: allvars_files:- var/vars.yml # 相對路徑,推薦寫相對路徑tasks:- name: debug module testdebug:msg: "{{ user }} is very handsome ,but {{ user }} is very pool"# 在var目錄下定義了user變量
[student@workstation playbook-review]$ cd var/
[student@workstation var]$ cat vars.yml user: ztf# 執(zhí)行playbook
[student@workstation playbook-review]$ ansible-playbook test.yml
上面這種定義變量的方式讓inventory的管理更復(fù)雜了。因為在同一個文件中包含了主機和變量,并且使用了不同的語法。
使用group_vars和host_vars目錄
其實大多數(shù)生產(chǎn)環(huán)境里,盡最大可能將變量和inventory文件以及playbook文件分開來寫,看著清爽。
不要混在一起,非常不利于維護和閱讀
使用這兩個目錄就可以解決上面的問題,解耦文件,生產(chǎn)環(huán)境中用的多。
很簡單,在你的playbook目錄下創(chuàng)建兩個這樣的目錄,分別是 group_vars和host_vars目錄
記住,文件名強制必須一樣,不能改變。
然后就很簡單了,如果你是針對主機組設(shè)置變量,就在group_vars目錄下創(chuàng)建一個主機組名稱相同的文件。
舉個例子,假設(shè)你的inventory文件里有一個主機組 production,里面有兩個主機 servera serverb
[production]
servera
serverb
然后你就在group_vars目錄下創(chuàng)建同名的主機組的文件 就叫 production,然后在這個文件里定義的變量都會應(yīng)用在這個production主機組里
其次,如果你是針對主機設(shè)置變量,就在host_vars目錄下創(chuàng)建一個主機名稱相同的文件。方法如上。
練習(xí)playbook變量
[kiosk@foundation0 ~]$ ssh workstation[student@workstation ~]$ lab data-variables start[student@workstation ~]$ cd data-variables/[student@workstation data-variables]$ cat inventory
[webserver]
servera.lab.example.com[student@workstation data-variables]$ cat ansible.cfg
[defaults]
inventory = inventory
remote_user = devops[privilege_escalation]
become = true# 創(chuàng)建playbook
[student@workstation data-variables]$ vim playbook.yml
[student@workstation data-variables]$ cat playbook.yml
--------------------------- 內(nèi)容如下 ----------------------------------------------------------
---
- name: Deploy and start Apache HTTPD servicehosts: webservervars:web_pkg: httpdfirewall_pkg: firewalldweb_service: httpdfirewall_service: firewalldpython_pkg: python3-PyMySQLrule: httptasks:- name: Required packages are installed and up to dateyum:name:- "{{ web_pkg }}"- "{{ firewall_pkg }}"- "{{ python_pkg }}"state: latest- name: The {{ firewall_service }} service is started and enabledservice:name: "{{ firewall_service }}"enabled: truestate: started- name: The {{ web_service }} service is started and enabledservice:name: "{{ web_service }}"enabled: truestate: started- name: Web content is in placecopy:content: "Example web content"dest: /var/www/html/index.html- name: The firewall port for {{ rule }} is openfirewalld:service: "{{ rule }}"permanent: trueimmediate: truestate: enabled- name: second play Verify the Apache servicehosts: localhostbecome: falsetasks:- name: Ensure the webserver is reachableuri:url: http://servera.lab.example.comstatus_code: 200
-------------------------------------------------------------------------------------
# 運行playbook,結(jié)果正確
[student@workstation data-variables]$ ansible-playbook playbook.yml------------------------------ 【警戒線】 -------------------------------#【注意】在這個例子中,定義的變量是在playbook文件里,我們運用之前所學(xué)知識,將變量定義在外部的單獨文件里。
[student@workstation data-variables]$ mkdir variables
[student@workstation data-variables]$ cd variables/
[student@workstation variables]$ vim web.yml
-------------------------------------------------------
web_pkg: httpd
firewall_pkg: firewalld
web_service: httpd
firewall_service: firewalld
python_pkg: python3-PyMySQL
rule: http
-------------------------------------------------------
# 修改playbook.yml
[student@workstation data-variables]$ vim playbook.yml vars_files:- variables/web.yml# 運行效果正確。
[student@workstation data-variables]$ ansible-playbook playbook.yml ------------------------------ 【警戒線】 -------------------------------
# 再運用group_vars和host_vars的知識再來修改
# 這里的inventroy文件里只有主機組,那么我們創(chuàng)建一個group_vars[student@workstation data-variables]$ mkdir group_vars
[student@workstation data-variables]$ cd group_vars/
[student@workstation group_vars]$ vim webserver
[student@workstation group_vars]$ cd ..
[student@workstation data-variables]$ vim playbook.yml
# 這一步修改playbook.yml文件,就是去掉 vars_files:- variables/web.yml 這個變量文件這兩行。# 然后再執(zhí)行,執(zhí)行效果正確。
[student@workstation data-variables]$ ansible-playbook playbook.yml # 練習(xí)完還原環(huán)境即可
[student@workstation data-variables]$ lab data-variables finish
加密敏感數(shù)據(jù)
通過 vault 來加密一些敏感數(shù)據(jù),例如密碼,令牌等
[student@workstation playbook-review]$ cd var
[student@workstation var]$ ls
vars.yml
[student@workstation var]$ ansible-vault create test.yml # 創(chuàng)建加密文件
New Vault password:
Confirm New Vault password: # 查看加密文件內(nèi)容(如果你直接使用cat去查看,就是一堆加密的字母)
[student@workstation var]$ ansible-vault view test.yml
Vault password:
user: ztf# 編輯加密文件
[student@workstation var]$ ansible-vault edit test.yml
Vault password: # 加密現(xiàn)有的文件
[student@workstation var]$ ansible-vault encrypt vars.yml
New Vault password:
Confirm New Vault password:
Encryption successful# 解密現(xiàn)有的文件
[student@workstation var]$ ansible-vault decrypt test.yml
Vault password:
Decryption successful
[student@workstation var]$ cat test.yml
user: ztf# 改密碼
[student@workstation var]$ ansible-vault rekey vars.yml
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful
ansible vault 練習(xí)
[student@workstation ~]$ lab data-secret start[student@workstation data-secret]$ ansible-vault edit secret.yml
密碼是redhat
去掉注釋符號,保存退出[student@workstation data-secret]$ vim create_user.yml---
- name: Create user accounts for all our servershosts: devserversbecome: Trueremote_user: devopsvars_files:- secret.ymltasks:- name: Creating user from secret.ymluser:name: {{ username }}password: {{ pwhash }}[student@workstation data-secret]$ ansible-playbook --ask-vault-pass create_user.yml [student@workstation ~]$ lab data-secret finish
Facts變量(重要)
Ansible facts是在一個被管理主機上通過ansible自動被發(fā)現(xiàn)的變量。facts包含特定的主機信息,這些主機信息可以像正
plays,conditionals,loops或者其它場景下,不同的應(yīng)用場景取決于從被管理主機上采集的value類型
常見的facts變量
從被管理主機上可以搜集到facts包含:
1.主機名
2.內(nèi)核版本
3.網(wǎng)卡
4.地址
5.操作系統(tǒng)版本
6.環(huán)境變量
7.CPU的數(shù)量
8.可用內(nèi)存或者空閑內(nèi)容
9.可用磁盤空間
使用場景
使用facts來檢索被管理主機的狀態(tài)是非常方便的,而且還可以基于這些狀態(tài)做不同的動作,例如:
1.一個主機可以通過條件task判斷如果系統(tǒng)的內(nèi)核版本不匹配則重啟切換到最新的內(nèi)核版本。
2.通過fact檢索的內(nèi)存情況來自定義mysql的配置文件
3.在配置文件中使用的IPv4地址可以基于fact來設(shè)置
運行原理
每個play都會在第一個task之前自動運行setup模塊,以便搜集fact。在Ansible2.3版本,通常這個task會被報告成“
Facts”,在以前的版本通常會被報告執(zhí)行setup。你不需要在你的play中運行setup,它會自動運行。
如果你想看到setup模塊的內(nèi)容,你可以通過ad hoc命令運行
[student@workstation data-secret]$ ansible servera.lab.example.com -m setup
關(guān)閉facts采集
有時候,你可能不想在你的paly中開啟facts采集。為什么會有這樣的情況有幾點原因:
1.你不想在你的paly中使用facts
2.你想提升你的play速度
3.你想減少負載
可能被管理主機不能運行setup模塊,比如需要在采集facts之前需要安裝前置軟件
Task控制
loop循環(huán)
這里的{{item}} 是固定的,固定寫法就是這樣。不能變
條件判斷
語法
多條件判斷
條件判斷和循環(huán)結(jié)合
loop循環(huán)練習(xí)
[student@workstation ~]$ lab control-flow start
[student@workstation ~]$ cd control-flow/
[student@workstation control-flow]$ ls
ansible.cfg inventory
[student@workstation control-flow]$ cat ansible.cfg inventory
[defaults]
inventory=inventory
remote_user=devops[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[database_dev]
servera.lab.example.com[database_prod]
serverb.lab.example.com[student@workstation control-flow]$ cat playbook.yml
---
- name: this is a first playhosts: database_devvars:mariadb_packages:- mariadb-server- python3-PyMySQLtasks: - name: install pkgyum:name: "{{ item }}"state: presentloop: "{{ mariadb_packages }}"- name: start db serviceservice:name: mariadbstate: startedenabled: true[student@workstation control-flow]$ ansible-playbook playbook.yml [student@workstation control-flow]$ ansible database_prod -m command -a 'cat /etc/redhat-release' -u devops --become
serverb.lab.example.com | CHANGED | rc=0 >>
Red Hat Enterprise Linux release 8.0 (Ootpa)[student@workstation ~]$ lab control-flow finish
handlers練習(xí)
[student@workstation ~]$ lab control-handlers start
[student@workstation ~]$ cd control-handlers/
[student@workstation control-handlers]$ ls
ansible.cfg configure_db.yml inventory[student@workstation control-handlers]$ vim configure_db.yml [student@workstation control-handlers]$ cat configure_db.yml
---
- name: Installing MariaDB serverhosts: databasesvars:db_packages:- mariadb-server- python3-PyMySQLdb_service: mariadbresources_url: http://materials.example.com/labs/control-handlersconfig_file_url: "{{ resources_url }}/my.cnf.standard"config_file_dst: /etc/my.cnftasks:- name: install pkgyum:name: "{{ db_packages }}"state: presentnotify:- set db password- name: start serviceservice:name: "{{ db_service }}"state: startedenabled: true- name: download db cfgget_url:url: "{{ config_file_url }}"dest: "{{ config_file_dst }}"owner: mysqlgroup: mysqlforce: yesnotify:- restart db servicehandlers:- name: restart db serviceservice:name: "{{ db_service }}"state: restarted- name: set db passwordmysql_user:name: rootpassword: redhat[student@workstation control-handlers]$ ansible-playbook configure_db.yml 假設(shè)如果你的tasks運行錯誤,就不會通知handlers,那么此時你在寫之前,就應(yīng)該加上,force_handlers: yes
即使錯了,也會通知handlers,不會影響運行。
---
- hosts: all
force_handlers: yes但是,如果你忘記加了,但是已經(jīng)運行過playbook了,那么你就要在要被通知的tasks手動加上changed_when: truetasks:- name: install pkgyum:name: "{{ db_packages }}"state: presentchanged_when: true # 讓changed的狀態(tài)改變就行notify:- set db password[student@workstation ~]$ lab control-handlers finish
錯誤控制的練習(xí)
[student@workstation ~]$ lab control-errors start
[student@workstation control-errors]$ cat playbook.yml
---
- name: testhosts: databasesvars:web_package: httpdb_package: mariadb-serverdb_service: mariadbtasks:- name: install httpd pkgyum:name: "{{ web_package }}"state: present- name: install mariadb-serveryum:name: "{{ db_package }}"state: present[student@workstation control-errors]$ ansible-playbook playbook.yml # 運行后會報錯# 加一個忽略錯誤的命令
[student@workstation control-errors]$ cat playbook.yml
---
- name: testhosts: databasesvars:web_package: httpdb_package: mariadb-serverdb_service: mariadbtasks:- name: install httpd pkgyum:name: "{{ web_package }}"state: presentignore_errors: yes # 忽略錯誤- name: install mariadb-serveryum:name: "{{ db_package }}"state: present[student@workstation control-errors]$ ansible-playbook playbook.yml # 錯誤被跳過# 添加一個block
---
- name: testhosts: databasesvars:web_package: httpdb_package: mariadb-serverdb_service: mariadbtasks:- name: add blockblock:- name: install httpd pkgyum:name: "{{ web_package }}"state: presentrescue:- name: install mariadb-serveryum:name: "{{ db_package }}"state: present[student@workstation control-errors]$ ansible-playbook playbook.yml 當block里的東西運行失敗了,他還是會運行rescue的代碼# 加了always,如果block是對的,那么rescue是不會運行的,就直接運行always了
---
- name: testhosts: databasesvars:web_package: httpddb_package: mariadb-serverdb_service: mariadbtasks:- name: add blockblock:- name: install httpd pkgyum:name: "{{ web_package }}"state: presentrescue:- name: install mariadb-serveryum:name: "{{ db_package }}"state: presentalways:- name: add a alwaysservice:name: "{{ db_service }}"state: started[student@workstation ~]$ lab control-errors finish