使用 Ansible 自動更換磁碟

使用 Ansible 自動更換磁碟

大家好。 我在 OK 擔任首席系統管理員,負責門戶的穩定運作。 我想談談我們如何建立一個自動更換磁碟的流程,然後我們如何將管理員排除在這個流程之外,並用機器人取代他。

本文是一種音譯 表演 在 HighLoad+ 2018

建置磁碟更換流程

首先是一些數字

OK 是數百萬人使用的龐大服務。 它由大約 7 台伺服器提供服務,這些伺服器位於 4 個不同的資料中心。 伺服器包含超過 70 萬個磁碟。 如果將它們堆疊在一起,就會得到一座超過 1 公里高的塔。

硬碟機是最常發生故障的伺服器元件。 對於這樣的捲,我們每週必須更換大約 30 個磁碟,而這個過程已經成為一個不太愉快的例行公事。

使用 Ansible 自動更換磁碟

事件

我們公司引入了成熟的事件管理。 我們在 Jira 中記錄每個事件,然後解決並整理。 如果某個事件對使用者產生了影響,那麼我們肯定會聚在一起思考如何在這種情況下更快地做出反應,如何減少影響,當然還有如何防止再次發生。

儲存設備也不例外。 它們的狀態由 Zabbix 監控。 我們監控 Syslog 中的消息是否有寫入/讀取錯誤、分析硬體/軟體 raid 的狀態、監控 SMART 並計算 SSD 的磨損。

以前如何更換磁碟

當 Zabbix 中發生觸發時,Jira 中會建立一個事件,並自動指派給資料中心中的對應工程師。 我們對所有硬體事件(即需要對資料中心設備進行任何實體操作的事件)執行此操作。
資料中心工程師是解決與硬體相關的問題並負責安裝、維護和拆卸伺服器的人員。 收到票後,工程師開始工作。 在磁碟架中,他獨立更換磁碟。 但如果他無法存取所需的設備,工程師就會向值班的系統管理員尋求協助。 首先,您需要將磁碟從旋轉中取出。 為此,您需要在伺服器上進行必要的變更、停止應用程式並卸載磁碟。

值班系統管理員在輪班期間負責整個門戶的運作。 他調查事件、進行維修並幫助開發人員完成小任務。 他不僅僅處理硬碟。

此前,資料中心工程師透過聊天方式與系統管理員溝通。 工程師發送了 Jira 票證的鏈接,管理員跟踪了它們,並在記事本中保存了工作日誌。 但聊天對於此類任務來說並不方便:那裡的資訊沒有結構化,並且很快就會丟失。 管理員可以簡單地離開計算機,在一段時間內不回應請求,而工程師則拿著一堆磁碟站在伺服器旁等待。

但最糟糕的是,管理員看不到全貌:有哪些磁碟事件,哪裡可能出現問題。 這是因為我們將所有硬體事件委託給工程師。 是的,可以在管理員的儀表板上顯示所有事件。 但它們的數量很多,而管理員只參與了其中的一些。

此外,工程師無法正確設定優先級,因為他對特定伺服器的用途或磁碟機之間的資訊分佈一無所知。

新的更換程序

我們做的第一件事是將所有磁碟事件移至一個單獨的類型「硬體磁碟」中,並向其中添加「區塊裝置名稱」、「大小」和「磁碟類型」字段,以便這些資訊將儲存在票證中,且不必在聊天中不斷交流。

使用 Ansible 自動更換磁碟
我們也同意,在一次事件中我們只更換一張磁碟。 這大大簡化了自動化流程、統計收集和未來的工作。

此外,我們還新增了「責任管理員」欄位。 值班的系統管理員會自動插入那裡。 這非常方便,因為現在工程師總是能看到誰負責。 無需去日曆和搜尋。 正是這個欄位使得在管理員的儀表板上顯示可能需要他的幫助的票證成為可能。

使用 Ansible 自動更換磁碟
為了確保所有參與者從創新中獲得最大利益,我們創建了過濾器和儀表板,並向大家介紹了它們。 當人們理解變化時,他們就不會因為不必要的事情而與變化保持距離。 對於工程師來說,了解伺服器所在的機架號碼、磁碟的大小和類型非常重要。 管理員首先需要了解這是什麼類型的伺服器群組以及更換磁碟時可能會產生什麼影響。

字段的存在及其顯示很方便,但它並沒有使我們免於使用聊天的需要。 為此,我們必須改變工作流程。

以前是這樣的:

使用 Ansible 自動更換磁碟
這就是工程師今天在不需要管理員幫助時繼續工作的方式。

我們做的第一件事就是引入一個新的狀態 調查。 當工程師尚未決定是否需要管理員時,工單處於此狀態。 透過此狀態,工程師可以將工單轉給管理員。 此外,當需要更換磁碟但磁碟本身不在現場時,我們會使用此狀態來標記工單。 這種情況發生在 CDN 和遠端站點的情況下。

我們也加入了狀態 各就各位。 更換磁碟後,票據將轉移到其中。 也就是說,一切都已完成,但 HW/SW RAID 在伺服器上同步。 這可能需要相當長的時間。

如果管理員參與這項工作,該方案就會變得有點複雜。

使用 Ansible 自動更換磁碟
從狀態 已提交 系統管理員和工程師都可以翻譯工單。 狀態中 進行中 管理員將磁碟從旋轉中移除,以便工程師可以簡單地將其拉出:打開背光、卸載磁碟、停止應用程序,具體取決於特定的伺服器群組。

然後票證將被轉移到 準備改變:這是向工程師發出的信號,表示磁碟可以拔出。 Jira 中的所有欄位都已填寫,工程師知道磁碟的類型和大小。 此資料可以在先前的狀態下自動輸入,也可以由管理員輸入。

更換磁碟後,票據狀態變為 。 它檢查是否已插入正確的磁碟、是否已完成分割區、是否啟動了應用程式以及是否啟動了一些資料復原任務。 票也可以轉移到狀態 各就各位,在這種情況下,管理員仍將負責,因為他使磁碟旋轉。 完整的圖如下。

使用 Ansible 自動更換磁碟
新增欄位使我們的生活變得更加輕鬆。 這些人開始處理結構化訊息,需要做什麼以及在哪個階段做什麼就變得很清楚了。 優先順序變得更加相關,因為它們現在是由管理員設定的。

無需聊天。 當然,管理員可以給工程師寫信“這個需要快點更換”,或者“已經晚上了,你有時間更換嗎?” 但我們不再每天在聊天中就這些問題進行交流。

磁碟開始批量更換。 如果管理員上班得早一點,有空閒時間,而且還沒有發生任何事情,他可以準備多台伺服器進行更換:填寫字段,將磁碟從輪換中移除,然後將任務轉移給工程師。 工程師稍後來到資料中心,查看任務,從倉庫取出必要的驅動器並立即更換它們。 結果,替代率增加了。

建構工作流程時所學到的經驗教訓

  • 建置過程時,您需要從不同來源收集資訊。
    我們的一些管理員不知道工程師自己更換了磁碟。 有些人認為 MD RAID 同步是由工程師處理的,儘管他們中的一些人甚至沒有權利這樣做。 一些領先的工程師這樣做了,但並非總是如此,因為該過程沒有在任何地方被描述。
  • 過程應該簡單易懂。
    一個人很難記住很多步驟。 Jira 中最重要的相鄰狀態應放置在主螢幕上。 您可以對它們進行重命名,例如我們稱之為“進行中準備更改”。 其他狀態可以隱藏在下拉式選單中,這樣就不礙眼了。 但最好不要限制人們,給他們過渡的機會。
    解釋創新的價值。 當人們理解時,他們就會更容易接受新程式。 對我們來說非常重要的是,人們不要點擊整個過程,而是跟隨它。 然後我們在此基礎上建立了自動化。
  • 等等,分析一下,搞清楚。
    我們花了大約一個月的時間來制定程序、技術實施、會議和討論。 而實施需要三個多月的時間。 我看到人們如何慢慢開始使用這項創新。 早期階段存在著許多負面情緒。 但它完全獨立於程式本身及其技術實現。 例如,一位管理員沒有使用Jira,而是Confluence中的Jira插件,有些東西他無法使用。 我們向他展示了 Jira,管理員的一般任務和更換磁碟的工作效率都提高了。

磁碟更換自動化

我們多次嘗試實現磁碟更換的自動化。 我們已經有了開發和腳本,但它們都以互動方式或手動方式工作,並且需要啟動。 只有在引入新程式後,我們才意識到這正是我們所缺少的。

由於現在我們的替換流程分為多個階段,每個階段都有一個特定的執行者和一系列操作,因此我們可以分階段啟用自動化,而不是一次全部啟用。 例如,最簡單的階段 - 就緒(檢查 RAID/資料同步)可以輕鬆委託給機器人。 當機器人學到了一些知識後,您可以給它一個更重要的任務 - 讓磁碟旋轉等。

動物園設置

