Skip to content

Commit 6a674a3

Browse files
authored
Drop kube-rbac-proxy container config for metrics (#177)
1 parent abbb9e9 commit 6a674a3

34 files changed

+875
-247
lines changed

.github/workflows/test-e2e.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: E2E Tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test-e2e:
9+
name: Run on Ubuntu
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Clone the code
13+
uses: actions/checkout@v4
14+
15+
- name: Setup Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Install the latest version of kind
21+
run: |
22+
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
23+
chmod +x ./kind
24+
sudo mv ./kind /usr/local/bin/kind
25+
26+
- name: Verify kind installation
27+
run: kind version
28+
29+
- name: Create kind cluster
30+
run: kind create cluster
31+
32+
- name: Running Test e2e
33+
run: |
34+
go mod tidy
35+
make test-e2e

Makefile

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11

22
# Image URL to use all building/pushing image targets
33
IMG ?= controller:latest
4-
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
5-
ENVTEST_K8S_VERSION = 1.31.0
64

75
# Docker image name for the mkdocs based local development setup
86
IMAGE=ironcore-dev/boot-operator-docs
@@ -72,16 +70,28 @@ check-license: addlicense ## Check that every file has a license header present.
7270
find . -name '*.go' -exec $(ADDLICENSE) -check -c 'IronCore authors' {} +
7371

7472
.PHONY: test
75-
test: manifests generate fmt vet envtest ## Run tests.
73+
test: manifests generate fmt vet setup-envtest ## Run tests.
7674
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
7775

78-
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
79-
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
80-
test-e2e:
76+
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
77+
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
78+
# Prometheus and CertManager are installed by default; skip with:
79+
# - PROMETHEUS_INSTALL_SKIP=true
80+
# - CERT_MANAGER_INSTALL_SKIP=true
81+
.PHONY: test-e2e
82+
test-e2e: manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.
83+
@command -v kind >/dev/null 2>&1 || { \
84+
echo "Kind is not installed. Please install Kind manually."; \
85+
exit 1; \
86+
}
87+
@kind get clusters | grep -q 'kind' || { \
88+
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
89+
exit 1; \
90+
}
8191
go test ./test/e2e/ -v -ginkgo.v
8292

8393
.PHONY: lint
84-
lint: golangci-lint ## Run golangci-lint linter & yamllint
94+
lint: golangci-lint ## Run golangci-lint linter
8595
$(GOLANGCI_LINT) run
8696

8797
.PHONY: lint-fix
@@ -120,21 +130,17 @@ PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
120130
docker-buildx: ## Build and push docker image for the manager for cross-platform support
121131
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
122132
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
123-
- $(CONTAINER_TOOL) buildx create --name project-v3-builder
124-
$(CONTAINER_TOOL) buildx use project-v3-builder
133+
- $(CONTAINER_TOOL) buildx create --name boot-operator-builder
134+
$(CONTAINER_TOOL) buildx use boot-operator-builder
125135
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
126-
- $(CONTAINER_TOOL) buildx rm project-v3-builder
136+
- $(CONTAINER_TOOL) buildx rm boot-operator-builder
127137
rm Dockerfile.cross
128138

129139
.PHONY: build-installer
130140
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
131141
mkdir -p dist
132-
@if [ -d "config/crd" ]; then \
133-
$(KUSTOMIZE) build config/crd > dist/install.yaml; \
134-
fi
135-
echo "---" >> dist/install.yaml # Add a document separator before appending
136-
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
137-
$(KUSTOMIZE) build config/default >> dist/install.yaml
142+
cd config/manager && $(KUSTOMIZE) edit set image controller=${CONTROLLER_IMG}
143+
$(KUSTOMIZE) build config/default > dist/install.yaml
138144

139145
##@ Deployment
140146

@@ -155,6 +161,12 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in
155161
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
156162
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
157163

164+
## This e2e-deploy target is specifically used for metrics endpoint validation
165+
.PHONY: e2e-deploy
166+
e2e-deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
167+
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
168+
$(KUSTOMIZE) build config/e2e-metrics-validation | $(KUBECTL) apply -f -
169+
158170
.PHONY: undeploy
159171
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
160172
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
@@ -168,18 +180,21 @@ $(LOCALBIN):
168180

169181
## Tool Binaries
170182
KUBECTL ?= kubectl
171-
KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
172-
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
173-
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
174-
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
183+
KUSTOMIZE ?= $(LOCALBIN)/kustomize
184+
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
185+
ENVTEST ?= $(LOCALBIN)/setup-envtest
186+
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
175187
ADDLICENSE ?= $(LOCALBIN)/addlicense
176-
GOIMPORTS ?= $(LOCALBIN)/goimports-$(GOIMPORTS_VERSION)
177-
GEN_CRD_API_REFERENCE_DOCS ?= $(LOCALBIN)/gen-crd-api-reference-docs-$(GEN_CRD_API_REFERENCE_DOCS_VERSION)
188+
GOIMPORTS ?= $(LOCALBIN)/goimports
189+
GEN_CRD_API_REFERENCE_DOCS ?= $(LOCALBIN)/gen-crd-api-reference-docs
178190

179191
## Tool Versions
180-
KUSTOMIZE_VERSION ?= v5.3.0
181-
CONTROLLER_TOOLS_VERSION ?= v0.16.0
182-
ENVTEST_VERSION ?= latest
192+
KUSTOMIZE_VERSION ?= v5.5.0
193+
CONTROLLER_TOOLS_VERSION ?= v0.17.1
194+
#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20)
195+
ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}')
196+
#ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31)
197+
ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d.%d",$$3, $$2}')
183198
GOLANGCI_LINT_VERSION ?= v2.1
184199
ADDLICENSE_VERSION ?= v1.1.1
185200
GOIMPORTS_VERSION ?= v0.31.0
@@ -195,6 +210,14 @@ controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessar
195210
$(CONTROLLER_GEN): $(LOCALBIN)
196211
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))
197212

