kubernetes最佳实践(三) - kubedns部署

2023-11-18

1. 服务发现

kubernetes 提供了 service 的概念可以通过 VIP 访问 pod 提供的服务,但是在使用的时候还有一个问题:怎么知道某个应用的 VIP?比如我们有两个应用,一个 app,一个 是 db,每个应用使用 rc 进行管理,并通过 service 暴露出端口提供服务。app 需要连接到 db 应用,我们只知道 db 应用的名称,但是并不知道它的 VIP 地址。

最简单的办法是从 kubernetes 提供的 API 查询。但这是一个糟糕的做法,首先每个应用都要在启动的时候编写查询依赖服务的逻辑,这本身就是重复和增加应用的复杂度;其次这也导致应用需要依赖 kubernetes,不能够单独部署和运行(当然如果通过增加配置选项也是可以做到的,但这又是增加负责度)。

开始的时候,kubernetes 采用了 docker 使用过的方法——环境变量。每个 pod 启动时候,会把通过环境变量设置所有服务的 IP 和 port 信息,这样 pod 中的应用可以通过读取环境变量来获取依赖服务的地址信息。这种方式服务和环境变量的匹配关系有一定的规范,使用起来也相对简单,但是有个很大的问题:依赖的服务必须在 pod 启动之前就存在,不然是不会出现在环境变量中的。

更理想的方案是:应用能够直接使用服务的名字,不需要关心它实际的 ip 地址,中间的转换能够自动完成。名字和 ip 之间的转换就是 DNS 系统的功能,因此 kubernetes 也提供了 DNS 方法来解决这个问题。

2. 部署 DNS 服务

DNS 服务不是独立的系统服务,而是一种 addon ,作为插件来安装的,不是 kubernetes 集群必须的(但是非常推荐安装)。可以把它看做运行在集群上的应用,只不过这个应用比较特殊而已。

DNS 有两种配置方式,在 1.3 之前使用 etcd + kube2sky + skydns 的方式,在 1.3 之后可以使用 kubedns + dnsmasq 的方式。

本章节主要讲述kubedns+dnsmasq的部署方式

在 kubernetes 1.3 版本之后,kubernetes 改变了 DNS 的部署方式,变成了 kubeDNS + dnsmasq,没有了 etcd 。在这种模式下,kubeDNS 是原来 kube2sky + skyDNS + etcd,只不过它把数据都保存到自己的内存,而不是 kv store 中;dnsmasq 的引进是为了提高解析的速度,因为它可以配置 DNS 缓存。

2.1 先下载用到的三个镜像

虽然k8s启动一个rc会从指定地址下载镜像,如果搭建私有云,一般我比较喜欢先下载镜像到本地,然后push到自己的私有镜像仓库,后面使用比较方便速度更快

docker pull index.tenxcloud.com/google_containers/kubedns-amd64:v1.3

docker pull index.tenxcloud.com/google_containers/dnsmasq-amd64:v1.1

docker pull index.tenxcloud.com/google_containers/exechealthz-amd64:v1.0

2.2 修改 kubelet 启动参数

不管以什么方式启动,对外的效果是一样的。要想使用 DNS 功能,还需要修改 kubelet的启动配置项,告诉 kubelet,给每个启动的 pod 设置对应的 DNS 信息,一共有两个参数:--cluster_dns=10.1.10.10 --cluster_domain=cluster.local,分别是 DNS 在集群中的 vip 和域名后缀,要和 DNS rc 中保持一致(rc见后面章节)。

2.3 kubedns-rc启动

下面是这种方式的部署配置文件(完整版请见附件kubedns-rc.yaml):

第23,24行的是镜像拉取的密钥,为了保证在每个node上都可以拉取到私有仓库的镜像。其中,第24行的registrybaidu.registrykey是通过如下命令生成的密钥key(结果都是存储在etcd中)

kubectl create secret docker-registry registrybaidu.registrykey --docker-server= registry.baidu.com --docker-username=lixiaodong --docker-password=wZu9GZvFWa4lGb --docker-email=lixiaodong@ baidu.com --namespace=kube-system

如上的命令会生成一个密钥相关的字符串经过base64编码后在k8s中存储,如下图的。

就是dockercfg字段:eyJyZWdpc3RyeS5iYWlkdS5jb20iOnsidXNlcm5hbWUiOiJsaXhpYW9kb25nIiwicGFzc3dvcmQiOiJ3WnU5R1p2RldhNGxHYiIsImVtYWlsIjoibGl4aWFvZG9uZ0BiYWlkdS5jb20iLCJhdXRoIjoiYkdsNGFXRnZaRzl1WnpwM1duVTVSMXAyUmxkaE5HeEhZZz09In19

