日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何编写清晰的Ansible剧本(复杂剧本如何构建)

發(fā)布時間:2023/12/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何编写清晰的Ansible剧本(复杂剧本如何构建) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫在前面


  • 嗯,學(xué)習(xí)Ansible高級特性,整理這部分筆記
  • 博文內(nèi)容涉及
    • 復(fù)雜Ansible劇本的編寫規(guī)范
    • 一個具體的編寫Demo
  • 食用方式:
    • 理論有些枯燥,不感興趣小伙伴可以直接跳過去看Demo
    • 需要有ansible基礎(chǔ),了解ansible角色的使用

傍晚時分,你坐在屋檐下,看著天慢慢地黑下去,心里寂寞而凄涼,感到自己的生命被剝奪了。當(dāng)時我是個年輕人,但我害怕這樣生活下去,衰老下去。在我看來,這是比死亡更可怕的事。--------王小波


如何編寫清晰的Ansible腳本

對于運(yùn)維小伙伴來講,Ansible并不陌生,配置簡單,上手容易,只要掌握幾個基本的模塊就可以解決好多運(yùn)維中重復(fù)的事,但是對于處理更為高級的功能和更大、更復(fù)雜的項目時,管理和維護(hù)Ansible Playbook或高效使用將變得更加困難。

下面的的playbook是一個k8s安裝環(huán)境初始化的劇本,其實現(xiàn)方式簡單,是在k8s集群中所有節(jié)點(diǎn)都需要做的一些處理,實現(xiàn)如下功能

  • 配置firewall,selinux,配置hosts
  • 關(guān)閉swap
  • 配置yum源
  • 安裝docker-ce,導(dǎo)入缺少的鏡像,配置docker加速
  • 安裝k8s相關(guān)包:kubelet、kubeadm、kubectl
  • 啟動kubelet服務(wù)
- name: init k8shosts: alltasks:# 關(guān)閉防火墻- shell: firewall-cmd --set-default-zone=trusted# 關(guān)閉selinux- shell: getenforceregister: out- debug: msg="{{out}}"- shell: setenforce 0when: out.stdout != "Disabled"- replace:path: /etc/selinux/configregexp: "SELINUX=enforcing"replace: "SELINUX=disabled"- shell: cat /etc/selinux/configregister: out- debug: msg="{{out}}"- copy:src: ./hostsdest: /etc/hostsforce: yes# 關(guān)閉交換分區(qū)- shell: swapoff -a- shell: sed -i '/swap/d' /etc/fstab- shell: cat /etc/fstabregister: out- debug: msg="{{out}}"# 配置yum源- shell: tar -cvf /etc/yum.tar /etc/yum.repos.d/- shell: rm -rf /etc/yum.repos.d/*- shell: wget ftp://ftp.rhce.cc/k8s/* -P /etc/yum.repos.d/# 安裝docker-ce- yum:name: docker-cestate: present# 配置docker加速- shell: mkdir /etc/docker- copy:src: ./daemon.jsondest: /etc/docker/daemon.json- shell: systemctl daemon-reload- shell: systemctl restart docker# 配置屬性,安裝k8s相關(guān)包- copy:src: ./k8s.confdest: /etc/sysctl.d/k8s.conf- shell: yum install -y kubelet-1.21.1-0 kubeadm-1.21.1-0 kubectl-1.21.1-0 --disableexcludes=kubernetes# 缺少鏡像導(dǎo)入- copy:src: ./coredns-1.21.tardest: /root/coredns-1.21.tar- shell: docker load -i /root/coredns-1.21.tar# 啟動服務(wù)- shell: systemctl restart kubelet- shell: systemctl enable kubelet

如果搭建的集群節(jié)點(diǎn)很多,那么使用ansible要方便很多,但是上面的劇本沒有使用角色,所有的操作都耦合在一起,所以看起來不是特別清晰,可讀性差,而且一些可變的變量也沒有抽離出來。復(fù)用性差,也沒有考慮失敗回滾的問題,大部分的操作是通過shell模塊來完成的,尤其是對一些文件的操作,shell模塊不滿足冪等性。

