mirror of https://github.com/docker/compose.git
Implement Hostname-only service discovery using LOCALDOMAIN
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
0864513bfe
commit
4ab37f8229
|
@ -39,3 +39,27 @@ file do not include unsupported features.
|
|||
* _Convert_ produces a CloudFormation template to define all resources required to implement the application model on AWS.
|
||||
* _Apply_ phase do apply the CloudFormation template, either by exporting to a stack file or to deploy on AWS.
|
||||
|
||||
## Application model
|
||||
|
||||
### Services
|
||||
|
||||
Compose services are mapped to ECS services. Compose specification has no support for multi-container services, nor
|
||||
does it support sidecars. When an ECS feature requires a sidecar, we introduce custom Compose extension (`x-aws-*`)
|
||||
to actually expose ECS feature as a service-level feature, not plumbing details.
|
||||
|
||||
### Networking
|
||||
|
||||
We map the "network" abstraction from Compose model to AWS SecurityGroups. The whole application is created within a
|
||||
single VPC, SecurityGroups are created per networks, including the implicit `default` one. Services are attached
|
||||
according to the networks declared in Compose model. Doing so, services attached to a common security group can
|
||||
communicate together, while services from distinct SecurityGroups can't. We just can't set service aliasses per network.
|
||||
|
||||
A CloudMap private namespace is created for application as `{project}.local`. Services get registered so that we
|
||||
get service discovery and DNS round-robin (equivalent for Compose's `endpoint_mode: dnsrr`). Hostname-only service
|
||||
discovery is enabled by running application containers with `LOCALDOMAIN={project}.local`
|
||||
(see [resolv.conf(5)](http://man7.org/linux/man-pages/man5/resolv.conf.5.html)). This works out-of-the-box for
|
||||
debian-based Docker images. Alpine images have to include a tiny entrypoint script to replicate this feature:
|
||||
```shell script
|
||||
if [ $LOCALDOMAIN ]; then echo "search ${LOCALDOMAIN}" >> /etc/resolv.conf; fi
|
||||
```
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ require (
|
|||
github.com/Microsoft/hcsshim v0.8.7 // indirect
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
|
||||
github.com/aws/aws-sdk-go v1.28.9
|
||||
github.com/aws/aws-sdk-go v1.30.22
|
||||
github.com/awslabs/goformation/v4 v4.8.0
|
||||
github.com/bitly/go-hostpool v0.1.0 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
|
@ -24,7 +24,6 @@ require (
|
|||
github.com/docker/go v1.5.1-1 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/golang/mock v1.4.3
|
||||
|
|
|
@ -21,6 +21,9 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.28.9 h1:grIuBQc+p3dTRXerh5+2OxSuWFi0iXuxbFdTSg0jaW0=
|
||||
github.com/aws/aws-sdk-go v1.28.9/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.30.2/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.30.22 h1:wImJ8jQrplgmxaTeUY7FrJFn4te/VtWq+mmmJ1TnWAg=
|
||||
github.com/aws/aws-sdk-go v1.30.22/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/awslabs/goformation/v4 v4.8.0 h1:UiUhyokRy3suEqBXTnipvY8klqY3Eyl4GCH17brraEc=
|
||||
github.com/awslabs/goformation/v4 v4.8.0/go.mod h1:GcJULxCJfloT+3pbqCluXftdEK2AD/UqpS3hkaaBntg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
|
@ -161,6 +164,8 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
|||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
|
@ -300,6 +305,7 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
|||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0=
|
||||
github.com/theupdateframework/notary v0.6.1/go.mod h1:MOfgIfmox8s7/7fduvB2xyPPMJCrjRLRizA8OFwpnKY=
|
||||
|
@ -357,6 +363,7 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 h1:KaQtG+aDELoNmXYas3TVkGNYR
|
|||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package amazon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
ecsapi "github.com/aws/aws-sdk-go/service/ecs"
|
||||
"github.com/awslabs/goformation/v4/cloudformation"
|
||||
"github.com/awslabs/goformation/v4/cloudformation/ecs"
|
||||
|
@ -21,9 +22,17 @@ func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDe
|
|||
}
|
||||
credential := getRepoCredentials(service)
|
||||
|
||||
// override resolve.conf search directive to also search <project>.local
|
||||
// TODO remove once ECS support hostname-only service discovery
|
||||
service.Environment["LOCALDOMAIN"] = aws.String(
|
||||
cloudformation.Join("", []string{
|
||||
cloudformation.Ref("AWS::Region"),
|
||||
".compute.internal",
|
||||
fmt.Sprintf(" %s.local", project.Name),
|
||||
}))
|
||||
|
||||
return &ecs.TaskDefinition{
|
||||
ContainerDefinitions: []ecs.TaskDefinition_ContainerDefinition{
|
||||
// Here we can declare sidecars and init-containers using https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_dependson
|
||||
{
|
||||
Command: service.Command,
|
||||
DisableNetworking: service.NetworkMode == "none",
|
||||
|
@ -50,7 +59,6 @@ func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDe
|
|||
"awslogs-stream-prefix": service.Name,
|
||||
},
|
||||
},
|
||||
MountPoints: nil,
|
||||
Name: service.Name,
|
||||
PortMappings: toPortMappings(service.Ports),
|
||||
Privileged: service.Privileged,
|
||||
|
@ -68,7 +76,7 @@ func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDe
|
|||
},
|
||||
},
|
||||
Cpu: cpu,
|
||||
Family: project.Name,
|
||||
Family: fmt.Sprintf("%s-%s", project.Name, service.Name),
|
||||
IpcMode: service.Ipc,
|
||||
Memory: mem,
|
||||
NetworkMode: ecsapi.NetworkModeAwsvpc, // FIXME could be set by service.NetworkMode, Fargate only supports network mode ‘awsvpc’.
|
||||
|
@ -77,7 +85,6 @@ func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDe
|
|||
ProxyConfiguration: nil,
|
||||
RequiresCompatibilities: []string{ecsapi.LaunchTypeFargate},
|
||||
Tags: nil,
|
||||
Volumes: []ecs.TaskDefinition_Volume{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -122,7 +129,7 @@ func toLimits(service types.ServiceConfig) (string, string, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return "", "", errors.New("unable to find cpu/mem for the required resources")
|
||||
return "", "", fmt.Errorf("unable to find cpu/mem for the required resources")
|
||||
}
|
||||
|
||||
func toRequiresCompatibilities(isolation string) []*string {
|
||||
|
@ -198,8 +205,7 @@ func toTmpfs(tmpfs types.StringList) []ecs.TaskDefinition_Tmpfs {
|
|||
for _, path := range tmpfs {
|
||||
o = append(o, ecs.TaskDefinition_Tmpfs{
|
||||
ContainerPath: path,
|
||||
MountOptions: nil,
|
||||
Size: 0,
|
||||
Size: 100, // size is required on ECS, unlimited by the compose spec
|
||||
})
|
||||
}
|
||||
return o
|
||||
|
|
Loading…
Reference in New Issue