创建自定义资源

自定义资源定义 (CRD) 是共享的全局对象,它将 Kubernetes API 扩展到标准资源类型之外。CRD 用作自定义资源 (CR) 实例的蓝图。您创建用来指定所需环境状态的 CR,操作器监控 CR 以维护其命名空间内对象的状态。

为方便起见,此示例 CR 使用 YAML 格式的文件。有关所有可用 CR 设置的详细信息,请参阅自定义资源参数

先决条件

创建 Secret

使用 kubectl 命令行工具创建 Secret 以将敏感信息存储在您的自定义资源中,而不会暴露敏感信息所代表的值。

  1. 为 Vertica 许可证创建一个名为 vertica-license 的 Secret:

    $ kubectl create secret generic vertica-license --from-file=license.dat=/path/to/license.dat
    

    默认情况下,Helm 图表使用免费的社区版许可证。此许可证仅限于 3 个节点和 1 TB 数据。

  2. 创建名为 su-passwd 的 Secret 来存储您的超级用户密码。如果不添加超级用户密码,则没有与数据库关联的密码:

    $ kubectl create secret generic su-passwd --from-literal=password=secret-password
    
  3. 以下命令将 S3 兼容的公共访问权限和密钥凭证存储在名为 s3-creds 的秘密中:

    $ kubectl create secret generic s3-creds --from-literal=accesskey=accesskey --from-literal=secretkey=secretkey
    
  4. 本教程配置一个证书颁发机构 (CA) 捆绑包,该捆绑包对与自定义资源的、与 S3 兼容的连接进行身份验证。创建名为 aws-cert 的 Secret:

    $ kubectl create secret generic aws-cert --from-file=root-cert.pem
    
  5. 您可以在 Vertica 服务器文件系统中挂载多个证书。以下命令在名为 mtls 的 Secret 中为您的 mTLS 证书创建一个 Secret:

    $ kubectl create secret generic mtls --from-file=mtls=/path/to/mtls-cert
    

必填字段

VerticaDB 定义以用来描述版本、资源类型和元数据的必填字段开头:

apiVersion: vertica.com/v1beta1
kind: VerticaDB
metadata:
  name: verticadb

前面的示例定义了以下内容:

  • apiVersionapi-group/version 格式的 API 组和 Kubernetes API 版本。

  • kind:资源类型。VerticaDB 是 Vertica 自定义资源类型的名称。

  • metadata:标识命名空间中的对象的数据。

    • name:此 CR 对象的名称。

规范定义

spec 字段定义了 CR 的所需状态。在控制循环期间,操作器将规范值与当前状态进行比较并协调任何差异。

以下部分将值嵌套在 spec 字段下,以定义自定义资源对象的所需状态。

映像管理

每个自定义资源实例都需要访问 Vertica 服务器映像以及有关多久下载一次新映像的说明:

spec:
  image: vertica/vertica-k8s:latest
  imagePullPolicy: Always

前面的示例定义了以下内容:

  • image:要在 Vertica 服务器容器 pod 中运行的映像,在此处以 docker-registry-hostname/image-name:tag 格式定义。有关可用 Vertica 映像的完整列表,请参阅 Vertica Dockerhub 注册表

  • imagePullPolicy:控制操作器何时从容器注册表中提取 image。当您使用 latest 标记时,请将此项设置为 Alwayslatest 标记会被每个新版本覆盖,因此您应该检查映像注册表以确保使用正确的最新映像。

群集描述值

此部分对用来配置数据库及其操作方式的字段进行逻辑分组:

spec:
  ...
  initPolicy: Create
  kSafety: "1"
  licenseSecret: vertica-license
  superuserPasswordSecret: su-passwd

前面的示例定义了以下内容:

  • initPolicy:指定如何初始化数据库。 Create 为自定义资源初始化一个新数据库。

  • kSafety:确定子群集的容错。对于三 Pod 子群集,将 kSafety 设置为 1。

  • licenseSecretSecret 包含您的 Vertica 许可证密钥。许可证挂载在 /home/dbadmin/licensing/mnt 目录中。

  • superuserPasswordSecretSecret 包含数据库超级用户密码。

挂载自定义 TLS 证书

certSecrets 是一个列表,其中包含您为了对 CR 的内部和外部通信加密而创建的每个 Secret。使用 name 键添加每个证书:

spec:
  ...
  certSecrets:
    - name: mtls
    - name: aws-cert

certSecrets 接受无限数量的 name 值。如果您更新现有证书,操作器将替换 Vertica 服务器容器中的证书。如果您添加或删除证书,操作器将使用新配置重新调度 pod。

每个 certSecret 都挂载在 /certs/certSecrets.name 目录中的 Vertica 服务器容器中。例如,aws-cert Secret 挂载在 certs/aws-cert 目录中。

配置公共存储

以下示例为 S3 端点配置公共存储。有关支持的公共存储位置的列表,请参阅容器化环境。有关每个公共存储位置的实施详细信息,请参阅配置公共存储

communal 部分中提供存储位置的位置和凭据:

