improved containerized CI/CD environments, sensor-ipc-mode and sensor-ipc-endpoint for build and profile

This commit is contained in:
Kyle Quest 2022-01-06 00:48:44 -08:00
parent 3f30e81f24
commit 6f1bf2b36c
11 changed files with 127 additions and 35 deletions

View File

@ -504,6 +504,8 @@ In the interactive CLI prompt mode you must specify the target image using the `
- `--remove-expose` - Remove EXPOSE instructions for the optimized image
- `--exec` - A shell script snippet to run via Docker exec
- `--exec-file` - A shell script file to run via Docker exec
- `--sensor-ipc-mode` - Select sensor IPC mode: proxy | direct (useful for containerized CI/CD environments)
- `--sensor-ipc-endpoint` - Override sensor IPC endpoint
In the interactive CLI prompt mode you must specify the target image using the `--target` flag while in the traditional CLI mode you can use the `--target` flag or you can specify the target image as the last value in the command.

View File

@ -144,6 +144,9 @@ var CLI = &cli.Command{
commands.Cflag(commands.FlagContinueAfter),
commands.Cflag(commands.FlagUseLocalMounts),
commands.Cflag(commands.FlagUseSensorVolume),
//Sensor flags:
commands.Cflag(commands.FlagSensorIPCEndpoint),
commands.Cflag(commands.FlagSensorIPCMode),
},
Action: func(ctx *cli.Context) error {
xc := app.NewExecutionContext(Name)
@ -690,6 +693,8 @@ var CLI = &cli.Command{
execCmd,
string(execFileCmd),
deleteFatImage,
ctx.String(commands.FlagSensorIPCEndpoint),
ctx.String(commands.FlagSensorIPCMode),
ctx.String(commands.FlagLogLevel),
ctx.String(commands.FlagLogFormat))

View File

@ -158,6 +158,8 @@ func OnCommand(
execCmd string,
execFileCmd string,
deleteFatImage bool,
sensorIPCEndpoint string,
sensorIPCMode string,
logLevel string,
logFormat string) {
@ -948,6 +950,8 @@ func OnCommand(
logLevel,
logFormat,
gparams.InContainer,
sensorIPCEndpoint,
sensorIPCMode,
true,
prefix)
xc.FailOn(err)
@ -969,6 +973,10 @@ func OnCommand(
logger.Info("starting instrumented 'fat' container...")
err = containerInspector.RunContainer()
if err != nil && containerInspector.DoShowContainerLogs {
containerInspector.ShowContainerLogs()
}
xc.FailOn(err)
inspectorCleanup := func() {

View File

@ -122,6 +122,8 @@ var CommandFlagSuggestions = &commands.FlagSuggestions{
{Text: commands.FullFlagName(FlagCBOTarget), Description: FlagCBOTargetUsage},
{Text: commands.FullFlagName(FlagCBONetwork), Description: FlagCBONetworkUsage},
{Text: commands.FullFlagName(FlagCBOCacheFrom), Description: FlagCBOCacheFromUsage},
{Text: commands.FullFlagName(commands.FlagSensorIPCMode), Description: commands.FlagSensorIPCModeUsage},
{Text: commands.FullFlagName(commands.FlagSensorIPCEndpoint), Description: commands.FlagSensorIPCEndpointUsage},
},
Values: map[string]commands.CompleteValue{
//NOTE: with FlagPull target complete needs to check remote registries too
@ -168,5 +170,6 @@ var CommandFlagSuggestions = &commands.FlagSuggestions{
commands.FullFlagName(FlagKeepTmpArtifacts): commands.CompleteBool,
commands.FullFlagName(commands.FlagCROHostConfigFile): commands.CompleteFile,
commands.FullFlagName(FlagDockerfileContext): commands.CompleteFile,
commands.FullFlagName(commands.FlagSensorIPCMode): commands.CompleteIPCMode,
},
}

View File

@ -110,6 +110,10 @@ const (
FlagUseSensorVolume = "use-sensor-volume"
FlagContinueAfter = "continue-after"
//Sensor IPC Options (for build and profile commands)
FlagSensorIPCEndpoint = "sensor-ipc-endpoint"
FlagSensorIPCMode = "sensor-ipc-mode"
FlagExec = "exec"
FlagExecFile = "exec-file"
@ -201,6 +205,9 @@ const (
FlagUseSensorVolumeUsage = "Sensor volume name to use"
FlagContinueAfterUsage = "Select continue mode: enter | signal | probe | timeout-number-in-seconds | container.probe"
FlagSensorIPCEndpointUsage = "Override sensor IPC endpoint"
FlagSensorIPCModeUsage = "Select sensor IPC mode: proxy | direct"
FlagExecUsage = "A shell script snippet to run via Docker exec"
FlagExecFileUsage = "A shell script file to run via Docker exec"
@ -580,6 +587,18 @@ var CommonFlags = map[string]cli.Flag{
Usage: FlagShowContainerLogsUsage,
EnvVars: []string{"DSLIM_SHOW_CLOGS"},
},
FlagSensorIPCMode: &cli.StringFlag{
Name: FlagSensorIPCMode,
Value: "",
Usage: FlagSensorIPCModeUsage,
EnvVars: []string{"DSLIM_SENSOR_IPC_MODE"},
},
FlagSensorIPCEndpoint: &cli.StringFlag{
Name: FlagSensorIPCEndpoint,
Value: "",
Usage: FlagSensorIPCEndpointUsage,
EnvVars: []string{"DSLIM_SENSOR_IPC_ENDPOINT"},
},
FlagExec: &cli.StringFlag{
Name: FlagExec,
Value: "",

View File

@ -244,6 +244,11 @@ var continueAfterValues = []prompt.Suggest{
{Text: "<seconds>", Description: "Enter the number of seconds to wait instead of <seconds>"},
}
var ipcModeValues = []prompt.Suggest{
{Text: "proxy", Description: "Proxy sensor ipc mode"},
{Text: "direct", Description: "Direct sensor ipc mode"},
}
func CompleteProgress(ia *InteractiveApp, token string, params prompt.Document) []prompt.Suggest {
switch runtime.GOOS {
case "darwin":
@ -265,6 +270,10 @@ func CompleteContinueAfter(ia *InteractiveApp, token string, params prompt.Docum
return prompt.FilterHasPrefix(continueAfterValues, token, true)
}
func CompleteIPCMode(ia *InteractiveApp, token string, params prompt.Document) []prompt.Suggest {
return prompt.FilterHasPrefix(ipcModeValues, token, true)
}
func CompleteTarget(ia *InteractiveApp, token string, params prompt.Document) []prompt.Suggest {
images, err := dockerutil.ListImages(ia.dclient, "")
if err != nil {

View File

@ -90,19 +90,14 @@ var CLI = &cli.Command{
commands.Cflag(commands.FlagHostname),
commands.Cflag(commands.FlagExpose),
commands.Cflag(commands.FlagExcludeMounts),
commands.Cflag(commands.FlagExcludePattern),
//commands.Cflag(commands.FlagPathPerms),
//commands.Cflag(commands.FlagPathPermsFile),
//commands.Cflag(commands.FlagIncludePath),
//commands.Cflag(commands.FlagIncludePathFile),
//commands.Cflag(commands.FlagIncludeBin),
//commands.Cflag(commands.FlagIncludeExe),
//commands.Cflag(commands.FlagIncludeShell),
commands.Cflag(commands.FlagExcludePattern), //should remove too (no need)
commands.Cflag(commands.FlagMount),
commands.Cflag(commands.FlagContinueAfter),
commands.Cflag(commands.FlagUseLocalMounts),
commands.Cflag(commands.FlagUseSensorVolume),
//commands.Cflag(commands.FlagKeepTmpArtifacts),
//Sensor flags:
commands.Cflag(commands.FlagSensorIPCEndpoint),
commands.Cflag(commands.FlagSensorIPCMode),
},
Action: func(ctx *cli.Context) error {
xc := app.NewExecutionContext(Name)
@ -406,6 +401,8 @@ var CLI = &cli.Command{
doUseSensorVolume,
//doKeepTmpArtifacts,
continueAfter,
ctx.String(commands.FlagSensorIPCEndpoint),
ctx.String(commands.FlagSensorIPCMode),
ctx.String(commands.FlagLogLevel),
ctx.String(commands.FlagLogFormat))

View File

@ -86,6 +86,8 @@ func OnCommand(
doUseSensorVolume string,
//doKeepTmpArtifacts bool,
continueAfter *config.ContinueAfter,
sensorIPCEndpoint string,
sensorIPCMode string,
logLevel string,
logFormat string) {
const cmdName = Name
@ -270,6 +272,8 @@ func OnCommand(
logLevel,
logFormat,
gparams.InContainer,
sensorIPCEndpoint,
sensorIPCMode,
true,
prefix)
errutil.FailOn(err)

View File

@ -62,18 +62,12 @@ var CommandFlagSuggestions = &commands.FlagSuggestions{
{Text: commands.FullFlagName(commands.FlagExpose), Description: commands.FlagExposeUsage},
{Text: commands.FullFlagName(commands.FlagExcludeMounts), Description: commands.FlagExcludeMountsUsage},
{Text: commands.FullFlagName(commands.FlagExcludePattern), Description: commands.FlagExcludePatternUsage},
//{Text: commands.FullFlagName(commands.FlagPathPerms), Description: commands.FlagPathPermsUsage},
//{Text: commands.FullFlagName(commands.FlagPathPermsFile), Description: commands.FlagPathPermsFileUsage},
//{Text: commands.FullFlagName(commands.FlagIncludePath), Description: commands.FlagIncludePathUsage},
//{Text: commands.FullFlagName(commands.FlagIncludePathFile), Description: commands.FlagIncludePathFileUsage},
//{Text: commands.FullFlagName(commands.FlagIncludeBin), Description: commands.FlagIncludeBinUsage},
//{Text: commands.FullFlagName(commands.FlagIncludeExe), Description: commands.FlagIncludeExeUsage},
//{Text: commands.FullFlagName(commands.FlagIncludeShell), Description: commands.FlagIncludeShellUsage},
{Text: commands.FullFlagName(commands.FlagMount), Description: commands.FlagMountUsage},
{Text: commands.FullFlagName(commands.FlagContinueAfter), Description: commands.FlagContinueAfterUsage},
{Text: commands.FullFlagName(commands.FlagUseLocalMounts), Description: commands.FlagUseLocalMountsUsage},
{Text: commands.FullFlagName(commands.FlagUseSensorVolume), Description: commands.FlagUseSensorVolumeUsage},
//{Text: commands.FullFlagName(commands.FlagKeepTmpArtifacts), Description: commands.FlagKeepTmpArtifactsUsage},
{Text: commands.FullFlagName(commands.FlagSensorIPCMode), Description: commands.FlagSensorIPCModeUsage},
{Text: commands.FullFlagName(commands.FlagSensorIPCEndpoint), Description: commands.FlagSensorIPCEndpointUsage},
},
Values: map[string]commands.CompleteValue{
commands.FullFlagName(commands.FlagPull): commands.CompleteBool,
@ -102,5 +96,6 @@ var CommandFlagSuggestions = &commands.FlagSuggestions{
commands.FullFlagName(commands.FlagUseSensorVolume): commands.CompleteVolume,
//commands.FullFlagName(commands.FlagKeepTmpArtifacts): commands.CompleteBool,
commands.FullFlagName(commands.FlagCROHostConfigFile): commands.CompleteFile,
commands.FullFlagName(commands.FlagSensorIPCMode): commands.CompleteIPCMode,
},
}

View File

@ -35,6 +35,8 @@ import (
// Container inspector constants
const (
SensorIPCModeDirect = "direct"
SensorIPCModeProxy = "proxy"
SensorBinPath = "/opt/dockerslim/bin/docker-slim-sensor"
ContainerNamePat = "dockerslimk_%v_%v"
ArtifactsDir = "artifacts"
@ -127,6 +129,9 @@ type Inspector struct {
PrintState bool
PrintPrefix string
InContainer bool
SensorIPCEndpoint string
SensorIPCMode string
TargetHost string
dockerEventCh chan *dockerapi.APIEvents
dockerEventStopCh chan struct{}
ipcClient *ipc.Client
@ -193,6 +198,8 @@ func NewInspector(
logLevel string,
logFormat string,
inContainer bool,
sensorIPCEndpoint string,
sensorIPCMode string,
printState bool,
printPrefix string) (*Inspector, error) {
@ -242,6 +249,8 @@ func NewInspector(
PrintState: printState,
PrintPrefix: printPrefix,
InContainer: inContainer,
SensorIPCEndpoint: sensorIPCEndpoint,
SensorIPCMode: sensorIPCMode,
xc: xc,
crOpts: crOpts,
}
@ -742,7 +751,6 @@ func (i *Inspector) RunContainer() error {
}
i.ContainerID = containerInfo.ID
if i.PrintState {
i.xc.Out.Info("container",
ovars{
@ -863,6 +871,20 @@ func (i *Inspector) RunContainer() error {
i.ContainerPortsInfo = strings.Join(portKeys, ",")
}
if i.PrintState {
var containerIP string
if i.ContainerInfo.NetworkSettings != nil {
containerIP = i.ContainerInfo.NetworkSettings.IPAddress
}
i.xc.Out.Info("container",
ovars{
"status": "running",
"name": containerInfo.Name,
"id": i.ContainerID,
"ip": containerIP,
})
}
if err = i.initContainerChannels(); err != nil {
return err
}
@ -1131,25 +1153,58 @@ func (i *Inspector) FinishMonitoring() {
}
func (i *Inspector) initContainerChannels() error {
var targetHost string
const op = "container.Inspector.initContainerChannels"
var cmdPort string
var evtPort string
var ipcMode string
var cn string
if i.InContainer || i.Overrides.Network == "host" {
targetHost = i.ContainerInfo.NetworkSettings.IPAddress
if i.Overrides != nil {
cn = i.Overrides.Network
}
switch i.SensorIPCMode {
case SensorIPCModeDirect, SensorIPCModeProxy:
ipcMode = i.SensorIPCMode
default:
if i.InContainer || cn == "host" {
ipcMode = SensorIPCModeDirect
} else {
ipcMode = SensorIPCModeProxy
}
}
switch ipcMode {
case SensorIPCModeDirect:
i.TargetHost = i.ContainerInfo.NetworkSettings.IPAddress
cmdPort = cmdPortStrDefault
evtPort = evtPortStrDefault
} else {
case SensorIPCModeProxy:
i.DockerHostIP = dockerhost.GetIP()
i.TargetHost = i.DockerHostIP
cmdPortBindings := i.ContainerInfo.NetworkSettings.Ports[i.CmdPort]
evtPortBindings := i.ContainerInfo.NetworkSettings.Ports[i.EvtPort]
i.DockerHostIP = dockerhost.GetIP()
targetHost = i.DockerHostIP
cmdPort = cmdPortBindings[0].HostPort
evtPort = evtPortBindings[0].HostPort
}
ipcClient, err := ipc.NewClient(targetHost, cmdPort, evtPort, defaultConnectWait)
i.SensorIPCMode = ipcMode
if i.SensorIPCEndpoint != "" {
i.TargetHost = i.SensorIPCEndpoint
}
i.logger.WithFields(log.Fields{
"op": op,
"in.container": i.InContainer,
"container.network": cn,
"ipc.mode": ipcMode,
"target": i.TargetHost,
"port.cmd": cmdPort,
"port.evt": evtPort,
}).Debugf("target.container.ipc.connect")
ipcClient, err := ipc.NewClient(i.TargetHost, cmdPort, evtPort, defaultConnectWait)
if err != nil {
return err
}

View File

@ -153,7 +153,7 @@ func NewCustomProbe(
for _, pnum := range probe.TargetPorts {
pspec := dockerapi.Port(fmt.Sprintf("%v/tcp", pnum))
if _, ok := inspector.ContainerInfo.NetworkSettings.Ports[pspec]; ok {
if inspector.InContainer {
if inspector.SensorIPCMode == container.SensorIPCModeDirect {
probe.Ports = append(probe.Ports, fmt.Sprintf("%d", pnum))
} else {
probe.Ports = append(probe.Ports, inspector.ContainerInfo.NetworkSettings.Ports[pspec][0].HostPort)
@ -176,7 +176,7 @@ func NewCustomProbe(
if _, ok := inspector.ContainerInfo.NetworkSettings.Ports[pspec]; ok {
hostPort := inspector.ContainerInfo.NetworkSettings.Ports[pspec][0].HostPort
if inspector.InContainer {
if inspector.SensorIPCMode == container.SensorIPCModeDirect {
if containerPort := availableHostPorts[hostPort]; containerPort != "" {
probe.Ports = append(probe.Ports, containerPort)
} else {
@ -197,7 +197,7 @@ func NewCustomProbe(
}
for hostPort, containerPort := range availableHostPorts {
if inspector.InContainer {
if inspector.SensorIPCMode == container.SensorIPCModeDirect {
probe.Ports = append(probe.Ports, containerPort)
} else {
probe.Ports = append(probe.Ports, hostPort)
@ -336,12 +336,7 @@ func (p *CustomProbe) Start() {
}
for _, proto := range protocols {
var targetHost string
if p.ContainerInspector.InContainer {
targetHost = p.ContainerInspector.ContainerInfo.NetworkSettings.IPAddress
} else {
targetHost = p.ContainerInspector.DockerHostIP
}
targetHost := p.ContainerInspector.TargetHost
maxRetryCount := probeRetryCount
if p.RetryCount > 0 {