cat-picture-operator

module
v0.0.0-...-39431f3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2018 License: MIT

README

Cat Picture Operator

A tutorial for creating a new custom resource type called a CatPicture. This will be acted upon by an operator written with the operator framework.

Requirements

  • A Go development environment
  • A working Kubernetes cluster
  • The operator-sdk installed
  • A place to store container images

Build Steps

Build the cat serving app
# In the app directory
make build
docker build -t cat-operator-app:latest
# Substitute IMAGE_REPO for the image repo of your choice
docker push [IMAGE_REPO]/cat-operator-app:latest
Create the project scaffolding
operator-sdk new operator --api-version=cat.example.com/v1 --kind=CatPicture --skip-git-init
Define the spec for the CatPicture type
// operator/pkg/apis/cat/v1/types.go
type CatPictureSpec struct {
	// The number of containers to have running in the ReplicaSet
	Num int32 `json:"num,omitempty"`
}
Update the business logic for the Handler

Rename the stub package to cats by renaming the folder and replacing the reference in cats/handler.go. Make sure to rename the references in operator/cmd/operator/main.go

Remove the newBusyBox method. We'll want to create two things: a Service and a Deployment. Create the deployment first. We'll need import Deployments from the Kubernetes client-go library.

import (
    // ... a bunch of stuff
    appsv1 "k8s.io/api/apps/v1"
)
// operator/pkg/cats/handler.go

// catContainerImage is the name of the container image
const catContainerImage = "fill-in-your-location"

// newCatDeployment creates a new deployment of the cat picture service
func newCatDeployment(cr *v1.CatPicture) *appsv1.Deployment {
	return &appsv1.Deployment{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "apps/v1",
			Kind:       "Deployment",
		},

		ObjectMeta: metav1.ObjectMeta{
			Name:      "cat-deployment",
			Namespace: cr.Namespace,
		},

		Spec: appsv1.DeploymentSpec{
			Selector: &metav1.LabelSelector{
				MatchLabels: map[string]string{
					"app": "cat-pictures",
				},
			},
			Replicas: &cr.Spec.Num,
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{
						"app": "cat-pictures",
					},
				},
				Spec: corev1.PodSpec{
					Containers: []corev1.Container{
						{
							Name:  "cat-pictures",
							Image: catContainerImage,
							Ports: []corev1.ContainerPort{
								{
									HostPort:      8080,
									ContainerPort: 8080,
								},
							},
						},
					},
				},
			},
		},
	}
}

And then the service

// operator/pkg/cats/handler.go

// newCatService creates a new service for the cat application
func newCatService(cr *v1.CatPicture) *corev1.Service {
	return &corev1.Service{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "Service",
		},
		ObjectMeta: metav1.ObjectMeta{
			Labels: map[string]string{
				"service": "cats",
			},
			Namespace: cr.Namespace,
			Name:      "cat-pictures",
		},
		Spec: corev1.ServiceSpec{
			Type: "LoadBalancer",
			Selector: map[string]string{
				"app": "cat-pictures",
			},
			Ports: []corev1.ServicePort{
				{
					Name:       "http",
					Port:       80,
					TargetPort: intstr.IntOrString{IntVal: 8080},
					Protocol:   "TCP",
				},
			},
		},
	}
}

Plug the two creation functions into the handler

type Handler struct{}

func (h *Handler) Handle(ctx context.Context, event sdk.Event) error {
	switch o := event.Object.(type) {
	case *v1.CatPicture:
		if err := sdk.Create(newCatDeployment(o)); err != nil && !errors.IsAlreadyExists(err) {
			logrus.Errorf("Failed to create cat deployment : %v", err)
			return err
		}

		if err := sdk.Create(newCatService(o)); err != nil && !errors.IsAlreadyExists(err) {
			logrus.Errorf("Failed to create cat service : %v", err)
			return err
		}
	}

	return nil
}
Build the operator
# Replace IMAGE_REPO with what's being pushed to.
# For google container images, use gcr.io/[YOUR_PROJECT_ID]

# From within the operator folder
operator-sdk build [IMAGE_REPO]/cat-picture-operator

docker push [IMAGE_REPO]/cat-picture-operator:latest
Deploy the operator
kubectl apply -f ./operator/deploy/crd.yaml
# Optional, but recommended
kubectl apply -f ./operator/deploy/rbac.yaml
# This file is generated by the build step above
kubectl apply -f ./operator/deploy/operator.yaml
Deploy the example resource
kubectl apply -f ./operator/deploy/cr.yaml
Get some cat picture

Get the cat-pictures service and copy the ExternalIP

kubectl get svc

Copy the IP into your browser and enjoy the cats

Directories

Path Synopsis
operator
pkg/apis/cat/v1
+k8s:deepcopy-gen=package +groupName=cat.example.com
+k8s:deepcopy-gen=package +groupName=cat.example.com

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL