# K8S入門hands on </br> # 目錄 > [TOC] --- # 事前說明 ## Container Orchestriation容器編排 - 編排應用程式與後端容器(資料庫、SNS、其它後端服務)的依賴關係。 - 根據負載,設定應用程式的擴縮。 - 常見容器編排工具: - Docker Swarm - Kubernetes - MESOS(Apache) --- # 一、Kubernetes組成架構 ## 1. Nodes(Minions)節點 - 安裝Kubernetes的虛擬主機,可以是一台AWS EC2、GCP Compute Engine等。 - 如果應用程式僅部屬單一Node節點,則該Node若出現故障,會導致應用程式無法運行。 ## 2. Cluster 叢集 - 由多個Node組成的叢集,彼此協助負載流量。 - 若單一Node出現故障,仍可以從其他Node訪問應用程式。 - 一個Cluster叢集包含下列2種類型的Node節點: ![Kubernetes主叢節點](https://hackmd.io/_uploads/BklKqplFR.png) - **Master節點:** - **說明:** 包含所有子節點的配置訊息,並負責子節點上容器的實際編排。 - **API Server:** K8S的前端服務,用戶、CMD都透過API Server與K8S進行通信、交互。 - **etcd:** 以Key-Value、分佈式的形式儲存用於管理集群的所有數據。 - **Controller:** 在節點、容器、端點出現故障時,負責進行通知、響應,必且做出創建新容器的決定。 - **Scheduler:** 負責節點間的調度、分配工作或容器、查找新創建的容器並將其分配給節點。 - **Worker節點:** - **說明:** 負責託管、運行容器的節點(但Kubernetes不會直接在Worker節點上部屬容器)。 - **kubelet:** 確保容器按預期在節點上運行。 - **kube-proxy:** 與其他節點進行通信、節點網路設定。 - **Container Runtime:** 接收Master節點API Server的請求動作,並根據請求運行容器。 ## 3. Pod - 運行應用程式的最小單位,且Pod也是Kubernetes運作的最小單位。 - 通常Pod數量會對應應用程式數量(含多個容器Container),不會在同一Pod擴展應用程式數量。 - **Kubernetes 擴展(說明 Node、Cluster、Pod 間的關係):** ![Kubernetes添加POD、NODE](https://hackmd.io/_uploads/B1vkfAeKR.png) - 若應用程式的使用者增加,會先直接在同一Node中添加一個運行應用程式的Pod2(1 個 Node 運行 2 個 Pod)。 - 若應用程式的使用者再度增加,且Node節點沒有足夠容量再添加Pod,則會擴展Cluster集群的Node2節點(2 個 Node 運行 3 個 Pod)。 - **Docker v.s Kubernetes Pod:** - 若純Docker環境的應用程式有一個Web容器+資料庫容器,擴展時必須先添加多組Web容器+資料庫容器的應用程式,並且設置多個容器共用網路、映射共同目錄、多容器監控等作業。 - Kubernetes環境則可以透過Pod打包應用程式(Web容器+資料庫容器),來管理多容器應用程式。 --- # 二、CentOS作業系統部屬 K8S 測試環境 ## **1. 說明** - **Docker Engine:** Kubernetes是一個容器編排的應用程式,因此必須有Docker Engine來啟動、管理容器。 - **kubectl:** 用於Kubernetes集群的部署和管理應用程式的Kubernetes指令集。 - **minikube:** 於本地主機啟動、部屬單節點的Kubernetes叢集。 ## **2. 安裝、部屬** - **Docker Engine:** [Docker官方網站說明](https://docs.docker.com/engine/install/)。 - **kubectl:** [Kubernetes官方網站說明](https://kubernetes.io/docs/tasks/tools/)。 - **minikube:** [Kubernetes官方網站說明](https://minikube.sigs.k8s.io/docs/start/?arch=%2Flinux%2Fx86-64%2Fstable%2Fbinary+download) - 啟動minikube時,不得使用root管理員,因此必須創建minikube使用者並給予權限。 ![minikube1](https://hackmd.io/_uploads/r1XGdlWFA.jpg) ``` sudo useradd -m minikubeuser sudo passwd minikubeuser sudo usermod -aG docker minikubeuser ``` ``` su - minikubeuser ``` ``` minikube start --driver=docker ``` ![minikube2](https://hackmd.io/_uploads/SyPdOgWK0.jpg) ## **3. kubectl常用指令** - `kubectl run 鏡像名稱`:命令在集群的Pod部屬容器。 - `kubectl cluster info`:用於查看集群訊息。 - `kubectl get nodes`:列出所有節點。 ## **4. 實作範例** :::info :::spoiler **Pod實作** </br> **1.創建Pod並從Docker Hub Repository下載Nginx鏡像** ``` kubectl run nginx --image nginx ``` ![pod1](https://hackmd.io/_uploads/SJUUc0ltR.jpg) </br> **2.查看Pods列表** ``` kubectl get pods ``` ![pod2](https://hackmd.io/_uploads/BkRPqCgFR.jpg) </br> **3.查看該Pod的詳細資訊** ``` kubectl describe pod pod名稱 ``` ![pod3](https://hackmd.io/_uploads/H14lR3EYC.jpg) - Pod本身之IP地址、Port端口 - Pod所在Node節點之IP地址 - 啟動的容器、鏡像訊息 - 創建Pod之流程事件 </br> **4.查看Pod本身之IP地址、端口** ``` kubectl get pods -o wide ``` ![pod4](https://hackmd.io/_uploads/ry_meaNY0.jpg) </br> ::: --- # 三、Kubernetes的YAML文件(Pod) ## **1. YAML說明** 使用YAML文件來創建Object對象如:Pod、Replica副本、Deployment部屬、Service服務。 ## **2. YAML文件內容** - **apiVersion** - 創建對象時,指定的Kubernetes API版本。  - 範例: | Kind | Version | | -------- | -------- | | Pod | v1 | | Service | v1 | | ReplicaSet | apps/v1 | | Deployment | apps/v1 | - **kind** - 對象的類型,如:Pod、Replica、Deployment、Service(下方3. 實作範例包含4種類型的yaml範例文件)。 - **metadata** - 對象的元數據,如:name名稱、labels標籤(包含app、type)等。 - **spec** - 對象的詳細資訊,如:啟動的容器名稱、鏡像名稱等。 ## **3. 實作範例** :::info :::spoiler **使用Pod的YAML文件創建Pod** **1. 撰寫pod-definition.yml文件** ``` apiVersion: v1 kind: Pod metadata: name: nginx labels: app: myapp tier: front-end spec: containers: - name: nginx image: nginx ##第2個容器 ##- name: busybox ## image: busybox ``` ![yaml1](https://hackmd.io/_uploads/By9w0pNFA.jpg) </br> **2. 執行YAML文件來創建Pod** ``` kubectl create -f pod-definition.yml ``` ![yaml2](https://hackmd.io/_uploads/BJQOCa4F0.jpg) </br> **3. 查看Pod列表** ``` kubectl get pods ``` ![yaml3](https://hackmd.io/_uploads/r1idRTVKA.jpg) </br> **4. 查看Pod詳細資料** ``` kubectl describe pod myapp-pod ``` ![yaml4](https://hackmd.io/_uploads/SkEFApEFC.jpg) </br> ::: --- # 四、Kubernetes的YAML文件(Replication) ## **1. Replication Controller(舊技術)說明** 由Kubernetes Master節點中的Replication Controller元件決定是否增加新Pod、容器(可跨節點執行),並確保指定數量的Pod始終在運行(不論數量大小)。 :::info :::spoiler **使用Replication Controller的YAML文件創建Pod** **1. 撰寫rc-definition.yml文件** ``` apiVersion: v1 kind: ReplicationController metadata: name: nginx-rc labels: app: myapp tier: front-end spec: template: ##replica的啟動範本(參照啟動Pod之yaml文件) metadata: name: nginx labels: app: myapp type: front-end spec: containers: - name: nginx image: nginx replicas: 3 ##replica副本數量 ``` ![replication1](https://hackmd.io/_uploads/BJjEJDvK0.jpg) </br> **2. 執行YAML文件來創建Replication** ``` kubectl create -f rc-definition.yml ``` ![replication2](https://hackmd.io/_uploads/B1BBkvPYC.jpg) </br> **3. 查看Replication列表** ``` kubectl get replicationcontroller ``` ![replication3](https://hackmd.io/_uploads/rJK01vvKC.jpg) </br> **4. 查看Pod列表** ``` kubectl get pods ``` ![replication4](https://hackmd.io/_uploads/HysGxDDKR.jpg) </br> ::: ## 2. Replica Set(新技術) 相較於Replication Controller,Replica Set可以透過標籤(selector-matchLabels)的方式,篩選並監控帶有該標籤內容的Pod,若有任一Pod出現問題,Replica Set便會生成新Pod。 :::info :::spoiler **使用Replica Set的YAML文件創建Pod** **1. 撰寫replicaset-definition.yml文件** ``` apiVersion: apps/v1 ##版本必須撰寫成『apps/版本號』  kind: ReplicaSet metadata: name: nginx-replicaset labels: app: myapp tier: front-end spec: template: ##replica的啟動範本(參照啟動Pod之yaml文件) metadata: name: nginx labels: app: myapp type: front-end spec: containers: - name: nginx image: nginx replicas: 3 ##replica副本數量 selector: ##非必要撰寫,replica副本標籤 matchLabels: type: front-end ``` ![replicaset1](https://hackmd.io/_uploads/B1-C3PwFR.jpg) </br> **2. 執行YAML文件來創建ReplicaSet** ``` kubectl create -f replicaset-definition.yml ``` ![replicaset2](https://hackmd.io/_uploads/r1YJ6vPtA.jpg) </br> **3. 查看ReplicaSet列表** ``` kubectl get replicaset ``` ![replicaset3](https://hackmd.io/_uploads/rk_46vvtA.jpg) </br> **4. 查看Pod列表** ``` kubectl get pods ``` ![replicaset5](https://hackmd.io/_uploads/HyXO6wPtC.jpg) </br> **5. 將Replication副本添加為6個Pod** - **方法1** ``` 修改replicaset-definition.yml的[replicas項目為6] ``` ![replicaset6](https://hackmd.io/_uploads/S1lyAdPKR.jpg) ``` kubectl replace -f replicaset-definition.yml ``` ![replicaset7](https://hackmd.io/_uploads/SJ-ApuvtA.jpg) - **方法2** ``` kubectl scale --replicas=6 -f replicaset-definition.yml ``` ![replicaset8](https://hackmd.io/_uploads/Bym6puvtR.jpg) ::: --- # 五、Kubernetes的YAML文件(Deployment) ## 1. Deployment說明 ![Deployment](https://hackmd.io/_uploads/S1Jkq5lcA.png) Deployment在Kubernetes中是更高層級的對象類型(Object Kind),負責為Replication Controller/ReplicaSet部屬的Pod,執行版本上的滾動升級、暫停更新、恢復更新等操作。 ## 2. 實作範例 :::info :::spoiler **使用Deployment的YAML文件創建Pod** **1. 撰寫deployment-definition.yml文件** ``` apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: myapp type: front-end spec: template: metadata: name: nginx labels: app: myapp type: front-end spec: containers: - name: nginx image: nginx replicas: 3 selector: matchLabels: type: front-end ``` </br> **2. 執行YAML文件** ``` kubectl create -f deployment-definition.yml ``` ![deployment1](https://hackmd.io/_uploads/S17gGox90.jpg) </br> **3. 查看Deployment列表** ``` kubectl get deployment ``` ![deployment2](https://hackmd.io/_uploads/Hyn7zsx9C.jpg) </br> **4. 查看Replicaset列表** ``` kubectl get replicaset ``` ![deployment3](https://hackmd.io/_uploads/SJiDzix9C.jpg) </br> **5. 查看Pod列表** ``` kubectl get pods ``` ![deployment4](https://hackmd.io/_uploads/SkAnzox9C.jpg) ::: ## 3. Update & Rollback - **執行Rollout的策略** - **Rolling Update策略(Default)** 逐步Update,而不影響應用程式的運行。 ![rollout](https://hackmd.io/_uploads/rJ3fV3WqA.png) - **Recreate策略** 全部一起Update,會導致應用程式暫停運行。 ![rollout2](https://hackmd.io/_uploads/HJ8Nv2W9A.png) - **常用指令** :::info :::spoiler **修改Deployment鏡像並套用至Deployment** - **方法1** 手動修改YAML文件後,套用至Deployment。 ``` kubectl apply -f deployment-definition.yml ``` ![deployment5](https://hackmd.io/_uploads/HJaKih-5R.jpg) ![deployment6](https://hackmd.io/_uploads/H1n5s3b9R.jpg) - **方法2** 直接修改Deploymnet的YAML文件並套用至Deployment。 ``` kubectl set image deployment/deployment名稱 container容器名稱=鏡像名稱 ``` ![deployment7](https://hackmd.io/_uploads/ry7hahb9R.jpg) ::: :::info :::spoiler **執行Rollout(Rolling Update)** ``` kubectl rollout status deployment/deployment名稱 ``` ![deployment5](https://hackmd.io/_uploads/rk10CoW9R.jpg) ::: :::info :::spoiler **查看Rollout(Rolling Update)修訂歷史紀錄** ``` kubectl rollout history deployment/deployment名稱 ``` ![deployment6](https://hackmd.io/_uploads/Hy1P13Z5R.jpg)