Skip to content

Instantly share code, notes, and snippets.

@eggsbenjamin
Created April 24, 2021 14:08
Show Gist options
  • Save eggsbenjamin/d1837e0b0dd707ea398574cb8a1ec65a to your computer and use it in GitHub Desktop.
Save eggsbenjamin/d1837e0b0dd707ea398574cb8a1ec65a to your computer and use it in GitHub Desktop.
Minimal Kubebuilder Local Setup
.PHONY: kubebuilder
# Directory to store local binaries in - can be overridden where necessary
BIN_PATH ?= $(CURDIR)/bin
SHELL := /bin/bash
# Ensure binaries in bin are used
PATH := $(BIN_PATH):$(BIN_PATH)/bin:$(PATH)
export PATH
OS := $(shell go env GOOS)
ARCH := $(shell go env GOARCH)
KUBEBUILDER_VERSION := 2.3.1
KUBEBUILDER_URL := https://go.kubebuilder.io/dl/$(KUBEBUILDER_VERSION)/$(OS)/$(ARCH)
KUBEBUILDER_DIR := kubebuilder
KUBEBUILDER_RESOURCE_GROUP := webapp
KUBEBUILDER_RESOURCE_VERSION := v1
KUBEBUILDER_RESOURCES := Guestbook Eagle # resource names must begin with a capital letter
KUBEBUILDER_CONTROLLERS := $(foreach resource, $(KUBEBUILDER_RESOURCES), $(KUBEBUILDER_DIR)/controllers/$(shell echo $(resource) | tr '[:upper:]' '[:lower:]')_controller.go)
KUBEBUILDER_CONTROLLER_IMG := controller:test
KUBEBUILDER_NAMESPACE ?= kubebuilder-system
KUBEBUILDER_NAME_PREFIX ?= kubebuilder-
KUBEBUILDER_INITIALISED_FILE = $(CURDIR)/.KUBEBUILDER_INITIALISED
KIND_URL := sigs.k8s.io/kind
KIND_VERSION := v0.8.1
KIND_KUBERNETES_VERSION := v1.12.10
KIND_CLUSTER_NAME := kubebuilder-test
KIND_CONTEXT := kind-$(KIND_CLUSTER_NAME)
KIND_CLUSTER_FILE = $(CURDIR)/.KIND_CLUSTER
KUBERNETES_LOCAL_CONTEXT ?= $(KIND_CONTEXT)
KUBECTL_VERSION := v1.13.10
KUBECTL_URL := https://dl.k8s.io/$(KUBECTL_VERSION)/kubernetes-client-$(OS)-$(ARCH).tar.gz
# Source based on OS
ifeq ($(OS),linux)
SHASUM := sha256sum -c
endif
ifeq ($(OS),darwin)
SHASUM := shasum -a 256 -c
endif
all: kubebuilder_run_local_kind ## build all resources defined in KUBEBUILDER_RESOURCES and deploy to kind cluster
clean: kind_delete_cluster ## removes all artifacts produced via this makefile *use with caution*
ifneq (,$(wildcard $(BIN_PATH)))
rm -rf $(BIN_PATH)
endif
ifneq (,$(wildcard $(KUBEBUILDER_DIR)))
rm -rf $(KUBEBUILDER_DIR)
endif
ifneq (,$(wildcard $(KUBEBUILDER_INITIALISED_FILE)))
rm $(KUBEBUILDER_INITIALISED_FILE)
endif
# from https://suva.sh/posts/well-documented-makefiles/
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-30s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
deps: $(BIN_PATH) $(BIN_PATH)/kubebuilder $(BIN_PATH)/kubectl $(BIN_PATH)/kind ## install deps
kubebuilder: kubebuilder_init $(KUBEBUILDER_CONTROLLERS) ## scaffold minimal kubebuilder project with controllers defined in KUBEBUILDER_CONTROLLERS
$(KUBEBUILDER_DIR)/go.mod:
mkdir -p $(KUBEBUILDER_DIR)
cd $(KUBEBUILDER_DIR) && go mod init kubebuilder
kubebuilder_init: deps $(KUBEBUILDER_DIR)/go.mod ## scaffold kubebuilder project and remove cruft
mkdir -p $(KUBEBUILDER_DIR)
ifeq (,$(wildcard $(KUBEBUILDER_INITIALISED_FILE)))
cd $(KUBEBUILDER_DIR) && kubebuilder init --domain my.domain
# remove unwanted generated files and cruft.
rm -rf $(KUBEBUILDER_DIR)/config/{certmanager,prometheus,webhook}
rm $(KUBEBUILDER_DIR)/config/default/*patch.yaml
rm $(KUBEBUILDER_DIR)/config/rbac/auth_proxy*.yaml
echo -e \
namespace: kubebuilder-system\\n\
namePrefix: kubebuilder-\\n\
bases:\\n\
- ../crd\\n\
- ../rbac\\n\
- ../manager\\n > $(KUBEBUILDER_DIR)/config/default/kustomization.yaml
head -n 5 $(KUBEBUILDER_DIR)/config/rbac/kustomization.yaml > $(KUBEBUILDER_DIR)/config/rbac/kustomization.yaml
touch $(KUBEBUILDER_INITIALISED_FILE)
else
echo "kubebuilder pre-initialised..."
endif
# define template for controller target
define make-controller-target
$(KUBEBUILDER_DIR)/controllers/$(shell echo $1 | tr '[:upper:]' '[:lower:]')_controller.go: kubebuilder_init
if [ ! -f $(KUBEBUILDER_DIR)/controllers/$(shell echo $1 | tr '[:upper:]' '[:lower:]')_controller.go ]; then \
cd $(KUBEBUILDER_DIR) && kubebuilder create api --group $(KUBEBUILDER_RESOURCE_GROUP) --version $(KUBEBUILDER_RESOURCE_VERSION) --kind $1 --resource --controller ; \
fi
endef
# dynamically generate controller targets for each resource
$(foreach resource,$(KUBEBUILDER_RESOURCES),$(eval $(call make-controller-target,$(resource))))
kubebuilder_run_local: kubebuilder ## run kubebuilder controller manager against local cluster defined in KUBERNETES_LOCAL_CONTEXT. Defaults to kind cluster.
kubectl config use-context $(KUBERNETES_LOCAL_CONTEXT)
make -C kubebuilder
make -C kubebuilder install
make -C kubebuilder run
kubebuilder_run_local_kind: kubebuilder kind_create_cluster ## create and run controller manager against local kind cluster. Cluster created if not pre-existing
kubectl config use-context $(KIND_CONTEXT)
make -C kubebuilder
make -C kubebuilder install
make -C kubebuilder docker-build IMG=$(KUBEBUILDER_CONTROLLER_IMG)
kind load docker-image $(KUBEBUILDER_CONTROLLER_IMG) --name $(KIND_CLUSTER_NAME)
make -C kubebuilder deploy IMG=$(KUBEBUILDER_CONTROLLER_IMG)
kind_create_cluster: ## creates a local kind cluster with name KIND_CLUSTER_NAME
ifeq (,$(wildcard $(KIND_CLUSTER_FILE)))
kind create cluster --image=kindest/node:$(KIND_KUBERNETES_VERSION) --name=$(KIND_CLUSTER_NAME)
echo $(KIND_CONTEXT) > $(KIND_CLUSTER_FILE)
else
echo "pre-existing kind cluster $(KIND_CLUSTER_NAME)"
endif
kind_delete_cluster: ## deletes local kind cluster with name KIND_CLUSTER_NAME
ifneq (,$(wildcard $(KIND_CLUSTER_FILE)))
kind delete cluster --name $(KIND_CLUSTER_NAME)
rm $(KIND_CLUSTER_FILE)
else
echo "kind cluster $(KIND_CLUSTER_NAME) does not exist"
endif
# Dependencies
$(BIN_PATH):
mkdir -p $(BIN_PATH)
$(BIN_PATH)/kubebuilder:
curl --fail -sL $(KUBEBUILDER_URL) | tar -xz -C $(BIN_PATH)
mv $(BIN_PATH)/kubebuilder_$(KUBEBUILDER_VERSION)_$(OS)_$(ARCH)/bin/{kubebuilder,etcd,kube-apiserver} $(BIN_PATH)
rm -rf $(BIN_PATH)/kubebuilder_$(KUBEBUILDER_VERSION)_$(OS)_$(ARCH)
$(BIN_PATH)/kind:
GOBIN=$(BIN_PATH) GO111MODULE=on go get $(KIND_URL)@$(KIND_VERSION)
$(BIN_PATH)/kubectl:
curl --fail -sL $(KUBECTL_URL) | tar -xz -C $(BIN_PATH)
mv $(BIN_PATH)/kubernetes/client/bin/kubectl $(BIN_PATH)
rm -rf $(BIN_PATH)/kubernetes
@eggsbenjamin
Copy link
Author

Dependencies

Usage

  • Run make help for available targets
  • Run make to scaffold a local kubebuilder project and deploy to a local kind cluster (idempotent).
  • Append resources names to the KUBEBUILDER_RESOURCES variable and then run make to scaffold and deploy them to the local kind cluster.
  • Run make after making changes to controller source code to update deployed controller
  • Run make clean (idempotent) to remove all artifacts created from running make.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment