Skip to content

Replace kube-rbac-proxy with controller-runtime's built-in TLS capabilities #437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: agent-metrics-monitor
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: agent-metrics-monitor
app.kubernetes.io/part-of: bpfman-operator
name: bpfman-agent-metrics-monitor
spec:
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
path: /metrics
port: https-metrics
scheme: https
tlsConfig:
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
insecureSkipVerify: false
serverName: bpfman-agent-metrics-service.bpfman.svc
selector:
matchLabels:
app.kubernetes.io/component: metrics
app.kubernetes.io/instance: agent-metrics-service
app.kubernetes.io/name: agent-metrics-service
24 changes: 24 additions & 0 deletions bundle/manifests/bpfman-agent-metrics-service_v1_service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.openshift.io/serving-cert-secret-name: agent-metrics-tls
creationTimestamp: null
labels:
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: agent-metrics-service
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: agent-metrics-service
app.kubernetes.io/part-of: bpfman-operator
name: bpfman-agent-metrics-service
spec:
ports:
- name: https-metrics
port: 8443
protocol: TCP
targetPort: https-metrics
selector:
name: bpfman-daemon
status:
loadBalancer: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: auth-delegator
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrolebinding
app.kubernetes.io/part-of: bpfman-operator
name: bpfman-auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: bpfman-operator
namespace: bpfman
- kind: ServiceAccount
name: bpfman-daemon
namespace: bpfman
2 changes: 1 addition & 1 deletion bundle/manifests/bpfman-config_v1_configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ data:
bpfman.agent.healthprobe.addr: :8175
bpfman.agent.image: quay.io/bpfman/bpfman-agent:latest
bpfman.agent.log.level: info
bpfman.agent.metric.addr: 127.0.0.1:8174
bpfman.agent.metric.addr: :8443
bpfman.image: quay.io/bpfman/bpfman:latest
bpfman.log.level: info
bpfman.toml: |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: controller-manager-metrics-monitor
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: servicemonitor
app.kubernetes.io/part-of: bpfman-operator
control-plane: controller-manager
name: bpfman-controller-manager-metrics-monitor
spec:
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
path: /metrics
port: https-metrics
scheme: https
tlsConfig:
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
insecureSkipVerify: false
serverName: bpfman-controller-manager-metrics-service.bpfman.svc
selector:
matchLabels:
control-plane: controller-manager
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.openshift.io/serving-cert-secret-name: controller-manager-metrics-tls
creationTimestamp: null
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: controller-manager-metrics-service
app.kubernetes.io/managed-by: kustomize
Expand All @@ -13,10 +15,10 @@ metadata:
name: bpfman-controller-manager-metrics-service
spec:
ports:
- name: https
- name: https-metrics
port: 8443
protocol: TCP
targetPort: https
targetPort: https-metrics
selector:
control-plane: controller-manager
status:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kind: ClusterRole
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: bpfman-operator
app.kubernetes.io/instance: metrics-reader
app.kubernetes.io/managed-by: kustomize
Expand Down
55 changes: 17 additions & 38 deletions bundle/manifests/bpfman-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ metadata:
capabilities: Basic Install
categories: OpenShift Optional
containerImage: quay.io/bpfman/bpfman-operator:latest
createdAt: "2025-04-30T21:37:41Z"
createdAt: "2025-05-01T12:26:00Z"
description: The bpfman Operator is designed to manage eBPF programs for applications.
features.operators.openshift.io/cnf: "false"
features.operators.openshift.io/cni: "false"
Expand Down Expand Up @@ -1507,18 +1507,6 @@ spec:
- get
- list
- watch
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
serviceAccountName: bpfman-operator
deployments:
- label:
Expand All @@ -1540,6 +1528,7 @@ spec:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
service.beta.openshift.io/serving-cert-secret-name: controller-manager-metrics-tls
labels:
control-plane: controller-manager
spec:
Expand All @@ -1560,33 +1549,11 @@ spec:
values:
- linux
containers:
- args:
- --secure-listen-address=0.0.0.0:8443
- --upstream=http://127.0.0.1:8174/
- --logtostderr=true
- --v=0
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0
name: kube-rbac-proxy
ports:
- containerPort: 8443
name: https
protocol: TCP
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 5m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
- args:
- --health-probe-bind-address=:8175
- --metrics-bind-address=127.0.0.1:8174
- --metrics-bind-address=:8443
- --leader-elect
- --cert-dir=/tmp/k8s-webhook-server/serving-certs
command:
- /bpfman-operator
env:
Expand All @@ -1601,6 +1568,10 @@ spec:
initialDelaySeconds: 15
periodSeconds: 20
name: bpfman-operator
ports:
- containerPort: 8443
name: https-metrics
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
Expand All @@ -1612,17 +1583,25 @@ spec:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
cpu: 5m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: controller-manager-metrics-tls
readOnly: true
securityContext:
runAsNonRoot: true
serviceAccountName: bpfman-operator
terminationGracePeriodSeconds: 10
volumes:
- name: controller-manager-metrics-tls
secret:
secretName: controller-manager-metrics-tls
permissions:
- rules:
- apiGroups:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: bpfman-prometheus-k8s
rules:
- apiGroups:
- ""
resources:
- pods
- services
- endpoints
- configmaps
- secrets
verbs:
- get
- list
- watch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: bpfman-prometheus-k8s
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: bpfman-prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: openshift-monitoring
55 changes: 49 additions & 6 deletions cmd/bpfman-agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"os"
"os/signal"
"path/filepath"
"sync"
"syscall"

