This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/cloudstack-kubernetes-provider.git
The following commit(s) were added to refs/heads/main by this push:
new 0150bf58 Add hostname annotation to set lb ingress hostname (#48)
0150bf58 is described below
commit 0150bf581a142e1de0bcba6ddbeeeb5afd60f433
Author: Hans Rakers <[email protected]>
AuthorDate: Tue May 28 14:35:02 2024 +0200
Add hostname annotation to set lb ingress hostname (#48)
This fixes problems with kube-proxy in ipvs mode considering the lb IP as
local to the node
See https://github.com/kubernetes/kubernetes/issues/66607
This can also be used to access PROXY proto service from the inside
---
cloudstack_loadbalancer.go | 63 +++++++++++++++++++++++++++++++++++++++++++---
protocol.go | 18 +++----------
2 files changed, 62 insertions(+), 19 deletions(-)
diff --git a/cloudstack_loadbalancer.go b/cloudstack_loadbalancer.go
index 8c7ef197..ed703339 100644
--- a/cloudstack_loadbalancer.go
+++ b/cloudstack_loadbalancer.go
@@ -32,9 +32,19 @@ import (
cloudprovider "k8s.io/cloud-provider"
)
-// defaultAllowedCIDR is the network range that is allowed on the firewall
-// by default when no explicit CIDR list is given on a LoadBalancer.
-const defaultAllowedCIDR = "0.0.0.0/0"
+const (
+ // defaultAllowedCIDR is the network range that is allowed on the
firewall
+ // by default when no explicit CIDR list is given on a LoadBalancer.
+ defaultAllowedCIDR = "0.0.0.0/0"
+
+ // ServiceAnnotationLoadBalancerProxyProtocol is the annotation used on
the
+ // service to enable the proxy protocol on a CloudStack load balancer.
+ // Note that this protocol only applies to TCP service ports and
+ // CloudStack >= 4.6 is required for it to work.
+ ServiceAnnotationLoadBalancerProxyProtocol =
"service.beta.kubernetes.io/cloudstack-load-balancer-proxy-protocol"
+
+ ServiceAnnotationLoadBalancerLoadbalancerHostname =
"service.beta.kubernetes.io/cloudstack-load-balancer-hostname"
+)
type loadBalancer struct {
*cloudstack.CloudStackClient
@@ -123,7 +133,7 @@ func (cs *CSCloud) EnsureLoadBalancer(ctx context.Context,
clusterName string, s
for _, port := range service.Spec.Ports {
// Construct the protocol name first, we need it a few times
- protocol := ProtocolFromServicePort(port, service.Annotations)
+ protocol := ProtocolFromServicePort(port, service)
if protocol == LoadBalancerProtocolInvalid {
return nil, fmt.Errorf("unsupported load balancer
protocol: %v", port.Protocol)
}
@@ -202,6 +212,13 @@ func (cs *CSCloud) EnsureLoadBalancer(ctx context.Context,
clusterName string, s
}
status = &corev1.LoadBalancerStatus{}
+ // If hostname is explicitly set using service annotation
+ // Workaround for https://github.com/kubernetes/kubernetes/issues/66607
+ if hostname := getStringFromServiceAnnotation(service,
ServiceAnnotationLoadBalancerLoadbalancerHostname, ""); hostname != "" {
+ status.Ingress = []corev1.LoadBalancerIngress{{Hostname:
hostname}}
+ return status, nil
+ }
+ // Default to IP
status.Ingress = []corev1.LoadBalancerIngress{{IP: lb.ipAddr}}
return status, nil
@@ -805,3 +822,41 @@ func (lb *loadBalancer) deleteFirewallRule(publicIpId
string, publicPort int, pr
return deleted, err
}
+
+// getStringFromServiceAnnotation searches a given v1.Service for a specific
annotationKey and either returns the annotation's value or a specified
defaultSetting
+func getStringFromServiceAnnotation(service *corev1.Service, annotationKey
string, defaultSetting string) string {
+ klog.V(4).Infof("getStringFromServiceAnnotation(%s/%s, %v, %v)",
service.Namespace, service.Name, annotationKey, defaultSetting)
+ if annotationValue, ok := service.Annotations[annotationKey]; ok {
+ //if there is an annotation for this setting, set the "setting"
var to it
+ // annotationValue can be empty, it is working as designed
+ // it makes possible for instance provisioning loadbalancer
without floatingip
+ klog.V(4).Infof("Found a Service Annotation: %v = %v",
annotationKey, annotationValue)
+ return annotationValue
+ }
+ //if there is no annotation, set "settings" var to the value from cloud
config
+ if defaultSetting != "" {
+ klog.V(4).Infof("Could not find a Service Annotation; falling
back on cloud-config setting: %v = %v", annotationKey, defaultSetting)
+ }
+ return defaultSetting
+}
+
+// getBoolFromServiceAnnotation searches a given v1.Service for a specific
annotationKey and either returns the annotation's boolean value or a specified
defaultSetting
+func getBoolFromServiceAnnotation(service *corev1.Service, annotationKey
string, defaultSetting bool) bool {
+ klog.V(4).Infof("getBoolFromServiceAnnotation(%s/%s, %v, %v)",
service.Namespace, service.Name, annotationKey, defaultSetting)
+ if annotationValue, ok := service.Annotations[annotationKey]; ok {
+ returnValue := false
+ switch annotationValue {
+ case "true":
+ returnValue = true
+ case "false":
+ returnValue = false
+ default:
+ returnValue = defaultSetting
+ }
+
+ klog.V(4).Infof("Found a Service Annotation: %v = %v",
annotationKey, returnValue)
+ return returnValue
+ }
+ klog.V(4).Infof("Could not find a Service Annotation; falling back to
default setting: %v = %v", annotationKey, defaultSetting)
+ return defaultSetting
+}
diff --git a/protocol.go b/protocol.go
index c9142237..07d81748 100644
--- a/protocol.go
+++ b/protocol.go
@@ -20,7 +20,7 @@
package cloudstack
import (
- "k8s.io/api/core/v1"
+ v1 "k8s.io/api/core/v1"
)
// LoadBalancerProtocol represents a specific network protocol supported by
the CloudStack load balancer.
@@ -35,14 +35,6 @@ const (
LoadBalancerProtocolInvalid
)
-// ServiceAnnotationLoadBalancerProxyProtocol is the annotation used on the
-// service to enable the proxy protocol on a CloudStack load balancer.
-// The value of this annotation is ignored, even if it is seemingly boolean.
-// Simple presence of the annotation will enable it.
-// Note that this protocol only applies to TCP service ports and
-// CloudStack 4.6 is required for it to work.
-const ServiceAnnotationLoadBalancerProxyProtocol =
"service.beta.kubernetes.io/cloudstack-load-balancer-proxy-protocol"
-
// String returns the same value as CSProtocol.
func (p LoadBalancerProtocol) String() string {
return p.CSProtocol()
@@ -89,12 +81,8 @@ func (p LoadBalancerProtocol) IPProtocol() string {
// -> "tcp-proxy" (CloudStack 4.6 and later)
//
// Other values return LoadBalancerProtocolInvalid.
-func ProtocolFromServicePort(port v1.ServicePort, annotations
map[string]string) LoadBalancerProtocol {
- proxy := false
- // FIXME this accepts any value as true, even "false", 0 or other
falsey stuff
- if _, ok := annotations[ServiceAnnotationLoadBalancerProxyProtocol]; ok
{
- proxy = true
- }
+func ProtocolFromServicePort(port v1.ServicePort, service *v1.Service)
LoadBalancerProtocol {
+ proxy := getBoolFromServiceAnnotation(service,
ServiceAnnotationLoadBalancerProxyProtocol, false)
switch port.Protocol {
case v1.ProtocolTCP:
if proxy {