mirror of https://github.com/k3s-io/k3s
Remove kubelet dependency on pidof
Issue #26093 identified pidof as one of the dependencies of kublet which could be worked around. In this PR, we just look at /proc to construct the list of pids we need for a specified process instead of running "pidof" executable Related to #26093pull/6/head
parent
012eb941d6
commit
1fdcea28e5
|
@ -22,10 +22,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -42,6 +40,7 @@ import (
|
||||||
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
utilerrors "k8s.io/kubernetes/pkg/util/errors"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/util/oom"
|
"k8s.io/kubernetes/pkg/util/oom"
|
||||||
|
"k8s.io/kubernetes/pkg/util/procfs"
|
||||||
"k8s.io/kubernetes/pkg/util/runtime"
|
"k8s.io/kubernetes/pkg/util/runtime"
|
||||||
"k8s.io/kubernetes/pkg/util/sets"
|
"k8s.io/kubernetes/pkg/util/sets"
|
||||||
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
|
utilsysctl "k8s.io/kubernetes/pkg/util/sysctl"
|
||||||
|
@ -526,22 +525,7 @@ func getPidsForProcess(name, pidFile string) ([]int, error) {
|
||||||
runtime.HandleError(err)
|
runtime.HandleError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return procfs.PidOf(name), nil
|
||||||
out, err := exec.Command("pidof", name).Output()
|
|
||||||
if err != nil {
|
|
||||||
return []int{}, fmt.Errorf("failed to find pid of %q: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The output of pidof is a list of pids.
|
|
||||||
pids := []int{}
|
|
||||||
for _, pidStr := range strings.Split(strings.TrimSpace(string(out)), " ") {
|
|
||||||
pid, err := strconv.Atoi(pidStr)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pids = append(pids, pid)
|
|
||||||
}
|
|
||||||
return pids, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that the Docker daemon is in the desired container.
|
// Ensures that the Docker daemon is in the desired container.
|
||||||
|
|
|
@ -17,12 +17,17 @@ limitations under the License.
|
||||||
package procfs
|
package procfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProcFS struct{}
|
type ProcFS struct{}
|
||||||
|
@ -56,3 +61,46 @@ func (pfs *ProcFS) GetFullContainerName(pid int) (string, error) {
|
||||||
}
|
}
|
||||||
return containerNameFromProcCgroup(string(content))
|
return containerNameFromProcCgroup(string(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PidOf(name string) []int {
|
||||||
|
pids := []int{}
|
||||||
|
filepath.Walk("/proc", func(path string, info os.FileInfo, err error) error {
|
||||||
|
base := filepath.Base(path)
|
||||||
|
// Traverse only the directories we are interested in
|
||||||
|
if info.IsDir() && path != "/proc" {
|
||||||
|
// If the directory is not a number (i.e. not a PID), skip it
|
||||||
|
if _, err := strconv.Atoi(base); err != nil {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if base != "cmdline" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cmdline, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(4).Infof("Error reading file %s: %+v", path, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// The bytes we read have '\0' as a separator for the command line
|
||||||
|
parts := bytes.SplitN(cmdline, []byte{0}, 2)
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Split the command line itself we are interested in just the first part
|
||||||
|
exe := strings.FieldsFunc(string(parts[0]), func(c rune) bool {
|
||||||
|
return unicode.IsSpace(c) || c == ':'
|
||||||
|
})
|
||||||
|
if len(exe) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Check if the name of the executable is what we are looking for
|
||||||
|
if filepath.Base(exe[0]) == name {
|
||||||
|
dirname := filepath.Base(filepath.Dir(path))
|
||||||
|
// Grab the PID from the directory path
|
||||||
|
pid, _ := strconv.Atoi(dirname)
|
||||||
|
pids = append(pids, pid)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return pids
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,12 @@ package procfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func verifyContainerName(procCgroupText, expectedName string, expectedErr bool, t *testing.T) {
|
func verifyContainerName(procCgroupText, expectedName string, expectedErr bool, t *testing.T) {
|
||||||
|
@ -56,3 +61,12 @@ func TestContainerNameFromProcCgroup(t *testing.T) {
|
||||||
procCgroupInvalid := "devices:docker/kubelet\ncpuacct:pkg/kubectl"
|
procCgroupInvalid := "devices:docker/kubelet\ncpuacct:pkg/kubectl"
|
||||||
verifyContainerName(procCgroupInvalid, "", true, t)
|
verifyContainerName(procCgroupInvalid, "", true, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPidOf(t *testing.T) {
|
||||||
|
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
|
||||||
|
t.Skipf("not supported on GOOS=%s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
pids := PidOf(filepath.Base(os.Args[0]))
|
||||||
|
assert.NotZero(t, pids)
|
||||||
|
assert.Contains(t, pids, os.Getpid())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue