This documentation is for a release that is no longer maintained
See documentation for the latest supported version 3 or the latest supported version 4.4.2. Creating Ansible-based Operators
This guide outlines Ansible support in the Operator SDK and walks Operator authors through examples building and running Ansible-based Operators with the operator-sdk CLI tool that use Ansible playbooks and modules.
4.2.1. Ansible support in the Operator SDK 复制链接链接已复制到粘贴板!
The Operator Framework is an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. This framework includes the Operator SDK, which assists developers in bootstrapping and building an Operator based on their expertise without requiring knowledge of Kubernetes API complexities.
One of the Operator SDK options for generating an Operator project includes leveraging existing Ansible playbooks and modules to deploy Kubernetes resources as a unified application, without having to write any Go code.
4.2.1.1. Custom resource files 复制链接链接已复制到粘贴板!
Operators use the Kubernetes extension mechanism, custom resource definitions (CRDs), so your custom resource (CR) looks and acts just like the built-in, native Kubernetes objects.
The CR file format is a Kubernetes resource file. The object has mandatory and optional fields:
| Field | Description |
|---|---|
|
| Version of the CR to be created. |
|
| Kind of the CR to be created. |
|
| Kubernetes-specific metadata to be created. |
|
| Key-value list of variables which are passed to Ansible. This field is empty by default. |
|
|
Summarizes the current state of the object. For Ansible-based Operators, the |
|
| Kubernetes-specific annotations to be appended to the CR. |
The following list of CR annotations modify the behavior of the Operator:
| Annotation | Description |
|---|---|
|
|
Specifies the reconciliation interval for the CR. This value is parsed using the standard Golang package |
Example Ansible-based Operator annotation
4.2.1.2. watches.yaml file 复制链接链接已复制到粘贴板!
A group/version/kind (GVK) is a unique identifier for a Kubernetes API. The watches.yaml file contains a list of mappings from custom resources (CRs), identified by its GVK, to an Ansible role or playbook. The Operator expects this mapping file in a predefined location at /opt/ansible/watches.yaml.
| Field | Description |
|---|---|
|
| Group of CR to watch. |
|
| Version of CR to watch. |
|
| Kind of CR to watch |
|
|
Path to the Ansible role added to the container. For example, if your |
|
|
Path to the Ansible playbook added to the container. This playbook is expected to be a way to call roles. This field is mutually exclusive with the |
|
| The reconciliation interval, how often the role or playbook is run, for a given CR. |
|
|
When set to |
Example watches.yaml file
4.2.1.2.1. Advanced options 复制链接链接已复制到粘贴板!
Advanced features can be enabled by adding them to your watches.yaml file per GVK. They can go below the group, version, kind and playbook or role fields.
Some features can be overridden per resource using an annotation on that CR. The options that can be overridden have the annotation specified below.
| Feature | YAML key | Description | Annotation for override | Default value |
|---|---|---|---|---|
| Reconcile period |
| Time between reconcile runs for a particular CR. |
|
|
| Manage status |
|
Allows the Operator to manage the |
| |
| Watch dependent resources |
| Allows the Operator to dynamically watch resources that are created by Ansible. |
| |
| Watch cluster-scoped resources |
| Allows the Operator to watch cluster-scoped resources that are created by Ansible. |
| |
| Max runner artifacts |
| Manages the number of artifact directories that Ansible Runner keeps in the Operator container for each individual resource. |
|
|
Example watches.yml file with advanced options
4.2.1.3. Extra variables sent to Ansible 复制链接链接已复制到粘贴板!
Extra variables can be sent to Ansible, which are then managed by the Operator. The spec section of the custom resource (CR) passes along the key-value pairs as extra variables. This is equivalent to extra variables passed in to the ansible-playbook command.
The Operator also passes along additional variables under the meta field for the name of the CR and the namespace of the CR.
For the following CR example:
The structure passed to Ansible as extra variables is:
The message and newParameter fields are set in the top level as extra variables, and meta provides the relevant metadata for the CR as defined in the Operator. The meta fields can be accessed using dot notation in Ansible, for example:
- debug:
msg: "name: {{ meta.name }}, {{ meta.namespace }}"
- debug:
msg: "name: {{ meta.name }}, {{ meta.namespace }}"
4.2.1.4. Ansible Runner directory 复制链接链接已复制到粘贴板!
Ansible Runner keeps information about Ansible runs in the container. This is located at /tmp/ansible-operator/runner/<group>/<version>/<kind>/<namespace>/<name>.
Additional resources
-
To learn more about the
runnerdirectory, see the Ansible Runner documentation.
4.2.2. Installing the Operator SDK CLI 复制链接链接已复制到粘贴板!
The Operator SDK has a CLI tool that assists developers in creating, building, and deploying a new Operator project. You can install the SDK CLI on your workstation so you are prepared to start authoring your own Operators.
4.2.2.1. Installing from GitHub release 复制链接链接已复制到粘贴板!
You can download and install a pre-built release binary of the Operator SDK CLI from the project on GitHub.
Prerequisites
- Go v1.13+
-
dockerv17.03+,podmanv1.2.0+, orbuildahv1.7+ -
OpenShift CLI (
oc) v4.5+ installed - Access to a cluster based on Kubernetes v1.12.0+
- Access to a container registry
Procedure
Set the release version variable:
RELEASE_VERSION=v0.17.2
$ RELEASE_VERSION=v0.17.2Copy to Clipboard Copied! Toggle word wrap Toggle overflow Download the release binary.
For Linux:
curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnuCopy to Clipboard Copied! Toggle word wrap Toggle overflow For macOS:
curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwinCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Verify the downloaded release binary.
Download the provided
.ascfile.For Linux:
curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.ascCopy to Clipboard Copied! Toggle word wrap Toggle overflow For macOS:
curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc$ curl -OJL https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.ascCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Place the binary and corresponding
.ascfile into the same directory and run the following command to verify the binary:For Linux:
gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.asc$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu.ascCopy to Clipboard Copied! Toggle word wrap Toggle overflow For macOS:
gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.asc$ gpg --verify operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin.ascCopy to Clipboard Copied! Toggle word wrap Toggle overflow
If you do not have the public key of the maintainer on your workstation, you will get the following error:
Example output with error
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> gpg: Can't check signature: No public key$ 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 keyCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- RSA key string.
To download the key, run the following command, replacing
<key_id>with the RSA key string provided in the output of the previous command:gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>"
$ gpg [--keyserver keys.gnupg.net] --recv-key "<key_id>"1 Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- If you do not have a key server configured, specify one with the
--keyserveroption.
Install the release binary in your
PATH:For Linux:
chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnuCopy to Clipboard Copied! Toggle word wrap Toggle overflow sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk$ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdkCopy to Clipboard Copied! Toggle word wrap Toggle overflow rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu$ rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnuCopy to Clipboard Copied! Toggle word wrap Toggle overflow For macOS:
chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin$ chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwinCopy to Clipboard Copied! Toggle word wrap Toggle overflow sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdk$ sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin /usr/local/bin/operator-sdkCopy to Clipboard Copied! Toggle word wrap Toggle overflow rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwin$ rm operator-sdk-${RELEASE_VERSION}-x86_64-apple-darwinCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Verify that the CLI tool was installed correctly:
operator-sdk version
$ operator-sdk versionCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.2.2.2. Installing from Homebrew 复制链接链接已复制到粘贴板!
You can install the SDK CLI using Homebrew.
Prerequisites
- Homebrew
-
dockerv17.03+,podmanv1.2.0+, orbuildahv1.7+ -
OpenShift CLI (
oc) v4.5+ installed - Access to a cluster based on Kubernetes v1.12.0+
- Access to a container registry
Procedure
Install the SDK CLI using the
brewcommand:brew install operator-sdk
$ brew install operator-sdkCopy to Clipboard Copied! Toggle word wrap Toggle overflow Verify that the CLI tool was installed correctly:
operator-sdk version
$ operator-sdk versionCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.2.2.3. Compiling and installing from source 复制链接链接已复制到粘贴板!
You can obtain the Operator SDK source code to compile and install the SDK CLI.
Prerequisites
Procedure
Clone the
operator-sdkrepository:mkdir -p $GOPATH/src/github.com/operator-framework
$ mkdir -p $GOPATH/src/github.com/operator-frameworkCopy to Clipboard Copied! Toggle word wrap Toggle overflow cd $GOPATH/src/github.com/operator-framework
$ cd $GOPATH/src/github.com/operator-frameworkCopy to Clipboard Copied! Toggle word wrap Toggle overflow git clone https://github.com/operator-framework/operator-sdk
$ git clone https://github.com/operator-framework/operator-sdkCopy to Clipboard Copied! Toggle word wrap Toggle overflow cd operator-sdk
$ cd operator-sdkCopy to Clipboard Copied! Toggle word wrap Toggle overflow Check out the desired release branch:
git checkout master
$ git checkout masterCopy to Clipboard Copied! Toggle word wrap Toggle overflow Compile and install the SDK CLI:
make dep
$ make depCopy to Clipboard Copied! Toggle word wrap Toggle overflow make install
$ make installCopy to Clipboard Copied! Toggle word wrap Toggle overflow This installs the CLI binary
operator-sdkat $GOPATH/bin.Verify that the CLI tool was installed correctly:
operator-sdk version
$ operator-sdk versionCopy to Clipboard Copied! Toggle word wrap Toggle overflow
This procedure walks through an example of building a simple Memcached Operator powered by Ansible playbooks and modules using tools and libraries provided by the Operator SDK.
Prerequisites
- Operator SDK CLI installed on the development workstation
-
Access to a Kubernetes-based cluster v1.11.3+ (for example OpenShift Container Platform 4.5) using an account with
cluster-adminpermissions -
OpenShift CLI (
oc) v4.5+ installed -
ansiblev2.9.0+ -
ansible-runnerv1.1.0+ -
ansible-runner-httpv1.0.0+
Procedure
Create a new Operator project. A namespace-scoped Operator watches and manages resources in a single namespace. Namespace-scoped Operators are preferred because of their flexibility. They enable decoupled upgrades, namespace isolation for failures and monitoring, and differing API definitions.
To create a new Ansible-based, namespace-scoped
memcached-operatorproject and change to the new directory, use the following commands:operator-sdk new memcached-operator \ --api-version=cache.example.com/v1alpha1 \ --kind=Memcached \ --type=ansible$ operator-sdk new memcached-operator \ --api-version=cache.example.com/v1alpha1 \ --kind=Memcached \ --type=ansibleCopy to Clipboard Copied! Toggle word wrap Toggle overflow cd memcached-operator
$ cd memcached-operatorCopy to Clipboard Copied! Toggle word wrap Toggle overflow This creates the
memcached-operatorproject specifically for watching theMemcachedresource with API versionexample.com/v1apha1and kindMemcached.Customize the Operator logic.
For this example, the
memcached-operatorexecutes the following reconciliation logic for eachMemcachedcustom resource (CR):-
Create a
memcacheddeployment if it does not exist. -
Ensure that the deployment size is the same as specified by the
MemcachedCR.
By default, the
memcached-operatorwatchesMemcachedresource events as shown in thewatches.yamlfile and executes the Ansible roleMemcached:- version: v1alpha1 group: cache.example.com kind: Memcached
- version: v1alpha1 group: cache.example.com kind: MemcachedCopy to Clipboard Copied! Toggle word wrap Toggle overflow You can optionally customize the following logic in the
watches.yamlfile:Specifying a
roleoption configures the Operator to use this specified path when launchingansible-runnerwith an Ansible role. By default, theoperator-sdk newcommand fills in an absolute path to where your role should go:- version: v1alpha1 group: cache.example.com kind: Memcached role: /opt/ansible/roles/memcached
- version: v1alpha1 group: cache.example.com kind: Memcached role: /opt/ansible/roles/memcachedCopy to Clipboard Copied! Toggle word wrap Toggle overflow Specifying a
playbookoption in thewatches.yamlfile configures the Operator to use this specified path when launchingansible-runnerwith an Ansible playbook:- version: v1alpha1 group: cache.example.com kind: Memcached playbook: /opt/ansible/playbook.yaml
- version: v1alpha1 group: cache.example.com kind: Memcached playbook: /opt/ansible/playbook.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow
-
Create a
Build the Memcached Ansible role.
Modify the generated Ansible role under the
roles/memcached/directory. This Ansible role controls the logic that is executed when a resource is modified.Define the
Memcachedspec.Defining the spec for an Ansible-based Operator can be done entirely in Ansible. The Ansible Operator passes all key-value pairs listed in the CR spec field along to Ansible as variables. The names of all variables in the spec field are converted to snake case (lowercase with an underscore) by the Operator before running Ansible. For example,
serviceAccountin the spec becomesservice_accountin Ansible.提示You should perform some type validation in Ansible on the variables to ensure that your application is receiving expected input.
In case the user does not set the
specfield, set a default by modifying theroles/memcached/defaults/main.ymlfile:size: 1
size: 1Copy to Clipboard Copied! Toggle word wrap Toggle overflow Define the
Memcacheddeployment.With the
Memcachedspec now defined, you can define what Ansible is actually executed on resource changes. Because this is an Ansible role, the default behavior executes the tasks in theroles/memcached/tasks/main.ymlfile.The goal is for Ansible to create a deployment if it does not exist, which runs the
memcached:1.4.36-alpineimage. Ansible 2.7+ supports the k8s Ansible module, which this example leverages to control the deployment definition.Modify the
roles/memcached/tasks/main.ymlto match the following:Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注意This example used the
sizevariable to control the number of replicas of theMemcacheddeployment. This example sets the default to1, but any user can create a CR that overwrites the default.
Deploy the CRD.
Before running the Operator, Kubernetes needs to know about the new custom resource definition (CRD) that the Operator will be watching. Deploy the
MemcachedCRD:oc create -f deploy/crds/cache.example.com_memcacheds_crd.yaml
$ oc create -f deploy/crds/cache.example.com_memcacheds_crd.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Build and run the Operator.
There are two ways to build and run the Operator:
- As a pod inside a Kubernetes cluster.
-
As a Go program outside the cluster using the
operator-sdk upcommand.
Choose one of the following methods:
Run as a pod inside a Kubernetes cluster. This is the preferred method for production use.
Build the
memcached-operatorimage and push it to a registry:operator-sdk build quay.io/example/memcached-operator:v0.0.1
$ operator-sdk build quay.io/example/memcached-operator:v0.0.1Copy to Clipboard Copied! Toggle word wrap Toggle overflow podman push quay.io/example/memcached-operator:v0.0.1
$ podman push quay.io/example/memcached-operator:v0.0.1Copy to Clipboard Copied! Toggle word wrap Toggle overflow Deployment manifests are generated in the
deploy/operator.yamlfile. The deployment image in this file needs to be modified from the placeholderREPLACE_IMAGEto the previous built image. To do this, run:sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.1|g' deploy/operator.yaml
$ sed -i 's|REPLACE_IMAGE|quay.io/example/memcached-operator:v0.0.1|g' deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Deploy the
memcached-operatormanifests:oc create -f deploy/service_account.yaml
$ oc create -f deploy/service_account.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role.yaml
$ oc create -f deploy/role.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role_binding.yaml
$ oc create -f deploy/role_binding.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/operator.yaml
$ oc create -f deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Verify that the
memcached-operatordeployment is up and running:oc get deployment
$ oc get deploymentCopy to Clipboard Copied! Toggle word wrap Toggle overflow NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 1m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 1mCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Run outside the cluster. This method is preferred during the development cycle to speed up deployment and testing.
Ensure that Ansible Runner and Ansible Runner HTTP Plug-in are installed or else you will see unexpected errors from Ansible Runner when a CR is created.
It is also important that the role path referenced in the
watches.yamlfile exists on your machine. Because normally a container is used where the role is put on disk, the role must be manually copied to the configured Ansible roles path (for example/etc/ansible/roles).To run the Operator locally with the default Kubernetes configuration file present at
$HOME/.kube/config:operator-sdk run --local
$ operator-sdk run --localCopy to Clipboard Copied! Toggle word wrap Toggle overflow To run the Operator locally with a provided Kubernetes configuration file:
operator-sdk run --local --kubeconfig=config
$ operator-sdk run --local --kubeconfig=configCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Create a
MemcachedCR.Modify the
deploy/crds/cache_v1alpha1_memcached_cr.yamlfile as shown and create aMemcachedCR:cat deploy/crds/cache_v1alpha1_memcached_cr.yaml
$ cat deploy/crds/cache_v1alpha1_memcached_cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
Copy to Clipboard Copied! Toggle word wrap Toggle overflow oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
$ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Ensure that the
memcached-operatorcreates the deployment for the CR:oc get deployment
$ oc get deploymentCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 2m example-memcached 3 3 3 3 1m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE memcached-operator 1 1 1 1 2m example-memcached 3 3 3 3 1mCopy to Clipboard Copied! Toggle word wrap Toggle overflow Check the pods to confirm three replicas were created:
oc get pods
$ oc get podsCopy to Clipboard Copied! Toggle word wrap Toggle overflow NAME READY STATUS RESTARTS AGE example-memcached-6fd7c98d8-7dqdr 1/1 Running 0 1m example-memcached-6fd7c98d8-g5k7v 1/1 Running 0 1m example-memcached-6fd7c98d8-m7vn7 1/1 Running 0 1m memcached-operator-7cc7cfdf86-vvjqk 1/1 Running 0 2m
NAME READY STATUS RESTARTS AGE example-memcached-6fd7c98d8-7dqdr 1/1 Running 0 1m example-memcached-6fd7c98d8-g5k7v 1/1 Running 0 1m example-memcached-6fd7c98d8-m7vn7 1/1 Running 0 1m memcached-operator-7cc7cfdf86-vvjqk 1/1 Running 0 2mCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Update the size.
Change the
spec.sizefield in thememcachedCR from3to4and apply the change:cat deploy/crds/cache_v1alpha1_memcached_cr.yaml
$ cat deploy/crds/cache_v1alpha1_memcached_cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
Copy to Clipboard Copied! Toggle word wrap Toggle overflow oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
$ oc apply -f deploy/crds/cache_v1alpha1_memcached_cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Confirm that the Operator changes the deployment size:
oc get deployment
$ oc get deploymentCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE example-memcached 4 4 4 4 5m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE example-memcached 4 4 4 4 5mCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Clean up the resources:
oc delete -f deploy/crds/cache_v1alpha1_memcached_cr.yaml
$ oc delete -f deploy/crds/cache_v1alpha1_memcached_cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc delete -f deploy/operator.yaml
$ oc delete -f deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc delete -f deploy/role_binding.yaml
$ oc delete -f deploy/role_binding.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc delete -f deploy/role.yaml
$ oc delete -f deploy/role.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc delete -f deploy/service_account.yaml
$ oc delete -f deploy/service_account.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc delete -f deploy/crds/cache_v1alpha1_memcached_crd.yaml
$ oc delete -f deploy/crds/cache_v1alpha1_memcached_crd.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow
To manage the lifecycle of your application on Kubernetes using Ansible, you can use the k8s Ansible module. This Ansible module allows a developer to either leverage their existing Kubernetes resource files (written in YAML) or express the lifecycle management in native Ansible.
One of the biggest benefits of using Ansible in conjunction with existing Kubernetes resource files is the ability to use Jinja templating so that you can customize resources with the simplicity of a few variables in Ansible.
This section goes into detail on usage of the k8s Ansible module. To get started, install the module on your local workstation and test it using a playbook before moving on to using it within an Operator.
4.2.4.1. Installing the k8s Ansible module 复制链接链接已复制到粘贴板!
To install the k8s Ansible module on your local workstation:
Procedure
Install Ansible 2.9+:
sudo yum install ansible
$ sudo yum install ansibleCopy to Clipboard Copied! Toggle word wrap Toggle overflow Install the OpenShift python client package using
pip:sudo pip install openshift
$ sudo pip install openshiftCopy to Clipboard Copied! Toggle word wrap Toggle overflow sudo pip install kubernetes
$ sudo pip install kubernetesCopy to Clipboard Copied! Toggle word wrap Toggle overflow
4.2.4.2. Testing the k8s Ansible module locally 复制链接链接已复制到粘贴板!
Sometimes, it is beneficial for a developer to run the Ansible code from their local machine as opposed to running and rebuilding the Operator each time.
Procedure
Install the
community.kubernetescollection:ansible-galaxy collection install community.kubernetes
$ ansible-galaxy collection install community.kubernetesCopy to Clipboard Copied! Toggle word wrap Toggle overflow Initialize a new Ansible-based Operator project:
operator-sdk new --type ansible \ --kind Test1 \ --api-version test1.example.com/v1alpha1 test1-operator$ operator-sdk new --type ansible \ --kind Test1 \ --api-version test1.example.com/v1alpha1 test1-operatorCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
Copy to Clipboard Copied! Toggle word wrap Toggle overflow cd test1-operator
$ cd test1-operatorCopy to Clipboard Copied! Toggle word wrap Toggle overflow Modify the
roles/test1/tasks/main.ymlfile with the Ansible logic that you want. This example creates and deletes a namespace with the switch of a variable.Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- Setting
ignore_errors: trueensures that deleting a nonexistent project does not fail.
Modify the
roles/test1/defaults/main.ymlfile to setstatetopresentby default:state: present
state: presentCopy to Clipboard Copied! Toggle word wrap Toggle overflow Create an Ansible playbook
playbook.ymlin the top-level directory, which includes thetest1role:- hosts: localhost roles: - test1- hosts: localhost roles: - test1Copy to Clipboard Copied! Toggle word wrap Toggle overflow Run the playbook:
ansible-playbook playbook.yml
$ ansible-playbook playbook.ymlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Check that the namespace was created:
oc get namespace
$ oc get namespaceCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3s
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3sCopy to Clipboard Copied! Toggle word wrap Toggle overflow Rerun the playbook setting
statetoabsent:ansible-playbook playbook.yml --extra-vars state=absent
$ ansible-playbook playbook.yml --extra-vars state=absentCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Check that the namespace was deleted:
oc get namespace
$ oc get namespaceCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28dCopy to Clipboard Copied! Toggle word wrap Toggle overflow
After you are familiar with using the k8s Ansible module locally, you can trigger the same Ansible logic inside of an Operator when a custom resource (CR) changes. This example maps an Ansible role to a specific Kubernetes resource that the Operator watches. This mapping is done in the watches.yaml file.
4.2.4.3.1. Testing an Ansible-based Operator locally 复制链接链接已复制到粘贴板!
After getting comfortable testing Ansible workflows locally, you can test the logic inside of an Ansible-based Operator running locally.
To do so, use the operator-sdk run --local command from the top-level directory of your Operator project. This command reads from the watches.yaml file and uses the ~/.kube/config file to communicate with a Kubernetes cluster just as the k8s Ansible module does.
Procedure
Because the
run --localcommand reads from thewatches.yamlfile, there are options available to the Operator author. Ifroleis left alone (by default,/opt/ansible/roles/<name>) you must copy the role over to the/opt/ansible/roles/directory from the Operator directly.This is cumbersome because changes are not reflected from the current directory. Instead, change the
rolefield to point to the current directory and comment out the existing line:- version: v1alpha1 group: test1.example.com kind: Test1 # role: /opt/ansible/roles/Test1 role: /home/user/test1-operator/Test1
- version: v1alpha1 group: test1.example.com kind: Test1 # role: /opt/ansible/roles/Test1 role: /home/user/test1-operator/Test1Copy to Clipboard Copied! Toggle word wrap Toggle overflow Create a custom resource definition (CRD) and proper role-based access control (RBAC) definitions for the custom resource (CR)
Test1. Theoperator-sdkcommand autogenerates these files inside of thedeploy/directory:oc create -f deploy/crds/test1_v1alpha1_test1_crd.yaml
$ oc create -f deploy/crds/test1_v1alpha1_test1_crd.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/service_account.yaml
$ oc create -f deploy/service_account.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role.yaml
$ oc create -f deploy/role.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role_binding.yaml
$ oc create -f deploy/role_binding.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Run the
run --localcommand:operator-sdk run --local
$ operator-sdk run --localCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
[...] INFO[0000] Starting to serve on 127.0.0.1:8888 INFO[0000] Watching test1.example.com/v1alpha1, Test1, default
[...] INFO[0000] Starting to serve on 127.0.0.1:8888 INFO[0000] Watching test1.example.com/v1alpha1, Test1, defaultCopy to Clipboard Copied! Toggle word wrap Toggle overflow Now that the Operator is watching the resource
Test1for events, the creation of a CR triggers your Ansible role to execute. View thedeploy/cr.yamlfile:apiVersion: "test1.example.com/v1alpha1" kind: "Test1" metadata: name: "example"
apiVersion: "test1.example.com/v1alpha1" kind: "Test1" metadata: name: "example"Copy to Clipboard Copied! Toggle word wrap Toggle overflow Because the
specfield is not set, Ansible is invoked with no extra variables. The next section covers how extra variables are passed from a CR to Ansible. This is why it is important to set reasonable defaults for the Operator.Create a CR instance of
Test1with the default variablestateset topresent:oc create -f deploy/cr.yaml
$ oc create -f deploy/cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Check that the namespace
testwas created:oc get namespace
$ oc get namespaceCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3s
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d test Active 3sCopy to Clipboard Copied! Toggle word wrap Toggle overflow Modify the
deploy/cr.yamlfile to set thestatefield toabsent:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Apply the changes and confirm that the namespace is deleted:
oc apply -f deploy/cr.yaml
$ oc apply -f deploy/cr.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc get namespace
$ oc get namespaceCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28d
NAME STATUS AGE default Active 28d kube-public Active 28d kube-system Active 28dCopy to Clipboard Copied! Toggle word wrap Toggle overflow
After getting familiar running Ansible logic inside of an Ansible-based Operator locally, you can test the Operator inside of a pod on a Kubernetes cluster, such as OpenShift Container Platform. Running as a pod on a cluster is preferred for production use.
Procedure
Build the
test1-operatorimage and push it to a registry:operator-sdk build quay.io/example/test1-operator:v0.0.1
$ operator-sdk build quay.io/example/test1-operator:v0.0.1Copy to Clipboard Copied! Toggle word wrap Toggle overflow podman push quay.io/example/test1-operator:v0.0.1
$ podman push quay.io/example/test1-operator:v0.0.1Copy to Clipboard Copied! Toggle word wrap Toggle overflow Deployment manifests are generated in the
deploy/operator.yamlfile. The deployment image in this file must be modified from the placeholderREPLACE_IMAGEto the previously-built image. To do so, run the following command:sed -i 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yaml
$ sed -i 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow If you are performing these steps on macOS, use the following command instead:
sed -i "" 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yaml
$ sed -i "" 's|REPLACE_IMAGE|quay.io/example/test1-operator:v0.0.1|g' deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Deploy the
test1-operator:oc create -f deploy/crds/test1_v1alpha1_test1_crd.yaml
$ oc create -f deploy/crds/test1_v1alpha1_test1_crd.yaml1 Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 1
- Only required if the CRD does not exist already.
oc create -f deploy/service_account.yaml
$ oc create -f deploy/service_account.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role.yaml
$ oc create -f deploy/role.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/role_binding.yaml
$ oc create -f deploy/role_binding.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow oc create -f deploy/operator.yaml
$ oc create -f deploy/operator.yamlCopy to Clipboard Copied! Toggle word wrap Toggle overflow Verify that the
test1-operatoris up and running:oc get deployment
$ oc get deploymentCopy to Clipboard Copied! Toggle word wrap Toggle overflow Example output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE test1-operator 1 1 1 1 1m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE test1-operator 1 1 1 1 1mCopy to Clipboard Copied! Toggle word wrap Toggle overflow You can now view the Ansible logs for the
test1-operator:oc logs deployment/test1-operator
$ oc logs deployment/test1-operatorCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Ansible-based Operators automatically update custom resource (CR) status subresources with generic information about the previous Ansible run. This includes the number of successful and failed tasks and relevant error messages as shown:
Ansible-based Operators also allow Operator authors to supply custom status values with the k8s_status Ansible module, which is included in the operator_sdk.util collection. This allows the author to update the status from within Ansible with any key-value pair as desired.
By default, Ansible-based Operators always include the generic Ansible run output as shown above. If you would prefer your application did not update the status with Ansible output, you can track the status manually from your application.
Procedure
To track CR status manually from your application, update the
watches.yamlfile with amanageStatusfield set tofalse:- version: v1 group: api.example.com kind: Test1 role: Test1 manageStatus: false
- version: v1 group: api.example.com kind: Test1 role: Test1 manageStatus: falseCopy to Clipboard Copied! Toggle word wrap Toggle overflow Use the
operator_sdk.util.k8s_statusAnsible module to update the subresource. For example, to update with keytest1and valuetest2,operator_sdk.utilcan be used as shown:Copy to Clipboard Copied! Toggle word wrap Toggle overflow Collections can also be declared in the
meta/main.ymlfor the role, which is included for new scaffolded Ansible Operators:collections: - operator_sdk.util
collections: - operator_sdk.utilCopy to Clipboard Copied! Toggle word wrap Toggle overflow Declaring collections in the role meta allows you to invoke the
k8s_statusmodule directly:k8s_status: <snip> status: test1: test2k8s_status: <snip> status: test1: test2Copy to Clipboard Copied! Toggle word wrap Toggle overflow
Additional resources
- For more details about user-driven status management from Ansible-based Operators, see the Ansible-based Operator Status Proposal for Operator SDK.
4.2.6. Additional resources 复制链接链接已复制到粘贴板!
- See Appendices to learn about the project directory structures created by the Operator SDK.
- Reaching for the Stars with Ansible Operator - Red Hat OpenShift Blog
- Operator Development Guide for Red Hat Partners