1 Star 0 Fork 0

zhuchance / kubernetes

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
container_probe.go 14.16 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright 2015 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 common
import (
"fmt"
"time"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/uuid"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/test/e2e/framework"
testutils "k8s.io/kubernetes/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
imageutils "k8s.io/kubernetes/test/utils/image"
)
const (
probTestContainerName = "test-webserver"
probTestInitialDelaySeconds = 15
defaultObservationTimeout = time.Minute * 4
)
var _ = framework.KubeDescribe("Probing container", func() {
f := framework.NewDefaultFramework("container-probe")
var podClient *framework.PodClient
probe := webserverProbeBuilder{}
BeforeEach(func() {
podClient = f.PodClient()
})
/*
Testname: pods-readiness-probe-initial-delay
Description: Make sure that pod with readiness probe should not be
ready before initial delay and never restart.
*/
framework.ConformanceIt("with readiness probe should not be ready before initial delay and never restart [NodeConformance]", func() {
p := podClient.Create(makePodSpec(probe.withInitialDelay().build(), nil))
f.WaitForPodReady(p.Name)
p, err := podClient.Get(p.Name, metav1.GetOptions{})
framework.ExpectNoError(err)
isReady, err := testutils.PodRunningReady(p)
framework.ExpectNoError(err)
Expect(isReady).To(BeTrue(), "pod should be ready")
// We assume the pod became ready when the container became ready. This
// is true for a single container pod.
readyTime, err := getTransitionTimeForReadyCondition(p)
framework.ExpectNoError(err)
startedTime, err := getContainerStartedTime(p, probTestContainerName)
framework.ExpectNoError(err)
framework.Logf("Container started at %v, pod became ready at %v", startedTime, readyTime)
initialDelay := probTestInitialDelaySeconds * time.Second
if readyTime.Sub(startedTime) < initialDelay {
framework.Failf("Pod became ready before it's %v initial delay", initialDelay)
}
restartCount := getRestartCount(p)
Expect(restartCount == 0).To(BeTrue(), "pod should have a restart count of 0 but got %v", restartCount)
})
/*
Testname: pods-readiness-probe-failure
Description: Make sure that pod with readiness probe that fails should
never be ready and never restart.
*/
framework.ConformanceIt("with readiness probe that fails should never be ready and never restart [NodeConformance]", func() {
p := podClient.Create(makePodSpec(probe.withFailing().build(), nil))
Consistently(func() (bool, error) {
p, err := podClient.Get(p.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
return podutil.IsPodReady(p), nil
}, 1*time.Minute, 1*time.Second).ShouldNot(BeTrue(), "pod should not be ready")
p, err := podClient.Get(p.Name, metav1.GetOptions{})
framework.ExpectNoError(err)
isReady, err := testutils.PodRunningReady(p)
Expect(isReady).NotTo(BeTrue(), "pod should be not ready")
restartCount := getRestartCount(p)
Expect(restartCount == 0).To(BeTrue(), "pod should have a restart count of 0 but got %v", restartCount)
})
/*
Testname: pods-cat-liveness-probe-restarted
Description: Make sure the pod is restarted with a cat /tmp/health
liveness probe.
*/
framework.ConformanceIt("should be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance]", func() {
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-exec",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: busyboxImage,
Command: []string{"/bin/sh", "-c", "echo ok >/tmp/health; sleep 10; rm -rf /tmp/health; sleep 600"},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
Exec: &v1.ExecAction{
Command: []string{"cat", "/tmp/health"},
},
},
InitialDelaySeconds: 15,
FailureThreshold: 1,
},
},
},
},
}, 1, defaultObservationTimeout)
})
/*
Testname: pods-cat-liveness-probe-not-restarted
Description: Make sure the pod is not restarted with a cat /tmp/health
liveness probe.
*/
framework.ConformanceIt("should *not* be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance]", func() {
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-exec",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: busyboxImage,
Command: []string{"/bin/sh", "-c", "echo ok >/tmp/health; sleep 600"},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
Exec: &v1.ExecAction{
Command: []string{"cat", "/tmp/health"},
},
},
InitialDelaySeconds: 15,
FailureThreshold: 1,
},
},
},
},
}, 0, defaultObservationTimeout)
})
/*
Testname: pods-http-liveness-probe-restarted
Description: Make sure when http liveness probe fails, the pod should
be restarted.
*/
framework.ConformanceIt("should be restarted with a /healthz http liveness probe [NodeConformance]", func() {
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-http",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: imageutils.GetE2EImage(imageutils.Liveness),
Command: []string{"/server"},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Path: "/healthz",
Port: intstr.FromInt(8080),
},
},
InitialDelaySeconds: 15,
FailureThreshold: 1,
},
},
},
},
}, 1, defaultObservationTimeout)
})
// Slow by design (5 min)
/*
Testname: pods-restart-count
Description: Make sure when a pod gets restarted, its start count
should increase.
*/
framework.ConformanceIt("should have monotonically increasing restart count [Slow][NodeConformance]", func() {
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-http",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: imageutils.GetE2EImage(imageutils.Liveness),
Command: []string{"/server"},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Path: "/healthz",
Port: intstr.FromInt(8080),
},
},
InitialDelaySeconds: 5,
FailureThreshold: 1,
},
},
},
},
}, 5, time.Minute*5)
})
/*
Testname: pods-http-liveness-probe-not-restarted
Description: Make sure when http liveness probe succeeds, the pod
should not be restarted.
*/
framework.ConformanceIt("should *not* be restarted with a /healthz http liveness probe [NodeConformance]", func() {
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-http",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: imageutils.GetE2EImage(imageutils.NginxSlim),
Ports: []v1.ContainerPort{{ContainerPort: 80}},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Path: "/",
Port: intstr.FromInt(80),
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 5,
FailureThreshold: 5, // to accommodate nodes which are slow in bringing up containers.
},
},
},
},
}, 0, defaultObservationTimeout)
})
/*
Testname: pods-docker-liveness-probe-timeout
Description: Make sure that the pod is restarted with a docker exec
liveness probe with timeout.
*/
It("should be restarted with a docker exec liveness probe with timeout ", func() {
// TODO: enable this test once the default exec handler supports timeout.
framework.Skipf("The default exec handler, dockertools.NativeExecHandler, does not support timeouts due to a limitation in the Docker Remote API")
runLivenessTest(f, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "liveness-exec",
Labels: map[string]string{"test": "liveness"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "liveness",
Image: busyboxImage,
Command: []string{"/bin/sh", "-c", "sleep 600"},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
Exec: &v1.ExecAction{
Command: []string{"/bin/sh", "-c", "sleep 10"},
},
},
InitialDelaySeconds: 15,
TimeoutSeconds: 1,
FailureThreshold: 1,
},
},
},
},
}, 1, defaultObservationTimeout)
})
})
func getContainerStartedTime(p *v1.Pod, containerName string) (time.Time, error) {
for _, status := range p.Status.ContainerStatuses {
if status.Name != containerName {
continue
}
if status.State.Running == nil {
return time.Time{}, fmt.Errorf("Container is not running")
}
return status.State.Running.StartedAt.Time, nil
}
return time.Time{}, fmt.Errorf("cannot find container named %q", containerName)
}
func getTransitionTimeForReadyCondition(p *v1.Pod) (time.Time, error) {
for _, cond := range p.Status.Conditions {
if cond.Type == v1.PodReady {
return cond.LastTransitionTime.Time, nil
}
}
return time.Time{}, fmt.Errorf("No ready condition can be found for pod")
}
func getRestartCount(p *v1.Pod) int {
count := 0
for _, containerStatus := range p.Status.ContainerStatuses {
count += int(containerStatus.RestartCount)
}
return count
}
func makePodSpec(readinessProbe, livenessProbe *v1.Probe) *v1.Pod {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "test-webserver-" + string(uuid.NewUUID())},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: probTestContainerName,
Image: imageutils.GetE2EImage(imageutils.TestWebserver),
LivenessProbe: livenessProbe,
ReadinessProbe: readinessProbe,
},
},
},
}
return pod
}
type webserverProbeBuilder struct {
failing bool
initialDelay bool
}
func (b webserverProbeBuilder) withFailing() webserverProbeBuilder {
b.failing = true
return b
}
func (b webserverProbeBuilder) withInitialDelay() webserverProbeBuilder {
b.initialDelay = true
return b
}
func (b webserverProbeBuilder) build() *v1.Probe {
probe := &v1.Probe{
Handler: v1.Handler{
HTTPGet: &v1.HTTPGetAction{
Port: intstr.FromInt(80),
Path: "/",
},
},
}
if b.initialDelay {
probe.InitialDelaySeconds = probTestInitialDelaySeconds
}
if b.failing {
probe.HTTPGet.Port = intstr.FromInt(81)
}
return probe
}
func runLivenessTest(f *framework.Framework, pod *v1.Pod, expectNumRestarts int, timeout time.Duration) {
podClient := f.PodClient()
ns := f.Namespace.Name
Expect(pod.Spec.Containers).NotTo(BeEmpty())
containerName := pod.Spec.Containers[0].Name
// At the end of the test, clean up by removing the pod.
defer func() {
By("deleting the pod")
podClient.Delete(pod.Name, metav1.NewDeleteOptions(0))
}()
By(fmt.Sprintf("Creating pod %s in namespace %s", pod.Name, ns))
podClient.Create(pod)
// Wait until the pod is not pending. (Here we need to check for something other than
// 'Pending' other than checking for 'Running', since when failures occur, we go to
// 'Terminated' which can cause indefinite blocking.)
framework.ExpectNoError(framework.WaitForPodNotPending(f.ClientSet, ns, pod.Name),
fmt.Sprintf("starting pod %s in namespace %s", pod.Name, ns))
framework.Logf("Started pod %s in namespace %s", pod.Name, ns)
// Check the pod's current state and verify that restartCount is present.
By("checking the pod's current state and verifying that restartCount is present")
pod, err := podClient.Get(pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, fmt.Sprintf("getting pod %s in namespace %s", pod.Name, ns))
initialRestartCount := podutil.GetExistingContainerStatus(pod.Status.ContainerStatuses, containerName).RestartCount
framework.Logf("Initial restart count of pod %s is %d", pod.Name, initialRestartCount)
// Wait for the restart state to be as desired.
deadline := time.Now().Add(timeout)
lastRestartCount := initialRestartCount
observedRestarts := int32(0)
for start := time.Now(); time.Now().Before(deadline); time.Sleep(2 * time.Second) {
pod, err = podClient.Get(pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, fmt.Sprintf("getting pod %s", pod.Name))
restartCount := podutil.GetExistingContainerStatus(pod.Status.ContainerStatuses, containerName).RestartCount
if restartCount != lastRestartCount {
framework.Logf("Restart count of pod %s/%s is now %d (%v elapsed)",
ns, pod.Name, restartCount, time.Since(start))
if restartCount < lastRestartCount {
framework.Failf("Restart count should increment monotonically: restart cont of pod %s/%s changed from %d to %d",
ns, pod.Name, lastRestartCount, restartCount)
}
}
observedRestarts = restartCount - initialRestartCount
if expectNumRestarts > 0 && int(observedRestarts) >= expectNumRestarts {
// Stop if we have observed more than expectNumRestarts restarts.
break
}
lastRestartCount = restartCount
}
// If we expected 0 restarts, fail if observed any restart.
// If we expected n restarts (n > 0), fail if we observed < n restarts.
if (expectNumRestarts == 0 && observedRestarts > 0) || (expectNumRestarts > 0 &&
int(observedRestarts) < expectNumRestarts) {
framework.Failf("pod %s/%s - expected number of restarts: %d, found restarts: %d",
ns, pod.Name, expectNumRestarts, observedRestarts)
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/meoom/kubernetes.git
git@gitee.com:meoom/kubernetes.git
meoom
kubernetes
kubernetes
v1.11.10-beta.0

搜索帮助

344bd9b3 5694891 D2dac590 5694891