在討論機器人之前,讓我們先參觀一下我們的裝置動物園。 首先,這是由於我們的基礎設施規模龐大。 其次,我們嘗試為每個服務選擇最佳的硬體配置。 我們有大約20種硬體RAID型號,主要是LSI和Adaptec,但也有HP和DELL的不同版本。 每個 RAID 控制器都有自己的管理實用程式。 對於每個 RAID 控制器,命令集及其發出可能因版本而異。 在不使用 HW-RAID 的情況下,可以使用 mdraid。

我們幾乎所有新安裝都沒有磁碟備份。 我們嘗試不再使用硬體和軟體 RAID,因為我們在資料中心層級備份系統,而不是伺服器。 但當然有許多遺留伺服器需要支援。

RAID 控制器中的磁碟在某些地方被轉移到原始設備,在某些地方使用了 JBOD。 伺服器中有一張系統盤的配置,如果需要更換,則必須重新安裝伺服器,安裝相同版本的作業系統和應用程序,然後添加配置文件,啟動應用程式。 還有很多伺服器群組的備份不是在磁碟子系統層級執行的,而是直接在應用程式本身中執行的。

我們總共擁有 400 多個獨特的伺服器群組,運行著近 100 個不同的應用程式。 為了涵蓋如此多的選項,我們需要一個多功能自動化工具。 最好使用簡單的 DSL,這樣不僅是編寫它的人可以支援它。

我們選擇 Ansible 是因為它是無代理的:無需準備基礎設施,快速啟動。 此外,它是用 Python 編寫的,Python 已被團隊內接受為標準。

一般計劃

讓我們以一個事件為例來看看一般的自動化方案。 Zabbix 偵測到 sdb 磁碟發生故障,觸發器亮起,並在 Jira 中建立票證。 管理員查看後,意識到這不是重複,也不是誤報,即需要更換磁碟,並將票證轉移到「進行中」。

使用 Ansible 自動更換磁碟
用 Python 編寫的 DiskoBot 應用程式會定期輪詢 Jira 以取得新票證。 它注意到出現了一個新的「正在進行」票證,相應的線程被觸發,這會在 Ansible 中啟動 playbook(這是針對 Jira 中的每個狀態完成的)。 在這種情況下,將啟動Prepare2change。

Ansible 被傳送到主機,從旋轉中刪除磁碟並透過回呼向應用程式報告狀態。

使用 Ansible 自動更換磁碟
根據結果,機器人會自動將機票轉移到「準備更改」。 工程師收到通知,去換盤,然後將工單轉給Changed。

使用 Ansible 自動更換磁碟
根據上述方案,票證回到機器人,機器人啟動另一個劇本,轉到主機並使磁碟旋轉。 機器人關閉票證。 萬歲!

使用 Ansible 自動更換磁碟
現在我們來談談系統的一些組件。

迪斯可機器人

該應用程式是用 Python 編寫的。 它根據 JQL 從 Jira 選擇票證。 根據票證的狀態,後者會轉到對應的處理程序,該處理程序會啟動與該狀態相對應的 Ansible playbook。

JQL 和輪詢間隔在應用程式設定檔中定義。

jira_states:
  investigate:
    jql: '… status = Open and "Disk Size" is EMPTY'
    interval: 180

  inprogress:
    jql: '…  and "Disk Size" is not EMPTY and "Device Name" is not EMPTY'
 
  ready:
    jql: '… and (labels not in ("dbot_ignore") or labels is EMPTY)'
    interval: 7200

例如,在「處理中」狀態的工單中,僅選擇填寫了「磁碟大小」和「裝置名稱」欄位的工單。 設備名稱是執行劇本所需的區塊設備的名稱。 需要磁碟大小,以便工程師知道需要什麼大小的磁碟。

在就緒狀態的工單中,帶有 dbot_ignore 標籤的工單將會被過濾掉。 順便說一句,我們使用 Jira 標籤進行此類過濾以及標記重複票證和收集統計數據。

如果 playbook 失敗,Jira 會指派 dbot_failed 標籤,以便稍後對其進行排序。

與 Ansible 的互通性

應用程式透過以下方式與 Ansible 通訊 Ansible Python API。 我們向 playbook_executor 傳遞檔案名稱和一組變數。 這允許您以常規 yml 檔案的形式保留 Ansible 項目,而不是用 Python 程式碼描述它。

同樣在 Ansible 中,透過 *extra_vars*、區塊裝置的名稱、票證的狀態以及包含問題金鑰的回呼_url - 它用於 HTTP 中的回調。

每次啟動時,都會產生一個臨時清單,其中包含一台主機和該主機所屬的群組,以便套用 group_vars。

以下是實作 HTTP 回呼的任務範例。

