返回文章列表

Kubernetes 容器隔離與協調實踐

本文探討容器隔離在微服務架構中的重要性,並解析 Kubernetes 如何解決生產環境的容器管理挑戰。從容器引擎的基礎知識到 Kubernetes 的核心概念,文章涵蓋了容器技術的發展歷程、優勢以及 Kubernetes 的實踐應用。同時,也介紹了 KubeVirt 如何橋接容器和虛擬機器,以及 Kubernetes

容器技術 雲原生

容器技術的興起,尤其是 Docker 的普及,極大簡化了微服務的佈署和管理。容器的輕量級特性和隔離性,使其成為微服務架構的理想選擇。然而,單純使用容器引擎在生產環境中仍面臨諸多挑戰,例如擴充套件性、災難復原和安全性等。Kubernetes 作為一個生產級容器協調平台,有效地應對了這些挑戰。它提供自動化佈署、擴充套件、網路管理和安全策略等功能,簡化了容器化應用在生產環境中的維運。此外,KubeVirt 的出現,更進一步擴充套件了 Kubernetes 的能力,使其能管理虛擬機器,為混合雲環境提供了更靈活的解決方案。

容器隔離的重要性與 Kubernetes 的基礎

瞭解容器隔離的優勢

容器引擎如 Docker 和 Podman 在管理微服務方面扮演著至關重要的角色。與需要完整客戶作業系統的虛擬機器(VM)不同,容器是輕量級的單元,它們分享主機的 Linux 核心。這使得它們比虛擬機器啟動和停止的速度更快。容器引擎提供了一個友好的 API,用於建置、佈署和管理容器。它們並沒有引入額外的虛擬化層,而是利用 Linux 核心的內建功能進行程式隔離、安全性和資源分配。這種高效的方法使容器化成為佈署微服務的一種極具吸引力的解決方案。

下圖展示了容器與虛擬機器的區別: 此圖示顯示了虛擬機器和容器之間的差異

您的微服務將在這個層上啟動,而不是直接在主機系統上,而主機系統的唯一角色是執行您的容器。

由於容器是隔離的,您可以執行任意數量的容器,並讓它們執行不同語言編寫的應用程式,而不會產生任何衝突。微服務的重新佈署變得就像停止一個正在執行的容器,並在另一台機器上從同一個映像啟動另一個容器一樣簡單。

容器化的優勢

使用容器與微服務提供了三個主要優勢:

  • 減少了對主機系統的佔用。
  • 在不同的微服務之間實作了主機系統的分享而不會產生衝突。
  • 消除了微服務與主機系統之間的耦合。

一旦微服務被容器化,您就可以消除它與主機作業系統之間的耦合。微服務將只依賴於它將要執行的容器。由於容器比真正的全功能 Linux 作業系統輕得多,因此它將很容易在許多不同的機器上分享和佈署。因此,容器和您的微服務將能夠在任何執行容器引擎的機器上工作。

下圖展示了一個微服務架構,其中每個微服務都被一個容器包裹: 此圖示展示了一個微服務應用程式,其中所有的微服務都被容器包裹;應用程式的生命週期與容器繫結,並且很容易將其佈署在任何執行容器引擎的機器上

內容解密:

  1. 減少佔用:容器分享主機的核心,不需要像虛擬機器那樣為每個例項都安裝一個完整的作業系統,因此佔用資源較少。
  2. 避免衝突:不同的微服務可以在不同的容器中執行,避免了依賴衝突的問題。
  3. 消除耦合:微服務被封裝在容器中,使其能夠在任何安裝了容器引擎的機器上執行,無需擔心環境差異。

容器引擎的侷限性

儘管 Docker 或 Podman 等容器引擎本身是非常好的工具,但您會發現很難單獨在生產環境中使用它們。

開發環境中的優勢

  • 簡單性:容器引擎易於安裝和使用,使開發人員能夠快速建置、測試和執行容器化應用程式。
  • 靈活性:開發人員可以使用容器引擎來嘗試不同的容器組態,探索容器化的世界。
  • 隔離性:容器引擎確保應用程式之間的隔離,避免衝突,簡化除錯。

生產環境中的挑戰

  • 擴充套件性:Docker 或 Podman 等容器引擎不提供內建的自動擴充套件功能,以根據資源利用率動態調整容器佈署。
  • 災難復原:容器引擎不提供全面的災難復原能力,以確保在中斷情況下保持服務可用性。
  • 安全性:雖然容器引擎提供基本的隔離,但管理跨多台機器的規模化容器化佈署的安全策略可能具有挑戰性。
  • 標準化:容器引擎需要自定義指令碼或整合來與外部系統(如 CI/CD 管道或監控工具)互動。

