Service can freely communicate within a network

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2020-05-28 16:45:53 +02:00
parent 6c57fb9693
commit 5783b63556
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
6 changed files with 93 additions and 24 deletions

View File

@ -55,11 +55,9 @@ according to the networks declared in Compose model. Doing so, services attached
communicate together, while services from distinct SecurityGroups can't. We just can't set service aliasses per network. 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 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 get service discovery and DNS round-robin (equivalent for Compose's `endpoint_mode: dnsrr`). Docker images SHOULD
discovery is enabled by running application containers with `LOCALDOMAIN={project}.local` include a tiny entrypoint script to replicate this feature:
(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 ```shell script
if [ $LOCALDOMAIN ]; then echo "search ${LOCALDOMAIN}" >> /etc/resolv.conf; fi if [ ! -z LOCALDOMAIN ]; then echo "search ${LOCALDOMAIN}" >> /etc/resolv.conf; fi
``` ```

View File

@ -5,6 +5,8 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/compose-spec/compose-go/types"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
cloudmapapi "github.com/aws/aws-sdk-go/service/servicediscovery" cloudmapapi "github.com/aws/aws-sdk-go/service/servicediscovery"
@ -77,9 +79,10 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
} }
cluster := cloudformation.If("CreateCluster", cloudformation.Ref("Cluster"), cloudformation.Ref(ParameterClusterName)) cluster := cloudformation.If("CreateCluster", cloudformation.Ref("Cluster"), cloudformation.Ref(ParameterClusterName))
for net := range project.Networks { for _, net := range project.Networks {
name, resource := convertNetwork(project, net, cloudformation.Ref(ParameterVPCId)) for k, v := range convertNetwork(project, net, cloudformation.Ref(ParameterVPCId)) {
template.Resources[name] = resource template.Resources[k] = v
}
} }
logGroup := fmt.Sprintf("/docker-compose/%s", project.Name) logGroup := fmt.Sprintf("/docker-compose/%s", project.Name)
@ -204,25 +207,28 @@ func (c client) Convert(project *compose.Project) (*cloudformation.Template, err
return template, nil return template, nil
} }
func convertNetwork(project *compose.Project, net string, vpc string) (string, cloudformation.Resource) { func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc string) map[string]cloudformation.Resource {
resources := map[string]cloudformation.Resource{}
var ingresses []ec2.SecurityGroup_Ingress var ingresses []ec2.SecurityGroup_Ingress
for _, service := range project.Services { if !net.Internal {
if _, ok := service.Networks[net]; ok { for _, service := range project.Services {
for _, port := range service.Ports { if _, ok := service.Networks[net.Name]; ok {
ingresses = append(ingresses, ec2.SecurityGroup_Ingress{ for _, port := range service.Ports {
CidrIp: "0.0.0.0/0", ingresses = append(ingresses, ec2.SecurityGroup_Ingress{
Description: fmt.Sprintf("%s:%d/%s", service.Name, port.Target, port.Protocol), CidrIp: "0.0.0.0/0",
FromPort: int(port.Target), Description: fmt.Sprintf("%s:%d/%s", service.Name, port.Target, port.Protocol),
IpProtocol: strings.ToUpper(port.Protocol), FromPort: int(port.Target),
ToPort: int(port.Target), IpProtocol: strings.ToUpper(port.Protocol),
}) ToPort: int(port.Target),
})
}
} }
} }
} }
securityGroup := networkResourceName(project, net) securityGroup := networkResourceName(project, net.Name)
resource := &ec2.SecurityGroup{ resources[securityGroup] = &ec2.SecurityGroup{
GroupDescription: fmt.Sprintf("%s %s Security Group", project.Name, net), GroupDescription: fmt.Sprintf("%s %s Security Group", project.Name, net.Name),
GroupName: securityGroup, GroupName: securityGroup,
SecurityGroupIngress: ingresses, SecurityGroupIngress: ingresses,
VpcId: vpc, VpcId: vpc,
@ -233,11 +239,20 @@ func convertNetwork(project *compose.Project, net string, vpc string) (string, c
}, },
{ {
Key: NetworkTag, Key: NetworkTag,
Value: net, Value: net.Name,
}, },
}, },
} }
return securityGroup, resource
ingress := securityGroup + "Ingress"
resources[ingress] = &ec2.SecurityGroupIngress{
Description: fmt.Sprintf("Allow communication within network %s", net.Name),
IpProtocol: "-1", // all protocols
GroupId: cloudformation.Ref(securityGroup),
SourceSecurityGroupId: cloudformation.Ref(securityGroup),
}
return resources
} }
func networkResourceName(project *compose.Project, network string) string { func networkResourceName(project *compose.Project, network string) string {

View File

@ -232,6 +232,19 @@
} }
}, },
"Type": "AWS::EC2::SecurityGroup" "Type": "AWS::EC2::SecurityGroup"
},
"TestSimpleConvertDefaultNetworkIngress": {
"Properties": {
"Description": "Allow communication within network default",
"GroupId": {
"Ref": "TestSimpleConvertDefaultNetwork"
},
"IpProtocol": "-1",
"SourceSecurityGroupId": {
"Ref": "TestSimpleConvertDefaultNetwork"
}
},
"Type": "AWS::EC2::SecurityGroupIngress"
} }
} }
} }

View File

@ -232,6 +232,19 @@
} }
}, },
"Type": "AWS::EC2::SecurityGroup" "Type": "AWS::EC2::SecurityGroup"
},
"TestSimpleWithOverridesDefaultNetworkIngress": {
"Properties": {
"Description": "Allow communication within network default",
"GroupId": {
"Ref": "TestSimpleWithOverridesDefaultNetwork"
},
"IpProtocol": "-1",
"SourceSecurityGroupId": {
"Ref": "TestSimpleWithOverridesDefaultNetwork"
}
},
"Type": "AWS::EC2::SecurityGroupIngress"
} }
} }
} }

View File

@ -54,6 +54,7 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error
return err return err
} }
fmt.Println()
return c.WaitStackCompletion(ctx, project.Name, StackCreate) return c.WaitStackCompletion(ctx, project.Name, StackCreate)
} }

View File

@ -49,5 +49,34 @@ func Normalize(model *types.Config) error {
} }
model.Services[i] = s model.Services[i] = s
} }
for i, n := range model.Networks {
if n.Name == "" {
n.Name = i
model.Networks[i] = n
}
}
for i, v := range model.Volumes {
if v.Name == "" {
v.Name = i
model.Volumes[i] = v
}
}
for i, c := range model.Configs {
if c.Name == "" {
c.Name = i
model.Configs[i] = c
}
}
for i, s := range model.Secrets {
if s.Name == "" {
s.Name = i
model.Secrets[i] = s
}
}
return nil return nil
} }