把这串字符串放入一个文件secret64文件中,通过base64 -d secret64可以看到内容,如下

其中,auth字段是通过docker login registry.baidu.com登录后在~/.docker/config.json中的registry.baidu.com下的值,如下图

如上命令是我为registry.baidu.com这个镜像仓库,以及lixiaodong/wZu9GZvFWa4lGb这个账户密码生成的。

kubectl get secret

 

可以看看所有生成的key,如下图

这里有两个需要根据实际情况配置的地方:

  • kube_master_url: kubedns 会用到 kubernetes master API,它会读取里面的 service 信息
  • domain:域名后缀,跟kubelet添加的启动参数cluster_domain一致,默认是 cluster.local,你可以根据实际需要修改成任何合法的值

启动kubedns-rc.yaml:

$ kubectl create -f ./kubedns-rc.yml

参看是否启动成功:

$ kubectl get pod --namespace=kube-system

2.4 kubedns-svc service文件启动

见附件kubedns-svc.yaml

这里需要注意的是 clusterIP: 10.1.10.10 这一行手动指定了 DNS service 的 IP 地址,这个地址必须在预留的 vip 网段(见kubernetes最佳实践(一) - 集群部署的3.4节)。

手动指定的原因是为了固定这个 ip,这样启动 kubelet 的时候配置 --cluster_dns=10.1.10.10 比较方便(2.2节的kubelet启动参数),不需要再动态获取 DNS 的 vip 地址。

有了这两个文件,直接创建对象就行:

$ kubectl create -f ./kubedns-svc.yml

启动成功。

3. 测试 DNS 可用性

3.1 dns域名规则

不管那种部署很是,kubernetes 对外提供的 DNS 服务是一致的。每个 service 都会有对应的 DNS 记录,kubernetes 保存 DNS 记录的格式如下:

<service_name>.<namespace>.svc.<domain>  

每个部分的字段意思:

  • service_name: 服务名称,就是定义 service 的时候取的名字
  • namespace:service 所在 namespace 的名字
  • domain:提供的域名后缀,比如默认的 cluster.local

在 pod 中可以通过 service_name.namespace.svc.domain 来访问任何的服务,也可以使用缩写 service_name.namespace,如果 pod 和 service 在同一个 namespace,甚至可以直接使用 service_name

NOTE:正常的 service 域名会被解析成 service vip,而 headless service 域名会被直接解析成背后的 pods ip。

虽然不会经常用到,但是 pod 也会有对应的 DNS 记录,格式是 pod-ip-address.<namespace>.pod.<domain>,其中 pod-ip-address 为 pod ip 地址的用 - 符号隔开的格式,比如 pod ip 地址是 1.2.3.4 ,那么对应的域名就是 1-2-3-4.default.pod.cluster.local

 

3.2 运行busybox pod验证dns

busybox镜像中有nslookup命令,如果自己的pod里面有nslookup命令也可以使用

下载镜像:docker pull index.tenxcloud.com/google_containers/busybox:latest

执行附件中的busybox-rc.yaml

$ kubectl create -f busybox-rc.yaml

进入容器内部查看dns是否配置成功

$ docker exec -it 637a21082cd9 /bin/sh

查看容器内部的resolve.conf文件(resolve.conf是linux上的DNS域名解析的配置文件,机器内部域名寻址先到resolve.conf查找,然后再到外部dns查找)

$ more /etc/resolve.conf

看到如下,已经按照3.2节的规则在容器的resolv.conf中生成域名搜索规则以及域名服务器地址(刚好是我们配置kubedns的service clusterIp地址,也是2.2节在kubelet中配置的cluster_dns地址),说明配置正确

看基于kubedns配置的域名是否生效(按照),找个已存在的service实验下,就用k8s默认启动的kubernetes这个service

可以看出,如果我们在默认的 namespace default 创建了名为 kubernetes 的服务,以下所有域名都能被正确解析:

kubernetes
kubernetes.default.svc
kubernetes.default.svc.cluster.local

4. kubernetes DNS 原理解析

我们前面介绍了两种不同 DNS 部署方式,这部分讲讲它们内部的原理。

4.1 kube2sky 模式