高效的使用Ansible不僅僅在于功能或工具的使用,對于實踐方法和項目組織更重要,對于劇本的編寫規(guī)范,有以下三點(diǎn):

  • 保持簡單
  • 井然有序
  • 經(jīng)常測試

保持簡單

Ansible 的一大優(yōu)勢是簡潔性。使用playbook保持簡單,我們就能更加輕松地使用、修改和理解它們。

保持 Playbook 的可讀性

  • 確保playbook有恰當(dāng)注釋且易于閱讀。合理地使用垂直空白和注釋。
  • 始終為play和任務(wù)提供有意義的名稱,明確play或任務(wù)的用途。
  • 對于劇本編寫文件格式,YAML 它非常適合表述?系列的字典和數(shù)組。
  • 對于難以在Ansible Playbook 中表述?些復(fù)雜的控制結(jié)構(gòu)或條件,可以通過模板和Jinja2過濾器巧妙地處理變量中的數(shù)據(jù)。
  • 使用原生 YAML 語法,而不是“折疊”的語法,以下示例不是推薦的格式:
- hosts: node1,node2tasks:- yum: name=httpd state=present- copy: content="RHCE Test" dest=/var/www/html/index.html force=yes- service: name=httpd state=restarted enabled=yes- service: name=firewalld state=restarted enabled=yes- firewalld: service=http state=enabled permanent=yes immediate=yes

使用現(xiàn)有的模塊

  • 編寫新playbook時,從基礎(chǔ)playbook開始,并盡可能使用靜態(tài)清單。
  • 在構(gòu)建設(shè)計時,將debug 模塊用作測試或存根。
  • 在playbook按預(yù)期工作后,使用import或include將playbook分成較小的邏輯組件。
  • 盡量使用Ansible中包含的特殊用途模塊,而不是command、shell、raw這樣的通用模塊。使用為特定任務(wù)設(shè)計的模塊可以輕松地使 Playbook 具有冪等性,且易于維護(hù)。

遵循標(biāo)準(zhǔn)樣式

編寫Ansible項目時,應(yīng)考慮和同時遵循標(biāo)準(zhǔn)的樣式:遵循統(tǒng)一的標(biāo)準(zhǔn)有助于提高可維護(hù)性和可讀性。

  • 縮進(jìn)多少個空格
  • 如何使用垂直空白
  • 如何命名任務(wù)劇本角色和變量
  • 應(yīng)對什么進(jìn)行注釋
  • 如何注釋

井然有序

Ansible項目的組織和Playbook的運(yùn)行方式有助于維護(hù)、故障排除和審計。

遵循變量命名約定

因為 Ansible 具有相對扁平的命令空間,所以變量名非常重要。應(yīng)使用描述性變量且應(yīng)闡明內(nèi)容,如 apache_tls_port ,在角色中給最好能給角色變量添加前綴,如myapp_apache_tls_port 。

標(biāo)準(zhǔn)化項目結(jié)構(gòu)

在文件系統(tǒng)上構(gòu)建 Ansible 項目時,請使用統(tǒng)一的模式,推薦的示例:

Playbook 結(jié)構(gòu)的一大優(yōu)勢在于,可以將較?的playbook分成較小的?件,使其更易閱讀,而較小的子playbook 可能會包含可以獨(dú)立運(yùn)行的、適合特定用途的 play。

使用動態(tài)清單

動態(tài)清單支持從?個真實的中央來源集中管理主機(jī)和組,并確保清單自動更新。動態(tài)清單一般與云提供商、容器和虛擬機(jī)管理系統(tǒng)結(jié)合使用。

如果無法使用動態(tài)清單,則其它工具可以動態(tài)構(gòu)建組或其他信息。group_by 模塊根據(jù)事實動態(tài)生成組成員資格,該組成員資格對 playbook 的其余部分有效。

