2019-01-12 04:58:27 +00:00
|
|
|
/*
|
|
|
|
Copyright 2016 The Kubernetes Authors.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package kubelet
|
|
|
|
|
|
|
|
import (
|
2019-12-12 01:27:03 +00:00
|
|
|
"context"
|
2019-01-12 04:58:27 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
cadvisorapiv1 "github.com/google/cadvisor/info/v1"
|
2020-08-10 17:43:49 +00:00
|
|
|
cadvisorv2 "github.com/google/cadvisor/info/v2"
|
|
|
|
"k8s.io/klog/v2"
|
2020-12-01 01:06:26 +00:00
|
|
|
"k8s.io/mount-utils"
|
2019-12-12 01:27:03 +00:00
|
|
|
utilpath "k8s.io/utils/path"
|
2020-08-10 17:43:49 +00:00
|
|
|
utilstrings "k8s.io/utils/strings"
|
2019-01-12 04:58:27 +00:00
|
|
|
|
2019-12-12 01:27:03 +00:00
|
|
|
v1 "k8s.io/api/core/v1"
|
2019-01-12 04:58:27 +00:00
|
|
|
"k8s.io/apimachinery/pkg/types"
|
|
|
|
"k8s.io/kubernetes/pkg/kubelet/cm"
|
|
|
|
"k8s.io/kubernetes/pkg/kubelet/config"
|
|
|
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
2020-01-15 01:52:20 +00:00
|
|
|
kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
|
2019-01-12 04:58:27 +00:00
|
|
|
utilnode "k8s.io/kubernetes/pkg/util/node"
|
2020-08-10 17:43:49 +00:00
|
|
|
"k8s.io/kubernetes/pkg/volume/csi"
|
2019-01-12 04:58:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// getRootDir returns the full path to the directory under which kubelet can
|
|
|
|
// store data. These functions are useful to pass interfaces to other modules
|
|
|
|
// that may need to know where to write data without getting a whole kubelet
|
|
|
|
// instance.
|
|
|
|
func (kl *Kubelet) getRootDir() string {
|
|
|
|
return kl.rootDirectory
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodsDir returns the full path to the directory under which pod
|
|
|
|
// directories are created.
|
|
|
|
func (kl *Kubelet) getPodsDir() string {
|
|
|
|
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPodsDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPluginsDir returns the full path to the directory under which plugin
|
|
|
|
// directories are created. Plugins can use these directories for data that
|
|
|
|
// they need to persist. Plugins should create subdirectories under this named
|
|
|
|
// after their own names.
|
|
|
|
func (kl *Kubelet) getPluginsDir() string {
|
|
|
|
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPluginsDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPluginsRegistrationDir returns the full path to the directory under which
|
|
|
|
// plugins socket should be placed to be registered.
|
|
|
|
// More information is available about plugin registration in the pluginwatcher
|
|
|
|
// module
|
|
|
|
func (kl *Kubelet) getPluginsRegistrationDir() string {
|
|
|
|
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPluginsRegistrationDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPluginDir returns a data directory name for a given plugin name.
|
|
|
|
// Plugins can use these directories to store data that they need to persist.
|
|
|
|
// For per-pod plugin data, see getPodPluginDir.
|
|
|
|
func (kl *Kubelet) getPluginDir(pluginName string) string {
|
|
|
|
return filepath.Join(kl.getPluginsDir(), pluginName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getVolumeDevicePluginsDir returns the full path to the directory under which plugin
|
|
|
|
// directories are created. Plugins can use these directories for data that
|
|
|
|
// they need to persist. Plugins should create subdirectories under this named
|
|
|
|
// after their own names.
|
|
|
|
func (kl *Kubelet) getVolumeDevicePluginsDir() string {
|
|
|
|
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPluginsDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getVolumeDevicePluginDir returns a data directory name for a given plugin name.
|
|
|
|
// Plugins can use these directories to store data that they need to persist.
|
|
|
|
// For per-pod plugin data, see getVolumeDevicePluginsDir.
|
|
|
|
func (kl *Kubelet) getVolumeDevicePluginDir(pluginName string) string {
|
|
|
|
return filepath.Join(kl.getVolumeDevicePluginsDir(), pluginName, config.DefaultKubeletVolumeDevicesDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPodDir returns the full path to the per-pod data directory for the
|
|
|
|
// specified pod. This directory may not exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) GetPodDir(podUID types.UID) string {
|
|
|
|
return kl.getPodDir(podUID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodDir returns the full path to the per-pod directory for the pod with
|
|
|
|
// the given UID.
|
|
|
|
func (kl *Kubelet) getPodDir(podUID types.UID) string {
|
|
|
|
return filepath.Join(kl.getPodsDir(), string(podUID))
|
|
|
|
}
|
|
|
|
|
2019-01-22 20:53:35 +00:00
|
|
|
// getPodVolumesSubpathsDir returns the full path to the per-pod subpaths directory under
|
|
|
|
// which subpath volumes are created for the specified pod. This directory may not
|
|
|
|
// exist if the pod does not exist or subpaths are not specified.
|
|
|
|
func (kl *Kubelet) getPodVolumeSubpathsDir(podUID types.UID) string {
|
|
|
|
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumeSubpathsDirName)
|
|
|
|
}
|
|
|
|
|
2019-01-12 04:58:27 +00:00
|
|
|
// getPodVolumesDir returns the full path to the per-pod data directory under
|
|
|
|
// which volumes are created for the specified pod. This directory may not
|
|
|
|
// exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) getPodVolumesDir(podUID types.UID) string {
|
|
|
|
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumesDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodVolumeDir returns the full path to the directory which represents the
|
|
|
|
// named volume under the named plugin for specified pod. This directory may not
|
|
|
|
// exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) getPodVolumeDir(podUID types.UID, pluginName string, volumeName string) string {
|
|
|
|
return filepath.Join(kl.getPodVolumesDir(podUID), pluginName, volumeName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodVolumeDevicesDir returns the full path to the per-pod data directory under
|
|
|
|
// which volumes are created for the specified pod. This directory may not
|
|
|
|
// exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) getPodVolumeDevicesDir(podUID types.UID) string {
|
|
|
|
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletVolumeDevicesDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodVolumeDeviceDir returns the full path to the directory which represents the
|
|
|
|
// named plugin for specified pod. This directory may not exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) getPodVolumeDeviceDir(podUID types.UID, pluginName string) string {
|
|
|
|
return filepath.Join(kl.getPodVolumeDevicesDir(podUID), pluginName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodPluginsDir returns the full path to the per-pod data directory under
|
|
|
|
// which plugins may store data for the specified pod. This directory may not
|
|
|
|
// exist if the pod does not exist.
|
|
|
|
func (kl *Kubelet) getPodPluginsDir(podUID types.UID) string {
|
|
|
|
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletPluginsDirName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodPluginDir returns a data directory name for a given plugin name for a
|
|
|
|
// given pod UID. Plugins can use these directories to store data that they
|
|
|
|
// need to persist. For non-per-pod plugin data, see getPluginDir.
|
|
|
|
func (kl *Kubelet) getPodPluginDir(podUID types.UID, pluginName string) string {
|
|
|
|
return filepath.Join(kl.getPodPluginsDir(podUID), pluginName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodContainerDir returns the full path to the per-pod data directory under
|
|
|
|
// which container data is held for the specified pod. This directory may not
|
|
|
|
// exist if the pod or container does not exist.
|
|
|
|
func (kl *Kubelet) getPodContainerDir(podUID types.UID, ctrName string) string {
|
|
|
|
return filepath.Join(kl.getPodDir(podUID), config.DefaultKubeletContainersDirName, ctrName)
|
|
|
|
}
|
|
|
|
|
2019-08-30 18:33:25 +00:00
|
|
|
// getPodResourcesSocket returns the full path to the directory containing the pod resources socket
|
|
|
|
func (kl *Kubelet) getPodResourcesDir() string {
|
|
|
|
return filepath.Join(kl.getRootDir(), config.DefaultKubeletPodResourcesDirName)
|
|
|
|
}
|
|
|
|
|
2019-01-12 04:58:27 +00:00
|
|
|
// GetPods returns all pods bound to the kubelet and their spec, and the mirror
|
|
|
|
// pods.
|
|
|
|
func (kl *Kubelet) GetPods() []*v1.Pod {
|
2019-08-30 18:33:25 +00:00
|
|
|
pods := kl.podManager.GetPods()
|
|
|
|
// a kubelet running without apiserver requires an additional
|
|
|
|
// update of the static pod status. See #57106
|
|
|
|
for _, p := range pods {
|
2020-01-15 01:52:20 +00:00
|
|
|
if kubelettypes.IsStaticPod(p) {
|
|
|
|
if status, ok := kl.statusManager.GetPodStatus(p.UID); ok {
|
2020-08-10 17:43:49 +00:00
|
|
|
klog.V(2).InfoS("Pod status updated", "pod", klog.KObj(p), "status", status.Phase)
|
2020-01-15 01:52:20 +00:00
|
|
|
p.Status = status
|
|
|
|
}
|
2019-08-30 18:33:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return pods
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetRunningPods returns all pods running on kubelet from looking at the
|
|
|
|
// container runtime cache. This function converts kubecontainer.Pod to
|
|
|
|
// v1.Pod, so only the fields that exist in both kubecontainer.Pod and
|
|
|
|
// v1.Pod are considered meaningful.
|
|
|
|
func (kl *Kubelet) GetRunningPods() ([]*v1.Pod, error) {
|
|
|
|
pods, err := kl.runtimeCache.GetPods()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
apiPods := make([]*v1.Pod, 0, len(pods))
|
|
|
|
for _, pod := range pods {
|
|
|
|
apiPods = append(apiPods, pod.ToAPIPod())
|
|
|
|
}
|
|
|
|
return apiPods, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPodByFullName gets the pod with the given 'full' name, which
|
|
|
|
// incorporates the namespace as well as whether the pod was found.
|
|
|
|
func (kl *Kubelet) GetPodByFullName(podFullName string) (*v1.Pod, bool) {
|
|
|
|
return kl.podManager.GetPodByFullName(podFullName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPodByName provides the first pod that matches namespace and name, as well
|
|
|
|
// as whether the pod was found.
|
|
|
|
func (kl *Kubelet) GetPodByName(namespace, name string) (*v1.Pod, bool) {
|
|
|
|
return kl.podManager.GetPodByName(namespace, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPodByCgroupfs provides the pod that maps to the specified cgroup, as well
|
|
|
|
// as whether the pod was found.
|
|
|
|
func (kl *Kubelet) GetPodByCgroupfs(cgroupfs string) (*v1.Pod, bool) {
|
|
|
|
pcm := kl.containerManager.NewPodContainerManager()
|
|
|
|
if result, podUID := pcm.IsPodCgroup(cgroupfs); result {
|
|
|
|
return kl.podManager.GetPodByUID(podUID)
|
|
|
|
}
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetHostname Returns the hostname as the kubelet sees it.
|
|
|
|
func (kl *Kubelet) GetHostname() string {
|
|
|
|
return kl.hostname
|
|
|
|
}
|
|
|
|
|
|
|
|
// getRuntime returns the current Runtime implementation in use by the kubelet.
|
|
|
|
func (kl *Kubelet) getRuntime() kubecontainer.Runtime {
|
|
|
|
return kl.containerRuntime
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNode returns the node info for the configured node name of this Kubelet.
|
|
|
|
func (kl *Kubelet) GetNode() (*v1.Node, error) {
|
|
|
|
if kl.kubeClient == nil {
|
2019-12-12 01:27:03 +00:00
|
|
|
return kl.initialNode(context.TODO())
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
2019-12-12 01:27:03 +00:00
|
|
|
return kl.nodeLister.Get(string(kl.nodeName))
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// getNodeAnyWay() must return a *v1.Node which is required by RunGeneralPredicates().
|
|
|
|
// The *v1.Node is obtained as follows:
|
|
|
|
// Return kubelet's nodeInfo for this node, except on error or if in standalone mode,
|
|
|
|
// in which case return a manufactured nodeInfo representing a node with no pods,
|
|
|
|
// zero capacity, and the default labels.
|
|
|
|
func (kl *Kubelet) getNodeAnyWay() (*v1.Node, error) {
|
|
|
|
if kl.kubeClient != nil {
|
2021-05-14 17:12:55 +00:00
|
|
|
if n, err := kl.nodeLister.Get(string(kl.nodeName)); err == nil {
|
2019-01-12 04:58:27 +00:00
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
}
|
2019-12-12 01:27:03 +00:00
|
|
|
return kl.initialNode(context.TODO())
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetNodeConfig returns the container manager node config.
|
|
|
|
func (kl *Kubelet) GetNodeConfig() cm.NodeConfig {
|
|
|
|
return kl.containerManager.GetNodeConfig()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetPodCgroupRoot returns the listeral cgroupfs value for the cgroup containing all pods
|
|
|
|
func (kl *Kubelet) GetPodCgroupRoot() string {
|
|
|
|
return kl.containerManager.GetPodCgroupRoot()
|
|
|
|
}
|
|
|
|
|
2020-12-01 01:06:26 +00:00
|
|
|
// GetHostIPs returns host IPs or nil in case of error.
|
|
|
|
func (kl *Kubelet) GetHostIPs() ([]net.IP, error) {
|
2019-01-12 04:58:27 +00:00
|
|
|
node, err := kl.GetNode()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot get node: %v", err)
|
|
|
|
}
|
2020-12-01 01:06:26 +00:00
|
|
|
return utilnode.GetNodeHostIPs(node)
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 01:06:26 +00:00
|
|
|
// getHostIPsAnyWay attempts to return the host IPs from kubelet's nodeInfo, or
|
2019-01-12 04:58:27 +00:00
|
|
|
// the initialNode.
|
2020-12-01 01:06:26 +00:00
|
|
|
func (kl *Kubelet) getHostIPsAnyWay() ([]net.IP, error) {
|
2019-01-12 04:58:27 +00:00
|
|
|
node, err := kl.getNodeAnyWay()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-12-01 01:06:26 +00:00
|
|
|
return utilnode.GetNodeHostIPs(node)
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetExtraSupplementalGroupsForPod returns a list of the extra
|
|
|
|
// supplemental groups for the Pod. These extra supplemental groups come
|
|
|
|
// from annotations on persistent volumes that the pod depends on.
|
|
|
|
func (kl *Kubelet) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 {
|
|
|
|
return kl.volumeManager.GetExtraSupplementalGroupsForPod(pod)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPodVolumePathListFromDisk returns a list of the volume paths by reading the
|
|
|
|
// volume directories for the given pod from the disk.
|
|
|
|
func (kl *Kubelet) getPodVolumePathListFromDisk(podUID types.UID) ([]string, error) {
|
|
|
|
volumes := []string{}
|
|
|
|
podVolDir := kl.getPodVolumesDir(podUID)
|
|
|
|
|
2019-04-07 17:07:55 +00:00
|
|
|
if pathExists, pathErr := mount.PathExists(podVolDir); pathErr != nil {
|
2019-09-27 21:51:53 +00:00
|
|
|
return volumes, fmt.Errorf("error checking if path %q exists: %v", podVolDir, pathErr)
|
2019-01-12 04:58:27 +00:00
|
|
|
} else if !pathExists {
|
2021-03-18 22:40:29 +00:00
|
|
|
klog.InfoS("Path does not exist", "path", podVolDir)
|
2019-01-12 04:58:27 +00:00
|
|
|
return volumes, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
volumePluginDirs, err := ioutil.ReadDir(podVolDir)
|
|
|
|
if err != nil {
|
2021-03-18 22:40:29 +00:00
|
|
|
klog.ErrorS(err, "Could not read directory", "path", podVolDir)
|
2019-01-12 04:58:27 +00:00
|
|
|
return volumes, err
|
|
|
|
}
|
|
|
|
for _, volumePluginDir := range volumePluginDirs {
|
|
|
|
volumePluginName := volumePluginDir.Name()
|
|
|
|
volumePluginPath := filepath.Join(podVolDir, volumePluginName)
|
2019-04-07 17:07:55 +00:00
|
|
|
volumeDirs, err := utilpath.ReadDirNoStat(volumePluginPath)
|
2019-01-12 04:58:27 +00:00
|
|
|
if err != nil {
|
2019-09-27 21:51:53 +00:00
|
|
|
return volumes, fmt.Errorf("could not read directory %s: %v", volumePluginPath, err)
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
2020-08-10 17:43:49 +00:00
|
|
|
unescapePluginName := utilstrings.UnescapeQualifiedName(volumePluginName)
|
|
|
|
|
|
|
|
if unescapePluginName != csi.CSIPluginName {
|
|
|
|
for _, volumeDir := range volumeDirs {
|
|
|
|
volumes = append(volumes, filepath.Join(volumePluginPath, volumeDir))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// For CSI volumes, the mounted volume path has an extra sub path "/mount", so also add it
|
|
|
|
// to the list if the mounted path exists.
|
|
|
|
for _, volumeDir := range volumeDirs {
|
|
|
|
path := filepath.Join(volumePluginPath, volumeDir)
|
|
|
|
csimountpath := csi.GetCSIMounterPath(path)
|
|
|
|
if pathExists, _ := mount.PathExists(csimountpath); pathExists {
|
|
|
|
volumes = append(volumes, csimountpath)
|
|
|
|
}
|
|
|
|
}
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return volumes, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (kl *Kubelet) getMountedVolumePathListFromDisk(podUID types.UID) ([]string, error) {
|
|
|
|
mountedVolumes := []string{}
|
|
|
|
volumePaths, err := kl.getPodVolumePathListFromDisk(podUID)
|
|
|
|
if err != nil {
|
|
|
|
return mountedVolumes, err
|
|
|
|
}
|
2020-08-10 17:43:49 +00:00
|
|
|
// Only use IsLikelyNotMountPoint to check might not cover all cases. For CSI volumes that
|
|
|
|
// either: 1) don't mount or 2) bind mount in the rootfs, the mount check will not work as expected.
|
|
|
|
// We plan to remove this mountpoint check as a condition before deleting pods since it is
|
|
|
|
// not reliable and the condition might be different for different types of volumes. But it requires
|
|
|
|
// a reliable way to clean up unused volume dir to avoid problems during pod deletion. See discussion in issue #74650
|
2019-01-12 04:58:27 +00:00
|
|
|
for _, volumePath := range volumePaths {
|
|
|
|
isNotMount, err := kl.mounter.IsLikelyNotMountPoint(volumePath)
|
|
|
|
if err != nil {
|
2020-08-10 17:43:49 +00:00
|
|
|
return mountedVolumes, fmt.Errorf("fail to check mount point %q: %v", volumePath, err)
|
2019-01-12 04:58:27 +00:00
|
|
|
}
|
|
|
|
if !isNotMount {
|
|
|
|
mountedVolumes = append(mountedVolumes, volumePath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return mountedVolumes, nil
|
|
|
|
}
|
|
|
|
|
2021-03-19 18:50:37 +00:00
|
|
|
// getPodVolumeSubpathListFromDisk returns a list of the volume-subpath paths by reading the
|
|
|
|
// subpath directories for the given pod from the disk.
|
|
|
|
func (kl *Kubelet) getPodVolumeSubpathListFromDisk(podUID types.UID) ([]string, error) {
|
|
|
|
volumes := []string{}
|
|
|
|
podSubpathsDir := kl.getPodVolumeSubpathsDir(podUID)
|
2019-01-22 20:53:35 +00:00
|
|
|
|
2021-03-19 18:50:37 +00:00
|
|
|
if pathExists, pathErr := mount.PathExists(podSubpathsDir); pathErr != nil {
|
|
|
|
return nil, fmt.Errorf("error checking if path %q exists: %v", podSubpathsDir, pathErr)
|
2019-01-22 20:53:35 +00:00
|
|
|
} else if !pathExists {
|
2021-03-19 18:50:37 +00:00
|
|
|
return volumes, nil
|
2019-01-22 20:53:35 +00:00
|
|
|
}
|
2021-03-19 18:50:37 +00:00
|
|
|
|
|
|
|
// Explicitly walks /<volume>/<container name>/<subPathIndex>
|
|
|
|
volumePluginDirs, err := ioutil.ReadDir(podSubpathsDir)
|
|
|
|
if err != nil {
|
2021-03-18 22:40:29 +00:00
|
|
|
klog.ErrorS(err, "Could not read directory", "path", podSubpathsDir)
|
2021-03-19 18:50:37 +00:00
|
|
|
return volumes, err
|
|
|
|
}
|
|
|
|
for _, volumePluginDir := range volumePluginDirs {
|
|
|
|
volumePluginName := volumePluginDir.Name()
|
|
|
|
volumePluginPath := filepath.Join(podSubpathsDir, volumePluginName)
|
|
|
|
containerDirs, err := ioutil.ReadDir(volumePluginPath)
|
|
|
|
if err != nil {
|
|
|
|
return volumes, fmt.Errorf("could not read directory %s: %v", volumePluginPath, err)
|
|
|
|
}
|
|
|
|
for _, containerDir := range containerDirs {
|
|
|
|
containerName := containerDir.Name()
|
|
|
|
containerPath := filepath.Join(volumePluginPath, containerName)
|
|
|
|
// Switch to ReadDirNoStat at the subPathIndex level to prevent issues with stat'ing
|
|
|
|
// mount points that may not be responsive
|
|
|
|
subPaths, err := utilpath.ReadDirNoStat(containerPath)
|
|
|
|
if err != nil {
|
|
|
|
return volumes, fmt.Errorf("could not read directory %s: %v", containerPath, err)
|
|
|
|
}
|
|
|
|
for _, subPathDir := range subPaths {
|
|
|
|
volumes = append(volumes, filepath.Join(containerPath, subPathDir))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return volumes, nil
|
2019-01-22 20:53:35 +00:00
|
|
|
}
|
|
|
|
|
2020-08-10 17:43:49 +00:00
|
|
|
// GetRequestedContainersInfo returns container info.
|
|
|
|
func (kl *Kubelet) GetRequestedContainersInfo(containerName string, options cadvisorv2.RequestOptions) (map[string]*cadvisorapiv1.ContainerInfo, error) {
|
|
|
|
return kl.cadvisor.GetRequestedContainersInfo(containerName, options)
|
|
|
|
}
|
|
|
|
|
2019-01-12 04:58:27 +00:00
|
|
|
// GetVersionInfo returns information about the version of cAdvisor in use.
|
|
|
|
func (kl *Kubelet) GetVersionInfo() (*cadvisorapiv1.VersionInfo, error) {
|
|
|
|
return kl.cadvisor.VersionInfo()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCachedMachineInfo assumes that the machine info can't change without a reboot
|
|
|
|
func (kl *Kubelet) GetCachedMachineInfo() (*cadvisorapiv1.MachineInfo, error) {
|
2020-08-10 17:43:49 +00:00
|
|
|
kl.machineInfoLock.RLock()
|
|
|
|
defer kl.machineInfoLock.RUnlock()
|
2019-01-12 04:58:27 +00:00
|
|
|
return kl.machineInfo, nil
|
|
|
|
}
|
2020-08-10 17:43:49 +00:00
|
|
|
|
|
|
|
func (kl *Kubelet) setCachedMachineInfo(info *cadvisorapiv1.MachineInfo) {
|
|
|
|
kl.machineInfoLock.Lock()
|
|
|
|
defer kl.machineInfoLock.Unlock()
|
|
|
|
kl.machineInfo = info
|
|
|
|
}
|