---
title: 'k8s 基礎'
disqus: hackmd
---
[TOC]
<style>
#doc {
min-width: 1200px;
margin-left: 200px;
}
</style>
# K8s Node 定義

:::info
Master Node是由etcd、kube-controller-manager、kube-apiserver、kubescheduler構成
:::
**Etcd**
* 用來存放 Kubernetes Cluster 的資料作為備份,當 Master 因為某些原因而故障時,我們可以透過 etcd 幫我們還原 Kubernetes 的狀態
**kube-controller-manager**
* 負責管理並運行 Kubernetes controller 的組件,簡單來說 controller 就是 Kubernetes 裡一個個負責監視 Cluster 狀態的 Process
* 這些 Process 會在 Cluster 與預期狀態(desire state)不符時嘗試更新現有狀態(current state)
* controller-manager 的監控與嘗試更新也都需要透過訪問 kube-apiserver 達成
* controller 包含以下四種:
* Node controller
* 當節點有問題時負責通知與回應
* Replication controller
* 用來管理 Pod 的數量及狀態,並可確保有指定數量的 Pod 正在運行
* Endpoints controller
* 用來結合 Pod 和 Service 的物件
* Service Account & Token controllers
* 建立預設的帳號、為新的 namespace 建立新的 API 存取 token
**kube-apiserver**
* 管理整個 Kubernetes 所需 API 的接口(Endpoint)
* 負責 Node 之間的溝通橋樑,每個 Node 彼此不能直接溝通,必須要透過 apiserver 轉介
* 負責 Kubernetes 中的請求的身份認證與授權
**Kubescheduler**
* 整個 K8S 的 Pods 調度員,scheduler 會監視新建立但還沒有被指定要跑在哪個 Node 上的 Pod,並根據每個 Node 上面資源規定、硬體限制等條件去協調出一個最適合放置的 Node 讓該 Pod 跑
:::info
WorkerNode是由kubelet、kube-Proxy、Container Runtime構成
:::
**Kubelet**
* kubelet相當於 node agent,用於管理該 Node 上的所有 pods以及與 master node 即時溝通。
**kube-Proxy**
* kube-proxy則是會將目前該 Node 上所有 Pods 的資訊傳給 iptables,讓 iptables 即時獲得在該 Node 上所有 Pod 的最新狀態。
**Container Runtime**
* 該 Node 真正負責容器執行的程式,以 Docker 容器為例其對應的 Container Runtime 就是 Docker Engine。
---
# K8s Object 定義

