mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-22 21:08:38 +00:00
cmd/k8s-operator: support being the default loadbalancer controller
Updates #502 Signed-off-by: Mike Beaumont <mjboamail@gmail.com>
This commit is contained in:
parent
4af22f3785
commit
ce4bf41dcf
@ -183,6 +183,9 @@ waitOnline:
|
|||||||
// startReconcilers starts the controller-runtime manager and registers the
|
// startReconcilers starts the controller-runtime manager and registers the
|
||||||
// ServiceReconciler.
|
// ServiceReconciler.
|
||||||
func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *rest.Config, tsClient *tailscale.Client, image, priorityClassName, tags string) {
|
func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *rest.Config, tsClient *tailscale.Client, image, priorityClassName, tags string) {
|
||||||
|
var (
|
||||||
|
isDefaultLoadBalancer = defaultBool("OPERATOR_DEFAULT_LOAD_BALANCER", false)
|
||||||
|
)
|
||||||
startlog := zlog.Named("startReconcilers")
|
startlog := zlog.Named("startReconcilers")
|
||||||
// For secrets and statefulsets, we only get permission to touch the objects
|
// For secrets and statefulsets, we only get permission to touch the objects
|
||||||
// in the controller's own namespace. This cannot be expressed by
|
// in the controller's own namespace. This cannot be expressed by
|
||||||
@ -234,9 +237,10 @@ func startReconcilers(zlog *zap.SugaredLogger, tsNamespace string, restConfig *r
|
|||||||
Watches(&appsv1.StatefulSet{}, reconcileFilter).
|
Watches(&appsv1.StatefulSet{}, reconcileFilter).
|
||||||
Watches(&corev1.Secret{}, reconcileFilter).
|
Watches(&corev1.Secret{}, reconcileFilter).
|
||||||
Complete(&ServiceReconciler{
|
Complete(&ServiceReconciler{
|
||||||
ssr: ssr,
|
ssr: ssr,
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
logger: zlog.Named("service-reconciler"),
|
logger: zlog.Named("service-reconciler"),
|
||||||
|
isDefaultLoadBalancer: isDefaultLoadBalancer,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
startlog.Fatalf("could not create controller: %v", err)
|
startlog.Fatalf("could not create controller: %v", err)
|
||||||
|
@ -650,6 +650,52 @@ func TestCustomPriorityClassName(t *testing.T) {
|
|||||||
expectEqual(t, fc, expectedSTS(shortName, fullName, "custom-priority-class-name", "tailscale-critical"))
|
expectEqual(t, fc, expectedSTS(shortName, fullName, "custom-priority-class-name", "tailscale-critical"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDefaultLoadBalancer(t *testing.T) {
|
||||||
|
fc := fake.NewFakeClient()
|
||||||
|
ft := &fakeTSClient{}
|
||||||
|
zl, err := zap.NewDevelopment()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
sr := &ServiceReconciler{
|
||||||
|
Client: fc,
|
||||||
|
ssr: &tailscaleSTSReconciler{
|
||||||
|
Client: fc,
|
||||||
|
tsClient: ft,
|
||||||
|
defaultTags: []string{"tag:k8s"},
|
||||||
|
operatorNamespace: "operator-ns",
|
||||||
|
proxyImage: "tailscale/tailscale",
|
||||||
|
},
|
||||||
|
logger: zl.Sugar(),
|
||||||
|
isDefaultLoadBalancer: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a service that we should manage, and check that the initial round
|
||||||
|
// of objects looks right.
|
||||||
|
mustCreate(t, fc, &corev1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
Namespace: "default",
|
||||||
|
// The apiserver is supposed to set the UID, but the fake client
|
||||||
|
// doesn't. So, set it explicitly because other code later depends
|
||||||
|
// on it being set.
|
||||||
|
UID: types.UID("1234-UID"),
|
||||||
|
},
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
ClusterIP: "10.20.30.40",
|
||||||
|
Type: corev1.ServiceTypeLoadBalancer,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expectReconciled(t, sr, "default", "test")
|
||||||
|
|
||||||
|
fullName, shortName := findGenName(t, fc, "default", "test")
|
||||||
|
|
||||||
|
expectEqual(t, fc, expectedSecret(fullName))
|
||||||
|
expectEqual(t, fc, expectedHeadlessService(shortName))
|
||||||
|
expectEqual(t, fc, expectedSTS(shortName, fullName, "default-test", ""))
|
||||||
|
}
|
||||||
|
|
||||||
func expectedSecret(name string) *corev1.Secret {
|
func expectedSecret(name string) *corev1.Secret {
|
||||||
return &corev1.Secret{
|
return &corev1.Secret{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
@ -780,6 +826,9 @@ func findGenName(t *testing.T, client client.Client, ns, name string) (full, noS
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("finding secret for %q: %v", name, err)
|
t.Fatalf("finding secret for %q: %v", name, err)
|
||||||
}
|
}
|
||||||
|
if s == nil {
|
||||||
|
t.Fatalf("no secret found for %q", name)
|
||||||
|
}
|
||||||
return s.GetName(), strings.TrimSuffix(s.GetName(), "-0")
|
return s.GetName(), strings.TrimSuffix(s.GetName(), "-0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,9 @@ import (
|
|||||||
|
|
||||||
type ServiceReconciler struct {
|
type ServiceReconciler struct {
|
||||||
client.Client
|
client.Client
|
||||||
ssr *tailscaleSTSReconciler
|
ssr *tailscaleSTSReconciler
|
||||||
logger *zap.SugaredLogger
|
logger *zap.SugaredLogger
|
||||||
|
isDefaultLoadBalancer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func childResourceLabels(name, ns, typ string) map[string]string {
|
func childResourceLabels(name, ns, typ string) map[string]string {
|
||||||
@ -177,8 +178,8 @@ func (a *ServiceReconciler) shouldExpose(svc *corev1.Service) bool {
|
|||||||
func (a *ServiceReconciler) hasLoadBalancerClass(svc *corev1.Service) bool {
|
func (a *ServiceReconciler) hasLoadBalancerClass(svc *corev1.Service) bool {
|
||||||
return svc != nil &&
|
return svc != nil &&
|
||||||
svc.Spec.Type == corev1.ServiceTypeLoadBalancer &&
|
svc.Spec.Type == corev1.ServiceTypeLoadBalancer &&
|
||||||
svc.Spec.LoadBalancerClass != nil &&
|
(svc.Spec.LoadBalancerClass != nil && *svc.Spec.LoadBalancerClass == "tailscale" ||
|
||||||
*svc.Spec.LoadBalancerClass == "tailscale"
|
svc.Spec.LoadBalancerClass == nil && a.isDefaultLoadBalancer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServiceReconciler) hasAnnotation(svc *corev1.Service) bool {
|
func (a *ServiceReconciler) hasAnnotation(svc *corev1.Service) bool {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user