Kubernetes (K8s) 介紹 - 基本
什麼是 Kubernetes (K8s)?
Kubernetes 也可以叫 K8s,這個名稱來源希臘語,意思是舵手或是飛行員,所以我們可以看到它的 logo 是一個船舵的標誌,之所以叫 K8s 是因為 Kubernetes 的 k 到 s 中間有 8 的英文字母,為了方便,大家常以這個名稱來稱呼他!

kubernetes logo
Kubernetes 是一種開源可用來自動化部屬、擴展以及管理多個容器的系統,適用於當容器數量增加,需要穩定容器環境,以及管理資源或權限分配的狀況。
我們之前在 Docker 介紹 文章中,已經有介紹以往傳統虛擬機以及容器化的 Docker 差異以及優點,那當我們在管理容器時,其中一個容器出現故障,則需要啟動另一個容器,如果要用手動,會十分麻煩,所以這時就是 Kubernetes 的厲害的地方了,Kubernetes 提供:
- 服務發現和負載平衡:K8s 可以使用 DNS 名稱或是自己的 IP 位址來公開容器。如果容器流量過高,Kubernetes 能夠使用負載平衡和分配網路流量,能使部署更穩定。
- 編排儲存:Kubernetes 允許使用自動掛載來選擇儲存系統,例如使用本地儲存,或是公共雲等。
- 自動部署、刪除:可以使用 Kubernetes 來幫我們自動化部屬新的容器、刪除現有的容器並將其資源用於新容器。
- 自動打包:當我們為 Kubernetes 提供一個節點叢集,它可以用來運行容器化的任務,告訴 Kubernetes 每個容器需要多少 CPU 和 RAM。Kubernetes 可以將容器安裝到節點上,充分利用資源。
- 自動修復:Kubernetes 會重新啟動失敗的容器、替換容器、刪除不回應用戶的不健康容器,並且在容器準備好服務之前不會通知客戶端。
- 機密和配置管理:Kubernetes 允許儲存和管理敏感訊息,例如密碼、OAuth token 和 SSH 金鑰。可以部署和更新機密的應用程序配置。

