解讀基礎設施即代碼

現代軟件開發對基礎設施的管理提出了更苛刻的要求。產品要適應瞬息萬變的市場,要求基礎設施要有更快的響應速度。而持續交付和DevOps的推行要求產品團隊對部署和運維要有更高的自主性。技術的快速進步和演化,也使得基礎設施的配置不得不頻繁變化。在這種快速變化的過程當中,要求基礎設施既要靈活,也要安全、可靠。nginx

而傳統的基礎設施運維管理具備如下幾個問題。apache

  • 被動響應。 產品團隊獲取服務器資源採用的是申請制,中間存在若干審批過程,以及須要等待運維團隊實施,響應不及時。ubuntu

  • 自動化缺少串聯。雖然有必定的自動化,但不能作到無人值守,須要執行一些臨時命令介入。因爲環境釋放和重建的成本高,於是傾向於不釋放,致使資源利用率低。安全

  • 和產品團隊脫節。很難根據需求隨時動態增長環境。須要額外的文檔來描述環境,可能更新不及時。服務器

產品團隊是實施持續交付的過程當中,必須考慮將基礎設施的維護歸入進來,做爲支持產品運行的一部分。如下是產品團隊的持續交付流水線全景圖。網絡

從上圖能夠看出,產品團隊除了管理項目自己代碼外,還要管理環境定義腳本。環境定義腳本能夠由基礎設施自動化工具執行,動態建立和銷燬和更新產品運行所需的環境(包括服務器、負載均衡器、防火牆配置、第三方依賴等)。架構

若是實現了這一點,那麼就實現了基礎設施即代碼的雛形。Kief在《Infarftruce As Code》一書中對基礎設施即代碼定義以下:負載均衡

基礎設施即代碼是一種使用新的技術來構建和管理動態基礎設施的方式。它把基礎設施、工具和服務以及對基礎設施的管理自己做爲一個軟件系統,採納軟件工程實踐以結構化的安全的方式來管理對系統的變動。運維

基礎設施即代碼有四項關鍵原則。工具

  • 再生性。

環境中的任何元素能夠輕鬆複製。

  • 一致性。 不管什麼時候,建立的環境各個元素的配置是徹底相同的。

  • 快速反饋。 可以頻繁、容易地進行變動,並快速知道變動是否正確。

  • 可見性。 全部對環境的變動應該容易理解,可審計,受版本控制。

基礎設施即代碼的目標是:

  • 標準化。 以代碼來定義環境,實現開發環境、測試環境、生產環境的標準化。

  • 自動化。 以自動化工具來驅動代碼準備環境。包括建立環境、更新環境以及銷燬環境。

  • 可視化。 以監控來可視化環境信息。環境當前狀態可視、環境變動歷史可視、可追溯。

基礎設施即代碼實踐會產生高成熟度的持續交付和DevOps。

在實施基礎設施即代碼時,要遵照如下實踐。

  • 使用DSL描述環境。

Ansible、Chef、SaltStack、Terraform等基礎設施自動化工具都有各自的描述性語言實現對基礎設施的定義。使用DSL更容易經過描述性的語言定義基礎設施,也有助於代碼重用。團隊成員能創建起共同理解,從而維護腳本。

如下是Ansible的一個playbook示例。

1
2
3
4
5
6
7
8
9
10
11
--- - hosts: local  tasks:  - name: Install Nginx  apt: pkg=nginx state=installed update_cache=true  notify:  - Start Nginx   handlers:  - name: Start Nginx  service: name=nginx state=started 
  • 自測試系統。

在編寫環境代碼的配置時,也要編寫對環境的測試。確保全部服務器都正確進行了配置,遵照了全部的安全規則,網絡連通性等進行了驗證。咱們通常提倡將測試代碼和配置代碼放在一塊兒維護。這樣配置代碼更新的化,能保證測試代碼也被及時更新。

一些典型的基礎設施自動化測試工具備ServerSpec、Testinfra等。如下是一個ServerSpec的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 require 'spec_helper'  describe package('httpd'), :if => os[:family] == 'redhat' do  it { should be_installed } end  describe package('apache2'), :if => os[:family] == 'ubuntu' do  it { should be_installed } end  describe service('httpd'), :if => os[:family] == 'redhat' do  it { should be_enabled }  it { should be_running } end  describe service('apache2'), :if => os[:family] == 'ubuntu' do  it { should be_enabled }  it { should be_running } end  describe service('org.apache.httpd'), :if => os[:family] == 'darwin' do  it { should be_enabled }  it { should be_running } end  describe port(80) do  it { should be_listening } end 
  • 一切進行版本化。

一旦採用了環境定義腳本實現對環境的控制後,須要將環境定義腳本歸入到版本管理中。而且以後全部的環境變動都應該先修改環境定義腳本,由環境定義腳本觸發對環境的變動。登陸到服務器執行一些臨時性命令是被堅定禁止的。由於這極有可能會破壞環境的一致性。當重建服務器時,也不能保證能應用全部須要的變動。

下圖是基礎設施即代碼的一個典型使用場景。

除此以外,若是想要在生產環境中建立可伸縮性的服務的話,也須要藉助機艙設施即代碼這一實踐。在高峯時期,系統能夠根據定義的環境自動建立並加入新的節點實現動態擴容,並在低峯時將其銷燬。當監控發現某節點失敗,系統能夠根據定義的環境自動建立新的節點來替換失敗節點,實現自動災難恢復。

最後是咱們在某團隊實施基礎設施即代碼的案例解析。這張圖是某團隊的基礎設施架構圖。

該團隊使用AWS做爲基礎設施平臺。咱們選用ansible做爲基礎設施自動化工具,並結合AWS提供的cloudformation服務實現快速建立和銷燬資源。全部網元都有清晰的角色劃分,配套對應的配置腳本。從網絡配置到網元配置以及應用配置都實現了全自動化。全部的配置腳本都和源代碼一塊兒託管在GitHub。團隊全部成員均可以查看並修改。

相關文章
相關標籤/搜索