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 #26093
pull/6/head
Davanum Srinivas 2016-08-03 13:02:09 -04:00
parent 012eb941d6
commit 1fdcea28e5
3 changed files with 64 additions and 18 deletions

View File

@ -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.

View File

@ -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
}

View File

@ -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())
}