# Create nested groups - group_by:key: el{{ ansible_distribution_major_version }}-{{ ansible_architecture }}parents:- el{{ ansible_distribution_major_version }} TASK [group_by] **************************************************************************************************** task path: /root/ansible/group_by.yaml:5 [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details changed: [192.168.26.82] => {"add_group": "el7-x86_64","changed": true,"parent_groups": ["el7"] } changed: [192.168.26.81] => {"add_group": "el7-x86_64","changed": true,"parent_groups": ["el7"] }

充分利用組

主機(jī)可以是多個組的成員,可以按以下特征將主機(jī)劃分不同的種類:

  • 地理位置
  • 環(huán)境
  • 站點(diǎn)或服務(wù)

將角色用于可重復(fù)使用的內(nèi)容

  • 角色可以是 playbook 保持簡單,能夠通過重復(fù)利用項目間的通用代碼來減少工作量。
  • 通過變量使角色成為可配置的通同角色,以便在將它們用于?組不同的playbook時無需對其進(jìn)行編輯。
  • 使用ansible-galaxy init命令來初始化角色的目錄結(jié)構(gòu)。
  • RHEL 中的redhat-system-roles 軟件提供的角色受到官方支持。
  • 也可以通過Ansible Galaxy 提供的角色,但是注意其質(zhì)量和安全。
  • 將角色保存在項目的roles子目錄中。

集中運(yùn)行 Playbook

使用一個專用的控制節(jié)點(diǎn)來控制對系統(tǒng)的訪問和審計 Ansible 活動,讓所有的 Ansible Playbook 都從上面運(yùn)行。

系統(tǒng)管理員仍應(yīng)在系統(tǒng)上擁有自己的賬戶,以及用于連接受管主機(jī)的憑據(jù),并在需要時可以進(jìn)行權(quán)限提升。當(dāng)系統(tǒng)管理員離職時,因從受管主機(jī)的authorized_keys文件中刪除其 SSH 密鑰,同時撤銷其 sudo 權(quán)限。也可以考慮使用紅帽 Ansible Tower 作為中央控制節(jié)點(diǎn)。

經(jīng)常測試

在開發(fā)過程中、任務(wù)運(yùn)行時以及Playbook投入使用后,應(yīng)經(jīng)常測試 Playbook 和 task

測試任務(wù)的結(jié)果

如果需要確認(rèn)任務(wù)是否成功,請驗證任務(wù)的結(jié)果,而不要信任模塊的返回代碼

- start web server service: name: httpd status: started - name: Check web site from web server uri: ur1: http://{{ ansible_fqdn}}return_content: yes register: example_webpage failed_when: example_webpage. status !=200

使用 Block/Rescue 來恢復(fù)或回滾

block 指令可用于對任務(wù)進(jìn)行分組,與 rescue 指令結(jié)合使用時,可幫助從錯誤和故障中恢復(fù)。

--- - name: block testhosts: node1tasks:- block:- debug: msg="vg myvg not found" #提示卷組沒找到- debug: msg="create vg myvg .. .." #做其他操作(比如創(chuàng)建這個卷組...)when: ('myvg' not in ansible_lvm.vgs) #當(dāng)卷組myvg不存在時rescue:- debug: msg="creating failed .. .." #block失敗時提示創(chuàng)建卷組失敗always:- shell: vgscan #列出卷組信息register: list #保存到名為list的變量- debug: msg={{list.stdout_lines}} #提示卷組掃描結(jié)果

使用最新的 Ansible 版本開發(fā) Playbook

即使不在?產(chǎn)中使用最新版本的 Ansible,也應(yīng)該定期針對 Ansible 的最新版本測試 playbook。這將避免在Ansible 模塊和功能不斷演變時出現(xiàn)的問題。

如果 playbook 在運(yùn)行時顯示警告或棄用消息,應(yīng)注意它們并做出相應(yīng)的調(diào)整。通常,Ansible 中的某?功能已棄用或有變化,則該項目會在刪除或更改功能之前提早四個小版本提供棄用通知。

使用測試工具

使用 ansible-playbook --syntax-check 命令進(jìn)行語法檢測。

┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible-playbook group_by.yaml --syntax-checkplaybook: group_by.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$echo 22 >> group_by.yaml ┌──[root@vms81.liruilongs.github.io]-[~/ansible] └─$ansible-playbook group_by.yaml --syntax-check ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each: JSON: No JSON object could be decodedSyntax Error while loading YAML.could not find expected ':'The error appears to be in '/root/ansible/group_by.yaml': line 11, column 1, but may be elsewhere in the file depending on the exact syntax problem.The offending line appears to be:22 ^ here

使用 ansible-playbook --check 命令,檢查模式,針對check_mode中的實際受管主機(jī)運(yùn)行 Playbook(不會改變主機(jī)狀態(tài)),以查看Playbook執(zhí)行的更改。此項檢查不能保證完全準(zhǔn)確性,因為 playbook 可能需要實際運(yùn)行?些任務(wù),playbook 中的后續(xù)任務(wù)才能正常運(yùn)行。可能有?些標(biāo)記有check_mode: no指令的任務(wù)。這些任務(wù)即使在檢查模式中也會運(yùn)行。

tasks:- name: This task will always make changes to the systemansible.builtin.command: /something/to/run --even-in-check-modecheck_mode: no- name: This task will never make changes to the systemansible.builtin.lineinfile:line: "important config"dest: /path/to/myconfig.confstate: presentcheck_mode: yesregister: changes_to_important_config

一個Demo

下面我們來看一個完整的Demo,這個Demo做的事很簡單,但是劇本編寫清晰,在三臺機(jī)器部署一個web服務(wù),其中一臺機(jī)器用haproxy作為負(fù)載,剩下的兩臺機(jī)器提供web能力(安裝http服務(wù)并部署APP),劇本中創(chuàng)建了四個角色,用于描述四種行為:

  • 安裝配置負(fù)載均衡器
  • 安裝配置web服務(wù)器
  • 部署服務(wù)到web服務(wù)器
  • LB、HTTP 服務(wù)的firewall配置

配置、清單、主劇本文件編寫

編寫一個ansible.cfg 配置文件,這個不多講,指定主機(jī)清單文件位置和ssh用戶,配置sudo 提權(quán)方式。

[defaults] inventory=inventory remote_user=devops[privilege_escalation] become=True become_method=sudo become_user=root become_ask_pass=False

inventory 主機(jī)清單文件,定義兩個分組,

  • 作為LB的機(jī)器為 servera
  • 提供web能力的機(jī)器為serverb和serverc
[lb_servers] servera.lab.example.com[web_servers] server[b:c].lab.example.com

site.yml為定義的實際執(zhí)行的主劇本,這里通過,這里通過import_playbook模塊來引入一個外部的調(diào)用角色的模塊。一般情況下,當(dāng)一個playbook很長很復(fù)雜,可以通過對劇本進(jìn)行拆分。通過模塊化的方式將多個playbook組合為一個完整的playbook,或者把文件中的任務(wù)列表插入到play中.

嗯,簡單介紹下,ansible 可以使用兩種方式實現(xiàn)劇本的模塊化:

  • 包含內(nèi)容:動態(tài)操作(include_task),在playbook運(yùn)行期間,Ansible會在內(nèi)容到達(dá)時處理包含的內(nèi)容
  • 導(dǎo)入內(nèi)容: 靜態(tài)包含(import_task,import_playbook),在playbook運(yùn)行之前,Ansible在最初解析的時候預(yù)處理導(dǎo)入的內(nèi)容

和Java web體系中的Jsp腳本有些類似,通過include指令和include動作引入文件

我們可以看到,site.yml執(zhí)行的三個劇本都是通過導(dǎo)入的方式。

- name: Deploy HAProxyimport_playbook: deploy_haproxy.yml- name: Deploy Web Serverimport_playbook: deploy_apache.yml- name: Deploy Web Appimport_playbook: deploy_webapp.yml

執(zhí)行順序為,創(chuàng)建LB、創(chuàng)建web Serve,部署 web app,這里把劇本行為抽象為角色,然后在deploy_*里面調(diào)用角色,實現(xiàn)了行為和劇本的解耦。

