Skip to content

Commit

Permalink
feat: kubebuilder 4.2.0 upgrade (#50)
Browse files Browse the repository at this point in the history
* feat: update operator-v1

* feat: update operator-v2

* chore: nit

* feat: update operator-v2-with-tests

* chore: update tests

* docs: small update to contributing docs

* docs: update main README

* ci: bump to go 1.22

* fix: lint
  • Loading branch information
leovct authored Oct 20, 2024
1 parent 2e78e34 commit 6ea91c5
Show file tree
Hide file tree
Showing 84 changed files with 1,185 additions and 640 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ concurrency:
cancel-in-progress: true

env:
GO_VERSION: "1.21"
GO_VERSION: "1.22"

jobs:
prep-matrix:
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🛠️ Build a Kubernetes Operator in 10 minutes

> **👋 The source code has been updated in May 2024 to use the latest version of kubebuilder ([v3.15.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v3.15.0)). Expect the code to be kept up to date with the latest kubebuilder releases!**
> **👋 The source code has been updated in October 2024 to use the latest version of kubebuilder ([v4.2.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.2.0)). Expect the code to be kept up to date with the latest kubebuilder releases!**
## Table of Contents

Expand Down Expand Up @@ -336,9 +336,10 @@ Note: this is an example with `operator-v1`. Repeat the same steps for all the o
./scripts/bump.sh operator-v2
./scripts/bump.sh operator-v2-with-tests


# 2) Test that the new version works.
# 2) Test that the new version works (for each folder: operator-v1, operator-v2 and operator-v2-with-tests).
# Note: for this step, you will need a running Kubernetes cluster.
make test

kind create cluster
kubectl cluster-info --context kind-kind
kubectl get nodes
Expand Down
7 changes: 7 additions & 0 deletions operator-v1/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ linters:
- dupl
- errcheck
- exportloopref
- ginkgolinter
- goconst
- gocyclo
- gofmt
Expand All @@ -33,8 +34,14 @@ linters:
- misspell
- nakedret
- prealloc
- revive
- staticcheck
- typecheck
- unconvert
- unparam
- unused

linters-settings:
revive:
rules:
- name: comment-spacings
2 changes: 1 addition & 1 deletion operator-v1/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.21 AS builder
FROM golang:1.22 AS builder
ARG TARGETOS
ARG TARGETARCH

Expand Down
38 changes: 20 additions & 18 deletions operator-v1/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.29.0
ENVTEST_K8S_VERSION = 1.31.0

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand Down Expand Up @@ -69,7 +69,7 @@ test-e2e:
go test ./test/e2e/ -v -ginkgo.v

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter & yamllint
lint: golangci-lint ## Run golangci-lint linter
$(GOLANGCI_LINT) run

.PHONY: lint-fix
Expand Down Expand Up @@ -108,10 +108,10 @@ PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name project-v3-builder
$(CONTAINER_TOOL) buildx use project-v3-builder
- $(CONTAINER_TOOL) buildx create --name operator-v1-builder
$(CONTAINER_TOOL) buildx use operator-v1-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm project-v3-builder
- $(CONTAINER_TOOL) buildx rm operator-v1-builder
rm Dockerfile.cross

.PHONY: build-installer
Expand Down Expand Up @@ -152,16 +152,16 @@ $(LOCALBIN):

## Tool Binaries
KUBECTL ?= kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint

## Tool Versions
KUSTOMIZE_VERSION ?= v5.3.0
CONTROLLER_TOOLS_VERSION ?= v0.14.0
ENVTEST_VERSION ?= release-0.17
GOLANGCI_LINT_VERSION ?= v1.57.2
KUSTOMIZE_VERSION ?= v5.4.3
CONTROLLER_TOOLS_VERSION ?= v0.16.1
ENVTEST_VERSION ?= release-0.19
GOLANGCI_LINT_VERSION ?= v1.59.1

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
Expand All @@ -181,18 +181,20 @@ $(ENVTEST): $(LOCALBIN)
.PHONY: golangci-lint
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary (ideally with version)
# $1 - target path with name of binary
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f $(1) ] || { \
@[ -f "$(1)-$(3)" ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
rm -f $(1) || true ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
}
mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef
2 changes: 1 addition & 1 deletion operator-v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
## Getting Started

### Prerequisites
- go version v1.21.0+
- go version v1.22.0+
- docker version 17.03+.
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
Expand Down
6 changes: 3 additions & 3 deletions operator-v1/api/v1/foo_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ type FooStatus struct {
Happy bool `json:"happy,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// Foo is the Schema for the foos API
type Foo struct {
Expand All @@ -45,7 +45,7 @@ type Foo struct {
Status FooStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// FooList contains a list of Foo
type FooList struct {
Expand Down
48 changes: 35 additions & 13 deletions operator-v1/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"

tutorialv1 "my.domain/tutorial/api/v1"
"my.domain/tutorial/internal/controller"
//+kubebuilder:scaffold:imports
// +kubebuilder:scaffold:imports
)

var (
Expand All @@ -48,7 +49,7 @@ func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

utilruntime.Must(tutorialv1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
// +kubebuilder:scaffold:scheme
}

func main() {
Expand All @@ -57,13 +58,15 @@ func main() {
var probeAddr string
var secureMetrics bool
var enableHTTP2 bool
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
var tlsOpts []func(*tls.Config)
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&secureMetrics, "metrics-secure", false,
"If set the metrics endpoint is served securely")
flag.BoolVar(&secureMetrics, "metrics-secure", true,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
opts := zap.Options{
Expand All @@ -85,7 +88,6 @@ func main() {
c.NextProtos = []string{"http/1.1"}
}

tlsOpts := []func(*tls.Config){}
if !enableHTTP2 {
tlsOpts = append(tlsOpts, disableHTTP2)
}
Expand All @@ -94,13 +96,33 @@ func main() {
TLSOpts: tlsOpts,
})

// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
// More info:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/server
// - https://book.kubebuilder.io/reference/metrics.html
metricsServerOptions := metricsserver.Options{
BindAddress: metricsAddr,
SecureServing: secureMetrics,
// TODO(user): TLSOpts is used to allow configuring the TLS config used for the server. If certificates are
// not provided, self-signed certificates will be generated by default. This option is not recommended for
// production environments as self-signed certificates do not offer the same level of trust and security
// as certificates issued by a trusted Certificate Authority (CA). The primary risk is potentially allowing
// unauthorized access to sensitive metrics data. Consider replacing with CertDir, CertName, and KeyName
// to provide certificates, ensuring the server communicates using trusted and secure certificates.
TLSOpts: tlsOpts,
}

if secureMetrics {
// FilterProvider is used to protect the metrics endpoint with authn/authz.
// These configurations ensure that only authorized users and service accounts
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/filters#WithAuthenticationAndAuthorization
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{
BindAddress: metricsAddr,
SecureServing: secureMetrics,
TLSOpts: tlsOpts,
},
Scheme: scheme,
Metrics: metricsServerOptions,
WebhookServer: webhookServer,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
Expand Down Expand Up @@ -129,7 +151,7 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "Foo")
os.Exit(1)
}
//+kubebuilder:scaffold:builder
// +kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
Expand Down
2 changes: 1 addition & 1 deletion operator-v1/config/crd/bases/tutorial.my.domain_foos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.16.1
name: foos.tutorial.my.domain
spec:
group: tutorial.my.domain
Expand Down
6 changes: 3 additions & 3 deletions operator-v1/config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
# It should be run by config/default
resources:
- bases/tutorial.my.domain_foos.yaml
#+kubebuilder:scaffold:crdkustomizeresource
# +kubebuilder:scaffold:crdkustomizeresource

patches:
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
#+kubebuilder:scaffold:crdkustomizewebhookpatch
# +kubebuilder:scaffold:crdkustomizewebhookpatch

# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
# patches here are for enabling the CA injection for each CRD
#- path: patches/cainjection_in_foos.yaml
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
# +kubebuilder:scaffold:crdkustomizecainjectionpatch

# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
Expand Down
15 changes: 12 additions & 3 deletions operator-v1/config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,21 @@ resources:
#- ../certmanager
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
#- ../prometheus
# [METRICS] Expose the controller manager metrics service.
- metrics_service.yaml
# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.
# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.
# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will
# be able to communicate with the Webhook Server.
#- ../network-policy

# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
patches:
# [METRICS] The following patch will enable the metrics endpoint. Ensure that you also protect this endpoint.
# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.
# More info: https://book.kubebuilder.io/reference/metrics
# If you want to expose the metric endpoint of your controller-manager uncomment the following line.
#- path: manager_metrics_patch.yaml
- path: manager_metrics_patch.yaml
target:
kind: Deployment

# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
Expand Down
10 changes: 0 additions & 10 deletions operator-v1/config/default/manager_config_patch.yaml

This file was deleted.

17 changes: 4 additions & 13 deletions operator-v1/config/default/manager_metrics_patch.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
# This patch adds the args to allow exposing the metrics endpoint securely
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
args:
- "--metrics-bind-address=0.0.0.0:8080"
# This patch adds the args to allow exposing the metrics endpoint using HTTPS
- op: add
path: /spec/template/spec/containers/0/args/0
value: --metrics-bind-address=:8443
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ metadata:
namespace: system
spec:
ports:
- name: http
port: 8080
- name: https
port: 8443
protocol: TCP
targetPort: 8080
targetPort: 8443
selector:
control-plane: controller-manager
1 change: 0 additions & 1 deletion operator-v1/config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ spec:
args:
- --leader-elect
- --health-probe-bind-address=:8081
- --metrics-bind-address=0
image: controller:latest
name: manager
securityContext:
Expand Down
Loading

0 comments on commit 6ea91c5

Please sign in to comment.