1. 程式人生 > 其它 >容器運維模式(一)-- 概述

容器運維模式(一)-- 概述

其實我挺早就接觸Docker和Kubernetes,時間大概在3、4年前吧,但是由於當時所在技術團隊的業務模式所限制,還沒有真正對容器雲的技術需求,所以我更多還是以一種技術玩具的心態接觸容器技術。

直到去年開始才正式接觸基於容器雲平臺的技術架構,我從業務運維和DevOps的角度來看,和之前的物理機和虛擬機器等IaaS層基礎上的運維模式有著非常大的差異。

根據這段時間的運維經驗,我嘗試總結一下某些容器雲的運維方法的共同特性,並將其稱為“容器運維模式”,簡單百度谷歌了一下,沒有這個名詞,希望是我的首創~

這個名詞靈感來自軟體工程的“設計模式”,設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、經過分類的、程式碼設計經驗的總結。使用設計模式的目的:為了程式碼可重用性、讓程式碼更容易被他人理解、保證程式碼可靠性。 設計模式使程式碼編寫真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。

而“容器運維模式”,指的是由DevOps(題外話:DevOps、SRE、SA、運維 等等,其實都差不多是同一個意思,業界喜歡創一個新的名詞來代替運維,主要是為了區分自己和一些低端系統維護人員)在日常運維容器化專案的一些經驗總結,為了區別於傳統的物理機、虛擬機器的運維套路,而歸納出來的容器運維方法。

回顧過去

從大概10年前,大家都是以【自建IDC】+【物理伺服器】的形式進行生產環境基礎架構的建設;

然後持續到大概5年前,私有云技術和公有云的興起,讓大批中小型企業減少對物理裝置資源建設的人力和資金投入,可以專注於業務研發和運營;

最後到大概3、4年前,容器技術 Docker 和以 Kubernetes 為代表的容器編排技術的崛起,以及微服務技術的同步普及,宣告了容器雲平臺的來臨;

而事實上,以Kubernetes為首的相關周邊專案,已經成為了容器雲領域的首選標準,所以絕大部分技術團隊如果現在需要選型容器編排體系,可以無腦選k8s了。

需求的根本--應用交付

在傳統裸機(bare metal)或虛擬化的時代,當開發團隊將程式碼交付給運維進行生產環境中部署,但是它卻未能正常工作時,挑戰就出現了。

“執行環境不一致”、“沒有安裝相關依賴軟體”、“配置檔案不一樣”等等已經成了開發和運維溝通的慣用語。

在傳統的開發場景中,開發和測試團隊使用的是與生產環境不同的基礎設施,儘管做到了程式碼和配置解耦,但是在執行環境的轉換中,依然會得到像前面所述的團隊協作和環境依賴問題

而貫穿軟體生命週期共享相同的容器映象是容器化帶來的最大好處,它簡化了開發與運維團隊之間的協作關係

由於本地開發/測試伺服器和生產環境的不一致以及應用程式打包部署的過程,一直是讓研發和運維糾結的難題,但有了容器之後,由於容器映象裡打包的不僅是應用,而是整個作業系統的檔案和目錄,即是其執行所需的所有依賴,都能被封裝一起。

有了容器映象的打包能力之後,這些應用程式所需的基礎依賴環境,也成為了這個應用沙盒的一部分,這可以給這個應用包賦予這樣的能力:無論在開發、測試還是生產環境執行,我們只需要解壓這個容器映象,那麼這個應用所需的所有執行依賴都是存在的、一致的。

如果熟悉Docker容器技術原理的話,我們知道它主要由Linux核心的Namespace和CGroups以及rootfs技術隔離出來一種特殊程序。把docker形容為一個房子的話,namespace構成了四面牆,為PID\NET\MNT\UTS\IPC等資源進行隔離;而CGroups形成了它的天花板,限制了對系統資源的佔用;而rootfs是其地基,是通過copy-on-write機制構成的分層映象,也是開發者最為關心的應用資訊的傳遞載體。作為開發者,他們可能不關心由前兩者構成的容器執行時的環境差異,因為真正承載容器化應用的傳遞載體,這是這個不變的容器映象。

在Docker技術的普及後不久,為了整個完整的DevOps鏈條的打通,包括CI/CD、監控、網路、儲存、日誌收集等生產環境的剛需,以及整個容器生命週期的管理和排程,以Kubernetes為首的容器編排體系也作為上層建築也迎來了一波快速的增長。從容器到容器雲的蛻變,標誌著容器運維時代的來臨。


