cmd/{containerboot,k8s-operator},k8s-operator,kube: add ProxyGroup controller (#13684)

Implements the controller for the new ProxyGroup CRD, designed for
running proxies in a high availability configuration. Each proxy gets
its own config and state Secret, and its own tailscale node ID.

We are currently mounting all of the config secrets into the container,
but will stop mounting them and instead read them directly from the kube
API once #13578 is implemented.

Updates #13406

Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
Tom Proctor
2024-10-07 14:58:45 +01:00
committed by GitHub
parent 1005cbc1e4
commit e48cddfbb3
20 changed files with 1117 additions and 32 deletions
+1 -1
View File
@@ -526,7 +526,7 @@ _Appears in:_
| `tags` _[Tags](#tags)_ | Tags that the Tailscale devices will be tagged with. Defaults to [tag:k8s].<br />If you specify custom tags here, make sure you also make the operator<br />an owner of these tags.<br />See https://tailscale.com/kb/1236/kubernetes-operator/#setting-up-the-kubernetes-operator.<br />Tags cannot be changed once a ProxyGroup device has been created.<br />Tag values must be in form ^tag:[a-zA-Z][a-zA-Z0-9-]*$. | | Pattern: `^tag:[a-zA-Z][a-zA-Z0-9-]*$` <br />Type: string <br /> |
| `replicas` _integer_ | Replicas specifies how many replicas to create the StatefulSet with.<br />Defaults to 2. | | |
| `hostnamePrefix` _[HostnamePrefix](#hostnameprefix)_ | HostnamePrefix is the hostname prefix to use for tailnet devices created<br />by the ProxyGroup. Each device will have the integer number from its<br />StatefulSet pod appended to this prefix to form the full hostname.<br />HostnamePrefix can contain lower case letters, numbers and dashes, it<br />must not start with a dash and must be between 1 and 62 characters long. | | Pattern: `^[a-z0-9][a-z0-9-]{0,61}$` <br />Type: string <br /> |
| `proxyClass` _string_ | ProxyClass is the name of the ProxyClass custom resource that contains<br />configuration options that should be applied to the resources created<br />for this ProxyGroup. If unset, and no default ProxyClass is set, the<br />operator will create resources with the default configuration. | | |
| `proxyClass` _string_ | ProxyClass is the name of the ProxyClass custom resource that contains<br />configuration options that should be applied to the resources created<br />for this ProxyGroup. If unset, the operator will create resources with<br />the default configuration. | | |
#### ProxyGroupStatus
@@ -54,7 +54,7 @@ type ProxyGroupSpec struct {
// Replicas specifies how many replicas to create the StatefulSet with.
// Defaults to 2.
// +optional
Replicas *int `json:"replicas,omitempty"`
Replicas *int32 `json:"replicas,omitempty"`
// HostnamePrefix is the hostname prefix to use for tailnet devices created
// by the ProxyGroup. Each device will have the integer number from its
@@ -66,8 +66,8 @@ type ProxyGroupSpec struct {
// ProxyClass is the name of the ProxyClass custom resource that contains
// configuration options that should be applied to the resources created
// for this ProxyGroup. If unset, and no default ProxyClass is set, the
// operator will create resources with the default configuration.
// for this ProxyGroup. If unset, the operator will create resources with
// the default configuration.
// +optional
ProxyClass string `json:"proxyClass,omitempty"`
}
@@ -584,7 +584,7 @@ func (in *ProxyGroupSpec) DeepCopyInto(out *ProxyGroupSpec) {
}
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int)
*out = new(int32)
**out = **in
}
}
+8
View File
@@ -93,6 +93,14 @@ func SetRecorderCondition(tsr *tsapi.Recorder, conditionType tsapi.ConditionType
tsr.Status.Conditions = conds
}
// SetProxyGroupCondition ensures that ProxyGroup status has a condition with the
// given attributes. LastTransitionTime gets set every time condition's status
// changes.
func SetProxyGroupCondition(pg *tsapi.ProxyGroup, conditionType tsapi.ConditionType, status metav1.ConditionStatus, reason, message string, gen int64, clock tstime.Clock, logger *zap.SugaredLogger) {
conds := updateCondition(pg.Status.Conditions, conditionType, status, reason, message, gen, clock, logger)
pg.Status.Conditions = conds
}
func updateCondition(conds []metav1.Condition, conditionType tsapi.ConditionType, status metav1.ConditionStatus, reason, message string, gen int64, clock tstime.Clock, logger *zap.SugaredLogger) []metav1.Condition {
newCondition := metav1.Condition{
Type: string(conditionType),
+2 -2
View File
@@ -29,9 +29,9 @@ type Records struct {
IP4 map[string][]string `json:"ip4"`
}
// TailscaledConfigFileNameForCap returns a tailscaled config file name in
// TailscaledConfigFileName returns a tailscaled config file name in
// format expected by containerboot for the given CapVer.
func TailscaledConfigFileNameForCap(cap tailcfg.CapabilityVersion) string {
func TailscaledConfigFileName(cap tailcfg.CapabilityVersion) string {
if cap < 95 {
return "tailscaled"
}