[軟體概念入門系列][Workshop] Linux與後端服務 #3
前置準備
- 安裝minikube
https://minikube.sigs.k8s.io/docs/start/
成功執行以下指令
#minikube不能用root user啟動, 需要先執行以下指令把你的user加入docker group中
sudo usermod -aG docker {linux user name} && newgrp docker
minikube start
alias kubectl="minikube kubectl --"
minikube dashboard
並可以存取畫面上顯示的網址
如
Workshop目標
- 理解K8S中Pod, Service, Deployment及Ingress的運作方式
- 將workshop #2的container都改為Pod, Nginx部分改為Ingress
你會學習到
- 如何使用minikube作為一個本機的K8S cluster來部署物件
- 透過kubectl指令或minikube dashboard查看各種物件的執行狀況
- 使用deployment配合replica sets管理pods
- 使用service實作load balance, 並配合ingress實作反向代理
建立python api pod及service
- 建立兩個pod
將以下script建立為新檔案 pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod-1
labels:
app: workshop-app
spec:
containers:
- name: flask-api-container
image: bretthiggs/flask-api:1.0
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod-2
labels:
app: workshop-app
spec:
containers:
- name: flask-api-container
image: bretthiggs/flask-api:1.0
ports:
- containerPort: 3000
以上yaml檔表示會建立兩個pod, 分別為my-pod-1及my-pod-2
每個pod裡面都只包含一個container, 會由docker hub取得image
而image名稱版本為bretthiggs/flask-api:1.0
接著執行kubectl建立這兩個pod
kubectl apply -f pod.yaml
#確認pod是否正確產生
kubectl get pods
2. 建立service以存取pods
將以下script建立為service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: workshop-app
type: NodePort
ports:
- protocol: TCP
port: 3001
targetPort: 5566
nodePort: 30390
以上yaml會建立service物件, 並透過selector “workshop-app”將請求導到有篩選到的pod
port: 在k8s cluster中service本身要被內部服務呼叫用的port
targetPort: service要對應到的pod使用的port
nodePort: service要開放到k8s cluster外部被呼叫用的port
接著執行kubectl建立這個service
kubectl apply -f service.yaml
#確認service是否正確產生
kubectl get service
3. 確認service是否真的可被連接
以下curl可以重複執行幾次, 可看到請求會被分配到不同的pod上
#從minikube內部, 按下ctrl+d可以離開minikube ssh
minikube ssh
curl {service的cluster-ip}:3001
#從minikube外部
minikube ip
curl {minikube的ip}:30390
4. 查看pod log, 並透過minikube dashboard觀察相關物件
kubectl logs {pod name}
minikube dashboard
以deployment建立python api pod
由於自行管理pod並不是一個有效率的方式, 因此接下來我們會操作使用deployment並借助replica sets來部署並管理多個pod
- 移除剛剛建立的pod並撰寫deployment設定檔
kubectl delete -f pod.yaml
將以下script建立為deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: workshop-app
spec:
containers:
- name: flask-api-container
image: bretthiggs/flask-api:1.0
ports:
- containerPort: 3000
selector:
matchLabels:
app: workshop-app
以上script將會以template中的內容建立3個pod, 而selector代表這個deployment透過”workshop-app”這個label取得並管理符合條件的pod
接著執行以下指令套用deployment並確認相關物件有產生
kubectl apply -f deployment.yaml
kubectl get deployment
kubectl get pods
2. 確認pods可透過service存取
執行剛剛的語法確認請求有被分配到三個pod
#從minikube內部, 按下ctrl+d可以離開minikube ssh
minikube ssh
curl {service的cluster-ip}:3001
#從minikube外部
minikube ip
curl {minikube的ip}:30390
3. 調整deployment中的replicas數量並套用, 觀察replica sets及pod行為
將deployment.yaml中的replicas從3改為7, 並重新執行以下指令
kubectl apply -f deployment.yaml
kubectl get replicaset
kubectl get pods
反覆這樣的動作調整replicas並觀察replica sets及pod
也可透過dashboard觀看
以deployment, service, ingress建立python api pod並設定反向代理
- 移除先前的deployment及service
執行以下指令移除deployment及service
kubectl delete -f deployment.yaml
kubectl delete -f service.yaml
2. 建立分成兩個群組的pod分群
將以下script建立成deployment-reverse-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment-a
spec:
replicas: 2
template:
metadata:
labels:
app: workshop-app-group-a
spec:
containers:
- name: flask-api-container-group-a
image: bretthiggs/flask-api:1.0
ports:
- containerPort: 3000
selector:
matchLabels:
app: workshop-app-group-a
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment-b
spec:
replicas: 2
template:
metadata:
labels:
app: workshop-app-group-b
spec:
containers:
- name: flask-api-container-group-b
image: bretthiggs/flask-api:1.0
ports:
- containerPort: 3000
selector:
matchLabels:
app: workshop-app-group-b
接著執行以下指令建立deployment
kubectl apply -f deployment-reverse-proxy.yaml
3. 建立兩個service分別對應到兩個pod的分群
將以下script建立成service-reverse-proxy.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service-group-a
spec:
selector:
app: workshop-app-group-a
type: NodePort
ports:
- protocol: TCP
port: 3001
targetPort: 5566
---
apiVersion: v1
kind: Service
metadata:
name: my-service-group-b
spec:
selector:
app: workshop-app-group-b
type: NodePort
ports:
- protocol: TCP
port: 3002
targetPort: 5566
接著執行以下指令建立service
kubectl apply -f service-reverse-proxy.yaml
4. 建立ingress將指定的路徑對應到個別的service
將以下script建立為ingress-reverse-proxy.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: workshop-reverse-proxy.com
http:
paths:
- path: /group-a
pathType: Prefix
backend:
service:
name: my-service-group-a
port:
number: 3001
- path: /group-b
pathType: Prefix
backend:
service:
name: my-service-group-b
port:
number: 3002
以上script幾點簡述
host: 代表要定義的domain
path: 代表此domain下符合的路徑要做的處理
service: 符合的路徑要轉導到的service名稱
port: 對應到該service開放的port
nginx.ingress.kubernetes.io/rewrite-target: 代表符合的路徑被導轉後要改寫url成什麼值, 以此範例來說會被改寫為根目錄
綜合以上
workshop-reverse-proxy.com/group-a會被導轉到service “my-service-group-a” 以存取到後面的pod, 而url會被改寫為“/”, 亦即url會變成
“http://{my-service-group-a的cluster-ip}:3001/”
workshop-reverse-proxy.com/group-b以此類推
如果你的minikube從來沒有啟用過ingress, 請先執行以下指令, 否則可以跳過此步
minikube addons enable ingress
kubectl get pods -n ingress-nginx
接著執行以下指令建立ingress
kubectl apply -f ingress-reverse-proxy.yaml
5. 驗證ingress是否有效
接著我們要設定wsl中的host file, 以讓workshop-reverse-proxy.com可以解析為minikube ip
sudo vim /etc/hosts
請在檔案中加入一條記錄, 若你是從workshop #1做過來的請留意這條可能已經存在, 就直接調整ip即可
{minikube ip} workshop-reverse-proxy.com
接著我們可以嘗試以下指令看是否ingress有生效
curl workshop-reverse-proxy.com/group-a
curl workshop-reverse-proxy.com/group-b
Recap
回顧我們這次做過的內容
- 撰寫pod描述檔並以docker image建立對應的pod, 使用service讓pod可以被存取
- 撰寫deployment描述檔管理對應的pod, 調整replica數量套用後, K8S會自動增減pod
- 使用ingress依據不同的path將請求導轉到service, 以實現反向代理
延伸思考
- K8S怎麼判斷pod是否健康, 何時需要產生新的pod來取代舊的
- K8S有辦法依據pod資源使用量來auto scaling嗎
- 如何使用K8S實作藍綠部署或其他的部署策略
- 如何用ConfigMap, Secret管理設定檔