云原生俱乐部-k8s知识点归纳(8)

这一部分主要讲一讲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: v1alpha1
      served: true                # 是否启用该版本
      storage: true               # 是否持久化存储
      schema:                     # 字段校验规则(OpenAPI v3)
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                replicas:
                  type: integer
                  minimum: 1
                version:
                  type: string
                  pattern: "^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: 3
  version: "8.0"

[3]实现控制器

以下是控制器的部分代码,一般来说,需要定义CR资源的结构体,并处理相应的字段。我们通过将控制器构建成docker容器镜像,并通过deployment(或其他控制器)来部署自定义的控制器。这样我们实现的控制器就会监听apiserver的请求并创建对应的资源。

复制代码
// controllers/mysqlcluster_controller.go

type 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 = true
    if 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: ServiceAccount
  name: mysql-operator-sa    # 控制器使用的 ServiceAccount
  namespace: default
roleRef:
  kind: Role
  name: mysql-operator-role
  apiGroup: 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 Controller
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              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-config
    group: elbv2.k8s.aws
    kind: 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  # 关联 GatewayClass
  listeners:
  - name: https
    hostnames: ["app.example.com"]  # 域名
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: 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-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: "/api"
    backendRefs:
    - name: api-svc
      port: 8080
  - matches:
    - headers:
      - name: env
        value: canary
    backendRefs:
    - name: canary-svc
      port: 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  # 引用已定义的 PriorityClass
  containers:
  - name: nginx
    image: 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/v1
    kind: Deployment
    name: php-apache       # 目标工作负载
  minReplicas: 1           # 最小副本数
  maxReplicas: 10          # 最大副本数
  metrics:
  - type: Resource
    resource:
      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 分钟。

相关推荐
deeper_wind1 小时前
k8s-容器化部署论坛和商城服务(小白的“升级打怪”成长之路)
linux·运维·容器·kubernetes
hello_ world.5 小时前
k8s笔记04-常用部署命令
笔记·容器·kubernetes
阿里云云原生5 小时前
拥抱 AI 原生!8月29日深圳,企业实践工作坊火热报名中
云原生
阿里云云原生5 小时前
不增加 GPU,首 Token 延迟下降 50%|LLM 服务负载均衡的新实践
云原生
阿里云云原生6 小时前
性能瓶颈定位更快更准:ARMS 持续剖析能力升级解析
云原生
小猿姐7 小时前
如何在 OpenShift 上部署和使用 KubeBlocks
云原生·kubernetes
小猿姐7 小时前
KubeBlocks for Kafka 揭秘
kafka·kubernetes
Monly217 小时前
Docker:部署Nginx
nginx·docker·容器
会飞的土拨鼠呀8 小时前
K8s部署MySQL8.0数据库
数据库·容器·kubernetes