cmd/k8s-operator,k8s-operator: Kubernetes Peer Relays (#20495)

This commit contains the Kubernetes implementation of peer relays via the new `PeerRelay` CRD. It's a mega branch consisting of the commits of other PRs gone into this work:

1. https://github.com/tailscale/tailscale/pull/20211
2. https://github.com/tailscale/tailscale/pull/20329
3. https://github.com/tailscale/tailscale/pull/20423
4. https://github.com/tailscale/tailscale/pull/20503

An instance of the `PeerRelay` CRD deploys a `StatefulSet` of containerboot instances configured to advertise themselves as peer relays using the IP addresses configured via `LoadBalancer` services on each cloud provider (with some AWS specifics as it's less automatic than its competing cloud providers). 

Per replica, a `LoadBalancer` type `Service` resource is provisioned and its IP address is used to configure the respective relay.

This has been tested with success in AWS, GCP & Azure and provides additional modification to `Service` resources via the CRD for any other kinds of deployment environments. It also contains some work that may appear to be duplication of what already exists within `cmd/k8s-operator` so we can start building an appropriate migration path for `Connector`, `ProxyGroup` etc into respective `k8s-operator/reconciler/*` packages.

Closes https://github.com/tailscale/corp/issues/34524
This commit is contained in:
David Bond
2026-07-20 16:37:15 +01:00
committed by GitHub
parent 2dd5d82f56
commit be0e460a20
22 changed files with 3823 additions and 1 deletions
@@ -550,6 +550,199 @@ func (in *NodePortConfig) DeepCopy() *NodePortConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelay) DeepCopyInto(out *PeerRelay) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelay.
func (in *PeerRelay) DeepCopy() *PeerRelay {
if in == nil {
return nil
}
out := new(PeerRelay)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PeerRelay) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayAWS) DeepCopyInto(out *PeerRelayAWS) {
*out = *in
if in.ElasticIPs != nil {
in, out := &in.ElasticIPs, &out.ElasticIPs
*out = make([]PeerRelayAWSElasticIP, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayAWS.
func (in *PeerRelayAWS) DeepCopy() *PeerRelayAWS {
if in == nil {
return nil
}
out := new(PeerRelayAWS)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayAWSElasticIP) DeepCopyInto(out *PeerRelayAWSElasticIP) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayAWSElasticIP.
func (in *PeerRelayAWSElasticIP) DeepCopy() *PeerRelayAWSElasticIP {
if in == nil {
return nil
}
out := new(PeerRelayAWSElasticIP)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayEndpoint) DeepCopyInto(out *PeerRelayEndpoint) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayEndpoint.
func (in *PeerRelayEndpoint) DeepCopy() *PeerRelayEndpoint {
if in == nil {
return nil
}
out := new(PeerRelayEndpoint)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayList) DeepCopyInto(out *PeerRelayList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PeerRelay, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayList.
func (in *PeerRelayList) DeepCopy() *PeerRelayList {
if in == nil {
return nil
}
out := new(PeerRelayList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PeerRelayList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayService) DeepCopyInto(out *PeerRelayService) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayService.
func (in *PeerRelayService) DeepCopy() *PeerRelayService {
if in == nil {
return nil
}
out := new(PeerRelayService)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelaySpec) DeepCopyInto(out *PeerRelaySpec) {
*out = *in
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make(Tags, len(*in))
copy(*out, *in)
}
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
}
if in.Service != nil {
in, out := &in.Service, &out.Service
*out = new(PeerRelayService)
(*in).DeepCopyInto(*out)
}
if in.AWS != nil {
in, out := &in.AWS, &out.AWS
*out = new(PeerRelayAWS)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelaySpec.
func (in *PeerRelaySpec) DeepCopy() *PeerRelaySpec {
if in == nil {
return nil
}
out := new(PeerRelaySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PeerRelayStatus) DeepCopyInto(out *PeerRelayStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]PeerRelayEndpoint, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerRelayStatus.
func (in *PeerRelayStatus) DeepCopy() *PeerRelayStatus {
if in == nil {
return nil
}
out := new(PeerRelayStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Pod) DeepCopyInto(out *Pod) {
*out = *in