使用者導向的Kubernetes (k8s) 入門介紹: 基本架構與使用概念

使用者導向的Kubernetes (k8s) 入門介紹: 基本架構與使用概念

隨著電腦科學的發展,主流的軟體系統已經不是單單部屬在一台計算機上,而是部屬在一群計算機組成的叢集 (cluster)。一般常見的雲端資源,其實背後也都是由 cluster支持。另一方面,因為近期使用容器 (container) 來部屬應用程式也相當流行,因此部屬基於 container的 Kubernetes自然成為架設 cluster的熱門選項

Kubernetes (k8s) 是用於自動部署、擴充和管理「容器化應用程式」的開源系統,是目前軟體開發領域炙手可熱的要角。藉由 Kubernetes可以建構出一套穩健的 cluster與營運系統,並且無縫使用大量的開源專案資源。不過 Kubernetes本身使用與操作也具有一定難度,因此對於大部分的人來說也是有一定的學習難度。這篇文章以使用者的角度,概述 container與 Kubernetes的基本架構與使用概念

Cover made with Canva(圖片來源)

Tip

文章難度:★★★☆☆

閱讀建議: 本篇文章為 Kubernetes的入門簡介,從 container切入,就 Kubernetes的基本設計與元件介紹,再用最基本的 pod操作範例結尾。據我所知,對於大部分的 data scientist來說,接觸 Kubernetes的過程很容易被無數的文檔與細節埋沒。因此這邊文章嘗試以貼近使用者的角度,介紹 Kunernetes的理解大方向,減少在理解過程中被過多細節干擾而抓不到重點。

推薦背景知識:container, Docker, virtual machine,cluster computing, cloud computing, Kubernetes, object storage, network filesystem, microservices architecture, zero-downtime deployment.

如前所述,時下主流的軟體系統已經不是單單部屬在一台計算機上,而是部屬在一群計算機組成的叢集 (cluster)。要部屬在 cluster上一個很直接的問題就是如何將應用程式快速地在不同計算機上部屬,而 container的觀念就從這裡展現它的價值。

What’s Container

Container是一個軟體運行單位,包含了程式碼以及執行所需程式庫、系統工具等軟體相依資源。

透過 container,我們可以在不同電腦上快速地建立、測試和部署程式。

對比於 Container,另一個很常聽到的名詞就是 VM (Virtual Machine)。其實不論是 Container或是 VM,都是將硬體虛擬化的實現

VM主要的核心概念是透過 Hypervisor提供虛擬的作業平台來執行客戶作業系統,負責管理其他客作業系統的執行階段,可以簡單想像 Hypervisor是在模擬硬體的行為實現硬體虛體化。而** Container不生成整個 OS kernel,透過直接調用 OS kernel,大幅提升效率並減少運行單位大小**,可以說是透過虛擬化作業系統實現硬體虛體化,是更輕量化的選擇。

VM與 Container的差異。(資料來源)

所謂的 Container本身是種概念,因此需要透過標準規範其相關設定與運作,讓不同 Container的解決方案能夠有更高的相容性,這個就是Open Container Initiative (OCI) 。我們常常聽到的** Docker ,其實就是基於 OCI的一種引擎實作 (或者說 OCI提出時大量參考 Docker設計)。**

符合OCI的Docker Engine設計。(資料來源)

Docker利用 Linux核心中的資源分離機制,例如cgroups,以及 Linux核心命名空間 (namespaces),來建立獨立的 containers。這可以在單一Linux實體下運作,避免啟動一個虛擬機器造成的額外負擔。 Docker是目前最流行的 container實現,有極其豐富的生態系。

What’s Kubernetes (k8s)

有了 container,開發者就可以靈活地將應用程式在不同的計算機間搬移與部屬,但這也說不上是 cluster。因此,對一群計算機,最大幅度地利用 container的靈活就是 Kubernetes閃閃發光的價值

Kubernetes是用於自動部署、擴充和管理「容器化應用程式」的開源系統。