Kubernetes 的作用

Kubernetes 是一個強大的容器協調平台,能夠應對生產環境中的挑戰。它管理整個容器的生命週期,從將它們排程到可用資源上執行,到根據需求擴充套件或縮減佈署,以及分配流量以實作最佳效能(負載平衡)。與使用容器引擎進行自定義指令碼不同,Kubernetes 提供了一個定義良好的 API,用於與容器化應用程式互動,簡化了與生產環境中使用的其他工具的整合。除了基本的隔離之外,Kubernetes 還提供了諸如根據角色的存取控制和網路策略等先進的安全功能。

這使得能夠在同一基礎架構上高效管理來自多個團隊或專案的容器化工作負載,最佳化資源利用率並簡化複雜的佈署。

程式碼範例:使用 Kubernetes 佈署一個簡單的應用程式

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

內容解密:

  1. apiVersionkind:定義了 Kubernetes 資源的版本和型別,這裡是一個 Deployment。
  2. metadata:提供了關於 Deployment 的後設資料,如名稱。
  3. spec:描述了 Deployment 的期望狀態,包括副本數量、選擇器和範本。
  4. replicas: 3:指定了應該執行的應用程式副本數量,這裡是 3 個。
  5. selectortemplate:定義了 Deployment 管理哪些 Pod,以及如何建立這些 Pod。
  6. containers:列出了 Pod 中的容器,這裡只有一個名為 example-app 的容器,使用 example-app:latest 映象,並暴露了 80 埠。

透過這個簡單的例子,您可以看到 Kubernetes 如何簡化應用程式的佈署和管理。Kubernetes 不僅提供了強大的自動化功能,還確保了應用程式的高用性和可擴充套件性,使其成為現代雲原生應用的理想選擇。

容器引擎與容器基礎知識

在容器化技術中,容器引擎扮演著至關重要的角色。它作為使用者與REST客戶端的介面,負責管理使用者輸入、從容器登入檔中下載容器映像、將下載的映像解壓到磁碟上、轉換使用者或REST客戶端的資料以與容器引擎互動、準備容器掛載點,以及促進與容器引擎的通訊。簡單來說,容器引擎是使用者與容器技術之間的橋樑,簡化了映像和容器的管理,而底層的容器執行時則處理容器和映像管理的複雜細節。

容器引擎的多樣性

Docker 是目前最廣泛採用的容器引擎之一,但除此之外,還有多種其他的容器引擎可供選擇,例如 LXD、Rkt、CRI-O 和 Podman 等。這些不同的容器引擎為使用者提供了多樣化的選擇,以滿足不同的需求和環境。

Docker 的核心元件

Docker 的核心是 containerd 容器執行時,它負責管理容器的生命週期、映像傳輸和儲存、執行和監控,以及儲存和網路附件。containerd 進一步依賴於 runc 和 hcsshim 等元件。runc 是一個命令列工具,用於在 Linux 上建立和執行容器,而 hcsshim 則在 Windows 容器的建立和管理中發揮著關鍵作用。

值得注意的是,containerd 通常不設計為直接與終端使用者互動。相反,容器引擎(如 Docker)與容器執行時互動,以促進容器的建立和管理。runc 的基本角色顯而易見,不僅服務於 containerd,也被 Podman、CRI-O 和 Docker 等使用。

容器的基本概念

容器映像

容器映像是一種範本,用於啟動容器。它是一個自包含的可執行套件,封裝了應用程式及其依賴項,包括執行程式碼、執行環境、函式庫和系統工具等。容器映像是透過 Dockerfile 或 Containerfile 建立的,這些檔案指定了構建步驟。

# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

Dockerfile 解讀

  1. # syntax=docker/dockerfile:1:定義了用於構建映像的 Dockerfile 語法版本。
  2. FROM node:18-alpine:指定了容器的基礎映像,使用官方的 Node.js 18 映像與 Alpine Linux 基礎,提供了一個輕量且高效的應用程式基礎。
  3. WORKDIR /app:設定了容器內的工作目錄為 /app,後續的命令將相對於此目錄執行。
  4. COPY . .:將當前上下文(Dockerfile 所在目錄)中的所有檔案和目錄複製到工作目錄 /app 中,實質上是將整個應用程式碼函式庫複製到容器中。
  5. RUN yarn install --production:在容器內執行命令,使用 yarn 套件管理器安裝 package.json 中列出的生產依賴項,--production 旗標確保只安裝生產依賴項,而不包括開發依賴項。

