Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Support configuring externalTrafficPolicy on the envoy service #2432

Merged
merged 2 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion api/v1alpha1/kubernetes_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ func DefaultResourceRequirements() *corev1.ResourceRequirements {
// DefaultKubernetesService returns a new KubernetesServiceSpec with default settings.
func DefaultKubernetesService() *KubernetesServiceSpec {
return &KubernetesServiceSpec{
Type: DefaultKubernetesServiceType(),
Type: DefaultKubernetesServiceType(),
ExternalTrafficPolicy: DefaultKubernetesServiceExternalTrafficPolicy(),
}
}

Expand All @@ -80,6 +81,14 @@ func GetKubernetesServiceType(serviceType ServiceType) *ServiceType {
return &serviceType
}

func DefaultKubernetesServiceExternalTrafficPolicy() *ServiceExternalTrafficPolicy {
return GetKubernetesServiceExternalTrafficPolicy(ServiceExternalTrafficPolicyLocal)
}

func GetKubernetesServiceExternalTrafficPolicy(serviceExternalTrafficPolicy ServiceExternalTrafficPolicy) *ServiceExternalTrafficPolicy {
return &serviceExternalTrafficPolicy
}

// defaultKubernetesDeploymentSpec fill a default KubernetesDeploymentSpec if unspecified.
func (deployment *KubernetesDeploymentSpec) defaultKubernetesDeploymentSpec(image string) {
if deployment.Replicas == nil {
Expand Down
23 changes: 23 additions & 0 deletions api/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,23 @@ const (
ServiceTypeNodePort ServiceType = "NodePort"
)

// ServiceExternalTrafficPolicy describes how nodes distribute service traffic they
// receive on one of the Service's "externally-facing" addresses (NodePorts, ExternalIPs,
// and LoadBalancer IPs.
// +enum
// +kubebuilder:validation:Enum=Local;Cluster
type ServiceExternalTrafficPolicy string

const (
// ServiceExternalTrafficPolicyCluster routes traffic to all endpoints.
ServiceExternalTrafficPolicyCluster ServiceExternalTrafficPolicy = "Cluster"

// ServiceExternalTrafficPolicyLocal preserves the source IP of the traffic by
// routing only to endpoints on the same node as the traffic was received on
// (dropping the traffic if there are no local endpoints).
ServiceExternalTrafficPolicyLocal ServiceExternalTrafficPolicy = "Local"
)

// KubernetesServiceSpec defines the desired state of the Kubernetes service resource.
type KubernetesServiceSpec struct {
// Annotations that should be appended to the service.
Expand Down Expand Up @@ -229,6 +246,12 @@ type KubernetesServiceSpec struct {
// +optional
LoadBalancerIP *string `json:"loadBalancerIP,omitempty"`

// ExternalTrafficPolicy determines the externalTrafficPolicy for the Envoy Service. Valid options
// are Local and Cluster. Default is "Local". "Local" means traffic will only go to pods on the node
// receiving the traffic. "Cluster" means connections are loadbalanced to all pods in the cluster.
// +kubebuilder:default:="Local"
// +optional
ExternalTrafficPolicy *ServiceExternalTrafficPolicy `json:"externalTrafficPolicy,omitempty"`
// TODO: Expose config as use cases are better understood, e.g. labels.
}

Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6540,6 +6540,18 @@ spec:
description: Annotations that should be appended to the
service. By default, no annotations are appended.
type: object
externalTrafficPolicy:
default: Local
description: ExternalTrafficPolicy determines the externalTrafficPolicy
for the Envoy Service. Valid options are Local and Cluster.
Default is "Local". "Local" means traffic will only
go to pods on the node receiving the traffic. "Cluster"
means connections are loadbalanced to all pods in the
cluster.
enum:
- Local
- Cluster
type: string
loadBalancerClass:
description: LoadBalancerClass, when specified, allows
for choosing the LoadBalancer provider implementation
Expand Down
7 changes: 5 additions & 2 deletions internal/infrastructure/kubernetes/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func ExpectedServiceSpec(service *egv1a1.KubernetesServiceSpec) corev1.ServiceSp
serviceSpec := corev1.ServiceSpec{}
serviceSpec.Type = corev1.ServiceType(*service.Type)
serviceSpec.SessionAffinity = corev1.ServiceAffinityNone
if service.ExternalTrafficPolicy == nil {
service.ExternalTrafficPolicy = egv1a1.DefaultKubernetesServiceExternalTrafficPolicy()
}
if *service.Type == egv1a1.ServiceTypeLoadBalancer {
if service.LoadBalancerClass != nil {
serviceSpec.LoadBalancerClass = service.LoadBalancerClass
Expand All @@ -37,9 +40,9 @@ func ExpectedServiceSpec(service *egv1a1.KubernetesServiceSpec) corev1.ServiceSp
if service.LoadBalancerIP != nil {
serviceSpec.LoadBalancerIP = *service.LoadBalancerIP
}
// Preserve the client source IP and avoid a second hop for LoadBalancer.
serviceSpec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicyTypeLocal
serviceSpec.ExternalTrafficPolicy = corev1.ServiceExternalTrafficPolicy(*service.ExternalTrafficPolicy)
}

return serviceSpec
}

Expand Down
12 changes: 12 additions & 0 deletions internal/infrastructure/kubernetes/resource/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ func TestExpectedServiceSpec(t *testing.T) {
ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyTypeLocal,
},
},
{
name: "LoadBalancerWithExternalTrafficPolicyCluster",
args: args{service: &egv1a1.KubernetesServiceSpec{
Type: egv1a1.GetKubernetesServiceType(egv1a1.ServiceTypeLoadBalancer),
ExternalTrafficPolicy: egv1a1.GetKubernetesServiceExternalTrafficPolicy(egv1a1.ServiceExternalTrafficPolicyCluster),
}},
want: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer,
SessionAffinity: corev1.ServiceAffinityNone,
ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyTypeCluster,
},
},
{
name: "LoadBalancerWithClass",
args: args{service: &egv1a1.KubernetesServiceSpec{
Expand Down
12 changes: 12 additions & 0 deletions site/content/en/latest/api/extension_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,7 @@ _Appears in:_
| `loadBalancerClass` _string_ | LoadBalancerClass, when specified, allows for choosing the LoadBalancer provider implementation if more than one are available or is otherwise expected to be specified |
| `allocateLoadBalancerNodePorts` _boolean_ | AllocateLoadBalancerNodePorts defines if NodePorts will be automatically allocated for services with type LoadBalancer. Default is "true". It may be set to "false" if the cluster load-balancer does not rely on NodePorts. If the caller requests specific NodePorts (by specifying a value), those requests will be respected, regardless of this field. This field may only be set for services with type LoadBalancer and will be cleared if the type is changed to any other type. |
| `loadBalancerIP` _string_ | LoadBalancerIP defines the IP Address of the underlying load balancer service. This field may be ignored if the load balancer provider does not support this feature. This field has been deprecated in Kubernetes, but it is still used for setting the IP Address in some cloud providers such as GCP. |
| `externalTrafficPolicy` _[ServiceExternalTrafficPolicy](#serviceexternaltrafficpolicy)_ | ExternalTrafficPolicy determines the externalTrafficPolicy for the Envoy Service. Valid options are Local and Cluster. Default is "Local". "Local" means traffic will only go to pods on the node receiving the traffic. "Cluster" means connections are loadbalanced to all pods in the cluster. |


#### KubernetesWatchMode
Expand Down Expand Up @@ -1905,6 +1906,17 @@ _Appears in:_



#### ServiceExternalTrafficPolicy

_Underlying type:_ `string`

ServiceExternalTrafficPolicy describes how nodes distribute service traffic they receive on one of the Service's "externally-facing" addresses (NodePorts, ExternalIPs, and LoadBalancer IPs.

_Appears in:_
- [KubernetesServiceSpec](#kubernetesservicespec)



#### ServiceType

_Underlying type:_ `string`
Expand Down