CoreDNS实战(十)-kubernetes插件

CoreDNS作为现阶段k8s的默认DNS服务以及服务发现的重要一环,其内置的kubernetes插件可谓是举足轻重。本文主要讲解介绍CoreDNS内置的核心插件kubernetes的使用方式和适用场景。

CoreDNS的kubernetes插件的具体实现遵循k8s官方提供的标准指南Kubernetes DNS-Based Service Discovery Specification,这也是它能够替代kube-dns成为kubebernetes中默认的DNS的重要原因。

虽然 Kubernetes 中的服务发现可以通过其他协议和机制提供(如consul等服务注册发现中心),但DNS是非常常用的一种协议,同时考虑到K8S中的东西流量互访主要也是通过域名实现,因此K8S官方非常推荐使用DNS插件来实现K8S中的服务发现。

This document is a specification for DNS-based Kubernetes service discovery. While service discovery in Kubernetes may be provided via other protocols and mechanisms, DNS is very commonly used and is a highly recommended add-on. The actual DNS service itself need not be provided by the default Kube-DNS implementation. This document is intended to provide a baseline for commonality between implementations.

在开始介绍kubernetes插件之前,我们需要先了解一些K8S中的基础DNS知识。

1 K8S中的DNS服务

众所周知,在K8S中,IP是随时会发生变化的,变化最频繁的就是Pod IPCluster IP也并不是一定不会发生变化,EXTERNAL-IP虽然可以手动指定静态IP保持不变,但是主要面向的是集群外部的服务;因此在K8S集群中,最好的服务之间相互访问的方式就是通过域名。

1.1 DNS创建规则

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

前面我们介绍了K8S中的每个SVC都会有一个对应的域名,域名的组成格式为$service_name.$namespace_name.svc.$cluster_name,同时也会给这个SVC下的所有Pod都创建一个$pod_name.$service_name.$namespace_name.svc.$cluster_name的这种域名,这个域名的解析结果就是Pod IP。

Pod域名有两个比较明显的特征:

  • 一是域名的组成比较特殊,因为域名中使用了Pod的名称,而pod名称在K8S中是会发生变化的(例如在服务更新或者滚动重启时),同时由于默认情况下Pod的命名是没有太明显的规律(大部分名字中会包含一串随机UUID)
  • 二是域名的解析结果特殊,相较于集群内的其他类型域名,Pod域名的解析是可以精确到特定的某个Pod,因此一些特殊的需要点对点通信的服务可以使用这类Pod域名

1.2 DNS策略配置

DNS 策略可以逐个 Pod 来设定。目前 Kubernetes 支持以下特定 Pod 的 DNS 策略。 这些策略可以在 Pod 规约中的 dnsPolicy 字段设置:

  • Default: Pod 从运行所在的K8S宿主机节点继承域名解析配置;
  • ClusterFirst不指定任何dnsPolicy配置情况下的默认选项,所有查询的域名都会根据生成的集群的K8S域名等信息生成的 /etc/resolv.conf 配置进行解析和转发到集群内部的DNS服务进行解析;
  • ClusterFirstWithHostNet:主要用于以 hostNetwork 方式运行的 Pod,如果这些pod想要使用K8S集群内的DNS服务,则可以配置为这个字段;
  • None: 此设置允许 Pod 忽略 Kubernetes 环境中的 DNS 设置,Pod 会使用其 dnsConfig 字段 所配置的 DNS 设置;

说明: 下面主要介绍ClusterFirst模式

1.3 DNS解析规则

DNS 查询参照 Pod 中的 /etc/resolv.conf 配置,kubelet 会为每个 Pod 生成此文件。因此在每个pod里面都有一个类似下面这样的 /etc/resolv.conf文件,通过修改其中的配置可以更改DNS的查询规则:

 nameserver 10.32.0.10search <namespace>.svc.cluster.local svc.cluster.local cluster.localoptions ndots:5

