---
# System prepended metadata

title: Kubernetes 簡介與安裝
tags: [k8s, Kubernetes]

---

---
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