我們使用回調來獲得執行劇本的結果。 它們有兩種類型:

  • Ansible 回呼插件,它提供有關 playbook 執行結果的數據。 它描述了已啟動、成功完成或不成功的任務。 當劇本播放完畢時,會呼叫此回調。
  • 用於播放 playbook 時接收訊息的 HTTP 回呼。 在 Ansible 任務中,我們對應用程式執行 POST/GET 請求。

變數透過 HTTP 回調傳遞,這些回呼是在 playbook 執行期間定義的,我們希望在後續運行中保存和使用這些變數。 我們將這些資料寫入 sqlite 中。

我們也透過 HTTP 回調留下評論並更改票證狀態。

HTTP回呼

# Make callback to Diskobot App
# Variables:
#    callback_post_body: # A dict with follow keys. All keys are optional
#       msg: If exist it would be posted to Jira as comment
#       data: If exist it would be saved in Incident.variables
#       desire_state: Set desire_state for incident
#       status: If exist Proceed issue to that status

  - name: Callback to Diskobot app (jira comment/status)
    uri:
      url: "{{ callback_url }}/{{ devname }}"
      user: "{{ diskobot_user }}"
      password: "{{ diskobot_pass }}"
      force_basic_auth: True
      method: POST
      body: "{{ callback_post_body | to_json }}"
      body_format: json
    delegate_to: 127.0.0.1

與許多相同類型的任務一樣,我們將其放在單獨的公開文件中,並在必要時將其包含在內,以免在劇本中不斷重複。 這包括callback_ url,其中包含問題金鑰和主機名稱。 當 Ansible 執行此 POST 請求時,機器人知道它是某個事件的一部分。

這是劇本中的一個範例,其中我們從 MD 設備輸出磁碟:

  # Save mdadm configuration
  - include: common/callback.yml
    vars:
      callback_post_body:
        status: 'Ready to change'
        msg: "Removed disk from mdraid {{ mdadm_remove_disk.msg | comment_jira }}"
        data:
          mdadm_data: "{{ mdadm_remove_disk.removed }}"
          parted_info: "{{ parted_info | default() }}"
    when:
      - mdadm_remove_disk | changed
      - mdadm_remove_disk.removed

此任務將 Jira 票證轉移到「準備更改」狀態並新增評論。 此外,mdam_data 變數儲存從中刪除磁碟的 md 裝置列表,parted_info 儲存來自parted 的分割區轉儲。

當工程師插入新磁碟時,我們可以使用這些變數來還原分割區轉儲,以及將磁碟插入到從中刪除的 md 裝置中。

Ansible 檢查模式

打開自動化是很可怕的。 因此,我們決定在該模式下運行所有劇本
空運行,其中 Ansible 不會在伺服器上執行任何操作,而只是模擬它們。

這樣的啟動是透過單獨的回呼模組運行的,並且 playbook 執行的結果會作為註釋保存在 Jira 中。

使用 Ansible 自動更換磁碟

首先,這使得驗證機器人和劇本的工作成為可能。 其次,它增加了管理員對機器人的信心。

當我們通過驗證並意識到您不僅可以在試運行模式下運行 Ansible 時,我們在 Jira 中創建了一個 Run Diskobot 按鈕,以在同一主機上但在正常模式下啟動具有相同變數的相同 playbook。

此外,該按鈕也用於在 Playbook 崩潰時重新啟動。

劇本結構

我已經提到過,根據 Jira 票證的狀態,機器人會啟動不同的劇本。

首先,組織入口要容易得多。
其次,在某些情況下這是完全必要的。

例如,更換系統磁碟時,首先需要進入部署系統,建立任務,正確部署後,伺服器就可以透過ssh訪問,並且可以將應用程式部署到伺服器上。 如果我們在一本劇本中完成所有這些工作,那麼 Ansible 將無法完成它,因為主機無法使用。

我們為每組伺服器使用 Ansible 角色。 在這裡您可以看到劇本在其中一本中的組織方式。

使用 Ansible 自動更換磁碟

這很方便,因為可以立即清楚哪些任務位於何處。 在作為 Ansible 角色的輸入的 main.yml 中,我們可以簡單地包含每個人所需的票證狀態或一般任務,例如傳遞身分或接收令牌。

調查.yml

在調查和開放狀態下運行票證。 對於本劇本來說,最重要的是塊設備名稱。 此資訊並不總是可用。

為了取得它,我們分析 Jira 摘要,即 Zabbix 觸發器的最後一個值。 它可能包含塊設備的名稱 - lucky。 或者它可能包含一個掛載點,那麼你需要去伺服器,解析它併計算所需的磁碟。 觸發器還可以傳輸 scsi 位址或一些其他資訊。 但也有可能沒有線索,就得分析。

