這篇將會開始介紹在 K8s 組出服務必備的元素,第一篇來講的是 Pod & Workloads。
接下來的三篇內,會簡介每個 Kubernetes 裡面組出基礎服務所需的元件。
Pod 是 K8s 的最小單位,每個 Pod 內部可能會有一個或多個 Container,而一個 Pod 會對應到一個應用程式,同一個 Pod 中的 Containers 則會共享相同的網路資源(如:IP地址、主機名稱等)。
這個是 Pod 的基礎設定:
# 1. Save as `nginx-pod.yaml`
# 2. In bash, `kubectl apply -f nginx-pod.yaml`
# 3. If you want to remove, `kubectl delete -f nginx-pod.yaml`
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
想要實作可以看上面的三行敘述:
nginx-pod.yaml
kubectl apply -f nginx-pod.yaml
套用進 K8s 裡面kubectl delete -f nginx-pod.yaml
就可以讓 K8s 刪掉通常實際在部署的時候也不會用 Pod,而是會用下面的那幾種 Workloads 來做,這邊只是先說 K8s 的基礎單位,之後要做 Debug 的時候優先都從 Pod 找起。
ReplicaSet 跟 Deployment 可以合併介紹,Deployment 也是基於 ReplicaSet 實作而成的。
ReplicaSet 就是一組重複多個 Pod 組合而成,會有這樣的需求是為了要分攤運算
我們來用一張圖解釋
今天上述的圖看起來架構沒有問題,但如果流量突然提高,只有一個 Pod 其實就很容易掛掉,就算你給單個的 Pod 資源較多,但回應速度還是會很慢,因此我們就會需要 ReplicaSet 來分攤流量。
Deployment 又是為了什麼而產生的呢?因為 ReplicaSet 不能做 Image 替換,Deployment 可以,這樣就可以做到 Rolling update,可以讓服務不斷線的情況下滾動升級。
Deployment 的基礎架構如下:
# 1. Save as `nginx-deploy.yaml`
# 2. In bash, `kubectl apply -f nginx-deploy.yaml`
# 3. If you want to remove, `kubectl delete -f nginx-deploy.yaml`
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
這裡要注意的是,.spec.selector.matchLabels
必須跟 .spec.template.metadata.labels
相同,不然會被系統 Reject,雖然不一定要跟原本 Deployment .metadata.labels
相同,但方便起見還是設定相同。
大部分的應用程式都是 Stateless,但如果需要有狀態管理,StatefulSet 會是比較適用的情境。
這樣說感覺有點抽象,但可以用以下資訊來判斷是否要用到 StatefulSet:
.spec.podManagementPolicy
預設 OrderedReady
,也可以改成 Parallel
同時產生)依照以上這些判斷,其實可以知道,如果想要用 Pod 來組 MongoDB Cluster 或 MySQL Cluster,Deployment 是不適合套用這個情境,StatefulSet 會是較佳的解決方式。
因為這裡還沒有介紹 PVC,這裡會寫沒有 .spec.volumeClaimTemplates
的版本
# 1. Save as `nginx-sts.yaml`
# 2. In bash, `kubectl apply -f nginx-sts.yaml`
# 3. If you want to remove, `kubectl delete -f nginx-sts.yaml`
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: "nginx-sts"
spec:
selector:
matchLabels:
app: "nginx-sts"
serviceName: "nginx-sts"
replicas: 3
template:
metadata:
labels:
app: "nginx-sts"
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
kubectl apply
進去以後,系統會依照編號產生 Pod。
DaemonSet 會把 Pod 部署在每一個節點上,也就是在後台跑的程式,通常會應用在需要監控的情形,像是 Node metric、Logs collections。
DaemonSet 的基礎範例如下:
# 1. Save as `nginx-ds.yaml`
# 2. In bash, `kubectl apply -f nginx-ds.yaml`
# 3. If you want to remove, `kubectl delete -f nginx-ds.yaml`
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx-daemonset
spec:
selector:
matchLabels:
app: nginx-daemonset
template:
metadata:
labels:
app: nginx-daemonset
spec:
tolerations:
# 預設 DaemonSet 是不會把 Pod 放到 Control plane (Master node) 上
# 加了 tolerations 這幾行設定就可以放到 Control plane 上面了
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: nginx-daemonset
image: nginx:alpine
resources:
limits:
cpu: 250m
memory: 512Mi
requests:
cpu: 250m
memory: 512Mi
Job 就代表只有一次性的工作,我目前看過 Job 會出現的情形就是 GitLab 升級檢查的時候,會做 Pre-check 的工作,他們有規定版本升級步驟,為了確保升級、Migrate 可以順利進行。
# 1. Save as `pi-job.yaml`
# 2. In bash, `kubectl apply -f pi-job.yaml`
# 3. If you want to remove, `kubectl delete -f pi-job.yaml`
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-ttl
spec:
ttlSecondsAfterFinished: 100 # 100 秒以後,此 Pod 將會被自動清除,沒有設定就不會清除
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
CronJob 就是定時工作,如果 Application 本身會產生 Caches 需要清理,或者每天檢查更新版本,這些都可以放在 CronJob 進行。
如果想要再找其他的相關範例,可以去 K8s 官方文件來去閱讀。
本系列內容也會同步貼到我的 Blog https://blog.yangjerry.tw 歡迎來我的 Blog 點一下 RSS 追蹤,那我們就下一篇文章見啦!