惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Last Watchdog
The Last Watchdog
Microsoft Security Blog
Microsoft Security Blog
宝玉的分享
宝玉的分享
小众软件
小众软件
雷峰网
雷峰网
F
Full Disclosure
B
Blog
Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
月光博客
月光博客
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
TaoSecurity Blog
TaoSecurity Blog
博客园 - 聂微东
P
Palo Alto Networks Blog
N
Netflix TechBlog - Medium
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
P
Privacy & Cybersecurity Law Blog
U
Unit 42
Cloudbric
Cloudbric
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Vercel News
Vercel News
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
T
Tailwind CSS Blog
S
Schneier on Security
IT之家
IT之家
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tenable Blog
Google DeepMind News
Google DeepMind News
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
Cyberwarzone
Cyberwarzone
P
Privacy International News Feed
I
InfoQ
MongoDB | Blog
MongoDB | Blog
Project Zero
Project Zero
B
Blog RSS Feed
Help Net Security
Help Net Security
H
Heimdal Security Blog
有赞技术团队
有赞技术团队
The Register - Security
The Register - Security
V
V2EX
C
CXSECURITY Database RSS Feed - CXSecurity.com
J
Java Code Geeks

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程 开发 Tips(5)
Kubernetes 中的 DNS 服务
微信公众号 · 2020-04-24 · via 陈少文的网站

1. 关于 DNS

1.1 DNS 服务的用途

DNS 提供的是域名到 IP 的映射服务。例如,在浏览器输入 https://www.chenshaowen.com 访问页面,但数据链路是基于 IP 的通信,无法识别 www.chenshaowen.com 。这时就需要进行 DNS 查询,输入参数是 www.chenshaowen.com ,返回结果是 IP 地址。

可以看到 DNS 提供了一种助记方法,我们不必关注 IP 地址以及其变动,而只需记住一段英文字符串,就能够找到服务。

一种常见的服务发现机制是配置管理中心,存储 Key/Value 值,例如 Consul、ZooKeeper、Etcd 等。而 DNS 提供的功能,也可以满足微服务架构中服务发现的需求,Kubernetes 就是采用的这种方式。

Kubernetes 从 1.11 版本开始,使用 CoreDNS 替代 KubeDNS 成为了内置的 DNS 服务。

1.2 resolv.conf

/etc/resolv.conf 是 DNS 客户端的配置文件,主要有四部分组成:

  • nameserver ,DNS 服务器的 IP 地址
  • domain ,本地域名的后缀
  • search ,搜索的域名后缀
  • sortlist ,对查询结果进行特定排序

当遇到无法解析的域名时,解析器才会用到 domain 、search 。例如,访问 http://abc/index.html, 解析器无法解析 abc ,就会拼接 domain 或 search 的配置作为后缀继续解析。当配置了 search 时,domain 失效。

2. CoreDNS

2.1 简介

CoreDNS 是 CNCF 正式毕业的项目。它是一个基于 Caddy 实现,模块化且可插拔的 DNS 服务器。

每个插件都遵循一个特定的接口协议。在 Corefile 文件中采用 DSL 定义 DNS 服务,可以很方便地开启各种插件,定制 DNS 服务。下面是一个示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
example.org:53 {
        errors
        cache 30
        reload
        loop
        forward . 10.10.10.10 {
            prefer_udp
            max_concurrent 100
        }
        prometheus :9153
    }
.:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        rewrite name xxx.xxx.com xxx.svc.cluster.local
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . 10.10.10.10 {
            prefer_udp
            max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
}

这个配置暴露了一个 DNS Server ,监听在 8000 端口,根据不同的域名匹配不同的处理逻辑。每个逻辑,加载指定的插件处理。

2.2 相关插件

常用的插件包括:

  • hosts,配置集群全局可解析的 hosts ,需要注意的是域名后缀需要与 search 保持一致,例如,cluster.local ,否则 nodelocaldns 无法上报 coredns 解析
  • errors, 错误记录到 stdout
  • health,提供健康报告接口
  • kubernetes,解析为 Kubernetes 集群服务的 IP 地址
  • prometheus,提供 Prometheus 的 Metrics 接口
  • proxy,不在集群域内的查询转到指定解析器
  • cache,启用缓存
  • loop,检测死循环,并中断
  • reload,自动加载 Corefile,热更新
  • loadbalance,DNS 负载均衡器

2.3 集群 ConfigMap 配置

  • 查看 CoreDNS 的服务:
1
2
3
kubectl -n kube-system get svc coredns

coredns                            ClusterIP   10.233.0.3      <none>        53/UDP,53/TCP,9153/TCP   5h
  • 查看 CoreDNS 的配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
kubectl -n kube-system get cm  coredns -o yaml

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          upstream /etc/resolv.conf
          fallthrough in-addr.arpa ip6.arpa
        }
        hosts {
           127.1.1.1 example.org
           fallthrough
        }
        prometheus :9153
        forward . /etc/resolv.conf {
          prefer_udp
        }
        cache 30
        loop
        reload
        loadbalance
    }

DNS 的默认端口是 53 。cluster.local 、 in-addr.arpa 、 ip6.arpa 格式的域名将被解析为 Kubernetes 的内部 IP 地址。

hosts 中的 fallthrough 配置非常重要,未匹配的域名继续向下匹配。

2.4 运维建议

如果是在生产环境更新,建议仅进行容器级别进行灰度更新,而不要让 CoreDNS 发生节点变化。

