---
# System prepended metadata

title: Kubernetes Workloads
tags: [K8S]

---

---
lang: zh-tw
title: Kubernetes Workloads
tags: K8s
---

# Workloads

+ Pods
+ Controllers

## What is a Pod?

+ Pod 是可以在Kubernetes中被建立和管理的最小可部署單位

### Using Pods

+ Pod 在Cluster中主要有兩種用法

|||
| -------- | -------- |
|單容器|最常見的使用方法|
|多容器|封裝多個緊密關聯且需要共用資源的容器組成|

1. 可以將Pod看作單個容器的包裝器，Kubernetes直接管理Pod，而不是容器
2. 只有在容器的關聯緊密時才使用多個容器運行在一個Pod
3. 每個Pod都只運行給特定的應用
4. 水平擴展應該使用多個Pod，每個應用使用一個Pod，稱為Replication
5. 通常使用一種Workload resource和對應的Controller建立和管理一組Pod Replication
6. Workloads能處理Replica的管理、上線，並在Pod故障時建立可替換的Pod

### Storage in Pods

+ 一個Pod可以設置一組共用的Storage Volume
+ Volume 允許Pod 中的容器重新啟動保留持久化資料
+ Pod 中的所有容器都可以訪問該共用Volume，從而共用資料

### Pod networking

+ Kubernetes為每個Pod都分配了唯一的IP位址，稱為Pod IP
+ Pod內每個容器共用Pod IP
+ Pod內的容器間可以用`localhost`溝通

### Pod 資源配置

+ Kubernetes裡，通常以千分之一的CPU配額為最小單位，用m來表示
+ 通常一個容器的CPU配額被定義為100~ 300m，即佔用0.1~0.3個CPU
+ 記憶體配額與CPU相似，單位是bytes
+ 資源配額限定需要設定以下兩個參數

|||
| -------- | -------- |
|requests|資源的最小需求量|
|limits  |資源的最大允許量|

+ [Pod Template](/QzphVaWxTYCw2x-3JSK3tQ?view)

## Controller
+ ReplicaSet
+ ReplicationController
+ Deployment
+ StatefulSet
+ DaemonSet
+ Job and CronJob
+ Horizontal Pod Autoscaler

### [ReplicaSet](/rn63_NYCS9qC0F2VgEyaiw?view)

+ 目的是维護一組在任何時候都處於運行的Pod
+ 創建新的Pod會使用腳本內的Pod Template
+ 如果要使用`rolling update`請使用Deployment
+ 主要被Deployment 用來協調Pod 建立、刪除和更新

### ReplicationController

+ 可縮寫為"rc"
+ 確保有特定數量的Pod 處於運行狀態
+ 建立的Pod在失敗、被刪除或被終止時會自動替換
+ 會監控跨多個Node的多個Pod


1. ReplicaSet, ReplicationController，都集中於Deployment管理，都被Deployment用作協調Pod建立、刪除和更新的機制。
2. 建議使用Deployment而不是直接使用ReplicaSet，除非需要自定義更新流程或不需要更新

### [Deployment](/ykmB_w6CQcaDJDqqgk13IQ?view)