調(diào)用角色劇本編寫

看一下導(dǎo)入的執(zhí)行角色的劇本deploy_haproxy.yml

- name: Ensure HAProxy is deployedhosts: lb_serversforce_handlers: Trueroles:# The "haproxy" role has a dependency# on the "firewall" role. The# "firewall" role requires a# "firewall_rules" variable be defined.- role: haproxyfirewall_rules:# Allow 80/tcp connections- port: 80/tcp

通過劇本執(zhí)行LB角色,并且定義·變量firewall_rules,聲明開放的端口協(xié)議,這里有一個force_handlers,我們看一下,劇本中handlers用于任務(wù)處理(布雷),可以設(shè)置一個或一塊任務(wù),但是他不會主動執(zhí)行,需要通過notify通知觸發(fā)(引爆),還有一些需要注意的點(diǎn):

  • 每個劇本中handlers任務(wù)只會執(zhí)行一次,即使收到多個任務(wù)的觸發(fā)通知
  • handlers組的每一個任務(wù)都要設(shè)置名稱(name)
  • handlers的層次與tasks平級
  • 其他任務(wù)在必要時,使用notify語句通知handlers任務(wù)名
  • 僅當(dāng)發(fā)起notify的任務(wù)的執(zhí)行狀態(tài)為changed時,handlers任務(wù)才會被執(zhí)行

看一個Demo

--- - name: handlers testhosts: node5tasks:- lvol: lv=vo001 size=100M vg=search #創(chuàng)建邏輯卷vo001notify: mkfs #如果changed則通知格式化(否則無需格式化)handlers:- name: mkfs #定義格式化操作處理filesystem: dev=/dev/search/vo001 fstype=xfs force=yes ...

那么這里的force_handlers即強(qiáng)制執(zhí)行的意思,當(dāng)觸發(fā)他的通知對應(yīng)的任務(wù)執(zhí)行失敗,但是handlers任然會執(zhí)行,

deploy_apache.yml

- name: Ensure Apache is deployedhosts: web_serversforce_handlers: Trueroles:# The "apache" role has a dependency# on the "firewall" role. The# "firewall" role requires a# "firewall_rules" variable be defined.- role: apachefirewall_rules:# Allow http requests from any# internal zone source.- zone: internalservice: http# Add servera, the load balancer,# to the internal zone.- zone: internalsource: "172.25.250.10"

deploy_webapp.yml

- name: Ensure Web App is deployedhosts: web_serversvars:- webapp_version: v1.0roles:- role: webapp

這里需要說明下,vars定義的變量屬于劇本變量,而在roles下面的變量為角色變量

自定義角色編寫

我們來看一下角色,一共有四個角色,其中三個在上面的deplay_*.yaml 文件中被調(diào)用,firewall角色被apache和haproxy依賴調(diào)用

  • apache http web服務(wù)器部署
  • firewall 防火墻部署配置
  • haproxy LB部署配置
  • wen app 能力部署
┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles] └─$ls apache firewall haproxy webapp

關(guān)于角色這里我們簡單的回顧下

ansible 中的role指的是,為了方便復(fù)雜任務(wù)(包含大批量任務(wù)操作、模板、變量等資源)的重復(fù)使用,降低playbook劇本編寫難度,而預(yù)先定義好的一套目錄結(jié)構(gòu)。

針對每一個角色,ansible會到固定的目錄去調(diào)取特定的數(shù)據(jù),關(guān)于角色在劇本中的使用,可以看看上面 deplay_*.yaml

角色內(nèi)一般不指定hosts: 清單主機(jī)列表,而是交給調(diào)用此角色的劇本來指定,當(dāng)然測試除外,具體看下

haproxy 角色

