in agent/app/agent.go [261:388]
func (agent *ecsAgent) doStart(containerChangeEventStream *eventstream.EventStream,
credentialsManager credentials.Manager,
state dockerstate.TaskEngineState,
imageManager engine.ImageManager,
client api.ECSClient,
execCmdMgr execcmd.Manager) int {
// check docker version >= 1.9.0, exit agent if older
if exitcode, ok := agent.verifyRequiredDockerVersion(); !ok {
return exitcode
}
// Conditionally create '/ecs' cgroup root
if agent.cfg.TaskCPUMemLimit.Enabled() {
if err := agent.cgroupInit(); err != nil {
seelog.Criticalf("Unable to initialize cgroup root for ECS: %v", err)
return exitcodes.ExitTerminal
}
}
if agent.cfg.GPUSupportEnabled {
err := agent.initializeGPUManager()
if err != nil {
seelog.Criticalf("Could not initialize Nvidia GPU Manager: %v", err)
return exitcodes.ExitError
}
}
// Create the task engine
taskEngine, currentEC2InstanceID, err := agent.newTaskEngine(containerChangeEventStream,
credentialsManager, state, imageManager, execCmdMgr)
if err != nil {
seelog.Criticalf("Unable to initialize new task engine: %v", err)
return exitcodes.ExitTerminal
}
agent.initMetricsEngine()
loadPauseErr := agent.loadPauseContainer()
if loadPauseErr != nil {
seelog.Errorf("Failed to load pause container: %v", loadPauseErr)
}
var vpcSubnetAttributes []*ecs.Attribute
// Check if Task ENI is enabled
if agent.cfg.TaskENIEnabled.Enabled() {
// check pause container image load
if loadPauseErr != nil {
if pause.IsNoSuchFileError(loadPauseErr) || pause.UnsupportedPlatform(loadPauseErr) {
return exitcodes.ExitTerminal
} else {
return exitcodes.ExitError
}
}
err, terminal := agent.initializeTaskENIDependencies(state, taskEngine)
switch err {
case nil:
// No error, we can proceed with the rest of initialization
// Set vpc and subnet id attributes
vpcSubnetAttributes = agent.constructVPCSubnetAttributes()
case instanceNotLaunchedInVPCError:
// We have ascertained that the EC2 Instance is not running in a VPC
// No need to stop the ECS Agent in this case; all we need to do is
// to not update the config to disable the TaskENIEnabled flag and
// move on
seelog.Warnf("Unable to detect VPC ID for the Instance, disabling Task ENI capability: %v", err)
agent.cfg.TaskENIEnabled = config.BooleanDefaultFalse{Value: config.ExplicitlyDisabled}
default:
// Encountered an error initializing dependencies for dealing with
// ENIs for Tasks. Exit with the appropriate error code
seelog.Criticalf("Unable to initialize Task ENI dependencies: %v", err)
if terminal {
return exitcodes.ExitTerminal
}
return exitcodes.ExitError
}
}
// Register the container instance
err = agent.registerContainerInstance(client, vpcSubnetAttributes)
if err != nil {
if isTransient(err) {
return exitcodes.ExitError
}
return exitcodes.ExitTerminal
}
// Add container instance ARN to metadata manager
if agent.cfg.ContainerMetadataEnabled.Enabled() {
agent.metadataManager.SetContainerInstanceARN(agent.containerInstanceARN)
agent.metadataManager.SetAvailabilityZone(agent.availabilityZone)
agent.metadataManager.SetHostPrivateIPv4Address(agent.getHostPrivateIPv4AddressFromEC2Metadata())
agent.metadataManager.SetHostPublicIPv4Address(agent.getHostPublicIPv4AddressFromEC2Metadata())
}
if agent.cfg.Checkpoint.Enabled() {
agent.saveMetadata(data.AgentVersionKey, version.Version)
agent.saveMetadata(data.AvailabilityZoneKey, agent.availabilityZone)
agent.saveMetadata(data.ClusterNameKey, agent.cfg.Cluster)
agent.saveMetadata(data.ContainerInstanceARNKey, agent.containerInstanceARN)
agent.saveMetadata(data.EC2InstanceIDKey, currentEC2InstanceID)
}
// now that we know the container instance ARN, we can build out the doctor
// and pass it on to ACS and TACS
doctor, doctorCreateErr := agent.newDoctorWithHealthchecks(agent.cfg.Cluster, agent.containerInstanceARN)
if doctorCreateErr != nil {
seelog.Warnf("Error starting doctor, healthchecks won't be running: %v", err)
} else {
seelog.Debug("Doctor healthchecks set up properly.")
}
// Begin listening to the docker daemon and saving changes
taskEngine.SetDataClient(agent.dataClient)
imageManager.SetDataClient(agent.dataClient)
taskEngine.MustInit(agent.ctx)
// Start back ground routines, including the telemetry session
deregisterInstanceEventStream := eventstream.NewEventStream(
deregisterContainerInstanceEventStreamName, agent.ctx)
deregisterInstanceEventStream.StartListening()
taskHandler := eventhandler.NewTaskHandler(agent.ctx, agent.dataClient, state, client)
attachmentEventHandler := eventhandler.NewAttachmentEventHandler(agent.ctx, agent.dataClient, client)
agent.startAsyncRoutines(containerChangeEventStream, credentialsManager, imageManager,
taskEngine, deregisterInstanceEventStream, client, taskHandler, attachmentEventHandler, state, doctor)
// Start the acs session, which should block doStart
return agent.startACSSession(credentialsManager, taskEngine,
deregisterInstanceEventStream, client, state, taskHandler, doctor)
}