| title | linkTitle | weight |
|---|---|---|
Ansible Operator Tutorial |
Tutorial |
3 |
This tutorial walks operator authors through the entire process of:
- building a simple Ansible-based operator using the
operator sdkscaffolding - deploying and using the operator on a cluster.
If you would prefer to try out an existing operator you can skip to the Using the Operator section using a container we've built from the [operator-sdk-samples][TODO/ansible-memcached] repository.
TODO(asmacdo) remove Note to reviewer
I can remove this part for now, but if we put this in place,
prospective operator authors can understand and play with a working
operator without needing to write one.
- [docker][docker_tool] version 17.03+.
- [kubectl][kubectl_tool] version v1.11.3+.
- [Ansible Operator SDK Installation][ansible-operator-install] v1.0.0+
- Access to a Kubernetes v1.11.3+ cluster.
In this tutorial we will:
- extend the Kubernetes API with a [Custom Resource Definition][TODO] that allows users to create
Memcachedresources. - create a manager that updates the state of the cluster to the desired state defined by
Memcachedresources.
Begin by generating a new project from a new directory.
# TODO(asmacdo) I Dont think this needs to be in the gopath, even for `make run`?
$ mkdir memcached-operator && cd memcached-operator
$ operator-sdk init --plugins=ansibleAmong the files generated by this command is a Kubebuilder PROJECT
file. Subsequent operator-sdk commands (and help text) run from the
project root read this file and are aware that the project type is
Ansible.
# Since this is an Ansible-based project, this help text is Ansible specific.
$ operator-sdk create api -hNext, we will create a Memcached API.
$ operator-sdk create api --generate-playbook --group cache --version v1alpha1 --kind Memcached --generate-roleThe scaffolded operator has the following structure:
MemcachedCustom Resource Definition, and a sampleMemcachedresource.- A "Manager" that [reconciles][TODO] the state of the cluster to the desired state
- A reconciler, which is an Ansible Role or Playbook.
- A
watches.yamlfile, which connects theMemcachedresource to thememcachedAnsible Role.
See [scaffolded files reference][TODO] and [watches reference][watches reference TODO] for more detailed information
Now we need to provide the reconcile logic, in the form of an Ansible
Role, which will run every time a Memcached resource is created,
updated, or delete.
Update roles/memecached/tasks/main.yml:
---
- name: start memcached
community.kubernetes.k8s:
definition:
kind: Deployment
apiVersion: apps/v1
metadata:
name: '{{ meta.name }}-memcached'
namespace: '{{ meta.namespace }}'
spec:
replicas: "{{size}}"
selector:
matchLabels:
app: memcached
template:
metadata:
labels:
app: memcached
spec:
containers:
- name: memcached
command:
- memcached
- -m=64
- -o
- modern
- -v
image: "docker.io/memcached:1.4.36-alpine"
ports:
- containerPort: 11211This memcached role will:
- Ensure a memcached Deployment exists
- Set the Deployment size
It is good practice to set default values for variables used in Ansible
Roles, so edit memcached-operator/roles/memecached/defaults/main.yml:
---
# defaults file for Memcached
size: 1Finally, update the Memcached sample, memcached-operator/config/samples/cache_v1alpha1_memcached.yaml:
apiVersion: cache.example.com/v1alpha1
kind: Memcached
metadata:
name: memcached-sample
spec:
size: 3The key-value pairs in the Custom Resource spec are passed to Ansible as extra variables.
Note: The names of all variables in the spec field are converted to
snake_case by the operator before running ansible. For example,
serviceAccount in the spec becomes service_account in ansible. You can
disable this case conversion by setting the snakeCaseParameters option
to false in your watches.yaml. It is recommended that you perform some
type validation in Ansible on the variables to ensure that your
application is receiving expected input.
All that remains is building and pushing the operator container to your favorite registry.
$ IMG=quay.io/someuser/image:v1.0.0 make docker-build && make docker-pushNote To allow the cluster to pull the image, the repository needs to be set to public.
This section walks through the steps that operator users will perform to deploy the operator and managed resources.
If you've built an operator using the steps above, use your image:
$ export IMG=<yourimage>OR: If you just want to try out an operator, you can also use our pre-built image.
export IMG=quay.io/operator-sd/ansible-memcached-operator-tutorial:v0.0.0To apply the Memcached Kind (CRD):
$ make install# IMG environment variable must be set
$ make deployVerify that the memcached-operator is up and running:
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
memcached-operator 1 1 1 1 1mCreate the resource, the operator will do the rest.
kubectl apply -f config/samples/cache_v1alpha1_memcached.yamlVerify that Memcached pods are created
kubectl get podsIn order to see the logs from a particular you can run:
kubectl logs deployment/kb-controller-manager -c managerThe logs contain the information about the Ansible run and will make it much easier to debug issues within your Ansible tasks. Note that the logs will contain much more detailed information about the Ansible Operator's internals and interface with Kubernetes as well.
Also, you can use the environment variable ANSIBLE_DEBUG_LOGS set as True to check the full Ansible result in the logs in order to be able to debug it.
Example
In the deploy/operator.yaml:
...
- name: ANSIBLE_DEBUG_LOGS
value: "True"
...Clean up the resources:
# TODO(asmacdo) the CR should be removed when CRD is removed $ kubectl delete -f config/samples/blahblak
$ make undeployFor development it may be easier to [run the operator locally][TODO(asmacdo)], which does not require rebuilding the manager image every iteration.
We recommend reading through the our [Ansible development section][TODO(asmacdo)] for tips and tricks.
In this tutorial, the scaffolded watches.yaml could be used as-is, but
has additional optional features. See [watches reference][TODO(asmacdo)]
For brevity, some of the scaffolded files were left out of this guide. See [Scaffolding Reference][TODO(asmacdo)]
This example built a namespaced scope operator, but Ansible operators can also be used with cluster-wide scope. See the operator scope documentation.
To version, install, and upgrade your operator, see out [Operator Lifecycle Management integration][TODO(asmacdo)] documentation.
This method is preferred during the development cycle to speed up deployment and testing.
Note: Ensure that Ansible Runner and Ansible Runner HTTP Plugin is installed or else you will see unexpected errors from Ansible Runner when a Custom Resource is created.
It is also important that the role path referenced in watches.yaml exists
on your machine. Since we are normally used to using a container where the Role
is put on disk for us, we need to manually copy our role to the configured
Ansible Roles path (e.g /etc/ansible/roles.
Run the operator locally with the default Kubernetes config file present at
$HOME/.kube/config:
$ operator-sdk run local
INFO[0000] Go Version: go1.10
INFO[0000] Go OS/Arch: darwin/amd64
INFO[0000] operator-sdk Version: 0.0.5+gitRun the operator locally with a provided Kubernetes config file:
$ operator-sdk run local --kubeconfig=config
INFO[0000] Go Version: go1.10
INFO[0000] Go OS/Arch: darwin/amd64
INFO[0000] operator-sdk Version: 0.0.5+gitDeploy your Operator with the Operator Lifecycle Manager (OLM)
OLM will manage creation of most if not all resources required to run your operator,
using a bit of setup from other operator-sdk commands. Check out the OLM integration
user guide for more information.
Modify deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml as shown and create a Memcached custom resource:
$ cat deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml
apiVersion: "cache.example.com/v1alpha1"
kind: "Memcached"
metadata:
name: "example-memcached"
spec:
size: 3
$ kubectl apply -f deploy/crds/cache.example.com_v1alpha1_memcached_cr.yamlEnsure that the memcached-operator creates the deployment for the CR:
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
memcached-operator 1 1 1 1 2m
example-memcached 3 3 3 3 1mCheck the pods to confirm 3 replicas were created:
$ kubectl get pods
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 2/2 Running 0 2mOccasionally while developing additional debug in the Operator logs is nice to have.
Using the memcached operator as an example, we can simply add the
"ansible.sdk.operatorframework.io/verbosity" annotation to the Custom
Resource with the desired verbosity.
apiVersion: "cache.example.com/v1alpha1"
kind: "Memcached"
metadata:
name: "example-memcached"
annotations:
"ansible.sdk.operatorframework.io/verbosity": "4"
spec:
size: 4Change the spec.size field in the memcached CR from 3 to 4 and apply the
change:
$ cat deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml
apiVersion: "cache.example.com/v1alpha1"
kind: "Memcached"
metadata:
name: "example-memcached"
spec:
size: 4
$ kubectl apply -f deploy/crds/cache.example.com_v1alpha1_memcached_cr.yamlConfirm that the operator changes the deployment size:
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
example-memcached 4 4 4 4 5mClean up the resources:
$ kubectl delete -f deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml
$ kubectl delete -f deploy/operator.yaml
$ kubectl delete -f deploy/role_binding.yaml
$ kubectl delete -f deploy/role.yaml
$ kubectl delete -f deploy/service_account.yaml
$ kubectl delete -f deploy/crds/cache.example.com_memcacheds_crd.yamlNOTE Additional CR/CRD's can be added to the project by running, for example, the command :operator-sdk add api --api-version=cache.example.com/v1alpha1 --kind=AppService
For more information, refer cli doc.