213+
.PHONY: setup-envtest
214+
setup-envtest: envtest ## Download the binaries required for ENVTEST in the local bin directory.
215+
@echo "Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)..."
216+
@$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \
217+
echo "Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION)."; \
218+
exit 1; \
219+
}
220+
198221
.PHONY: envtest
199222
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
200223
$(ENVTEST): $(LOCALBIN)
@@ -235,15 +258,17 @@ $(GEN_CRD_API_REFERENCE_DOCS): $(LOCALBIN)
235258
$(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/ahmetb/gen-crd-api-reference-docs,$(GEN_CRD_API_REFERENCE_DOCS_VERSION))
236259

237260
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
238-
# $1 - target path with name of binary (ideally with version)
261+
# $1 - target path with name of binary
239262
# $2 - package url which can be installed
240263
# $3 - specific version of package
241264
define go-install-tool
242-
@[ -f $(1) ] || { \
265+
@[ -f "$(1)-$(3)" ] || { \
243266
set -e; \
244267
package=$(2)@$(3) ;\
245268
echo "Downloading $${package}" ;\
269+
rm -f $(1) || true ;\
246270
GOBIN=$(LOCALBIN) go install $${package} ;\
247-
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
248-
}
271+
mv $(1) $(1)-$(3) ;\
272+
} ;\
273+
ln -sf $(1)-$(3) $(1)
249274
endef

cmd/main.go

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"flag"
1010
"fmt"
1111
"os"
12+
"path/filepath"
1213