因为不同节点的 /etc/resolv.conf 可能不同,会无法回滚配置。

3. NodelocalDNS

3.1 简介

为了避免 Pod 进行 DNS 解析时,频繁查询 CoreDNS ,NodelocalDNS 在每个节点上都以 DaemonSet 运行 DNS 缓存以提高集群性能。

NodelocalDNS 的原理是,运行一个 hostNetwork 网络模式的 Pod,创建一个网卡绑定本地 DNS 的 IP 地址。节点上的 Pod 请求 DNS 解析时,将被拦截到 NodelocaDNS 。NodelocalDNS 通过取缓存或向上游请求 DNS ,完成解析过程。

3.2 集群 ConfigMap 配置

  • 查看 NodelocalDNS 服务
1
2
3
kubectl -n kube-system get ds nodelocaldns

nodelocaldns   1         1         1       1            1           <none>                        5h
  • 查看 NodelocalDNS 配置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
kubectl -n kube-system get cm nodelocaldns -o yaml

apiVersion: v1
data:
  Corefile: |
    cluster.local:53 {
        errors
        cache {
            success 9984 30
            denial 9984 5
        }
        reload
        loop
        bind 169.254.25.10
        forward . 10.233.0.3 {
            force_tcp
        }
        prometheus :9253
        health 169.254.25.10:9254
    }
    in-addr.arpa:53 {
        errors
        cache 30
        reload
        loop
        bind 169.254.25.10
        forward . 10.233.0.3 {
            force_tcp
        }
        prometheus :9253
    }
    ip6.arpa:53 {
        errors
        cache 30
        reload
        loop
        bind 169.254.25.10
        forward . 10.233.0.3 {
            force_tcp
        }
        prometheus :9253
    }
    .:53 {
        errors
        cache 30
        reload
        loop
        bind 169.254.25.10
        forward . /etc/resolv.conf
        prometheus :9253
    }
...

同样使用 53 端口提供 DNS 服务,但是根据不同的域名,NodelocalDNS 提供了不同的解析策略。 cluster.local、in-addr.arpa、ip6.arpa 格式的域名从 CoreDNS 解析后缓存到本地,其他则使用节点的 DNS 解析后缓存。

3.3 将节点的 DNS 改为 NodelocalDNS

  • 修改参数
1
vim /var/lib/kubelet/config.yaml

将指向 CoreDNS 的

1
2
clusterDNS:
- 10.96.0.10

改为指向 NodelocalDNS 的 IP 地址

1
2
clusterDNS:
- 169.254.25.10
  • 重启 Kubelet
1
systemctl restart kubelet

这个节点新创建的 Pod 就会使用 NodelocalDNS 进行 DNS 解析。

3.4 运维建议

在生产过程中,有时不会部署 NodeLocalDNS ,而是直接使用 CoreDNS 。

这样做并不是一个好的选择,原因主要在于: 如果想要切换 DNS 服务时,修改 CoreDNS 的配置将会影响整个集群,而无法仅修改指定的节点做灰度测试。

生产环境建议强烈建议部署 NodeLocalDNS ,这样可以保证集群的稳定性。

4. Kubernetes Pod 中的 DNS 解析

  • 创建测试用的 Pod
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cat > busybox.yaml <<-EOF
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - name: busybox
    image: busybox:1.28.4
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
EOF
1
kubectl apply -f busybox.yaml
  • 查看 DNS 解析配置
1
2
3
4
5
kubectl exec busybox cat /etc/resolv.conf

nameserver 169.254.25.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
  • 解析正常的内部服务
1
2
3
4
5
6
7
kubectl exec -ti busybox -- nslookup kubernetes.default

Server:    169.254.25.10
Address 1: 169.254.25.10

Name:      kubernetes.default
Address 1: 10.233.0.1 kubernetes.default.svc.cluster.local

解析链路:nodelocaldns -> 缓存 -> coredns -> 返回 IP

其中涉及 search 添加域名后缀的逻辑,在此不再表述。

  • 解析不存在的服务
1
2
3
4
5
6
kubectl exec -ti busybox -- nslookup a.b

Server:    169.254.25.10
Address 1: 169.254.25.10

nslookup: can't resolve 'a.b'

解析链路:nodelocaldns -> 节点配置的 DNS -> 未找到

  • 解析正常的外部服务
1
2
3
4
5
6
7
kubectl exec -ti busybox -- nslookup www.chenshaowen.com

Server:    169.254.25.10
Address 1: 169.254.25.10

Name:      www.chenshaowen.com
Address 1: 163.181.33.208

解析逻辑:nodelocaldns -> 节点配置的 DNS -> 返回 IP

5. ExternalName - CNAME 解析

ExternalName Service 是 Service 的一个特例,没有选择器,可以用于给外部服务取一个内部别名。

  • 创建 ExternalName Service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat > externalname.yaml <<-EOF
apiVersion: v1
kind: Service
metadata:
  name: chenshaowen
  namespace: default
spec:
  type: ExternalName
  externalName: www.chenshaowen.com
EOF
1
kubectl apply -f externalname.yaml
  • 测试访问内部服务
1
2
3
4
5
6
7
kubectl exec -ti busybox -- nslookup chenshaowen.default

Server:    169.254.25.10
Address 1: 169.254.25.10

Name:      chenshaowen.default
Address 1: 58.215.145.110

chenshaowen.default 将会被映射到 www.chenshaowen.com ,这是通过 DNS 的 CNAME 记录实现的。

6. 参考