mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
cmd/k8s-operator: base ProxyGroup StatefulSet on common proxy.yaml definition (#13714)
As discussed in #13684, base the ProxyGroup's proxy definitions on the same scaffolding as the existing proxies, as defined in proxy.yaml Updates #13406 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
parent
83efadee9f
commit
07c157ee9f
@ -239,7 +239,10 @@ func (r *ProxyGroupReconciler) maybeProvision(ctx context.Context, pg *tsapi.Pro
|
|||||||
return fmt.Errorf("error provisioning ConfigMap: %w", err)
|
return fmt.Errorf("error provisioning ConfigMap: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ss := pgStatefulSet(pg, r.tsNamespace, r.proxyImage, r.tsFirewallMode, cfgHash)
|
ss, err := pgStatefulSet(pg, r.tsNamespace, r.proxyImage, r.tsFirewallMode, cfgHash)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error generating StatefulSet spec: %w", err)
|
||||||
|
}
|
||||||
ss = applyProxyClassToStatefulSet(proxyClass, ss, nil, logger)
|
ss = applyProxyClassToStatefulSet(proxyClass, ss, nil, logger)
|
||||||
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
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||||
"tailscale.com/kube/egressservices"
|
"tailscale.com/kube/egressservices"
|
||||||
"tailscale.com/types/ptr"
|
"tailscale.com/types/ptr"
|
||||||
@ -19,21 +20,34 @@
|
|||||||
|
|
||||||
// Returns the base StatefulSet definition for a ProxyGroup. A ProxyClass may be
|
// Returns the base StatefulSet definition for a ProxyGroup. A ProxyClass may be
|
||||||
// applied over the top after.
|
// applied over the top after.
|
||||||
func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHash string) *appsv1.StatefulSet {
|
func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHash string) (*appsv1.StatefulSet, error) {
|
||||||
return &appsv1.StatefulSet{
|
ss := new(appsv1.StatefulSet)
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
if err := yaml.Unmarshal(proxyYaml, &ss); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal proxy spec: %w", err)
|
||||||
|
}
|
||||||
|
// Validate some base assumptions.
|
||||||
|
if len(ss.Spec.Template.Spec.InitContainers) != 1 {
|
||||||
|
return nil, fmt.Errorf("[unexpected] base proxy config had %d init containers instead of 1", len(ss.Spec.Template.Spec.InitContainers))
|
||||||
|
}
|
||||||
|
if len(ss.Spec.Template.Spec.Containers) != 1 {
|
||||||
|
return nil, fmt.Errorf("[unexpected] base proxy config had %d containers instead of 1", len(ss.Spec.Template.Spec.Containers))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatefulSet config.
|
||||||
|
ss.ObjectMeta = metav1.ObjectMeta{
|
||||||
Name: pg.Name,
|
Name: pg.Name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: pgLabels(pg.Name, nil),
|
Labels: pgLabels(pg.Name, nil),
|
||||||
OwnerReferences: pgOwnerReference(pg),
|
OwnerReferences: pgOwnerReference(pg),
|
||||||
},
|
}
|
||||||
Spec: appsv1.StatefulSetSpec{
|
ss.Spec.Replicas = ptr.To(pgReplicas(pg))
|
||||||
Replicas: ptr.To(pgReplicas(pg)),
|
ss.Spec.Selector = &metav1.LabelSelector{
|
||||||
Selector: &metav1.LabelSelector{
|
|
||||||
MatchLabels: pgLabels(pg.Name, nil),
|
MatchLabels: pgLabels(pg.Name, nil),
|
||||||
},
|
}
|
||||||
Template: corev1.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
// Template config.
|
||||||
|
tmpl := &ss.Spec.Template
|
||||||
|
tmpl.ObjectMeta = metav1.ObjectMeta{
|
||||||
Name: pg.Name,
|
Name: pg.Name,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: pgLabels(pg.Name, nil),
|
Labels: pgLabels(pg.Name, nil),
|
||||||
@ -41,37 +55,42 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHa
|
|||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
podAnnotationLastSetConfigFileHash: cfgHash,
|
podAnnotationLastSetConfigFileHash: cfgHash,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
tmpl.Spec.ServiceAccountName = pg.Name
|
||||||
|
tmpl.Spec.InitContainers[0].Image = image
|
||||||
|
tmpl.Spec.Volumes = func() []corev1.Volume {
|
||||||
|
var volumes []corev1.Volume
|
||||||
|
for i := range pgReplicas(pg) {
|
||||||
|
volumes = append(volumes, corev1.Volume{
|
||||||
|
Name: fmt.Sprintf("tailscaledconfig-%d", i),
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
Secret: &corev1.SecretVolumeSource{
|
||||||
|
SecretName: fmt.Sprintf("%s-%d-config", pg.Name, i),
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
|
||||||
ServiceAccountName: pg.Name,
|
|
||||||
InitContainers: []corev1.Container{
|
|
||||||
{
|
|
||||||
Name: "sysctler",
|
|
||||||
Image: image,
|
|
||||||
SecurityContext: &corev1.SecurityContext{
|
|
||||||
Privileged: ptr.To(true),
|
|
||||||
},
|
},
|
||||||
Command: []string{
|
})
|
||||||
"/bin/sh",
|
}
|
||||||
"-c",
|
|
||||||
},
|
if pg.Spec.Type == tsapi.ProxyGroupTypeEgress {
|
||||||
Args: []string{
|
volumes = append(volumes, corev1.Volume{
|
||||||
"sysctl -w net.ipv4.ip_forward=1 && if sysctl net.ipv6.conf.all.forwarding; then sysctl -w net.ipv6.conf.all.forwarding=1; fi",
|
Name: pgEgressCMName(pg.Name),
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: pgEgressCMName(pg.Name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []corev1.Container{
|
})
|
||||||
{
|
}
|
||||||
Name: "tailscale",
|
|
||||||
Image: image,
|
return volumes
|
||||||
SecurityContext: &corev1.SecurityContext{
|
}()
|
||||||
Capabilities: &corev1.Capabilities{
|
|
||||||
Add: []corev1.Capability{
|
// Main container config.
|
||||||
"NET_ADMIN",
|
c := &ss.Spec.Template.Spec.Containers[0]
|
||||||
},
|
c.Image = image
|
||||||
},
|
c.VolumeMounts = func() []corev1.VolumeMount {
|
||||||
},
|
|
||||||
VolumeMounts: func() []corev1.VolumeMount {
|
|
||||||
var mounts []corev1.VolumeMount
|
var mounts []corev1.VolumeMount
|
||||||
for i := range pgReplicas(pg) {
|
for i := range pgReplicas(pg) {
|
||||||
mounts = append(mounts, corev1.VolumeMount{
|
mounts = append(mounts, corev1.VolumeMount{
|
||||||
@ -88,9 +107,10 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHa
|
|||||||
ReadOnly: true,
|
ReadOnly: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return mounts
|
return mounts
|
||||||
}(),
|
}()
|
||||||
Env: func() []corev1.EnvVar {
|
c.Env = func() []corev1.EnvVar {
|
||||||
envs := []corev1.EnvVar{
|
envs := []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
// TODO(irbekrm): verify that .status.podIPs are always set, else read in .status.podIP as well.
|
// TODO(irbekrm): verify that .status.podIPs are always set, else read in .status.podIP as well.
|
||||||
@ -127,12 +147,6 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHa
|
|||||||
Value: "false",
|
Value: "false",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if pg.Spec.Type == tsapi.ProxyGroupTypeEgress {
|
|
||||||
envs = append(envs, corev1.EnvVar{
|
|
||||||
Name: "TS_EGRESS_SERVICES_CONFIG_PATH",
|
|
||||||
Value: fmt.Sprintf("/etc/proxies/%s", egressservices.KeyEgressServices),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if tsFirewallMode != "" {
|
if tsFirewallMode != "" {
|
||||||
envs = append(envs, corev1.EnvVar{
|
envs = append(envs, corev1.EnvVar{
|
||||||
@ -141,41 +155,17 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode, cfgHa
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return envs
|
|
||||||
}(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Volumes: func() []corev1.Volume {
|
|
||||||
var volumes []corev1.Volume
|
|
||||||
for i := range pgReplicas(pg) {
|
|
||||||
volumes = append(volumes, corev1.Volume{
|
|
||||||
Name: fmt.Sprintf("tailscaledconfig-%d", i),
|
|
||||||
VolumeSource: corev1.VolumeSource{
|
|
||||||
Secret: &corev1.SecretVolumeSource{
|
|
||||||
SecretName: fmt.Sprintf("%s-%d-config", pg.Name, i),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if pg.Spec.Type == tsapi.ProxyGroupTypeEgress {
|
if pg.Spec.Type == tsapi.ProxyGroupTypeEgress {
|
||||||
volumes = append(volumes, corev1.Volume{
|
envs = append(envs, corev1.EnvVar{
|
||||||
Name: pgEgressCMName(pg.Name),
|
Name: "TS_EGRESS_SERVICES_CONFIG_PATH",
|
||||||
VolumeSource: corev1.VolumeSource{
|
Value: fmt.Sprintf("/etc/proxies/%s", egressservices.KeyEgressServices),
|
||||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
|
||||||
LocalObjectReference: corev1.LocalObjectReference{
|
|
||||||
Name: pgEgressCMName(pg.Name),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return volumes
|
return envs
|
||||||
}(),
|
}()
|
||||||
},
|
|
||||||
},
|
return ss, nil
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pgServiceAccount(pg *tsapi.ProxyGroup, namespace string) *corev1.ServiceAccount {
|
func pgServiceAccount(pg *tsapi.ProxyGroup, namespace string) *corev1.ServiceAccount {
|
||||||
|
@ -197,7 +197,10 @@ func expectProxyGroupResources(t *testing.T, fc client.WithWatch, pg *tsapi.Prox
|
|||||||
role := pgRole(pg, tsNamespace)
|
role := pgRole(pg, tsNamespace)
|
||||||
roleBinding := pgRoleBinding(pg, tsNamespace)
|
roleBinding := pgRoleBinding(pg, tsNamespace)
|
||||||
serviceAccount := pgServiceAccount(pg, tsNamespace)
|
serviceAccount := pgServiceAccount(pg, tsNamespace)
|
||||||
statefulSet := pgStatefulSet(pg, tsNamespace, testProxyImage, "auto", "")
|
statefulSet, err := pgStatefulSet(pg, tsNamespace, testProxyImage, "auto", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
statefulSet.Annotations = defaultProxyClassAnnotations
|
statefulSet.Annotations = defaultProxyClassAnnotations
|
||||||
|
|
||||||
if shouldExist {
|
if shouldExist {
|
||||||
|
Loading…
Reference in New Issue
Block a user