这种模式下主要有三个容器在运行:

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE                                              COMMAND                  CREATED             STATUS              PORTS                                          NAMES
919cbc006da2        172.16.1.41:5000/google_containers/kube2sky:1.12   "/kube2sky /kube2sky "   About an hour ago   Up About an hour                                                   k8s_kube2sky.80a41edc_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_1bd3fdb4
73dd11cac057        172.16.1.41:5000/jenkins/etcd:live                 "etcd -data-dir=/var/"   About an hour ago   Up About an hour                                                   k8s_etcd.4040370_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_b0e5a99f
0b10ae639989        172.16.1.41:5000/jenkins/skydns:20150703-113305    "bootstrap.sh"           About an hour ago   Up About an hour                                                   k8s_skydns.73baf3b1_kube-dns-twl0q_kube-system_ea1f5f4d-15cf-11e7-bece-080027c09e5b_2860aa6d

这三个容器的作用分别是:

  • etcd:保存所有的 DNS 数据
  • kube2sky: 通过 kubernetes API 监听 Service 的变化,然后同步到 etcd
  • skyDNS:根据 etcd 中的数据,对外提供 DNS 查询服务

4.2 kubeDNS 模式

这种模式下,kubeDNS 容器替代了原来的三个容器的功能,它会监听 apiserver 并把所有 service 和 endpoints 的结果在内存中用合适的数据结构保存起来,并对外提供 DNS 查询服务。

  • kubeDNS:提供了原来 kube2sky + etcd + skyDNS 的功能,可以单独对外提供 DNS 查询服务
  • dnsmasq: 一个轻量级的 DNS 服务软件,可以提供 DNS 缓存功能。kubeDNS 模式下,dnsmasq 在内存中预留一块大小(默认是 1G)的地方,保存当前最常用的 DNS 查询记录,如果缓存中没有要查找的记录,它会到 kubeDNS 中查询,并把结果缓存起来

每种模式都可以运行额外的 exec-healthz 容器对外提供 health check 功能,证明当前 DNS 服务是正常的。

  • exec-healthz:运行某个命令,根据结果来对外提供 /healthz 结果

总结

推荐使用 kubeDNS 的模式来部署,因为它有着以下的好处:

  • 不需要额外的存储,省去了额外的维护和数据保存的工作
  • 更好的性能。通过 dnsmasq 缓存和直接把 DNS 记录保存在内存中,来提高 DNS 解析的速度

 

参考文献:http://cizixs.com/2017/04/11/kubernetes-intro-kube-dns

                  http://tonybai.com/2016/10/23/install-dns-addon-for-k8s/

                  http://blog.csdn.net/iiiiher/article/details/77099059

                  https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/

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

kubernetes最佳实践(三) - kubedns部署 的相关文章

