11.3. 创建基于 Helm 的 Operator
本指南概述了 Operator SDK 中的 Helm Chart 支持,借助示例引导 Operator 作者通过使用现有 Helm Chart 的 operator-sdk
CLI 工具来构建和运行 Nginx Operator。
11.3.1. Operator SDK 中的 Helm Chart 支持
Operator Framework 是一个开源工具包,用于以有效、自动化且可扩展的方式管理 Kubernetes 原生应用程序,即 Operator。该框架中包含 Operator SDK,可协助开发人员利用自己的专业知识来引导和构建 Operator,而无需了解 Kubernetes API 复杂性。
通过 Operator SDK 生成 Operator 项目的其中一种方案是利用现有 Helm Chart 来部署 Kubernetes 资源作为统一应用程序,而无需编写任何 Go 代码。这种基于 Helm 的 Operator 非常适合于推出时所需逻辑极少的无状态应用程序,因为更改应该应用于作为 Chart 一部分生成的 Kubernetes 对象。这听起来似乎很有局限性,但就 Kubernetes 社区构建的 Helm Chart 的增长而言,这足以满足它们的大量用例需要。
Operator 的主要功能是从代表应用程序实例的自定义对象中读取数据,并使其所需状态与正在运行的状态相匹配。对于基于 Helm 的 Operator,对象的 spec 字段是一个配置选项列表,通常在 Helm 的 values.yaml
文件中描述。您可以不使用 Helm CLI(如 helm install -f values.yaml
)来通过标志设置这些值,而是在自定义资源 (CR) 中表达这些值,因为 CR 作为原生 Kubernetes 对象能够实现应用的 RBAC 以及审核跟踪所带来的好处。
举一个名为 Tomcat
的简单 CR 示例:
apiVersion: apache.org/v1alpha1 kind: Tomcat metadata: name: example-app spec: replicaCount: 2
replicaCount
值(本例中为 2
)会通过以下命令传播到 Chart 模板中:
{{ .Values.replicaCount }}
构建并部署完 Operator 后,您可通过新建一个 CR 实例来部署新的应用实例,或使用 oc
命令列出所有环境中运行的不同实例:
$ oc get Tomcats --all-namespaces
不要求使用 Helm CLI 或安装 Tiller;基于 Helm 的 Operator 会从 Helm 项目中导入代码。您要做的只是运行一个 Operator 实例,并使用自定义资源定义 (CRD) 注册 CR。因其遵循 RBAC,所以可以更容易防止生产环境改变。
11.3.2. 安装 Operator SDK CLI
Operator SDK 配有一个 CLI 工具,可协助开发人员创建、构建和部署新的 Operator 项目。您可在工作站上安装 SDK CLI,为编写您自己的 Operator 做准备。
11.3.2.1. 从 GitHub 版本安装
您可从 GitHub 上的项目下载并安装 SDK CLI 的预构建发行版文件。
先决条件
-
docker
v17.03+ -
已安装 OpenShift CLI (
oc
) v4.1+ - 访问基于 Kubernetes v1.11.3+ 的集群
- 访问容器 registry
流程
设置发行版本变量:
RELEASE_VERSION=v0.8.0
下载发行版二进制文件。
Linux:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
macOS:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
验证所下载的发行版本二进制文件。
下载所提供的 ASC 文件。
Linux:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
macOS:
$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
将二进制文件与对应的 ASC 文件放在同一个目录中,并运行以下命令来验证该二进制文件:
Linux:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc
macOS:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc
如果您的工作站上没有维护人员公钥,则会出现以下错误:
$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc $ gpg: assuming signed data in 'operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin' $ gpg: Signature made Fri Apr 5 20:03:22 2019 CEST $ gpg: using RSA key <key_id> 1 $ gpg: Can't check signature: No public key
- 1
- RSA 密钥字符串。
要下载密钥,请运行以下命令,用上一条命令输出的 RSA 密钥字符串来替换
<key_id>
:$ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>" 1
- 1
- 如果您尚未配置密钥服务器,请使用
--keyserver
选项指定一个密钥服务器。
在您的
PATH
中安装发行版本二进制文件:Linux:
$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk $ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
macOS:
$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin $ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk $ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin
验证是否已正确安装 CLI 工具:
$ operator-sdk version
11.3.2.2. 通过 Homebrew 安装
可使用 Homebrew 来安装 SDK CLI。
先决条件
流程
使用
brew
命令安装 SDK CLI:$ brew install operator-sdk
验证是否已正确安装 CLI 工具:
$ operator-sdk version
11.3.2.3. 通过源代码编译并安装
可获取 Operator SDK 源代码来编译和安装 SDK CLI。
先决条件
流程
克隆
operator-sdk
存储库:$ mkdir -p $GOPATH/src/github.com/operator-framework $ cd $GOPATH/src/github.com/operator-framework $ git clone https://github.com/operator-framework/operator-sdk $ cd operator-sdk
检查所需的发行版本分支:
$ git checkout master
编译并安装 SDK CLI:
$ make dep $ make install
该操作会在 $GOPATH/bin 中安装 CLI 二进制
operator-sdk
。验证是否已正确安装 CLI 工具:
$ operator-sdk version
11.3.3. 使用 Operator SDK 来构建基于 Helm 的 Operator
本流程介绍了使用 Operator SDK 中的工具和库来构建由 Helm Chart 提供技术支持的简单 Nginx Operator 的示例。
最好为每个 Chart 新建一个 Operator。如果要在 Go 中编写一个成熟的 Operator,摆脱基于 Helm 的 Operator,这种做法支持更多具有原生行为的 Kubernetes API(如 oc get Nginx
),也更灵活。
先决条件
- 开发工作站已安装 Operator SDK CLI
-
使用具有
cluster-admin
权限的账户访问基于 Kubernetes 的集群 v1.11.3+(如 OpenShift Container Platform 4.2) -
已安装 OpenShift CLI (
oc
) v4.1+
流程
使用
operator-sdk new
命令来创建新 Operator 项目,可以是全命名空间范围,也可以是全集群范围。选择以下任意一项:全命名空间范围的 Operator(默认)会监视和管理单一命名空间中的资源。全命名空间范围的 Operator 因灵活性高而常被视为首选。这类 Operator 支持解耦升级、针对故障和监控隔离命名空间以及区别化 API 定义。
要创建基于 Helm 的、全命名空间范围的新
nginx-operator
项目,请使用以下命令:$ operator-sdk new nginx-operator \ --api-version=example.com/v1alpha1 \ --kind=Nginx \ --type=helm $ cd nginx-operator
这样会创建一个
nginx-operator
项目,专门用于监视 APIVersion 为example.com/v1apha1
、Kind 为Nginx
的 Nginx 资源。全集群范围的 Operator 会监视并管理整个集群的资源,在某些情况下非常实用。例如,
cert-manager
Operator 通常会以全集群范围权限和监视功能进行部署,以便管理整个集群的证书颁发。要创建全集群范围的
nginx-operator
项目,请使用以下命令:$ operator-sdk new nginx-operator \ --cluster-scoped \ --api-version=example.com/v1alpha1 \ --kind=Nginx \ --type=helm
使用
--cluster-scoped
标记来构建进行了以下修改的新 Operator:-
deploy/operator.yaml
:设置WATCH_NAMESPACE=""
而不要将其设置为 Pod 的命名空间。 -
deploy/role.yaml
:使用ClusterRole
来代替Role
。 deploy/role_binding.yaml
:-
使用
ClusterRoleBinding
来代替rolebinding
。 -
将主题命名空间设置为
REPLACE_NAMESPACE
。该命名空间必须改为部署 Operator 的命名空间。
-
使用
-
自定义 Operator 逻辑。
在本例中,
nginx-operator
会针对每个Nginx
自定义资源 (CR) 执行以下协调逻辑:- 如果尚无 Nginx Deployment,请创建一个。
- 如果尚无 Nginx Service,请创建一个。
- 如果支持 Nginx Ingress 但尚不存在,请创建一个。
- 确保 Deployment、Service 和可选的 Ingress 符合 Nginx CR 指定的所需配置(如副本数、镜像、服务类型)。
默认情况下,
nginx-operator
会监视Vginx
资源事件,如watches.yaml
文件中所示,并使用指定 Chart 执行 Helm 发行版本:- version: v1alpha1 group: example.com kind: Nginx chart: /opt/helm/helm-charts/nginx
查阅 Nginx Helm Chart。
创建 Helm Operator 项目后,Operator SDK 会创建一个 Helm Chart 示例,其中包含一组模板,用于简单的 Nginx 发行版本。
本例中,针对 Deployment、Service 和 Ingress 资源提供了模板,另外还有
NOTES.txt
模板,Helm Chart 开发人员可利用该模板传达有关发型版本的实用信息。如果您对 Helm Chart 还不够熟悉,请花一点时间查阅 Helm Chart开发人员文档。
了解 Nginx CR spec。
Helm 会使用一个名为 values 的概念来自定义 Helm Chart 的默认值,具体值在 Helm Chart 的
values.yaml
文件中定义。通过在 CR spec 中设置所需值来覆盖这些默认值。以副本数量为例:
首先,检查
helm-charts/nginx/values.yaml
文件,会发现 Chart 有一个名为replicaCount
的值,默认设置为1
。要在部署中使用 2 个 Nginx 实例,您的 CR spec 中必须包含replicaCount: 2
。更新
deploy/crds/example_v1alpha1_nginx_cr.yaml
文件,如下所示:apiVersion: example.com/v1alpha1 kind: Nginx metadata: name: example-nginx spec: replicaCount: 2
同样,服务端口默认设置为
80
。要改用8080
,请通过添加服务端口覆盖来再次更新deploy/crds/example_v1alpha1_nginx_cr.yaml
文件:apiVersion: example.com/v1alpha1 kind: Nginx metadata: name: example-nginx spec: replicaCount: 2 service: port: 8080
Helm Operator 应用整个 spec,将其视为 values 文件内容,与
helm install -f ./overrides.yaml
命令的工作方式类似。
部署 CRD。
在运行 Operator 之前,Kubernetes 需要了解 Operator 将会监视的新自定义资源定义 (CRD)。部署以下 CRD:
$ oc create -f deploy/crds/example_v1alpha1_nginx_crd.yaml
构建并运行 Operator。
有两种方式来构建和运行 Operator:
- 作为 Kubernetes 集群内的一个 Pod。
-
作为集群外的 Go 程序,使用
operator-sdk up
命令。
选择以下任一方法:
作为 Kubernetes 集群内的一个 Pod 来运行。这是生产环境的首先方法。
构建
nginx-operator
镜像并将其推送至 registry:$ operator-sdk build quay.io/example/nginx-operator:v0.0.1 $ docker push quay.io/example/nginx-operator:v0.0.1
deploy/operator.yaml
文件中会生成 Deployment 清单。本文件中的部署镜像需要从占位符REPLACE_IMAGE
修改为之前构建的镜像。为此,请运行:$ sed -i 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml
如果使用
--cluster-scoped=true
标记来创建 Operator,请更新所生成的ClusterRoleBinding
中的服务账户命名空间,以匹配 Operator 的部署位置:$ export OPERATOR_NAMESPACE=$(oc config view --minify -o jsonpath='{.contexts[0].context.namespace}') $ sed -i "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml
如果要在 OSX 中执行这些步骤,请使用以下命令:
$ sed -i "" 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml $ sed -i "" "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml
部署
nginx-operator
:$ oc create -f deploy/service_account.yaml $ oc create -f deploy/role.yaml $ oc create -f deploy/role_binding.yaml $ oc create -f deploy/operator.yaml
验证
nginx-operator
是否正在运行:$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-operator 1 1 1 1 1m
在集群外运行。这是开发阶段的首选方法,可加快部署和测试的速度。
此外,还务必要确保您的计算机上存在
watches.yaml
文件中引用的 Chart 路径。watches.yaml
文件默认能够与通过operator-sdk build
命令构建的 Operator 镜像一起使用。当使用operator-sdk up local
命令开发和测试您的 Operator 时,SDK 会在您的本地文件系统中查找该路径。在该位置创建符号链接,以指向您的 Helm Chart 路径:
$ sudo mkdir -p /opt/helm/helm-charts $ sudo ln -s $PWD/helm-charts/nginx /opt/helm/helm-charts/nginx
要使用
$HOME/.kube/config
中的默认 Kubernetes 配置文件在本地运行 Operator:$ operator-sdk up local
要使用所提供的 Kubernetes 配置文件在本地运行 Operator:
$ operator-sdk up local --kubeconfig=<path_to_config>
部署
Nginx
CR。应用之前修改的
Nginx
CR:$ oc apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml
确保
nginx-operator
为 CR 创建部署:$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE example-nginx-b9phnoz9spckcrua7ihrbkrt1 2 2 2 2 1m
检查 Pod,确认已创建两个副本:
$ oc get pods NAME READY STATUS RESTARTS AGE example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-fjcr9 1/1 Running 0 1m example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-ljbzl 1/1 Running 0 1m
检查 Service 端口是否已设置为
8080
:$ oc get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 8080/TCP 1m
更新
replicaCount
并删除端口。将
spec.replicaCount
字段从2
改为3
,删除spec.service
字段并应用更改:$ cat deploy/crds/example_v1alpha1_nginx_cr.yaml apiVersion: "example.com/v1alpha1" kind: "Nginx" metadata: name: "example-nginx" spec: replicaCount: 3 $ oc apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml
确认 Operator 已更改 Deployment 大小:
$ oc get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE example-nginx-b9phnoz9spckcrua7ihrbkrt1 3 3 3 3 1m
检查 Service 端口是否已设置为默认值
80
。$ oc get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 80/TCP 1m
清理资源:
$ oc delete -f deploy/crds/example_v1alpha1_nginx_cr.yaml $ oc delete -f deploy/operator.yaml $ oc delete -f deploy/role_binding.yaml $ oc delete -f deploy/role.yaml $ oc delete -f deploy/service_account.yaml $ oc delete -f deploy/crds/example_v1alpha1_nginx_crd.yaml
11.3.4. 其他资源
- 有关 Operator SDK 所创建的项目目录结构的信息,请参阅附录。
- 面向红帽合作伙伴的 Operator 开发指南