該系統由 Google設計並捐贈給 Cloud Native Computing Foundation來使用。 它旨在提供**「跨主機叢集的自動部署、擴充以及執行應用程式容器的平台」**。

聽起來有點抽象,簡單的理解就是Kubernetes可以建立一套由許多 node (可以想像成電腦) 構成的叢集 (cluster),開發者將應用程式,比如說 model service enpoint,或是一個 model training job,容器化後透過 Kubernetes API送到出,由 kubernetes決定實際執行的硬體

Kubernete大方向架構圖。(資料來源)

除了自動決定部屬硬體外, Kubernetes在維護系統時可以依照使用流量自動調度資源。以 API來說,外部進來的 request會被自動安排到不同的實體回應,而隨著 request的增減, Kubernetes也可以自動增加或減少在 API背後提供計算的實體。一般這個負責導流的原件稱為 Load Balancer,而增減運算實體的行為則稱為 auto scaling

Kubernetes可以使用 load balancer實現更穩健的系統。(資料來源)

複習一下:容器化讓應用程式可以快速的部屬到不同的環境,但即使省略了環境的設定,終究還是要挑台電腦來部屬。而透過 Kubernetes則是可以更進一步地將容器化程式有效地部屬到 cluster,將部屬與管理實體硬體的過程進一步自動化,也是所謂 IaC (Infrastructure as Code) 理念的實踐。

部屬 container到 cluster上的邏輯。(資料來源)

Kubernetes整體上會有以下幾個重要組成元件:

  • Control plane(Master): 負責接受來自 k8s API的 request,再分配給任務給負責執行的電腦,像是一個管理中心。 Control plane可以、也通常是同時交給多台電腦擔任。另外,在control plane內會額外維護一個稱為 etcd的儲存應用,用來儲存集群狀態和一些中繼數據
  • Compute machine(Worker): 負責實際執行任務的電腦。
  • Persistent storage: container在運行的邏輯與直接跑在電腦上不同,並不是直接把資料寫在硬體上,而是透過背後 engine分發資源。因此通常 container關閉時,資料也都會被自動清除。但其實有許多資料是使用者希望長期保存的,因此Kubernetes也有對應的資源規劃,稱為 Persistent Volume (簡稱PV),通常是由 NFS或是 object storage (如 S3或 MinIO) 實現。
  • Container registry: 因為kubernetes執行都是 container,因此需要有一個空間儲存 container images。以 Docker為例,可以直接使用 docker engine的 private registry或是使用功能更全面的 Harbor,也可以直接使用雲端的 DockerHub或 AWS ECR。
Kubernetes架構與重點元件。(資料來源)

Application在 Kubernetes的運作

一個**應用程序在 Kubernete的 lifecycle大致分成幾個階段: 提交執行要求後,進入排程等候資源,安排實際資源並執行,最後執行完成後回收資源。**以下先介紹 Kubernetes在計算與儲存兩個面向的重要觀念,再看一個部屬應用的簡單範例。

Pod是應用程序 (application) 在 Kubernetes cluster運行的最小單位。

以下列幾個 pod的重點觀念:

  • Pod是應用服務的最小運行單位,依照執行狀態大致可分為 pending, running與 completed三個階段
  • 在 Pod被創建後,會先進入排程等候實體資源 (pending),等到資源足夠後,Kubernetes才會將 Pod安排到 Node運行 (running),這時候才會開始實際運作。當 pod內的應用執行完畢, Kubernetes會關閉 pod並回收資源 (completed)
  • 一個 pod 裡面可以存在一個或是多個 container。同一個 Pod 中的 Containers 共享相同資源及網路,彼此透過可以直接透過 local port number 溝通。
Node與 pod的關係。(資料來源)

通常虛擬化的計算機至少會包含計算與儲存兩個部分,先前的部分解釋了 Kubernetes如何將計算放到實體的計算機上,但管理計算資源與儲存空間其實是兩個完全不同的問題。

