Kubernetes 提供了容器化應用佈署和管理的完整解決方案,有效解決了生產環境中容器管理、自動擴充套件和高用性等挑戰。本文從 Docker 與 Kubernetes 的關係切入,說明容器技術如何解決應用程式佈署的依賴衝突和資源消耗問題。接著,我們將逐步介紹 Kubernetes 的核心概念,例如節點、Pod、名稱空間和服務,並透過佈署 Nginx 和自定義 mynginx 映像檔的例項,展示如何在 MicroK8s 環境中操作 Kubernetes。同時,我們也提供 YAML 設定檔範例,以更清晰地說明 Pod 和佈署的組態方式。最後,我們將探討 Kubernetes ,例如使用外部容器倉函式庫、CI/CD 自動化佈署以及監控和日誌管理,為讀者提供更全面的 Kubernetes 學習路徑。
Kubernetes 簡介:容器化應用的佈署與管理
Kubernetes(K8s)是一種開源系統,用於自動化佈署、擴充套件和管理容器化應用。本章節將探討 Docker 與 Kubernetes 之間的關係,並建立 Kubernetes 工作站。接著,我們將透過佈署一個基本的 Nginx 應用以及我們自建的 mynginx 映像檔來進一步探索 Kubernetes 叢集,從而更深入地瞭解 Kubernetes 的各種功能。
Kubernetes 與 Docker 的關係
容器技術並非新興事物。在基礎設施領域,我們已經見證並操作過各種形式的容器技術,例如 LPARs 和 Solaris Zones。現代容器技術解決了將應用程式以自包含格式佈署的問題,減少了分享函式庫之間的衝突風險,同時保持最小的執行時期足跡。
在早期,開發者可能會將每個版本的應用程式連同其依賴項佈署在單獨的虛擬機器中。每個虛擬機器可能佔用約 20-50GB 的磁碟空間、2-4 個 vCPU 等,並伴隨著諸如修補、安全性和身份管理等管理開銷。這與我們在本文開始時討論的問題類別似。
Docker 的誕生正是為瞭解決這個問題。它提供了完整的生態系統,包括建置工具、執行時期工具和倉函式倉管理工具,從而成為該領域的主導者。因此,我們在前幾章中學習了一些 Docker 的知識,並熟悉了容器技術。
為何需要 Kubernetes
在開發環境中,將靜態網站應用佈署在單一容器中是可行的。然而,在生產環境中佈署應用時,我們需要更多的功能,例如容器管理(如監控容器狀態、在失敗時重啟或傳送警示)、自動化的擴充套件能力等。Kubernetes 解決了上述問題,並提供了更多的功能。
在本文中,我們將介紹 Kubernetes 生態系統及其各種功能,並測試其核心能力。官方 Kubernetes 網站為 https://kubernetes.io/。
Kubernetes 的發行版
Kubernetes 有多種發行版,從微型/小型實作(如 K3S 和 MicroK8s)到公有雲中的生產級 Kubernetes(如 AWS EKS 和 Google 的 GKE)。
基本概念
對於我們的學習目的,我們將從熟悉的根據 Ubuntu 的 MicroK8S 實作開始,並在其中佈署我們的靜態網站應用。首先,我們來瞭解一些基本概念。
節點(Nodes)
節點為 Kubernetes 叢集提供計算資源,容器就在這些節點上執行。節點具有基礎作業系統,如 Ubuntu 或 CentOS,但我們不應將它們視為普通的虛擬機器或電腦。它們的唯一目的是為執行在其上的容器提供計算資源(CPU、記憶體)和容器執行環境。
容器組(Pods)
容器組是一組由 Kubernetes 管理的一個或多個容器(即你的應用程式)。每個容器組都有自己的 IP 位址。
名稱空間(Namespaces)
名稱空間是一種邏輯上的分割方式,可以根據業務線或其他有意義的方式來劃分工作負載。例如,可以根據業務線建立單獨的名稱空間,並在這些名稱空間中佈署相關的工作負載。這樣,可以根據名稱空間邊界進行顯示成本、收費和存取控制。
服務(Service)
當我們啟動容器時,會暴露一個連線埠,即應用程式正在監聽的連線埠。然後,我們會對映一個外部(主機)連線埠,以便外部實體可以存取該服務。在 Kubernetes 中,我們定義一個服務,告訴 Kubernetes 將服務定義中定義的連線埠對映到應用程式正在監聽的容器組連線埠上。
容器執行環境介面(CRI)
容器執行環境介面是 kubelet 和容器執行環境用來交換資訊的協定或標準語言。
Kubelet
Kubelet 可以被視為執行在每個節點上的代理軟體,允許進行節點管理,如向 API 伺服器註冊節點狀態和報告執行中的容器健康狀態。如果容器因某種原因失敗,kubelet 會將此狀態報告給 API 伺服器;然後,API 伺服器可以根據佈署規範採取糾正措施。
apiVersion: v1
kind: Pod
metadata:
name: mynginx-pod
spec:
containers:
- name: mynginx
image: mynginx:latest
ports:
- containerPort: 80
內容解密:
上述 YAML 檔案定義了一個名為 mynginx-pod
的容器組。該容器組包含一個名為 mynginx
的容器,使用 mynginx:latest
映像檔,並暴露容器內的 80 連線埠。apiVersion
和 kind
欄位指定了 Kubernetes API 的版本和資源型別。metadata
欄位提供了容器的後設資料,如名稱。spec
欄位定義了容器的規格,包括容器名稱、映像檔和連線埠組態。
graph LR; A[Kubernetes 叢集] --> B[節點1]; A --> C[節點2]; B --> D[容器組1]; B --> E[容器組2]; C --> F[容器組3]; D --> G[容器1]; D --> H[容器2]; E --> I[容器3];
圖表翻譯: 此圖表展示了 Kubernetes 叢集的架構。Kubernetes 叢集由多個節點組成,每個節點上可以執行多個容器組,而每個容器組中又可以包含一個或多個容器。這種架構允許 Kubernetes 有效地管理和協調容器化應用。
在未來的章節中,我們將更深入地探討 Kubernetes 的各種功能和特性,包括如何佈署和管理複雜的應用程式、如何進行擴充套件和縮減、以及如何確保應用程式的高用性等。透過實際操作和案例分析,我們將能夠更全面地掌握 Kubernetes 的強大功能,並將其應用於實際的生產環境中。
詳細 Kubernetes 應用案例分析
在後續章節中,我們將探討更多 Kubernetes 的應用案例,包括如何佈署一個具有多個服務的複雜應用程式、如何使用 Kubernetes 的自動擴充套件功能來應對變化的工作負載、以及如何利用 Kubernetes 的滾動更新功能來確保應用的持續可用性等。這些內容將幫助讀者更深入地理解 Kubernetes 的強大功能和靈活性。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mynginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: mynginx
template:
metadata:
labels:
app: mynginx
spec:
containers:
- name: mynginx
image: mynginx:latest
ports:
- containerPort: 80
內容解密:
這個 YAML 檔案定義了一個名為 mynginx-deployment
的佈署。該佈署指定了 3 個副本,使用 mynginx:latest
映像檔,並暴露容器內的 80 連線埠。selector
欄位用於選擇符合標籤 app: mynginx
的容器組。template
欄位定義了容器組的範本,包括後設資料和規格。
結語
透過本章節的學習,我們對 Kubernetes 有了基本的瞭解,並學習瞭如何定義和佈署簡單的容器組和佈署。隨著 Kubernetes 技術的不斷發展和完善,它已經成為容器協調領域的事實標準。掌握 Kubernetes 將為我們開啟更廣闊的容器化應用開發和管理的大門。
在 Kubernetes 上佈署我們的首個應用程式
在上一章中,我們已經成功地設定了 Kubernetes 工作站,本章將進一步探索 Kubernetes 叢集,佈署一個基本的 Nginx 應用程式以及我們之前建立的 mynginx 映像檔,以介紹 Kubernetes 的各種功能。
執行一個 Pod - 公共 Nginx
在 Kubernetes 叢集中啟動容器的過程非常簡單。我們需要告訴 Kubernetes 要啟動哪個映像檔、佈署的名稱是什麼,以及其他任何需要公開的服務等引數。這與我們在 Docker 世界中所做的非常相似。
步驟1:執行 Nginx 映像檔
要執行 Nginx 映像檔並檢查在 Kubernetes 叢集上的啟動狀態,我們執行兩個命令:kubectl run
和 kubectl get pods
,如 清單 6-1 所示。
kubectl run myrun01 --image=nginx
kubectl get pods
清單 6-1:執行我們的首個 Pod
shiva@wks01:~$ kubectl run myrun01 --image=nginx
pod/myrun01 created
shiva@wks01:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myrun01 1/1 Running 0 11s
shiva@wks01:~$
內容解密:
kubectl run myrun01 --image=nginx
:此命令指示 Kubernetes 使用名為nginx
的映像檔建立一個名為myrun01
的 Pod。kubectl get pods
:此命令用於取得當前叢集中所有 Pod 的狀態。在這個例子中,我們可以看到myrun01
已經成功啟動並正在執行。
設定 Kubernetes 工作站
在開始佈署應用程式之前,我們首先需要設定我們的 Kubernetes 工作站。以下是設定的步驟:
安裝 MicroK8s:
- 首先,我們需要一個至少具有 2 vCPUs、4GB 記憶體和 40GB 硬碟空間的 Ubuntu 22.04 虛擬機器。
- 使用以下命令安裝 MicroK8s:
cd ~ sudo snap install microk8s --classic --channel=1.27/stable
- 內容解密: 這個命令使用
snap
套件管理器安裝 MicroK8s,一個完整的 Kubernetes 發行版。
設定使用者許可權:
- 為了避免一直使用
sudo
,我們將普通使用者加入microk8s
群組:sudo usermod -a -G microk8s shiva sudo chown -f -R shiva ~/.kube newgrp microk8s id
- 內容解密: 這些命令將使用者
shiva
加入microk8s
群組,並更新相關的許可權設定。
- 為了避免一直使用
確認 MicroK8s 狀態:
- 執行以下命令確認 MicroK8s 是否正在執行:
microk8s start microk8s status
- 內容解密: 這些命令啟動 MicroK8s 並檢查其狀態。
- 執行以下命令確認 MicroK8s 是否正在執行:
設定命令列別名(可選):
- 為了簡化操作,可以將
microk8s kubectl
設定為kubectl
的別名:alias kubectl='microk8s kubectl'
- 內容解密: 這樣設定後,我們就可以直接使用
kubectl
命令來與 Kubernetes 叢集互動。
- 為了簡化操作,可以將
執行第一個 Kubernetes 命令:
- 使用以下命令檢查叢集中的節點:
kubectl get nodes
- 內容解密: 這個命令顯示了叢集中的節點狀態。
- 使用以下命令檢查叢集中的節點:
你的任務
確保你已經成功設定並執行了 MicroK8s,因為後續章節將依賴於此 Kubernetes 例項進行進一步的學習。
Kubernetes 佈署流程
graph LR; A[開始] --> B[安裝 MicroK8s]; B --> C[設定使用者許可權]; C --> D[確認 MicroK8s 狀態]; D --> E[設定命令列別名]; E --> F[執行第一個 Kubernetes 命令]; F --> G[佈署 Nginx 應用程式];
圖表翻譯: 此圖示展示了從安裝 MicroK8s 到佈署 Nginx 應用程式的整個流程。首先,我們安裝並設定 MicroK8s,然後確認其狀態,接著設定命令列別名,最後執行 Kubernetes 命令並佈署應用程式。
在Kubernetes中佈署自定義應用程式
使用kubectl命令操作Kubernetes
在Kubernetes中,大多數透過CLI的操作都是透過kubectl
命令驅動的;熟悉這個命令非常重要。kubectl run
是第一個命令,其形式如下:
kubectl run <pod名稱> --image=<映像名稱>
run
是要求kubectl
執行某個東西的命令。<pod名稱>
,例如myrun01
,是我們為第一次執行所取的名稱;這是一個任意的、使用者提供的名稱。--image=nginx
是要在Pod中使用的容器映像名稱;我們選擇了nginx
。有很多其他的容器映像可供選擇,等待我們去發現——更多內容將在後面的章節中介紹。
驗證Pod執行狀態
執行以下命令來取得當前正在執行的Pods列表:
kubectl get pods
輸出的解釋如下:
READY
:正在執行的Pod數量;1/1
是預設值,因為我們沒有要求啟動多個Pods。STATUS
:指示我們的Pod正在執行。RESTARTS
:Kubernetes無論出於何種原因重新啟動我們的Pod的次數,因為期望狀態是1,如果Kubernetes注意到Pod失敗,它將自動重新啟動容器以達到期望狀態,同時記錄重新啟動的次數。AGE
:Pod已經執行的時間。
內容解密:
此命令用於檢查Kubernetes叢集中當前執行的Pods狀態。透過檢查READY
、STATUS
、RESTARTS
和AGE
等欄位,可以瞭解Pods的健康狀態和執行時間。
佈署自定義容器映像
步驟概述
- 設定本地容器倉函式庫。
- 建立佈署。
- 建立服務。
- 存取服務(在我們的例子中是Web伺服器/網站)。
步驟1:重新標記Docker映像
首先,讓我們將mynginx
映像重新標記為local/mynginx
。我們可以將倉函式庫名稱命名為local/mynginx
,因為映像是本地VM的,並且該映像為我們提供nginx
應用程式。
docker tag mynginx:01 local/mynginx:01
執行以下命令來確認映像是否已正確標記:
docker images
輸出結果應該顯示local/mynginx:01
已正確標記。
內容解密:
重新標記映像是為了遵循<倉函式庫名稱>/<映像描述性名稱>
的命名慣例。這樣做有助於更好地管理和識別映像。
將容器映像匯入microk8s
雖然Docker守護程式知道這個倉函式庫,但我們的microk8s不知道,因此我們需要將這個容器映像匯入microk8s生態系統,以便microk8s能夠識別這個倉函式庫/映像。
步驟1:匯出Docker映像到tar檔案
docker image save local/mynginx:01 > mynginx_1.0.tar
步驟2:確認tar檔案已成功建立
ls -l *.tar
步驟3:將映像匯入microk8s
microk8s ctr image import mynginx_1.0.tar
步驟4:確認映像已成功匯入
microk8s ctr images list -q | grep [m]ynginx
輸出結果應該顯示docker.io/local/mynginx:01
,表示映像已成功匯入並可供使用。
內容解密:
匯入映像到microk8s的過程包括匯出Docker映像到tar檔案,然後將其匯入microk8s環境。這樣做是因為microk8s有自己的容器執行時環境,需要單獨匯入映像。
使用自定義映像執行Pod
現在,讓我們使用我們自己的映像在microk8s Kubernetes叢集中啟動一個容器,而不是之前使用的標準nginx
映像。
首先,刪除之前建立的Pod:
kubectl delete pod <pod名稱>
然後,使用我們自己的nginx
容器映像重新啟動Pod:
kubectl run mynginx --image=local/mynginx:01
執行以下命令來驗證Pod是否正在執行:
kubectl get pods
輸出結果應該顯示新的Pod正在執行。
內容解密:
使用自定義映像執行Pod需要先將映像匯入microk8s環境,然後使用kubectl run
命令啟動Pod。這樣可以驗證自定義映像是否能夠在Kubernetes叢集中正常執行。
- 使用外部容器倉函式庫:在實際生產環境中,通常會使用外部或專用的構件倉函式庫,如JFrog Artifactory或Sonatype Nexus。
- 自動化佈署:使用CI/CD工具自動化佈署流程,提高佈署效率和可靠性。
- 監控和日誌管理:實施監控和日誌管理方案,以便更好地瞭解應用程式的執行狀態和效能。
透過這些措施,可以進一步提高Kubernetes叢集的穩定性和可維護性。