k8s指南-DNS与服务发现

2023-11-10

目录:
(1)k8s指南-概述
(2)k8s指南-架构
(3)k8s指南-工作负载(1)
(4)k8s指南-工作负载(2)
(5)k8s指南-工作负载(3)
(6)k8s指南-工作负载(4)
(7)k8s指南-Service
(8)k8s指南-Ingress
(9)k8s指南-DNS与服务发现
(10)K8S指南-平滑升级与自动扩缩容

K8S组件包括控制平面,Node组件和插件,而插件中必不可少的就是DNS。


K8S中的DNS服务

在k8s中,ip是随时可能发生变化的,特别是pod的ip,服务的ip也是可以改变的。因此服务或pod之间相互访问一般是通过域名来实现的。

在K8S集群中,Kubernetes为Service和Pod创建DNS记录。

Service DNS

普通的service会以svc-name.namespace.svc.cluster.local的形式生成DNS记录,并解析到该Service的Cluster IP。其中,namespace是命名空间,cluster.local 是集群域名。
Headless Service(没有Cluster IP)也会以同样的格式生成DNS记录,只不过其解析的ip地址不是一个,而是一组被选中的pod的IP,当然如果没有backend则不做处理。

在上一篇关于Ingress的blog中创建过my-nginx的服务,并有关联的pods。下面在pod中查一下域名:

nslookup my-nginx.default.svc.cluster.local

Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   my-nginx.default.svc.cluster.local
Address: 10.100.64.53

可以看到确实与Service的集群IP地址相同:

kubectl get service -n default
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx     ClusterIP   10.100.64.53   <none>        80/TCP    23h

Pod DNS

Pod会以pod-ip.namespace.pod.cluster.local的形式生成记录,注意ip地址中点换成横杠。

还是以my-nginx为例,其pod的IP地址为:10.1.0.82,随便在k8s中选一个pod,查询该域名:

nslookup 10-1-0-82.default.pod.cluster.local

Server:         10.96.0.10
Address:        10.96.0.10:53

Name:   10-1-0-82.default.pod.cluster.local
Address: 10.1.0.82

事实上,对于以Deployment或Daemonset类型创建的Pod,还会设置另一个域名,格式为pod-ip.{deployment/daemonset-name}.namespace.svc.cluster.local,如下所示

nslookup 10-1-0-82.my-nginx.default.svc.cluster.local

Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   10-1-0-82.my-nginx.default.svc.cluster.local
Address: 10.1.0.82

解析域名时使用的Server就是K8S的DNS服务地址:

kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   133d

Pod自定义hostname和subdomain

默认情况下,Pod的名称就是pod创建时指定的name,但如果是通过RS控制器创建的,还会在name后面加一个随机后缀名。如下所示:

kubectl get pods -n default

NAME                       READY   STATUS    RESTARTS   AGE
my-nginx-dd5b4b7dd-dt9tz   1/1     Running   0          23h
pod1                       1/1     Running   0          2m12s
pod2                       1/1     Running   0          2m12s

my-nginx-dd5b4b7dd-dt9tz是通过deployment创建的,pod1pod2是直接创建的。

Pod的主机名默认为pod的名称,进入my-nginx-dd5b4b7dd-dt9tz 查看/etc/hosts文件:

# Kubernetes-managed hosts file.
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.1.0.82       my-nginx-dd5b4b7dd-dt9tz

可以看到主机名就是pod的名称,也可以通过hostname直接获取。

Pod的规范中有一个可选的hostname字段,可以用来指定主机名,还有一个subdomain字段,可以用来指定子域名。
假设某pod的主机名设置为foo,子域名设置为bar,在命名空间default中,其完全限定域名FQDN为foo.bar.default.svc.cluster.local

下面创建一个pod,分别指定其hostnamesubdomain

apiVersion: v1
kind: Service
metadata:
  name: busybox-subdomain
spec:
  selector:
    name: busybox
  clusterIP: None
  ports:
  - name: foo # 实际上不需要指定端口号
    port: 1234
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostname: busybox-1
  subdomain: busybox-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

该pod的主机名为busybox-1, 完全限定域名FQDN为:busybox-1.busybox-subdomain.default.svc.cluster.local。 登录pod查看/etc/hosts:

10.1.0.84	     busybox-1.busybox-subdomain.default.svc.cluster.local   busybox-1

可以看到其完全限定域名和后面的主机名。

