Helm Operator

Helm Operator - Memcached

Let’s begin my creating a new project called myproject:

oc new-project myproject

If the project already exits, make sure we are currently scoped to it:

oc project myproject

Let’s now create a new directory for our project:

mkdir -p $HOME/projects/memcached-helm-operator

Navigate to the directory:

cd $HOME/projects/memcached-helm-operator

Create a new Helm-based Operator SDK project for the Memcached Operator:

operator-sdk init --plugins helm --domain example.com

For Helm-based projects, operator-sdk init also generates the RBAC rules in config/rbac/role.yaml based on the resources that would be deployed by the chart’s default manifest. Be sure to double check that the rules generated in config/rbac/role.yaml meet the operator’s permission requirements.

Automatically fetch the Memcached Helm Chart and generate the CRD/API:

operator-sdk create api --helm-chart memcached --helm-chart-repo=https://charts.helm.sh/stable

The watches.yaml file maps a Group, Version, and Kind to a specific Helm Chart. Observe the contents of the watches.yaml:

cat watches.yaml

Create the CRD:

oc apply -f config/crd/bases/charts.example.com_memcacheds.yaml

Run the operator locally:

WATCH_NAMESPACE=myproject make run

Open a new terminal window and navigate to the memcached-helm-operator top-level directory:

cd $HOME/projects/memcached-helm-operator

Before applying the Memcached Custom Resource, observe the Memcached Helm Chart values.yaml:

Memcached Helm Chart Values.yaml file

Update the Memcached Custom Resource at config/samples/charts_v1alpha1_memcached.yaml with the following values:

  • spec.replicaCount: 3
apiVersion: charts.example.com/v1alpha1
kind: Memcached
  name: memcached-sample
  # Default values copied from <project_dir>/helm-charts/memcached/values.yaml
  AntiAffinity: soft
  affinity: {}
  extraContainers: ""
  extraVolumes: ""
  image: memcached:1.5.20
  kind: StatefulSet
    extendedOptions: modern
    extraArgs: []
    maxItemMemory: 64
    verbosity: v
    enabled: false
    image: quay.io/prometheus/memcached-exporter:v0.6.0
    resources: {}
      enabled: false
      interval: 15s
  nodeSelector: {}
  pdbMinAvailable: 2
  podAnnotations: {}
  replicaCount: 3
      cpu: 50m
      memory: 64Mi
    enabled: false 
    fsGroup: 1001
    runAsUser: 1001
  serviceAnnotations: {}
  tolerations: {}
    type: RollingUpdate

You can easily update this file by running the following command:

\cp /tmp/charts_v1alpha1_memcached.yaml config/samples/charts_v1alpha1_memcached.yaml

After updating the Memcached Custom Resource with our desired spec, apply it to the cluster. Ensure you are currently scoped to the myproject Namespace:

oc project myproject

Create the Memcached Custom Resource:

oc apply -f config/samples/charts_v1alpha1_memcached.yaml

Confirm that the Custom Resource was created:

oc get memcached.charts.example.com

It may take some time for the environment to pull down the Memcached container image. Confirm that the Stateful Set was created:

oc get statefulset

Confirm that the Stateful Set’s pod is currently running:

oc get pods

Confirm that the Memcached “internal” and “public” ClusterIP Service were created:

oc get services

Let’s now update the Memcached example Custom Resource and increase the desired number of replicas to 5:

oc patch memcached.charts.example.com memcached-sample -p '{"spec":{"replicaCount": 5}}' --type=merge

Verify that the Memcached Stateful Set is creating two additional pods:

oc get pods

If any Memcached member fails it gets restarted or recreated automatically by the Kubernetes infrastructure, and will rejoin the cluster automatically when it comes back up. You can test this scenario by killing any of the pods:

oc delete pods -l app.kubernetes.io/name=memcached

Watch the pods respawn:

oc get pods -l app.kubernetes.io/name=memcached

Delete the Memcached cluster and all associated resources by deleting the example Custom Resource:

oc delete memcached.charts.example.com memcached-sample

Verify that the Stateful Set, pods, and services are removed:

oc get statefulset
oc get pods
oc get services