容器運維模式的主要場景分析

1、宣告式 vs 命令列

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.12.2
        ports:
        - containerPort: 80

我們知道Kubernetes是通過yaml檔案(樣例如上所示)來對其API物件,如Deployment、Pod、Service、DaemonSet等進行期望狀態的描述,然後k8s的控制器有一套狀態調諧的機制讓各種API物件按要求所述的狀態執行。由於這樣一套執行機制的存在,所以使得k8s和過往運維常見的命令列,也包括指令碼式的執行方式有著很大的差異。

深度使用過puppet的運維工程師可能會比較清楚兩者的區別,puppet也是一套基於宣告式機制的配置管理和狀態管理的工具。在沒有puppet之前,運維工程師喜歡用簡單的shell、python指令碼對眾多伺服器進行統一的軟體安裝、配置管理,但隨著伺服器數量增多和配置項的遞增,命令列式的配置管理往往出現各種缺陷。如狀態不一致、歷史版本無法回滾、配置沒有冪等性、需要很多狀態判斷才能執行最終的操作等等。

而宣告式的配置管理方法,可以規避以上弊端,原因如下:

當我們確認了一個版本yaml配置檔案後,表示向k8s的Kube-Controller-Manager提交了我們所期望的物件狀態資訊,然後k8s使用patch的方式對API物件進行修改。而宣告式API是k8s專案編排能力的核心所在,它可以在無需干預的情況下對api物件進行增刪改查,完成對“期望狀態”和“實際狀態”的reconcile過程。

以我們最常用的deployment物件為例,

方式一:

$ kubectl apply -f deploy-ooxx.yaml

方式二:

首次建立使用 create ,修改yaml使用edit,然後用replace使之生效。

k8s對這兩種機制的處理方法是完全不同的,前者是宣告式,後者是命令式。

兩者的結果雖然都是觸發滾動更新,但是前者是對原有API物件打patch,後者是物件的銷燬和替換。前者能一次處理多個yaml配置變更的寫操作並具備相同配置項的merge能力,後者只能逐個處理,否則有衝突的可能。

所以,我們只需要確認yaml檔案的版本,一律通過 kubectl apply 命令進行執行,無需再考慮第一步建立、第二步修改、第三部替換之類的命令列。那麼我們統一用apply命令,可以通過history命令進行回溯版本,也可以保證apply的結果的冪等性等等。

使用宣告式只需要描述最終所需的狀態,無需使用者關心過多的實現流程和細節,沒有像買二手遊戲地圖命令列式的那麼多上下文關係或者執行環境依賴,甚至可以由開發人員直接編寫,運維進行code review即可。特別在使用Kubernetes這樣的容器編排工具,更加要深刻理解和靈活運用宣告式的運維模式。

2、API物件

Hi峰叔:容器運維模式(二)-- API物件​zhuanlan.zhihu.com

3、控制器模式

Hi峰叔:容器運維模式(三)-- 控制器模式​zhuanlan.zhihu.com

4、介面和實現

Hi峰叔:容器運維模式(四)-- 介面與實現​zhuanlan.zhihu.com

5、Master-Node & Api-server

Hi峰叔:容器運維模式(五)-- Master-Node & Api-Server​zhuanlan.zhihu.com

總結

從過去的【單體式應用+物理機】,到現在【微服務應用+容器雲】的執行環境的變革,需要運維工程師同步改變以往的運維技術思維。新技術的應用,會引發更深層次的思考,深入瞭解容器之後,我們會自然而然地會去學習業務最主流的編排工具--Kubernetes。

Kubernetes前身是谷歌的 Borg 容器編排管理平臺,它充分體現了谷歌公司多年對編排技術的最佳實踐。而容器雲字面意思就是容器的雲,實際指的是以容器為單位,封裝環境、提供構建、釋出、執行分散式應用平臺。

而運維工程師在面對業界更新迭代極快的技術潮流下,需要選定一個方向進行深耕,無疑,Kubernetes是值得我們去深入學習的,畢竟它戰勝了幾乎所有的編排排程工具,成為業內編排標準。我們通過搭建容器雲環境下的應用執行平臺,並實現運維自動化,快速部署應用、彈性伸縮和動態調整應用環境資源,提高研發運營效率,最終實現自身的運維價值。

以上是筆者的一些淺薄的學習體會,希望可以給大家一個參考~