haproxy 角色 在劇本中負(fù)責(zé)LB 相關(guān)行為,簡單看一下目錄結(jié)構(gòu)

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles] └─$cd haproxy/ #角色根目錄 ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$tree . ├── defaults #定義變量的缺省值,優(yōu)先級較低 │ └── main.yml ├── handlers #定義handlers處理任務(wù) │ └── main.yml ├── meta #定義作者、版本、兼容性、依賴項等描述信息 │ └── main.yml ├── tasks #任務(wù)入口,最主要的文件 │ └── main.yml ├── templates #存放模板文件 │ └── haproxy.cfg.j2 └── tests # 用于角色測試├── inventory└── test.yml6 directories, 7 files

當(dāng)然,這里的角色目錄并不是最全的,正常的角色中還會有vars目錄用于定義變量,相對于defaults優(yōu)先級更高,files目錄存放一些靜態(tài)文件,README.md文件用于描述自述信息,我們通過init命令生成一個角色看一下目錄

┌──[root@vms81.liruilongs.github.io]-[~/ansible/roles] └─$ansible-galaxy init demo - Role demo was created successfully ┌──[root@vms81.liruilongs.github.io]-[~/ansible/roles] └─$ls demo ┌──[root@vms81.liruilongs.github.io]-[~/ansible/roles] └─$tree . └── demo├── defaults│ └── main.yml├── files├── handlers│ └── main.yml├── meta│ └── main.yml├── README.md├── tasks│ └── main.yml├── templates├── tests│ ├── inventory│ └── test.yml└── vars└── main.yml9 directories, 8 files ┌──[root@vms81.liruilongs.github.io]-[~/ansible/roles] └─$

嗯,回到我們的haproxy來看一下 defaults目錄下的yaml文件用于定義一些缺省的變量。

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat defaults/main.yml # Log-level for HAProxy logs log_level: info# Port exposed to clients port: 80# Name for the default backend backend_name: app# Port backend is exposed to backend_port: 80# The appservers variable is a list # of backend servers that provide # the web service that is proxied # haproxy. Each server must define: # name, address, port. Below is # and example structure: # appservers: # - name: serverb.lab.example.com # ip_address: 1.2.3.4 # port: 5000 # - name: serverc.lab.example.com # ip_address: 1.2.3.5 # port: 5000 # The default is no defined backend servers. appservers: []# Socket used to communicate with haproxy service. DO NOT CHANGE socket: /var/run/haproxy.sock

handlers這個目錄用于定義需要處理被激活的任務(wù)。這里定義了兩個任務(wù),都用到了Service模塊

  • 重新啟動haproxy服務(wù)
  • 重新加載haproxy服務(wù)配置文件
┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat handlers/main.yml --- # handlers file for haproxy- name: restart haproxyservice:name: haproxystate: restarted- name: reload haproxyservice:name: haproxystate: reloaded

看下meth元數(shù)據(jù),作者信息,版本,以及通過dependencies我們可以看到該角色依賴角色firewall

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat meta/main.yml galaxy_info:author: Ophelia Dunhamdescription: A role to ensure deployment of HAProxycompany: Example, Inc. 。。。。license: license (GPLv2, CC-BY, etc)min_ansible_version: 2.4 。。。。galaxy_tags: [] 。。 dependencies:- name: firewall

這里我們簡單聊聊角色依賴,角色依賴可以在使用角色時自動拉入其他角色。Ansible 執(zhí)行角色依賴項,則必須使用關(guān)鍵字dependencies在mate文件夾下的main.yaml中聲明在指定角色之前插入的角色和參數(shù)列表,我們這里的參數(shù)是定義在deploy_*.yaml

主任務(wù)劇本

  • 通過yum模塊下載負(fù)載均衡工具h(yuǎn)aproxy和反向代理工具socat
  • 通過Service模塊啟動haproxy,并設(shè)置開啟自啟
  • 通過template模塊,利用jieja2 模板,替換配置文件,這里處理完要通知前面重載配置文件的handlers
┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat tasks/main.yml --- # tasks file for haproxy - name: Ensure haproxy packages are presentyum:name:- haproxy- socatstate: present- name: Ensure haproxy is started and enabledservice:name: haproxystate: startedenabled: yes- name: Ensure haproxy configuration is settemplate:src: haproxy.cfg.j2dest: /etc/haproxy/haproxy.cfg#validate: haproxy -f %s -c -qnotify: reload haproxy