默认情况下,hostname命令会返回该短主机名,而hostname -f命令返回FQDN。

DNS 会为FQDN提供一个 A 记录(ipv4)和 AAAA 记录(ipv6),指向该Pod 的 IP

说明:在 Linux 中,内核的主机名字段(struct utsname 的 nodename 字段)限定最多 64 个字符。
如果 Pod 启用这一特性,而其 FQDN 超出 64 字符,Pod 的启动会失败。 Pod 会一直出于 Pending 状态(通过 kubectl 所看到的 ContainerCreating), 并产生错误事件,例如 “Failed to construct FQDN from Pod hostname and cluster domain, FQDN long-FQDN is too long (64 characters is the max, 70 characters requested).” (无法基于 Pod 主机名和集群域名构造 FQDN,FQDN long-FQDN 过长,至多 64 个字符,请求字符数为 70)。 对于这种场景而言,改善用户体验的一种方式是创建一个准入Webhook 控制器, 在用户创建顶层对象(如 Deployment)的时候控制FQDN 的长度。

CoreDNS

在微服务架构中,服务注册大体上有两种方式。一种是使用Zookeeper等注册中心,另一种是使用DNS服务,Kubernetes就是使用的后一种。

从Kubernetes 1.13开始,CoreDNS就成了Kubernetes的默认DNS服务器。

CoreDNS的一个重要特点就是以插件的形式提供服务,且配置简单。通过命令获取corefile配置文件信息:

kubectl -n kube-system get cm coredns -o yaml

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors  # 错误记录到标准输出
        health {
           lameduck 5s
        }
        ready # 在端口8181上提供的一个HTTP末端,当所有能够表达自身的插件都已经就绪时,通过此末端返回200 OK
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        prometheus :9153
        # 将不在集群域内的域名转发到预定义解析器
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        cache 30  # 前端缓存
        loop # 转发环检测,如果发现死循环则终止CoreDNS进程
        reload # 允许自动重新加载已更改的Corefile
        loadbalance # 轮转式DNS负载均衡器,随机分配A,AAAA和MX记录的顺序
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2022-11-16T02:37:11Z"
  name: coredns
  namespace: kube-system
  resourceVersion: "227"
  uid: 5520fd16-cbb8-4bc1-abb5-474778c191b4

CoreDNS能够配置存根域和上游域名服务器。比如现在需要将.consul.local后缀指向一个单独的域名服务器,可以在corefile配置:

consul.local:53 {
	errors
	cache 30
	forward . 10.23.32.113
}

如果域名后缀无法统一,也可以自定义域名服务器,直接修改转发的预定义解析服务器:

...
prometheus :9153
# 将不在集群域内的域名转发到预定义解析器
 forward . 10.0.0.10 {
    max_concurrent 1000
 }
 cache 30  # 前端缓存
 ...

某些场景下需要将域名解析到固定ip时,可以在corefile中配置外部域名解析:

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors 
        health {
           lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
           ttl 30
        }
        hosts {
        	221.6.16.11 harbor.example.com
        	221.6.16.13 es.example.com
        }
        prometheus :9153
        forward . /etc/resolv.conf {
           max_concurrent 1000
        }
        ...
    }

Pod的DNS策略

Kubernetes支持pod维度的DNS策略设置。通过pod规约中的dnsPolicy可以设置以下策略:

  • Default: Pod从自身所在的Node上继承域名解析配置。
  • ClusterFirst: 将优先使用kubernetes环境的dns服务(如coreDNS提供的域名解析服务),将无法解析的域名转发到系统配置的上游(宿主机)DNS服务器。
  • ClusterFirstWithHostNet: 对于以hostNetwork方式运行的Pod,应将其DNS策略显式设置为该策略。
  • None: 此设置允许忽略Kubernetes环境中的DNS设置,pod会使用其dnsConfig字段所提供的DNS设置。

注意,Default并不是默认的DNS策略,ClusterFirst才是。当未设置dnsPolicy时,使用ClusterFirst策略。

下面是一个DNS策略设置示例:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
  hostNetwork: true // 此方式须指定ClusterFirstWithHostNet策略
  dnsPolicy: ClusterFirstWithHostNet

DNS策略最终配置在/etc/resolv.conf文件中,也就是说k8s最终还是通过pod容器中resolv.conf文件来做域名解析的。

CluterFirst策略

不指定任何DNS策略时,默认使用该策略。
查看pod上的/etc/resolv.conf

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

