0x01 背景

Pod需要使用远程存储的PV,由同k8s集群内的服务提供的存储服务。一开始的做法是:

  1. CSI中解析Service的clusterIP。
  2. 然后使用clusterIP挂载PV卷。

但因为走clusterIP时,经过多次转换:

  1. clusterIP到Pod IP 经过了1次NAT
  2. Pod IP到最终服务。经过1次转发,具体性能损耗跟 CNI 实现相关。

导致了最终client写PV的性能损失严重。

0x02 解决方法

既然走容器网络导致性能差,修改服务端的部署形式为 hostNetwork,绕过容器网络。但带来一个问题,存储服务可能切换节点,导致 client 端无法正常重连(切换节点带来的数据不一致的问题能处理),这一点不能接受。

新的方案:

为服务端创建一个 Headless Service,针对 Deployment 类型的负载Headless Service会解析提到所有Pod的 IP 地址列表具体见官方文档,那唯一的问题还剩下 client 重连时,这个域名怎么解析?因为使用的驱动是内核提供的,内核中无法直接使用glibc的域名解析功能,即无法使用外部的DNS Server,即使是/etc/resolv.conf中指定的。

0x03 request-key 机制

通过调查了解到内核提供了request-key机制,可以从内核调用到用户态的应用。request-key本来是用于内核和用户态之间的安全token管理的,后也扩展用于其他用途。以内核解析域名来说,大概流程如下:

  1. 内核发起域名解析转到dns_resolver模块【内核态】。
  2. 发起request-key请求转到key管理模块【内核态】。
  3. key管理模块调用/sbin/request-key,调用到用户态【内核态】。
  4. /sbin/request-key根据/etc/request-key.conf中的配置,分发到对应的命令调用,示例为/sbin/key.dns_resolver【用户态】。
  5. /sbin/key.dns_resolver调用glibc域名解析,完成解析,并调用request-key相关系统调用,设置好payload,即域名对应的IP地址【用户态】。

但还有新的问题:key.dns_resolver只能使用/etc/hosts和/etc/resolv.conf解析域名,不支持从额外的dns server解析域名。

0x04 具体的方案

所有的方法都要通过修改 /etc/request-key.conf配置文件指定自己的程序进行解析。

后面的流程有以下方案:

自己写脚本,通过/etc/request-key.conf配置文件指定自己的脚本,通过kubectl去查询 Pod IP地址,调用/sbin/request-key将结果写回。

问题:C语言中对字符串的处理在dns_resolver和request-key两个模块之间发生了冲突,使用/sbin/request-key写入的IP地址被dns_resolver内核模块认为非法,这个方案行不通,详见QA部分解释。

通过C调用key-utils的SDK,可以实现同样的功能,但基本上照抄key.dns_resolver的实现。突然想到可以用Python调用so库的方法,验证了下基本可行。但又有一个新的问题:

Python标准库中的域名解析同样不支持指定域名,想要支持就要引入第3方的dns模块。

最终方案比较:

方案 优点 缺点
写Python调用key-utils的SDK so完成IP写回内核 灵活控制对coreDNS的访问。 需要调用第3方的dns解析服务、或者直接访问 kube-apiserver获取IP,加重kube-apiserver的负担。
shell脚本通过unshare mount namespace 隔离,生成临时的/etc/resolv.conf,调用/sbin/key.dns_resolver实现 不用访问 kube-apsierver,根据kubelet的配置可获取coreDNS的地址,不用感知具体的DNS解析细节。更通用,其他的 headless也可以用 无法控制调用频率

考虑这种异常切换解析并不会太频繁,最终选择了第2种方案。mount namespace 可以方便地通过 unshare -m 来实现。

0x05 补充QA

Q:/sbin/key.dns_resolver支持从/etc/hosts解析域名,为什么不修改 /etc/hosts?

A:/etc/hosts是全局配置,修改冲突不容易控制,出现冲突时影响不可控。

Q:为什么不能修改/etc/resolv.conf配置,指向coreDNS?

A:虽然coreDNS也支持将非k8s域名转向宿主中/etc/resolv.conf中的指定的DNS,但这种机制依赖 coreDNS,对整个系统的影响过大。

Q: 为什么不用/sbin/request-key回写解析到的IP地址?

A:这种实现了验证了,发现request-key和dns_resolver的实现关于C中字符串的处理有不一致的地方,前者payload长度未包含\0,后者要求包含。这一点是通过bpf钩子确认的。

0x06 总结

问题的解决过程中尝试了多种方案,最终最适合的方案巧妙运用了命名空间隔离机制,这也是了解容器底层原理的好处。

同时带来一点关于命名空间的用途回顾:

  1. 容器内不希望被宿主机影响。
  2. 容器内不期望影响宿主机(本文中的场景),可随意设置/etc/resolv.conf。

