一千萬個為什麽

搜索

Ansible與在Vagrant中簡單運行配置bash shell有何不同?



一群經驗豐富的使用shell腳本解決問題的IT系統管理員正在考慮開始使用Ansible來代替。

是否有充分的差異和充分的理由開始使用Ansible與繼續編寫shell腳本?

轉載註明原文: Ansible與在Vagrant中簡單運行配置bash shell有何不同?

一共有 4 個回答:

當你這樣說時,即使Ansible具有一些固有的優點,但使用熟悉的工具(在這種情況下,shell腳本)的好處必須被超過。我不認為這有明確的答案。

如果團隊可以實現Ansible在shell中提供的東西:

  1. 聲明式,冪等配置管理
  2. 訪問行業常用服務的可重復使用的片段(即劇本)。
  3. 遠程執行的可靠管理,包括重試,滾動邏輯等。

那麽他們可能會堅持他們所知道的。

畢竟,你可以在BASH中實現“守衛”。你可以找到很多BASH現有的工作來解決各種服務器配置任務(實際上任何Dockerfile都有90%的bash安裝代碼)。您可以非常接近Ansible/Salt/Chef-Zero為您提供的內容,而無需實際將現有解決方案移植到這些工具中。

這是美國國立衛生研究院(不是在這裏發明的)傾向之間的平衡行為,並且拋棄了良好的既定腳本,轉而采用更強大的解決方案。

最後要考慮的一點是:當你試圖招募更多的人加入團隊時,你的技術堆棧如何實現。找到具有Ansible經驗的人比找到在您自己的自制腳本CM工具方面有經驗的人容易得多。這不僅僅是技術上的考慮,更多的是文化上的考慮。你想成為發明自己的Ansible的奇怪組織嗎,還是你想成為找到合適工具的合理組織?這些決定會影響你繪制人才的能力。

我從未使用過Ansible,但幾周後,我試圖找出Ansible與shell腳本相比的優點 - 這證明,至少在我的情況下,他們運行的令人困惑的廣告活動是有效的!經過許多不成功的嘗試 - 這證明了他們的文檔在回答最明顯的問題時失敗了 - 我想我終於明白了:

現在,讓我們觀看介紹視頻,並通過Ansible的介紹材料隨機選擇一位潛在的新用戶,讓我們將其與熟練的shell程序員可以立即產生的內容進行比較。

我的結論是,對於shell腳本,Ansible實際上提供了1.檢查系統是否符合所需狀態的可能性,2.與Ansible Tower集成的能力,Ansible Tower是一種支付系統,似乎包含監控功能。在一些重要的情況下,比如在實現不可變的服務器模式時,點1可能不是非常有用,因此列表很薄。

我的結論是,Ansible提供的shell腳本提供的好處,正如文檔所展示的那樣,在可用模塊涵蓋的少數樂觀案例中可能是明智的,但在一般情況下很小甚至是假設。對於一個熟練的shell程序員來說,這些好處很可能是由平衡的其他方面所抵消。

但是這也許只能證明介紹材料有多糟糕!

快速入門視頻:

快速入門視頻。它從一個頁面開始聲稱......這些都不是真正的主張,這些都是子彈清單,一個人工制品通常用於暫停演講中的關鍵判斷(因為邏輯沒有顯示,所以不能批評!)

1. Ansible很簡單:

1.1人類可讀自動化 - 規範是技術文檔,怎麽可能

  name: upgrade all packages
  yum:
    name: '*'
    state: latest

比在shell腳本中找到的相應的 yum 調用更容易閱讀?此外,任何與AppleScript聯系的人都會在閱讀“人類可讀自動化”時大笑起來。

1.2不需要特殊的編碼技巧 - 如果不編寫正式的規範,什麽是編碼?他們有條件,變量,那麽,它是不是編碼?為什麽我需要一些我無法編​​程的東西,從今以後會變得不靈活?該聲明令人高興地不準確!

1.3按順序執行的任務 - 好吧,也許一些 codegolf aficionados 意識到執行混亂任務的語言,但按順序執行任務似乎很難。

1.4快速提高生產力 - 熟練的shell程序員現在生產效率很高。這個反駁的論點和最初的論點一樣嚴重。

Ansible強大

一個流行的推銷員賣藝術品的伎倆是欺騙人們相信他們會獲得這些文物的“權力”。汽車或等滲飲料廣告的歷史應該提供一個有說服力的例子列表。

在這裏,Ansible可以做“應用程序部署” - 但shell腳本肯定會做“配置管理”,但這僅僅是該工具目的的一種聲明,而不是一種功能,而“工作流程編排”看起來有點自命不凡,但沒有例子超出了 GNU Parallel 所能做到的事情。

Ansible是無代理的

為了填充列,他們以三種不同的方式寫這只需要 ssh, ,正如每個人都知道的那樣是一個守護進程,並且與這些代理無關遍布全球的配置管理!

視頻的其余部分

視頻的其余部分 introduces inventories, which are static lists of resources (like servers) and demonstrates how to deploy Apache on three servers simultaneously. This really does not match the way I work, where resources are highly dynamic and can be enumerated by command-line tooling provided by my cloud provider, and consumed by my shell functions using the pipe | operator. Also, I do not deploy Apache on three servers simultaneously, rather, I build a master instance image that I then use to start 3 instances which are exact replicas one of the other. So the “orchestrating” part of the argumentation does not look very pertinent.

隨機文檔步驟1:與EC2集成

EC2是來自亞馬遜的計算服務,與它的交互由一些 Ansible模塊支持。 (還提供了其他流行的雲計算提供商):

# demo_setup.yml

