rkt: Do not run rkt pod inside a pre-created netns when network plugin is no-op.

This fixed a panic where the returned pod network status is nil.
Also this makes lkvm stage1 able to run inside a user defined
network, where the network name needs to be 'rkt.kubernetes.io'.

Also fixed minor issues such as passing the wrong pod UID, ignoring
logging errors.
This commit is contained in:
Yifan Gu
2016-06-07 13:22:55 -07:00
parent 6a388d4a0d
commit 5a9ea30814
2 changed files with 235 additions and 69 deletions

View File

@@ -38,6 +38,7 @@ import (
kubetesting "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/lifecycle"
"k8s.io/kubernetes/pkg/kubelet/network"
"k8s.io/kubernetes/pkg/kubelet/network/kubenet"
"k8s.io/kubernetes/pkg/kubelet/network/mock_network"
"k8s.io/kubernetes/pkg/kubelet/rkt/mock_os"
"k8s.io/kubernetes/pkg/kubelet/types"
@@ -75,7 +76,7 @@ func makeRktPod(rktPodState rktapi.PodState,
rktPodID, podUID, podName, podNamespace string, podCreatedAt, podStartedAt int64,
podRestartCount string, appNames, imgIDs, imgNames,
containerHashes []string, appStates []rktapi.AppState,
exitcodes []int32) *rktapi.Pod {
exitcodes []int32, ips map[string]string) *rktapi.Pod {
podManifest := &appcschema.PodManifest{
ACKind: appcschema.PodManifestKind,
@@ -149,6 +150,11 @@ func makeRktPod(rktPodState rktapi.PodState,
})
}
var networks []*rktapi.Network
for name, ip := range ips {
networks = append(networks, &rktapi.Network{Name: name, Ipv4: ip})
}
return &rktapi.Pod{
Id: rktPodID,
State: rktPodState,
@@ -156,6 +162,7 @@ func makeRktPod(rktPodState rktapi.PodState,
Manifest: mustMarshalPodManifest(podManifest),
StartedAt: podStartedAt,
CreatedAt: podCreatedAt,
Networks: networks,
}
}
@@ -357,6 +364,7 @@ func TestGetPods(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
},
[]*kubecontainer.Pod{
@@ -395,6 +403,7 @@ func TestGetPods(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4003", "43", "guestbook", "default",
@@ -405,6 +414,7 @@ func TestGetPods(t *testing.T) {
[]string{"10011", "10022"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_EXITED, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4004", "43", "guestbook", "default",
@@ -415,6 +425,7 @@ func TestGetPods(t *testing.T) {
[]string{"10011", "10022"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_RUNNING},
[]int32{0, 0},
nil,
),
},
[]*kubecontainer.Pod{
@@ -560,16 +571,19 @@ func TestGetPodStatus(t *testing.T) {
}
tests := []struct {
pods []*rktapi.Pod
result *kubecontainer.PodStatus
networkPluginName string
pods []*rktapi.Pod
result *kubecontainer.PodStatus
}{
// No pods.
// # case 0, No pods.
{
kubenet.KubenetPluginName,
nil,
&kubecontainer.PodStatus{ID: "42", Name: "guestbook", Namespace: "default"},
},
// One pod.
// # case 1, One pod.
{
kubenet.KubenetPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_RUNNING,
"uuid-4002", "42", "guestbook", "default",
@@ -580,6 +594,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
},
&kubecontainer.PodStatus{
@@ -616,8 +631,59 @@ func TestGetPodStatus(t *testing.T) {
},
},
},
// Multiple pods.
// # case 2, One pod with no-op network plugin name.
{
network.DefaultPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_RUNNING,
"uuid-4002", "42", "guestbook", "default",
ns(10), ns(20), "7",
[]string{"app-1", "app-2"},
[]string{"img-id-1", "img-id-2"},
[]string{"img-name-1", "img-name-2"},
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
map[string]string{defaultNetworkName: "10.10.10.22"},
),
},
&kubecontainer.PodStatus{
ID: "42",
Name: "guestbook",
Namespace: "default",
IP: "10.10.10.22",
ContainerStatuses: []*kubecontainer.ContainerStatus{
{
ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"),
Name: "app-1",
State: kubecontainer.ContainerStateRunning,
CreatedAt: time.Unix(10, 0),
StartedAt: time.Unix(20, 0),
FinishedAt: time.Unix(0, 30),
Image: "img-name-1:latest",
ImageID: "rkt://img-id-1",
Hash: 1001,
RestartCount: 7,
},
{
ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"),
Name: "app-2",
State: kubecontainer.ContainerStateExited,
CreatedAt: time.Unix(10, 0),
StartedAt: time.Unix(20, 0),
FinishedAt: time.Unix(0, 30),
Image: "img-name-2:latest",
ImageID: "rkt://img-id-2",
Hash: 1002,
RestartCount: 7,
Reason: "Completed",
},
},
},
},
// # case 3, Multiple pods.
{
kubenet.KubenetPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4002", "42", "guestbook", "default",
@@ -628,6 +694,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_RUNNING, // The latest pod is running.
"uuid-4003", "42", "guestbook", "default",
@@ -638,6 +705,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 1},
nil,
),
},
&kubecontainer.PodStatus{
@@ -721,13 +789,16 @@ func TestGetPodStatus(t *testing.T) {
mockFI.EXPECT().ModTime().Return(podTime)
return mockFI, nil
}
fnp.EXPECT().Name().Return(tt.networkPluginName)
if tt.result.IP != "" {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(&network.PodNetworkStatus{IP: net.ParseIP(tt.result.IP)}, nil)
} else {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(nil, fmt.Errorf("no such network"))
if tt.networkPluginName == kubenet.KubenetPluginName {
if tt.result.IP != "" {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(&network.PodNetworkStatus{IP: net.ParseIP(tt.result.IP)}, nil)
} else {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(nil, fmt.Errorf("no such network"))
}
}
status, err := r.GetPodStatus("42", "guestbook", "default")
@@ -1070,9 +1141,10 @@ func TestSetApp(t *testing.T) {
func TestGenerateRunCommand(t *testing.T) {
hostName := "test-hostname"
tests := []struct {
pod *api.Pod
uuid string
netnsName string
networkPlugin network.NetworkPlugin
pod *api.Pod
uuid string
netnsName string
dnsServers []string
dnsSearches []string
@@ -1083,6 +1155,7 @@ func TestGenerateRunCommand(t *testing.T) {
}{
// Case #0, returns error.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@@ -1099,6 +1172,7 @@ func TestGenerateRunCommand(t *testing.T) {
},
// Case #1, returns no dns, with private-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@@ -1110,10 +1184,11 @@ func TestGenerateRunCommand(t *testing.T) {
[]string{},
"pod-hostname-foo",
nil,
" --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo",
"/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo",
},
// Case #2, returns no dns, with host-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@@ -1134,6 +1209,7 @@ func TestGenerateRunCommand(t *testing.T) {
},
// Case #3, returns dns, dns searches, with private-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@@ -1150,10 +1226,11 @@ func TestGenerateRunCommand(t *testing.T) {
[]string{"."},
"pod-hostname-foo",
nil,
" --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
"/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
},
// Case #4, returns no dns, dns searches, with host-network.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@@ -1172,10 +1249,28 @@ func TestGenerateRunCommand(t *testing.T) {
nil,
fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=%s rkt-uuid-foo", hostName),
},
// Case #5, with no-op plugin, returns --net=rkt.kubernetes.io, with dns and dns search.
{
&network.NoopNetworkPlugin{},
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
},
Spec: api.PodSpec{},
},
"rkt-uuid-foo",
"default",
[]string{"127.0.0.1"},
[]string{"."},
"pod-hostname-foo",
nil,
"/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=rkt.kubernetes.io --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
},
}
rkt := &Runtime{
os: &kubetesting.FakeOS{HostName: hostName},
nsenterPath: "/usr/bin/nsenter",
os: &kubetesting.FakeOS{HostName: hostName},
config: &Config{
Path: "/bin/rkt/rkt",
Stage1Image: "/bin/rkt/stage1-coreos.aci",
@@ -1187,6 +1282,7 @@ func TestGenerateRunCommand(t *testing.T) {
for i, tt := range tests {
testCaseHint := fmt.Sprintf("test case #%d", i)
rkt.networkPlugin = tt.networkPlugin
rkt.runtimeHelper = &fakeRuntimeHelper{tt.dnsServers, tt.dnsSearches, tt.hostName, "", tt.err}
rkt.execer = &utilexec.FakeExec{CommandScript: []utilexec.FakeCommandAction{func(cmd string, args ...string) utilexec.Cmd {
return utilexec.InitFakeCmd(&utilexec.FakeCmd{}, cmd, args...)