Kubernetes 很常被拿來與 Docker Swarm 做比較,兩者不同的是,Docker Swarm 必須建構在 Docker 的架構下,功能侷限、無法跳脫。
Kubernetes 則因為功能較為廣泛,而逐漸取代 Docker Swarm 在市場上的地位。下方有簡易的比較表格:
| 比較 | Kubernetes | Docker Swarm |
|---|---|---|
| 說明 | Kubernetes 是一個開源容器的編排平台,Kubernetes 的叢集結構比 Docker Swarm 更為複雜。 Kubernetes 通常有建構器和工作節點,還可進一步分為 Pod、命名空間、配置映射等。 | Docker Swarm 是一個由 Docker 構建和維護的開源容器編排平台。 一個 Docker Swarm 叢集通常包含三個項目:Nodes、Services and tasks、Load balancers。 |
| 優點 | 它有龐大的開源社群,由 Google 支持。 它可以維持和管理大型架構和複雜的工作負載。 它是自動化,並支持自動化擴展的自我修護能力。 它有內建監控和廣泛的可用集成。 | Docker Swarm 安裝簡單,它輕量化且容易學習使用。 Docker Swarm 與 Docker CLI 一起運作,因此不需要多運行或是安裝新的 CLI |
| 缺點 | 它複雜的安裝過程以及較難學習 它需要安裝單獨的 CLI 工具並且學習每一項功能 | 它是輕量級且與 Docker API 相關聯,與 Kubernetes 相比,Docker Swarm 被限制很多功能,且自動化也沒有 Kubernetes 強大。 |
Kubernetes 元件介紹與說明
Kubernetes 是如何幫我們管理以及部署 Container ? 要了解 Kubernetes 如何運作,就要先了解它的元件以及架構:
那我們由小的往大的來做介紹:依序是 Pod、Worker Node、Master Node、Cluster
Pod
Kubernetes 運作中最小的單位,一個 Pod 會對應到一個應用服務 (Application),舉例來說一個 Pod 可能會對應到一個 NginxServer。
- 每個 Pod 都有一個定義文件,也就是屬於這個 Pod 的
yaml檔。 - 一個 Pod 裡面可以有一個或多個 Container,但一般情況一個 Pod 最好只有一個 Container。
- 同一個 Pod 中的 Containers 共享相同的資源以及網路,彼此透過 local port number 溝通。
Worker Node
Kubernetes 運作的最小硬體單位,一個 Worker Node (簡稱 Node) 對應到一台機器,可以是實體例如你的筆電、或是虛擬機例如 GCP 上的一台 Computer Engine。
每一個 Node 都有三個組件所組成:kubelet、kube-proxy、Container Runtime
kubelet
該 Node 的管理員,負責管理該 Node 上的所有 Pods 的狀態並負責與 Master Node 溝通。
kube-proxy
該 Node 的傳訊員,負責更新 Node 的 iptables,讓 Kubernetes 中不在該 Node 的其他物件可以得知該 Node 上的所有 Pods 的最新狀態。
Container Runtime
該 Node 真正負責容器執行的程式,K8s 預設是 Docker,但也支援其他 Runtime Engine,例如 Mirantis Container Runtime、CRI-O、containerd
常見誤解:
很多人認為 Kubernetes 是 docker container 的管理工具,包含我一開始也是這樣認為,但其實 Kubernetes 是用來管理容器化 (containerized applications) 並不是專屬於 docker 獨享,作為一個 container orchestrator 的角色,Kubernetes 希望能夠管理所有容器化的應用程式
Master Node
Kubernetes 運作的指揮中心,可以簡化看成一個特殊化的 Node 來負責管理所有其他的 Node。
一個 Master Node (簡稱 Master) 中有四個組件組成:kube-apiserver、etcd、kube-scheduler、kube-controller-manager
kube-apiserver
- 管理整個 Kubernetes 所需 API 的接口 (Endpoint),例如從 Command Line 下 kubectl 指令就會把指令送到這裡。
- 負責 Node 之間的構通橋樑,每個 Node 彼此不能直接溝通,必須要透過 apiserver 轉介。
- 負責 Kubernetes 中的請求的身份認證與授權。
etcd
- etcd 是兼具一制性和高可用性的分散式鍵值數據庫,可以保存 Kubernetes 所有 Cluster 的後台數據庫。
kube-scheduler
- 整個 Kubernetes 的 Pods 調度員,scheduler 會監視新建立但還沒有被指定要跑在哪個 Node 上的 Pod ,並根據每個 Node 上面資源規定,硬體限制等條件去協調出一個最適合放置 Node 來讓該 Pod 運行。
kube-controller-manager
- 負責管理並運行 Kubernetes controller 的組件,簡單來說 controller 就是 Kubernetes 裡一個負責監視 Cluster 狀態的 Process,例如:Node Controller、Replication Controller。
- 這些 Process 會在 Cluster 與預期狀態 (desire state) 不符時嘗試更新現有狀態 (current state)。例如:現在要多開一台機器以應付突然增加的流量,那我的預期狀態就會更新成 N+1,現有狀態是 N,這時相對應的 controller 就會想辦法多開一台機器。
- controller-manager 的監視與嘗試更新也都需要透過訪問 kube-apiserver 達成。
Cluster
Cluster 也叫叢集,可以管理眾多機器的存在,在一般的系統架設中我們不會只有一台機器而已,通常都是多個機器一起運行同一種內容,在沒有 Kubernetes 的時候就必須要土法煉鋼的一台一台機器去更新,但有了 Kubernetes 我們就可以透過 Cluster 進行控管,只要更新 Master 旗下的機器,也會一併將更新的內容放上去,十分方便。在 Kubernetes 中多個 Worker Node 與 Master Node 的集合。
基本運作

kubernetes 組件 Kubernetes 基礎教學(一)原理介紹
接下來我們用 「Kuberntes 是如何建立一個 Pod ?」來複習一下整個 Kubernetes 的架構。
(上圖是一個簡易的 Kubernetes Cluster ,通常 Cluster 為了高穩定性都會有多個 Master 作為備援,但為了簡化我們只顯示一個。)
- 當使用者要部署一個新的 Pod 到 Kubernetes Cluster 時,使用者要先透過 User Command (kubectl) 輸入建立 Pod 對應的指令 (後面會說明要如何實際的動手建立一個 Pod)。此時指令會經過一層確認使用者身份後,傳遞到 Master Node 中的 API Server,API Server 會把指令備份到 etcd。
- controller-manager 會從 API Server 收到需要創建一個新的 Pod 的訊息,並檢查如果資源許可,就會建立一個新的 Pod。最後 Scheduler 在定期訪問 API Server 時,會詢問 controller-manager 是否有建置新的 Pod,如果發現新建立的 Pod 時,Scheduler 就會負責把 Pod 配送到最適合的 Node 上面。
雖然上面基本的運作看起來十分複雜,但其實我們在實際操作時,只是需入一行指令後,剩下的都是 Kubernetes 會自動幫我們完成後續的動作。
安裝 Kubernetes
在我們開始操作 Kubernetes 之前,需要先下載 Minikube、Hyperkit、Kubectl 套件:
一個 Google 發佈的輕量級工具,讓開發者可以輕鬆體驗一個 Kubernetes Cluster。(僅限開發測試環境)

