Skip to content

Commit 2f7ee7d

Browse files
feat/fix: enhance cert-manager integration for metrics endpoints (follow-up to PR kubernetes-sigs#4243)
This commit is a follow-up to PR kubernetes-sigs#4243, which introduced support for using cert-manager certificates for securing the metrics endpoint and ServiceMonitor. Related to kubernetes-sigs#3871 and kubernetes-sigs#4003 Key enhancements: - Added support for configuring certificate integration via a Kustomize patch. - Introduced configurable flags for greater flexibility in customization. - Use Certwatcher to allow certificate rotation This configuration provides an option for users to be production-ready
1 parent d240946 commit 2f7ee7d

File tree

44 files changed

+717
-272
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+717
-272
lines changed

.github/workflows/test-e2e-samples.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242
KUSTOMIZATION_FILE_PATH="testdata/project-v4/config/default/kustomization.yaml"
4343
sed -i '25s/^#//' $KUSTOMIZATION_FILE_PATH
4444
# Uncomment all cert-manager injections
45-
sed -i '55,168s/^#//' $KUSTOMIZATION_FILE_PATH
46-
sed -i '170,185s/^#//' $KUSTOMIZATION_FILE_PATH
45+
sed -i '57,170s/^#//' $KUSTOMIZATION_FILE_PATH
46+
sed -i '172,187s/^#//' $KUSTOMIZATION_FILE_PATH
4747
cd testdata/project-v4/
4848
go mod tidy
4949
@@ -87,8 +87,8 @@ jobs:
8787
# since this sample has no defaulting webhooks
8888
sed -i '55,121s/^#//' $KUSTOMIZATION_FILE_PATH
8989
# Uncomment only --conversion webhooks CA injection
90-
sed -i '153,168s/^#//' $KUSTOMIZATION_FILE_PATH
91-
sed -i '170,185s/^#//' $KUSTOMIZATION_FILE_PATH
90+
sed -i '155,170s/^#//' $KUSTOMIZATION_FILE_PATH
91+
sed -i '172,187s/^#//' $KUSTOMIZATION_FILE_PATH
9292
cd testdata/project-v4-with-plugins/
9393
go mod tidy
9494
@@ -128,8 +128,8 @@ jobs:
128128
KUSTOMIZATION_FILE_PATH="testdata/project-v4-multigroup/config/default/kustomization.yaml"
129129
sed -i '25s/^#//' $KUSTOMIZATION_FILE_PATH
130130
# Uncomment all cert-manager injections
131-
sed -i '55,168s/^#//' $KUSTOMIZATION_FILE_PATH
132-
sed -i '170,185s/^#//' $KUSTOMIZATION_FILE_PATH
131+
sed -i '57,170s/^#//' $KUSTOMIZATION_FILE_PATH
132+
sed -i '172,187s/^#//' $KUSTOMIZATION_FILE_PATH
133133
cd testdata/project-v4-multigroup
134134
go mod tidy
135135

docs/book/src/cronjob-tutorial/testdata/project/cmd/main.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"crypto/tls"
2222
"flag"
2323
"os"
24+
"path/filepath"
2425

2526
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2627
// to ensure that exec-entrypoint and run can make use of them.
@@ -30,6 +31,7 @@ import (
3031
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3132
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3233
ctrl "sigs.k8s.io/controller-runtime"
34+
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
3335
"sigs.k8s.io/controller-runtime/pkg/healthz"
3436
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3537
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
@@ -54,8 +56,9 @@ Builtin types such as Job have their scheme added by `clientgoscheme`.
5456
*/
5557

5658
var (
57-
scheme = runtime.NewScheme()
58-
setupLog = ctrl.Log.WithName("setup")
59+
scheme = runtime.NewScheme()
60+
setupLog = ctrl.Log.WithName("setup")
61+
certWatcher *certwatcher.CertWatcher
5962
)
6063

6164
func init() {
@@ -74,6 +77,9 @@ func main() {
7477
/*
7578
*/
7679
var metricsAddr string
80+
var certDir string
81+
var certName string
82+
var certKey string
7783
var enableLeaderElection bool
7884
var probeAddr string
7985
var secureMetrics bool
@@ -87,6 +93,10 @@ func main() {
8793
"Enabling this will ensure there is only one active controller manager.")
8894
flag.BoolVar(&secureMetrics, "metrics-secure", true,
8995
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
96+
flag.StringVar(&certDir, "cert-dir", "",
97+
"The directory that contains the server key and certificate. If set, the metrics server will serve using the provided key and certificate.")
98+
flag.StringVar(&certName, "cert-name", "tls.crt", "CertName is the server certificate name. Defaults to tls.crt")
99+
flag.StringVar(&certKey, "cert-key", "tls.key", "KeyName is the server key name. Defaults to tls.key")
90100
flag.BoolVar(&enableHTTP2, "enable-http2", false,
91101
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
92102
opts := zap.Options{
@@ -133,16 +143,27 @@ func main() {
133143
// https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/metrics/filters#WithAuthenticationAndAuthorization
134144
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
135145

136-
// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
146+
// If cert-name, cert-key, and cert-name are not specified, controller-runtime will automatically
137147
// generate self-signed certificates for the metrics server. While convenient for development and testing,
138148
// this setup is not recommended for production.
139-
140-
// TODO(user): If cert-manager is enabled in config/default/kustomization.yaml,
141-
// you can uncomment the following lines to use the certificate managed by cert-manager.
142-
// metricsServerOptions.CertDir = "/tmp/k8s-metrics-server/metrics-certs"
143-
// metricsServerOptions.CertName = "tls.crt"
144-
// metricsServerOptions.KeyName = "tls.key"
145-
149+
//
150+
// TODO(user): If you are using cert-manager, enable [METRICS-WITH-CERTS] at config/default/kustomization.yaml"
151+
// to generate and use certificates managed by cert-manager for the metrics server.
152+
if len(certDir) > 0 {
153+
setupLog.Info("using certificates for the metrics server",
154+
"cert-dir", certDir, "cert-name", certName, "cert-key", certKey)
155+
156+
var err error
157+
certWatcher, err = certwatcher.New(filepath.Join(certDir, certName), filepath.Join(certDir, certKey))
158+
if err != nil {
159+
setupLog.Error(err, "to initialize certificate watcher", "error", err)
160+
os.Exit(1)
161+
}
162+
163+
metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {
164+
config.GetCertificate = certWatcher.GetCertificate
165+
})
166+
}
146167
}
147168

148169
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
@@ -196,6 +217,14 @@ func main() {
196217
}
197218
// +kubebuilder:scaffold:builder
198219

220+
if secureMetrics && certWatcher != nil {
221+
setupLog.Info("Adding certificate watcher to manager")
222+
if err := mgr.Add(certWatcher); err != nil {
223+
setupLog.Error(err, "unable to add certificate watcher to manager")
224+
os.Exit(1)
225+
}
226+
}
227+
199228
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
200229
setupLog.Error(err, "unable to set up health check")
201230
os.Exit(1)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# This patch adds the args and volumes to allow the manager to use the metrics-server certs
2+
# Ensure the volumeMounts field exists by creating it if missing
3+
- op: add
4+
path: /spec/template/spec/containers/0/volumeMounts
5+
value: []
6+
# Add the volume mount for the serving certificates
7+
- op: add
8+
path: /spec/template/spec/containers/0/volumeMounts/-
9+
value:
10+
mountPath: /tmp/k8s-metrics-server/serving-certs
11+
name: metrics-certs
12+
readOnly: true
13+
# Add the cert-dir argument
14+
- op: add
15+
path: /spec/template/spec/containers/0/args/-
16+
value: --cert-dir=/tmp/k8s-metrics-server/serving-certs
17+
# Ensure the volumes field exists by creating it if missing
18+
- op: add
19+
path: /spec/template/spec/volumes
20+
value: []
21+
# Add the volume for the serving certificates
22+
- op: add
23+
path: /spec/template/spec/volumes/-
24+
value:
25+
name: metrics-certs
26+
secret:
27+
secretName: metrics-server-cert
28+
optional: false
29+
items:
30+
- key: ca.crt
31+
path: ca.crt
32+
- key: tls.crt
33+
path: tls.crt
34+
- key: tls.key
35+
path: tls.key

docs/book/src/cronjob-tutorial/testdata/project/config/default/certmanager_metrics_manager_patch.yaml

Lines changed: 0 additions & 21 deletions
This file was deleted.

docs/book/src/cronjob-tutorial/testdata/project/config/default/kustomization.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ patches:
4242
kind: Deployment
4343

4444
# Uncomment the patches line if you enable Metrics and CertManager
45-
# [METRICS WITH CERTMANGER] To enable metrics protected with certmanager, uncomment the following line.
46-
# This patch will protect the metrics with certmanager self-signed certs.
47-
- path: certmanager_metrics_manager_patch.yaml
45+
# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.
46+
# This patch will protect the metrics with certManager self-signed certs.
47+
- path: cert_metrics_manager_patch.yaml
48+
target:
49+
kind: Deployment
4850

4951
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
5052
# crd/kustomization.yaml

docs/book/src/cronjob-tutorial/testdata/project/config/default/manager_metrics_patch.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
- op: add
33
path: /spec/template/spec/containers/0/args/0
44
value: --metrics-bind-address=:8443
5+
- op: add
6+
path: /spec/template/spec/containers/0/args/0
7+
value: --metrics-secure=true

docs/book/src/cronjob-tutorial/testdata/project/dist/install.yaml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4115,9 +4115,11 @@ spec:
41154115
spec:
41164116
containers:
41174117
- args:
4118+
- --metrics-secure=true
41184119
- --metrics-bind-address=:8443
41194120
- --leader-elect
41204121
- --health-probe-bind-address=:8081
4122+
- --cert-dir=/tmp/k8s-metrics-server/serving-certs
41214123
command:
41224124
- /manager
41234125
image: controller:latest
@@ -4154,6 +4156,9 @@ spec:
41544156
- mountPath: /tmp/k8s-webhook-server/serving-certs
41554157
name: cert
41564158
readOnly: true
4159+
- mountPath: /tmp/k8s-metrics-server/serving-certs
4160+
name: metrics-certs
4161+
readOnly: true
41574162
securityContext:
41584163
runAsNonRoot: true
41594164
seccompProfile:
@@ -4165,10 +4170,104 @@ spec:
41654170
secret:
41664171
defaultMode: 420
41674172
secretName: webhook-server-cert
4173+
- name: metrics-certs
4174+
secret:
4175+
items:
4176+
- key: ca.crt
4177+
path: ca.crt
4178+
- key: tls.crt
4179+
path: tls.crt
4180+
- key: tls.key
4181+
path: tls.key
4182+
optional: false
4183+
secretName: metrics-server-cert
4184+
---
4185+
apiVersion: cert-manager.io/v1
4186+
kind: Certificate
4187+
metadata:
4188+
labels:
4189+
app.kubernetes.io/component: certificate
4190+
app.kubernetes.io/created-by: project
4191+
app.kubernetes.io/instance: metrics-certs
4192+
app.kubernetes.io/managed-by: kustomize
4193+
app.kubernetes.io/name: certificate
4194+
app.kubernetes.io/part-of: project
4195+
name: project-metrics-certs
4196+
namespace: project-system
4197+
spec:
4198+
dnsNames:
4199+
- project-webhook-service.project-system.svc
4200+
- project-webhook-service.project-system.svc.cluster.local
4201+
issuerRef:
4202+
kind: Issuer
4203+
name: project-selfsigned-issuer
4204+
secretName: metrics-server-cert
4205+
---
4206+
apiVersion: cert-manager.io/v1
4207+
kind: Certificate
4208+
metadata:
4209+
labels:
4210+
app.kubernetes.io/component: certificate
4211+
app.kubernetes.io/created-by: project
4212+
app.kubernetes.io/instance: serving-cert
4213+
app.kubernetes.io/managed-by: kustomize
4214+
app.kubernetes.io/name: certificate
4215+
app.kubernetes.io/part-of: project
4216+
name: project-serving-cert
4217+
namespace: project-system
4218+
spec:
4219+
dnsNames:
4220+
- project-webhook-service.project-system.svc
4221+
- project-webhook-service.project-system.svc.cluster.local
4222+
issuerRef:
4223+
kind: Issuer
4224+
name: project-selfsigned-issuer
4225+
secretName: webhook-server-cert
4226+
---
4227+
apiVersion: cert-manager.io/v1
4228+
kind: Issuer
4229+
metadata:
4230+
labels:
4231+
app.kubernetes.io/managed-by: kustomize
4232+
app.kubernetes.io/name: project
4233+
name: project-selfsigned-issuer
4234+
namespace: project-system
4235+
spec:
4236+
selfSigned: {}
4237+
---
4238+
apiVersion: monitoring.coreos.com/v1
4239+
kind: ServiceMonitor
4240+
metadata:
4241+
labels:
4242+
app.kubernetes.io/managed-by: kustomize
4243+
app.kubernetes.io/name: project
4244+
control-plane: controller-manager
4245+
name: project-controller-manager-metrics-monitor
4246+
namespace: project-system
4247+
spec:
4248+
endpoints:
4249+
- tlsConfig:
4250+
ca:
4251+
secret:
4252+
key: ca.crt
4253+
name: metrics-server-cert
4254+
cert:
4255+
secret:
4256+
key: tls.crt
4257+
name: metrics-server-cert
4258+
insecureSkipVerify: false
4259+
keySecret:
4260+
key: tls.key
4261+
name: metrics-server-cert
4262+
selector:
4263+
matchLabels:
4264+
control-plane: controller-manager
41684265
---
41694266
apiVersion: admissionregistration.k8s.io/v1
41704267
kind: MutatingWebhookConfiguration
41714268
metadata:
4269+
annotations:
4270+
cert-manager.io/inject-ca-from: project-system/project-serving-cert
41724271
name: project-mutating-webhook-configuration
41734272
webhooks:
41744273
- admissionReviewVersions:
@@ -4195,6 +4294,8 @@ webhooks:
41954294
apiVersion: admissionregistration.k8s.io/v1
41964295
kind: ValidatingWebhookConfiguration
41974296
metadata:
4297+
annotations:
4298+
cert-manager.io/inject-ca-from: project-system/project-serving-cert
41984299
name: project-validating-webhook-configuration
41994300
webhooks:
42004301
- admissionReviewVersions:

docs/book/src/cronjob-tutorial/testdata/project/internal/controller/suite_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Kubebuilder scaffolded a `internal/controller/suite_test.go` file that does the
2222
First, it will contain the necessary imports.
2323
*/
2424

25-
2625
package controller
2726

2827
import (

0 commit comments

Comments
 (0)