-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AWS ELB-ALB support #211
AWS ELB-ALB support #211
Conversation
533731a
to
4e4421f
Compare
When creating a new ECS service, allow the user to specify an ELB target group ARN, container name and port that it will associate with the newly created ECS service.
4e4421f
to
6011ce7
Compare
} | ||
|
||
s.loadBalancer = &ecs.LoadBalancer{ | ||
TargetGroupArn: aws.String(targetGroupArn), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also support Classic Load Balancer (ELB) as well? You will need to add LoadBalancerName
as a parameter.
http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LoadBalancer.html
func (client *ecsClient) CreateService(serviceName, taskDefName string, loadBalancer *ecs.LoadBalancer, role string, deploymentConfig *ecs.DeploymentConfiguration) error { | ||
var err error | ||
|
||
if *loadBalancer.TargetGroupArn != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend initializing the common inputs first, and if TargetGroupARN
or LoadBalancerName
is specified, add the fields that are needed for creating ELB/ALB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to check if loadBalancer
is nil
before dereferencing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per loadContext
method https://github.com/aws/amazon-ecs-cli/pull/211/files#diff-97b4106c54aad3d402f437209e9fc4e3R78 loadBalancer
could have empty values but it'll never be nil
.
func (client *ecsClient) CreateService(serviceName, taskDefName string, loadBalancer *ecs.LoadBalancer, role string, deploymentConfig *ecs.DeploymentConfiguration) error { | ||
var err error | ||
|
||
if *loadBalancer.TargetGroupArn != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to check if loadBalancer
is nil
before dereferencing it.
@@ -136,3 +136,36 @@ func deploymentConfigFlags(specifyDefaults bool) []cli.Flag { | |||
}, | |||
} | |||
} | |||
|
|||
func loadBalancerFlags(specifyDefaults bool) []cli.Flag { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nrdlngr Can you review this text?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI, the text is copy pasted from the param description in the AWS API docs. But please, review.
CreateService use a common CreateServiceInput object for both cases (ELB/no ELB) set it first, then set the ELB params if present.
New param --load-balancer-name allow to set a classic load balancer name for the service. Note that in case of both target-goup-arn and load-balancer-name present, target-group-arn param will take precedence.
loadBalancerNameUsageString := "[Optional] The name of the load balancer." | ||
roleUsageString := "[Optional] The name or full Amazon Resource Name (ARN) of the IAM role that allows Amazon ECS to make calls to your load balancer on your behalf. This parameter is required if you are using a load balancer with your service. If you specify the role parameter, you must also specify a target-group-arn, container-name and container-port." | ||
|
||
if specifyDefaults { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When will this be false?
Also, I don't think we need to specify the defaults as none. "Optional" already indicates that it will be empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it should never be called with false. Removed
containerNameUsageString += " Defaults to none" | ||
containerPortUsageString += " Defaults to none" | ||
loadBalancerNameUsageString += " Defaults to none" | ||
roleUsageString += " Defaults to ecsServiceRole" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it actually defaults to ecsServiceRole
?
Also, to specify defaults use Value
in the cli.StringFlag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took license here and used the role name used in AWS docs http://docs.aws.amazon.com/AmazonECS/latest/developerguide/service_IAM_role.html on creating an IAM role for ECS services.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Victorcoder I'm seeing 2 issues here.
- You are specifying in the command help text that the role defaults to
ecsServiceRole
, but in your actual implementation of createService, you're not setting the default toecsServiceRole
- By setting the default role, we are assuming everyone has created the role
ecsServiceRole
which is not always the case, we should be creating the role for them if the role does not exist.
I would leave out the defaults in the command help text for now, and add it back once we have the implementations. Hope that makes sense!
ecs-cli/modules/compose/ecs/flags.go
Outdated
ContainerNameFlag = "container-name" | ||
ContainerPortFlag = "container-port" | ||
LoadBalancerNameFlag = "load-balancer-name" | ||
RoleDefaultValue = "ecsServiceRole" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also remove the RoleDefaultValue
? This is something we need to revisit
ContainerPort: containerPort, | ||
} | ||
|
||
if targetGroupArn != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to educate the customers that loadBalancerName
and targetGroupArn
by throwing an error when both are specified instead of picking one for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I did in with the other params is let the AWS API validate the user input, the validation errors are quite meaninfull in most cases.
If we remove the targetGoupArn
/loadBalancerName
fallback here, we get a good server side message educating the user:
FATA[0000] InvalidParameterException: loadBalancerName and targetGroupArn cannot both be specified. You must specify either a load BalancerName or a targetGroupArn.
So removing the check here
if err != nil { | ||
} | ||
|
||
if *loadBalancer.TargetGroupArn != "" || *loadBalancer.LoadBalancerName != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
I understand that for the current use case, the loadBalancer will always be set and will never be nil, but this
CreateServce
method can be reused in the future, hence I would still recommend adding a nil pointer check here. -
Can you change
*loadBalancer.TargetGroupArn
to use aws.StringValue (aws.StringValue(loadBalancer.TargetGroupArn)
andaws.StringValue(loadBalancer.LoadBalancerName)
)
@@ -136,3 +136,35 @@ func deploymentConfigFlags(specifyDefaults bool) []cli.Flag { | |||
}, | |||
} | |||
} | |||
|
|||
func loadBalancerFlags() []cli.Flag { | |||
targetGroupArnUsageString := "[Optional] The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am working on reviewing the text with others, and will update you once I have the final version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the full Amazon Resource Name (ARN) of a previously configured Elastic Load Balancing target group to associate with your service."
We let AWS API to inform the user of the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few doc suggestions to keep things consistent with our existing help text.
I modified a few of the help strings to indicate that they were required for both classic and application load balancers, and that the load balancer resources must exist before the command is run.
containerNameUsageString := "[Optional] Mandatory if target-group-arn is specified. The container name (as it appears in a container definition)." | ||
containerPortUsageString := "[Optional] Mandatory if target-group-arn is specified. The container port to access from the load balancer." | ||
loadBalancerNameUsageString := "[Optional] The name of the load balancer." | ||
roleUsageString := fmt.Sprintf("[Optional] The name or full Amazon Resource Name (ARN) of the IAM role that allows Amazon ECS to make calls to your load balancer on your behalf. This parameter is required if you are using a load balancer with your service. If you specify the role parameter, you must also specify a target-group-arn, container-name and container-port.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the name or full Amazon Resource Name (ARN) of the IAM role that allows Amazon ECS to make calls to your load balancer or target group on your behalf. This parameter is required if you are using a load balancer or target group with your service. If you specify the role parameter, you must also specify a load balancer name or target group ARN, along with a container name and container port."
@@ -136,3 +136,35 @@ func deploymentConfigFlags(specifyDefaults bool) []cli.Flag { | |||
}, | |||
} | |||
} | |||
|
|||
func loadBalancerFlags() []cli.Flag { | |||
targetGroupArnUsageString := "[Optional] The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the full Amazon Resource Name (ARN) of a previously configured Elastic Load Balancing target group to associate with your service."
|
||
func loadBalancerFlags() []cli.Flag { | ||
targetGroupArnUsageString := "[Optional] The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service." | ||
containerNameUsageString := "[Optional] Mandatory if target-group-arn is specified. The container name (as it appears in a container definition)." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the container name (as it appears in a container definition). This parameter is required if a load balancer or target group is specified."
func loadBalancerFlags() []cli.Flag { | ||
targetGroupArnUsageString := "[Optional] The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service." | ||
containerNameUsageString := "[Optional] Mandatory if target-group-arn is specified. The container name (as it appears in a container definition)." | ||
containerPortUsageString := "[Optional] Mandatory if target-group-arn is specified. The container port to access from the load balancer." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the port on the container to associate with the load balancer. This port must correspond to a containerPort in the service's task definition. This parameter is required if a load balancer or target group is specified."
targetGroupArnUsageString := "[Optional] The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service." | ||
containerNameUsageString := "[Optional] Mandatory if target-group-arn is specified. The container name (as it appears in a container definition)." | ||
containerPortUsageString := "[Optional] Mandatory if target-group-arn is specified. The container port to access from the load balancer." | ||
loadBalancerNameUsageString := "[Optional] The name of the load balancer." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind changing this to:
"[Optional] Specifies the name of a previously configured Elastic Load Balancing load balancer to associate with your service."
@Victorcoder Can you please make text changes base on @nrdlngr's suggestions? Thank you! |
Changes applied @nrdlngr |
containerNameUsageString := "[Optional] Specifies the container name (as it appears in a container definition). This parameter is required if a load balancer or target group is specified." | ||
containerPortUsageString := "[Optional] Specifies the port on the container to associate with the load balancer. This port must correspond to a containerPort in the service's task definition. This parameter is required if a load balancer or target group is specified." | ||
loadBalancerNameUsageString := "[Optional] Specifies the name of a previously configured Elastic Load Balancing load balancer to associate with your service." | ||
roleUsageString := fmt.Sprintf("[Optional] Specifies the name or full Amazon Resource Name (ARN) of the IAM role that allows Amazon ECS to make calls to your load balancer or target group on your behalf. This parameter is required if you are using a load balancer or target group with your service. If you specify the role parameter, you must also specify a load balancer name or target group ARN, along with a container name and container port.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating the text. Just one minor comment
printf is not longer needed here.
@Victorcoder Are you fine with your commit being merged in under the Apache 2.0 license? |
@yinshiua Thanks to you, I'm ok, go ahead. |
Thanks for your contribution. I am giving a pass on this PR, but will have minor followup changes on bug fixing. |
Shouldn't this be able to read from a JSON or YAML file, so the service can be created, dropped, recreated without having to reproduce command line options? What about other service parameters such as maximumPercent and minimumHealthyPercent? |
@markriggins That could be a good improvement but those parameters wouldn't be compose compatible so it will force to have another file to create the service. In any case, that would be the goal of another PR. |
Yeah, we wound up adding a *service-name--env.json *file to our services,
and then wrapping ecs-cli with a script to pick up these extra service
settings. But we had no choice, since we could not add new keywords to
the yaml. ecs-cli could add some custom sections, no?
Mark Riggins
CLOUD COMPUTING ARCHITECT
336.312.7125
www.SocialCode.com <http://socialcode.com/>
…On Fri, Mar 24, 2017 at 10:30 AM, Victor Castell ***@***.***> wrote:
@markriggins <https://github.com/markriggins> That could be a good
improvement but those parameters wouldn't be compose compatible so it will
force to have another file to create the service.
In any case, that would be the goal of another PR.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#211 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABNfuj8EIUWc06CI9CQJTocHO3XDCg6oks5ro9N2gaJpZM4MKDRN>
.
|
Would it be possible for someone to give an example on how to use this new feature please? |
@markriggins This would be a good enhancement to read all these fields from yaml or JSON. (ex. @serragnoli An example for ALB would be:
|
@serragnoli <https://github.com/serragnoli> -- this feature is currently
unavailable via ecs-cli, so we had to use the `aws ecs` command instead
after reading these settings from a json file and merging them with the
existing settings.
The important line from the script reads something like this.
aws ecs update-service --service ecscompose-service-$serviceName
--cli-input-json
"$service_settings"
Mark Riggins
CLOUD COMPUTING ARCHITECT
336.312.7125
www.SocialCode.com <http://socialcode.com/>
…On Mon, Apr 17, 2017 at 3:51 PM, Fabio Serragnoli ***@***.***> wrote:
Would it be possible for someone to give an example on how to use this new
feature please?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#211 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABNfutIIDqAEejrQVkng5OF4kaCBvd5uks5rw8KngaJpZM4MKDRN>
.
|
@yinshiua Thank you for the example.... Just to clarify, when using the --target-group-arn setting, I would assume that the target group is already existing as a part of an ALB, and thus there's no need to specify the ALB, right? Thus, when using the --load-balancer-name setting instead, it would assume that it is using a classic load balancer, not an ALB, since, as I'd imagine, just putting an ALB would be insufficient in stating where it needs to go? I'll still trying to navigate my way thru in terms of understanding ECS, in terms of tasks, services, etc... so any help would be greatly appreciated! |
@vchan2002 The following documentations may be helpful: |
We want to be able to create a new service and assign it an Application Load Balancer.
Add 5 new params that allows to specify the Load Balancer details in order for the service to be created with an associated ELB/ALB.
Specify the Target Group ARN, Load Balancer Name, Container Name, Container Port and Role to allow the service to register new instances in the ELB/ALB.
--target-group-arn
: The full Amazon Resource Name (ARN) of the Elastic Load Balancing target group associated with a service.--load-balancer-name
: The name of the classic load balancer.--container-name
: The name of the container (as it appears in a container definition) to associate with the load balancer.--container-port
: The port on the container to associate with the load balancer. This port must correspond to a containerPort in the service's task definition. Your container instances must allow ingress traffic on the hostPort of the port mapping.--role
: The name or full Amazon Resource Name (ARN) of the IAM role that allows Amazon ECS to make calls to your load balancer on your behalf. This parameter is required if you are using a load balancer with your service. If you specify the role parameter, you must also specify a load balancer object with the loadBalancers parameter.If
--target-group-arn
or--load-balancer-name
is not passed then the current behaviour is maintained and it doesn't try to associate an ELB with the service.Note: If both
target-goup-arn
andload-balancer-name
present,target-group-arn
param will take precedence.