--- title: Kubernetes 簡介與安裝 langs: zh tags: Kubernetes, k8s image: https://raw.githubusercontent.com/cncf/artwork/master/projects/kubernetes/icon/color/kubernetes-icon-color.svg?sanitize=true --- # Kubernetes Intro ![K8s Logo](https://raw.githubusercontent.com/cncf/artwork/master/projects/kubernetes/horizontal/all-blue-color/kubernetes-horizontal-all-blue-color.svg) **Kubernetes**(常簡稱為**K8s**)是用於自動部署、擴展和管理「容器化(containerized)應用程式」的開源系統。該系統由 Google 設計並捐贈給 Cloud Native Computing Foundation(今屬 Linux 基金會)來使用。 它旨在提供「跨主機集群的自動部署、擴展以及運行應用程式容器的平台」。它支持一系列容器工具,包括 Docker 等。 ## Kubernetes 概覽 ### 應用程式演化 ![Container evolution](https://d33wubrfki0l68.cloudfront.net/26a177ede4d7b032362289c6fccd448fc4a91174/eb693/images/docs/container_evolution.svg) - **傳統部署時期**:早期,應用程式執行於實體伺服器(physical server)上。此種方式無法為實體伺服器中的應用程式規定資源使用量,因此會導致資源分配問題。 - **虛擬化部署時期**:作為解決方法,虛擬化被引入了。它能讓你在一台實體伺服器的CPU上同時運行多個虛擬機器(Virtual machines)。虛擬化能讓應用程式在不同的虛擬機之間隔離,並提供安全層級,因為一個應用程式的資訊不能被另一個應用程式任意存取。 虛擬化在實體伺服器中能有更好的資源使用和較佳的擴展性,因為應用程式可以簡單地被新增或更新、減少硬體消耗......。 - **容器部署時期**:容器類似於虛擬機,但它們擁有開放的(relaxed)隔離屬性,在應用程式間共享作業系統(OS)。因此容器被認為是輕量的。和虛擬機類似,容器擁有自己的檔案系統、CPU、記憶體、執行空間......等。由於他們與底層基礎架構分離,因此能夠跨雲端和作業系統分發進行移植。 ### 為什麼需要 Kubernetes 和它能做什麼 Kubernetes 提供一種框架去彈性地執行分散式系統。它負責應用程式的擴展和故障轉移(failover),提供部署模式(patterns)等。 Kubernetes 提供: - 服務發現(Service discovery)和負載平衡 K8s可以使用DNS名稱或使用自己的IP位址公開(expose)容器。如果容器流量很高,K8s能夠負載平衡並分散網路流量來使此部署穩定。 - 儲存協作(Orchestration) K8s允許你自動掛載(mount)你選擇的儲存系統,像是本地儲存,公開的雲端供應商...等。 - 自動推出(rollouts)和回滾(rollbacks) 你可以利用K8s描述已部署容器的所需狀態,並且可以已受控的速率將實際狀態改變為所需狀態。例如:你可以自動化 Kubernetes 為了你的部署去建立新容器,移除現存的容器並將他們所有的資源用於新容器。 - 自動包裹包裝(Automatic bin packing) 你提供K8s一個可用於運行容器化任務的節點集群(cluster)。你告訴K8s每個容器需要多少CPU和記憶體(RAM)。K8s可以將容器安裝到你的節點上,以充分利用你的資源。 - 自我修復(Self-healing) K8s重啟失效的容器、替換容器、終止(kills)不回應用戶定義的狀況檢查的容器,在準備好服務之前不會將它們通知給客戶端。 - 機密(Secret)和組態管理 K8s讓你儲存和管理敏感資訊,像是密碼、開放授權代幣(OAuth token)和SSH密鑰。你可以部署和更新機密和應用程式組態而不需要重建你的容器映像(images),也不用在堆疊組態(stack configuration)中暴露你的機密。 ## Kubernetes 元件 ![Components of Kubernetes](https://d33wubrfki0l68.cloudfront.net/2475489eaf20163ec0f54ddc1d92aa8d4c87c96b/e7c81/images/docs/components-of-kubernetes.svg) 當你部署 Kubernetes 時,你會得到一個**叢集(cluster)**。 一個 Kubernetes cluster 由一組執行容器化的應用程式的工作機器,稱作**節點(nodes)** 所組成。每個 cluster 至少有一個**工作節點(worker node)**。 工作節點託管(host)作為應用程式工作負載的組件 - **pod**。**控制平面(Control Plane)** 管理 cluster 中的 worker nodes 和 pods。在生產環境中,Control Plane 通常在多台電腦間運行,而 cluster 通常運行多個 node,以提供容錯和高可用性。 ![components](https://d33wubrfki0l68.cloudfront.net/7016517375d10c702489167e704dcb99e570df85/7bb53/images/docs/components-of-kubernetes.png) ### Control Plane Components > Control Plane 的元件對 cluster 進行全局決策(例如:排程),並偵測和回應 cluster 事件(例如:當部署的 `replicas` 欄位不滿足時,啟動新的 pod)。 > [color=#0b67b4] > Control Plane 元件可以被任何同一 cluster 中的機器執行。然而,為了簡單起見,設置腳本(set up scripts)通常在同一台機器上啟動所有 Control Plane 元件,且不會在該機器上運行使用者容器(user containers)。 可以將其看成 cluster 中的主節點(master node) #### kube-apiserver > API server 是 Kubernetes control plane 元件,它會公開 Kubernetes API。API server 是 Kubernetes control plane 的前端(front end)。 主要用途為管理整個K8s所需API的接口(Endpoint),像是從命令列下 `kubectl` 指令,就會把指令送到這。 #### etcd > 一致和高可用的鍵值存儲用作給所有 cluster 數據的 Kubernetes 的備用存儲。 #### kube-scheduler > Control Plane 元件,該元件監看新建的且未被分配給 node 的 pods,並選擇一個要在其上運行的 node 給它們。 > > 排程決定需要考慮的因素包括個體和集體的資源需求、軟/硬體/策略約束...等。 Pods 調度員 #### kube-controller-manager > 執行 controller[^1]程序的 Control Plane 元件。 > - Node Controller: 負責注意和回應當nodes下線 > - Replication Controller: 負責為系統中的每個複製控制器物件維護正確數量的pods > - Endpoints Contorller: 自動生產端點物件(即是,加入Services & Pods) > - Service Account & Token Controllers: 建立預設帳戶和API存取tokens給新命名空間。 簡單來說 controller 就是 Kubernetes 中,一個負責監視 cluster 狀態的 process #### cloud-controller-manager cloud-contorller-manager 運行與底層雲端提供者互動的控制器。 ### Node Components Node 元件運行在每個節點上,維護運行的 pods 和提供 Kubernetes 運行環境。 #### kubelet > 在 cluster 中執行在每個節點的代理者。它確保容器皆運行於pod之中。 > > kubelet 包含通過各種機制提供的一組 PodSpec,並確保這些在 PodSpec 中描述的容器運作正常。kubelet 並不管理不是由 Kubernetes 建立的容器。 該 Node 的管理員,負責與 control plane 溝通。 #### kube-proxy kube-proxy 是一個運行在 cluster 內的每個 node 上的網絡代理,實作了部分 Kubernetes Service 概念。 #### Container Runtime 是真正在節點中執行容器的軟體。 Kubernetes 支援多種 container runtime。一般預設為 [Docker](https://www.docker.com/) ## 基本運作流程 ![K8s](https://miro.medium.com/max/1024/0*5N7SlevIHOdKB-yC) > 接下來我們用一個簡單的問題「Kubernetes 是如何建立一個 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 就會自動幫我們完成後續的動作。 > [name=[胡程維](https://medium.com/@C.W.Hu/kubernetes-basic-concept-tutorial-e033e3504ec0)] [color=#4f70d4] # 安裝與執行 Kubernetes :::info 以下皆於 macOS 操作 ::: ## 安裝K8s ### 學習環境 想在本地端使用 Kubernetes 必須安裝以下三個套件: 1. **kubectl**:Kuberbetes command-line 工具,能讓你對 Kubernetes cluster 執行指令。 :::spoiler 雖然有另一種儀表板(Dashboard)UI 介面可供操作,但本章只使用指令控制K8s。 ::: 安裝方式請參考:[Install and Set Up kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl) 2. **虛擬機監視器**(此處使用免費的 **VirtualBox**): 於[下載頁面](https://www.virtualbox.org/wiki/Downloads)選擇對應的作業系統並安裝 3. **Minikube**:能夠在PC上的虛擬機運行單一節點(single-node) Kubernetes cluster 的工具。 安裝方式請參考:[Installing minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/) ### 生產環境 請參閱 [Production environment](https://kubernetes.io/docs/setup/#production-environment) ## Kubernetes 基礎運行 確認皆安裝完畢後,開啟命令列即可開始第一次的測試 1. 啟動 Minikube 和建立 cluster ``` minikube start ``` 2. 現在,你可以利用 `kubectl` 與你的 cluster 互動了。讓我們利用現存的 image `echoserver` 建立一個 Kubernetes Deployment,它是一個簡單的 HTTP 伺服器以及利用 `--port` 將8080埠公開。 ```shell kubectl create deployment hello-minikub --image=k8s.gcr.io/echoserver:1.10 ``` 3. 為了要能夠存取 `hello-minikube` Deployment,將它公開為一項 Service ```shell kubectl expose deployment hello-minikube --type=NodePort --port=8080 ``` 選項 `--type=NodePort` 規定 Service 的類型 4. `hello-minikube` Pod 現在已經啟動了,但你必須在利用公開的 Service 存取它之前等待該 Pod 上線。 確認 Pod 是否上線並運行: ```shell kubectl get pod ``` 如果輸出顯示 `STATUS` 為 `ContainerCreating`,則 Pod 正在建立中;如果輸出顯示 `STATUS` 為 `Running`,則表示該 Pod 正在線上並運行。 5. 取得公開的 Service 的 URL 檢視 Service 詳細資料: ```shell minikube service hello-minikube --url ``` 6. 為了查看本地的 cluster 的詳細資料,複製並貼上你從輸出畫面得到的 URL 在瀏覽器上。 輸出應該像這樣: ``` Hostname: hello-minikube-7c77b68cff-8wdzq Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=172.17.0.1 method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://192.168.99.100:8080/ Request Headers: accept=*/* host=192.168.99.100:30674 user-agent=curl/7.47.0 Request Body: -no body in request- ``` 如果你不想 Service 和 cluster 繼續運行,你可以刪除它們。 7. 刪除 `hello-minikube` Service: ```shell kubectl delete services hello-minikube ``` 8. 刪除 `hello-minikube` Deployment ```shell kubectl delete deployment hello-minikube ``` 9. 停止本地 Minikube cluster: ```shell minikube stop ``` 10. 刪除本地 Minikube cluster ```shell minikube delete ``` ### 額外運行 [額外物件教學](https://medium.com/@C.W.Hu/kubernetes-implement-ingress-deployment-tutorial-7431c5f96c3e) ## [Kubernetes Objects](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/) *Kubernetes objects* 是在 K8s 系統內的永久實體。K8s 使用這些實體來表示 cluster 的狀態。具體來說,它們描述: - 正在運行哪些容器化應用程式(和在哪個節點上) - 那些應用程式可用的資源 - 那些應用程式的行為政策,像是重啟政策、升級和容錯 ### Object Spec and Status 幾乎所有 Kubernetes object 都會包含兩個監管物件組態的巢狀物件欄位:`spec` 和 `status`。如果物件含有 `spec`,你必須在建立此物件時設定它,提供你希望你的資源擁有什麼樣的特性的描述:他的理想狀態。 ## 附件 基礎物件: - Pod - Service - Volume - Namespace higher-level abstractions: - Deployment - DaemonSet - StatefulSet - ReplicaSet - Job [Source](https://kubernetes.io/docs/concepts/#kubernetes-objects) [^1]: controller: A control loop that watches the shared state of the cluster through the apiserver and makes changes attempting to move the current state towards the desired state. *[CNCF]: Cloud Native Computing Foundation *[K8s]: Kubernetes