触手可及:掌握Ansible运算符以管理Kubernetes中的应用程序

让我们看看如何使用Ansible Galaxy中发布的角色作为管理Kubernetes中应用程序的操作员,并看看如何创建一个操作员来简单地安装应用程序并根据环境灵活地调整其行为。



我们将使用Ansible Operatork8s模块来展示如何使用Ansible创建Kubernetes应用程序。

Ansible Operator是Operator SDK的一部分,可让您以Ansible角色和剧本的语言制定应用程序的操作规定(应如何安装和维护)。 当创建这样的角色和剧本时,k8s模块又扩展了在Kubernetes中管理对象的能力。

像这样创建一个运算符。

FROM quay.io/operator-framework/ansible-operator RUN ansible-galaxy install djzager.hello_world_k8s RUN echo $'--- \n\ - version: v1alpha1\n\ group: examples.djzager.io\n\ kind: HelloWorld\n\ role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml 

开始键


首先, 简要介绍一下k8s Ansible模块 。 它出现在Ansible 2.6中,并扩展了使用Ansible的Kubernetes对象以及任何Kubernetes发行版(包括Red Hat OpenShift)的可能性。 Ansible博客上有一篇关于该模块和Red Hat OpenShift动态Python客户端单独文章 。 我们认为,不使用k8s模块通过Ansible处理Kubernetes对象是错误的。 操作员机制最初是为了在Kubernetes中运行应用程序而创建的,而Operator SDK提供了用于组装,测试和打包操作员的工具。 反过来,需要使用Ansible Operator才能以Ansible语言设置应用程序的操作规则。 相应的工作流的组织方式非常简单:首先,我们执行operator-sdk new --type = Ansible来为Ansible运算符生成必要的文件,然后绘制Ansible,最后我们进行operator-sdk构建以构建可在Kubernetes中工作的应用程序。 但是,如果我们已经在Ansible Galaxy中担任过角色,该角色可控制Kubernetes中的应用程序,事情将会变得更加容易。 下面我们将执行以下操作:

  1. 让我们建立一个Ansible角色来管理Kubernetes中的Hello World应用程序,这将帮助我们演示k8s Ansible模块的功能。
  2. 我们将在Ansible Galaxy中发布此角色。

因此,让我们使用在Ansible Galaxy中发布的角色组装Ansible-operator。 为什么还要使用Ansible Galaxy中的角色创建操作员? 有两个原因:

  1. 为了不重复 。 如果我们已经对Ansible角色进行了编程以管理Hello World应用程序并将其发布在Ansible Galaxy中,则在创建Ansible运算符时使用它是合乎逻辑的。
  2. 由于职责分工 。 我们希望Hello World Ansible角色可以在Kubernetes中管理同名应用程序,并且希望操作(操作)逻辑保留在操作员内部。 在我们的示例中,操作逻辑非常简单:每次创建或修改自定义HelloWorld资源时,它只需调用djzager.hello_world_k8s角色。 但是, 将来这种分离将变得更加重要,例如,我们将通过Ansible角色向Hello World应用程序添加验证,并且我们将通过运算符逻辑实现HelloWorld自定义资源的状态控制。

您好Kubernetes,认识Ansible


我们需要什么


  1. Ansible-如果您尚未安装 Ansible,请参阅安装指南
  2. OpenShift的Python客户端(可选)。 仅在本地启动时需要。 安装说明在这里

让我们开始吧。 首先,使用ansible-galaxy创建角色骨架:

 # I like clear names on projects. # In meta/main.yml I will make role_name: hello-world-k8s $ ansible-galaxy init ansible-role-hello-world-k8s 

创建新的Ansible角色后,我们将立即设置所有默认值,以同时记录其有效配置参数。 此外,在这方面,我们的Hello World示例并不特别复杂。 这是我们的defaults / main.yml文件的样子:

 --- # NOTE: meta.name(space) comes from CR metadata when run with Ansible Operator # deploy/crds has an example CR for reference name: "{{ meta.name | default('hello-world') }}" namespace: "{{ meta.namespace | default('hello-world') }}" image: docker.io/ansibleplaybookbundle/hello-world:latest # To uninstall from the cluster # state: absent state: present # The size of the hello-world deployment size: 1 

设置默认值后,有必要确定角色将要执行的操作。 Hello World应用程序必须执行以下操作:

  1. 获取有关集群中可用API的信息。
  2. 创建几个模板,并确保它们在群集中存在或不存在。

