diff --git a/docs/toml.md b/docs/toml.md index 5902a667f..61266e9ad 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -1777,6 +1777,8 @@ Labels can be used on task containers to override default behaviour: - `traefik.protocol=https`: override the default `http` protocol - `traefik.weight=10`: assign this weight to the container - `traefik.enable=false`: disable this container in Træfik +- `traefik.backend.loadbalancer.method=drr`: override the default `wrr` load balancer algorithm +- `traefik.backend.loadbalancer.sticky=true`: enable backend sticky sessions - `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.priority=10`: override default frontend priority diff --git a/provider/ecs/ecs.go b/provider/ecs/ecs.go index b1e93ec82..b092ec8f9 100644 --- a/provider/ecs/ecs.go +++ b/provider/ecs/ecs.go @@ -180,8 +180,10 @@ func wrapAws(ctx context.Context, req *request.Request) error { func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types.Configuration, error) { var ecsFuncMap = template.FuncMap{ - "filterFrontends": p.filterFrontends, - "getFrontendRule": p.getFrontendRule, + "filterFrontends": p.filterFrontends, + "getFrontendRule": p.getFrontendRule, + "getLoadBalancerSticky": p.getLoadBalancerSticky, + "getLoadBalancerMethod": p.getLoadBalancerMethod, } instances, err := p.listInstances(ctx, client) @@ -191,10 +193,20 @@ func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types instances = fun.Filter(p.filterInstance, instances).([]ecsInstance) + services := make(map[string][]ecsInstance) + + for _, instance := range instances { + if serviceInstances, ok := services[instance.Name]; ok { + services[instance.Name] = append(serviceInstances, instance) + } else { + services[instance.Name] = []ecsInstance{instance} + } + } + return p.GetConfiguration("templates/ecs.tmpl", ecsFuncMap, struct { - Instances []ecsInstance + Services map[string][]ecsInstance }{ - instances, + services, }) } @@ -457,6 +469,26 @@ func (p *Provider) getFrontendRule(i ecsInstance) string { return "Host:" + strings.ToLower(strings.Replace(i.Name, "_", "-", -1)) + "." + p.Domain } +func (p *Provider) getLoadBalancerSticky(instances []ecsInstance) string { + if len(instances) > 0 { + label := instances[0].label(types.LabelBackendLoadbalancerSticky) + if label != "" { + return label + } + } + return "false" +} + +func (p *Provider) getLoadBalancerMethod(instances []ecsInstance) string { + if len(instances) > 0 { + label := instances[0].label(types.LabelBackendLoadbalancerMethod) + if label != "" { + return label + } + } + return "wrr" +} + // Provider expects no more than 100 parameters be passed to a DescribeTask call; thus, pack // each string into an array capped at 100 elements func (p *Provider) chunkedTaskArns(tasks []*string) [][]*string { diff --git a/templates/ecs.tmpl b/templates/ecs.tmpl index 83abdb008..99c758d24 100644 --- a/templates/ecs.tmpl +++ b/templates/ecs.tmpl @@ -1,17 +1,25 @@ -[backends]{{range .Instances}} - [backends.backend-{{ .Name }}.servers.server-{{ .Name }}{{ .ID }}] - url = "{{ .Protocol }}://{{ .Host }}:{{ .Port }}" - weight = {{ .Weight }} +[backends]{{range $serviceName, $instances := .Services}} + [backends.backend-{{ $serviceName }}.loadbalancer] + sticky = {{ getLoadBalancerSticky $instances}} + method = "{{ getLoadBalancerMethod $instances}}" + + {{range $index, $i := $instances}} + [backends.backend-{{ $i.Name }}.servers.server-{{ $i.Name }}{{ $i.ID }}] + url = "{{ $i.Protocol }}://{{ $i.Host }}:{{ $i.Port }}" + weight = {{ $i.Weight }} + {{end}} {{end}} -[frontends]{{range filterFrontends .Instances}} - [frontends.frontend-{{ .Name }}] - backend = "backend-{{ .Name }}" - passHostHeader = {{ .PassHostHeader }} - priority = {{ .Priority }} - entryPoints = [{{range .EntryPoints }} - "{{.}}", - {{end}}] - [frontends.frontend-{{ .Name }}.routes.route-frontend-{{ .Name }}] - rule = "{{getFrontendRule .}}" -{{end}} +[frontends]{{range $serviceName, $instances := .Services}} + {{range filterFrontends $instances}} + [frontends.frontend-{{ $serviceName }}] + backend = "backend-{{ $serviceName }}" + passHostHeader = {{ .PassHostHeader }} + priority = {{ .Priority }} + entryPoints = [{{range .EntryPoints }} + "{{.}}", + {{end}}] + [frontends.frontend-{{ $serviceName }}.routes.route-frontend-{{ $serviceName }}] + rule = "{{getFrontendRule .}}" + {{end}} +{{end}} \ No newline at end of file