diff --git a/container/container.go b/container/container.go index c42819da..0927d327 100644 --- a/container/container.go +++ b/container/container.go @@ -59,6 +59,9 @@ type ContainerHandler interface { // Returns container labels, if available. GetContainerLabels() map[string]string + // Returns the container's ip address, if available + GetContainerIPAddress() string + // Returns whether the container still exists. Exists() bool diff --git a/container/docker/handler.go b/container/docker/handler.go index fd3e2fdc..c8f4a68e 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -94,6 +94,9 @@ type dockerContainerHandler struct { // Filesystem handler. fsHandler common.FsHandler + // The IP address of the container + ipAddress string + ignoreMetrics container.MetricSet // thin pool watcher @@ -222,6 +225,22 @@ func newDockerContainerHandler( handler.networkMode = ctnr.HostConfig.NetworkMode handler.deviceID = ctnr.GraphDriver.Data["DeviceId"] + // Obtain the IP address for the contianer. + // If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified. + // This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address + ipAddress := ctnr.NetworkSettings.IPAddress + networkMode := string(ctnr.HostConfig.NetworkMode) + if ipAddress == "" && strings.HasPrefix(networkMode, "container:") { + containerId := strings.TrimPrefix(networkMode, "container:") + c, err := client.ContainerInspect(context.Background(), containerId) + if err != nil { + return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) + } + ipAddress = c.NetworkSettings.IPAddress + } + + handler.ipAddress = ipAddress + if !ignoreMetrics.Has(container.DiskUsageMetrics) { handler.fsHandler = &dockerFsHandler{ fsHandler: common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo), @@ -412,6 +431,10 @@ func (self *dockerContainerHandler) GetContainerLabels() map[string]string { return self.labels } +func (self *dockerContainerHandler) GetContainerIPAddress() string { + return self.ipAddress +} + func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { return containerlibcontainer.GetProcesses(self.cgroupManager) } diff --git a/container/raw/handler.go b/container/raw/handler.go index 7b959acf..29bf7c1e 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -256,6 +256,11 @@ func (self *rawContainerHandler) GetContainerLabels() map[string]string { return map[string]string{} } +func (self *rawContainerHandler) GetContainerIPAddress() string { + // the IP address for the raw container corresponds to the system ip address. + return "127.0.0.1" +} + func (self *rawContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { return common.ListContainers(self.name, self.cgroupPaths, listType) } diff --git a/container/rkt/handler.go b/container/rkt/handler.go index a6b75652..fad91dbe 100644 --- a/container/rkt/handler.go +++ b/container/rkt/handler.go @@ -250,6 +250,21 @@ func (handler *rktContainerHandler) GetStats() (*info.ContainerStats, error) { return stats, nil } +func (self *rktContainerHandler) GetContainerIPAddress() string { + // attempt to return the ip address of the pod + // if a specific ip address of the pod could not be determined, return the system ip address + if self.isPod && len(self.apiPod.Networks) > 0 { + address := self.apiPod.Networks[0].Ipv4 + if address != "" { + return address + } else { + return self.apiPod.Networks[0].Ipv6 + } + } else { + return "127.0.0.1" + } +} + func (handler *rktContainerHandler) GetCgroupPath(resource string) (string, error) { path, ok := handler.cgroupPaths[resource] if !ok { diff --git a/container/testing/mock_handler.go b/container/testing/mock_handler.go index 89f3a10f..7dfd0ca4 100644 --- a/container/testing/mock_handler.go +++ b/container/testing/mock_handler.go @@ -96,6 +96,11 @@ func (self *MockContainerHandler) Type() container.ContainerType { return args.Get(0).(container.ContainerType) } +func (self *MockContainerHandler) GetContainerIPAddress() string { + args := self.Called() + return args.Get(0).(string) +} + type FactoryForMockContainerHandler struct { Name string PrepareContainerHandlerFunc func(name string, handler *MockContainerHandler)