Support canary weight for external name service

This commit is contained in:
Kim Min 2018-11-06 14:48:03 +08:00 committed by Traefiker Bot
parent fa562dc916
commit 057498ed01
4 changed files with 61 additions and 7 deletions

View file

@ -357,15 +357,16 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
continue
}
if service.Spec.Type == "ExternalName" {
// We have to treat external-name service differently here b/c it doesn't have any endpoints
if service.Spec.Type == corev1.ServiceTypeExternalName {
url := protocol + "://" + service.Spec.ExternalName
if port.Port != 443 && port.Port != 80 {
url = fmt.Sprintf("%s:%d", url, port.Port)
}
externalNameServiceWeight := weightAllocator.getWeight(r.Host, pa.Path, pa.Backend.ServiceName)
templateObjects.Backends[baseName].Servers[url] = types.Server{
URL: url,
Weight: label.DefaultWeight,
Weight: externalNameServiceWeight,
}
} else {
endpoints, exists, err := k8sClient.GetEndpoints(service.Namespace, service.Name)

View file

@ -3232,6 +3232,7 @@ func TestPercentageWeightServiceAnnotation(t *testing.T) {
buildIngress(
iAnnotation(annotationKubernetesServiceWeights, `
service1: 10%
service3: 20%
`),
iNamespace("testing"),
iRules(
@ -3240,6 +3241,7 @@ service1: 10%
iPaths(
onePath(iPath("/foo"), iBackend("service1", intstr.FromString("8080"))),
onePath(iPath("/foo"), iBackend("service2", intstr.FromString("7070"))),
onePath(iPath("/foo"), iBackend("service3", intstr.FromString("9090"))),
onePath(iPath("/bar"), iBackend("service2", intstr.FromString("7070"))),
)),
),
@ -3264,6 +3266,16 @@ service1: 10%
sPorts(sPort(7070, "")),
),
),
buildService(
sName("service3"),
sNamespace("testing"),
sUID("1"),
sSpec(
sType(corev1.ServiceTypeExternalName),
sExternalName("example.com"),
sPorts(sPort(9090, "")),
),
),
}
endpoints := []*corev1.Endpoints{
@ -3311,8 +3323,9 @@ service1: 10%
servers(
server("http://10.10.0.1:8080", weight(int(newPercentageValueFromFloat64(0.05)))),
server("http://10.10.0.2:8080", weight(int(newPercentageValueFromFloat64(0.05)))),
server("http://10.10.0.3:7070", weight(int(newPercentageValueFromFloat64(0.45)))),
server("http://10.10.0.4:7070", weight(int(newPercentageValueFromFloat64(0.45)))),
server("http://10.10.0.3:7070", weight(int(newPercentageValueFromFloat64(0.35)))),
server("http://10.10.0.4:7070", weight(int(newPercentageValueFromFloat64(0.35)))),
server("http://example.com:9090", weight(int(newPercentageValueFromFloat64(0.2)))),
),
lbMethod("wrr"),
),

View file

@ -7,6 +7,7 @@ import (
"github.com/containous/traefik/old/provider/label"
"gopkg.in/yaml.v2"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
)
@ -165,6 +166,23 @@ func getServiceInstanceCounts(ingress *extensionsv1beta1.Ingress, client Client)
for _, rule := range ingress.Spec.Rules {
for _, pa := range rule.HTTP.Paths {
svc, exists, err := client.GetService(ingress.Namespace, pa.Backend.ServiceName)
if err != nil {
return nil, fmt.Errorf("failed to get service %s/%s: %v", ingress.Namespace, pa.Backend.ServiceName, err)
}
if !exists {
return nil, fmt.Errorf("service not found for %s/%s", ingress.Namespace, pa.Backend.ServiceName)
}
if svc.Spec.Type == corev1.ServiceTypeExternalName {
// external-name service has only one instance b/c it will actually be interpreted as a DNS record
// instead of real server.
serviceInstanceCounts[ingressService{
host: rule.Host,
path: pa.Path,
service: pa.Backend.ServiceName,
}] = 1
continue
}
count := 0
endpoints, exists, err := client.GetEndpoints(ingress.Namespace, pa.Backend.ServiceName)
if err != nil {

View file

@ -169,6 +169,24 @@ service1: 1000%
func TestComputeServiceWeights(t *testing.T) {
client := clientMock{
services: []*corev1.Service{
buildService(
sName("service1"),
sNamespace("testing"),
),
buildService(
sName("service2"),
sNamespace("testing"),
),
buildService(
sName("service3"),
sNamespace("testing"),
),
buildService(
sName("service4"),
sNamespace("testing"),
),
},
endpoints: []*corev1.Endpoints{
buildEndpoint(
eNamespace("testing"),
@ -446,8 +464,12 @@ service2: 80%
if test.expectError {
require.Error(t, err)
} else {
for ingSvc, percentage := range test.expectedWeights {
assert.Equal(t, int(percentage), weightAllocator.getWeight(ingSvc.host, ingSvc.path, ingSvc.service))
if err != nil {
t.Errorf("%v failed: %v", test.desc, err)
} else {
for ingSvc, percentage := range test.expectedWeights {
assert.Equal(t, int(percentage), weightAllocator.getWeight(ingSvc.host, ingSvc.path, ingSvc.service))
}
}
}
})