An Operator is a Kubernetes controller
that deploys and manages application’s resources and services in Kubernetes.
In Kubernetes each of your application’s resources can be defined by a Custom Resource Definition (CRD). CRD’s uniquely identifies your applications custom resources by its Group
, Version
and Kind
in a Kubernetes cluster. Once the CRD’s have been created, you would then create an instance of the Custom Resource, or CR, with a unique name.
Based on the User Guide which walks through an example of building a simple memcached-operator powered by Ansible tools and librairies provided by the Operator SDK I decided to build my own Squash Ansible Operator.
I'm explaining here how to create an ansible Operator but if you want just to test the Squash Operator
you can clone the project and go to the Deploy the squash-operator section
$GOPATH/bin/operator-sdk --version
operator-sdk version 0.0.6+git
$ mkdir -p -p $GOPATH/src/github.com/squash-operator/
$ cd $GOPATH/src/github.com/squash-operator/
The Operator SDK provides an option to create an Ansible Operator. An Ansible Operator leverages the full power of Ansible and it does not require the knowledge or the experience of any other programming language like GO or java. You have just write some Ansible code and edit a few YAML file to get your Operator up and running.
$ $GOPATH/bin/operator-sdk new squash-operator --api-version=app.example.com/v1alpha1 --kind=Squash --type=ansible
Create squash-operator/tmp/init/galaxy-init.sh
Create squash-operator/tmp/build/Dockerfile
Create squash-operator/tmp/build/test-framework/Dockerfile
Create squash-operator/tmp/build/go-test.sh
Rendering Ansible Galaxy role [squash-operator/roles/Squash]...
Cleaning up squash-operator/tmp/init
Create squash-operator/watches.yaml
Create squash-operator/deploy/rbac.yaml
Create squash-operator/deploy/crd.yaml
Create squash-operator/deploy/cr.yaml
Create squash-operator/deploy/operator.yaml
Run git init ...
Initialized empty Git repository in /Users/dwojciec/go/src/github.com/squash-operator/squash-operator/.git/
Run git init done
$ cd squash-operator
$ tree
.
├── deploy
│ ├── cr.yaml
│ ├── crd.yaml
│ ├── operator.yaml
│ └── rbac.yaml
├── roles
│ └── Squash
│ ├── README.md
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
│ └── main.yml
├── tmp
│ └── build
│ ├── Dockerfile
│ ├── go-test.sh
│ └── test-framework
│ └── Dockerfile
└── watches.yaml
14 directories, 16 files
Once all the code generated by the Operator SDK. I have to go to the deploy directory to check the content of all files.
$ pwd
/Users/dwojciec/go/src/github.com/squash-operator/squash-operator/deploy
$ tree
.
├── cr.yaml
├── crd.yaml
├── operator.yaml
└── rbac.yaml
0 directories, 4 files
I updated rbac.yaml with the code here. Check the content of the rbac.yaml file because by default the namespace used is the default one for ClusterRoleBinding and maybe you want to use a different project to deploy your application. In my case I will deploy my Operator in a project I will create named operator-squash . I added and created a sa.yaml file to define ServiceAccount for my application squash-operator.
The first thing to do is to modify the generated Ansible role under roles/Squash
. This Ansible Role controls the logic that is executed when a resource is modified.
I updated the empty file roles/Squash/tasks/main.yaml
with :
---
# tasks file for squash-server
- name: start squash-server
k8s:
definition:
kind: Deployment
apiVersion: apps/v1
metadata:
name: squash-server
namespace: '{{ meta.namespace }}'
spec:
selector:
matchLabels:
app: squash-server
template:
metadata:
labels:
app: squash-server
spec:
containers:
- name: squash-server
image: soloio/squash-server:v0.2.1
- name: start squash-client
k8s:
state: present
definition: "{{ lookup('template', '/opt/ansible/k8s/squash-client.yml') | from_yaml }}"
- name: create squash-server service
k8s:
state: present
definition: "{{ lookup('template', '/opt/ansible/k8s/squash-server-svc.yml') | from_yaml }}"
This Ansible task is creating a Kubernetes deplyment using k8s module. The k8s Ansible module allows you to easily interact with the kubernetes resources idempotently.
Inside the roles/Squash/tasks/main.yaml
file I’m using multiples external files (template), like '/opt/ansible/k8s/squash-server-svc.yml' and to consume this files I updated the Dockerfile to add them.
From ...squash-operator/tmp/build/Dockerfile
FROM quay.io/water-hole/ansible-operator
COPY roles/ ${HOME}/roles/
COPY watches.yaml ${HOME}/watches.yaml
to
FROM quay.io/water-hole/ansible-operator
COPY k8s/ ${HOME}/k8s/
COPY roles/ ${HOME}/roles/
COPY playbook.yaml ${HOME}/playbook.yaml
COPY watches.yaml ${HOME}/watches.yaml
By default the operator SDK generated watches.yaml
file watches Squash resource events and executes Ansible Role Squash.
$ cat watches.yaml
---
- version: v1alpha1
group: app.example.com
kind: Squash
role: /opt/ansible/roles/Squash
I decided to use the Playbook option by specifying a playbook.yaml
file inside watch.yaml
which will configure the operator to use this specified path when launching ansible-runner with the Ansible Playbook.
---
- version: v1alpha1
group: app.example.com
kind: Squash
playbook: /opt/ansible/playbook.yaml
finalizer:
name: finalizer.app.example.com
vars:
sentinel: finalizer_running
Before running the squash operator, Kubernetes needs to know about the new CRD the operator will be watching.
$ oc new-project operator-squash
$ kubectl create -f deploy/crd.yaml
$ $GOPATH/bin/operator-sdk build quay.io/dwojciec/squash-operator:v0.0.1
$ docker push quay.io/dwojciec/squash-operator:v0.0.1
Kubernetes deployment manifests are generated in deploy/operator.yaml
. The deployment image in this file needs to be modified from the placeholder REPLACE_IMAGE to the previous built image. Edit deploy/operator.yaml
file and change :
spec:
containers:
- name: squash-operator
image: REPLACE_IMAGE
ports:
By
spec:
containers:
- name: squash-operator
image: quay.io/dwojciec/squash-operator:v0.0.1
ports:
$ kubectl create -f deploy/rbac.yaml
$ kubectl create -f deploy/operator.yaml
$ kubectl create -f deploy/sa.yaml
Before testing squash you have to run :
oc adm policy add-scc-to-user privileged -z squash-client
oc expose svc squash-server