diff --git a/build/integration.sh b/build/integration.sh index 951434d048..c871318e2f 100755 --- a/build/integration.sh +++ b/build/integration.sh @@ -27,7 +27,7 @@ function start { set +e # We want to handle errors if cAdvisor crashes. echo ">> starting cAdvisor locally" # This cpuset, percpu, memory, disk, diskIO, network, perf_event metrics should be enabled. - GORACE="halt_on_error=1" ./cadvisor --enable_metrics="cpuset,percpu,memory,disk,diskIO,network,perf_event" --docker_env_metadata_whitelist=TEST_VAR --v=6 --logtostderr $CADVISOR_ARGS &> "$log_file" + GORACE="halt_on_error=1" ./cadvisor --enable_metrics="cpuset,percpu,memory,disk,diskIO,network,perf_event" --env_metadata_whitelist=TEST_VAR --v=6 --logtostderr $CADVISOR_ARGS &> "$log_file" if [ $? != 0 ]; then echo "!! cAdvisor exited unexpectedly with Exit $?" kill $TEST_PID # cAdvisor crashed: abort testing. diff --git a/cmd/cadvisor.go b/cmd/cadvisor.go index 458210feef..7ded915d01 100644 --- a/cmd/cadvisor.go +++ b/cmd/cadvisor.go @@ -65,6 +65,8 @@ var collectorKey = flag.String("collector_key", "", "Key for the collector's cer var storeContainerLabels = flag.Bool("store_container_labels", true, "convert container labels and environment variables into labels on prometheus metrics for each container. If flag set to false, then only metrics exported are container name, first alias, and image name") var whitelistedContainerLabels = flag.String("whitelisted_container_labels", "", "comma separated list of container labels to be converted to labels on prometheus metrics for each container. store_container_labels must be set to false for this to take effect.") +var envMetadataWhiteList = flag.String("env_metadata_whitelist", "", "a comma-separated list of environment variable keys matched with specified prefix that needs to be collected for containers, only support containerd and docker runtime for now.") + var urlBasePrefix = flag.String("url_base_prefix", "", "prefix path that will be prepended to all paths to support some reverse proxies") var rawCgroupPrefixWhiteList = flag.String("raw_cgroup_prefix_whitelist", "", "A comma-separated list of cgroup path prefix that needs to be collected even when -docker_only is specified") @@ -129,7 +131,7 @@ func main() { collectorHttpClient := createCollectorHttpClient(*collectorCert, *collectorKey) - resourceManager, err := manager.New(memoryStorage, sysFs, manager.HousekeepingConfigFlags, includedMetrics, &collectorHttpClient, strings.Split(*rawCgroupPrefixWhiteList, ","), *perfEvents) + resourceManager, err := manager.New(memoryStorage, sysFs, manager.HousekeepingConfigFlags, includedMetrics, &collectorHttpClient, strings.Split(*rawCgroupPrefixWhiteList, ","), strings.Split(*envMetadataWhiteList, ","), *perfEvents) if err != nil { klog.Fatalf("Failed to create a manager: %s", err) } diff --git a/cmd/internal/container/mesos/factory.go b/cmd/internal/container/mesos/factory.go index e339310507..1b6f66b49c 100644 --- a/cmd/internal/container/mesos/factory.go +++ b/cmd/internal/container/mesos/factory.go @@ -59,7 +59,7 @@ func (f *mesosFactory) String() string { return MesosNamespace } -func (f *mesosFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) { +func (f *mesosFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (container.ContainerHandler, error) { client, err := Client() if err != nil { return nil, err @@ -72,6 +72,7 @@ func (f *mesosFactory) NewContainerHandler(name string, inHostNamespace bool) (c f.fsInfo, f.includedMetrics, inHostNamespace, + metadataEnvAllowList, client, ) } diff --git a/cmd/internal/container/mesos/handler.go b/cmd/internal/container/mesos/handler.go index f9685ac933..2d18c985cc 100644 --- a/cmd/internal/container/mesos/handler.go +++ b/cmd/internal/container/mesos/handler.go @@ -57,6 +57,7 @@ func newMesosContainerHandler( fsInfo fs.FsInfo, includedMetrics container.MetricSet, inHostNamespace bool, + metadataEnvAllowList []string, client mesosAgentClient, ) (container.ContainerHandler, error) { cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name) diff --git a/cmd/internal/container/mesos/handler_test.go b/cmd/internal/container/mesos/handler_test.go index daee1c12aa..081fdcddb3 100644 --- a/cmd/internal/container/mesos/handler_test.go +++ b/cmd/internal/container/mesos/handler_test.go @@ -37,13 +37,14 @@ func PopulateContainer() *mContainer { func TestContainerReference(t *testing.T) { as := assert.New(t) type testCase struct { - client mesosAgentClient - name string - machineInfoFactory info.MachineInfoFactory - fsInfo fs.FsInfo - cgroupSubsystems *containerlibcontainer.CgroupSubsystems - inHostNamespace bool - includedMetrics container.MetricSet + client mesosAgentClient + name string + machineInfoFactory info.MachineInfoFactory + fsInfo fs.FsInfo + cgroupSubsystems *containerlibcontainer.CgroupSubsystems + inHostNamespace bool + metadataEnvAllowList []string + includedMetrics container.MetricSet hasErr bool errContains string @@ -57,6 +58,7 @@ func TestContainerReference(t *testing.T) { nil, &containerlibcontainer.CgroupSubsystems{}, false, + []string{}, nil, true, @@ -70,6 +72,7 @@ func TestContainerReference(t *testing.T) { nil, &containerlibcontainer.CgroupSubsystems{}, false, + []string{}, nil, true, @@ -83,6 +86,7 @@ func TestContainerReference(t *testing.T) { nil, &containerlibcontainer.CgroupSubsystems{}, false, + []string{}, nil, false, @@ -95,7 +99,7 @@ func TestContainerReference(t *testing.T) { }, }, } { - handler, err := newMesosContainerHandler(ts.name, ts.cgroupSubsystems, ts.machineInfoFactory, ts.fsInfo, ts.includedMetrics, ts.inHostNamespace, ts.client) + handler, err := newMesosContainerHandler(ts.name, ts.cgroupSubsystems, ts.machineInfoFactory, ts.fsInfo, ts.includedMetrics, ts.inHostNamespace, ts.metadataEnvAllowList, ts.client) if ts.hasErr { as.NotNil(err) if ts.errContains != "" { diff --git a/container/containerd/factory.go b/container/containerd/factory.go index e968c5045e..d8bebb71a2 100644 --- a/container/containerd/factory.go +++ b/container/containerd/factory.go @@ -34,6 +34,8 @@ import ( var ArgContainerdEndpoint = flag.String("containerd", "/run/containerd/containerd.sock", "containerd endpoint") var ArgContainerdNamespace = flag.String("containerd-namespace", "k8s.io", "containerd namespace") +var containerdEnvMetadataWhiteList = flag.String("containerd_env_metadata_whitelist", "", "DEPRECATED: this flag will be removed, please use `env_metadata_whitelist`. A comma-separated list of environment variable keys matched with specified prefix that needs to be collected for containerd containers") + // The namespace under which containerd aliases are unique. const k8sContainerdNamespace = "containerd" @@ -41,8 +43,6 @@ const k8sContainerdNamespace = "containerd" // --cgroup-parent have another prefix than 'containerd' var containerdCgroupRegexp = regexp.MustCompile(`([a-z0-9]{64})`) -var containerdEnvWhitelist = flag.String("containerd_env_metadata_whitelist", "", "a comma-separated list of environment variable keys matched with specified prefix that needs to be collected for containerd containers") - type containerdFactory struct { machineInfoFactory info.MachineInfoFactory client ContainerdClient @@ -58,13 +58,18 @@ func (f *containerdFactory) String() string { return k8sContainerdNamespace } -func (f *containerdFactory) NewContainerHandler(name string, inHostNamespace bool) (handler container.ContainerHandler, err error) { +func (f *containerdFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (handler container.ContainerHandler, err error) { client, err := Client(*ArgContainerdEndpoint, *ArgContainerdNamespace) if err != nil { return } - metadataEnvs := strings.Split(*containerdEnvWhitelist, ",") + containerdMetadataEnvAllowList := strings.Split(*containerdEnvMetadataWhiteList, ",") + + // prefer using the unified metadataEnvAllowList + if len(metadataEnvAllowList) != 0 { + containerdMetadataEnvAllowList = metadataEnvAllowList + } return newContainerdContainerHandler( client, @@ -73,7 +78,7 @@ func (f *containerdFactory) NewContainerHandler(name string, inHostNamespace boo f.fsInfo, &f.cgroupSubsystems, inHostNamespace, - metadataEnvs, + containerdMetadataEnvAllowList, f.includedMetrics, ) } diff --git a/container/containerd/handler.go b/container/containerd/handler.go index a8be0acbef..04981442b0 100644 --- a/container/containerd/handler.go +++ b/container/containerd/handler.go @@ -60,7 +60,7 @@ func newContainerdContainerHandler( fsInfo fs.FsInfo, cgroupSubsystems *containerlibcontainer.CgroupSubsystems, inHostNamespace bool, - metadataEnvs []string, + metadataEnvAllowList []string, includedMetrics container.MetricSet, ) (container.ContainerHandler, error) { // Create the cgroup paths. @@ -134,9 +134,9 @@ func newContainerdContainerHandler( // Add the name and bare ID as aliases of the container. handler.image = cntr.Image - for _, exposedEnv := range metadataEnvs { + for _, exposedEnv := range metadataEnvAllowList { if exposedEnv == "" { - // if no containerdEnvWhitelist provided, len(metadataEnvs) == 1, metadataEnvs[0] == "" + // if no containerdEnvWhitelist provided, len(metadataEnvAllowList) == 1, metadataEnvAllowList[0] == "" continue } diff --git a/container/containerd/handler_test.go b/container/containerd/handler_test.go index edcf6339a5..85f7559c94 100644 --- a/container/containerd/handler_test.go +++ b/container/containerd/handler_test.go @@ -45,14 +45,14 @@ func (m *mockedMachineInfo) GetVersionInfo() (*info.VersionInfo, error) { func TestHandler(t *testing.T) { as := assert.New(t) type testCase struct { - client ContainerdClient - name string - machineInfoFactory info.MachineInfoFactory - fsInfo fs.FsInfo - cgroupSubsystems *containerlibcontainer.CgroupSubsystems - inHostNamespace bool - metadataEnvs []string - includedMetrics container.MetricSet + client ContainerdClient + name string + machineInfoFactory info.MachineInfoFactory + fsInfo fs.FsInfo + cgroupSubsystems *containerlibcontainer.CgroupSubsystems + inHostNamespace bool + metadataEnvAllowList []string + includedMetrics container.MetricSet hasErr bool errContains string @@ -121,7 +121,7 @@ func TestHandler(t *testing.T) { map[string]string{"TEST_REGION": "FRA", "TEST_ZONE": "A"}, }, } { - handler, err := newContainerdContainerHandler(ts.client, ts.name, ts.machineInfoFactory, ts.fsInfo, ts.cgroupSubsystems, ts.inHostNamespace, ts.metadataEnvs, ts.includedMetrics) + handler, err := newContainerdContainerHandler(ts.client, ts.name, ts.machineInfoFactory, ts.fsInfo, ts.cgroupSubsystems, ts.inHostNamespace, ts.metadataEnvAllowList, ts.includedMetrics) if ts.hasErr { as.NotNil(err) if ts.errContains != "" { diff --git a/container/crio/factory.go b/container/crio/factory.go index 32f607680f..fd61168c4b 100644 --- a/container/crio/factory.go +++ b/container/crio/factory.go @@ -64,13 +64,11 @@ func (f *crioFactory) String() string { return CrioNamespace } -func (f *crioFactory) NewContainerHandler(name string, inHostNamespace bool) (handler container.ContainerHandler, err error) { +func (f *crioFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (handler container.ContainerHandler, err error) { client, err := Client() if err != nil { return } - // TODO are there any env vars we need to white list, if so, do it here... - metadataEnvs := []string{} handler, err = newCrioContainerHandler( client, name, @@ -80,7 +78,7 @@ func (f *crioFactory) NewContainerHandler(name string, inHostNamespace bool) (ha f.storageDir, &f.cgroupSubsystems, inHostNamespace, - metadataEnvs, + metadataEnvAllowList, f.includedMetrics, ) return diff --git a/container/crio/handler.go b/container/crio/handler.go index b1ef5b045d..3a4ef0c85a 100644 --- a/container/crio/handler.go +++ b/container/crio/handler.go @@ -85,7 +85,7 @@ func newCrioContainerHandler( storageDir string, cgroupSubsystems *containerlibcontainer.CgroupSubsystems, inHostNamespace bool, - metadataEnvs []string, + metadataEnvAllowList []string, includedMetrics container.MetricSet, ) (container.ContainerHandler, error) { // Create the cgroup paths. @@ -186,7 +186,7 @@ func newCrioContainerHandler( handler.fsHandler = common.NewFsHandler(common.DefaultPeriod, rootfsStorageDir, storageLogDir, fsInfo) } // TODO for env vars we wanted to show from container.Config.Env from whitelist - //for _, exposedEnv := range metadataEnvs { + //for _, exposedEnv := range metadataEnvAllowList { //klog.V(4).Infof("TODO env whitelist: %v", exposedEnv) //} diff --git a/container/crio/handler_test.go b/container/crio/handler_test.go index 86edd656c0..3bbba54052 100644 --- a/container/crio/handler_test.go +++ b/container/crio/handler_test.go @@ -28,16 +28,16 @@ import ( func TestHandler(t *testing.T) { as := assert.New(t) type testCase struct { - client CrioClient - name string - machineInfoFactory info.MachineInfoFactory - fsInfo fs.FsInfo - storageDriver storageDriver - storageDir string - cgroupSubsystems *containerlibcontainer.CgroupSubsystems - inHostNamespace bool - metadataEnvs []string - includedMetrics container.MetricSet + client CrioClient + name string + machineInfoFactory info.MachineInfoFactory + fsInfo fs.FsInfo + storageDriver storageDriver + storageDir string + cgroupSubsystems *containerlibcontainer.CgroupSubsystems + inHostNamespace bool + metadataEnvAllowList []string + includedMetrics container.MetricSet hasErr bool errContains string @@ -102,7 +102,7 @@ func TestHandler(t *testing.T) { }, }, } { - handler, err := newCrioContainerHandler(ts.client, ts.name, ts.machineInfoFactory, ts.fsInfo, ts.storageDriver, ts.storageDir, ts.cgroupSubsystems, ts.inHostNamespace, ts.metadataEnvs, ts.includedMetrics) + handler, err := newCrioContainerHandler(ts.client, ts.name, ts.machineInfoFactory, ts.fsInfo, ts.storageDriver, ts.storageDir, ts.cgroupSubsystems, ts.inHostNamespace, ts.metadataEnvAllowList, ts.includedMetrics) if ts.hasErr { as.NotNil(err) if ts.errContains != "" { diff --git a/container/docker/factory.go b/container/docker/factory.go index 1490a88f41..69a3a8c3fd 100644 --- a/container/docker/factory.go +++ b/container/docker/factory.go @@ -47,21 +47,21 @@ var ArgDockerCert = flag.String("docker-tls-cert", "cert.pem", "path to client c var ArgDockerKey = flag.String("docker-tls-key", "key.pem", "path to private key") var ArgDockerCA = flag.String("docker-tls-ca", "ca.pem", "path to trusted CA") +var dockerEnvMetadataWhiteList = flag.String("docker_env_metadata_whitelist", "", "DEPRECATED: this flag will be removed, please use `env_metadata_whitelist`. A comma-separated list of environment variable keys matched with specified prefix that needs to be collected for docker containers") + // The namespace under which Docker aliases are unique. const DockerNamespace = "docker" // The retry times for getting docker root dir const rootDirRetries = 5 -//The retry period for getting docker root dir, Millisecond +// The retry period for getting docker root dir, Millisecond const rootDirRetryPeriod time.Duration = 1000 * time.Millisecond // Regexp that identifies docker cgroups, containers started with // --cgroup-parent have another prefix than 'docker' var dockerCgroupRegexp = regexp.MustCompile(`([a-z0-9]{64})`) -var dockerEnvWhitelist = flag.String("docker_env_metadata_whitelist", "", "a comma-separated list of environment variable keys matched with specified prefix that needs to be collected for docker containers") - var ( // Basepath to all container specific information that libcontainer stores. dockerRootDir string @@ -136,13 +136,18 @@ func (f *dockerFactory) String() string { return DockerNamespace } -func (f *dockerFactory) NewContainerHandler(name string, inHostNamespace bool) (handler container.ContainerHandler, err error) { +func (f *dockerFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (handler container.ContainerHandler, err error) { client, err := Client() if err != nil { return } - metadataEnvs := strings.Split(*dockerEnvWhitelist, ",") + dockerMetadataEnvAllowList := strings.Split(*dockerEnvMetadataWhiteList, ",") + + // prefer using the unified metadataEnvAllowList + if len(metadataEnvAllowList) != 0 { + dockerMetadataEnvAllowList = metadataEnvAllowList + } handler, err = newDockerContainerHandler( client, @@ -153,7 +158,7 @@ func (f *dockerFactory) NewContainerHandler(name string, inHostNamespace bool) ( f.storageDir, &f.cgroupSubsystems, inHostNamespace, - metadataEnvs, + dockerMetadataEnvAllowList, f.dockerVersion, f.includedMetrics, f.thinPoolName, diff --git a/container/docker/handler.go b/container/docker/handler.go index e9afc75244..8528cbcb07 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -123,7 +123,7 @@ func newDockerContainerHandler( storageDir string, cgroupSubsystems *containerlibcontainer.CgroupSubsystems, inHostNamespace bool, - metadataEnvs []string, + metadataEnvAllowList []string, dockerVersion []int, includedMetrics container.MetricSet, thinPoolName string, @@ -249,9 +249,9 @@ func newDockerContainerHandler( } // split env vars to get metadata map. - for _, exposedEnv := range metadataEnvs { + for _, exposedEnv := range metadataEnvAllowList { if exposedEnv == "" { - // if no dockerEnvWhitelist provided, len(metadataEnvs) == 1, metadataEnvs[0] == "" + // if no dockerEnvWhitelist provided, len(metadataEnvAllowList) == 1, metadataEnvAllowList[0] == "" continue } diff --git a/container/docker/handler_test.go b/container/docker/handler_test.go index ec549e74df..3eedb90c63 100644 --- a/container/docker/handler_test.go +++ b/container/docker/handler_test.go @@ -55,11 +55,11 @@ func TestStorageDirDetectionWithNewVersions(t *testing.T) { } func rawMetadataEnvMatch(dockerEnvWhiteList string, cntConfig container.Config) map[string]string { - metadataEnvs := strings.Split(dockerEnvWhiteList, ",") + metadataEnvAllowList := strings.Split(dockerEnvWhiteList, ",") handlerEnvs := make(map[string]string) // split env vars to get metadata map. - for _, exposedEnv := range metadataEnvs { + for _, exposedEnv := range metadataEnvAllowList { for _, envVar := range cntConfig.Env { if envVar != "" { splits := strings.SplitN(envVar, "=", 2) @@ -74,13 +74,13 @@ func rawMetadataEnvMatch(dockerEnvWhiteList string, cntConfig container.Config) } func newMetadataEnvMatch(dockerEnvWhiteList string, cntConfig container.Config) map[string]string { - metadataEnvs := strings.Split(dockerEnvWhiteList, ",") + metadataEnvAllowList := strings.Split(dockerEnvWhiteList, ",") handlerEnvs := make(map[string]string) // split env vars to get metadata map. - for _, exposedEnv := range metadataEnvs { + for _, exposedEnv := range metadataEnvAllowList { if exposedEnv == "" { - // if no dockerEnvWhitelist provided, len(metadataEnvs) == 1, metadataEnvs[0] == "" + // if no dockerEnvWhitelist provided, len(metadataEnvAllowList) == 1, metadataEnvAllowList[0] == "" continue } diff --git a/container/factory.go b/container/factory.go index c85fe0d17e..f2a86c266a 100644 --- a/container/factory.go +++ b/container/factory.go @@ -29,7 +29,7 @@ import ( type ContainerHandlerFactory interface { // Create a new ContainerHandler using this factory. CanHandleAndAccept() must have returned true. - NewContainerHandler(name string, inHostNamespace bool) (c ContainerHandler, err error) + NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (c ContainerHandler, err error) // Returns whether this factory can handle and accept the specified container. CanHandleAndAccept(name string) (handle bool, accept bool, err error) @@ -227,7 +227,7 @@ func HasFactories() bool { } // Create a new ContainerHandler for the specified container. -func NewContainerHandler(name string, watchType watcher.ContainerWatchSource, inHostNamespace bool) (ContainerHandler, bool, error) { +func NewContainerHandler(name string, watchType watcher.ContainerWatchSource, metadataEnvAllowList []string, inHostNamespace bool) (ContainerHandler, bool, error) { factoriesLock.RLock() defer factoriesLock.RUnlock() @@ -243,7 +243,7 @@ func NewContainerHandler(name string, watchType watcher.ContainerWatchSource, in return nil, false, nil } klog.V(3).Infof("Using factory %q for container %q", factory, name) - handle, err := factory.NewContainerHandler(name, inHostNamespace) + handle, err := factory.NewContainerHandler(name, metadataEnvAllowList, inHostNamespace) return handle, canAccept, err } klog.V(4).Infof("Factory %q was unable to handle container %q", factory, name) diff --git a/container/factory_test.go b/container/factory_test.go index d8a103f790..cb00a971f7 100644 --- a/container/factory_test.go +++ b/container/factory_test.go @@ -43,13 +43,15 @@ func (f *mockContainerHandlerFactory) CanHandleAndAccept(name string) (bool, boo return f.CanHandleValue, f.CanAcceptValue, nil } -func (f *mockContainerHandlerFactory) NewContainerHandler(name string, isHostNamespace bool) (container.ContainerHandler, error) { +func (f *mockContainerHandlerFactory) NewContainerHandler(name string, metadataEnvAllowList []string, isHostNamespace bool) (container.ContainerHandler, error) { args := f.Called(name) return args.Get(0).(container.ContainerHandler), args.Error(1) } const testContainerName = "/test" +var testMetadataEnvAllowList = []string{} + var mockFactory containertest.FactoryForMockContainerHandler func TestNewContainerHandler_FirstMatches(t *testing.T) { @@ -64,13 +66,13 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) { container.RegisterContainerHandlerFactory(allwaysYes, []watcher.ContainerWatchSource{watcher.Raw}) // The yes factory should be asked to create the ContainerHandler. - mockContainer, err := mockFactory.NewContainerHandler(testContainerName, true) + mockContainer, err := mockFactory.NewContainerHandler(testContainerName, testMetadataEnvAllowList, true) if err != nil { t.Error(err) } allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil) - cont, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, true) + cont, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, testMetadataEnvAllowList, true) if err != nil { t.Error(err) } @@ -97,13 +99,13 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) { container.RegisterContainerHandlerFactory(allwaysYes, []watcher.ContainerWatchSource{watcher.Raw}) // The yes factory should be asked to create the ContainerHandler. - mockContainer, err := mockFactory.NewContainerHandler(testContainerName, true) + mockContainer, err := mockFactory.NewContainerHandler(testContainerName, testMetadataEnvAllowList, true) if err != nil { t.Error(err) } allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil) - cont, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, true) + cont, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, testMetadataEnvAllowList, true) if err != nil { t.Error(err) } @@ -129,7 +131,7 @@ func TestNewContainerHandler_NoneMatch(t *testing.T) { } container.RegisterContainerHandlerFactory(allwaysNo2, []watcher.ContainerWatchSource{watcher.Raw}) - _, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, true) + _, _, err := container.NewContainerHandler(testContainerName, watcher.Raw, testMetadataEnvAllowList, true) if err == nil { t.Error("Expected NewContainerHandler to fail") } @@ -152,7 +154,7 @@ func TestNewContainerHandler_Accept(t *testing.T) { } container.RegisterContainerHandlerFactory(cannotAccept, []watcher.ContainerWatchSource{watcher.Raw}) - _, accept, err := container.NewContainerHandler(testContainerName, watcher.Raw, true) + _, accept, err := container.NewContainerHandler(testContainerName, watcher.Raw, testMetadataEnvAllowList, true) if err != nil { t.Error("Expected NewContainerHandler to succeed") } diff --git a/container/raw/factory.go b/container/raw/factory.go index aa022529c9..ca0cc14376 100644 --- a/container/raw/factory.go +++ b/container/raw/factory.go @@ -56,7 +56,7 @@ func (f *rawFactory) String() string { return "raw" } -func (f *rawFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) { +func (f *rawFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (container.ContainerHandler, error) { rootFs := "/" if !inHostNamespace { rootFs = "/rootfs" diff --git a/container/systemd/factory.go b/container/systemd/factory.go index 0d5fc68e0b..e33f698657 100644 --- a/container/systemd/factory.go +++ b/container/systemd/factory.go @@ -32,7 +32,7 @@ func (f *systemdFactory) String() string { return "systemd" } -func (f *systemdFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) { +func (f *systemdFactory) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (container.ContainerHandler, error) { return nil, fmt.Errorf("Not yet supported") } diff --git a/container/testing/mock_handler.go b/container/testing/mock_handler.go index d6022ee138..9591431040 100644 --- a/container/testing/mock_handler.go +++ b/container/testing/mock_handler.go @@ -110,7 +110,7 @@ func (h *FactoryForMockContainerHandler) String() string { return h.Name } -func (h *FactoryForMockContainerHandler) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) { +func (h *FactoryForMockContainerHandler) NewContainerHandler(name string, metadataEnvAllowList []string, inHostNamespace bool) (container.ContainerHandler, error) { handler := &MockContainerHandler{} if h.PrepareContainerHandlerFunc != nil { h.PrepareContainerHandlerFunc(name, handler) diff --git a/docs/runtime_options.md b/docs/runtime_options.md index 676f517da2..ed1b1e528b 100644 --- a/docs/runtime_options.md +++ b/docs/runtime_options.md @@ -6,6 +6,10 @@ This document describes a set of runtime flags available in cAdvisor. * `--store_container_labels=false` - do not convert container labels and environment variables into labels on prometheus metrics for each container. * `--whitelisted_container_labels` - comma separated list of container labels to be converted to labels on prometheus metrics for each container. `store_container_labels` must be set to false for this to take effect. +## Container envs + +* `--env_metadata_whitelist`: a comma-separated list of environment variable keys that needs to be collected for containers, only support containerd and docker runtime for now. + ## Limiting which containers are monitored * `--docker_only=false` - do not report raw cgroup metrics, except the root cgroup. * `--raw_cgroup_prefix_whitelist` - a comma-separated list of cgroup path prefix that needs to be collected even when `--docker_only` is specified @@ -52,7 +56,6 @@ From [glog](https://github.com/golang/glog) here are some flags we find useful: ``` --docker="unix:///var/run/docker.sock": docker endpoint (default "unix:///var/run/docker.sock") ---docker_env_metadata_whitelist="": a comma-separated list of environment variable keys that needs to be collected for docker containers --docker_root="/var/lib/docker": DEPRECATED: docker root is read from docker info (this is a fallback, default: /var/lib/docker) (default "/var/lib/docker") --docker-tls: use TLS to connect to docker --docker-tls-cert="cert.pem": client certificate for TLS-connection with docker diff --git a/integration/runner/runner.go b/integration/runner/runner.go index 45048865a5..171cfc645e 100644 --- a/integration/runner/runner.go +++ b/integration/runner/runner.go @@ -113,7 +113,7 @@ func PushAndRunTests(host, testDir string) (result error) { portStr := strconv.Itoa(*port) errChan := make(chan error, 1) go func() { - err = RunSshCommand("ssh", host, "--", fmt.Sprintf("sudo GORACE='halt_on_error=1' %s --port %s --logtostderr --docker_env_metadata_whitelist=TEST_VAR &> %s/log.txt", path.Join(testDir, cadvisorBinary), portStr, testDir)) + err = RunSshCommand("ssh", host, "--", fmt.Sprintf("sudo GORACE='halt_on_error=1' %s --port %s --logtostderr --env_metadata_whitelist=TEST_VAR &> %s/log.txt", path.Join(testDir, cadvisorBinary), portStr, testDir)) if err != nil { errChan <- fmt.Errorf("error running cAdvisor: %v", err) } diff --git a/manager/manager.go b/manager/manager.go index 64f7d69929..0d12270a5a 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -152,7 +152,7 @@ type HouskeepingConfig = struct { } // New takes a memory storage and returns a new manager. -func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, houskeepingConfig HouskeepingConfig, includedMetricsSet container.MetricSet, collectorHTTPClient *http.Client, rawContainerCgroupPathPrefixWhiteList []string, perfEventsFile string) (Manager, error) { +func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, houskeepingConfig HouskeepingConfig, includedMetricsSet container.MetricSet, collectorHTTPClient *http.Client, rawContainerCgroupPathPrefixWhiteList, containerEnvMetadataWhiteList []string, perfEventsFile string) (Manager, error) { if memoryCache == nil { return nil, fmt.Errorf("manager requires memory storage") } @@ -209,6 +209,7 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, houskeepingConfig collectorHTTPClient: collectorHTTPClient, nvidiaManager: accelerators.NewNvidiaManager(includedMetricsSet), rawContainerCgroupPathPrefixWhiteList: rawContainerCgroupPathPrefixWhiteList, + containerEnvMetadataWhiteList: containerEnvMetadataWhiteList, } machineInfo, err := machine.Info(sysfs, fsInfo, inHostNamespace) @@ -271,6 +272,8 @@ type manager struct { resctrlManager stats.Manager // List of raw container cgroup path prefix whitelist. rawContainerCgroupPathPrefixWhiteList []string + // List of container env prefix whitelist, the matched container envs would be collected into metrics as extra labels. + containerEnvMetadataWhiteList []string } // Start the container manager. @@ -918,7 +921,7 @@ func (m *manager) createContainerLocked(containerName string, watchSource watche return nil } - handler, accept, err := container.NewContainerHandler(containerName, watchSource, m.inHostNamespace) + handler, accept, err := container.NewContainerHandler(containerName, watchSource, m.containerEnvMetadataWhiteList, m.inHostNamespace) if err != nil { return err }