模板文件編寫,這里用到了jieja2模板引擎,在一般的python web項目中用的比較多一點(diǎn),這里簡單的理解為變量替換。

haproxy.cfg.j2模板里用到了我們之前定義的大量變量,包括default目錄的下main.yaml中定義的變量,以及appservers.yaml中的變量。

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat templates/haproxy.cfg.j2 #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global#Send events/messages to rsyslog server.log 127.0.0.1:514 local0 {{ log_level }}chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 4000user haproxygroup haproxydaemon#state changes due to API calls are stored in this file.server-state-file /usr/local/haproxy/haproxy.state# turn on stats unix socket# required for the ansible haproxy module.stats socket {{ socket }} level admin# utilize system-wide crypto-policiesssl-default-bind-ciphers PROFILE=SYSTEMssl-default-server-ciphers PROFILE=SYSTEM#--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaultsmode httplog globaloption httplogoption dontlognulloption http-server-closeoption forwardfor except 127.0.0.0/8option redispatchretries 3timeout http-request 10stimeout queue 1mtimeout connect 10stimeout client 1mtimeout server 1mtimeout http-keep-alive 10stimeout check 10smaxconn 3000#Loads state changes from the state file.load-server-state-from-file global#--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend mainmode httpbind *:{{ port }}default_backend {{ backend_name }}#--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend {{ backend_name }}balance roundrobin {% for server in appservers %}server {{ server.name }} {{ server.ip }}:{{ backend_port }} {% endfor %}

appservers 清單變量用于定義需要負(fù)載的機(jī)器域名和ip。這里為了角色的復(fù)用性,單獨(dú)分離出來。

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices] └─$cat appservers.ymlappservers:- name: serverb.lab.example.comip: "172.25.250.11"- name: serverc.lab.example.comip: "172.25.250.12"

剩下的就是測試相關(guān)的yaml文件,不多介紹,remote_user指定連接受管機(jī)的遠(yuǎn)程用戶名

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat tests/inventory localhost┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/haproxy] └─$cat tests/test.yml --- - hosts: localhostremote_user: rootroles:- haproxy

apache 角色

apache 角色用于提供http 服務(wù),目錄結(jié)構(gòu)相對簡單

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles] └─$cd apache/ ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/apache] └─$tree . ├── meta │ └── main.yml ├── tasks │ └── main.yml └── tests├── inventory└── test.yml3 directories, 4 files ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/apache] └─$

meta 文件夾我們這里不多介紹了,涉及防火墻操作,所以依賴firewall角色,看一下主任務(wù)劇本

  • yum模塊安裝 http相關(guān)包
  • seboolean模塊用于設(shè)置selinux開機(jī)自啟,允許httpd_can_network_connect 訪問網(wǎng)絡(luò)
  • service模塊用于啟動http服務(wù)
┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/apache] └─$cat tasks/main.yml --- # tasks file for apache- name: Install httpyum:name:- httpd- php- git- php-mysqlndstate: present- name: Configure SELinux to allow httpd to connect to remote databaseseboolean:name: httpd_can_network_connect_dbstate: truepersistent: yes- name: http service stateservice:name: httpdstate: startedenabled: yes

webapp 角色

webapp角色用于部署web 項目到httpd服務(wù),主要涉及缺省變量編寫和主任務(wù)劇本。

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles] └─$cd webapp/ ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/webapp] └─$tree . ├── defaults │ └── main.yml ├── meta │ └── main.yml ├── tasks │ └── main.yml └── tests├── inventory└── test.yml4 directories, 5 files ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/webapp] └─$

defaults目錄下的清單變量只有一個webapp_message,meta目錄下的元數(shù)據(jù)不多介紹

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/webapp] └─$cat defaults/main.yml webapp_message: "This is" ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/webapp] └─$cat meta/main.yml