- hosts: localhost
  connection: local
  gather_facts: False

  tasks:

    - name: Provision a set of instances
      ec2:
         key_name: my_key
         group: test
         instance_type: t2.micro
         image: "{{ ami_id }}"
         wait: true
         exact_count: 5
         count_tag:
            Name: Demo
         instance_tags:
            Name: Demo
      register: ec2

相應的shell腳本將與由JSON替換的YAML基本相同:

provision_a_set_of_instances()
{
  aws --output=text ec2 run-instances --image-id …   
}

或JSON版本

provision_a_set_of_instances()
{
  aws --output=text ec2 run-instances --cli-input-json "$(provision_a_set_of_instances__json)"  
}

provision_a_set_of_instances__json()
{
  cat <

兩個版本基本相同,有效載荷的大部分是在YAML或JSON結構中枚舉初始化值。

隨機文檔第2步:持續交付和滾動升級

本指南的大部分內容並未顯示任何真正有趣的功能:它引入了變量(IIRC ,shell腳本也有變量)!, Ansible模塊處理mysql,所以如果不是在“如何創建一個擁有XY權限的mysql用戶”之後進行搜索,而是以類似於

# Create Application DB User
mysql --host "${mysql_host}" --user "${mysql_user}" --password "${mysql_password}" "${mysql_table}" <

你在“如何在 ansible 中創建一個擁有X Y權限的mysql用戶”之後進行搜索並最終以

- name: Create Application DB User
  mysql_user: name={{ dbuser }} password={{ upassword }}
              priv=*.*:ALL host='%' state=present

差異仍然可能不是很有意義。在該頁面上,我們還發現Ansible有一個模板元編程語言

{% for host in groups['monitoring'] %}
-A INPUT -p tcp -s {{ hostvars[host].ansible_default_ipv4.address }} --dport 5666 -j ACCEPT
{% endfor %}

當我看到這個時,我碰巧真的在我的舒適區。這種用於聲明性語言的簡單元編程與BSD Makefiles完全相同的理論範例!我恰巧已經被廣泛編程了這段文字向我們展示了使用YAML文件的承諾被破壞了(所以我無法通過YAML解析器運行我的劇本, )。它也向我們表明,Ansible必須討論評估順序的微妙藝術:我們必須確定變量是否擴展到語言的“聲明性部分”或語言的“必要”元部分。這裏的shell編程更簡單,除了 explicit eval 或external-script sourcing之外,沒有元編程。假設的等效殼體摘錄將是

enumerate_group 'monitoring' | {
  while read host; do
    …
  done
}

與Ansible變體相比,它的復雜性可能是可以容忍的:它只是使用語言中普通的,規則的,枯燥的構造。

隨機文檔步驟3:測試策略

最後,我們遇到的是Ansible第一個真正有趣的功能:Ansible資源是期望狀態的模型。因此,不應該有必要測試服務是否已啟動,是否安裝了包或其他類似的東西。 Ansible是確保這些事情是陳述真實的系統。相反,在你的劇本中聲明這些東西。“現在開始有點有趣,但是:

    除了可用模塊容易實現的一些標準情況之外,我還必須自己提供實現測試的位,這很可能涉及一些shell命令。

  1. 在執行不可變服務器模式的環境中,檢查安裝的一致性可能並不十分相關:所有運行的系統通常都是從主映像(例如實例映像或docker映像)衍生而來,永遠不會更新 - 它們被替換為新的。

未解決的擔憂:可維護性

介紹性資料 Ansible 忽略了可維護性的問題。基本上沒有類型系統,shell腳本具有JavaScript,Lisp或Python的易維護性:只有在廣泛的自動化測試套件的幫助下才能成功實現大量的重構 - 或者至少允許輕松進行交互式測試的設計。也就是說,雖然shell腳本是系統配置和維護的通用語,但幾乎每種編程語言都有一個到外殼的接口。因此,利用高級語言的可維護性優勢,通過使用它們將各種外殼配置位粘合在一起,是完全可行的。對於OCaml,我寫了 Rashell ,它基本上為子流程提供了一個通用的交互模式,這使得翻譯配置腳本到OCaml本質上是微不足道的。

從Ansible方面來看,劇本的結構非常薄弱,並且存在元編程功能,這使得情況與shell腳本的情況基本一樣糟糕,減去了如何為Ansible編寫單元測試並不明顯,引入專門的高級語言的論點不能被模仿。

配置步驟的冪等性

Ansible的文檔提請註意編寫冪等配置步驟的必要性。更確切地說,應該寫出配置步驟,以便將步驟順序簡化為 ,即我們不需要重復配置步驟。這是一個比冪等性更強的條件。由於Ansible允許劇本使用任意shell命令,因此Ansible本身無法保證這種更強大的條件得到尊重。這只依賴程序員的紀律。

上面的答案涵蓋了其中的一部分,但沒有涉及到重要元素之一:融合設計。我之前在 https://coderanger.net/thinking/但簡短的版本是bash腳本是一組指令,而Ansible playbook(或Chef recipe,Salt state等)是對所需狀態的描述。通過記錄你想要的狀態,而不是你想要達到的步驟,你可以應付更多的起始狀態。這是很早以前CFEngine中概述的Promise Theory的核心,以及我們(配置管理工具)自此以後都在復制的設計。

tl;博士Ansible代碼說你想要什麽,bash代碼說如何做一件事。

有一點值得註意的是,在遠程主機上運行您的可靠劇本的問題也會減少。因為這是管理理智的主要原因。當你使用shell腳本時,你仍然需要有一種方法將腳本編寫到遠程主機上。