log_path_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package e2enode
  14. import (
  15. "context"
  16. v1 "k8s.io/api/core/v1"
  17. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  18. "k8s.io/apimachinery/pkg/util/uuid"
  19. "k8s.io/kubernetes/pkg/kubelet"
  20. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  21. "k8s.io/kubernetes/test/e2e/framework"
  22. e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
  23. e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
  24. "github.com/onsi/ginkgo"
  25. )
  26. const (
  27. logString = "This is the expected log content of this node e2e test"
  28. logContainerName = "logger"
  29. )
  30. var _ = framework.KubeDescribe("ContainerLogPath [NodeConformance]", func() {
  31. f := framework.NewDefaultFramework("kubelet-container-log-path")
  32. var podClient *framework.PodClient
  33. ginkgo.Describe("Pod with a container", func() {
  34. ginkgo.Context("printed log to stdout", func() {
  35. makeLogPod := func(podName, log string) *v1.Pod {
  36. return &v1.Pod{
  37. ObjectMeta: metav1.ObjectMeta{
  38. Name: podName,
  39. },
  40. Spec: v1.PodSpec{
  41. // this pod is expected to exit successfully
  42. RestartPolicy: v1.RestartPolicyNever,
  43. Containers: []v1.Container{
  44. {
  45. Image: busyboxImage,
  46. Name: logContainerName,
  47. Command: []string{"sh", "-c", "echo " + log},
  48. },
  49. },
  50. },
  51. }
  52. }
  53. makeLogCheckPod := func(podName, log, expectedLogPath string) *v1.Pod {
  54. hostPathType := new(v1.HostPathType)
  55. *hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate))
  56. return &v1.Pod{
  57. ObjectMeta: metav1.ObjectMeta{
  58. Name: podName,
  59. },
  60. Spec: v1.PodSpec{
  61. // this pod is expected to exit successfully
  62. RestartPolicy: v1.RestartPolicyNever,
  63. Containers: []v1.Container{
  64. {
  65. Image: busyboxImage,
  66. Name: podName,
  67. // If we find expected log file and contains right content, exit 0
  68. // else, keep checking until test timeout
  69. Command: []string{"sh", "-c", "while true; do if [ -e " + expectedLogPath + " ] && grep -q " + log + " " + expectedLogPath + "; then exit 0; fi; sleep 1; done"},
  70. VolumeMounts: []v1.VolumeMount{
  71. {
  72. Name: "logdir",
  73. // mount ContainerLogsDir to the same path in container
  74. MountPath: expectedLogPath,
  75. ReadOnly: true,
  76. },
  77. },
  78. },
  79. },
  80. Volumes: []v1.Volume{
  81. {
  82. Name: "logdir",
  83. VolumeSource: v1.VolumeSource{
  84. HostPath: &v1.HostPathVolumeSource{
  85. Path: expectedLogPath,
  86. Type: hostPathType,
  87. },
  88. },
  89. },
  90. },
  91. },
  92. }
  93. }
  94. createAndWaitPod := func(pod *v1.Pod) error {
  95. podClient.Create(pod)
  96. return e2epod.WaitForPodSuccessInNamespace(f.ClientSet, pod.Name, f.Namespace.Name)
  97. }
  98. var logPodName string
  99. ginkgo.BeforeEach(func() {
  100. if framework.TestContext.ContainerRuntime == "docker" {
  101. // Container Log Path support requires JSON logging driver.
  102. // It does not work when Docker daemon is logging to journald.
  103. d, err := getDockerLoggingDriver()
  104. framework.ExpectNoError(err)
  105. if d != "json-file" {
  106. e2eskipper.Skipf("Skipping because Docker daemon is using a logging driver other than \"json-file\": %s", d)
  107. }
  108. // Even if JSON logging is in use, this test fails if SELinux support
  109. // is enabled, since the isolation provided by the SELinux policy
  110. // prevents processes running inside Docker containers (under SELinux
  111. // type svirt_lxc_net_t) from accessing the log files which are owned
  112. // by Docker (and labeled with the container_var_lib_t type.)
  113. //
  114. // Therefore, let's also skip this test when running with SELinux
  115. // support enabled.
  116. e, err := isDockerSELinuxSupportEnabled()
  117. framework.ExpectNoError(err)
  118. if e {
  119. e2eskipper.Skipf("Skipping because Docker daemon is running with SELinux support enabled")
  120. }
  121. }
  122. podClient = f.PodClient()
  123. logPodName = "log-pod-" + string(uuid.NewUUID())
  124. err := createAndWaitPod(makeLogPod(logPodName, logString))
  125. framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logPodName)
  126. })
  127. ginkgo.It("should print log to correct log path", func() {
  128. logDir := kubelet.ContainerLogsDir
  129. // get containerID from created Pod
  130. createdLogPod, err := podClient.Get(context.TODO(), logPodName, metav1.GetOptions{})
  131. logContainerID := kubecontainer.ParseContainerID(createdLogPod.Status.ContainerStatuses[0].ContainerID)
  132. framework.ExpectNoError(err, "Failed to get pod: %s", logPodName)
  133. // build log file path
  134. expectedlogFile := logDir + "/" + logPodName + "_" + f.Namespace.Name + "_" + logContainerName + "-" + logContainerID.ID + ".log"
  135. logCheckPodName := "log-check-" + string(uuid.NewUUID())
  136. err = createAndWaitPod(makeLogCheckPod(logCheckPodName, logString, expectedlogFile))
  137. framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logCheckPodName)
  138. })
  139. ginkgo.It("should print log to correct cri log path", func() {
  140. logCRIDir := "/var/log/pods"
  141. // get podID from created Pod
  142. createdLogPod, err := podClient.Get(context.TODO(), logPodName, metav1.GetOptions{})
  143. framework.ExpectNoError(err, "Failed to get pod: %s", logPodName)
  144. podNs := createdLogPod.Namespace
  145. podName := createdLogPod.Name
  146. podID := string(createdLogPod.UID)
  147. // build log cri file path
  148. expectedCRILogFile := logCRIDir + "/" + podNs + "_" + podName + "_" + podID + "/" + logContainerName + "/0.log"
  149. logCRICheckPodName := "log-cri-check-" + string(uuid.NewUUID())
  150. err = createAndWaitPod(makeLogCheckPod(logCRICheckPodName, logString, expectedCRILogFile))
  151. framework.ExpectNoError(err, "Failed waiting for pod: %s to enter success state", logCRICheckPodName)
  152. })
  153. })
  154. })
  155. })