5.6. 基于 Java 的 Operator
5.6.1. 基于 Java 的 Operator 的 Operator SDK 入门
基于 Java 的 Operator SDK 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
如需演示使用 Operator SDK 提供的工具和库来设置和运行基于 Java 的 Operator 的基本知识,Operator 开发人员可以为 Memcached 构建基于 Java 的 Operator 示例,一个分布式键值存储,并将它部署到集群中。
5.6.1.1. 先决条件
5.6.1.2. 创建并部署基于 Java 的 Operator
您可以使用 Operator SDK 为 Memcached 构建和部署简单的基于 Java 的 Operator。
流程
创建一个项目。
创建您的项目目录:
$ mkdir memcached-operator
切换到项目所在的目录:
$ cd memcached-operator
使用
quarkus
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=quarkus \ --domain=example.com \ --project-name=memcached-operator
创建 API。
创建简单的 Memcached API:
$ operator-sdk create api \ --plugins quarkus \ --group cache \ --version v1 \ --kind Memcached
构建并推送 Operator 镜像。
使用默认的
Makefile
目标来构建和推送 Operator。使用镜像的 pull spec 设置IMG
,该 spec 使用您可推送到的 registry:$ make docker-build docker-push IMG=<registry>/<user>/<image_name>:<tag>
运行 Operator。
安装 CRD:
$ make install
将项目部署到集群中。将
IMG
设置为您推送的镜像:$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
创建示例自定义资源(CR)。
创建一个示例 CR:
$ oc apply -f config/samples/cache_v1_memcached.yaml \ -n memcached-operator-system
查看 CR 协调 Operator:
$ oc logs deployment.apps/memcached-operator-controller-manager \ -c manager \ -n memcached-operator-system
删除 CR。
运行以下命令来删除 CR:
$ oc delete -f config/samples/cache_v1_memcached.yaml -n memcached-operator-system
清理。
运行以下命令清理在此流程中创建的资源:
$ make undeploy
5.6.1.3. 后续步骤
- 如需更深入地了解如何构建基于 Java 的 Operator,请参阅基于 Java 的 Operator SDK 指南。
5.6.2. 基于 Java 的 Operator 的 operator SDK 指南
基于 Java 的 Operator SDK 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
Operator 开发人员可以利用 Operator SDK 中的 Java 编程语言支持,为 Memcached 构建基于 Java 的 Operator 示例、分布式键值存储并管理其生命周期。
通过以下两个 Operator Framework 核心组件来完成此过程:
- Operator SDK
-
operator-sdk
CLI 工具和java-operator-sdk
library API - Operator Lifecycle Manager (OLM)
- 集群中 Operator 的安装、升级和基于角色的访问控制(RBAC)
本教程的内容比基于 Java 的 Operator 开始使用 Operator SDK的内容更详细。
5.6.2.1. 先决条件
5.6.2.2. 创建一个项目
使用 Operator SDK CLI 创建名为 memcached-operator 的
项目。
流程
为项目创建一个目录:
$ mkdir -p $HOME/projects/memcached-operator
进入该目录:
$ cd $HOME/projects/memcached-operator
使用
quarkus
插件运行operator-sdk init
命令以初始化项目:$ operator-sdk init \ --plugins=quarkus \ --domain=example.com \ --project-name=memcached-operator
5.6.2.2.1. PROJECT 文件
operator-sdk init
命令生成的文件中是一个 Kubebuilder PROJECT
文件。从项目 root 运行的后续 operator-sdk
命令以及 help
输出会读取该文件,并注意到项目类型为 Java。例如:
domain: example.com layout: - quarkus.javaoperatorsdk.io/v1-alpha projectName: memcached-operator version: "3"
5.6.2.3. 创建 API 和控制器
使用 Operator SDK CLI 创建自定义资源定义(CRD)API 和控制器。
流程
运行以下命令来创建 API:
$ operator-sdk create api \ --plugins=quarkus \1 --group=cache \2 --version=v1 \3 --kind=Memcached 4
验证
运行
tree
命令来查看文件结构:$ tree
输出示例
. ├── Makefile ├── PROJECT ├── pom.xml └── src └── main ├── java │ └── com │ └── example │ ├── Memcached.java │ ├── MemcachedReconciler.java │ ├── MemcachedSpec.java │ └── MemcachedStatus.java └── resources └── application.properties 6 directories, 8 files
5.6.2.3.1. 定义 API
定义 Memcached
自定义资源(CR)的 API。
流程
编辑作为
create api
进程一部分生成的以下文件:更新
MemcachedSpec.java
文件中的以下属性,以定义Memcached
CR 的所需状态:public class MemcachedSpec { private Integer size; public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } }
更新
MemcachedStatus.java
文件中的以下属性,以定义Memcached
CR 的观察状态:注意以下示例中显示了一个 Node 状态字段。建议您在实践中使用典型的状态属性。
import java.util.ArrayList; import java.util.List; public class MemcachedStatus { // Add Status information here // Nodes are the names of the memcached pods private List<String> nodes; public List<String> getNodes() { if (nodes == null) { nodes = new ArrayList<>(); } return nodes; } public void setNodes(List<String> nodes) { this.nodes = nodes; } }
更新
Memcached.java
文件,以定义 Memcached API 的 Schema,该 API 扩展至MemcachedSpec.java
和MemcachedStatus.java
文件。@Version("v1") @Group("cache.example.com") public class Memcached extends CustomResource<MemcachedSpec, MemcachedStatus> implements Namespaced {}
5.6.2.3.2. 生成 CRD 清单
在使用 MemcachedSpec
和 MemcachedStatus
文件定义 API 后,您可以生成 CRD 清单。
流程
从
memcached-operator
目录运行以下命令,以生成 CRD:$ mvn clean install
验证
验证
target/kubernetes/memcacheds.cache.example.com-v1.yml
文件中的 CRD 内容,如下例所示:$ cat target/kubernetes/memcacheds.cache.example.com-v1.yaml
输出示例
# Generated by Fabric8 CRDGenerator, manual edits might get overwritten! apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: memcacheds.cache.example.com spec: group: cache.example.com names: kind: Memcached plural: memcacheds singular: memcached scope: Namespaced versions: - name: v1 schema: openAPIV3Schema: properties: spec: properties: size: type: integer type: object status: properties: nodes: items: type: string type: array type: object type: object served: true storage: true subresources: status: {}
5.6.2.3.3. 创建自定义资源
生成 CRD 清单后,您可以创建自定义资源(CR)。
流程
创建名为
memcached-sample.yaml
的 Memcached CR:apiVersion: cache.example.com/v1 kind: Memcached metadata: name: memcached-sample spec: # Add spec fields here size: 1
5.6.2.4. 实现控制器
在创建新 API 和控制器后,您可以实现控制器逻辑。
流程
将以下依赖项附加到
pom.xml
文件中:<dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency>
在本例中,将生成的控制器文件
MemcachedReconciler.java
替换为以下示例实现:例 5.9.
MemcachedReconciler.java
示例package com.example; import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.fabric8.kubernetes.api.model.ContainerBuilder; import io.fabric8.kubernetes.api.model.ContainerPortBuilder; import io.fabric8.kubernetes.api.model.LabelSelectorBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.OwnerReferenceBuilder; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodSpecBuilder; import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder; import org.apache.commons.collections.CollectionUtils; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class MemcachedReconciler implements Reconciler<Memcached> { private final KubernetesClient client; public MemcachedReconciler(KubernetesClient client) { this.client = client; } // TODO Fill in the rest of the reconciler @Override public UpdateControl<Memcached> reconcile( Memcached resource, Context context) { // TODO: fill in logic Deployment deployment = client.apps() .deployments() .inNamespace(resource.getMetadata().getNamespace()) .withName(resource.getMetadata().getName()) .get(); if (deployment == null) { Deployment newDeployment = createMemcachedDeployment(resource); client.apps().deployments().create(newDeployment); return UpdateControl.noUpdate(); } int currentReplicas = deployment.getSpec().getReplicas(); int requiredReplicas = resource.getSpec().getSize(); if (currentReplicas != requiredReplicas) { deployment.getSpec().setReplicas(requiredReplicas); client.apps().deployments().createOrReplace(deployment); return UpdateControl.noUpdate(); } List<Pod> pods = client.pods() .inNamespace(resource.getMetadata().getNamespace()) .withLabels(labelsForMemcached(resource)) .list() .getItems(); List<String> podNames = pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList()); if (resource.getStatus() == null || !CollectionUtils.isEqualCollection(podNames, resource.getStatus().getNodes())) { if (resource.getStatus() == null) resource.setStatus(new MemcachedStatus()); resource.getStatus().setNodes(podNames); return UpdateControl.updateResource(resource); } return UpdateControl.noUpdate(); } private Map<String, String> labelsForMemcached(Memcached m) { Map<String, String> labels = new HashMap<>(); labels.put("app", "memcached"); labels.put("memcached_cr", m.getMetadata().getName()); return labels; } private Deployment createMemcachedDeployment(Memcached m) { Deployment deployment = new DeploymentBuilder() .withMetadata( new ObjectMetaBuilder() .withName(m.getMetadata().getName()) .withNamespace(m.getMetadata().getNamespace()) .build()) .withSpec( new DeploymentSpecBuilder() .withReplicas(m.getSpec().getSize()) .withSelector( new LabelSelectorBuilder().withMatchLabels(labelsForMemcached(m)).build()) .withTemplate( new PodTemplateSpecBuilder() .withMetadata( new ObjectMetaBuilder().withLabels(labelsForMemcached(m)).build()) .withSpec( new PodSpecBuilder() .withContainers( new ContainerBuilder() .withImage("memcached:1.4.36-alpine") .withName("memcached") .withCommand("memcached", "-m=64", "-o", "modern", "-v") .withPorts( new ContainerPortBuilder() .withContainerPort(11211) .withName("memcached") .build()) .build()) .build()) .build()) .build()) .build(); deployment.addOwnerReference(m); return deployment; } }
示例控制器为每个
Memcached
自定义资源(CR)运行以下协调逻辑:- 如果尚无 Memcached 部署,请创建一个。
-
确保部署大小与
Memcached
CR spec 指定的大小匹配。 -
使用
memcached
Pod 的名称更新Memcached
CR 状态。
下面的小节解释了示例中的控制器如何监视资源以及如何触发协调循环。您可以跳过这些小节来直接进入运行 Operator。
5.6.2.4.1. 协调循环
每个控制器都有一个协调器对象,它带有实现了协调循环的
Reconcile()
方法。协调循环通过Deployment
参数,如下例所示:Deployment deployment = client.apps() .deployments() .inNamespace(resource.getMetadata().getNamespace()) .withName(resource.getMetadata().getName()) .get();
如以下示例所示,如果
Deployment
是null
,则需要创建部署。创建Deployment
后,您可以确定是否需要协调。如果不需要协调,返回UpdateControl.noUpdate()
的值,否则返回 'UpdateControl.updateStatus(resource)的值:if (deployment == null) { Deployment newDeployment = createMemcachedDeployment(resource); client.apps().deployments().create(newDeployment); return UpdateControl.noUpdate(); }
获取
Deployment
后,获取当前和所需的副本,如下例所示:int currentReplicas = deployment.getSpec().getReplicas(); int requiredReplicas = resource.getSpec().getSize();
如果
currentReplicas
与requiredReplicas
不匹配,您必须更新Deployment
,如下例所示:if (currentReplicas != requiredReplicas) { deployment.getSpec().setReplicas(requiredReplicas); client.apps().deployments().createOrReplace(deployment); return UpdateControl.noUpdate(); }
以下示例演示了如何获取 pod 列表及其名称:
List<Pod> pods = client.pods() .inNamespace(resource.getMetadata().getNamespace()) .withLabels(labelsForMemcached(resource)) .list() .getItems(); List<String> podNames = pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList());
检查资源是否已创建并使用 Memcached 资源验证 pod 名称。如果这两个条件之一都存在不匹配,请执行协调,如下例所示:
if (resource.getStatus() == null || !CollectionUtils.isEqualCollection(podNames, resource.getStatus().getNodes())) { if (resource.getStatus() == null) resource.setStatus(new MemcachedStatus()); resource.getStatus().setNodes(podNames); return UpdateControl.updateResource(resource); }
5.6.2.4.2. 定义 labelsForMemcached
LabelsForMemcached
是一个返回要附加到资源的标签映射的工具:
private Map<String, String> labelsForMemcached(Memcached m) { Map<String, String> labels = new HashMap<>(); labels.put("app", "memcached"); labels.put("memcached_cr", m.getMetadata().getName()); return labels; }
5.6.2.4.3. 定义 createMemcachedDeployment
createMemcachedDeployment
方法使用 fabric8 DeploymentBuilder
类:
private Deployment createMemcachedDeployment(Memcached m) { Deployment deployment = new DeploymentBuilder() .withMetadata( new ObjectMetaBuilder() .withName(m.getMetadata().getName()) .withNamespace(m.getMetadata().getNamespace()) .build()) .withSpec( new DeploymentSpecBuilder() .withReplicas(m.getSpec().getSize()) .withSelector( new LabelSelectorBuilder().withMatchLabels(labelsForMemcached(m)).build()) .withTemplate( new PodTemplateSpecBuilder() .withMetadata( new ObjectMetaBuilder().withLabels(labelsForMemcached(m)).build()) .withSpec( new PodSpecBuilder() .withContainers( new ContainerBuilder() .withImage("memcached:1.4.36-alpine") .withName("memcached") .withCommand("memcached", "-m=64", "-o", "modern", "-v") .withPorts( new ContainerPortBuilder() .withContainerPort(11211) .withName("memcached") .build()) .build()) .build()) .build()) .build()) .build(); deployment.addOwnerReference(m); return deployment; }
5.6.2.5. 运行 Operator
您可以使用 Operator SDK CLI 构建和运行 Operator:
- 作为 Go 程序在集群外本地运行。
- 作为集群的部署运行。
- 捆绑 Operator,并使用 Operator Lifecycle Manager(OLM)在集群中部署。
5.6.2.5.1. 在集群外本地运行
您可以作为集群外的 Go 程序运行您的 Operator 项目。这可以加快部署和测试的速度,对于开发非常有用。
流程
运行以下命令来编译 Operator:
$ mvn clean install
输出示例
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 11.193 s [INFO] Finished at: 2021-05-26T12:16:54-04:00 [INFO] ------------------------------------------------------------------------
运行以下命令,将 CRD 安装到 default 命名空间:
$ oc apply -f target/kubernetes/memcacheds.cache.example.com-v1.yml
输出示例
customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created
如下例所示,名为
rbac.yaml
的文件:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: memcached-operator-admin subjects: - kind: ServiceAccount name: memcached-quarkus-operator-operator namespace: <operator_namespace> roleRef: kind: ClusterRole name: cluster-admin apiGroup: ""
运行以下命令通过应用
rbac.yaml
文件向memcached-quarkus-operator-operator
授予cluster-admin
权限:$ oc apply -f rbac.yaml
输入以下命令来运行 Operator:
$ java -jar target/quarkus-app/quarkus-run.jar
注意java
命令将运行 Operator 并保持运行,直到您结束进程。您需要另一个终端来完成这些命令的其余部分。使用以下命令应用
memcached-sample.yaml
文件:$ kubectl apply -f memcached-sample.yaml
输出示例
memcached.cache.example.com/memcached-sample created
验证
运行以下命令,确认 pod 已启动:
$ oc get all
输出示例
NAME READY STATUS RESTARTS AGE pod/memcached-sample-6c765df685-mfqnz 1/1 Running 0 18s
5.6.2.5.2. 作为集群的部署运行
您可以作为一个部署在集群中运行 Operator 项目。
流程
运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<image_name>:<tag>
注意镜像的名称和标签,如
IMG=<registry> /<user> /<image_name>:<tag>
,在两个命令中都可在您的 Makefile 中设置。修改IMG ?= controller:latest
值来设置您的默认镜像名称。
运行以下命令,将 CRD 安装到 default 命名空间:
$ oc apply -f target/kubernetes/memcacheds.cache.example.com-v1.yml
输出示例
customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created
如下例所示,名为
rbac.yaml
的文件:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: memcached-operator-admin subjects: - kind: ServiceAccount name: memcached-quarkus-operator-operator namespace: <operator_namespace> roleRef: kind: ClusterRole name: cluster-admin apiGroup: ""
重要rbac.yaml
文件将在以后的步骤中应用。运行以下命令来部署 Operator:
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
运行以下命令通过应用上一步中创建的
rbac.yaml
文件向memcached-quarkus-operator-operator
授予cluster-admin
权限:$ oc apply -f rbac.yaml
运行以下命令验证 Operator 是否正在运行:
$ oc get all -n default
输出示例
NAME READY UP-TO-DATE AVAILABLE AGE pod/memcached-quarkus-operator-operator-7db86ccf58-k4mlm 0/1 Running 0 18s
运行以下命令以应用
memcached-sample.yaml
并创建memcached-sample
pod:$ oc apply -f memcached-sample.yaml
输出示例
memcached.cache.example.com/memcached-sample created
验证
运行以下命令,确认 pod 已启动:
$ oc get all
输出示例
NAME READY STATUS RESTARTS AGE pod/memcached-quarkus-operator-operator-7b766f4896-kxnzt 1/1 Running 1 79s pod/memcached-sample-6c765df685-mfqnz 1/1 Running 0 18s
5.6.2.5.3. 捆绑 Operator 并使用 Operator Lifecycle Manager 进行部署
5.6.2.5.3.1. 捆绑 Operator
Operator 捆绑包格式是 Operator SDK 和 Operator Lifecycle Manager(OLM)的默认打包方法。您可以使用 Operator SDK 来构建和推送 Operator 项目作为捆绑包镜像,使 Operator 可供 OLM 使用。
先决条件
- 在开发工作站上安装 operator SDK CLI
-
已安装 OpenShift CLI (
oc
) v4.15+ - 使用 Operator SDK 初始化 operator 项目
流程
在 Operator 项目目录中运行以下
make
命令来构建和推送 Operator 镜像。在以下步骤中修改IMG
参数来引用您可访问的库。您可以获取在存储库站点(如 Quay.io)存储容器的帐户。构建镜像:
$ make docker-build IMG=<registry>/<user>/<operator_image_name>:<tag>
注意由 SDK 为 Operator 生成的 Dockerfile 需要为
go build
明确引用GOARCH=amd64
。这可以在非 AMD64 构架中使用GOARCH=$TARGETARCH
。Docker 自动将环境变量设置为-platform
指定的值。对于 Buildah,需要使用-build-arg
来实现这一目的。如需更多信息,请参阅多个架构。将镜像推送到存储库:
$ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
运行
make bundle
命令创建 Operator 捆绑包清单,该命令调用多个命令,其中包括 Operator SDKgenerate bundle
和bundle validate
子命令:$ make bundle IMG=<registry>/<user>/<operator_image_name>:<tag>
Operator 的捆绑包清单描述了如何显示、创建和管理应用程序。
make bundle
命令在 Operator 项目中创建以下文件和目录:-
包含
ClusterServiceVersion
对象的捆绑包清单目录,名为bundle/manifests
-
名为
bundle/metadata
的捆绑包元数据目录 -
config/crd
目录中的所有自定义资源定义(CRD) -
一个 Dockerfile
bundle.Dockerfile
然后,使用
operator-sdk bundle validate
自动验证这些文件,以确保磁盘上的捆绑包的格式是正确的。-
包含
运行以下命令来构建和推送捆绑包镜像。OLM 使用索引镜像来消耗 Operator 捆绑包,该镜像引用一个或多个捆绑包镜像。
构建捆绑包镜像。使用您要推送镜像的 registry、用户命名空间和镜像标签的详情,设置
BUNDLE_IMG
:$ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
推送捆绑包镜像:
$ docker push <registry>/<user>/<bundle_image_name>:<tag>
5.6.2.5.3.2. 使用 Operator Lifecycle Manager 部署 Operator
Operator Lifecycle Manager(OLM)可帮助您在 Kubernetes 集群中安装、更新和管理 Operator 及其相关服务的生命周期。OLM 在 OpenShift Container Platform 上默认安装,并作为 Kubernetes 扩展运行,以便您可以在没有任何额外工具的情况下将 Web 控制台和 OpenShift CLI(oc
)用于所有 Operator 生命周期管理功能。
Operator Bundle Format 是 Operator SDK 和 OLM 的默认打包方法。您可以使用 Operator SDK 在 OLM 上快速运行捆绑包镜像,以确保它正确运行。
先决条件
- 在开发工作站上安装 operator SDK CLI
- 构建并推送到 registry 的 Operator 捆绑包镜像
-
OLM安装在一个基于 Kubernetes 的集群上(如果使用
apiextensions.k8s.io/v1
CRD,则为 v1.16.0 或更新版本,如 OpenShift Container Platform 4.15) -
使用具有
cluster-admin
权限的账户使用oc
登录到集群
流程
输入以下命令在集群中运行 Operator:
$ operator-sdk run bundle \1 -n <namespace> \2 <registry>/<user>/<bundle_image_name>:<tag> 3
重要自 OpenShift Container Platform 4.11 起,
run bundle
命令默认支持 Operator 目录基于文件的目录格式。Operator 目录已弃用的 SQLite 数据库格式仍被支持,但将在以后的发行版本中删除。建议 Operator 作者将其工作流迁移到基于文件的目录格式。这个命令执行以下操作:
- 创建引用捆绑包镜像的索引镜像。索引镜像不透明且具有临时性,但准确反映了如何将捆绑包添加到生产中的目录中。
- 创建指向新索引镜像的目录源,以便 OperatorHub 能够发现 Operator。
-
通过创建一个
OperatorGroup
、Subscription
、InstallPlan
和所有其他所需资源(包括 RBAC),将 Operator 部署到集群中。
5.6.2.6. 其他资源
- 请参阅基于 Java 的 Operator 的项目布局,以了解 Operator SDK 创建的目录结构。
- 如果配置了集群范围的出口代理,集群管理员可以覆盖代理设置,或为 Operator Lifecycle Manager(OLM)上运行的特定 Operator 注入自定义 CA 证书。
5.6.3. 基于 Java 的 Operator 的项目布局
基于 Java 的 Operator SDK 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
operator-sdk
CLI 可为每个 Operator 项目生成或 scaffold 多个 软件包和文件。
5.6.3.1. 基于 Java 的项目布局
由 operator-sdk init
命令生成的基于 Java 的 Operator 项目包含以下文件和目录:
文件或目录 | 用途 |
---|---|
| 包含运行 Operator 所需的依赖项的文件。 |
|
包含代表 API 的文件的目录。如果域是 |
| 定义控制器实现的 Java 文件。 |
| 定义 Memcached CR 所需状态的 Java 文件。 |
| 定义 Memcached CR 观察状态的 Java 文件。 |
| 定义 Memcached API 的 Schema 的 Java 文件。 |
| 包含 CRD yaml 文件的目录。 |
5.6.4. 为较新的 Operator SDK 版本更新项目
OpenShift Container Platform 4.15 支持 Operator SDK 1.31.0。如果您已在工作站上安装了 1.28.0 CLI,您可以通过安装最新版本将 CLI 更新至 1.31.0。
但是,要确保现有 Operator 项目保持与 Operator SDK 1.31.0 的兼容性,需要执行更新的相关步骤才能解决从 1.28.0 以来引入的相关破坏更改。您必须在之前使用 1.28.0 创建或维护的任何 Operator 项目中手动执行更新步骤。
5.6.4.1. 为 Operator SDK 1.31.0 更新基于 Java 的 Operator 项目
以下流程更新了基于 Java 的 Operator 项目,以便与 1.31.0 兼容。
先决条件
- 已安装 operator SDK 1.31.0
- 使用 Operator SDK 1.28.0 创建或维护的 Operator 项目
流程
编辑 Operator 项目的 makefile,将 Operator SDK 版本更新至 1.31.0,如下例所示:
makefile 示例
# Set the Operator SDK version to use. By default, what is installed on the system is used. # This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. OPERATOR_SDK_VERSION ?= v1.31.0 1
- 1
- 将版本从
1.28.0
更改为1.31.0
。