安裝 minikube
- (Mac 專用) Hyperkit
Hyperkit 是 MacOS 系統細部設定的驅動程式。

安裝 hyperkit
Kubectl 是 Kubernetes 的 Command Line 工具,我們之後會透過 Kubectl 去操作我們的 Kubernetes Cluster。

安裝 kubectl
如何建立一個 Pod
版本資訊
- Minikube:v1.25.2
- hyperkit:0.20200908
- Kubectl:Client Version:v1.22.5、Server Version:v1.23.3
下載完 Minikube 後,我們可以先透過 Minikube 來查詢全部的指令,由於我們前面有安裝 Hyperkit 這個驅動程式,啟動 Minikube 預設是使用 Docker,我們這邊要利用 Hyperkit 來啟動,所以使用 Minikube start --vm-driver=hyperkit 來啟動 Minikube。
Minikube 其他指令介紹:
顯示 minikube 狀態 minikube status
停止 minikube 運行 minikube stop
ssh 進入 minikube 中 minikube ssh
查詢 minikube 對外的 ip minikube ip
使用 minikube 所提供的瀏覽器 GUI minikube dashboard (可以加 - - url 看網址歐)
我們啟動 minikube 後,我們要打做一個可以在 Pod 運行的小程式。這個小程式是一個 Node.js 的 Web 程式,他會建立一個 Server 來監聽 3000 Port,收到 request 進來後會渲染 index.html 這個檔案,這個檔案裡面會有一隻可愛的小柴犬。
因為本文章是在介紹 kubernetes 所以在程式部分就不多做說明,我把程式碼放在 Github,以及附上 Dockerhub 的 Repository 可以直接使用包好的 image 來做測試!
Pod yaml 檔案說明
接下來我們要先撰寫一個 Pod 的定義文件 (.yaml) 檔,這個 .yaml 檔就可以建立出 Pod 了!
- kubernetes-demo.yaml (程式縮排要正確,不然會無法執行歐!)
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-demo-pod
labels:
app: demo
spec:
containers:
- name: kubernetes-demo-container
image: 880831ian/kubernetes-demo
ports:
- containerPort: 3000apiVersion
該元件的版本號,必須依照 Server 上 K8s 版本來做設定 (想要知道 k8s 版本,可以使用 kubectl version 指令來查詢,會顯示 client 跟 server 的版本訊息,client 代表 kubectl 版本訊息,server 代表的是 master node 的 k8s 版本訊息),目前 k8s 都使用 1.23 版本以上,所以 apiVersion 直接寫 v1 即可。
kind
該元件的屬性,用來決定此設定檔的類型,常見的有 Pod、Node、Service、Namespace、ReplicationController 等等
metadata
用來擺放描述性資料的地方,像是 Pod 名稱或是標籤等等都會放在此處。
- name:指定該 Pod 的名稱
- labels:指定該 Pod 的標籤
spec
用來描述物件生成的細節,像是 Pod 內其實是跑 Dokcer container,所以在 Pod 的 spec 內就會描述 container 的細節。
- container.name:指定運行的 Container 的名稱
- container.image:指定 Container 要使用哪個 Image,這裡會從 DockerHub 上搜尋
- container.ports:指定該 Container 有哪些 Port number 是允許外部存取的
使用 kubectl 建立 Pod
當我們有了定義文件後,我們就可以使用 kubectl 的指令來建立 Pod
kubectl create -f kubernetes-demo.yaml
kubectl apply -f kubernetes-demo.yaml可以使用 create or apply 來建立 Pod ,那這兩個的差異是什麼呢?
- kubectl create
kubectl create是所謂的 “命令式管理” (Imperative Management)。通過這種方式,可以告訴 Kubernets API 你要建立、更新、刪除的內容。kubectl create命令是先刪除所有現有的東西,重新根據 YAML 文件生成新的 Pod。所以要求 YAML 文件中的配置必須完整。kubectl create命令,使用同一個 YAML 文件重複建立會失敗。
- kubectl apply
kubectl apply是 “聲明式管理” (Declarative Management)方法的一部分。在該方法中,即使對目標用了其他更新,也可以保持你對目標應用的更新。kubectl apply命令,根據配置文件裡面出來的內容,生成就有的。所以 YAML 文件的內容可以只寫需要升級的欄位。
如果看到 pod/kubernetes-demo-pod created 就代表我們成功建立第一個 Pod 了,接下來我們可以使用:
kubectl get pods可以查看我們運行中的 Pod:
NAME READY STATUS RESTARTS AGE
kubernetes-demo-pod 1/1 Running 0 3m5sPod 指令介紹:
查詢現有 Pod 狀態 kubectl get po/pod/pods
查看該 Pod 詳細資訊 kubectl describe pods <pod-name>
刪除 Pod kubectl delete pods
查看 Pod log kubectl logs <pod-name>
也可以使用 minikube 圖形化頁面來看一下是否成功!
minikube dashboard --url
🤔 Verifying dashboard health ...
🚀 Launching proxy ...
🤔 Verifying proxy health ...
http://127.0.0.1:55991/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
minikube dashboard
連線到 Pod 的服務
當我們建立好 Pod 之後,打開瀏覽器 localhost:3000 會發現,什麼都沒有,是因為我們剛剛在 .yaml 裡面設定的是 Pod 的 Port ,它與本機的 Port 是不相通的,因此我們需要使用 kubectl port-forward <pod> <external-port>:<pod-port> ,來將 Pod 與本機端做 mapping。
kubectl port-forward kubernetes-demo-pod 3000:3000
Forwarding from 127.0.0.1:3000 -> 3000
Forwarding from [::1]:3000 -> 3000
Handling connection for 3000我們在此瀏覽 localhost:3000,就會看到可愛的柴犬囉!

