-
Let’s talk about it first. I recently studied k8s dns and read a lot of related blogs. I found that many of them are the same content. Most of them are reprinted or copied, and they are sent out without verification. Again, condemn these people first!
-
Let's get started!
-
Usage scenario: ubuntu16.04, kubernetes1.4 and above, the cluster does not have certifications such as CA! Other scenes are for reference only!
1. Why deploy DNS
kubernetes provides the concept of service. You can access the services provided by pods through VIP (Service IP is virtual IP (VIP)), but there is still a problem when using it: how to know the VIP of an application? For example, we have two applications, one is app and the other is db. Each application is managed by rc or deployment, and provides services by exposing ports through service. The app needs to connect to the db application, we only know the name of the db application, but we don't know its VIP address. This involves the problem of == service discovery ==.
- In response to the above problems, k8s provides three == service discovery == methods:
Method 1. Query through the API provided by kubernetes
This method is relatively simple, but has many problems. First of all, each application needs to write the logic of querying dependent services at startup, which itself is repetitive and increases the complexity of the application; secondly, this also causes the application to depend on kubernetes and cannot be deployed and run separately (of course, if you add configuration options by adding configuration options) It can also be done, but again it adds complexity).
Method 2. Environment Variables
K8S supports it by default. This method is based on docker. When each pod starts, k8s will write the IP and port information of all existing services to the newly started pod in the form of environment variables, so that applications in the pod can read the environment variables to obtain the addresses of dependent services information. But there is a big problem: the dependent service must exist before the pod starts, otherwise it will not appear in the environment variables.
Method 3. DNS (the most ideal solution)
The application only needs to know the specific name of the service, and does not need to care about the actual IP address of the service. The intermediate == service name -- IP== conversion is done automatically by DNS. The translation between name and ip is a function of the DNS system.
2. DNS version introduction
The DNS service is not an independent system service, but an ==addon==, which is installed as a ==plugin== and is not required for a kubernetes cluster (==but it is highly recommended to install==). You can think of it as an application running on a cluster, but this application is special. There are two commonly used DNS configuration methods. Before 1.3, the method of etcd + kube2sky + skydns + exechealthz is used, and after 1.3, the method of kubedns + dnsmasq + sidecar can be used.
The functions of these components are described below
- Before version 1.3
- etcd: DNS storage
- kube2sky: Monitor changes of Service resources through K8S API, and register services to etcd
- skydns: Provides DNS domain name resolution service, and provides DNS query service for Pods in the cluster
- exechealthz: Provides health check function for skydns service
Architecture diagram
- After version 1.3
- kubedns: Monitor changes of Service resources through K8S API, and use tree structure to save DNS records in memory
- dnsmasq: Provides DNS domain name resolution service, and provides DNS query service for Pods in the cluster
- exechealthz: Provides health check function for kubedns and dnsmasq services, which is more complete
Architecture diagram
It can be seen from this that kubedns replaces the two functions of etcd and kube2sky, provides query services for dnsmasq, and uses a tree structure to save DNS records in memory
The role of dnsmasq in the kube-dns plugin: Obtain DNS rules through the kubedns container, provide DNS query services in the cluster, provide DNS caching, improve query performance, reduce the pressure on kubedns containers, and improve stability
3. Build DNS
There are many building tutorials on the Internet, I try them one by one! found no success! so awkward! It may be due to different k8s versions or different k8s cluster construction methods, or the introduction of modules such as ServiceAccount, token and authentication. It will not be described in detail here. Through my unremitting efforts (please allow me to install a B..), I finally realized a simplified DNS solution: kubedns + dnsmasq + exechealthz, the specific yaml file can be viewed here .
Without further ado, let's go directly to the content!
dns-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-dns-v15
namespace: kube-system
labels:
k8s-app: kube-dns
version: v15
kubernetes.io/cluster-service: "true"
spec:
replicas: 1
selector:
k8s-app: kube-dns
version: v15
template:
metadata:
labels:
k8s-app: kube-dns
version: v15
kubernetes.io/cluster-service: "true"
spec:
containers:
- name: kubedns
image: registry.cn-hangzhou.aliyuncs.com/sjq-k8s/kubedns-amd64:1.5
resources:
# TODO: Set memory limits when we've profiled the container for large
# clusters, then set request = limit to keep this container in
# guaranteed class. Currently, this container falls into the
# "burstable" category so the kubelet doesn't backoff from restarting it.
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /readiness
port: 8081
scheme: HTTP
# we poll on pod startup for the Kubernetes master service and
# only setup the /readiness HTTP server once that's available.
initialDelaySeconds: 30
timeoutSeconds: 5
args:
# command = "/kube-dns"
- --kube_master_url=http://192.168.122.10:8080
- --domain=cluster.local.
- --dns-port=10053
ports:
- containerPort: 10053
name: dns-local
protocol: UDP
- containerPort: 10053
name: dns-tcp-local
protocol: TCP
- name: dnsmasq
image: registry.cn-hangzhou.aliyuncs.com/sjq-k8s/dnsmasq:1.1
args:
- --cache-size=1000
- --no-resolv
- --server=127.0.0.1#10053
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- name: healthz
image: registry.cn-hangzhou.aliyuncs.com/sjq-k8s/exechealthz-amd64:1.0
resources:
# keep request = limit to keep this container in guaranteed class
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
args:
- -cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
- -port=8080
ports:
- containerPort: 8080
protocol: TCP
dnsPolicy: Default # Don't use cluster DNS.
Because the mirror is blocked by the wall, I directly replaced it with the mirror on my Alibaba Cloud, which can be downloaded and used directly. The IP in - --kube_master_url= http://192.168.122.10:8080 remember to replace it with your own master ip and port
dns-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 192.168.3.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
Among them, replace the ip in clusterIP: 192.168.3.10 with the dns cluster ip you actually defined.
Create rc and service
$ kubectl create -f skydns-rc.yaml
replicationcontroller "kube-dns-v15" created
$ kubectl create -f skydns-svc.yaml
service "kube-dns" created
Check if it is running
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
kube-dns-v15-32902 3/3 Running 0 2m
$
$ kubectl get svc -n kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns 192.168.3.10 <none> 53/UDP,53/TCP 7m
4. Verify that dns is valid
Verify that the DNS service is working by launching a busybox with the nslookup tool:
busybox.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
start up
$ kubectl create -f busybox.yaml
pod "busybox" created
After the pod runs successfully, test via kubectl exec <containerId> nslookup
$ kubectl exec busybox -- nslookup kubernetes
Server: 192.168.3.10
Address 1: 192.168.3.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes
Address 1: 192.168.3.1 kubernetes.default.svc.cluster.local
success!
If the namespace of the tested service is not default, then the namespace must be added, otherwise the following error will be reported
$ kubectl exec busybox -- nslookup kube-dns
nslookup: can't resolve 'kube-dns'
Server: 192.168.3.10
Address 1: 192.168.3.10 kube-dns.kube-system.svc.cluster.local
After adding the namespace
$ kubectl exec busybox -- nslookup kube-dns.kube-system
Server: 192.168.3.10
Address 1: 192.168.3.10 kube-dns.kube-system.svc.cluster.local
Name: kube-dns.kube-system
Address 1: 192.168.3.10 kube-dns.kube-system.svc.cluster.local
5. Actual build screenshots
Create a success graph
Verification success graph
possible problems
statement! The above content is purely personal creation! Please indicate the source when reprinting, thank you!
If this article is helpful to you, I hope you can move your little hands to like it. If there are any mistakes, please correct me! If there are any similarities! Pure coincidence!