spec:
  ...
  communal:
    credentialSecret: s3-creds
    endpoint: https://path/to/s3-endpoint
    path: s3://bucket-name/key-name
    caFile: /certs/aws-cert/root_cert.pem
    region: aws-region

前面的示例定义了以下内容:

  • credentialSecret:包含您的公共访问权限和密钥凭据的 Secret

  • endpoint:S3 端点 URL。

  • path:S3 存储桶的位置,采用 S3 存储桶表示法。在您创建自定义资源之前,此存储桶必须存在。创建自定义资源后,您不能更改此值。

  • caFile:在服务器容器文件系统中挂载证书文件,以验证与自定义资源的、与 S3 兼容的连接。CA 文件与挂载自定义 TLS 证书中添加的 aws-cert Secret 挂载在同一目录中。

  • region:公共存储资源的地理位置。

添加 sidecar 容器

sidecar 是一个实用程序容器,它与 Vertica 服务器容器在同一个 pod 中运行,并为 Vertica 服务器进程执行任务。例如,您可以使用 vertica-logger 映像添加一个 sidecar,将日志从 vertica.log 发送到主机节点上的标准输出以进行日志聚合。

sidecars 接受一个 sidecar 定义列表,其中每个元素定义以下值:

spec:
  ...
  sidecars:
    - name: sidecar-container
      image: sidecar-image:latest

前面的示例定义了以下内容:

  • name:sidecar 的名称。 name 指示 sidecar 元素的开头。

  • image:sidecar 容器的映像。

与 Vertica 服务器进程共享信息的 sidecar 必须在 pod 生命周期之间持久存储数据。以下部分在 sidecar 文件系统中挂载自定义卷。

挂载自定义卷

如果外部服务需要长期访问您的 Vertica 服务器数据,您可能需要挂载自定义卷以在 pod 生命周期之间持久存储数据。

使用 volumeMounts.* 参数挂载一个或多个自定义卷。要为 Vertica 服务器容器挂载自定义卷,请直接在规范下添加 volumeMounts.* 值。要为 sidecar 容器挂载自定义卷,请将 volumeMounts.* 值嵌套在 sidecars 数组中,作为单个 sidecar 元素定义的一部分。

volumes.* 参数使自定义卷可供 CR 挂载到相应的容器文件系统中。将 volumes 缩进到与其对应的 volumeMounts 条目相同的级别。以下示例为 Vertica 服务器容器和 sidecar 实用程序容器挂载自定义卷:

spec:
  ...
  volumeMounts:
  - name: tenants-vol
    mountPath: /path/to/tenants-vol
  volumes:
    - name: tenants-vol
      persistentVolumeClaim:
        claimName: vertica-pvc
    - name: sidecar-vol
      emptyDir: {}
  ...
  sidecars:
    - name: sidecar-container
      image: sidecar-image:latest
      volumeMounts:
        - name: sidecar-vol
          mountPath: /path/to/sidecar-vol

前面的示例定义了以下内容:

  • volumes:接受自定义卷和卷类型的列表以持久存储容器的数据。

  • volumes.name:持久存储数据的自定义卷的名称。此值必须与对应的 volumeMounts.name 值匹配。

  • persistentVolumeClaimemptyDir:卷类型和名称。Vertica 自定义资源接受任何 Kubernetes 卷类型。

本地容器信息

每个容器在 PersistentVolume (PV) 中持久存储编录、存储库、配置和日志数据。您必须为 pod 重新调度等操作提供有关数据和存储库位置的信息:

spec:
  ...
  local:
    dataPath: /data
    depotPath: /depot
    requestSize: 500Gi

前面的示例定义了以下内容:

  • dataPath/data 目录挂载在容器文件系统中的位置。/data 目录存储本地编录和临时文件。

  • depotPath:存储库挂载在容器文件系统中的位置。Eon 模式数据库将数据缓存在存储库本地,从而缩短从公共存储中获取数据以执行操作所需的时间。

  • requestSize:将 PV 绑定到 pod 时可用的本地数据卷的最小大小。

您必须将配置 StorageClass 为把 pod 绑定到 PersistentVolumeClaim (PVC)。有关详细信息,请参阅基于 Kubernetes 的容器化 Vertica

分片计数

shardCount 设置指定数据库中的分片数:

spec:
  ...
  shardCount: 12

实例化 CR 后不能更改此值。当您更改子群集中的 pod 数量,或者添加或移除子群集时,操作器自动重新平衡分片数

有关选择分片计数的指导,请参阅为 Eon 模式配置 Vertica 群集

子群集定义

subclusters 部分是元素列表,其中每个元素代表一个子群集及其属性。每个 CR 都需要一个主子群集,否则它会返回错误:

spec:
  ...
  subclusters:
  - isPrimary: true
    name: primary-subcluster
    size: 3

前面的示例定义了以下内容:

  • isPrimary:将子群集指定为主群集或辅助群集。每个 CR 都需要一个主子群集,否则它会返回错误。有关详细信息,请参阅子群集

  • name:子群集的名称。

  • size:子群集中的 pod 数量。

子群集服务对象

每个子群集通过服务对象与外部客户端和内部 pod 进行通信:

spec:
  ...
  subclusters:
    ...
    serviceName: connections
    serviceType: LoadBalancer
    serviceAnnotations:
      service.beta.kubernetes.io/load-balancer-source-ranges: 10.0.0.0/24

在前面的示例中:

  • serviceName:为服务对象分配自定义名称,以便您可以在需要时将相同的服务对象用于多个子群集。

    服务对象名称使用 metadata.name-serviceName 命名约定。此示例创建名为 verticadb-connections 的服务对象。

  • serviceType:定义子群集服务对象。

    默认情况下,子群集使用 ClusterIP serviceType,它设置只能从 Kubernetes 内部访问的稳定 IP 和端口。在许多情况下,外部客户端应用程序需要连接到针对特定工作负载进行微调的子群集。对于外部客户端访问,将 serviceType 设置为 NodePortLoadBalancer

    LoadBalancer 服务类型由您的云提供商管理。有关实施详细信息,请参阅 Kubernetes 文档和云提供商文档。

  • serviceAnnotations:为服务分配自定义注释。此注释定义了可以访问网络负载均衡器 (NLB) 的 CIDR。有关其他详细信息,请参阅 AWS 负载均衡器控制器文档。

有关 Vertica 和服务对象的详细信息,请参阅基于 Kubernetes 的容器化 Vertica

pod 资源限制和请求

设置每个主机节点为 Vertica 服务器 pod 分配的 CPU 和内存资源量,以及每个 pod 可以请求的资源量:

spec:
  ...
  subclusters:
    ...
    resources:
      limits:
        cpu: 32
        memory: 96Gi
      requests:
        cpu: 32
        memory: 96Gi

在前面的示例中:

  • resources:每个 pod 从其主机节点请求的资源量。当您更改资源设置时,Kubernetes 会使用更新的资源配置重新启动每个 pod。

  • limits:每个服务器 pod 可消耗的最大 CPU 和内存量。

  • requests:每个 pod 从 PV 请求的 CPU 和内存资源量。

    有关设置生产限制和请求的指导,请参阅关于调整 Vertica 节点和群集大小的建议

    最佳实践是,将资源请求和限制设置为相等的值,以便将它们分配给保证的 QoS 类。相等设置还可以提供在受限环境中针对内存不足 (OOM) 终止程序的最佳防护。

节点亲和性

Kubernetes 提供了亲和性和反亲和性设置来控制操作器使用哪些资源来调度 pod。最佳实践是,设置 affinity 以确保单个节点不为两个 Vertica pod 提供服务:

spec:
  ...
  subclusters:
    ...
    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: app.kubernetes.io/name
              operator: In
              values:
              - vertica
          topologyKey: "kubernetes.io/hostname"

在前面的示例中:

  • affinity:使用标签提供对 pod 和主机调度的控制。

  • podAntiAffinity:使用 pod 标签来防止对某些资源进行调度。

  • requiredDuringSchedulingIgnoredDuringExecution:在将 pod 调度到主机节点之前,必须满足此语句下定义的规则。

  • labelSelector:标识受此亲和性规则影响的 pod。

  • matchExpressions:包含 keyoperatorvalues 定义的 pod 选择器要求的列表。此 matchExpression 规则检查主机节点是否正在运行另一个使用 vertica 标签的 pod。

  • topologyKey:定义规则的范围。由于使用 hostname 拓扑标签,因此会根据 pod 和主机节点应用规则。

完整的文件参考

下面是可供参考的完整 CR YAML 文件:

apiVersion: vertica.com/v1beta1
kind: VerticaDB
metadata:
  name: verticadb
spec:
  image: vertica/vertica-k8s:latest
  imagePullPolicy: Always
  initPolicy: Create
  kSafety: "1"
  licenseSecret: vertica-license
  superuserPasswordSecret: su-passwd
  communal:
    credentialSecret: s3-creds
    endpoint: https://path/to/s3-endpoint
    path: s3://bucket-name/key-name
    caFile: /certs/aws-certs/root_cert.pem
    region: aws-region
  volumeMounts:
  - name: tenants-vol
    mountPath: /path/to/tenants-vol
  volumes:
    - name: tenants-vol
      persistentVolumeClaim:
        claimName: vertica-pvc
    - name: sidecar-vol
      emptyDir: {}
  sidecars:
    - name: sidecar-container
      image: sidecar-image:latest
      volumeMounts:
        - name: sidecar-vol
          mountPath: /path/to/sidecar-vol
  certSecrets:
    - name: mtls
    - name: aws-cert
  local:
    dataPath: /data
    depotPath: /depot
    requestSize: 500Gi
  shardCount: 12
  subclusters:
  - isPrimary: true
    name: primary-subcluster
    size: 3
    serviceName: connections
    serviceType: LoadBalancer
    serviceAnnotations:
      service.beta.kubernetes.io/load-balancer-source-ranges: 10.0.0.0/24
    resources:
      limits:
        cpu: 32
        memory: 96Gi
      requests:
        cpu: 32
        memory: 96Gi
    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: app.kubernetes.io/name
              operator: In
              values:
              - vertica
          topologyKey: "kubernetes.io/hostname"