主任務(wù)劇本中,用了一個dufault目錄下的缺省變量和一個ansible的魔法變量,一個使用角色時定義的劇本變量。通過copy模塊向http服務(wù)的引導(dǎo)頁寫入一句話。

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/webapp] └─$cat tasks/main.yml --- # tasks file for webapp#- name: Copy the code from the repository # git: # repo: "{{ webapp_repo }}" # version: "{{ webapp_version }}" # dest: /var/www/html/ # accept_hostkey: yes ## key_file: deployment key??- name: Copy a stub file.copy:content: "{{ webapp_message }} {{ ansible_hostname }}. (version {{ webapp_version}})\n"dest: /var/www/html/index.html

最后來看一下firewall角色

firewall 角色

firewall 角色并沒有被顯示的調(diào)用,那么它是如何被調(diào)用的?

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles] └─$cd firewall/ ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/firewall] └─$tree . ├── defaults │ └── main.yml ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── tasks │ └── main.yml └── tests├── inventory└── test.yml5 directories, 6 files ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/firewall] └─$

這里就要講到角色依賴,我們上面的haproxy角色和apache角色都在meta/main.yaml 文件中依賴了firewall角色,所以haproxy角色和apache角色在執(zhí)行的時候要先執(zhí)行firewall角色.

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/firewall] └─$cat defaults/main.yml --- # defaults file for firewall# This role requires that firewall_rules variable # be defined. The variable is a list of rules, and # each rule defines: # # service: (optional) # port: (optional) # zone: (optional) # source: (optional) # # A rule should only define a service or a port. # And example definition is: # # firewall_rules: # - service: http # zone: internal # - port: 8443 # source: 192.168.0.2# By default, no rules are implemented. firewall_rules: []

一個重載firewall 配置文件的任務(wù)

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/firewall] └─$cat handlers/main.yml --- # handlers file for firewall- name: reload firewalldservice:name: firewalldstate: reloaded

主任務(wù)文件,編寫防火墻配置,在配置完通知上面的handlers

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices/roles/firewall] └─$cat tasks/main.yml --- # tasks file for firewall- name: Ensure Firewall Sources Configurationfirewalld:source: "{{ item.source if item.source is defined else omit }}"zone: "{{ item.zone if item.zone is defined else omit }}"permanent: yesstate: "{{ item.state | default('enabled') }}"service: "{{ item.service if item.service is defined else omit }}"immediate: trueport: "{{ item.port if item.port is defined else omit }}"loop: "{{ firewall_rules }}"notify: reload firewalld

對劇本的clean

當(dāng)我們不需要這套環(huán)境了需要編寫一個卸載當(dāng)前環(huán)境的劇本clean.yml

- name: Clean Load Balancershosts: lb_serversgather_facts: notasks:- name: Remove packagesyum:name: haproxystate: absent- set_fact:firewall_rules:- port: 80/tcp- name: Clean Web Servershosts: web_serversgather_facts: notasks:- name: Remove packagesyum:name: httpdstate: absent- set_fact:firewall_rules:- zone: internalservice: http- zone: internalsource: 172.25.250.10- name: Clean Firewall ruleshosts: lb_servers, web_serverstasks:- name: Ensure Firewall Sources Configurationfirewalld:source: "{{ item.source if item.source is defined else omit }}"zone: "{{ item.zone if item.zone is defined else omit }}"permanent: yesstate: 'disabled'service: "{{ item.service if item.service is defined else omit }}"port: "{{ item.port if item.port is defined else omit }}"loop: "{{ firewall_rules }}"- name: reload firewalldservice:name: firewalldstate: reloaded- name: Remove web applicationhosts: web_serverstasks:- name: Remove stub filefile:state: absentpath: "/var/www/html/index.html"

下面是Demo完整的結(jié)構(gòu)

┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices] └─$ls ansible.cfg clean.yml deploy_haproxy.yml inventory site.yml appservers.yml deploy_apache.yml deploy_webapp.yml roles ┌──[root@workstation.lab.example.com]-[/home/student/DO447/labs/development-practices] └─$

總結(jié)

以上是生活随笔為你收集整理的如何编写清晰的Ansible剧本(复杂剧本如何构建)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。