mirror of
https://github.com/tailscale/tailscale.git
synced 2025-07-18 19:48:38 +00:00
cmd/k8s-operator: Set login server on tsrecorder nodes (#16443)
This commit modifies the recorder node reconciler to include the environment variable added in https://github.com/tailscale/corp/pull/30058 which allows for configuration of the coordination server. Updates https://github.com/tailscale/corp/issues/29847 Signed-off-by: David Bond <davidsbond93@gmail.com>
This commit is contained in:
parent
3a4b439c62
commit
5dc11d50f7
@ -82,6 +82,7 @@ func main() {
|
|||||||
tsFirewallMode = defaultEnv("PROXY_FIREWALL_MODE", "")
|
tsFirewallMode = defaultEnv("PROXY_FIREWALL_MODE", "")
|
||||||
defaultProxyClass = defaultEnv("PROXY_DEFAULT_CLASS", "")
|
defaultProxyClass = defaultEnv("PROXY_DEFAULT_CLASS", "")
|
||||||
isDefaultLoadBalancer = defaultBool("OPERATOR_DEFAULT_LOAD_BALANCER", false)
|
isDefaultLoadBalancer = defaultBool("OPERATOR_DEFAULT_LOAD_BALANCER", false)
|
||||||
|
loginServer = strings.TrimSuffix(defaultEnv("OPERATOR_LOGIN_SERVER", ""), "/")
|
||||||
)
|
)
|
||||||
|
|
||||||
var opts []kzap.Opts
|
var opts []kzap.Opts
|
||||||
@ -115,7 +116,7 @@ func main() {
|
|||||||
hostinfo.SetApp(kubetypes.AppAPIServerProxy)
|
hostinfo.SetApp(kubetypes.AppAPIServerProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, tsc := initTSNet(zlog)
|
s, tsc := initTSNet(zlog, loginServer)
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
restConfig := config.GetConfigOrDie()
|
restConfig := config.GetConfigOrDie()
|
||||||
apiproxy.MaybeLaunchAPIServerProxy(zlog, restConfig, s, mode)
|
apiproxy.MaybeLaunchAPIServerProxy(zlog, restConfig, s, mode)
|
||||||
@ -131,6 +132,7 @@ func main() {
|
|||||||
proxyTags: tags,
|
proxyTags: tags,
|
||||||
proxyFirewallMode: tsFirewallMode,
|
proxyFirewallMode: tsFirewallMode,
|
||||||
defaultProxyClass: defaultProxyClass,
|
defaultProxyClass: defaultProxyClass,
|
||||||
|
loginServer: loginServer,
|
||||||
}
|
}
|
||||||
runReconcilers(rOpts)
|
runReconcilers(rOpts)
|
||||||
}
|
}
|
||||||
@ -138,14 +140,13 @@ func main() {
|
|||||||
// initTSNet initializes the tsnet.Server and logs in to Tailscale. It uses the
|
// initTSNet initializes the tsnet.Server and logs in to Tailscale. It uses the
|
||||||
// CLIENT_ID_FILE and CLIENT_SECRET_FILE environment variables to authenticate
|
// CLIENT_ID_FILE and CLIENT_SECRET_FILE environment variables to authenticate
|
||||||
// with Tailscale.
|
// with Tailscale.
|
||||||
func initTSNet(zlog *zap.SugaredLogger) (*tsnet.Server, tsClient) {
|
func initTSNet(zlog *zap.SugaredLogger, loginServer string) (*tsnet.Server, tsClient) {
|
||||||
var (
|
var (
|
||||||
clientIDPath = defaultEnv("CLIENT_ID_FILE", "")
|
clientIDPath = defaultEnv("CLIENT_ID_FILE", "")
|
||||||
clientSecretPath = defaultEnv("CLIENT_SECRET_FILE", "")
|
clientSecretPath = defaultEnv("CLIENT_SECRET_FILE", "")
|
||||||
hostname = defaultEnv("OPERATOR_HOSTNAME", "tailscale-operator")
|
hostname = defaultEnv("OPERATOR_HOSTNAME", "tailscale-operator")
|
||||||
kubeSecret = defaultEnv("OPERATOR_SECRET", "")
|
kubeSecret = defaultEnv("OPERATOR_SECRET", "")
|
||||||
operatorTags = defaultEnv("OPERATOR_INITIAL_TAGS", "tag:k8s-operator")
|
operatorTags = defaultEnv("OPERATOR_INITIAL_TAGS", "tag:k8s-operator")
|
||||||
loginServer = strings.TrimSuffix(defaultEnv("OPERATOR_LOGIN_SERVER", ""), "/")
|
|
||||||
)
|
)
|
||||||
startlog := zlog.Named("startup")
|
startlog := zlog.Named("startup")
|
||||||
if clientIDPath == "" || clientSecretPath == "" {
|
if clientIDPath == "" || clientSecretPath == "" {
|
||||||
@ -610,6 +611,7 @@ func runReconcilers(opts reconcilerOpts) {
|
|||||||
l: opts.log.Named("recorder-reconciler"),
|
l: opts.log.Named("recorder-reconciler"),
|
||||||
clock: tstime.DefaultClock{},
|
clock: tstime.DefaultClock{},
|
||||||
tsClient: opts.tsClient,
|
tsClient: opts.tsClient,
|
||||||
|
loginServer: opts.loginServer,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
startlog.Fatalf("could not create Recorder reconciler: %v", err)
|
startlog.Fatalf("could not create Recorder reconciler: %v", err)
|
||||||
@ -693,6 +695,8 @@ type reconcilerOpts struct {
|
|||||||
// class for proxies that do not have a ProxyClass set.
|
// class for proxies that do not have a ProxyClass set.
|
||||||
// this is defined by an operator env variable.
|
// this is defined by an operator env variable.
|
||||||
defaultProxyClass string
|
defaultProxyClass string
|
||||||
|
// loginServer is the coordination server URL that should be used by managed resources.
|
||||||
|
loginServer string
|
||||||
}
|
}
|
||||||
|
|
||||||
// enqueueAllIngressEgressProxySvcsinNS returns a reconcile request for each
|
// enqueueAllIngressEgressProxySvcsinNS returns a reconcile request for each
|
||||||
|
@ -59,6 +59,7 @@ type RecorderReconciler struct {
|
|||||||
clock tstime.Clock
|
clock tstime.Clock
|
||||||
tsNamespace string
|
tsNamespace string
|
||||||
tsClient tsClient
|
tsClient tsClient
|
||||||
|
loginServer string
|
||||||
|
|
||||||
mu sync.Mutex // protects following
|
mu sync.Mutex // protects following
|
||||||
recorders set.Slice[types.UID] // for recorders gauge
|
recorders set.Slice[types.UID] // for recorders gauge
|
||||||
@ -202,7 +203,7 @@ func (r *RecorderReconciler) maybeProvision(ctx context.Context, tsr *tsapi.Reco
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("error creating RoleBinding: %w", err)
|
return fmt.Errorf("error creating RoleBinding: %w", err)
|
||||||
}
|
}
|
||||||
ss := tsrStatefulSet(tsr, r.tsNamespace)
|
ss := tsrStatefulSet(tsr, r.tsNamespace, r.loginServer)
|
||||||
if _, err := createOrUpdate(ctx, r.Client, r.tsNamespace, ss, func(s *appsv1.StatefulSet) {
|
if _, err := createOrUpdate(ctx, r.Client, r.tsNamespace, ss, func(s *appsv1.StatefulSet) {
|
||||||
s.ObjectMeta.Labels = ss.ObjectMeta.Labels
|
s.ObjectMeta.Labels = ss.ObjectMeta.Labels
|
||||||
s.ObjectMeta.Annotations = ss.ObjectMeta.Annotations
|
s.ObjectMeta.Annotations = ss.ObjectMeta.Annotations
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func tsrStatefulSet(tsr *tsapi.Recorder, namespace string) *appsv1.StatefulSet {
|
func tsrStatefulSet(tsr *tsapi.Recorder, namespace string, loginServer string) *appsv1.StatefulSet {
|
||||||
return &appsv1.StatefulSet{
|
return &appsv1.StatefulSet{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: tsr.Name,
|
Name: tsr.Name,
|
||||||
@ -59,7 +59,7 @@ func tsrStatefulSet(tsr *tsapi.Recorder, namespace string) *appsv1.StatefulSet {
|
|||||||
ImagePullPolicy: tsr.Spec.StatefulSet.Pod.Container.ImagePullPolicy,
|
ImagePullPolicy: tsr.Spec.StatefulSet.Pod.Container.ImagePullPolicy,
|
||||||
Resources: tsr.Spec.StatefulSet.Pod.Container.Resources,
|
Resources: tsr.Spec.StatefulSet.Pod.Container.Resources,
|
||||||
SecurityContext: tsr.Spec.StatefulSet.Pod.Container.SecurityContext,
|
SecurityContext: tsr.Spec.StatefulSet.Pod.Container.SecurityContext,
|
||||||
Env: env(tsr),
|
Env: env(tsr, loginServer),
|
||||||
EnvFrom: func() []corev1.EnvFromSource {
|
EnvFrom: func() []corev1.EnvFromSource {
|
||||||
if tsr.Spec.Storage.S3 == nil || tsr.Spec.Storage.S3.Credentials.Secret.Name == "" {
|
if tsr.Spec.Storage.S3 == nil || tsr.Spec.Storage.S3.Credentials.Secret.Name == "" {
|
||||||
return nil
|
return nil
|
||||||
@ -201,7 +201,7 @@ func tsrStateSecret(tsr *tsapi.Recorder, namespace string) *corev1.Secret {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func env(tsr *tsapi.Recorder) []corev1.EnvVar {
|
func env(tsr *tsapi.Recorder, loginServer string) []corev1.EnvVar {
|
||||||
envs := []corev1.EnvVar{
|
envs := []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
Name: "TS_AUTHKEY",
|
Name: "TS_AUTHKEY",
|
||||||
@ -239,6 +239,10 @@ func env(tsr *tsapi.Recorder) []corev1.EnvVar {
|
|||||||
Name: "TSRECORDER_HOSTNAME",
|
Name: "TSRECORDER_HOSTNAME",
|
||||||
Value: "$(POD_NAME)",
|
Value: "$(POD_NAME)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "TSRECORDER_LOGIN_SERVER",
|
||||||
|
Value: loginServer,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, env := range tsr.Spec.StatefulSet.Pod.Container.Env {
|
for _, env := range tsr.Spec.StatefulSet.Pod.Container.Env {
|
||||||
|
@ -90,7 +90,7 @@ func TestRecorderSpecs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ss := tsrStatefulSet(tsr, tsNamespace)
|
ss := tsrStatefulSet(tsr, tsNamespace, tsLoginServer)
|
||||||
|
|
||||||
// StatefulSet-level.
|
// StatefulSet-level.
|
||||||
if diff := cmp.Diff(ss.Annotations, tsr.Spec.StatefulSet.Annotations); diff != "" {
|
if diff := cmp.Diff(ss.Annotations, tsr.Spec.StatefulSet.Annotations); diff != "" {
|
||||||
@ -124,7 +124,7 @@ func TestRecorderSpecs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Container-level.
|
// Container-level.
|
||||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Env, env(tsr)); diff != "" {
|
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Env, env(tsr, tsLoginServer)); diff != "" {
|
||||||
t.Errorf("(-got +want):\n%s", diff)
|
t.Errorf("(-got +want):\n%s", diff)
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Image, tsr.Spec.StatefulSet.Pod.Container.Image); diff != "" {
|
if diff := cmp.Diff(ss.Spec.Template.Spec.Containers[0].Image, tsr.Spec.StatefulSet.Pod.Container.Image); diff != "" {
|
||||||
|
@ -25,7 +25,10 @@ import (
|
|||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
)
|
)
|
||||||
|
|
||||||
const tsNamespace = "tailscale"
|
const (
|
||||||
|
tsNamespace = "tailscale"
|
||||||
|
tsLoginServer = "example.tailscale.com"
|
||||||
|
)
|
||||||
|
|
||||||
func TestRecorder(t *testing.T) {
|
func TestRecorder(t *testing.T) {
|
||||||
tsr := &tsapi.Recorder{
|
tsr := &tsapi.Recorder{
|
||||||
@ -51,6 +54,7 @@ func TestRecorder(t *testing.T) {
|
|||||||
recorder: fr,
|
recorder: fr,
|
||||||
l: zl.Sugar(),
|
l: zl.Sugar(),
|
||||||
clock: cl,
|
clock: cl,
|
||||||
|
loginServer: tsLoginServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("invalid_spec_gives_an_error_condition", func(t *testing.T) {
|
t.Run("invalid_spec_gives_an_error_condition", func(t *testing.T) {
|
||||||
@ -234,7 +238,7 @@ func expectRecorderResources(t *testing.T, fc client.WithWatch, tsr *tsapi.Recor
|
|||||||
role := tsrRole(tsr, tsNamespace)
|
role := tsrRole(tsr, tsNamespace)
|
||||||
roleBinding := tsrRoleBinding(tsr, tsNamespace)
|
roleBinding := tsrRoleBinding(tsr, tsNamespace)
|
||||||
serviceAccount := tsrServiceAccount(tsr, tsNamespace)
|
serviceAccount := tsrServiceAccount(tsr, tsNamespace)
|
||||||
statefulSet := tsrStatefulSet(tsr, tsNamespace)
|
statefulSet := tsrStatefulSet(tsr, tsNamespace, tsLoginServer)
|
||||||
|
|
||||||
if shouldExist {
|
if shouldExist {
|
||||||
expectEqual(t, fc, auth)
|
expectEqual(t, fc, auth)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user