跳至主要内容

K8s Basic

K8s 元件架構

圖片來源

Master Node

元件說明
api-server公開基礎 Kubernetes API 的方式,提供操作 k8s 的統一入口,例如 kubectl 指令
etcd儲存 k8s cluster 的資料,並持久化,不會遺漏資料。當 Master Node 故障時,可以透過 etcd 儲存的資料`還原
scheduler負責資源調度,監聽每個 pod 的內部資源使用率,確保工作負載不會超過可用資源。佈署新的容器時,scheduler 會決定要放到哪個 pod
controller manager監控節點的狀態,根據設定重啟、刪除、擴增

Worker Node

元件說明
podk8s 的最小單位,負責執行容器。裡面所有容器共享儲存空間及網路,因此 pod 裡面的容器只需透過 localhost 的 port 就可以溝通
kubelet監控 Worker Node 的運行狀態,當 Pod 出問題時,會通知 Master 節點的 Controller Manager 處理,維持整個 Cluster 的運作
kube-proxy主要負責網絡代理,負載均衡的實現,同時會根據傳入請求的 IP 和 Port,將流量轉發到指定的合適的 Pod 裡面的容器中。

Pod

  • K8s 部署管理的最小單位
  • 由一個或多個容器組成
  • Pod 裡面的容器共享儲存空間及網路

容器生命週期

  • K8s 會監控每個容器的狀態,可以透過 kubectl describe pod <pod name> 查看 pod 底下每個容器的狀態
狀態描述
Pending等待 K8s 分配適當的節點來運行 Pod,或容器尚未建立、執行
RunningPod 成功在節點上運行,容器內的應用正在執行。
SucceededPod 內的所有容器都成功完成並結束,通常用於一次性任務。
FailedPod 內的所有容器以非零狀態結束,表示應用程式遇到問題。
Unknown無法確定 Pod 狀態的情況,可能由於通信問題或其他原因。

容器重啟策略

  • Pod 中可以使用容器的重啟策略來定義在容器退出後 k8s 該如何處理
  • 這些策略可以根據程式的需求調整。例如,如果程式是一個單獨的任務,可能會希望在失敗時重啟它;而對於一個排程任務,可能希望它僅運行一次而不自動重啟
  1. Always(始終重啟):當容器退出時,將自動重啟。這是預設的重啟策略
spec:
restartPolicy: Always
  1. OnFailure(僅在失敗時重啟):當容器以非零退出狀態退出時,將自動重啟
spec:
restartPolicy: OnFailure
  1. Never(從不重啟):不會自動重啟容器,無論何時容器退出
spec:
restartPolicy: Never

容器探針

設定教學

  • 用來檢測容器狀態的機制
  • 可以利用 exechttpGetgrpctcpSocket 四種方式檢測
名稱描述
Liveness Probe用來檢測容器是否運行正常,如果失敗 k8s 會依據重啟策略處理
Readiness Probe用來檢測容器是否已經可以接受流量,如果失敗 k8s 會依據重啟策略處理
Startup Probe用來檢測容器是否已經啟動並且可以接受流量。與 Readiness Probe 不同,啟動探針僅在容器啟動時執行,避免在啟動過程中處於無限重啟的狀態

Workload Management

多數的時候,K8s 中會有多個 pod,如果要一個一個管理會非常麻煩,透過 Workload management 的設定,可以讓 K8s 一次管理多個 pod

Deployment (ReplicaSet)

  • 所有的 pod 都是無狀態,所以任何一個 pod 都可以互相取代
  • 自動擴展和自我修復:Deployment 可以根據指定的規則自動調整 pod 的副本數量,以應對流量變化和節點失敗。當 pod 失敗或被刪除時,Deployment 也可以自動修復或替換它們。
  • 滾動更新:Deployment 支援滾動更新策略,允許您進行應用程式版本的平滑升級和回滾操作。這可以減少應用程式的停機時間,並確保新版本的穩定性。
  • 模板化配置:Deployment 使用 PodTemplateSpec 定義應用程式的 pod 模板,包括容器映像、資源限制、環境變數等。這使得在部署應用程式時可以方便地重用和管理配置。
  • 故障恢復:Deployment 可以監控 pod 的狀態並采取必要的措施來恢復服務的可用性。它可以自動重新啟動失敗的 pod,或者根據設置的健康檢查條件進行重新調度。
  • 滾動回滾:如果新版本的應用程式出現問題,Deployment 允許您輕鬆地回滾到之前的穩定版本。它會逐步將新版本的 pod 降級為舊版本,以確保應用程式的可用性。
# 在這個範例中,我們創建了一個名為 nginx-deployment 的 Deployment,指定了要運行 3 個副本的 Nginx 應用程式。該 Deployment 使用標籤選擇器將 pod 與 Deployment 關聯起來,並且使用了一個包含 Nginx 映像的容器。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

StatefulSet

DaemonSet

Service

Pod 的生命周期不是並永久的,一但重啟 IP 就會跟著改變,而 Service 抽象層,可以用 Label Selector 定義一組相同邏輯的 Pod,為這組 Pod 建立一個同一的存取管道

Cluster IP

k8s 內部的虛擬 IP,只能在 k8s 內部使用

apiVersion: v1
kind: Service
metadata:
name: service
spec:
selector:
app: nginx # 標籤是 app: nginx 的 pods
type: ClusterIP # 預設是 ClusterIp,其他還有 NodePort, LoadBalancer, ExternalName
ports:
- name: http
port: 80 # Service 對外開放的 port
targetPort: 80 # Pod 的 port
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP

Node Port

開放一個 port,讓外部可以透過這個 port 來訪問 k8s 的 pod

Load Balancer

Load Balancer 是另一個讓外部可以直接存取 k8s 內部 pod 的方式,但需要搭配外部的 load balancer 服務

External Name

把 Service 導向指定的 DNS name

Ingress

  • 在 K8s 中我們可能有多個 service,每個 service 都有自己的 IP 和 port。使用 Ingress 可以提供了一個統一的入口,將這些 service 暴露給外部,並隱藏 service 的 IP
  • 需要搭配 Ingress Controller,它負責監聽和處理進入 K8s 的流量,並根據 Ingress 中定義的規則來將流量導向到 service
# 在這個範例中,我們有兩條規則:
# 第一條規則是針對主機名為 example.com,當請求的路徑是 /app 時,將流量導向到名為 app-service 且 port 80 的 service
# 第二條規則是當請求的路徑是 /api 時,將流量導向到名為 api-service 且 port 8080 的 service

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
# 註釋 nginx.ingress.kubernetes.io/rewrite-target: /,它指定了在導向到後端服務時要重寫 URL 的目標。這意味著對於 /app 的請求將會被重寫為 /,而對於 /api 的請求則不會被重寫。
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
# 加入 SSL(Secure Sockets Layer)或 TLS(Transport Layer Security),讓 host 可以透過 https 訪問
tls:
- hosts:
- example.com
# 將 SSL/TLS 憑證轉換為 Kubernetes Secret
# kubectl create secret tls your-secret-name --cert=path/to/tls.crt --key=path/to/tls.key
secretName: your-secret-name
rules:
- host: example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080

參考資料