因此,我们的任务/ main.yml文件如下所示:

 --- - name: "Get information about the cluster" set_fact: api_groups: "{{ lookup('k8s', cluster_info='api_groups') }}" - name: 'Set hello-world objects state={{ state }}' k8s: state: '{{ state }}' definition: "{{ lookup('template', item.name) | from_yaml }}" when: item.api_exists | default(True) loop: - name: deployment.yml.j2 - name: service.yml.j2 - name: route.yml.j2 api_exists: "{{ True if 'route.openshift.io' in api_groups else False }}" 

在继续使用模板之前,请注意任务文件中的以下行:

 api_exists: "{{ True if 'route.openshift.io' in api_groups else False }}" 

使用set_fact,我们可以获得集群中所有可用API的列表,以便我们可以根据API是否存在(在这种情况下为route.openshift.io)有选择地生成模板。 默认情况下,在OpenShift的Kubernetes集群中,路由不可用并且我们不需要它们,因此仅在集群中存在route.openshift.io时才使用Route对象。

如果群集具有apps.openshift.io API,我们不仅可以根据某些API的可用性选择性地管理群集中的对象,还可以使用Jinja2模板在部署模板中使用OpenShift DeploymentConfig。 这是我们的模板/ deployment.yml.j2文件的样子:

 --- {% if 'apps.openshift.io' in api_groups %} apiVersion: apps.openshift.io/v1 kind: DeploymentConfig {% else %} apiVersion: apps/v1 kind: Deployment {% endif %} metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: replicas: {{ size }} {% if 'apps.openshift.io' in api_groups %} selector: app: {{ name }} service: {{ name }} {% else %} selector: matchLabels: app: {{ name }} service: {{ name }} {% endif %} template: metadata: labels: app: {{ name }} service: {{ name }} spec: containers: - image: {{ image }} name: hello-world ports: - containerPort: 8080 protocol: TCP 

文件模板/ service.yml.j2:

 --- apiVersion: v1 kind: Service metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: ports: - name: web port: 8080 protocol: TCP targetPort: 8080 selector: app: {{ name }} service: {{ name }} 

最后,模板/ route.yml.j2文件:

 --- apiVersion: route.openshift.io/v1 kind: Route metadata: name: {{ name }} namespace: {{ namespace }} labels: app: {{ name }} service: {{ name }} spec: port: targetPort: web to: kind: Service name: {{ name }} 

我们省略了meta / main.yml文件,但可以在此处找到。

因此,我们具有在Kubernetes中管理Hello World应用程序的Ansible角色,并且可以使用集群中可用的API。 换句话说,k8s模块和动态客户端简化了Kubernetes中对象的处理。 我们希望通过这个角色的例子,能够在与Kubernetes合作时展示Ansible的潜力。

你好银河,认识Kubernetes


Ansible Galaxy在设置服务器和管理应用程序方面有很多角色,但是管理Kubernetes应用程序的角色并不多,因此我们将做出一点贡献。

在将角色发布到GitHub后 ,剩下的就是:

  1. 登录Ansible Galaxy以访问我们在GitHub上的存储库。
  2. 导入我们的角色。

就是这样,现在我们的hello_world_k8s角色可以在此处的 Ansible Galaxy中公开使用。

您好Ansible接线员,认识银河


如果您仔细研究了GitHub上的Hello World项目 ,您将注意到我们在其中添加了创建Ansible-operator所需的几项内容,即:

  1. 一个Watches文件 ,它将Kubernetes的自定义资源映射 Ansible角色或剧本。
  2. Dockerfile来构建我们的运算符。
  3. 使用运行我们的操作员所需的Kubernetes对象部署目录

如果您需要了解有关如何构建自己的Ansible语句的更多信息,请使用《 用户指南》 。 但是由于我们承诺要使用Ansible Galaxy中发布的角色来构建Ansible运算符,因此我们真正需要的只是一个Dockerfile:

 FROM quay.io/operator-framework/ansible-operator RUN ansible-galaxy install djzager.hello_world_k8s RUN echo $'--- \n\ - version: v1alpha1\n\ group: examples.djzager.io\n\ kind: HelloWorld\n\ role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml 