容器

容器可以被視為容器映像的執行例項。它們將應用程式的程式碼、依賴項和執行環境封裝成一個單一、輕量級的套件。由於包含了執行所需的一切,因此容器能夠在不同環境中一致地執行。每個容器獨立執行,避免了與同一系統上其他應用程式的衝突。容器分享主機作業系統的核心,因此比虛擬機器更快地啟動和停止。

容器登入檔

容器登入檔是一個集中式的儲存函式庫,用於儲存和分享容器映像。它作為分發機制,允許使用者將映像推播到登入檔或從登入檔中提取映像。流行的公共登入檔包括 Docker Hub、Red Hat Quay、Amazon 的 Elastic Container Registry(ECR)、Azure Container Registry、Google Container Registry 和 GitHub Container Registry。組織通常使用私有登入檔來安全地儲存和分享自定義映像。登入檔在 Docker 生態系統中扮演著至關重要的角色,促進了協作和對容器化應用程式的高效管理。

總之,瞭解容器引擎和容器的基本概念對於掌握容器化技術至關重要。無論是 Docker 還是其他容器引擎,它們都在簡化應用程式的佈署和管理方面發揮著重要作用。透過深入瞭解 Dockerfile 的編寫和容器的運作原理,開發者可以更有效地利用容器技術來提高開發效率和應用程式的可移植性。

Kubernetes 管理容器:生產級的容器協調

在前一章中,我們探討了容器技術以及 Docker 的基本操作。現在,我們將深入瞭解 Kubernetes 如何幫助您高效地管理和協調容器。

為什麼需要 Kubernetes?