nameserver即域名解析服务器,也就是k8s中的DNS服务地址。

search是搜索域,会与实际访问名组合在一起进行解析。例如上文中的my-nginx服务,其完整域名是my-nginx.default.svc.cluster.local,访问时只需要服务名my-nginx即可,k8s会自动将服务名与搜索域中的配置组合起来。搜索域主要是为了方便k8s内部服务之间互相访问。

options ndots:5 表示当待解析的域名包含.的数量大于等于5时,就会将其当成完全限定域名直接解析,如果解析不成功,则会继续匹配search/domain域;而如果域名中包含的.小于5,则会将其视为非完全限定域名,与search域组合起来进行解析。

举例说明:
如果从pod中访问域名a.b.c.d,由于该域名中有4个.,小于5,所以在进行DNS解析时,会将其视为非完全限定域名,和search域的配置组合在一起,按照以下顺序进行解析:

a.b.c.d.default.svc.cluster.local. ->
a.b.c.d.svc.cluster.local. ->
a.b.c.d.cluster.local. ->

当以上域名都无法解析时,才会将a.b.c.d.作为绝对域名进行解析。也就是说,前三次解析是无效的。

None

dnsConfig可以与任何DNS策略一起使用。当dnsPolicy为None时,必须指定dnsConfig字段。

用户可以在dnsConfig中指定以下属性:

  • nameservers:指定DNS服务器的ip列表,最多3个。当dns策略为None时,至少要包含1个。
  • searches: 搜索域列表。Kubernetes最多允许6个搜索域。
  • options:可选对象列表,其中每个对象可能具有name(必须)和value(可选)。

下面是一个示例:

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 192.0.2.1 # 这是一个示例
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

创建上面的pod后,查看DNS策略的最终配置/etc/resolve.conf如下:

nameserver 192.0.2.1
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0

注意,Windows节点上运行的pod不支持ClusterFirstWithHostNet,Windows将艘有的带有.的名称视为全限定域名(FQDN)

参考资料

[1]. https://kubernetes.io/zh-cn/docs/concepts/services-networking/dns-pod-service/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k8s指南-DNS与服务发现 的相关文章

