-
Notifications
You must be signed in to change notification settings - Fork 158
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
Use the ECS RunTask API to run attached processes #1043
Conversation
To expand a bit on the idea of adding a method to provide the |
Oh that would be awesome if they were down for it. |
a66a9f2
to
390fb78
Compare
cmd/empire/main.go
Outdated
@@ -57,6 +57,8 @@ const ( | |||
FlagECSServiceRole = "ecs.service.role" | |||
FlagECSLogDriver = "ecs.logdriver" | |||
FlagECSLogOpts = "ecs.logopt" | |||
FlagECSAttachedEnabled = "ecs.attached.enabled" | |||
FlagECSAttachedPlacement = "ecs.attached.placement" |
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.
This should probably also allow you to set placement constraints for normal procs and detached procs. If not (and assuming you want to restrict attached processes to a group of hosts), normal tasks could get scheduled onto the hosts that you've designated for attached runs.
|
||
// Wait for the task to start running. It will stay in the | ||
// PENDING state while the container is being pulled. | ||
if err := m.ecs.WaitUntilTasksRunning(&ecs.DescribeTasksInput{ |
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.
This should actually wait until it's RUNNING or STOPPED. If you run something that returns quickly (e.g. emp run echo hello world
), the task could hit STOPPED
before this method had a change to actually see it was running. It should be fine to AttachToContainer
on a stopped task, since the ECS agent waits 3 hours to cleanup containers.
Ok, @phobologic. If you wanna give this another look, I think this is probably good to go. We've been running this on staging, without any hitches so far. Primary changes since the last review:
The first commit can just be ignored, since it's just an update to the AWS SDK. |
Noticed some zombie procs lying around. This should probably try a |
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.
Looks good so far!
CHANGELOG.md
Outdated
@@ -8,6 +8,7 @@ | |||
* An ALIAS record is now created for `<process>.<app>.<zone>` [#1005](https://github.com/remind101/empire/pull/1005) | |||
* You can now provide a `-p` flag to the `emp cert-attach` command to attach a certificate to a specific process (instead of just `web`). [#1014](https://github.com/remind101/empire/pull/1014) | |||
* Empire now supports a SAML authentication backend. [#1017](https://github.com/remind101/empire/pull/1017) | |||
* Empire supports a new (experimental) feature to enabled attached processes to be ran with ECS. [#1043](https://github.com/remind101/empire/pull/1043) |
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.
to enabled
-> to enable
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.
Good catch. I'll update.
cmd/empire/main.go
Outdated
@@ -310,6 +311,11 @@ var EmpireFlags = []cli.Flag{ | |||
Usage: "Log driver to options. Maps to the --log-opt docker cli arg", | |||
EnvVar: "EMPIRE_ECS_LOG_OPT", | |||
}, | |||
cli.BoolFlag{ | |||
Name: FlagECSAttachedEnabled, | |||
Usage: "When enabled, indicates that ECS tasks can be attached to, using `docker attach`. When provided, this will also use ECS to run attached processes.", |
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.
With this requiring the patched agent, it might be worth pointing at the doc that details what this means.
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.
Good call. I'll update.
scheduler/cloudformation/clients.go
Outdated
*ecs.ECS | ||
} | ||
|
||
func (c *ECS) WaitUntilTasksNotPending(input *ecs.DescribeTasksInput) 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.
my linter is going to complain about no docstring here :)
// Amazon ECS Container Agent, since the official agent doesn't | ||
// provide a method to pass these down to the `CreateContainer` | ||
// call. | ||
containerDefinition.DockerLabels["docker.config.Tty"] = aws.String("true") |
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.
Curious why both?
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.
The Tty
flag allocates a psuedo TTY for the container, and OpenStdin
opens the stdin stream.
Without OpenStdin
, running something like emp run bash
would just exit as soon as bash hit the prompt. Without Tty
, I think most commands that expect a TTY/terminal wouldn't work (If I try docker run -i ubuntu bash
(missing -t
flag), my terminal just hangs).
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.
👍 ah, right - not sure why I didn't tie this to docker run --it
|
||
// Wait for the task to start running. It will stay in the | ||
// PENDING state while the container is being pulled. | ||
if err := m.ecs.WaitUntilTasksNotPending(&ecs.DescribeTasksInput{ |
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.
Wondering if we need some sort of timeout here?
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.
This will timeout after 10 minutes (6 second delay between refreshes, and 100 retries).
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.
👍
// instance where the task is running. | ||
d, err := m.NewDockerClient(ec2Instance) | ||
if err != nil { | ||
return fmt.Errorf("error establishing docker client connection to %s", aws.StringValue(ec2Instance.InstanceId)) |
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.
Will this bubble up with the task id, etc? Might want to put some more info in this so it's easier to figure out what happened.
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.
Not atm. I'll add that information to 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.
Actually, it does already show this, since it's output above the error (Attaching to task/<task id>...
).
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.
Oh, but this is totally missing the err
.
aef931d
to
2f792d9
Compare
This has been working out pretty well for us in our staging environment without any major issues/bugs. Gonna go ahead and merge. |
Not ready to merge.
This is a prototype for switching
emp run
to use the ECS RunTask API, instead of calling out to Docker directly. The primary motivation behind this is to allow containers started withemp run
to use AWS Roles for ECS tasks. This is described in https://github.com/remind101/empire/wiki/RFC:-Use-RunTask-API-for-attached-runs.There's some serious caveats with this implementation at the moment:
AttachToContainer
, the container needs to be started with theTty
andOpenStdin
flags set to true. Unfortunately, the ECS API and the ECS agent don't currently provide a method to pass these down. We would currently need to fork the agent.On the plus side, this sets up some infrastructure for adding an
emp exec/attach
command for starting up a process in an existing container, or attaching to a running process.TODO
Tty
/OpenStdin
flags.Add ability to limit normal containers to a group of hosts.