---
# System prepended metadata

title: Kubernetes
tags: [study, School]

---

# Kubernetes介紹

## Kubernetes 是什麼？
![image](https://hackmd.io/_uploads/B1UcaM070.png  =80%x)
* Google 開源的容器化編排引擎
    * 主要用於容器化應用程式的部署和管理
* 容器編排的功能，可以透過.YAML文件配置

### **<font color="#1936C9">第一階段：建立 Docker/Podman 部署包</font>**
**App，也就是最後要運行起來的應用程式 (代表我們要部署什麼)
在Kubernet的世界中，所有要部署的東西都是一個「容器化後的應用程式」(也就是Image)**

有兩種方法產生Image：
* Docker
* Podman

### **<font color="#1936C9">第二階段：Kubernetes 部署計劃撰寫</font>**
**在這個階段要決定如何部署以及部署到哪裡**

> * How to deploy
>   * 部署什麼資源
>   * 要部署多少資源
> * Where to deploy
>   * Local
>   * Cloud 

* 規劃計算資源(Computing)
    * 對應到 Deployment 的部署模板
    * Scaling 的實現
        * 是Kubernet的強項之一
        * 對應到HPA(Horizontal Path Autoscaling) 的部署模板
            * 可以針對流量的變化對運算資源進行動態增減
* Network
    *  對應到 Service 的部署模板
* 儲存資源(Storage)
    * 對應到PVC(Persistent Volume Claim) 的部署模板 
> 以上的模板都可以根據Kubernetes所提供的模板語法，去客製化設定要如何部署以及部署到哪裡。
> 而Kubernet的定位就是這整個部署計劃的撰寫。


### **<font color="#1936C9">第三階段：Local vs AWS/GCP/Azure 資源部署</font>**
**將部署計劃寫好後，最後就是要進行真正的部署，包括：**
* 啟動VM的運算資源
* 設定網路
* 管理進出權限
* 建立儲存資源、永久保存資料

- - -

## Kubernetes 解決了什麼問題？

### **<font color="#1936C9">功用一：Dynamic Scaling</font>**
**根據當前的流量，動態的資加或減少運算資源**
![image](https://hackmd.io/_uploads/BkI7TenXA.png =80%x )

### **<font color="#1936C9">功用二：Self-Healing</font>**
**自動的重新啟動壞掉的應用程式**

### **<font color="#1936C9">功用三：Zero Downtime Rolling Update</font>**
**當我們部署一個新版本時，我們的整個服務，對於使用者來說將不會有任何關機的時候**

**舉例：**
假設目前有三個APP為v1版本要更新為v2版本，Kubernetes會根據我們的設定，一個個地將APP分別轉變為v2版本。
![image](https://hackmd.io/_uploads/rkez1b3XA.png  =90%x)

### **<font color="#1936C9">功用四：Zero Down Time Rollback</font>**
**無中斷時間的版本復原**
**同上述做法**

- - -
## Docker 相較於 Kubernetes 少了什麼？

### **<font color="#1936C9">Docker vs Kubernetes：定位面向比較</font>**
**Docker**
* 扮演容器引擎的角色
* 主要的功能為 ==「容器的創建與部署」==
> 比如說我們將一個專案打包成一個Image，並且放上DockerHub讓人使用。
> 又或者是透過Docker Run的方式直接進行部署。

**Kubernetes**
* 扮演容器管理平台的角色
* 主要的功能為 ==「模板化的容器部署」==
    * 透過撰寫一個.YAML檔案，讓我們每次的部署都是固定的。以後就能透過一個指令，去利用之前創建好的模板，多次的進行重複部署。
    * Docker compose功能也可達到相同的效果
* 自動化的資源部署
> 比如當前的動態流量突然高漲，需要更多的運算資源處理請求時，Kubernates就可以自動化的完成這個任務。
* 將程式部署到多台主機之中

### **<font color="#1936C9">Docker vs Kubernetes：階層關係比較</font>**
**Docker**
* 低階而特定
* 輕量而易上手
 
**Kubernetes**
* 高階而全面

### **<font color="#1936C9">Docker vs Kubernetes：適用對象比較</font>**
**Docker**
* 個人/小型公司
* 比如新創公司在PoC(Proof of Concept) 的時候使用

**Kubernetes**
* 中大型/跨國公司
* 原因
    * 他們部屬的容器專案必須要面對不斷變化的流量
    * 需要彈性管理：運算資源/網路資源/儲存資源
    * 容器監測

- - -

## Kubernetes 核心組件

### **<font color="#1936C9">Node</font>**
**一個Node就是一台虛擬機或者是物理機**

![image](https://hackmd.io/_uploads/HkEBgmR7A.png =85%x)
> * 我們可以在這個節點上運行一個或多個Pod
>    * 一個Pod就是一個或多個Container的組合

### **<font color="#1936C9">Service (SVC)</font>**
**將一組Pod封裝成一個服務，這個服務可以通過一個統一的入口來訪問**

![image](https://hackmd.io/_uploads/Hk2--mRXC.png =85%x)
> SVC 會自動將請求轉發到其他健康的Pod上，解決了Pod的IP地址不穩定的問題。

* 內部服務
    * 如上圖中的MySQL資料庫
    * 只需要在Cluster內部中被訪問就好
* 外部服務
    * 如API接口、前端UI
    * 常用的外部服務： node:port
> node:port會在節點上開放一個端口，然後將這個端口映射到SVC的IP地址和端口上。
> 如此一來就可以通過node的IP地址來訪問SVC了
* 其他的SVC種類

![image](https://hackmd.io/_uploads/ry2_TRQ4C.png)

### **<font color="#1936C9">Ingress</font>**
**用來管理使用者從Cluster外部，訪問Cluster內部服務的入口和方式**

![image](https://hackmd.io/_uploads/SyUK77CQR.png =85%x)

* 配置不同的轉發規則
    * 根據不同的規則訪問不同的SVC跟相對應的Pod
* 配置域名
    * 不再需要使用IP地址和port號
* 負載均衡, SSL證書

### **<font color="#1936C9">ConfigMap</font>**
**用於封裝配置內容(如URL,username,password)，並應用於APP的讀取和使用**
![image](https://hackmd.io/_uploads/S1_wHmAmR.png =85%x)
>  分離配置內容和 Image，以保持容器的可移植性

### **<font color="#1936C9">Secret</font>**
**和ConfigMap類似，用於封裝配置內容。**
**不同之處在於，這些敏感內容不是以明文的形式儲存，而是做了Base64編碼。**

![image](https://hackmd.io/_uploads/BkLnNr0X0.png =85%x)
> 需要搭配其他的安全機制，包括網路安全、訪問控制、身份認證等等

### **<font color="#1936C9">Volumes</font>**
**用於將一些持久化儲存的資源，掛載到：**
* Cluster 中的本地硬碟
* Cluster 外部的遠端數據庫

![image](https://hackmd.io/_uploads/ry8pHSCmR.png =85%x)
> 如此一來即使容器被銷毀或者重啟，數據也不會丟失，實現了容器中數據的持久化儲存。

### **<font color="#1936C9">Deployment</font>**
**用於定義和管理應用程式容器的副本數量以及應用程式容器的更新策略**

![image](https://hackmd.io/_uploads/H1MwdSRm0.png =85%x)
> 之前提到過，Pod 可以理解為在容器上面加了一層抽象，這樣就可以將一個或多個容器組合在一起。
>
> 而 Deployment 可以理解為在 Pod 上面再加上一層抽象，這樣就可以將一個或多個 Pod 組合在一起。

* 副本控制：定義和管理容器的副本數量
    * 比如我們可以定義一個應用程式的副本數量為3個，那麼如果有副本發生故障的時候，他會自動創建一個副本來替代它。
* 滾動更新：定義和管理容器的更新策略
    * 確保應用程序的平滑升級。
* 自動擴縮容

### **<font color="#1936C9">StatefulSet</font>**
**和Deployment非常類似，一樣提供了定義和管理容器副本數量、自動擴縮容等等的功能。但它==額外保證了每個副本都有自己穩定的網路標誌和持久化儲存的功能==**

![image](https://hackmd.io/_uploads/rku2tr0QC.png =85%x)
> 應用於，數據庫、緩存等等有狀態類的應用

- - -

## Kubernetes 基底結構：Master Node & Worker Node
![image](https://hackmd.io/_uploads/HkW59thNR.png)

### **<font color="#1936C9">Cluster 的概念</font>**
**包含這個Kubernets會用到的所有資源。**

### **<font color="#1936C9">Master Node 的概念</font>**
**對整個Cluster進行中央調控的地方。**
> 1. API Server作為進入點
> 2. Cluster Controller Manager接受API Server的請求，根據不同請求類別進行相對應的設定
> 3. Scheduler決定要將Pod部署到哪一臺Worker Node之中
> 4. Cluster State Store決定要把哪一些Cluster相關的狀態給保留下來
*  **API server**：
    *  Master Node與外界的溝通點，充當 Kubernetes 集群的前端。
    *  API 伺服器接收所有 REST 請求（例如，部署一個新應用程序，調度一個容器等），並且是所有其他 Kubernetes 組件進行通信的中心樞紐。
    * 提供Cluster的所有操作的入口點，並確保請求的有效性和一致性。
    * 可以使用Command Line(kubectl), .YAML模板與其互動。
* **Cluster Controller Manager**
    * Cluster Controller Manager是一個運行多個控制器的進程。
        * 節點控制器（負責節點的狀態監控）
        * 副本控制器（負責確保指定數量的 pod 副本運行）
        * 端點控制器（連接服務和 pod）
    * 通過不斷地觀察集群的狀態並執行相應的操作來維持集群的健康狀態。
* **Cluster State Store (etcd)**
    * 保存 Kubernetes 集群的所有數據（如 pod、服務、配置數據）。
    * 只儲存Cluster中的數據，Pod裡面的數據通常不會存在這。
* **Schedular**
![image](https://hackmd.io/_uploads/ByMkhrAmC.png =85%x)
    > 根據想要達到的目標狀態，去決定要把當下哪一個Pod，部署到哪一個Worker Node之中。


### **<font color="#1936C9">Master Replicate Node 的概念</font>**
**Master Node的備份，用於Master Node壞掉之後的補救。**

### **<font color="#1936C9">Worker Node 的概念</font>**
**當Master Node收到相關請求後，其中有一些動作需要和Worker Node進行交流。**
* **Kubelet Service：**
    * 負責管理和維護每個Node上的Pod，確保他們按照預期運行。
    * 處理所有來自Master Node的相關請求，來對當下的Worker Node進行相關的設定。
* **Kube-Proxy Service：**
    * 網路代理、負載均衡
    * 掌管網路請求，決定誰可以進/出當下的Worker Node。
* **Container Runtime：**
    * 在Kubernetes中，所有的部署都必須被容器化，變成一個Image。
    * 負責在系統上運行容器的軟件層，實現了容器的核心功能。
        * 例如：下載容器鏡像、創建和運行容器、管理容器的文件系統、網絡和資源隔離
    * 範例 
        * Docker-Engine
        * Podman Runtime
        * Containerd
        * CRI-0
        * Mirantis Container Runtime

> * 透過以上的三個元件，就可以將Master Node的請求進行處理，並且將程式部署到Kubernet上面。
> * 當Worker Node完成之後，也會進行回報，告訴Master Node可以更新狀態了。
> * Worker Node通常不會只有一台：Scaling的彈性


- - -

## 什麼是 Kubernetes Pod？
![image](https://hackmd.io/_uploads/BJSj9KhE0.png)

### **<font color="#1936C9">Pod是什麼</font>**
**在一個Kubernetes的Cluster中，談到運算部署的時候，他的==最小基本單位就是一個Pod==。**
* Pod (一個Pod裡面可以包含多個Container，每個container則會連結到一個Image。)
    * Container
        * Image
    * Container
        * Image
    * ... 
> 在kubernetes的視角中，他的最小單位依然是一個Pod。
> 因此有時在談論架構圖時，會先隱藏Pod內部的細部設定(如：Container, Image)

### **<font color="#1936C9">Docker Image從哪裡來</font>**
**Image都會儲存在Container Registry，可以透過：**
* Local
* Cloud
    * Docker Hub
    * AWS ECR (Elastic Container Registry)
    * GCP GAR (Google Artifact Registry)
    * Azure ACR (Azure container Registry)


> * 部署最小的基本單位是Pod。
> * 一個Pod可以涵蓋多個Container。
> * 每個Container會連結到一個Image。
>* mage會存在Container Registry中，透過本地或雲端的方式建立。

- - -

## Pod 與 Worker Node 的關係
### **<font color="#1936C9">資源歸屬的概念</font>**
**哪些資源是屬於Kubernetes，哪些資源是屬於Resource Provider(資源提供者)**

**透過Local或雲端服務商提供的運算資源，為Cluster創建出可以運作的Worker Node，使Cluster將各個Pod，分配給其中一個Worker node進行實際部署。**

### **<font color="#1936C9">屬於Kubernetes的資源</font>**
* 每一個Pod會落在哪一個Worker Node(也就是所謂的運算資源)，是由Cluster進行分配。
* 雖然Worker Node是Cluster之中的一個資源，但必須有人來提供他實際的運算資源(Resourece Provider)

### **<font color="#1936C9">屬於Resourece Provider的資源</font>**
**運算資源的提供者，有兩種方式：**
* Local：在本地建立運算資源，包括主機的啟動、維護，並註冊到Cluster中。
* Cloud：
    * AWS EC2
    * GCP Computing Engine
    * Azure VM

> * Cluster決定如何將Pod分佈到不同的Worker Node
> * Worker Node是Cluster中的一個資源，由Resource Provider提供實際的運算資源
> * Resource Provider可以是Local或是Cloud

## K8S的運算架構
<font color=red>為什麼要使用 Deployment 模板進行自動化部署？</font>
### **<font color="#1936C9">Pod 的使用時機與限制</font>**
* 如果有一個Cluster，部署Pod都是手動部署
    * 如果沒事 -> 正常運行
    * 出意外（如 Pod3 壞掉了）-> Cluster 的 Pod 數變為兩個，沒有自動修復的機制
### **<font color="#1936C9">ReplicaSet 的使用時機與限制</font>**
* 在一個ReplicaSet的資源中，會包含對Pod部署的所有設定，==包含最重要的Image==
* ReplicaSet的人設為 -> 想要維持幾個Pod持續運行
    * 比如我們想要維持3個Pod持續運行，那麼即使有一個壞掉了，也會透過ReplicaSet重啟
* 若想更新Image版本，還是只能透過手動
### **<font color="#1936C9">Deployment 的使用時機</font>**
* Deployment 會同時包含 ReplicaSet 以及 Pod 的所有部署資訊
    1. 先定義要哪個版本的Image -> Pod
    2. 再定義想要維持的Pod數量 -> ReplicaSet
* 若想更新Image版本
    1. Deployment會先刪除部份的Pod
    1. 然後創建一個新的ReplicaSet(帶有新版本的Image)
    2. 逐個取代
# Kubernetes 環境搭建

### **<font color="#1936C9">kubectl</font>**
**命令行工具，用於和 kubernetes API 互動，包含：**
* 資源管理：建立、刪除、更新和檢視 Kubernetes 資源（如 Pod、Service、Deployment 等）
* Cluster管理：檢視和管理 Kubernetes Cluster 的狀態和配置
* 調試和診斷：調試應用程式和 Cluster 問題，查看日誌和事件

- - -

## MiniKube (本地)
==**官方教學文檔：https://minikube.sigs.k8s.io/docs/**==

![image](https://hackmd.io/_uploads/SkwTuI07R.png =70%x)
### **<font color="#1936C9">MiniKube 介紹</font>**
**minikube是一個輕量級的Kubernetes發行版，可在==本地端==創建一臺虛擬機，並部署僅包含一個Node的簡單Cluster**

### **<font color="#1936C9">使用Minikube搭建K8S環境</font>**


- - -

## K3s & Multipass (本地)
**可以用來部署一些稍微複雜的應用**

### **<font color="#1936C9">K3s介紹</font>**

### **<font color="#1936C9">Multipass介紹</font>**
**Multipass是一個輕量級的虛擬機管理工具，用於在本地快速的創建和管理虛擬機**

### **<font color="#1936C9">使用K3s和Multipass搭建K8S環境</font>**


- - -

## Kubeadm (本地)
待補

- - -

## Kind (本地)
待補

- - -

## Killorcoda (線上)
https://killercoda.com/

**登入：**
![image](https://hackmd.io/_uploads/BJQVA80XA.png =50%x)

**選擇 Playground：**
![image](https://hackmd.io/_uploads/SkfKRIC7R.png )

**選擇Kubernete環境：**
![image](https://hackmd.io/_uploads/BJJACU0QA.png =35%x)

**開始使用：**
![image](https://hackmd.io/_uploads/BkEqyvRmC.png  =80%x)

* editor：用於配置文件
* tab1：終端機
    * 基本上所有Linux命令都可用
    * 已搭建好Kubernete環境

右上角可以調整字體大小
每次只能使用==一個小時==

- - -

## Play with Kubernetes (線上)
https://labs.play-with-k8s.com/

登入就可以直接用了
每次只能使用==四個小時==

- - -

# kubectl 常用命令
![image](https://hackmd.io/_uploads/Byqj0TQER.png)
kubectl命令大全：https://blog.csdn.net/anqixiang/article/details/114150945
Kubectl 常用命令大全：https://cloud.tencent.com/developer/article/1638810

### **<font color="#1936C9">查看集群中各種資源的狀態和信息</font>**
**kubectl get [資源類型] [資源名稱] [選項]**
* 資源類型
    * node(s)
    * service(svc)
    * pod(s)
    * deployments
    * ...
* 資源名稱: 指定要建立的資源名稱。
* 選項
    * -o：指定輸出格式
        * -o wide: 顯示詳細信息。
        * -o yaml: 以 YAML 格式输出。
        * -o json: 以 JSON 格式输出。
        * -o name: 僅顯示資源名稱。
    * -A：全列出來
    * -n：指定命名空間(如果未指定，使用當前命名空間)
    * -w：持續監視資源

### **<font color="#1936C9">創建一個新的 pod</font>**
**kubectl run [NAME] --image=[IMAGE] [選項]**
* NAME：pod的名稱
* IMAGE：指定容器使用的鏡像名稱
* 選項
    * -n：指定命名空間(如果未指定，使用當前命名空間)
    * --port：暴露容器的端口
    * --env: 設定環境變量，格式為 "KEY=VALUE"

### **<font color="#1936C9">創建各種資源</font>**
**kubectl create [資源類型] [資源名稱] [選項]**
> 與kubectl run不同，kubectl create主要透過 .YAML 或 JSON檔來定義和建立各種Kubernetes 資源
* 資源類型
    * node(s)
    * service(svc)
    * pod(s)
    * deployments
    * configmap 
    * ...
* 資源名稱：指定要建立的資源名稱。

```
常見指令：
    kubectl create -f <filename>：從 .YAML 或 JSON檔建立資源
    kubectl create namespace <name>：建立一個新的命名空間
    kubectl create configmap <name>：建立一個新的ConfigMap
    kubectl create secret <type> <name>：建立一個新的Secret
    kubectl create deployment <name>：建立一個新的Deployment
    kubectl create service <type> <name>：建立一個新的Service
```

### **<font color="#1936C9">查看 Kubernetes 中 Pod 或容器的日誌</font>**
**kubectl logs [選項] pod名稱**
* 選項
    * -f：跟随日誌輸出
    * -c：指定容器名稱，用於一個 Pod 中有多個容器的情况
    * --tail：只顯示最後的若干行日誌
        * 例如："--tail=20" 表示顯示最後20行日誌
    * --timestamps：在日誌每行前新增時間戳記
    
### **<font color="#1936C9">kubectl apply</font>** 

### **<font color="#1936C9">kubectl expose</font>** 

### **<font color="#1936C9">kubectl describe</font>** 
    
### **<font color="#1936C9">kubectl delete</font>**

- - -
    
# .YAML配置文件的使用
``` .YAML
範例：

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    selector:
        matchLabels:
            app: nginx
    replicas: 3
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
                - name: nginx
                  image: nginx:1.25
                  ports:
                    - containerPoet:80
```
* apiVersion：指定使用哪個版本的api
    * 格式為：group/version
* kind：指定資源對象的類型  
* metadata：定義資源對象的原始數據
    * 如：名稱、標籤、命名空間...
* spec (specification)：定義資源對象的配置信息
    * 如：有多少副本、使用哪個鏡像、暴露哪個端口...
    * selector：選擇特定的資源，通常與label搭配使用
    * replicas：表示有多少個副本
    * template：pod的配置信息
> 外層的spec是用來定義 deployment
> 內層的spec是用來定義 pod
    

- - -
# Kubernetes 十大核心模板
## Pods
## ReplicaSet
## Deployment
## Service
> Service 提供了一個穩定的存取入口,讓外部或內部的客戶端能夠連接到後端的Pod -> 負載均衡、抽象化
* ClusterIP
    * 每個Service只會有一個ClusterIP，並且只有在Cluster內部才可以存取
* NodePort
    1. 每個WorkerNode(仲介)上面會開啟一個特定的Port，請求會透過這個Port連接至Service
        * 需要同時開放多個WorkerNode的Port
        * 範圍為30000~32768 Port
    2. 再由這個Service去分配流量
    * 注意WorkerNode要有實際的運算資源才可以被建立，所以資源的環境會決定能不能成功連線
* Load Balancer
    * 





- - -
    
# 資源連結
K8S 自學聖經：10大核心模板快速入門【圖解教學】
https://www.tenlong.com.tw/products/9786267383490?list_name=lv

Kubernetes一小时轻松入门 
https://www.youtube.com/watch?v=SL83f7Nzxr0&list=WL&index=14&t=27s

Kubernetes Course - Full Beginners Tutorial
https://www.youtube.com/watch?v=d6WC5n9G_sM&t=1s

Kubernetes Tutorial for Beginners
https://www.youtube.com/watch?v=X48VuDVv0do

Kubernetes 官方文檔
https://kubernetes.io/zh-cn/docs/home/


### 備忘
1. Kubernetes的核心組件
* SVC, 因為pod是使用內部up溝通，所以如果對外是直接與pod溝通的話，可能會因為pod的產生跟消滅而改動up，就沒辦法溝通。所以就可以設定一個service，使用者只需要從外部跟這個svc溝通，由這個svc跟內部的pod溝通，就會簡化很多
* Ingress主要的功能就是配置域名，跟根據http的請求來將流量分配到不同的svc跟pod
* Configmap是用來打包一些配置的，這樣我們要修改一些使用者資訊的時候就不用一個pod一個pod進去修改，可以直接改Configmap就好
* Secret 就是在configmap 的基礎上面加密，但他其實也沒有很加密，就只是稍微編碼一下，其實應該要有可以加密的方法，但我還沒有研究
* Volume就是可以儲存要保留的資料，不會因為pod的產生跟消滅而導致資料的遺失
* Deployment是用來管理pod的，可以用來擴張跟縮小pod的數量，還可以用來更新pod裡面image的版本，基本上Kubernetes有一些很重要的特性，比如根據流量去增加或減少服務，還有不停機的更新、服務不中斷等等都是透過deployment這類的方式去實現
* Stateful就是跟deployment類似，但他讓每一個pod的副本都有自己的volume

一張slide差不多1分鐘 -> 15張slide
經驗越多 一張slide可以3分鐘以上

information sharing：
1. 對計畫有所進展
2. 對學習有幫助