这里的配置有几个需要注意的点:

  • nameserver:集群中的DNS服务器IP,一般来说就是CoreDNSClusterIP
  • search:需要搜索的域,默认情况下会从该pod所属的namespace开始逐级补充
  • options ndots:触发上面的search的域名点数,默认为1,上限15,在K8S中一般为5;例如在Linux中tinychen.com这个域名的ndots是1,tinychen.com.这个域名的ndots才是2(需要注意所有域名其实都有一个根域.,因此tinychen.com的全称应该是tinychen.com.

这是一个比较通用的案例,我们再来看一个比较特殊的配置

 # 首先进入一个pod查看里面的DNS解析配置[root@tiny-calico-master-88-1 tiny-calico]# kubectl exec -it -n ngx-system ngx-ex-deploy-6bf6c99d95-5qh2w /bin/bashkubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.[root@ngx-ex-deploy-6bf6c99d95-5qh2w /]# cat /etc/resolv.confnameserver 10.88.0.10search ngx-system.svc.cali-cluster.tclocal svc.cali-cluster.tclocal cali-cluster.tclocal k8s.tcinternaloptions ndots:5[root@ngx-ex-deploy-6bf6c99d95-5qh2w /]# exit

这个pod里面的/etc/resolv.conf配置文件有两个和前面不同的地方:

  • cluster.local变成了cali-cluster.tclocal
    这里我们可以看到coredns的配置中就是配置的cali-cluster.tclocal,也就是说/etc/resolv.conf中的配置其实是和coredns中的配置一样,更准确的说是和该K8S集群初始化时配置的集群名一样
 # 再查看K8S集群中的coredns的configmap [root@tiny-calico-master-88-1 tiny-calico]# kubectl get configmaps -n kube-system coredns -oyamlapiVersion: v1data:Corefile: |.:53 {errorshealth {lameduck 5s}readykubernetes cali-cluster.tclocal in-addr.arpa ip6.arpa {pods insecurefallthrough in-addr.arpa ip6.arpattl 30}prometheus :9153forward . 10.31.100.100 {max_concurrent 1000}cache 30loopreloadloadbalance}kind: ConfigMapmetadata:creationTimestamp: "2022-05-06T05:19:08Z"name: corednsnamespace: kube-systemresourceVersion: "3986029"uid: 54f5f803-a5ab-4c77-b149-f02229bcad0a
  • search新增了一个k8s.tcinternal
    实际上我们再查看K8S的宿主机节点的DNS配置规则时会发现这个k8s.tcinternal是从宿主机上面继承而来的
 # 最后查看宿主机节点上面的DNS解析配置[root@tiny-calico-master-88-1 tiny-calico]# cat /etc/resolv.conf# Generated by NetworkManagersearch k8s.tcinternalnameserver 10.31.254.253

1.4 DNS解析流程

温馨提示:阅读这部分内容的时候要特别注意域名结尾是否有一个点号 .

当ndots小于options ndots

前面我们说过options ndots的值默认情况下是1,在K8S中为5,为了效果明显,我们这里使用K8S中的5作为示例:

这里同样是在一个命名空间demo-ns中有两个SVC,分别为demo-svc1demo-svc2,那么他们的/etc/resolv.conf应该是下面这样的:

 nameserver 10.32.0.10search demo-ns.svc.cluster.local svc.cluster.local cluster.localoptions ndots:5

我们在demo-svc1中直接请求域名demo-svc2,此时ndots为1,小于配置中的5,因此会触发上面的search规则,这时第一个解析的域名就是demo-svc2.demo-ns.svc.cluster.local,当解析不出来的时候继续下面的demo-svc2.svc.cluster.localdemo-svc2.cluster.local,最后才是直接去解析demo-svc2.

注意上面的规则适用于任何一个域名,也就是当我们试图在pod中去访问一个外部域名如tinychen.com的时候也会依次进行上述查询。

当ndots大于等于options ndots

我们在demo-svc1中直接请求域名demo-svc2.demo-ns.svc.cluster.local,此时的ndots为4,还是会触发上面的search规则。

而请求域名demo-svc2.demo-ns.svc.cluster.local.,ndots为5,等于配置中的5,因此不会触发上面的search规则,直接去解析demo-svc2.demo-ns.svc.cluster.local.这个域名并返回结果

如果我们请求更长的域名如POD域名pod-1.demo-svc2.demo-ns.svc.cluster.local.,此时的ndots为6,大于配置中的5,因此也不会触发上面的search规则,会直接查询域名并返回解析

小结

通过上面的分析我们不难得出下面几点结论:

  • 同命名空间(namespace)内的服务直接通过$service_name进行互相访问而不需要使用全域名(FQDN),此时DNS解析速度最快;
  • 跨命名空间(namespace)的服务,可以通过$service_name.$namespace_name进行互相访问,此时DNS解析第一次查询失败,第二次才会匹配到正确的域名
  • 所有的服务之间通过全域名(FQDN)$service_name.$namespace_name.svc.$cluster_name.访问的时候DNS解析的速度最快
  • 在K8S集群内访问大部分的常见外网域名(ndots小于5)都会触发search规则,因此在访问外部域名的时候可以使用FQDN,即在域名的结尾配置一个点号.

2 kubernetes插件

kubernetes插件的主要作用就是用来连接k8s集群的apiserver并对外提供符合规范的域名解析服务,该插件在每个配置块中仅能使用一次,但在一个coredns实例中可以存在多个配置块,也就意味着一个coredns实例实际上是可以连接多个k8s集群并对外提供域名解析的。

接下来我们详细看一下kubernetes插件的各种具体配置,下面的这个是官方给出的一个配置文件示例:

 kubernetes [ZONES...] {endpoint URLtls CERT KEY CACERTkubeconfig KUBECONFIG [CONTEXT]namespaces NAMESPACE...namespace_labels EXPRESSIONlabels EXPRESSIONpods POD-MODEendpoint_pod_namesttl TTLnoendpointsfallthrough [ZONES...]ignore empty_service}
  • endpoint
    用来指定k8s集群的apiserver地址,如https://10.31.88.1:6443,当然也可以是域名等其他形式,如果不配置,那么默认情况下会使用对应的service account去连接当前k8s集群内的apiserver,如果不是在k8s集群中部署,那么就会连接失败。
  • tls
    CERT KEY CACERT是远程 k8s 连接的 TLS 证书、密钥和 CA 证书文件名。如果前面的endpoint没有配置,那么这个配置项会被忽略。
  • kubeconfig
    KUBECONFIG [CONTEXT]使用 kubeconfig 文件验证与远程 k8s 集群的连接。 [CONTEXT]是可选配置的,如果未设置,则将使用 kubeconfig中默认的[CONTEXT]。它支持 TLS、用户名和密码或基于令牌的身份验证。
    如果前面的endpoint没有配置,那么这个配置项会被忽略。
  • namespaces
    NAMESPACE [NAMESPACE…] 用来限制对外暴露的命名空间,多个命名空间之间使用空格间隔。如果不配置的话,则会暴露所有的命名空间。
  • namespace_labels
    namespace_labels EXPRESSION可以限定DNS的查询范围,仅有匹配labels命名空间才能被查询到。
  • labels
    labels EXPRESSION可以限定DNS的查询范围,仅有匹配lalelsservice才能被查询到。
注意这里的 labels匹配的是 service中的 labels,而前面的 labels匹配的是 namespace中的 labels。这两个 labels的配置写法可以和使用 kubectl命令中的 -l参数完全一致。
如果要使用多个labels匹配规则,注意不要使用空格,而是对应的表达式进行匹配:
-l, --selector='': Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)
  • pods
    pods POD-MODE设置处理基于 IP 的 pod A 记录的模式,例如客户端向coredns查询域名1-2-3-4.ns.pod.cluster.local.,该参数用于控制响应的结果,提供此选项是为了方便在直接连接到 pod 时使用 SSL 证书。
    POD-MODE 有效值:
    • disabled: 默认。不处理 pod 请求,总是返回NXDOMAIN
    • insecure:总是从请求中返回带有 IP 的 A 记录(不检查 k8s),即查询域名1-2-3-4.ns.pod.cluster.local.的时候,不论是否存在一个IP地址为1.2.3.4的pod,都返回这个结果给客户端。如果与通配符 SSL 证书一起被恶意使用,此选项很容易被滥用。提供此选项是为了向后兼容 kube-dns。
    • verified: 如果在同一个命名空间中存在匹配 IP 的 Pod,则返回 A 记录,即查询域名1-2-3-4.ns.pod.cluster.local.的时候,只有当该ns中确实存在一个IP地址为1.2.3.4的pod,才返回这个结果给客户端,否则返回NXDOMAIN。与insecure模式相比,此选项需要更多的内存,因为它需要监控所有的pods。
  • endpoint_pod_names
    使用endpoints所对应的pod名称作为A记录中的端点名称,例如, endpoint-name.my-service.namespace.svc.cluster.local. in A 1.2.3.4
    在没有配置该参数的情况下,endpoints名称选择如下:优先使用endpoints的hostname,如果endpoints没有配置hostname,则使用 IP 地址的虚线形式(例如,1-2-3-4.my-service.namespace.svc.cluster.local.
    如果配置了该参数,则endpoints名称选择如下:优先使用endpoints的hostname,如果endpoints没有配置hostname,则使用endpoints对应的pod名称,如果pod名称不存在或者长度超过63,则使用 IP 地址的虚线形式。
  • ttl
    设置标准的DNS域名TTL,默认值为 5 秒。允许的最小 TTL 为 0 秒,最大值为 3600 秒。将 TTL 设置为 0 将防止记录被缓存(如果查询的客户端遵循DNS规范)。
  • noendpoints
    配置该参数将禁用对K8S集群中的endpoints记录功能,因此所有endpoints查询和headless服务查询都将返回 NXDOMAIN。
  • fallthrough [ZONES…]
    正常情况下一个客户端对CoreDNS发起了一个DNS查询,如果该记录不存在,那么就会直接返回一个NXDOMAIN的响应。
    但是我们可以通过配置fallthrough参数来将这些NXDOMAIN的域名转发到配置块中的下一个插件。
    例如在fallthrough插件后面还使用了诸如file插件之类的配置了DNS解析,那么这个请求就会转发到file插件进行查询并响应
    zones参数可以用来控制哪些域的域名会被fallthrough插件转发,留空的情况下是所有的域名都会被转发,当然也可以指定部分域名如(for example in-addr.arpa and ip6.arpa),此时就只有in-addr.arpa 和 ip6.arpa的查询出现NXDOMAIN才会被转发到下一个插件进行查询
  • ignore empty_service
    如果一个service当中没有任何可用的endpoints(即关联的所有pods都不是ready状态),那么会返回一个NXDOMAIN。
    这个配置项的主要作用就是让这类不正常的服务域名查询的时候能够返回NXDOMAIN响应码,从而触发配置的其他插件(如上面提到的fallthrough)进行组合操作。

3 一些其他问题

3.1 延迟启动

当CoreDNS启用了kubernetes插件之后,CoreDNS实例在启动的时候会延迟5s的时间再对外提供服务,这5s内CoreDNS会尝试和K8S的apiserver建立连接并同步信息。

如果5s内CoreDNS还是无法和k8s的apiserver完成信息同步工作,那么会开始对外提供服务,并且继续尝试同步信息,但是在成功和apiserver建立连接并同步信息之前,所有k8s相关的域名查询都会返回SERVFAIL

3.2 连接中断

如果在CoreDNS实例正常运行的时候,突然和k8s的apiserver断开连接,并且一直没有恢复,那么此时的CoreDNS实例是依旧正常运行的,对应的K8S集群域名也是能够正常解析的,但是解析出来的endpoint信息就有可能不是最新的。

如果此时再对CoreDNS实例进行重启操作,那么具体的过程就和上面讲述的延迟启动一样,最后会导致所有k8s相关的域名查询都会返回SERVFAIL

3.3 配置检查

kubernetes的健康状态会暴露在ready插件中,如果出现配置错误可以通过请求ready插件暴露的接口发现,但是如果出现连接异常这种情况,ready接口是无法探测出来的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/199844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从0开始学Spring、Springboot总结笔记(持续更新中~)

文章目录 一.基于SpringBoot进行Web开发入门1.IDEA编译器中创建springboot工程扩展&#xff1a;如何解决pom.xml文件中“找不到Maven插件”的问题&#xff1f; 2.Springboot项目如何编写请求类和请求方法并启动访问编写请求类和请求方法启动Springboot访问 一些学习资源参考 一…

如何搭建eureka-server

在Spring Cloud项目的pom文件中添加eureka-server的starter依赖坐标 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://ma…

人工智能学习4(特征选择)

编译工具&#xff1a;PyCharm 有些编译工具在绘图的时候不需要写plt.show()或者是print就可以显示绘图结果或者是显示打印结果&#xff0c;pycharm需要&#xff08;matplotlib.pyplot&#xff09; 文章目录 编译工具&#xff1a;PyCharm 特征选择嵌入法特征选择练习&#xff…

云原生的 CI/CD 框架tekton - Trigger(二)

上一篇为大家详细介绍了tekton - pipeline&#xff0c;由于里面涉及到的概念比较多&#xff0c;因此需要好好消化下。同样&#xff0c;今天在特别为大家分享下tekton - Trigger以及案例演示&#xff0c;希望可以给大家提供一种思路哈。 文章目录 1. Tekton Trigger2. 工作流程3…

Linux高级系统编程中的系统调用

概念 是操作系统提供给用户使其可以操作内核提供服务的一组函数接口。 用户态和内核态&#xff1a; 引入 &#xff1a; 整个 计算机系统 的。好比你写 一个程序&#xff0c;但是因为你对 硬件操作 不熟悉&#xff0c;出现 问题&#xff0c;那么影响范围是多大&#xff1f;是整…

数据结构(超详细讲解!!)第二十六节 图(中)

1.存储结构 1.邻接矩阵 图的邻接矩阵表示法&#xff08;Adjacency Matrix&#xff09;也称作数组表示法。它采用两个数组来表示图&#xff1a; 一个是用于存储顶点信息的一维数组&#xff1b;另一个是用于存储图中顶点之间关联关系的二维数组&#xff0c;这个关联关系数组被…

ajax清空所有表单内容,包括input标签、单选框radio、多选框CheckBox、下拉框select以及文本域内容

为了实现重置并清空表单内容&#xff0c;你可以使用 jQuery 的 val 方法将各种表单元素的值设置为空字符串&#xff0c;并通过 layui 的 form.render 方法来更新表单的渲染。以下是修改后的代码&#xff1a; layui.use(["form", "laydate", "jquery&…

http面试题,三次握手四次挥手

在浏览器中输入网址按下回车经历了一个怎样的过程&#xff1f; 总的来说分为以下几个过程&#xff1a; 1、DNS解析&#xff1a;将域名解析为IP地址; 2、TCP连接&#xff1a;TCP三次握手; 3、发生HTTP请求; 4、服务器处理请求并返回HTTP报文; 5、浏览器解析渲染页面; 6、断开连接…

Isaac Sim教程03 Isaac Sim的基本使用

Isaac Sim 基本使用 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author holds…

CentOS服务自启权威指南:手动启动变为开机自启动(以Jenkins服务为例)

前言 CentOS系统提供了多种配置服务开机自启动的方式。本文将介绍其中两种常见的方式&#xff0c; 一种是使用Systemd服务管理器配置&#xff0c;不过&#xff0c;在实际中&#xff0c;如果你已经通过包管理工具安装的&#xff0c;那么服务通常已经被配置为Systemd服务&#…

渗透测试学习day7

文章目录 靶机&#xff1a;VaccineTask1Task2Task3Task4Task5Task6 7-9解题过程Task7Submit user flagSubmit root flag 靶机&#xff1a;Vaccine Task1 问题&#xff1a;除了SSH和HTTP&#xff0c;这个盒子上还托管了什么服务&#xff1f; ftpnmap扫一下 Task2 问题&…

【机器视觉技术栈】03 - 镜头

镜头 定焦镜头变焦镜头远心镜头 FA镜头与远心镜头的区别&#xff1f; 焦距越小畸变程度越大&#xff0c;精度要求不高的场景可以使用焦距大的FA镜头做尺寸测量&#xff0c;但焦距越大带来的问题就是整个机械设备越大。精度高的场景使用远心镜头进行尺寸测量。 光学基础知识…

Vue-安装及安装相应插件

安装Vue 安装nodejs&#xff0c; 地址&#xff1a;https://nodejs.org/en 下载后直接安装。 安装后重新打开命令行工具&#xff0c;输入 node -v PS C:\Users\zcl36> node -v v20.10.0 2. 安装vue包npm install -g vue/cli安装之后&#xff0c;你就可以在命令行中访问 vue…

Insomnia -- 非常nice的开源 API 调试工具

1. 这款开源 API 调试工具很棒&#xff01;&#xff01;&#xff01; Kong Insomnia是一个协作的开源API开发平台&#xff0c;可以轻松构建高质量的API&#xff0c;而不会像其他工具那样臃肿和混乱。 350开源插件 平衡能力和复杂性。当你需要的时候扩展工作流(当你不需要的时…

C++进阶篇7---异常

目录 一、异常的介绍 二、异常的使用 1.异常的抛出和捕获 2.异常的重新抛出 3.异常安全 4.异常规范 三、自定义异常体系 四、C标准库的异常体系 一、异常的介绍 异常是一种处理错误的方式&#xff0c;当一个函数发现自己无法处理的错误时就可以抛出异常&#xff0c;让…

LeetCode437.路径总和III

看完题目我就拿直接用递归写了如下代码&#xff1a; class Solution {private int ans;public int pathSum(TreeNode root, int targetSum) {ans 0;dfs(root, targetSum, 0);return ans;}public void dfs(TreeNode root, int targetSum, int sum){if(root null)return;sum r…

CSS面经(未完待续)

1. CSS选择器及其优先级 !important > 行内样式 > id选择器 > 类/伪类/属性选择器 > 标签/伪元素选择器 > 子/后台选择器 > *通配符 2. 重排和重绘是什么&#xff1f;浏览器的渲染机制是什么&#xff1f; 重排(回流)&#xff1a;当增加或删除dom节点&…

超大规模集成电路设计----CMOS反相器(五)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----数字集成电路——电路、系统与设计(第二版)及中国科学院段成华教授PPT 超大规模集成电路设计----CMOS反相器&#xff08;五&#xff09; 5.1 静态CMOS反相器综述5.1.1 静态CMOS反相器优点…

自定义连接池 用代码读写全过程

一 package 连接池;import java.sql.*; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor;public class MyConnection implements Connection {private MyDateSource myDateSource;private Connection connection;public MyConnec…

【C语言:自定义类型(结构体、位段、共用体、枚举)】

文章目录 1.结构体1.1什么是结构体1.2结构体类型声明1.3结构体变量的定义和初始化1.4结构体的访问 2.结构体对齐2.1如何对齐2.2为什么存在内存对齐&#xff1f; 3.结构体实现位段3.1什么是位段3.2位段的内存分配3.3位段的跨平台问题3.4位段的应用3.5位段使用注意事项 4.联合体4…