kubernetes-ClusterDNS介绍、DNS配置策略和示例、headless ExternalName 示例

207 阅读4分钟

service name 和service ip之间的解析

Cluster DNS 监视api server上对所有service资源的创建、删除、变更操作

例如service的ip变动, 在内部生成新的 DNS和IP的记录

DNS的三种记录

  • servicename --> serviceip
  • PTR serviceip --> servicename
  • service name ---> service Port

Cluster DNS

Cluster DNS(CoreDNS)是Kubernetes集群的必备附件,负责为Kubernetes提供名称解析和服务发现

  • 每个Service资源对象,在CoreDNS上都会自动生成一个遵循格式的名称

    <service>.<ns>.svc.<zone>
    
    • 当前Service对象的名称
    • 当前Service对象所属的名称空间
    • 当前Kubernetes集群使用的域名后缀,默认为“cluster.local”
  • 围绕该名称会生成一些DNS格式的资源记录

举例

nfs namespace下部署了一个nfs-server

DNS为

nfs-server.nfs.svc.cluster.local

DNS搜索域

Cluster DNS 监听apiserver上所有服务的创建 变更

Pod中各容器默认会在/etc/resolv.conf中,将nameserver指向CoreDNS相关的Service的ClusterIP

由kubelet创建Pod时根据指定的配置自动注入

pod中会自动配置 /etc/resolv.conf

cat /etc/resolv.conf 
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local

image.png

image.png

Service在Cluster DNS上的资源记录

每个Service,在CoreDNS上都会有A/AAAA、SRV和PTR资源记录

A/AAAA资源记录

<service>.<ns>.svc.<zone>. <ttl> IN A <cluster-ip>
<service>.<ns>.svc.<zone>. <ttl> IN AAAA <cluster-ip>

SRV记录

为每个定义了名称的端口生成一个SRV记录,以支持服务发现

_<port>._<proto>.<service>.<ns>.svc.<zone>. <ttl> IN SRV <weight> <priority> <port-number> <service>.<ns>.svc.<zone>.

PTR资源记录

为每个A记录(例如a.b.c.d)或AAAA记录生成对应的PTR记录,例如

<d>.<c>.<b>.<a>.in-addr.arpa. <ttl> IN PTR <service>.<ns>.svc.<zone>.

h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.

Pod可基于Service的DNS名称向其发起服务访问请求

特殊类型的除外

  • externalname
  • 静态endpoint
  • headless service

Pod上的DNS解析策略

两个特殊的svc

kubernetes 使用service网络的第一个地址 image.png

kube-dns 使用service网络的第10个地址 image.png

Kubernetes支持在单个Pod资源规范上自定义DNS解析策略和配置,并组合生效

  • spec.dnsPolicy:DNS解析策略
  • spec.dnsConfig:名称解析机制

DNS解析策略 参数解释

  • Default
    • 一律交给节点上的DNS 运行的节点继承DNS解析相关的配置
  • ClusterFirst
    • pod默认的解析策略
    • coredns先解析优先
      • 于集群DNS服务上 解析集群域内的名称
    • 其他域名的解析则交由从节点继承而来的上游名称服务器
  • ClusterFirstWithHostNet
    • 特殊的场景
    • 集群内部的coredns先解析 然后再交给节点上的DNS
    • 专用于在设置了hostNetwork的Pod对象上 使用的ClusterFirst策略
  • None
    • 不使用自动配置功能了 需要手工配置
    • 用于忽略Kubernetes集群的默认设定,而仅使用由dnsConfig自定义的配置

DNS解析机制

  • nameservers <[]string>:DNS名称服务器列表,附加于由dnsPolicy生成的DNS名称服务器之后

  • searches <[]string>:DNS名称解析时的搜索域,附加由于dnsPolicy生成的搜索域之后

  • options <[]Object>:DNS解析选项列表,同dnsPolicy生成的解析选项合并成最终生效的定义

自定义配置示例

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-dnspolicy
  namespace: default
spec:
  containers:
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
  dnsPolicy: None
  dnsConfig:
    nameservers:
    - 10.96.0.10
    - 223.5.5.5
    - 223.6.6.6
    searches: 
    - svc.cluster.local
    - cluster.local
    - ilinux.io
    options:
    - name: ndots
      value: "5"

image.png

创建 ExternalName 示例

kind: Service
apiVersion: v1
metadata:
  name: externalname-redis-svc
  namespace: default
spec:
  type: ExternalName
  externalName: redis.ik8s.io
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379
    nodePort: 0
  selector: {}

image.png

pod中解析的情况 image.png

创建 headless 示例

yml配置

# Maintainer: MageEdu <mage@magedu.com>
# URL: http://www.magedu.com
---
kind: Service
apiVersion: v1
metadata:
  name: demoapp-headless-svc
spec:
  clusterIP: None
  selector:
    app: demoapp
  ports:
  - port: 80
    targetPort: 80
    name: http

kubectl get svc demoapp-headless-svc -o yaml

root@k8s-node01:~/learning-k8s/examples/services# kubectl get svc demoapp-headless-svc -o yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"demoapp-headless-svc","namespace":"default"},"spec":{"clusterIP":"None","ports":[{"name":"http","port":80,"targetPort":80}],"selector":{"app":"demoapp"}}}
  creationTimestamp: "2023-10-24T07:32:50Z"
  name: demoapp-headless-svc
  namespace: default
  resourceVersion: "245102"
  uid: db844a61-45fe-4061-bd85-8dc0ba75ff26
spec:
  clusterIP: None
  clusterIPs:
  - None
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: demoapp
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
root@k8s-node01:~/learning-k8s/examples/services#     

kubectl describe svc demoapp-headless-svc

root@k8s-node01:~/learning-k8s/examples/services# kubectl describe svc demoapp-headless-svc
Name:              demoapp-headless-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                None
IPs:               None
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.14:80,10.244.1.15:80,10.244.2.19:80
Session Affinity:  None
Events:            <none>

image.png

手工创建endpoint示例

apiVersion: discovery.k8s.io/v1beta1
kind: EndpointSlice
metadata:
  name: demoapp-01
  labels:
    kubernetes.io/service-name: demoapp
addressType: IPv4
ports:
  - name: http
    protocol: TCP
    port: 80
endpoints:
  - addresses:
    - "10.244.1.111"
    conditions:
      ready: true
  - addresses:
    - "10.244.1.222"
    conditions:
      ready: true

pod中 /etc/resolv.conf 配置的nameserver 是dns的ENDPOINTS

image.png

kubelet的配置文件中也需要配置正确的clusterDNS image.png