找到區塊設備的名稱後,我們從中收集有關磁碟類型和大小的資訊以填寫 Jira 中的欄位。 我們還刪除了有關供應商、型號、韌體、ID、SMART 的信息,並將所有這些資訊插入 Jira 票證的評論中。 管理員和工程師不再需要搜尋這些數據。 🙂

使用 Ansible 自動更換磁碟

準備2change.yml

將磁碟從旋轉中取出,準備更換。 最困難也是最重要的階段。 您可以在此處停止不應停止的應用程式。 或取出沒有足夠副本的磁碟,從而對使用者產生影響,並遺失一些資料。 這裡我們在聊天中擁有最多的檢查和通知。

在最簡單的情況下,我們討論的是從 HW/MD RAID 中刪除磁碟。

在更複雜的情況下(在我們的儲存系統中),當在應用程式層級執行備份時,您需要透過 API 轉到應用程序,報告磁碟輸出,停用它並開始恢復。

我們現在正在集體遷移到 ,如果伺服器是基於雲端的,則 Diskobot 會呼叫雲端 API,表示它將與該 Minion(運行容器的伺服器)一起工作,並要求「從該 Minion 遷移所有容器」。 同時,打開磁碟的背光,以便工程師可以立即看到需要拔出哪一個。

更改.yml

更換磁碟後,我們首先檢查其可用性。

工程師並不總是安裝新驅動器,因此我們添加了對令我們滿意的 SMART 值的檢查。

我們正在尋找哪些屬性?重新分配的磁區數 (5) < 100
目前待處理扇區計數 (107) == 0

如果驅動器未通過測試,則會通知工程師再次更換。 如果一切正常,背光將關閉,標記將被應用,光碟將開始旋轉。

準備好.yml

最簡單的情況:檢查HW/SW raid同步或在應用程式中完成資料同步。

應用程式介面

我已經多次提到機器人經常存取應用程式 API。 當然,並非所有應用程式都有必要的方法,因此必須對其進行修改。 以下是我們使用的最重要的方法:

  • 地位。 集群或磁碟的狀態,以了解其是否可以使用;
  • 開始/停止。 磁碟啟動/停用;
  • 遷移/恢復。 更換期間和更換後的資料遷移和恢復。

從 Ansible 中學到的經驗教訓

我真的很喜歡 Ansible。 但通常,當我查看不同的開源專案並看到人們如何編寫劇本時,我會有點害怕。 複雜的when/loop邏輯交織,由於頻繁使用shell/命令而缺乏靈活性和冪等性。

我們決定利用 Ansible 的優勢——模組化,盡可能地簡化一切。 在最高層級有劇本;它們可以由任何管理員、了解一點 Ansible 的第三方開發人員編寫。

- name: Blink disk
  become: True
  register: locate_action
  disk_locate:
      locate: '{{ locate }}'
      devname: '{{ devname }}'
      ids: '{{ locate_ids | default(pd_id) | default(omit) }}'

如果某些邏輯難以在 playbook 中實現,我們會將其移至 Ansible 模組或過濾器中。 腳本可以用 Python 或任何其他語言編寫。

它們寫起來既簡單又快速。 例如,如上所示的碟式背光模組由265條線組成。

使用 Ansible 自動更換磁碟

最底層是圖書館。 對於這個項目,我們編寫了一個單獨的應用程序,這是執行相應請求的硬體和軟體 RAID 的抽象。

使用 Ansible 自動更換磁碟

Ansible 的最大優點在於其簡單性和清晰的劇本。 我相信您需要使用它,而不是生成可怕的 yaml 檔案和大量條件、shell 程式碼和循環。

如果您想重複我們使用 Ansible API 的體驗,請記住兩件事:

  • Playbook_executor 和 playbook 通常無法設定逾時。 ssh 會話有逾時,但 playbook 上沒有逾時。 如果我們嘗試卸載系統中不再存在的磁碟,則 playbook 將無休止地運行,因此我們必須將其啟動包裝在一個單獨的包裝器中,​​並透過逾時終止它。
  • Ansible 運行在分叉進程上,因此它的 API 不是線程安全的。 我們所有的劇本都是單執行緒運行的。

結果,我們能夠自動更換大約 80% 的磁碟。 總體而言,替代率翻了一番。 今天管理員只要看一下事件,決定是否需要更換磁碟,然後一鍵點擊即可。

但現在我們開始遇到另一個問題:有些新管理員不知道如何更改磁碟機。 🙂

來源: www.habr.com

添加評論