cmd/k8s-operator: draw more owl
Signed-off-by: Maisem Ali <maisem@tailscale.com>maisem/egress
parent
2e60c3c684
commit
731fecf3af
|
@ -9,7 +9,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -276,7 +275,7 @@ const (
|
||||||
AnnotationTags = "tailscale.com/tags"
|
AnnotationTags = "tailscale.com/tags"
|
||||||
AnnotationHostname = "tailscale.com/hostname"
|
AnnotationHostname = "tailscale.com/hostname"
|
||||||
|
|
||||||
AnnotationTarget = "tailscale.com/target"
|
AnnotationTargetIP = "tailscale.com/target-ip"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServiceReconciler is a simple ControllerManagedBy example implementation.
|
// ServiceReconciler is a simple ControllerManagedBy example implementation.
|
||||||
|
@ -329,11 +328,7 @@ func (a *ServiceReconciler) Reconcile(ctx context.Context, req reconcile.Request
|
||||||
return reconcile.Result{}, a.maybeCleanup(ctx, logger, svc)
|
return reconcile.Result{}, a.maybeCleanup(ctx, logger, svc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.hasTargetAnnotation(svc) {
|
return reconcile.Result{}, a.maybeProvision(ctx, logger, svc)
|
||||||
return reconcile.Result{}, a.maybeProvisionEgress(ctx, logger, svc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return reconcile.Result{}, a.maybeProvisionIngress(ctx, logger, svc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybeCleanup removes any existing resources related to serving svc over tailscale.
|
// maybeCleanup removes any existing resources related to serving svc over tailscale.
|
||||||
|
@ -409,16 +404,13 @@ func (a *ServiceReconciler) maybeCleanup(ctx context.Context, logger *zap.Sugare
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServiceReconciler) maybeProvisionEgress(ctx context.Context, logger *zap.SugaredLogger, svc *corev1.Service) error {
|
// TODO(maisem): XXXXXXXXXXXXXXXXXXX update docs
|
||||||
return errors.New("unimplemented")
|
// maybeProvision ensures that svc is exposed over tailscale, taking any actions
|
||||||
}
|
|
||||||
|
|
||||||
// maybeProvisionIngress ensures that svc is exposed over tailscale, taking any actions
|
|
||||||
// necessary to reach that state.
|
// necessary to reach that state.
|
||||||
//
|
//
|
||||||
// This function adds a finalizer to svc, ensuring that we can handle orderly
|
// This function adds a finalizer to svc, ensuring that we can handle orderly
|
||||||
// deprovisioning later.
|
// deprovisioning later.
|
||||||
func (a *ServiceReconciler) maybeProvisionIngress(ctx context.Context, logger *zap.SugaredLogger, svc *corev1.Service) error {
|
func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.SugaredLogger, svc *corev1.Service) error {
|
||||||
hostname, err := nameForService(svc)
|
hostname, err := nameForService(svc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -455,6 +447,19 @@ func (a *ServiceReconciler) maybeProvisionIngress(ctx context.Context, logger *z
|
||||||
return fmt.Errorf("failed to reconcile statefulset: %w", err)
|
return fmt.Errorf("failed to reconcile statefulset: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.hasTargetAnnotation(svc) {
|
||||||
|
headlessSvcName := hsvc.Name + "." + hsvc.Namespace + ".svc"
|
||||||
|
if svc.Spec.ExternalName != headlessSvcName || svc.Spec.Type != corev1.ServiceTypeExternalName {
|
||||||
|
svc.Spec.ExternalName = headlessSvcName
|
||||||
|
svc.Spec.Selector = nil
|
||||||
|
svc.Spec.Type = corev1.ServiceTypeExternalName
|
||||||
|
if err := a.Update(ctx, svc); err != nil {
|
||||||
|
return fmt.Errorf("failed to update service: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if !a.hasLoadBalancerClass(svc) {
|
if !a.hasLoadBalancerClass(svc) {
|
||||||
logger.Debugf("service is not a LoadBalancer, so not updating ingress")
|
logger.Debugf("service is not a LoadBalancer, so not updating ingress")
|
||||||
return nil
|
return nil
|
||||||
|
@ -508,7 +513,7 @@ func (a *ServiceReconciler) hasExposeAnnotation(svc *corev1.Service) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServiceReconciler) hasTargetAnnotation(svc *corev1.Service) bool {
|
func (a *ServiceReconciler) hasTargetAnnotation(svc *corev1.Service) bool {
|
||||||
return svc != nil && svc.Annotations[AnnotationTarget] != ""
|
return svc != nil && svc.Annotations[AnnotationTargetIP] != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServiceReconciler) reconcileHeadlessService(ctx context.Context, logger *zap.SugaredLogger, svc *corev1.Service) (*corev1.Service, error) {
|
func (a *ServiceReconciler) reconcileHeadlessService(ctx context.Context, logger *zap.SugaredLogger, svc *corev1.Service) (*corev1.Service, error) {
|
||||||
|
@ -626,11 +631,22 @@ func (a *ServiceReconciler) reconcileSTS(ctx context.Context, logger *zap.Sugare
|
||||||
}
|
}
|
||||||
container := &ss.Spec.Template.Spec.Containers[0]
|
container := &ss.Spec.Template.Spec.Containers[0]
|
||||||
container.Image = a.proxyImage
|
container.Image = a.proxyImage
|
||||||
|
if ip := parentSvc.Annotations[AnnotationTargetIP]; ip != "" {
|
||||||
|
container.Env = append(container.Env,
|
||||||
|
corev1.EnvVar{
|
||||||
|
Name: "TS_EGRESS_IP",
|
||||||
|
Value: ip,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
container.Env = append(container.Env,
|
container.Env = append(container.Env,
|
||||||
corev1.EnvVar{
|
corev1.EnvVar{
|
||||||
Name: "TS_DEST_IP",
|
Name: "TS_DEST_IP",
|
||||||
Value: parentSvc.Spec.ClusterIP,
|
Value: parentSvc.Spec.ClusterIP,
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
container.Env = append(container.Env,
|
||||||
corev1.EnvVar{
|
corev1.EnvVar{
|
||||||
Name: "TS_KUBE_SECRET",
|
Name: "TS_KUBE_SECRET",
|
||||||
Value: authKeySecret,
|
Value: authKeySecret,
|
||||||
|
|
Loading…
Reference in New Issue