Skip to content

Commit ebc2c02

Browse files
authored
Merge pull request #3693 from yinyic/sc-bridge-firelens
Support firelens for bridge mode ServiceConnect task
2 parents 3a9dcd4 + 9e7dfbe commit ebc2c02

File tree

3 files changed

+326
-119
lines changed

3 files changed

+326
-119
lines changed

agent/api/task/task.go

+4
Original file line numberDiff line numberDiff line change
@@ -3443,6 +3443,10 @@ func (task *Task) IsServiceConnectEnabled() bool {
34433443
return task.GetServiceConnectContainer() != nil
34443444
}
34453445

3446+
func (task *Task) IsServiceConnectBridgeModeApplicationContainer(container *apicontainer.Container) bool {
3447+
return container.GetNetworkModeFromHostConfig() == "container" && task.IsServiceConnectEnabled()
3448+
}
3449+
34463450
// PopulateServiceConnectContainerMappingEnvVar populates APPNET_CONTAINER_IP_MAPPING env var for AppNet Agent container
34473451
// aka SC container
34483452
func (task *Task) PopulateServiceConnectContainerMappingEnvVar() error {

agent/engine/docker_task_engine.go

+72-17
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,28 @@ func (engine *DockerTaskEngine) createContainer(task *apitask.Task, container *a
13771377
fluentNetworkPort: FluentNetworkPortValue,
13781378
})
13791379
} else if container.GetNetworkModeFromHostConfig() == "" || container.GetNetworkModeFromHostConfig() == apitask.BridgeNetworkMode {
1380-
ipAddress, ok := getContainerHostIP(task.GetFirelensContainer().GetNetworkSettings())
1380+
targetContainer := task.GetFirelensContainer()
1381+
// For bridge-mode ServiceConnect-enabled tasks, we inject pause container for each application container
1382+
// including the firelens container. Therefore, when resolving the container IP, we should be checking that
1383+
// of the associated pause container.
1384+
if task.IsServiceConnectEnabled() {
1385+
var err error
1386+
targetContainer, err = task.GetBridgeModePauseContainerForTaskContainer(targetContainer)
1387+
if err != nil {
1388+
logger.Error("Failed to create container", logger.Fields{
1389+
field.TaskID: task.GetID(),
1390+
field.Container: container.Name,
1391+
field.Error: errors.New(fmt.Sprintf(
1392+
"container uses awsfirelens log driver but we failed to resolve Firelens bridge IP: %v", err)),
1393+
})
1394+
return dockerapi.DockerContainerMetadata{
1395+
Error: dockerapi.CannotCreateContainerError{FromError: errors.New(fmt.Sprintf(
1396+
"failed to create container - container uses awsfirelens log driver but we failed to "+
1397+
"resolve Firelens bridge IP: %v", err))},
1398+
}
1399+
}
1400+
}
1401+
ipAddress, ok := getContainerHostIP(targetContainer.GetNetworkSettings())
13811402
if !ok {
13821403
err := apierrors.DockerClientConfigError{Msg: "unable to get BridgeIP for task in bridge mode"}
13831404
return dockerapi.DockerContainerMetadata{Error: apierrors.NamedError(&err)}
@@ -1629,34 +1650,68 @@ func (engine *DockerTaskEngine) startContainer(task *apitask.Task, container *ap
16291650
// If container is a firelens container, fluent host is needed to be added to the environment variable for the task.
16301651
// For the supported network mode - bridge and awsvpc, the awsvpc take the host 127.0.0.1 but in bridge mode,
16311652
// there is a need to wait for the IP to be present before the container using the firelens can be created.
1632-
if container.GetFirelensConfig() != nil {
1633-
if !task.IsNetworkModeAWSVPC() && (container.GetNetworkModeFromHostConfig() == "" || container.GetNetworkModeFromHostConfig() == apitask.BridgeNetworkMode) {
1634-
_, gotContainerIP := getContainerHostIP(dockerContainerMD.NetworkSettings)
1635-
if !gotContainerIP {
1636-
getIPBridgeBackoff := retry.NewExponentialBackoff(minGetIPBridgeTimeout, maxGetIPBridgeTimeout, getIPBridgeRetryJitterMultiplier, getIPBridgeRetryDelayMultiplier)
1637-
contextWithTimeout, cancel := context.WithTimeout(engine.ctx, time.Minute)
1638-
defer cancel()
1639-
err := retry.RetryWithBackoffCtx(contextWithTimeout, getIPBridgeBackoff, func() error {
1653+
//
1654+
// For bridge-mode ServiceConnect-enabled tasks, we inject pause container for each application container
1655+
// including the firelens container. Therefore, when resolving the container IP, we should be checking that
1656+
// of the associated pause container. In such case, the firelens container has network mode "container" since it's
1657+
// launched into its pause container's network namespace.
1658+
if container.GetFirelensConfig() != nil && task.IsNetworkModeBridge() {
1659+
_, gotContainerIP := getContainerHostIP(dockerContainerMD.NetworkSettings)
1660+
if task.IsServiceConnectEnabled() {
1661+
targetContainer, err := task.GetBridgeModePauseContainerForTaskContainer(container)
1662+
if err != nil {
1663+
logger.Error("Failed to start Firelens container", logger.Fields{
1664+
field.TaskID: task.GetID(),
1665+
field.Container: container.Name,
1666+
field.Error: err,
1667+
})
1668+
return dockerapi.DockerContainerMetadata{
1669+
Error: dockerapi.CannotStartContainerError{FromError: errors.New(fmt.Sprintf(
1670+
"failed to start firelens container: %v", err))},
1671+
}
1672+
}
1673+
_, gotContainerIP = getContainerHostIP(targetContainer.GetNetworkSettings())
1674+
}
1675+
1676+
if !gotContainerIP {
1677+
getIPBridgeBackoff := retry.NewExponentialBackoff(minGetIPBridgeTimeout, maxGetIPBridgeTimeout, getIPBridgeRetryJitterMultiplier, getIPBridgeRetryDelayMultiplier)
1678+
contextWithTimeout, cancel := context.WithTimeout(engine.ctx, time.Minute)
1679+
defer cancel()
1680+
err := retry.RetryWithBackoffCtx(contextWithTimeout, getIPBridgeBackoff, func() error {
1681+
gotIPBridge := false
1682+
if task.IsServiceConnectEnabled() {
1683+
targetContainer, err := task.GetBridgeModePauseContainerForTaskContainer(container)
1684+
if err != nil {
1685+
return err
1686+
}
1687+
_, gotIPBridge = getContainerHostIP(targetContainer.GetNetworkSettings())
1688+
if gotIPBridge {
1689+
return nil
1690+
}
1691+
} else {
16401692
inspectOutput, err := engine.client.InspectContainer(engine.ctx, dockerContainerMD.DockerID,
16411693
dockerclient.InspectContainerTimeout)
16421694
if err != nil {
16431695
return err
16441696
}
1645-
_, gotIPBridge := getContainerHostIP(inspectOutput.NetworkSettings)
1697+
_, gotIPBridge = getContainerHostIP(inspectOutput.NetworkSettings)
16461698
if gotIPBridge {
16471699
dockerContainerMD.NetworkSettings = inspectOutput.NetworkSettings
16481700
return nil
1649-
} else {
1650-
return errors.New("Bridge IP not available to use for firelens")
16511701
}
1702+
}
1703+
return errors.New("Bridge IP not available to use for firelens")
1704+
})
1705+
if err != nil {
1706+
logger.Error("Failed to start Firelens container", logger.Fields{
1707+
field.TaskID: task.GetID(),
1708+
field.Container: container.Name,
1709+
field.Error: err,
16521710
})
1653-
if err != nil {
1654-
return dockerapi.DockerContainerMetadata{
1655-
Error: dockerapi.CannotStartContainerError{FromError: err},
1656-
}
1711+
return dockerapi.DockerContainerMetadata{
1712+
Error: dockerapi.CannotStartContainerError{FromError: err},
16571713
}
16581714
}
1659-
16601715
}
16611716
}
16621717
if execcmd.IsExecEnabledContainer(container) {

0 commit comments

Comments
 (0)