现在我们收集运算符:

 $ docker build -t hello-world-operator -f Dockerfile . Sending build context to Docker daemon 157.2 kB Step 1/3 : FROM quay.io/operator-framework/ansible-operator latest: Pulling from operator-framework/ansible-operator Digest: sha256:1156066a05fb1e1dd5d4286085518e5ce15acabfff10a8145eef8da088475db3 Status: Downloaded newer image for quay.io/water-hole/ansible-operator:latest ---> 39cc1d19649d Step 2/3 : RUN ansible-galaxy install djzager.hello_world_k8s ---> Running in 83ba8c21f233 - downloading role 'hello_world_k8s', owned by djzager - downloading role from https://github.com/djzager/ansible-role-hello-world-k8s/archive/master.tar.gz - extracting djzager.hello_world_k8s to /opt/ansible/roles/djzager.hello_world_k8s - djzager.hello_world_k8s (master) was installed successfully Removing intermediate container 83ba8c21f233 ---> 2f303b45576c Step 3/3 : RUN echo $'--- \n- version: v1alpha1\n group: examples.djzager.io\n kind: HelloWorld\n role: /opt/ansible/roles/djzager.hello_world_k8s' > ${HOME}/watches.yaml ---> Running in cced495a9cb4 Removing intermediate container cced495a9cb4 ---> 5827bc3c1ca3 Successfully built 5827bc3c1ca3 Successfully tagged hello-world-operator:latest 

显然,要使用此运算符,您需要我们项目中deploy目录的内容,以创建服务帐户,角色和角色绑定,自定义资源定义以及部署运算符本身。 在部署操作员之后,您将需要创建一个自定义资源来获取Hello World应用程序的实例:

 apiVersion: examples.djzager.io/v1alpha1 kind: HelloWorld metadata: name: example-helloworld namespace: default spec: size: 3 

操作员范围:名称空间和集群


稍高一点,我们已经建议探索我们的deploy目录,并在其中查找启动操作员所需的Kubernetes对象。 使用部署操作员本身的名称空间管理自定义资源时,有三件事限制了操作员的范围:

  1. operator.yaml文件中的WATCH_NAMESPACE环境变量,告诉操作员在哪里寻找自定义资源
  2. 角色
  3. 角色绑定

这个限制对于运营商的发展当然是有用的。 但是,如果我们希望集群的所有用户都可以访问我们的应用程序,则需要管理员的帮助。 我将必须执行以下操作:

  1. 创建ClusterRole而不是Role。
  2. 在将要部署该语句的名称空间中创建ServiceAccount语句。
  3. 创建一个ClusterRoleBinding,它将特定命名空间中的ServiceAccount与ClusterRole关联。
  4. 使用未定义的WATCH_NAMESPACE环境变量(即“”)展开该语句。

如果完成所有这些操作,那么其余的群集用户将能够部署Hello World应用程序的实例。 如果您对此主题感兴趣,建议您学习Operator Lifecycle Manager (Operator框架的一部分)。

星际迷航


我们展示了如何创建一个Ansible角色来控制Kubernetes中的应用程序,如何在Ansible Galaxy中发布此角色以及如何在Ansible运算符中使用它。 我们希望您现在:

  1. 您将使用k8s Ansible模块
  2. 开始在Ansible Galaxy上发布用于管理Kubernetes应用程序的角色。
  3. Operator SDK感兴趣,并订阅我们的Operator Framework新闻

我们故意将Hello World应用程序变得非常简单,但是有些事情可以使它变得更加可靠,其中包括:

  1. 使用Operator SDK-在我们的示例中,我们故意没有这样做,以强调从Ansible角色转换为操作员是多么容易。 但是最好还是将此角色与SDK配合使用(即operator-sdk new),此外,您可能需要在下一步中使用此角色。
  2. 验证-在我们当前的版本中,用户可以创建大小为abc的CR,这将不可避免地在部署阶段导致错误。 因此,最好在规范阶段而不是在工作开始后发现错误。
  3. 生命周期-在更复杂的示例中,它可能是同一版本的更新。 在像我们这样的场景中,其中只有一个版本的Hello World应用程序,我们可以通过将工作容器的映像与相应容器注册表中的可用映像进行比较来确定工作容器的映像是否过时,并在必要时更新正在运行的实例。
  4. 测试-在开发和测试Ansible角色时, 分子非常有用。
  5. Operator Lifecycle Manager是用于管理操作员的工具包。 与之集成将有助于安装和更新我们的操作员。
  6. 状态-我们可以在Hello World CRD中激活状态子资源,并使用k8s_status模块(这是Ansible Operator映像的一部分)在自定义资源中包含状态信息。

Source: https://habr.com/ru/post/zh-CN440188/


All Articles