创建自定义资源
自定义资源定义 (CRD) 是共享的全局对象,它将 Kubernetes API 扩展到标准资源类型之外。CRD 用作自定义资源 (CR) 实例的蓝图。您创建用来指定所需环境状态的 CR,操作器监控 CR 以维护其命名空间内对象的状态。
为方便起见,此示例 CR 使用 YAML 格式的文件。有关所有可用 CR 设置的详细信息,请参阅自定义资源参数。
先决条件
-
配置动态卷配置器。
-
确认您有资源来部署您计划创建的对象。
-
获取 Vertica 许可证。默认情况下,Helm 图表部署免费的社区版许可证。
-
配置一个正在运行的 S3 端点,其中包含空的公共路径存储桶。要配置另一个受支持的存储位置,请参阅配置公共存储以获取说明。
创建 Secret
使用 kubectl 命令行工具创建 Secret 以将敏感信息存储在您的自定义资源中,而不会暴露敏感信息所代表的值。
重要
本部分中的每个命令都会在当前命名空间中创建一个 Secret。包含
--namespace=namespace
选项可为特定的命名空间创建 Secret。
例如,如果您使用 OperatorHub.io 安装选项,则操作器将安装在 my-verticadb-operator
命名空间中。要在该命名空间中创建 Secret,请使用以下格式:
$ kubectl create secret <span class="code-variable">options</span> --namespace=my-verticadb-operator
-
为 Vertica 许可证创建一个名为
vertica-license
的 Secret:$ kubectl create secret generic vertica-license --from-file=license.dat=/path/to/license.dat
默认情况下,Helm 图表使用免费的社区版许可证。此许可证仅限于 3 个节点和 1 TB 数据。
-
创建名为
su-passwd
的 Secret 来存储您的超级用户密码。如果不添加超级用户密码,则没有与数据库关联的密码:$ kubectl create secret generic su-passwd --from-literal=password=secret-password
-
以下命令将 S3 兼容的公共访问权限和密钥凭证存储在名为
s3-creds
的秘密中:$ kubectl create secret generic s3-creds --from-literal=accesskey=accesskey --from-literal=secretkey=secretkey
-
本教程配置一个证书颁发机构 (CA) 捆绑包,该捆绑包对与自定义资源的、与 S3 兼容的连接进行身份验证。创建名为
aws-cert
的 Secret:$ kubectl create secret generic aws-cert --from-file=root-cert.pem
-
您可以在 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
前面的示例定义了以下内容:
-
apiVersion
:api-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
标记时,请将此项设置为Always
。latest
标记会被每个新版本覆盖,因此您应该检查映像注册表以确保使用正确的最新映像。
群集描述值
此部分对用来配置数据库及其操作方式的字段进行逻辑分组:
spec:
...
initPolicy: Create
kSafety: "1"
licenseSecret: vertica-license
superuserPasswordSecret: su-passwd
前面的示例定义了以下内容:
-
initPolicy
:指定如何初始化数据库。Create
为自定义资源初始化一个新数据库。 -
kSafety
:确定子群集的容错。对于三 Pod 子群集,将kSafety
设置为 1。 -
licenseSecret
:Secret 包含您的 Vertica 许可证密钥。许可证挂载在/home/dbadmin/licensing/mnt
目录中。 -
superuserPasswordSecret
:Secret 包含数据库超级用户密码。
挂载自定义 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 端点配置公共存储。有关支持的公共存储位置的列表,请参阅容器化环境。有关每个公共存储位置的实施详细信息,请参阅配置公共存储。
注意
如果 Kubernetes 群集位于云中或托管服务上,则每个 Vertica 节点必须在同一可用性区域中运行。在 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
值匹配。 -
persistentVolumeClaim
和emptyDir
:卷类型和名称。Vertica 自定义资源接受任何 Kubernetes 卷类型。
本地容器信息
每个容器在 PersistentVolume (PV) 中持久存储编录、存储库、配置和日志数据。您必须为 pod 重新调度等操作提供有关数据和存储库位置的信息:
spec:
...
local:
dataPath: /data
depotPath: /depot
requestSize: 500Gi
前面的示例定义了以下内容:
-
dataPath
:/data
目录挂载在容器文件系统中的位置。/data
目录存储本地编录和临时文件。 -
depotPath
:存储库挂载在容器文件系统中的位置。Eon 模式数据库将数据缓存在存储库本地,从而缩短从公共存储中获取数据以执行操作所需的时间。 -
requestSize
:将 PV 绑定到 pod 时可用的本地数据卷的最小大小。注意
为了确保您不会用完磁盘空间,请验证底层存储是否大到足以容纳requestSize
设置。
您必须将配置 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
:子群集的名称。重要
资源类型名称不能包含下划线字符。资源类型名称用于完全限定域名 (FQDN),并且 FQDN 不允许使用下划线字符。您必须提供一个符合 Kubernetes 准则 的有效名称。
例如,Vertica 服务器生成的默认子群集名称为
default_subcluster
。此名称对 Kubernetes 资源类型无效。 -
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
设置为NodePort
或LoadBalancer
。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) 终止程序的最佳防护。
注意
选择您的主机节点可以容纳的资源设置。当 pod 启动或重新调度时,Kubernetes 会搜索具有足够资源的主机节点来启动 pod。如果不存在具有足够资源的主机节点,则 pod STATUS 将停留在 Pending,直到有足够的可用资源。
节点亲和性
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
:包含key
、operator
和values
定义的 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"