1314
"github.com/ironcore-dev/controller-utils/cmdutils/switches"
1415
metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
@@ -22,10 +23,12 @@ import (
2223
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2324
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2425
ctrl "sigs.k8s.io/controller-runtime"
26+
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
2527
"sigs.k8s.io/controller-runtime/pkg/client"
2628
controllerconfig "sigs.k8s.io/controller-runtime/pkg/config"
2729
"sigs.k8s.io/controller-runtime/pkg/healthz"
2830
"sigs.k8s.io/controller-runtime/pkg/log/zap"
31+
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
2932
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
3033
"sigs.k8s.io/controller-runtime/pkg/webhook"
3134

@@ -64,6 +67,7 @@ func main() {
6467
skipControllerNameValidation := true
6568

6669
var metricsAddr string
70+
var metricsCertPath, metricsCertName, metricsCertKey string
6771
var enableLeaderElection bool
6872
var probeAddr string
6973
var secureMetrics bool
@@ -88,8 +92,10 @@ func main() {
8892
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
8993
"Enable leader election for controller manager. "+
9094
"Enabling this will ensure there is only one active controller manager.")
91-
flag.BoolVar(&secureMetrics, "metrics-secure", false,
92-
"If set the metrics endpoint is served securely")
95+
flag.StringVar(&metricsCertPath, "metrics-cert-path", "", "The directory that contains the metrics server certificate.")
96+
flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.")
97+
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
98+
flag.BoolVar(&secureMetrics, "metrics-secure", true, "If set the metrics endpoint is served securely")
9399
flag.BoolVar(&enableHTTP2, "enable-http2", false,
94100
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
95101

@@ -143,17 +149,60 @@ func main() {
143149
tlsOpts = append(tlsOpts, disableHTTP2)
144150
}
145151

152+
// Create watchers for metrics and webhooks certificates
153+
var metricsCertWatcher *certwatcher.CertWatcher
154+
146155
webhookServer := webhook.NewServer(webhook.Options{
147156
TLSOpts: tlsOpts,
148157
})
158+
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
159+
// More info:
160+
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/metrics/server
161+
// - https://book.kubebuilder.io/reference/metrics.html
162+
metricsServerOptions := metricsserver.Options{
163+
BindAddress: metricsAddr,
164+
SecureServing: secureMetrics,
165+
TLSOpts: tlsOpts,
166+
}
167+
168+
if secureMetrics {
169+
// FilterProvider is used to protect the metrics endpoint with authn/authz.
170+
// These configurations ensure that only authorized users and service accounts
171+
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
172+
// https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/metrics/filters#WithAuthenticationAndAuthorization
173+
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
174+
}
175+
176+
// If the certificate is not specified, controller-runtime will automatically
177+
// generate self-signed certificates for the metrics server. While convenient for development and testing,
178+
// this setup is not recommended for production.
179+
//
180+
// TODO(user): If you enable certManager, uncomment the following lines:
181+
// - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
182+
// managed by cert-manager for the metrics server.
183+
// - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
184+
if len(metricsCertPath) > 0 {
185+
setupLog.Info("Initializing metrics certificate watcher using provided certificates",
186+
"metrics-cert-path", metricsCertPath, "metrics-cert-name", metricsCertName, "metrics-cert-key", metricsCertKey)
187+
188+
var err error
189+
metricsCertWatcher, err = certwatcher.New(
190+
filepath.Join(metricsCertPath, metricsCertName),
191+
filepath.Join(metricsCertPath, metricsCertKey),
192+
)
193+
if err != nil {
194+
setupLog.Error(err, "to initialize metrics certificate watcher", "error", err)
195+
os.Exit(1)
196+
}
197+
198+
metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {
199+
config.GetCertificate = metricsCertWatcher.GetCertificate
200+
})
201+
}
149202

150203
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
151-
Scheme: scheme,
152-
Metrics: metricsserver.Options{
153-
BindAddress: metricsAddr,
154-
SecureServing: secureMetrics,
155-
TLSOpts: tlsOpts,
156-
},
204+
Scheme: scheme,
205+
Metrics: metricsServerOptions,
157206
WebhookServer: webhookServer,
158207
Controller: controllerconfig.Controller{
159208
SkipNameValidation: &skipControllerNameValidation,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# The following manifests contain a self-signed issuer CR and a metrics certificate CR.
2+
# More document can be found at https://docs.cert-manager.io
3+
apiVersion: cert-manager.io/v1
4+
kind: Certificate
5+
metadata:
6+
labels:
7+
app.kubernetes.io/name: boot-operator
8+
app.kubernetes.io/managed-by: kustomize
9+
name: metrics-certs # this name should match the one appeared in kustomizeconfig.yaml
10+
namespace: system
11+
spec:
12+
dnsNames:
13+
# SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
14+
# replacements in the config/default/kustomization.yaml file.
15+
- SERVICE_NAME.SERVICE_NAMESPACE.svc
16+
- SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local
17+
issuerRef:
18+
kind: Issuer
19+
name: selfsigned-issuer
20+
secretName: metrics-server-cert

config/certmanager/issuer.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# The following manifests contain a self-signed issuer CR and a certificate CR.
2+
# More document can be found at https://docs.cert-manager.io
3+
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
4+
apiVersion: cert-manager.io/v1
5+
kind: Issuer
6+
metadata:
7+
labels:
8+
app.kubernetes.io/name: boot-operator
9+
app.kubernetes.io/managed-by: kustomize
10+
name: selfsigned-issuer
11+
namespace: system
12+
spec:
13+
selfSigned: {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resources:
2+
- issuer.yaml
3+
- certificate-metrics.yaml
4+
5+
configurations:
6+
- kustomizeconfig.yaml
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# This configuration is for teaching kustomize how to update name ref substitution
2+
nameReference:
3+
- kind: Issuer
4+
group: cert-manager.io
5+
fieldSpecs:
6+
- kind: Certificate
7+
group: cert-manager.io
8+
path: spec/issuerRef/name

config/crd/bases/boot.ironcore.dev_httpbootconfigs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.16.0
6+
controller-gen.kubebuilder.io/version: v0.17.1
77
name: httpbootconfigs.boot.ironcore.dev
88
spec:
99
group: boot.ironcore.dev

config/crd/bases/boot.ironcore.dev_ipxebootconfigs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.16.0
6+
controller-gen.kubebuilder.io/version: v0.17.1
77
name: ipxebootconfigs.boot.ironcore.dev
88
spec:
99
group: boot.ironcore.dev
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs.
2+
3+
# Add the volumeMount for the metrics-server certs
4+
- op: add
5+
path: /spec/template/spec/containers/0/volumeMounts/-
6+
value:
7+
mountPath: /tmp/k8s-metrics-server/metrics-certs
8+
name: metrics-certs
9+
readOnly: true
10+
11+
# Add the --metrics-cert-path argument for the metrics server
12+
- op: add
13+
path: /spec/template/spec/containers/0/args/-
14+
value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs
15+
16+
# Add the metrics-server certs volume configuration
17+
- op: add
18+
path: /spec/template/spec/volumes/-
19+
value:
20+
name: metrics-certs
21+
secret:
22+
secretName: metrics-server-cert
23+
optional: false
24+
items:
25+
- key: ca.crt
26+
path: ca.crt
27+
- key: tls.crt
28+
path: tls.crt
29+
- key: tls.key
30+
path: tls.key

0 commit comments

Comments
 (0)