随机推荐

  • CSS font-family 中的苹方字体

    苹方提供了六个字重 font family 定义如下 苹方 简 常规体 font family PingFangSC Regular sans serif 苹方 简 极细体 font family PingFangSC Ultralight
  • 【Pytorch】六行代码实现:特征图提取与特征图可视化

    前言 之前记录过特征图的可视化 Pytorch实现特征图可视化 当时是利用IntermediateLayerGetter 实现的 但是有很大缺陷 只能获取到一级的子模块的特征图输出 无法获取内部二级子模块的输出 今天补充另一种Pytorch
  • 微信小程序API——向服务器发送请求

    在微信小程序中 我们可以通过微信的API与服务器进行数据传递 接下来我会详细介绍一下wx request的用法 首先给出前端代码 我们定义一个按钮 绑定点击事件 用于给服务器发送请求 当服务器返回数据后 通过wx for循环出数组中的数据
  • oracle如修改表字段的类型(表中有数据)

    如何在数据表有数据的情况下 修改字段类型 看到如何修改表字段类型 我想大多数人都觉得直接用修改语句 ALTER TABLE 表名 MODIFY 列名 类型 如果是修改多个字段就在后面继续 modify ALTER TABLE 表名 MODI
  • Reactive的方式访问Redis

    前言 本文主要大概介绍一下响应式 反应式编程方式访问 redis 不能解决很多生产问题 只是帮助大家对响应式编程有一个认识 本文是以Reactive 对方式访问 Redis 当然也可以访问mongodb 以及部分关系型数据库 例如 Post
  • Channel的定义、写入、读取、关闭与遍历

    目录 1 Channel基础 为什么要引入Channel Channel简介 channel的定义 声明 channel的数据类型 引用类型 向channel中写入数据 从channel中读取数据 2 channel的遍历与关闭 chann
  • 51单片机按键控制数码管0~9_基于proteus的51单片机开发实例24-矩阵键盘(行列式键盘)...

    1 基于proteus的51单片机开发实例24 矩阵键盘 1 1 实验目的 图1 矩阵键盘电路 本实例我们来学习矩阵键盘 行列式键盘 的电路设计 编程实现 目的是通过较少的I O口来识别多个按键 1 2 设计思路 我们在前面已经学习过独立按
  • Maya_to_Unity工作流程

    注意事项 1 maya的place2Dtexture不起作用 只能使用pbs节点的uv调整 只能调整scale offect 所以贴图的rotate只能使用uv工具进行调整 2 Unity项目第一步将色彩空间设置为liner 3 灯光材质与
  • Keil中如何生成bin文件

    一般借助fromelf工具 安装好Keil后默认会在安装目录中找到fromelf工具 一般在windows平台很难像Linux平台一样使用命令的方式启动格式转换 但是类似IAR 或Keil等带编译器的IDE 都会有编译选项 即编译器或编译后
  • 秒杀详解!!秒杀竟有这些问题?再有人问秒杀,把这篇文章丢给他!!!

    什么是秒杀 seckill seckill是一个老生常谈的场景 它一般出现在电商系统中 在某些特定的节日 限定特定商品数量以超低折扣进行促销引流 按照秒杀的特性 特价商品一般在一两秒内被抢光 剩下的人只会出现售罄页面 这一两秒会出现一个瞬间
  • shadow文件中密码的加密方式

    shadow文件中密码的加密方式 1 查看shadow文件的内容 cat etc shadow 可以得到shadow文件的内容 限于篇幅 我们举例说明 root 1 Bg1H 4mz X89TqH7tpi9dX1B9j5YsF 14838
  • GANSS ALT71D键盘使用说明

    Ganss ALT71D键盘使用说明 两个月之前入手了这款双模键盘 到现在基本只使用蓝牙连接了 数据线太多了 太乱了 用了两个月之后有了一点经验 记录在这里 首先高斯键盘是有官网的 输入www ganss cn就可以看到两把104键的键盘了
  • 技术博客笔记大汇总

    hello 小伙伴们大家好 今天给小伙伴们推荐的开源项目是 YCBlogs 这个开源项目整合博客笔记等资料信息 15年10月到至今 包括Java基础及深入知识点 Android技术博客 Python Go学习笔记等等 还包括平时开发中遇到的
  • 高性能MySQL学习笔记(1) —— MySQL架构

    MySQL架构 1 MySQL逻辑架构 这里分为三层 1 连接层 连接与线程处理 这一层并不是MySQL独有 一般的基于C S架构的都有类似组件 比如连接处理 授权认证 安全等 2 SQL处理层 也叫MySQL服务器层 包括缓存查询 解析器
  • python——pip 安装出现ERROR: Exception: Traceback (most recent call last):的问题

    用pip安装东西 总会提示 当我按照指示输入 python m pip install upgrade pip 命令时 用100次pip 99次会报下面的错误之前看了很多前人的办法 有说是因为网络不好 建议多次暴力尝试的 还有建议说使用ea
  • AI时代你需要知道的:知识图谱技术原理(必读)

    知识图谱是什么 知识图谱最早由谷歌发布 为了提升搜索引擎返回答案的质量以及用户查询的效率 在知识图谱辅助下 搜索引擎可以洞察到用户查询背后的一个语义信息 然后返回更为精准结构化的信息 从而更大可能的去满足用户的一个查询需求 当我们进行搜索时
  • mysql集群

    3 mysql集群 3 1 企业中常用的数据库解决方案 3 2 mysql常见的几种集群方式 3 2 1 MYSQl MMM Master Master Replication Manager for MySQL MySQL MMM 是 M
  • idea debug到一半停止_使用IDEA的Debug调试功能,查看程序的运行过程

    Debug追踪 使用IDEA的断点调试功能 查看程序的运行过程 知乎视频 www zhihu com 1 在有效代码行 点击行号右边的空白区域 设置断点 程序执行到断点将停止 我们可以手动来运行程序 2 点击Debug运行模式 3 程序停止
  • C语言printf打印的奥秘

    基础补充 想完全掌握C语言的 printf 函数 你就得明白C语言中的基本类型及其所占字节数 位 字节 字的概念大家自己百度了解 下面我只给其关系 8位 1字节 2字节 1字 代码示例 作为一个刚入门的小白 我们玩的数据都是十分小的 一般不
  • kubernetes最佳实践(三) - kubedns部署

    1 服务发现 kubernetes 提供了 service 的概念可以通过 VIP 访问 pod 提供的服务 但是在使用的时候还有一个问题 怎么知道某个应用的 VIP 比如我们有两个应用 一个 app 一个 是 db 每个应用使用 rc 进