mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 02:34:03 +00:00
Merge pull request #10266 from ArtfulCoder/kubelet_resolv
update docker's resolv.conf file with options ndots:5
This commit is contained in:
commit
2bb4cf3f8f
6
contrib/for-tests/jessie-dnsutils/Dockerfile
Normal file
6
contrib/for-tests/jessie-dnsutils/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM debian:jessie
|
||||||
|
MAINTAINER Abhishek Shah "abshah@google.com"
|
||||||
|
|
||||||
|
RUN apt-get -q update && \
|
||||||
|
apt-get install -y dnsutils && \
|
||||||
|
apt-get clean
|
8
contrib/for-tests/jessie-dnsutils/Makefile
Normal file
8
contrib/for-tests/jessie-dnsutils/Makefile
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
all:
|
||||||
|
@echo "try 'make image' or 'make push'"
|
||||||
|
|
||||||
|
image:
|
||||||
|
docker build -t gcr.io/google_containers/jessie-dnsutils .
|
||||||
|
|
||||||
|
push:
|
||||||
|
gcloud docker push gcr.io/google_containers/jessie-dnsutils
|
@ -60,6 +60,10 @@ const (
|
|||||||
|
|
||||||
kubernetesPodLabel = "io.kubernetes.pod.data"
|
kubernetesPodLabel = "io.kubernetes.pod.data"
|
||||||
kubernetesContainerLabel = "io.kubernetes.container.name"
|
kubernetesContainerLabel = "io.kubernetes.container.name"
|
||||||
|
// ndots specifies the minimum number of dots that a domain name must contain for the resolver to consider it as FQDN (fully-qualified)
|
||||||
|
// we want to able to consider SRV lookup names like _dns._udp.kube-dns.default.svc to be considered relative.
|
||||||
|
// hence, setting ndots to be 5.
|
||||||
|
ndotsDNSOption = "options ndots:5\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DockerManager implements the Runtime interface.
|
// DockerManager implements the Runtime interface.
|
||||||
@ -1221,6 +1225,13 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
|
|||||||
}
|
}
|
||||||
if container.Name == PodInfraContainerName {
|
if container.Name == PodInfraContainerName {
|
||||||
util.ApplyOomScoreAdj(containerInfo.State.Pid, podOomScoreAdj)
|
util.ApplyOomScoreAdj(containerInfo.State.Pid, podOomScoreAdj)
|
||||||
|
// currently, Docker does not have a flag by which the ndots option can be passed.
|
||||||
|
// (A seperate issue has been filed with Docker to add a ndots flag)
|
||||||
|
// The addNDotsOption call appends the ndots option to the resolv.conf file generated by docker.
|
||||||
|
// This resolv.conf file is shared by all containers of the same pod, and needs to be modified only once per pod.
|
||||||
|
// we modify it when the pause container is created since it is the first container created in the pod since it holds
|
||||||
|
// the networking namespace.
|
||||||
|
err = addNDotsOption(containerInfo.ResolvConfPath)
|
||||||
} else {
|
} else {
|
||||||
// Children processes of docker daemon will inheritant the OOM score from docker
|
// Children processes of docker daemon will inheritant the OOM score from docker
|
||||||
// daemon process. We explicitly apply OOM score 0 by default to the user
|
// daemon process. We explicitly apply OOM score 0 by default to the user
|
||||||
@ -1231,6 +1242,36 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
|
|||||||
return kubeletTypes.DockerID(id), err
|
return kubeletTypes.DockerID(id), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addNDotsOption(resolvFilePath string) error {
|
||||||
|
if len(resolvFilePath) == 0 {
|
||||||
|
glog.Errorf("DNS ResolvConfPath is empty.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(resolvFilePath); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("DNS ResolvConfPath specified but does not exist. It could not be updated: %s", resolvFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(4).Infof("DNS ResolvConfPath exists: %s. Will attempt to add ndots option: %s", resolvFilePath, ndotsDNSOption)
|
||||||
|
|
||||||
|
if err := appendToFile(resolvFilePath, ndotsDNSOption); err != nil {
|
||||||
|
glog.Errorf("resolv.conf could not be updated. err:%v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendToFile(filePath, stringToAppend string) error {
|
||||||
|
f, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = f.WriteString(stringToAppend)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// createPodInfraContainer starts the pod infra container for a pod. Returns the docker container ID of the newly created container.
|
// createPodInfraContainer starts the pod infra container for a pod. Returns the docker container ID of the newly created container.
|
||||||
func (dm *DockerManager) createPodInfraContainer(pod *api.Pod) (kubeletTypes.DockerID, error) {
|
func (dm *DockerManager) createPodInfraContainer(pod *api.Pod) (kubeletTypes.DockerID, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
117
test/e2e/dns.go
117
test/e2e/dns.go
@ -38,7 +38,7 @@ var dnsServiceLableSelector = labels.Set{
|
|||||||
"kubernetes.io/cluster-service": "true",
|
"kubernetes.io/cluster-service": "true",
|
||||||
}.AsSelector()
|
}.AsSelector()
|
||||||
|
|
||||||
func createDNSPod(namespace, probeCmd string) *api.Pod {
|
func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod {
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
TypeMeta: api.TypeMeta{
|
TypeMeta: api.TypeMeta{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
@ -78,7 +78,18 @@ func createDNSPod(namespace, probeCmd string) *api.Pod {
|
|||||||
{
|
{
|
||||||
Name: "querier",
|
Name: "querier",
|
||||||
Image: "gcr.io/google_containers/dnsutils",
|
Image: "gcr.io/google_containers/dnsutils",
|
||||||
Command: []string{"sh", "-c", probeCmd},
|
Command: []string{"sh", "-c", wheezyProbeCmd},
|
||||||
|
VolumeMounts: []api.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: "results",
|
||||||
|
MountPath: "/results",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "jessie-querier",
|
||||||
|
Image: "gcr.io/google_containers/jessie-dnsutils",
|
||||||
|
Command: []string{"sh", "-c", jessieProbeCmd},
|
||||||
VolumeMounts: []api.VolumeMount{
|
VolumeMounts: []api.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "results",
|
Name: "results",
|
||||||
@ -92,7 +103,7 @@ func createDNSPod(namespace, probeCmd string) *api.Pod {
|
|||||||
return pod
|
return pod
|
||||||
}
|
}
|
||||||
|
|
||||||
func createProbeCommand(namesToResolve []string) (string, []string) {
|
func createProbeCommand(namesToResolve []string, fileNamePrefix string) (string, []string) {
|
||||||
fileNames := make([]string, 0, len(namesToResolve)*2)
|
fileNames := make([]string, 0, len(namesToResolve)*2)
|
||||||
probeCmd := "for i in `seq 1 600`; do "
|
probeCmd := "for i in `seq 1 600`; do "
|
||||||
for _, name := range namesToResolve {
|
for _, name := range namesToResolve {
|
||||||
@ -103,10 +114,10 @@ func createProbeCommand(namesToResolve []string) (string, []string) {
|
|||||||
if strings.HasPrefix(name, "_") {
|
if strings.HasPrefix(name, "_") {
|
||||||
lookup = "SRV"
|
lookup = "SRV"
|
||||||
}
|
}
|
||||||
fileName := fmt.Sprintf("udp@%s", name)
|
fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, name)
|
||||||
fileNames = append(fileNames, fileName)
|
fileNames = append(fileNames, fileName)
|
||||||
probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName)
|
probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName)
|
||||||
fileName = fmt.Sprintf("tcp@%s", name)
|
fileName = fmt.Sprintf("%s_tcp@%s", fileNamePrefix, name)
|
||||||
fileNames = append(fileNames, fileName)
|
fileNames = append(fileNames, fileName)
|
||||||
probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName)
|
probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName)
|
||||||
}
|
}
|
||||||
@ -140,6 +151,36 @@ func assertFilesExist(fileNames []string, fileDir string, pod *api.Pod, client *
|
|||||||
Expect(len(failed)).To(Equal(0))
|
Expect(len(failed)).To(Equal(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateDNSResults(f *Framework, pod *api.Pod, fileNames []string) {
|
||||||
|
|
||||||
|
By("submitting the pod to kubernetes")
|
||||||
|
podClient := f.Client.Pods(f.Namespace.Name)
|
||||||
|
defer func() {
|
||||||
|
By("deleting the pod")
|
||||||
|
defer GinkgoRecover()
|
||||||
|
podClient.Delete(pod.Name, nil)
|
||||||
|
}()
|
||||||
|
if _, err := podClient.Create(pod); err != nil {
|
||||||
|
Failf("Failed to create %s pod: %v", pod.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectNoError(f.WaitForPodRunning(pod.Name))
|
||||||
|
|
||||||
|
By("retrieving the pod")
|
||||||
|
pod, err := podClient.Get(pod.Name)
|
||||||
|
if err != nil {
|
||||||
|
Failf("Failed to get pod %s: %v", pod.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find results for each expected name.
|
||||||
|
By("looking for the results for each expected name from probiers")
|
||||||
|
assertFilesExist(fileNames, "results", pod, f.Client)
|
||||||
|
|
||||||
|
// TODO: probe from the host, too.
|
||||||
|
|
||||||
|
Logf("DNS probes using %s succeeded\n", pod.Name)
|
||||||
|
}
|
||||||
|
|
||||||
var _ = Describe("DNS", func() {
|
var _ = Describe("DNS", func() {
|
||||||
f := NewFramework("dns")
|
f := NewFramework("dns")
|
||||||
|
|
||||||
@ -175,38 +216,13 @@ var _ = Describe("DNS", func() {
|
|||||||
namesToResolve = append(namesToResolve, "metadata")
|
namesToResolve = append(namesToResolve, "metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
probeCmd, fileNames := createProbeCommand(namesToResolve)
|
wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, "wheezy")
|
||||||
|
jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, "jessie")
|
||||||
|
|
||||||
// Run a pod which probes DNS and exposes the results by HTTP.
|
// Run a pod which probes DNS and exposes the results by HTTP.
|
||||||
By("creating a pod to probe DNS")
|
By("creating a pod to probe DNS")
|
||||||
pod := createDNSPod(f.Namespace.Name, probeCmd)
|
pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd)
|
||||||
|
validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...))
|
||||||
By("submitting the pod to kubernetes")
|
|
||||||
podClient = f.Client.Pods(f.Namespace.Name)
|
|
||||||
defer func() {
|
|
||||||
By("deleting the pod")
|
|
||||||
defer GinkgoRecover()
|
|
||||||
podClient.Delete(pod.Name, nil)
|
|
||||||
}()
|
|
||||||
if _, err := podClient.Create(pod); err != nil {
|
|
||||||
Failf("Failed to create %s pod: %v", pod.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectNoError(f.WaitForPodRunning(pod.Name))
|
|
||||||
|
|
||||||
By("retrieving the pod")
|
|
||||||
pod, err = podClient.Get(pod.Name)
|
|
||||||
if err != nil {
|
|
||||||
Failf("Failed to get pod %s: %v", pod.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find results for each expected name.
|
|
||||||
By("looking for the results for each expected name")
|
|
||||||
assertFilesExist(fileNames, "results", pod, f.Client)
|
|
||||||
|
|
||||||
// TODO: probe from the host, too.
|
|
||||||
|
|
||||||
Logf("DNS probes using %s succeeded\n", pod.Name)
|
|
||||||
})
|
})
|
||||||
It("should provide DNS for services", func() {
|
It("should provide DNS for services", func() {
|
||||||
if providerIs("vagrant") {
|
if providerIs("vagrant") {
|
||||||
@ -283,38 +299,15 @@ var _ = Describe("DNS", func() {
|
|||||||
fmt.Sprintf("_http._tcp.%s.%s.svc", regularService.Name, f.Namespace.Name),
|
fmt.Sprintf("_http._tcp.%s.%s.svc", regularService.Name, f.Namespace.Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
probeCmd, fileNames := createProbeCommand(namesToResolve)
|
wheezyProbeCmd, wheezyFileNames := createProbeCommand(namesToResolve, "wheezy")
|
||||||
|
jessieProbeCmd, jessieFileNames := createProbeCommand(namesToResolve, "jessie")
|
||||||
|
|
||||||
// Run a pod which probes DNS and exposes the results by HTTP.
|
// Run a pod which probes DNS and exposes the results by HTTP.
|
||||||
By("creating a pod to probe DNS")
|
By("creating a pod to probe DNS")
|
||||||
pod := createDNSPod(f.Namespace.Name, probeCmd)
|
pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd)
|
||||||
pod.ObjectMeta.Labels = testServiceSelector
|
pod.ObjectMeta.Labels = testServiceSelector
|
||||||
|
|
||||||
By("submitting the pod to kubernetes")
|
validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...))
|
||||||
podClient = f.Client.Pods(f.Namespace.Name)
|
|
||||||
defer func() {
|
|
||||||
By("deleting the pod")
|
|
||||||
defer GinkgoRecover()
|
|
||||||
podClient.Delete(pod.Name, nil)
|
|
||||||
}()
|
|
||||||
if _, err := podClient.Create(pod); err != nil {
|
|
||||||
Failf("Failed to create %s pod: %v", pod.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectNoError(f.WaitForPodRunning(pod.Name))
|
|
||||||
|
|
||||||
By("retrieving the pod")
|
|
||||||
pod, err = podClient.Get(pod.Name)
|
|
||||||
if err != nil {
|
|
||||||
Failf("Failed to get pod %s: %v", pod.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find results for each expected name.
|
|
||||||
By("looking for the results for each expected name")
|
|
||||||
assertFilesExist(fileNames, "results", pod, f.Client)
|
|
||||||
|
|
||||||
// TODO: probe from the host, too.
|
|
||||||
|
|
||||||
Logf("DNS probes using %s succeeded\n", pod.Name)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user