这一部分主要讲一讲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 分钟。