Expand All @@ -40,9 +41,11 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
//+kubebuilder:scaffold:imports
Expand All @@ -68,12 +71,14 @@ func main() {
var opts zap.Options
var enableHTTP2, enableInterfacesDiscovery bool
var pprofAddr string
var certDir string

flag.StringVar(&metricsAddr, "metrics-bind-address", ":8174", "The address the metric endpoint binds to.")
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8443", "The address the metric endpoint binds to. Use \"0\" to disable.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8175", "The address the probe endpoint binds to.")
flag.BoolVar(&enableHTTP2, "enable-http2", enableHTTP2, "If HTTP/2 should be enabled for the metrics and webhook servers.")
flag.StringVar(&pprofAddr, "profiling-bind-address", "", "The address the profiling endpoint binds to, such as ':6060'. Leave unset to disable profiling.")
flag.BoolVar(&enableInterfacesDiscovery, "enable-interfaces-discovery", true, "Enable ebpfman agent process to auto detect interfaces creation and deletion")
flag.StringVar(&certDir, "cert-dir", "/tmp/k8s-webhook-server/serving-certs", "The directory containing TLS certificates for HTTPS servers.")

flag.Parse()

Expand Down Expand Up @@ -108,12 +113,19 @@ func main() {

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

metricsOptions := server.Options{
BindAddress: metricsAddr,
SecureServing: true,
CertDir: certDir,
TLSOpts: []func(*tls.Config){disableHTTP2},
FilterProvider: filters.WithAuthenticationAndAuthorization,
}

certWatcher := setupCertWatcher(certDir, &metricsOptions.TLSOpts)

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: server.Options{
BindAddress: metricsAddr,
TLSOpts: []func(*tls.Config){disableHTTP2},
},
Scheme: scheme,
Metrics: metricsOptions,
WebhookServer: webhook.NewServer(webhook.Options{
Port: 9443,
TLSOpts: []func(*tls.Config){disableHTTP2},
Expand All @@ -132,6 +144,15 @@ func main() {
os.Exit(1)
}

// Add the certificate watcher to the manager if it was
// created. This ensures proper certificate rotation.
if certWatcher != nil {
if err := mgr.Add(certWatcher); err != nil {
setupLog.Error(err, "unable to add certificate watcher to manager")
os.Exit(1)
}
}

// Set up a connection to bpfman, block until bpfman is up.
setupLog.Info("Waiting for active connection to bpfman")
conn, err := conn.CreateConnection(context.Background(), insecure.NewCredentials())
Expand Down Expand Up @@ -215,6 +236,28 @@ func main() {
}
}

// setupCertWatcher creates and configures a certificate watcher.
// Returns the watcher or nil if creation failed.
func setupCertWatcher(certDir string, tlsOpts *[]func(*tls.Config)) *certwatcher.CertWatcher {
certPath := filepath.Join(certDir, "tls.crt")
keyPath := filepath.Join(certDir, "tls.key")

certWatcher, err := certwatcher.New(certPath, keyPath)
if err != nil {
setupLog.Error(err, "Unable to create certificate watcher", "certPath", certPath, "keyPath", keyPath)
// Don't exit on failure - controller-runtime will
// handle certificates if the watcher fails.
return nil
}

*tlsOpts = append(*tlsOpts, func(c *tls.Config) {
c.GetCertificate = certWatcher.GetCertificate
})

setupLog.Info("Certificate watcher configured for metrics TLS", "certPath", certPath)
return certWatcher
}

func interfaceListener(ctx context.Context, ifaceEvents <-chan ifaces.Event, interfaces *sync.Map) {
for {
select {
Expand Down
Loading
Loading