随机推荐

  • 手机闪存速度排行_手机闪存性能排行

    手机专用闪存主要分为eMMC和UFS两大类别 前者仅支持并行读写 即半双工运行 读写必须分开执行 哪怕是最新的eMMC5 1标准其顺序读取和写入速度也不过300MB s和200MB s左右 常见于售价低于千元的入门级4G手机市场 UFS自诞
  • Win10 某个移动硬盘不自动分配盘符

    简单来说就是某个移动硬盘不自动分配盘符 每次都要到磁盘管理里面手动分配盘符 而且每次删除设备后 手动分配的盘符不消失 1 使用管理员启动 CMD 命令提示符 2 输入 diskpart 3 列出磁盘 list disk 4 选择磁盘 sel
  • 创建动态数组键盘输入一个正整数 n,创建大小为 n 的数组(采用动态数组的方式),将数组中的元素初始化为 n、n+1、...、2n - 1。并输出数组中的元素。输入描述:键盘输入一个正整数 n输

    include
  • 【QT 网络云盘客户端】——实现文件属性窗口

    目录 文件属性对话框 设置字体样式 获取文件的信息 显示文件属性对话框 当我们点击文件中的属性 则会弹出一个属性对话框 实现过程 0 设置 属性 菜单项的槽函数 1 鼠获取鼠标选中的QListWidgetItem 它包含 图标和文件名 2
  • 代码重构与单元测试——重构1的单元测试(四)

    四 重构1的vb net教程单元测c 教程试 程序开发过程中 写代码是为了实现需求 当我们的代码通过了编译 只是说明它的语法正确 功能能否实现则不能保证 因此 当我们的某些功能代码完成后 为了检验其是否满足程序的需求 可以通过编写测试代码
  • java自动化测试语言高级之多线程编程

    java自动化测试语言高级之多线程编程 Java 多线程编程 Java 给多线程编程提供了内置的支持 一条线程指的是进程中一个单一顺序的控制流 一个进程中可以并发多个线程 每条线程并行执行不同的任务 多线程是多任务的一种特别的形式 但多线程
  • Fiddler工具使用汇总

    Fiddler工作原理 fiddler作为一个代理服务器 跟浏览器建立连接之后 浏览器像目标服务器发送的请求都会经过fiddler代理 所以fiddler可以捕获到http s 请求 从而可以解释 分析 甚至重写发出去的http s 请求
  • Conda、pip下载包:PackagesNotFoundError: The following packages are not available from current channels:

    1 问题 安装包的时报下面错误 安装包之前查一下当前环境对应的包的版本 conda search 包名 2 解决方法1 报错原因是当前镜像中不存在这个包 解决方法如下 直接去官网https anaconda org 搜包名 找到对应的版本点
  • ESXI虚拟机 - 使用vmdk虚拟机转换为OVF模板,导入ESXI

    目录 一 前提条件 二 转换为OVF模板 三 导入ESXI系统 四 安装时可能会出现的问题 一 前提条件 已安装VMware Workstation 并且创建了一个的虚拟机 此处以win8 1为例 已存在ESXI系统 二 转换为OVF模板
  • 包装类Integer判断“==”相等

    今日小编在复习Java基本数据操作类是发现的遗忘问题 是Integer的 比较问题 与大家进行分享 示例代码如下 public class IntegerComparison public static void main String a
  • 四因素三水平正交试验表_最简单的正交试验教程,一次性搞懂它

    大家好 今天要分享的是正交试验设计与结果检验过程 正交试验设计时试验优化的常用技术 它可以通过科学合理地设计 达到用较少的试验次数 取得较为准确可靠的结果 正交试验设计一般包括以下几步 确定研究因素和指标水平 制作成正交试验表格 实施试验
  • seaborn简明教程(一)

    1 Seaborn简介 seaborn是基于matplotlib的数据可视化库 它在matplotlib的基础上 进行了更高级的API封装 从而使得绘图更加容易 不需要经过大量的调整 就能使图形变得精致 seaborn的几个鲜明特点如下 绘
  • 使用docker部署fastdfs集群版

    一 前言 本文档说明在node01和node02两台主机上安装部署FastDFS双节点 node01 ip 198 168 1 121 安装tracker1 storage1 node02 ip 198 168 1 122 安装tracke
  • 2020年,给你7个程序员接私活必备网站!

    2020互联网圈不好混 不是每个公司都能像蚂蚁金服一样这么大气 不少公司今年因为疫情已经开始裁员 不要抱怨 加油干就完事了 今天给大家推荐几个赚钱养家的好渠道 一起来看看吧 1 程序员客栈 程序员的经纪人 https www proginn
  • Python人员信息管理系统(简直期末人福音)

    1 涉及模块 datetime os random sys PyQt5 2 运行效果 支持功能 添加信息 修改信息 删除信息 查询信息 文件存储数据 每次运行都会加载显示之前的信息 3 部分源码 创建字体对象 用来对要显示的文字进行设定fo
  • IIS 网站安装SSL证书

    步骤一 申请SSL证书 申请免费证书步骤 阿里云申请免费证书步骤 申请完成后 等待证书签发 签发后下载到本地 解压缩后会得到如下两个文件 一个证书文件 一个密码文件 步骤二 将文件复制到服务器上 双击证书文件安装 安装选计算机 安装过程中要
  • Graph Stacked Hourglass Networks for 3D Human Pose Estimation

    方法重复使用编码器 解码器 图形结构特征在三种不同尺度的骨骼中表示 获取局部和全局特征 使用不同深度中间特征的多层次特征学习方法 目前的基于GCN的方法有一些局限性 图卷积利用所有关节点信息 可以看做是所有特征仅在 一个尺度 上处理 很难获
  • 安全类常用网站

    目录 Burp Suite Burpsuite学院 安全测试常用的几个工具 Burp Suite Burp Suite Application Security Testing Software PortSwiggerGet Burp Su
  • UniswapV2核心合约学习(3)——UniswapV2Pair.sol

    记得朋友圈看到过一句话 如果Defi是以太坊的皇冠 那么Uniswap就是这顶皇冠中的明珠 Uniswap目前已经是V2版本 相对V1 它的功能更加全面优化 然而其合约源码却并不复杂 本文为个人学习UniswapV2核心合约源码的系列文章的
  • k8s指南-DNS与服务发现

    目录 1 k8s指南 概述 2 k8s指南 架构 3 k8s指南 工作负载 1 4 k8s指南 工作负载 2 5 k8s指南 工作负载 3 6 k8s指南 工作负载 4 7 k8s指南 Service 8 k8s指南 Ingress 9 k