k8s实践——命名空间隔离+request-key机制解决CSI内核态域名解析的更多相关文章

  1. 大型网站技术架构(四)--核心架构要素 开启mac上印象笔记的代码块 大型网站技术架构(三)--架构模式 JDK8 stream toMap() java.lang.IllegalStateException: Duplicate key异常解决(key重复)

    大型网站技术架构(四)--核心架构要素   作者:13GitHub:https://github.com/ZHENFENG13版权声明:本文为原创文章,未经允许不得转载.此篇已收录至<大型网站技 ...

  2. k8s实践 - 如何优雅地给kong网关配置证书和插件。

    前言 从去年上半年微服务项目上线以来,一直使用kong作为微服务API网关,整个项目完全部署于k8s,一路走来,对于k8s,对于kong,经历了一个从无到有,从0到1的过程,也遇到过了一些坎坷,今天准 ...

  3. 用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面

    用nginx的反向代理机制解决前端跨域问题在nginx上部署web静态页面 1.什么是跨域以及产生原因 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,或是a页面为ip地 ...

  4. 02 | 健康之路 kubernetes(k8s) 实践之路 : 生产可用环境及验证

    上一篇< 01 | 健康之路 kubernetes(k8s) 实践之路 : 开篇及概况 >我们介绍了我们的大体情况,也算迈出了第一步.今天我们主要介绍下我们生产可用的集群架设方案.涉及了整 ...

  5. atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php

    atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 .打开浏览服务器文件夹java .net php 1. 环境:::项目java web,需要打开浏览服 ...

  6. atitit.提升稳定性---hibernate 增加重试retry 机制解决数据库连接关闭

    atitit.提升稳定性---hibernate 增加重试retry 机制解决数据库连接关闭 1. 流程总结 retry(5times).invoke(xxx).test().rest().$() t ...

  7. atitit.提升稳定性---hibernate 添加重试retry 机制解决数据库连接关闭

    atitit.提升稳定性---hibernate 添加重试retry 机制解决数据库连接关闭 1. 流程总结 retry(5times).invoke(xxx).test().rest().$() t ...

  8. 说说Request.Params[key]和Request[key]

    摘要 其实你一看到,就应该会想到,这个不简单吗,不就是服务端接收参数的一种方式吗?是的.在asp.net编程中,QueryString.Form.Cookie是三种比较常见的接收客户端参数的方式.Qu ...

  9. 报错:this class is not key value coding-compliant for the key closeLotTextField解决方法

    几种情况下都会报这种错误: 1,加载自定义的tableViewCell的时候总是死在: XInstrumentOpenCell *cell = [tableViewdequeueReusableCel ...

  10. 在Springmvc普通类@Autowired注入request为null解决方法

    在Springmvc普通类@Autowired注入request为null解决方法   在类中加入以下注入request对象的代码,运行时发现request为null,注入失败.在@Controlle ...

随机推荐

  1. 视觉语言跨模态特征语义相似度计算改进--表征空间维度语义依赖感知聚合算法 ACM MM

    论文链接:Unlocking the Power of Cross-Dimensional Semantic Dependency for Image-Text Matching (ACM MM23) ...

  2. 使用bootchart 对 高通Android 进行性能分析

    使用bootchart 对 高通Android 进行性能分析 Android版本:7.0 适用平台:高通和MTK 参考: https://blog.csdn.net/qq_19923217/artic ...

  3. ubuntu 安装 github desktop

    原文: https://gist.github.com/berkorbay/6feda478a00b0432d13f1fc0a50467f1 sudo wget https://github.com/ ...

  4. 使用Sqlcel操作数据库整理数据视频

    链接:https://pan.baidu.com/s/1G4FJbLbN0oXAu61syWxCOA 提取码:noyz

  5. P8451 题解

    显然,题面明摆着让你写一个可持久化 AC 自动机. 但是从空间来说这是不可能的. 想起做 不强制在线 的可持久化数据结构的一种方法,建立"时光树",具体来说,假若版本 \(x\) ...

  6. Java集合框架总结图

    Collection 接口的接口(对象集合) ├---List 接口:元素都有索引,可以重复,有序(迭代器顺序). │------├ LinkedList 接口实现类, 双向链表, 查询慢,增删快,效 ...

  7. Solo 开发者周刊 (第4期):什么样的新科技,能提高生活效率?

    这里会整合 Solo 社区每周推广内容.产品模块或活动投稿,每周五发布.在这期周刊中,我们将深入探讨开源软件产品的开发旅程,分享来自一线独立开发者的经验和见解.本杂志开源,欢迎投稿. 好文推荐 AI生 ...

  8. 使用GSAP制作动画视频

    GSAP 3Blue1Brown给我留下了深刻印象.利用动画制作视频,内容简洁,演示清晰.前两天刚好碰到一件事,我就顺便学习了一下怎么用代码做动画. 以javascrip为例,有两个动画引擎,GSAP ...

  9. manim边学边做--Matrix

    在代数问题中,矩阵是必不可少的工具,manim中提供了一套展示矩阵(Matrix)的模块,专门用于在动画中显示矩阵格式的数据.关于矩阵的类主要有4个: Matrix:通用的矩阵 IntegerMatr ...

  10. 解读GaussDB(for MySQL)灵活多维的二级分区表策略

    本文分享自华为云社区<GaussDB(for MySQL)创新特性:灵活多维的二级分区表策略>,作者:GaussDB 数据库. 背景介绍 分区表及二级分区表的功能,可以让数据库更加有效地管 ...