:::info
Basic
:::
* Pod
* Pod是k8s中可以被創造或是發布的最小的單位,一個 Pod 在k8s世界中就相當於一個application。Pod有以下特點:
1. 每個 Pod 都有屬於自己的 yaml 檔
2. 一個Pod裡面可以包含一個或多個Docker Container ( 或者是其他 Container)
3. 在同一個Pod裡面的Containers,可以用Local Port互相溝通
* Service
* k8s服務是一個abstraction,它定義了一組邏輯Pod和一個訪問它們的策略 - 有時稱為micro-service。負責不同Pod之間的溝通。
* Volume
* k8s服務中的Volume與Docker的Volume是類似的概念,他們都是為了在虛擬化系統中,因該設計的pod或是container生命週期是短暫的,為了要保存資料的永久性和完整性所做的方法,也就是保存資料用的,也可以用作共享資料,無論是在不同的pod或是container之間,但是k8s的Volume不同於Docker的是,它會有明確的生命週期,且能在產生pod時加入屬於Volume不同的參數,像是要掛載的檔案系統類型等等(如:NFS),簡言之它具有更大的彈性,另外它可在container切換時保持存在,以達到交換資料的目的。
* Namespace
* 所謂的Namespace,是劃分不同使用者能使用多少資源的方法(resource quota),舉例來說:CPU或是memory分配的多寡,在少量的使用者場景中(幾個或幾十個),這樣的功能是不需要的,此外,若是分配不同資源,並不需要使用不同的Namespace,只要在同個Namespace下定義不同的label即可。在管理k8s系統中的情況,最常使用到的是kube-system這個Namespace。
:::info
Abstraction
:::
* ReplicaSet
* 複製集,是基於Replication Controller的改良版,本質差異是在selector的支援多寡,在現在的使用情境下,我們不會直接操作到ReplicaSet,每個不同的Deployment會有他們自己的ReplicaSet,並會自動調配,除非我們有對於複製集有特殊設定需求,不然一般直接套用Deployment的預設即可,ReplicaSet顧名思義是讓同個Pod有多個分身在同時運行,舉例來說:這樣的好處是在更新的時候不會讓使用者斷線
* Deployment
* 部署,Deployment Controller提供Pods和ReplicaSets可定義的更新,k8s下的Deployment有許多feature可以使用,如:create、update、roll back、pause、resume等,針對Deployment的替代方案可以使用kubectl rolling update這個指令。
* StatefulSet
* StatefulSet管理一組Pod的部署(Deployment)和擴展(scaling),並提供有關這些Pod的排序和唯一性的保證。
* 與部署(Deployment)類似的是,StatefulSet管理基於相同容器規範的Pod。與部署(Deployment)不同的是,StatefulSet為其Pod保持標籤(label)。
* 這些Pod是根據相同的規範創建的,但不可互換:每個Pod都有一個永久性的標籤(label),它可以在任何重新安排時保留。
* DaemonSet
* DaemonSet能確保部份或所有node運行Pod的副本持續運行。
* 刪除DaemonSet將清除它創建的Pod。
* Job
* Job創建一個或多個pod,並確保指定數量的Pod工作完成後終止。
* 刪除Job將清除它創建的Pod。
* Job還可以用於並行運行多個Pod。
---
# Tool
```bash=
-- 查看 主服務狀態
kubectl get componentstatuses
-- 查看 現有Namespace
kubectl get namespace
-- 查看 pod/service/rc 較多資訊
kubectl get all -o wide
```
---
# Pod
yaml 建立 pod, 並指定特定label的node
k8s-web-pod-node-selector.yaml
```yaml=
apiVersion: v1
kind: Pod # 定義類型
metadata:
name: k8s-net-pod # 資源名稱
labels: # 該pod 的label
app: k8s-net-pod
spec: # 資源狀態
containers: # 單一Container的設定,可以單一Pod設定多個Container
- name: web # 該Container在該Pod的名稱
image: test_project/v1 # docker image 名稱
imagePullPolicy: IfNotPresent # 預設為 Always (每次都重遠端拉取Image),通過設定 IfNotPresent或Never来使用local Image
ports:
- containerPort: 80
livenessProbe: # 設定healthCheck
httpGet:
path: /host/CheckHealth # healthCheck API Path
port: 80 # healthCheck API Port
initialDelaySeconds: 15 # 服務啟動後 幾秒後做healthCheck default=0 min=0
periodSeconds: 15 # 每隔幾秒Check一次 default=10 min=1
timeoutSeconds: 30 # timeout時間 default=1 min=1
successThreshold: 1 # 呼叫幾次成功後 會更改狀態回success default=1 min=1
failureThreshold: 3 # 呼叫幾次失敗後 會更改狀態回failure default=1 min=1
nodeSelector:
SpecifyNode: node_test1 # 指定部屬到含有 label SpecifyNode=node_test1 的 node中
```
---
# Service
功能: 在Node 與 Pod 之間的橋樑, 幫忙轉接IP
```bash=
-- 當Node建立好後, 建立expose service
kubectl expose pod/k8s-net-pod --name=k8s-net-service --port=80 --type=NodePort
-- 查看目前 service 所有資訊
kubectl -ojson get service k8s-net-service
```
更新Service 的nodeport 的方式
```bash=
1. 編輯service
kubectl edit service k8s-net-service
=> 直接修改完後, ESC :wq 退出
2. 更新yaml檔後 重新apply
kubectl apply service -f k8s-web-service-demo.yaml
3. 更新yaml檔後 重新 replace
kubectl replace service -f k8s-web-service-demo.yaml
**若沒有yaml檔 可匯出當前Service的yaml檔設定 進行修改
**kubectl get service k8s-net-service -o yaml > k8s-web-service-demo.yaml
** apply 與 replace差異
apply => 若有現有service 則 更新, 若無 則創建
replace => 刪除現有service 重新創建
apply 可更新部分設定, 故不需完整的yaml檔
replace 則需完整的yaml檔, 因需要重新創建
4. Patch更新
kubectl patch service k8s-net-service --type='json' -p='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":31500}]'
```
yaml檔 建立 service
k8s-web-service.yaml
```yaml=
apiVersion: v1
kind: Service
metadata:
name: k8s-net-service
spec:
selector:
app: k8s-net-pod
ports:
- protocol: TCP
port: 80
targetPort:
nodePort: 31000
type: NodePort
```
# ReplicationController
功能:
1. 用來管理Pod的數量以及狀態的controller
2. 在Replication Controller設定檔中可以指定同時有多少個相同的Pods運行在Kubernetes Cluster上
3. 當某一Pod發生crash, failed,而終止運行時,Replication Controller會幫我們自動偵測,並且自動創建一個新的Pod,確保Pod運行的數量與設定檔的指定的數量相同
4. 當機器重新開啟時,之前在機器上運行的 Replication Controller 會自動被建立,確保pod隨時都在運行
```bash=
# 建立 ReplicationController
kubectl apply -f k8s-web-rc.yaml
# 自動擴展 pod數量
kubectl scale --replicas=4 -f k8s-web-rc.yaml
# 刪除RC時 其所指定label的pod 也會一併被刪除
kubectl describe rc my-replication-controller
# 刪除RC時 保留pods
kubectl describe rc my-replication-controller --cascade=false
```
yaml檔 建立 ReplicationController
k8s-web-rc.yaml
```yaml=
apiVersion: v1
kind: ReplicationController
metadata:
name: my-replication-controller
spec:
replicas: 3 # 欲創建pods 的數量
selector:
app: k8s-net-pod
template:
metadata:
labels: # 創建pods 的 label
app: k8s-net-pod
spec:
containers:
- name: web
image: test_project/v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
```
# Deployment
功能:
1. 部署一個應用服務(application)
2. 協助 applications 升級到某個特定版本
3. 服務升級過程中做到無停機服務遷移(zero downtime deployment)
4. 可以Rollback到先前版本
:::info
會自動創建Replica Sets (為 ReplicationController 的進化版,提供更彈性的selector設定)
:::
```bash=
# 建立 deployent
kubectl apply -f k8s-web-deployment.yaml
# 查看 deployment 較多資訊
kubectl get deploy -o wide
# 更新 Image版本
kubectl set image deploy/my-deployment web=test_project/v2 --record
# 查看 deployment滾動更新 紀錄
kubectl rollout history deploy my-deployment
# 回滾 deployment至上一個版本
kubectl rollout undo deploy my-deployment
# 回滾 deployment至某指定版本
kubectl rollout undo deploy my-deployment --to-revision=4
```
yaml檔 建立 Deployment
k8s-web-deployment.yaml
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: k8s-net-pod
template:
metadata:
labels:
app: k8s-net-pod
spec:
containers:
- name: web
image: test_project/v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /host/CheckHealth
port: 80
nodeSelector:
SpecifyNode: node_test1
```
# Lable
功能:
1. 每個物件可以同時擁有許多個labels(multiple labels)
2. 可以透過 Selector,幫我們縮小要尋找的物件
3. 目前 API 提供不再只是一個 key對應一個value(Equality-based requirement)的關係,我們也可以使用 matchExpressions 來設定更有彈性的Labels
```bash=
# 新增 label 至 指定pod中
kubectl label pods k8s-net-pod env=production
```
###### tags: `k8s`