成功顯示柴犬
前面我們已經創建屬於我們第一個 Pod 了,但當我們 Pod 越建越多時,要怎麼快速的得知每個 Pod 在做什麼事情?除了用 Pod 的 metadata name 來命名外,還有另一種方式:
什麼是 Label ?
Label 顧名思義就是標籤,可以為每一個 Pod 貼上標籤,讓 Kubernetes 更方便的管控這些 Pod。
Label 的寫法很簡單,可以自己自訂一對具有辨識度的 key/value,舉我們上面的例子來說:我們可以在 labels 內加入 app: demo,那 Label 有什麼好處呢?
這邊要稍微提一下 Selector,它的功用是選取對應的物件。為了要方便選取到我們設定好的 Pod,這時候 Label 就派上用場了!
Selector 的寫法也很簡單,只要把我們在 Label 定義的 key/value 直接完整的貼過來就可以了~
就像這樣:
selectors:
app: demo那選取後有什麼功用呢!請看 Kubernetes - 進階 - Service
講完 Label 後,順邊提一下跟 Label 有相似的:
什麼是 Annotation ?
前面提到的 Label 功用其目的是要讓 Kubernetes 知道可以去更方便管理的,那我們如果想要貼標籤但不想讓 Kubernetes 知道,要怎麼做呢?
這時我們就可以用 Annotation,透過 Annotation 可以將標籤單純給開發人員查看,那聽起來 Annotation 好像沒有什麼實質上的用途,因為 Kubernetes 不會採用這些標籤,但其實 Annotation 還是有用的歐!後續文章會再提到 ><
那既然 Label 跟 Annotation 有相似,所以寫法想必也是差不多吧:
annotations:
author: Pin-YI
contact: [email protected]一樣也是定義一組具有辨識度的 key/value ,我們這邊就先放 author、contact
那 Label 與 Annotation 要放在 Pod 的哪一處呢?
還記得我們上面說 metadata 是用來擺描述性資料的地方嗎,所以不管是 Label 或是 Annotation 都是放在 metadata 中歐!
metadata:
name: kubernetes-demo-pod
labels:
app: demo
annotations:
author: Pin-YI
contact: [email protected]參考資料
kubernetes 官網:https://kubernetes.io/
Kubernetes(K8s)是什麼?基礎介紹+3 大優點解析:https://www.sysage.com.tw/news/technology/293
Docker Swarm vs Kubernetes: how to choose a container orchestration tool:https://circleci.com/blog/docker-swarm-vs-kubernetes/
Kubernetes 基礎教學(一)原理介紹:https://cwhu.medium.com/kubernetes-basic-concept-tutorial-e033e3504ec0
Kubernetes 那些事 — 基礎觀念與操作:https://medium.com/andy-blog/kubernetes%E9%82%A3%E4%BA%9B%E4%BA%8B-%E5%9F%BA%E7%A4%8E%E8%A7%80%E5%BF%B5%E8%88%87%E6%93%8D%E4%BD%9C-97cc203a2660
Kubernetes 那些事 — Pod 篇:https://medium.com/andy-blog/kubernetes-%E9%82%A3%E4%BA%9B%E4%BA%8B-pod-%E7%AF%87-57475cec22f3
Kubernetes 那些事 — Label 篇:https://medium.com/andy-blog/kubernetes-%E9%82%A3%E4%BA%9B%E4%BA%8B-label-%E7%AF%87-4186af2af556