在一般的情況,在創建 pod的時候我們會掛載 (mount) 稱為 volume的儲存空間給 pod使用。與其他container 邏輯相似,在** **container 中的檔案不是永久存在的,隨著 container 的重啟檔案就會隨之消失。因為在 Kubernetes中一個 pod可以擁有多個 containers,Kubernetes規劃了更完整的 volume機制,volume不會隨著 containers的關閉而消失,並且可以讓 pod內的 containers同時存取

Pod與 volume的關係。(資料來源)

而對於某些希望長期存在,或者明確地說,不隨著 pod關閉而刪除的資料, Kubernetes則是設計了 Persistent Volume (PV)。基本上通常 PV由 cluster管理員建立,屬於虛擬化的資源,而使用者要使用的時候,則是要 claim要使用多少。在 Kubernetes這個被使用者 claimed的儲存空間稱為 Persistent Volume Claim (PVC),可以像 volume一樣直接mount給 pod使用。

Pod使用Persistent Volume的邏輯。(資料來源)

這邊補充一個小細節,在 Kubernetes PV的設計上, PV與 PVC是一對一的關係,即一個 PV只能被一個 PVC綁定。但一個 PVC可以被不同的 pods存取,因此可以達成跨 pods的資料共用。另外,PV可以分為靜態與動態兩種,不過這篇文章就不多提了。

不論是哪種實作的Kubernetes,通常都支援使用原生的 kubectl在Kubernetes上部署和管理應用程序,在大多數的情況,使用者都是透過 kubectl發送撰寫好的 yaml檔案在 Kubernetes cluster部署和管理應用程序

以下是一個簡單的 yaml範例,定義一個 pod,在 pod裡運行redis (儲存資料庫),並 mount volume給 pod使用。

Kubernetes內各種資源的 config其實都蠻複雜的,可以從重點設定慢慢了解。通常會先看kind,定義這個資源是什麼類別,可能是Pod、Deployment、PersistentVolumeClaim或是其他各種 k8s資源。剩下就像是 container的資源,通常這邊跟 Docker邏輯差不多,還有像是 volume的規劃等等。

使用上通常使用 kubectl來提交資源要求:

在這個範例中,Kubernetes在接收到 YAML spec後,就會開始安排執行這個 pod。當輪到這個 pod執行時,先安排到某個 node上,再到 docker registry上拉指定的 image,以上範例會去拉redis/redis 。當然 registry可以是公開的 Docker Hub、其他廠商提供的 registry或是自己架設的 private registry。

通常在比較完善的開發流程中,這個過程會被設定為一系列的 workflow,整合到 GitOps的一部分。具體上常見的全開源實作會是透過把 code上傳到 github,在透過 CI/CD Pipeline啟動 Jenkins,由 Jenkins來打包上傳 docker image,並透過 kubectl在 Kubernetes上完成布署。

將 Kubernete與 GitOps結合。(資料來源)

個人感覺Kubernetes在未來會持續流行很長很長一段時間,因為相關資源已經非常深厚地結合,甚至可以發現在不同雲端平台會有不同 Kubernetes的實作。不過對於使用者來說,其實知道他的大概念後,剩下的就是與自己的工作流程結合了,因此在 Kubernetes整個官方文檔我覺得這頁是最關鍵的:

當然也相當推薦多看看不同開發者或是各大雲端廠商的介紹,畢竟 Kubernetes真的是博大精深,不同人看到的面相一定是很不一樣的。以下列幾個推薦的資源:

好了~這篇文章就先到這邊。老話一句,軟體領域每年改變速度都相當快,說真的要跟緊不是一件容易的事。所以我的觀點可能也會存在瑕疵,若有發現什麼錯誤或值得討論的地方,歡迎回覆文章或來信一起討論 :)

Reference

  1. Docker[Official Website]
  2. Kubernetes[Official Website]
  3. Introduction to Kubernetes architecture[Red Hat Website]
  4. Microsoft Azure Kubernetes Basic[YouTube]
comments powered by Disqus