![](https://i.imgur.com/kaic8l3.jpg =70%x)

+ 可縮寫為`deploy`
+ Deployment為Pod和ReplicaSet提供更新能力
+ Deployment管理多個ReplicaSet原因在於Deployment支援回滾機制
+ 部署新的Deployment設定時，Kubernetes會依據新設定重新生成一個ReplicaSet並保留舊設定
+ 未來有需要就能直接用舊的ReplicaSet回滾到先前狀態
+ 透過擴展Deployment增加服務承載量
+ 命名規格：[Deployment_name]-[ReplicaSet_String]-[Pod_String]
+ 能確保服務的Pod數量（replicas）能滿足設定的值以及支援Rolling Update
+ Deployment支援Rollback的機制

### [StatefulSet](/ZhmvgaP7Sv-Fl-AVf5fuHw?view)


+ 可縮寫為`sts`
+ 用來管理有狀態的服務或應用
+ 用來管理Deployment和擴展一組Pod
+ 每個Pod提供序號和唯一性保證
+ 適合部署需要唯一持久身份和穩定主機名稱的應用

### StatefulSet 應用場景

+ 穩定、唯一的網路識別碼
+ 穩定、持久的Storage
+ 有順序的Deploy, Scale
+ 有順序、自動`Rolling Update`

例如MySQL, MongoDB, Zookeeper

### StatefulSet 使用限制

+ Pod的Storage必須是PersistentVolume
+ 刪除或收縮不會刪除關聯的Volume
+ StatefulSet需要Headless Service負責Pod的網路識別
+ 刪除StatefulSet時，StatefulSet不保證Pod會终止，因此為了StatefulSet的Pod可以有順序和graceful終止，在刪除之前可以將StatefulSet的replicas設為0

### [DaemonSet](/PK6JPx3lRSGKCZv1EWXYWg?view)

+ 確保全部或特定Node運行一個Pod的副本
+ Node加入Cluster時，也會為它新增一個Pod
+ Node從Cluster移除時，這些Pod也會被回收
+ 刪除DaemonSet將會刪除它建立的所有Pod

### DaemonSet 典型用法

+ 在每個Node上運行Cluster Storage Daemon
+ 在每個Node上運行Logs Collection Daemon
+ 在每個Node上運行Node Monitoring Daemon

### 與Deployments差異

|            |      |
| ---------- | ---- |
| Deployment | 無狀態的服務使用 |
| DaemonSet  | Pod 副本運行在全部或特定Node<br />並需要優先於其它Pod啟動時 |

Deployment：
建議為無狀態服務使用，比如前端服務。對這些服務而言，副本的數量進行擴展收容、Rolling Update，比精確控制Pod運行在某個Node上要重要。

### Job and CronJob

|          |      |
| -------- | ---- |
| Job |建立單一工作的Job，完成後即結束|
| CronJob |建立基於時間調度的Job<br />週期性的在指定的時間執行|

#### Job

+ Pod成功終止時，立即視Job為完成狀態
+ Job完成時不會再建立新的Pod
+ 已有的Pod不會被刪除
+ 被保留的Pod可以查看Log以更檢查錯誤

#### CronJob

+ CronJob就像crontab文件中的一行
+ 用Cron格式編寫，周期性的在指定的時間執行Job
+ 時間都是基於kube-controller-manager的時區
+ CronJob僅負責建立與它調度時間匹配的Job，Job又負責管理它代表的Pod

### Horizontal Pod Autoscaler

+ Pod水平自動擴充，簡稱HPA
+ apiVersion: autoscaling/v1
+ HPA不適用於無法擴展收容的控制器，如DaemonSet
+ 透過度量指標對目標Pod進行擴展收容

|||
| -------- | -------- |
|CPUUtilizationPercentage|Pod CPU使用率的平均值|
|應用自定的度量指標|如：服務在每秒內對應的請求數(TPS或QPS)|

1. 透過追蹤分析RC控制的所有目標Pod的負載變化情況，來確定是否需要針對性調整目標Pod的備份數

## 實作 Deployments

```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostnames
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hostnames
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
        - name: hostnames
          image: mirrorgooglecontainers/serve_hostname
          resources:
            requests:
              memory: "128Mi"
              cpu: "250m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          ports:
            - containerPort: 9376
              protocol: TCP
```

1. apiVersion: 元件版本號
2. kind: 元件的屬性，常見有`Pod`, `Node`, `Deployment`, `Service`, `Namespace`, `StatefulSet`, `DaemonSet`等
3. metadata.name: 建立名為`hostnames-deployemnt`的pod
4. spec.replicas: Deployment創建三個Pod副本，預設是1
5. spec.selector: 指令這個Deployment的規則適用哪些Pod
6. spec.selector: 定義Deployment 如何找到要管理的Pods，matchLabels是{key, value}
7. `teamplate`包含以下字段
    7-1. Pod標記為`app: hostnames`
    7-2. `.template.spec`指令Pods運行一個容器
    7-3. 創建一個容器並用`name`定段命名

Apply Deployment
    
    kubectl apply -f ./endpoints-deployment.yaml
    
Check Deployment Status

    kubectl get deploy
    
Check ReplicaSet

    kubectl get rs
    
Check Pods Status

    kubectl get pod
    
Update System with zero downtime rollout

    kubectl edit deployment hostnames-deployment
    kubectl rollout history deployment hostnames-deployment #查看所有版本
    kubectl rollout undo deployment hostnames-deployment #恢復上一版
    kubectl rollout undo deployment hostnames-deployment --to-revision=2 #指令版本
    
Gain more information of Deployment

    kubectl descirbe deployment
    
Scale Deployment

    kubectl scale deployment hostnames-deployment --replicas=5
    kubectl autoscale deployment hostnames-deployment --min=3 --max=5 --cpu-percent=80
    
Pause, Resume Deployment

    kubectl rollout pause deployment hostnames-deployment
    kubectl set images deployment hostnames-deployment ${container name}=${image name:tag}
    kubectl set resources deployment hostnames-deployment -c=hostnames --limits=cpu=200m,memory=512Mi
    kubectl rollout resume deployment hostnames-deployment

### Kubernetes Dashboard

Install the Dashboard application into our cluster

    kubectl apply -f ./k8s-dashboard.yaml

Check the resources it created based on the new namespace created

    kubectl get all -n kubernetes-dashboard

Start a kubectl proxy

    kubectl proxy
    
Enter the URL on your browser

    http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

Create a new ServiceAccount

    kubectl apply -f k8s-dashboard-service-account.yaml

Create a ClusterRoleBinding for the ServiceAccount

    kubectl apply -f k8s-dashboard-clusterrolebinding.yaml
    
Get the Token for the ServiceAccount

    kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
    