Kubernetes 是專為生產環境設計的容器協調平台。開啟官方 Kubernetes 網站(https://kubernetes.io),您會看到標題「Production-Grade Container Orchestration」,這四個單詞完美地總結了 Kubernetes 的定位:它是一個用於生產環境的容器協調平台。

Kubernetes 的核心價值

Kubernetes 並不是要取代 Docker 或其他容器引擎,而是旨在管理執行容器執行時的機器叢集。在使用 Kubernetes 時,您會同時使用 Kubernetes 和完整的容器執行時標準安裝。

生產環境的挑戰

如今,生產環境的工作負載管理與過去大不相同。過去,您的生產工作負載可能只包含幾台裸機伺服器,甚至只是一台本地伺服器,這些伺服器大多直接在主機 Linux 系統上執行單體應用。然而,現在藉助公有雲平台,如 Amazon Web Services(AWS)或 Google Cloud Platform(GCP),任何人都可以輕鬆獲得數百甚至數千台虛擬機器。

容器的管理挑戰

當您需要在雲端管理多台虛擬機器上的 Docker 安裝時,問題就出現了。假設您有 10 台(或 100 台,或 1,000 台)機器在您的首選雲端執行,並且您希望完成一項簡單的任務:在每台機器上佈署一個容器化的 Docker 應用程式。

您當然可以透過在每台機器上執行 docker run 命令來實作這一點,但這顯然不是最佳實踐。這時,像 Kubernetes 這樣的容器協調工具就派上用場了。簡而言之,Kubernetes 可以被視為一個 REST API,它維護著執行 Docker 守護程式的機器登入檔。

KubeVirt:連線容器和虛擬機器的橋樑

KubeVirt 是一個擴充套件 Kubernetes 功能的專案,允許使用者使用熟悉的 Kubernetes API 管理虛擬機器。這使得使用者能夠在佈署容器化應用程式的同時,利用 Kubernetes 的強大功能和靈活性來佈署虛擬機器。KubeVirt 採用了基礎設施即程式碼(IaC)的原則,讓使用者能夠在其 Kubernetes 清單中宣告式地定義和管理虛擬機器,從而簡化虛擬機器的管理,並將其無縫整合到現有的 Kubernetes 工作流程中。

透過將虛擬機器納入 Kubernetes 的管理之下,KubeVirt 為需要混合環境(同時包含容器和虛擬機器)的組織提供了一種令人信服的解決方案。這展示了 Kubernetes 作為一個能夠管理多樣化工作負載的平台的持續演進,可能會帶來更統一的應用程式佈署和管理方法。

Kubernetes 的歷史與發展

瞭解 Kubernetes 專案的歷史對於掌握其發展脈絡和背後的推動者至關重要。Kubernetes 的誕生源自 Google 在管理大規模、高需求工作負載方面的豐富經驗,尤其是在容器技術的應用上。

Kubernetes 的起源

自1998年成立以來,Google 在管理大規模工作負載方面積累了豐富的經驗,特別是在根據容器的工作負載管理。早在2000年代中期,Google 就開始將其應用程式開發為 Linux 容器。遠在 Docker 簡化容器使用之前,Google 就已經認識到容器化的優勢,並啟動了一個名為 Borg 的內部專案。為了增強 Borg 的架構,使其更加可擴充套件和強健,Google 發起了另一個容器協調器專案 Omega。隨後,Omega 引入的多項改進被納入 Borg 專案。

Kubernetes 作為 Google 的內部專案誕生,第一個提交記錄始於2014年,由 Brendan Burns、Joe Beda 和 Craig McLendon 等人共同完成。然而,Kubernetes 並非由 Google 獨立開源。Red Hat 的 Clayton Coleman 在其中扮演了關鍵角色,他極力倡導將 Kubernetes 開源,並確保其成功轉型為社群驅動的專案。CoreOS 的 Kelsey Hightower 成為 Kubernetes 的早期擁護者,透過演講、寫作和 KubeCon 的共同創辦,大大促進了 Kubernetes 的採用和社群成長。

如今,除了 Google 之外,Red Hat、Amazon、Microsoft 等公司也積極參與 Kubernetes 專案的貢獻。

Kubernetes 的技術基礎

Kubernetes 的開發源自 Google 管理生產環境中容器的經驗。最重要的是,它繼承了 Borg 和 Omega 的理念、概念和架構。以下是從 Borg 和 Omega 借鑒並在 Kubernetes 中實作的一些關鍵概念:

  • 使用 Pod 管理容器:Kubernetes 使用一個邏輯物件(Pod)來建立、更新和刪除容器。
  • 每個 Pod 在叢集中擁有自己的 IP 位址。
  • 分散式元件監控中央 Kubernetes API 以檢索叢集狀態。
  • Pod 和 Service 之間存在內部負載平衡。
  • 標籤(Labels)和選擇器(Selectors)是後設資料,用於共同管理和協調 Kubernetes 中的資源。

這些理念使 Kubernetes 在大規模管理容器方面極具優勢。儘管 Kubernetes 是一個相對年輕的專案,但它建立在堅實的基礎之上。

當前的 Kubernetes 管理

Kubernetes 已不再由 Google 維護,因為 Google 於2018年8月29日將 Kubernetes 專案的操作控制權移交給了雲原生計算基金會(CNCF)。CNCF 是一個非營利組織,旨在促進和維持雲原生技術的開放生態系統。Google 是 CNCF 的創始成員之一,其他成員包括 Cisco、Red Hat 和 Intel。Kubernetes 的原始碼託管在 GitHub 上,是該平台上極為活躍的專案。Kubernetes 的程式碼採用 Apache License 2.0,這是一種寬鬆的開源許可證。使用者無需支付費用即可使用 Kubernetes,若具備 Go 語言的程式設計能力,甚至可以為程式碼做出貢獻。

目前的 Kubernetes 生態

在容器協調領域,Kubernetes 面臨來自多種替代方案的競爭,包括開源解決方案和特定平台的產品。一些值得注意的競爭者包括:

  • Apache Mesos
  • HashiCorp Nomad
  • Docker Swarm
  • Amazon ECS

儘管每個協調器都有其自身的優缺點,Kubernetes 仍是目前最廣泛採用和流行的選擇。

Kubernetes 已贏得流行度和採用率的勝利,成為佈署根據容器的生產工作負載的標準方式。由於其巨大的成長,使其成為 IT 界最熱門的話題之一,雲端服務供應商紛紛推出 Kubernetes 服務。因此,現在幾乎所有地方都支援 Kubernetes。

以下根據 Kubernetes 的服務可以幫助您輕鬆啟動和執行 Kubernetes 叢集:

  • Google Cloud Platform 上的 Google Kubernetes Engine(GKE)
  • Amazon Elastic Kubernetes Service(Amazon EKS)
  • Microsoft Azure 上的 Azure Kubernetes Service
  • 阿里雲容器服務 for Kubernetes(ACK)

Kubernetes 的發展與應用

Kubernetes 不僅僅侷限於雲端服務,它在 Platform-as-a-Service(PaaS)市場中也扮演著重要的角色。紅帽(Red Hat)自 2015 年 OpenShift 第 3 版起,就開始將 Kubernetes 納入其容器平台,實作了架構的重大轉變,從原有的設計轉向根據 Kubernetes 的容器協調系統,為使用者提供了更強大的容器管理功能,以及一套完整的企業級工具來建置、佈署和管理容器。除了 OpenShift 外,其他專案如 Rancher,也被開發為 Kubernetes 發行版,提供了一整套圍繞 Kubernetes 協調器的工具,而像 Knative 這樣的專案,則負責管理根據 Kubernetes 的無伺服器工作負載。

Kubernetes 的未來走向

Kubernetes 的發展並未止步於容器管理,它正逐漸擴充套件到更廣泛的工作負載範圍。KubeVirt 專案讓 Kubernetes 能夠管理虛擬機器,而與 TensorFlow 等 AI/ML 框架的整合,則可能使 Kubernetes 成為管理機器學習任務的工具。Kubernetes 的未來充滿了彈性,有望成為一個統一的管理平台,涵蓋容器、虛擬機器,甚至 AI/ML 工作流程。

為何學習 Kubernetes?

對於從事雲原生應用生產管理的人員來說,學習 Kubernetes 是明智的選擇。Kubernetes 正在快速演進,其成長勢頭無可阻擋。掌握這項技術,將使你在 IT 產業中具備搶手的技能。

Kubernetes 如何簡化維運

Kubernetes 特別適合 DevOps 團隊,因為它是一個出色的容器協調平台,能夠管理容器化應用的佈署、擴充套件和網路連線。容器技術將應用及其依賴封裝,能夠在不同環境中實作快速、可靠的佈署。使用者之所以選擇 Kubernetes,是因為它具備以下優點:

  • 自動化:Kubernetes 自動執行許多與佈署和管理容器化應用相關的手動任務,讓開發者能夠專注於創新。
  • 可擴充套件性:Kubernetes 允許根據需求輕鬆擴充套件或縮減應用,確保資源的最佳利用。
  • 一致性:Kubernetes 保證在不同環境中,從開發到生產的一致性佈署,減少組態錯誤,簡化交付流程。
  • 靈活性:Kubernetes 與 DevOps 團隊常用的各種工具和技術相容,簡化了與現有工作流程的整合。

生產環境中的挑戰

在本地機器或開發環境中啟動容器,與在遠端機器上面對數百萬使用者的情況相比,所需的規劃層級大不相同。生產環境中會出現特定的問題,而 Kubernetes 正是解決這些問題的理想工具,例如:

  • 確保高用性
  • 處理發布管理和容器佈署
  • 自動擴充套件容器
  • 網路隔離
  • 根據角色的存取控制(RBAC)
  • 狀態工作負載
  • 資源管理

確保高用性

高用性是生產環境的核心原則,意味著應用始終保持可存取,不會宕機。雖然這是一種理想狀態,但應該始終朝著這個目標努力。Kubernetes 提供了一整套功能,透過在多台主機上複製容器並定期監控其健康狀態,使容器實作高用性。

當容器佈署後,應用的可存取性直接取決於容器的健康狀態。如果某個包含微服務的容器變得不可存取,使用 Docker 單獨無法自動保證該容器被終止並重新建立,以還原服務。而 Kubernetes 則能夠透過自動執行健康檢查和容器替換等任務,設計出能夠自我修復的應用。

發布管理和容器佈署

發布管理是 Kubernetes 解決的另一個生產特定問題。佈署過程涉及更新生產環境中的應用,以替換舊版本的微服務。使用 Kubernetes 能夠實作無縫的滾動更新,並且在出現問題時,可以快速回復到先前的版本。

每次發布新版本時,都涉及多個步驟,包括:

  1. 更新 Dockerfile 或 Containerfile 以包含最新的應用資訊。
  2. 建置新的 Docker 容器映像。
  3. 將新的容器映像推播到容器註冊中心。
  4. 從容器註冊中心提取新的容器映像到測試/生產系統。
  5. 停止並刪除現有的舊版本應用容器。
  6. 在測試/生產系統中啟動新的容器映像。

圖表說明:容器管理流程

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes 容器隔離與協調實踐

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

此圖示展示了一個典型的容器管理流程,每一步驟都至關重要,以確保應用的平滑更新。