cmd/k8s-operator,k8s-operator,kube: Add TSRecorder CRD + controller (#13299)
cmd/k8s-operator,k8s-operator,kube: Add TSRecorder CRD + controller Deploys tsrecorder images to the operator's cluster. S3 storage is configured via environment variables from a k8s Secret. Currently only supports a single tsrecorder replica, but I've tried to take early steps towards supporting multiple replicas by e.g. having a separate secret for auth and state storage. Example CR: ```yaml apiVersion: tailscale.com/v1alpha1 kind: Recorder metadata: name: rec spec: enableUI: true ``` Updates #13298 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
@ -22,6 +22,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
discoveryv1 "k8s.io/api/discovery/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/builder"
|
||||
@ -241,6 +242,8 @@ func runReconcilers(opts reconcilerOpts) {
|
||||
&appsv1.StatefulSet{}: nsFilter,
|
||||
&appsv1.Deployment{}: nsFilter,
|
||||
&discoveryv1.EndpointSlice{}: nsFilter,
|
||||
&rbacv1.Role{}: nsFilter,
|
||||
&rbacv1.RoleBinding{}: nsFilter,
|
||||
},
|
||||
},
|
||||
Scheme: tsapi.GlobalScheme,
|
||||
@ -389,6 +392,28 @@ func runReconcilers(opts reconcilerOpts) {
|
||||
if err != nil {
|
||||
startlog.Fatalf("could not create DNS records reconciler: %v", err)
|
||||
}
|
||||
|
||||
// Recorder reconciler.
|
||||
recorderFilter := handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &tsapi.Recorder{})
|
||||
err = builder.ControllerManagedBy(mgr).
|
||||
For(&tsapi.Recorder{}).
|
||||
Watches(&appsv1.StatefulSet{}, recorderFilter).
|
||||
Watches(&corev1.ServiceAccount{}, recorderFilter).
|
||||
Watches(&corev1.Secret{}, recorderFilter).
|
||||
Watches(&rbacv1.Role{}, recorderFilter).
|
||||
Watches(&rbacv1.RoleBinding{}, recorderFilter).
|
||||
Complete(&RecorderReconciler{
|
||||
recorder: eventRecorder,
|
||||
tsNamespace: opts.tailscaleNamespace,
|
||||
Client: mgr.GetClient(),
|
||||
l: opts.log.Named("recorder-reconciler"),
|
||||
clock: tstime.DefaultClock{},
|
||||
tsClient: opts.tsClient,
|
||||
})
|
||||
if err != nil {
|
||||
startlog.Fatalf("could not create Recorder reconciler: %v", err)
|
||||
}
|
||||
|
||||
startlog.Infof("Startup complete, operator running, version: %s", version.Long())
|
||||
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
|
||||
startlog.Fatalf("could not start manager: %v", err)
|
||||
@ -525,6 +550,7 @@ func dnsRecordsReconcilerIngressHandler(ns string, isDefaultLoadBalancer bool, c
|
||||
|
||||
type tsClient interface {
|
||||
CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error)
|
||||
Device(ctx context.Context, deviceID string, fields *tailscale.DeviceFieldsOpts) (*tailscale.Device, error)
|
||||
DeleteDevice(ctx context.Context, nodeStableID string) error
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user