這一部分主要講一講CRD客戶資源定義、Gateway API、Priority Class優先類、HPA自動擴縮這四部分內容。還剩下Argo CD的內容了整個k8s,至于operator的話單獨有一本書,都是實戰內容。
CRD客戶資源定義
先來講一講這節內容的幾個核心術語,Custom Resource (CR)?,用戶定義的資源實例。CRD,定義 CR 的 Schema(字段、類型、校驗規則)。還有controller,監聽 CR 變化并執行調諧邏輯的組件,準確來說是監聽apiserver。
[1]定義CRD
kind資源類型寫CRD,并定義CR的kid標識,以及單復數形式。主要定義的是CR的字段、類型和校驗規則。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:name: mysqlclusters.db.example.com
spec:group: db.example.com # API 組名scope: Namespaced # 資源作用域(Namespaced/Cluster)names:plural: mysqlclusters # API 中使用的復數形式singular: mysqlcluster # CLI 中使用的單數形式kind: MySQLCluster # Kind 標識shortNames: ["mysql"] # 縮寫(如 `kubectl get mysql`)versions:- name: v1alpha1served: true # 是否啟用該版本storage: true # 是否持久化存儲schema: # 字段校驗規則(OpenAPI v3)openAPIV3Schema:type: objectproperties:spec:type: objectproperties:replicas:type: integerminimum: 1version:type: stringpattern: "^5.7|8.0$"
[2]定義CR
即使不創建控制器,也能夠創建自定義資源的實例,即CR。可以通過kubectl get MySQLCluster -n ns來查看,但是注意的是,此時CR只是一個存儲在etcd中靜態聲明,并不會觸發集群的實際操作。除非有控制器能夠處理。
apiVersion: db.example.com/v1alpha1
kind: MySQLCluster
metadata:name: my-mysql
spec:replicas: 3version: "8.0"
[3]實現控制器
以下是控制器的部分代碼,一般來說,需要定義CR資源的結構體,并處理相應的字段。我們通過將控制器構建成docker容器鏡像,并通過deployment(或其他控制器)來部署自定義的控制器。這樣我們實現的控制器就會監聽apiserver的請求并創建對應的資源。
// controllers/mysqlcluster_controller.gotype MySQLClusterReconciler struct {client.Client // Kubernetes 客戶端Scheme *runtime.Scheme
}func (r *MySQLClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {// 1. 獲取 CR 對象cluster := &dbv1.MySQLCluster{}if err := r.Get(ctx, req.NamespacedName, cluster); err != nil {return ctrl.Result{}, client.IgnoreNotFound(err)}// 2. 調諧邏輯:根據 CR 的 Spec 創建實際資源if err := r.reconcileDeployment(cluster); err != nil {return ctrl.Result{}, err}// 3. 更新 CR 狀態cluster.Status.Ready = trueif err := r.Status().Update(ctx, cluster); err != nil {return ctrl.Result{}, err}return ctrl.Result{}, nil
}// 關聯資源創建邏輯
func (r *MySQLClusterReconciler) reconcileDeployment(cluster *dbv1.MySQLCluster) error {deploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: cluster.Name + "-deploy",Namespace: cluster.Namespace,},Spec: appsv1.DeploymentSpec{Replicas: &cluster.Spec.Replicas,Template: corev1.PodTemplateSpec{Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "mysql",Image: "mysql:" + cluster.Spec.Version,}},},},},}// 設置 OwnerReference(建立 CR 與 Deployment 的關聯)ctrl.SetControllerReference(cluster, deploy, r.Scheme)return r.CreateOrUpdate(context.TODO(), deploy)
}
[4]訪問權限
注意,CR屬于集群資源,如果集群范圍內創建CR,那么控制器就需要集群權限。如果僅在當前命名空間創建CR,那么當前命名空間的權限就足夠了。主要包括get、create、update等等權限,盡量只給予必要的權限。
# config/rbac/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: mysql-operator-role
rules:
- apiGroups: ["example.com"] # CRD 所屬的 API 組resources: ["mysqlclusters"] # 自定義資源名稱(復數形式)verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]resources: ["deployments"]verbs: ["*"] # 全權限
- apiGroups: [""]resources: ["pods", "services", "configmaps"]verbs: ["create", "get", "list", "watch"]
- apiGroups: [""]resources: ["events"]verbs: ["create", "patch"]
---
# config/rbac/role_binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: mysql-operator-rolebinding
subjects:
- kind: ServiceAccountname: mysql-operator-sa # 控制器使用的 ServiceAccountnamespace: default
roleRef:kind: Rolename: mysql-operator-roleapiGroup: rbac.authorization.k8s.io
Gateway API
Gateway?API?是?Kubernetes?官方推出的???下一代?Ingress?和?Service?Mesh?標準??,旨在解決傳統?Ingress?的局限性,提供更強大、更靈活的流量管理能力。
[1]ingress
首先回顧一下ingress的概念和作用,ingress定義與service之上,將路由的訪問流量轉發到service對應的端口(要提前部署控制器)。路徑有Prefix和Exact兩種,前者是前綴路由匹配,也可以叫兜底路由。后者是精確匹配該路由。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: my-app-ingress
spec:ingressClassName: nginx # 指定使用 Nginx Ingress Controllerrules:- host: example.comhttp:paths:- path: /pathType: Prefixbackend:service:name: my-serviceport:number: 80
[2]GatewayClass、Gateway、HTTPRoute
同樣的,使用Gateway API也需要指定控制器(提前部署).
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:name: alb-gateway-class
spec:controllerName: "alb.ingress.k8s.aws" # 指定控制器parametersRef: # 可選參數(如 AWS ALB 配置)name: alb-configgroup: elbv2.k8s.awskind: IngressClassParams
至于Gateway,需要定義協議,端口之類的規則,同時和GatewayClass關聯起來。需要指定spec.linsteners.hostname字段,定義提供HTTP的主機IP或者域名,否則該網關不監聽任何的請求,即使HTTPRoute定義也沒有用。
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:name: public-gateway
spec:gatewayClassName: alb-gateway-class # 關聯 GatewayClasslisteners:- name: httpshostnames: ["app.example.com"] # 域名port: 443protocol: HTTPStls:mode: TerminatecertificateRefs:- kind: Secretname: example-com-tls
定義HTTPRoute資源,需要和Gateway關聯起來,并定義具體的路由規則。因為Gateway并不定義路由規則,只聲明協議、端口,監聽的域名等。具體的訪問規則需要HTTPRoute來定義,并將流量轉發給service。
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:name: full-route
spec:hostnames: ["app.example.com"] # 域名parentRefs:- name: public-gatewayrules:- matches:- path:type: PathPrefixvalue: "/api"backendRefs:- name: api-svcport: 8080- matches:- headers:- name: envvalue: canarybackendRefs:- name: canary-svcport: 80
PriorityClass
PriorityClass 是 Kubernetes 調度系統的“緊急程度標簽”,用于解決資源競爭時的調度決策問題。 通過數值優先級和搶占機制定義 Pod 的相對重要性,當集群資源不足時,PriorityClass 決定哪些 Pod 應該優先獲得資源,并且高優先級 Pod 可以搶占低優先級 Pod 的資源。
通過名字就可以知道優先級類是定義的資源模板,PriorityClass 是非命名空間資源,是在集群級別定義的,在所有命名空間可見。值的通常范圍為 0- 10,000,000,系統組件建議≥1,000,000,業務應用不超過 5,000,000。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:name: high-priority
value: 1000000 # 優先級數值(必填)
globalDefault: false # 是否作為集群默認優先級(謹慎設置!)
description: "用于關鍵業務 Pod" # 描述信息
preemptionPolicy: PreemptLowerPriority # 搶占策略(默認值)
PreemptLowerPriority(允許搶占)或?Never(禁止搶占),在定義資源的時候,通過spec.PriorityClassName來指定該資源使用的優先級類。PriorityClass 獨立于 QoS 等級(如?Guaranteed
/Burstable
),但高優先級 Pod 通常應配置高 QoS。
apiVersion: v1
kind: Pod
metadata:name: nginx-high-priority
spec:priorityClassName: high-priority # 引用已定義的 PriorityClasscontainers:- name: nginximage: nginx
HPA自動擴縮
HPA(Horizontal Pod Autoscaler)是 Kubernetes 中的一種自動擴縮容機制,用于根據資源使用情況 動態調整 Pod 副本數量,確保應用能夠應對負載的變化,高負載時自動擴容(保證服務可用性),低負載時自動縮容(節約資源成本)。
以下定義的HPA會匹配名稱為php-apache的deployment,并應用該策略,最小副本數為1,最大副本數為10。Metrics Server 定期(默認 15s)從 Kubelet 收集所有 Pod 的 CPU/Memory 使用量,HPA 控制器通過 Metrics API 獲取當前指標值。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:name: php-apache-hpa
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: php-apache # 目標工作負載minReplicas: 1 # 最小副本數maxReplicas: 10 # 最大副本數metrics:- type: Resourceresource:name: cpu # 指標類型target:type: Utilization # 目標值類型(Utilization 或 AverageValue)averageUtilization: 50 # CPU 使用率閾值(50%)
CPU 利用率= (Pod 實際 CPU 使用量/Pod 的 CPU Request 值)×100%,當cpu使用率超過50%的時候,期望副本數= ceil[當前副本數×(當前指標值/目標指標值)],結果會被限制在 minReplicas 和 maxReplicas 之間。HPA 通過修改 Deployment 的 replicas 字段觸發擴縮容,擴 容時默認無延遲(可配置 scaleUp 規則),縮容默認等待 5 分鐘。