本文是上海站 Meetup 讲师王文虎根据其分享内容整理的文章。

KubeSphere 社区的小伙伴们,大家好。我是中通快递容器云平台的研发工程师王文虎,主要负责中通快递容器云平台开发、应用容器化推广、容器平台运维等工作。非常感谢 KubeSphere 社区的邀请,让我有机会跟大家分享中通快递关键业务和复杂架构挑战下的 Kubernetes 集群服务暴露实践。

ZKE 容器管理平台

首先介绍一下中通的容器云管理平台 ZKE。ZKE 平台是基于 KubeSphere 开发的,现在管理的中通内部集群超过十个,包含开发、测试、预发布、生产等环境,所有用户都通过 ZKE 平台管理容器应用。

Kubernetes 集群服务暴露方案

根据中通的实际业务需求和一些探索,梳理出了中通 kubernetes 集群服务暴露的几种方案。

Dubbo 服务之间访问

中通大部分应用都是基于 Java 语言开发的,使用的微服务框架为 Dubbo。在上容器之初,我们考虑到虚拟机和容器并存的场景可能会持续很长时间,所以在规划 Kubernetes 集群的时候,通过把容器网络和物理网络打通的方式,来解决 Dubbo 服务在容器和虚拟机混布的场景下互相调用的问题。

  • 如何打通 Kubernetes 容器网络和物理网络?

我们内部环境中 Kubernetes 集群网络组件使用 calico BGP 模式,数据中心物理网络也开启了 BGP 路由协议,通过在物理网络上开启 BGP RR(Route Reflector),避免后期集群规模太大导致 BGP 宣告路由条目过多的问题。BGP RR 和 Kubernetes 集群节点建立 EBGP 邻居,互相学习路由。

泛域名方式访问

在初步推广开发和测试容器化时,我们遇到最多的问题就是用户在应用发布到容器环境后如何访问。

用户在 ZKE 平台上创建 Ingress 以后,该域名是不能访问的,必须要运维把域名指向集群 Ingress Controller,而且公司申请域名需要走 OA 流程,所以这就使得我们的容器环境在初始推广阶段进度很慢。

我们收集了部分用户的反馈,加上自己的思考,终于探索出了一条开发/测试环境比较高效的 Ingress 使用之路:

通过给每个集群分配一个三级泛域名,在公司 DNS 上配置把对应泛域名指向集群的 Ingress Controller,用户后续创建业务域名时可以直接在 ZKE 界面上创建 Ingress,该域名便会立即生效,省去了很大部分测试和开发环境上容器的时间,因为公司安全管理要求,Ingress 只提供了暴露 HTTP 协议的功能,但是这一措施也还是很大程度加快了测试开发容器化的推广速度。

自定义域名访问

泛域名可以帮我们解决大部分开发/测试环境的域名需求,但是针对生产环境、项目域名需要使用 HTTPS 协议、项目需要自定义域名这些场景时,用户除了需要创建 Ingres 之外,还是需要通过 OA 流程进行审批的。

服务暴露方案踩坑实践

以下内容是我们在使用 Kubernetes 的过程中服务暴露以及网络相关踩的坑,供大家参考以避坑。

Ingress Nginx Controller 服务踩坑实践

下图是我根据 Ingress Nginx Controller 代码启动流程,画的启动流程图(关于启动流程以及这个问题更详细分析可以查看链接:https://mp.weixin.qq.com/s/Pw9-_cPXxhfrd6btSXUrqA)。

Ingress Nginx Controller 启动流程与一个通用的 K8S Controller 的类似,但是真正执行把 K8S Ingress 及其相关资源同步到 Nginx 配置文件的业务逻辑是从 n.syncIngress 函数开始的,这个留到下面说。

该问题是我们测试环境使用过程中踩过的一个坑,用户通过 ZKE 管理平台创建 Ingress 时触发了集群 Ingress Controller 故障。我们在做故障分析时发现了故障复现的条件,如下图所示:

前面说到 n.syncIngress 函数是 Ingress Nginx Controller 业务逻辑的入口,从该入口到本次故障最终调用函数中间的调用链 PPT 中也有提供,最终的问题点落在了 extractTLSSecretName 函数。

根据代码逻辑再分析一下原因:

  1. createServers 函数会遍历 ing.Spec.Rules,当 ing.Spec.TLS 字段不为空时会把 rule.Host、ingress 以参数形式传入 extractTLSSecretName 函数;
  2. extractTLSSecretName 函数首先会遍历 ing.Spec.TLS,校验 tls.Hosts 中是否包含 host,如果包含直接返回 tls.SecretName
  3. tls.Hosts 中不包含 host 时,会把 tls.SecretName 对应的 secret 资源转为 *ingress.SSLCert 类型并且校验 host 是否匹配证书中的 SAN 或 CN 属性。然而当配置的 secret 为非 TLS 类型证书时,cert.Certificate 值为 nil,就会导致 cert.Certificate.VerifyHostname(host) 处代码会报 panic 导致主程序异常,然后 nginx controller 就挂了;

修复措施分两部分:

  1. 平台用户操作层面避免这种情况:主要是通过用户创建 ingress 选择证书时过滤掉非 TLS 类型的 secret,保证绝大部分通过平台使用者不会触发此类问题;
  2. 修复代码逻辑根治此问题:增加判断 cert.Certificate 是否为nil的逻辑。

Calico 关闭 natOutgoing 配置

这个配置发生的背景是在 Dubbo 应用生产容器化过程中,生产环境 Zookeeper 对单个 IP 连接限制数比节点上 Pod 数小,导致节点上容器里的 Dubbo 应用经常会出现连接 Zookeeper 被拒绝的问题。再因为容器网络和物理网络已经打通,通过 calico 配置 natOutgoing 参数为 false,这个问题就迎刃而解了。

本文由博客一文多发平台 OpenWrite 发布!

中通快递关键业务和复杂架构挑战下的 Kubernetes 集群服务暴露实践的更多相关文章

  1. Kubernetes 集群日志 和 EFK 架构日志方案

    目录 第一部分:Kubernetes 日志 Kubernetes Logging 是如何工作的 Kubernetes Pod 日志存储位置 Kubelet Logs Kubernetes 容器日志格式 ...

  2. 初试 Kubernetes 集群中使用 Traefik 反向代理

    初试 Kubernetes 集群中使用 Traefik 反向代理 2017年11月17日 09:47:20 哎_小羊_168 阅读数:12308    版权声明:本文为博主原创文章,未经博主允许不得转 ...

  3. (转)在Kubernetes集群中使用JMeter对Company示例进行压力测试

    背景 压力测试是评估应用性能的一种有效手段.此外,越来越多的应用被拆分为多个微服务而每个微服务的性能不一,有的微服务是计算密集型,有的是IO密集型. 因此,压力测试在基于微服务架构的网络应用中扮演着越 ...

  4. linux运维、架构之路-Kubernetes集群部署

    一.kubernetes介绍        Kubernetes简称K8s,它是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部 ...

  5. 中通快递股份有限公司.net高级面试题

    中通快递分布式技术开发   gc垃圾回收原理 .net中,托管代码的内存管理是自动的,由GC进行管理,而对于非托管代码,则需要.net手动处理 CLR运行时,内存分为:托管堆和栈,其中栈用于存储值类型 ...

  6. 【转载】浅析从外部访问 Kubernetes 集群中应用的几种方式

    一般情况下,Kubernetes 的 Cluster Network 是属于私有网络,只能在 Cluster Network 内部才能访问部署的应用.那么如何才能将 Kubernetes 集群中的应用 ...

  7. kubernetes集群中的pause容器

    昨天晚上搭建好了k8s多主集群,启动了一个nginx的pod,然而每启动一个pod就伴随这一个pause容器,考虑到之前在做kubelet的systemd unit文件时有见到: 1 2 3 4 5 ...

  8. 解决项目迁移至Kubernetes集群中的代理问题

    解决项目迁移至Kubernetes集群中的代理问题 随着Kubernetes技术的日益成熟,越来越多的企业选择用Kubernetes集群来管理项目.新项目还好,可以选择合适的集群规模从零开始构建项目: ...

  9. 如何在 Kubernetes 集群中玩转 Fluid + JuiceFS

    作者简介: 吕冬冬,云知声超算平台架构师, 负责大规模分布式机器学习平台架构设计与功能研发,负责深度学习算法应用的优化与 AI 模型加速.研究领域包括高性能计算.分布式文件存储.分布式缓存等. 朱唯唯 ...

  10. ingress-nginx 的使用 =》 部署在 Kubernetes 集群中的应用暴露给外部的用户使用

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247488189&idx=1&sn=8175f067 ...

随机推荐

  1. Gradle工程编译报错:Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierImpl.getModuleIdentifier()Lorg/gradle/api/artifacts/ModuleIdentifier;

    1.背景 从git上拉取代码后,编译报错如下: Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm ...

  2. 面试题:写一个遍历ArrayList的时候,删除一个元素的例子?并说说原理。

    代码实现 方法一:for循环 public static void main(String[] args) { ArrayList<String> list = new ArrayList ...

  3. LeetCode40.组合总和II

    LeetCode40.组合总和II 力扣题目链接(opens new window) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 ...

  4. MPTCP(五):MPTCP路径管理工具iproute2/ip-mptcp编译及安装

    简介 ip-mptcp是一个MPTCP路径管理工具,它可以决定哪些链路允许作为MPTCP子流存在 仅对MPTCPv1有效 在支持MPTCPv1的内核中使用man ip-mptcp可以查看相关帮助 gi ...

  5. RISC-V全志D1多媒体套件文章汇总

    提示 此开发板的任何问题都可以在我们的论坛交流讨论 https://forums.100ask.net/c/aw/d1/57 文章目录汇总 教程共计14章,下面是章节汇总: 第0章_RISC-V全志D ...

  6. 关于EF延时加载的面试题

    public async Task<ActionResult> GetData() { var data = (from leftdata in GetLeft() join rightd ...

  7. OpenTelemetry 实战:从零实现应用指标监控

    前言 在上一篇文章:OpenTelemetry 实战:从零实现分布式链路追踪讲解了链路相关的实战,本次我们继续跟进如何使用 OpenTelemetry 集成 metrics 监控. 建议对指标监控不太 ...

  8. Docker 导出容器 / 镜像

    有时由于镜像大小.网络限制等原因,我们不能将本地制作的容器 / 镜像上传到公共容器注册表.此时我们可以选择将镜像以本地文件的形式导出. 导入 / 导出容器 docker export "CO ...

  9. Dify大语言模型应用开发平台新手必备:安装注册与私有服务器部署全步骤

    Dify简介 Dify是一个开源的大语言模型(Large Language Model, LLM)应用开发平台.它融合了后端即服务(Backend as a Service, BaaS)和LLMOps ...

  10. python3实现url全编码/解码

    最近在学习SQL注入,绕过方法中有编码注入绕过,需要将关键词进行全编码,百度了一下没有找到全编码工具,所有的编码工具里"and"编码完还是"and",于是查了一 ...