专栏首页运维部落【警惕】K8S下Telnet失效陷阱

【警惕】K8S下Telnet失效陷阱

  • 问题第一阶段
  • 问题第二阶段
  • 【必看】终于抓住大妖怪
    • 01 有svc但无pod
    • 02 有svc 有pod

【警惕】K8S下Telnet失效陷阱

脱离背景谈历史就是耍流氓,没想到在纯技术层面也能应验

文章会涉及到的技术领域如下:

  1. k8s集群
  2. Docker
  3. redis命令使用
  4. 网络基础

事情是这样的...

周一我们突然发现集成k8s的测试环境不能正常使用了,现象如下:

  1. GET方法的静态地址规律性404
  2. 登录页面504
  3. 验证码无法获取

追踪nginx和业务程序日志后,我们基本能定位到是 redis 服务不可用和后端的一台nginx容器无法连接导致问题。我们的简易架构图如下:

archer

定位到问题后,我们认为问题应该很好解决了。我们在 proxy中去掉有问题的服务器。前端 404的问题解决了。但在问题2和问题3上,我们折腾了2天依然才解决了问题却依然无法修复根源问题

先介绍一个大背景。历史原因,我们有一套 V1.5版本的k8s集群,大家要知道,现在k8s最新版已经是 1.18了,这样的大背景,对我们排查问题造成了很大的困扰。具体的困扰如下:

  1. 1.5版本的k8s,使用的二进制安装的方式,技术门槛高但维护人员已经离职;
  2. 整套k8s环境只在测试环境应用,生产和开发环境均没有使用,即流程是断档的;

问题第一阶段

问题1:最大的问题是我们要尽快学会1.5版本的k8s,比如1.5版本不使用 ~/.kube/conf 来管控k8s,这个在问题排查初期我们可不是这么认为的,因为我们在执行kubectl命令时,总会报错,

[root@k8s:~]# kubectl  get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

直接搜索报错关键字会发现,所有的解决方案都指向 ~/.kube/conf 不存在。大家要留意,这是google的搜索结果哦,说服力很强的哦。

google-resule

经检查确实没有发现该文件,

[root@K8S:~]# ls ~/.kube/
cache  schema

所以在问题第一阶段,我们理所当然的认为是哪位误删除了k8s的集群配置文件。

我们起初认为是哪位只是把 ~/.kube/conf 删除了,所以想把 /etc/kubernetes/admin.conf 复制到 .kube/conf 即可,但可悲的是这个文件也没有。

我们当时很生气但更害怕,因为我们再次觉得,是哪位入侵了我们的服务器「Linus会不会哭晕在厕所,他的Linux是如此的不靠谱,只要出问题,就怀疑是服务器被入侵」,因为这根本不像是误删除,根本就像是有意而为。

虽然被产品、开发、测试催成狗,我还是简单过滤了系统安全日志和 command history,初步确认没有入侵痕迹后,心里略松了一口气「linus想必也已经退了要我面基的飞机票」。

  • 生成 .kube/conf 配置

ok,现在问题的重心就是生成 .kube/conf配置文件了,因为是二进制安装的,所以

kubeadmin config print-default

直接生成配置的办法也泡汤了,在连蒙带骗的各种尝试下,我们拼出了 k8s 1.5版本生成 conf的方式。

kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/openssl/ca.crt \
  --embed-certs=true \
  --server=https://ipadress:443 \
  --kubeconfig=kubectl.kubeconfig

总算是生成 ~/.kube/conf了,但接下来蒙逼的事情发生了。

问题第二阶段

~/.kube/conf 有了,在和1.16 版本的配置对比后,也确认配置是生效的,但问题没有消除,依旧报错

[root@k8s:~]# kubectl  get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?

这时我们怀疑集群真的是坏了.... 但到目前为止不知道怎么去修.... 所以我们只能告知产品、开产、测试、PM尝试在其它测试环境重构测试数据...

当时我有怀疑是服务器重启,k8s的进程不在了,所以特意看了下系统时间

[root@K8S:~]# uptime
 13:19:20 up 82 days, 18:52,  1 user,  load average: 0.18, 0.21, 0.24

看到这里,我没怀疑是进程挂了因为没理由,后面的事实证明,是我幼稚了。但现在想解决这个问题,只能找到二进制安装k8s的文档,重头再来遍试试了。

网上1.5的版本太少了。抱着试试的态度,我在wiki上找了找,竟然找到部署文档。

神奇又恶心的事情来了,两个

  1. master机的kube-apiserver竟然没有

了解 k8s 架构的朋友知道,googlek8s的架构中,是专门把apiserver进程独立出来,是Master/Node及所有api接口的总闸门。

  1. .kube/conf 没用

为了验证 .kube/conf 在k8s 1.5版本中确实无用,所以我们特意mv conf{,.bak},发现1.5版本确实不需要conf。

Too young, Too Simple

到这里,你以为问题就搞定了吗?...

Too young, Too Simple +2

【必看】终于抓住大妖怪

我们以为大功告成,让大家用起来。这时才发现 问题2和问题3问题依旧。即验证码和登录依然 5xx。。

进一步排查问题后,我们发现,业务日志里报错 redis 无法连接.

这个问题,我们起初认为是小问题,因为通常问题无非两个:

  1. 网络不通
  2. 进程没启动
  • 网络不通

简单画下k8s svc 模式下数据流走向。

redis-k8s

  1. pod 中的容器监控 6379端口,并在映射到本机物理端口 30007;
  2. 用户/程序访问 redis 时,先经过svc, svc 在etcd中查询到对应主机,对应端口后;
  3. kube-proxy把请求转发至对应主机的kube-proxy进程
  4. kube-proxy接受并处理请求,最终的数据按原路返回给请求方

一个完整的请求流结束。

所以,我们

telnet pod1 30007

如果通的话,即可以证明 redis 就是通的了?对吧?「嘿嘿,记住你心里的答案哦」

telnet是时代的产物,发展至今就只剩下测试对端程序是否监听了TCP指定端口。如果能出现如下类似提示,即可以说明对端已经监听了指定的端口了,这是毫无疑问且无争议的

telnet

敲黑板!

敲黑板!

敲黑板!

重要的事情说三遍!通常情况下,确实如此。但结合k8s后,这里有一个巨大的陷阱!!

下面会通过两个试验给大家说明,请耐心看下去:

01 有svc但无pod

  1. 创建svc
kubectl apply  -f tmp-svc.yml
# cat tmp-svc.yml
apiVersion: v1
kind: Service
metadata:
  name: tmp-port
spec:
  type: NodePort
  ports:
  - port: 6379
    targetPort: 6379
    protocol: TCP
    name: httprequest
    nodePort: 30090
  selector:
    t1: tmp-port
  1. telnet测试

大家会发现,端口全部都能 telnet 通的哦!

但需要注意的是!

注意!

注意!!

我们集群中并没有labelt1=tmp-port 的pod哦

telnet

  1. Redis-cli测试

redis-cli测试

redis-cli 是可以正常连通的哦!

这点很重要,这里要埋个伏笔。

02 有svc 有pod

  1. 创建 svc和pod
# cat im-redis-service.yml
apiVersion: v1
kind: Service
metadata:
  name: t1-im-redis
spec:
  type: NodePort
  ports:
  - port: 6379
    targetPort: 6379
    protocol: TCP
    name: httprequest
    nodePort: 30031
  selector:
    t1: im-redis

pod yml太长,这里不详述。

  1. telnet测试

telnet测试

  1. redis-cli测试

大家也能看到,redis-cli 是能正常连接的哦

redis-cli连接测试

那么问题来了?!!!大家还记得前面问大家的问题吗?

telnet通了就代表服务正常启动了?!

大家有没有发现,在结合k8s后,连telnet都不能相信了。我们必须用最贴近结果的方式来验证结果,才有可能得到我们最终期望的结果

啊!生活好难!

请不要小看这个问题,为什么我敢这么讲呢?你想像这么一个场景:

你的k8s集群中,每个节点上运行有诸多POD容器,而这些节点有一个节点不明原因坏了,容器都可以正常部署且状态正常,telnet也可以通,监控也正常,但就是外部的其它节点无法连通他。

你想想该如何发现并定位到问题吧。。。

下次抽时间和大家聊聊 k8s 的网络架构,但k8s的网络架构是出了名的复杂!在这之前,要请大家需要做好一些基础网络知识技能储备。

本文分享自微信公众号 - 运维部落(linux178),作者:松鼠尚学堂

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • xargs 命令教程

    上面的代码使用了管道命令(|)。管道命令的作用,是将左侧命令(cat /etc/passwd)的标准输出转换为标准输入,提供给右侧命令(grep root)作为...

    运维部落
  • 分布式系统的时间问题

    1 什么是时间? 2 物理时间:墙上时钟 3 逻辑时钟:为事件定序 4 Turetime:物理时钟回归 5 区块链:重新定义时间 6 其他影响 6.1 NT...

    运维部落
  • 分享给您一个快速离职的 SHELL 脚本

    哪位同学清理磁盘空间了,因为实在太干净了,只剩下几个必要的目录其它的文件全被删除了。「安全原因这里就不放图了」

    运维部落
  • 一个MySQL服务CPU 100%的优化案例反思

    昨天在快下班的时候和同事处理了一起性能故障导致的服务器CPU 100%的案例。虽然问题解决了,但是在事后我做了一些反思,总体来说不够乐观。

    jeanron100
  • Rafy 领域实体框架演示(2) - 新功能展示

    本文的演示需要先完成上一篇文章中的演示:《Rafy 领域实体框架示例(1) - 转换传统三层应用程序》。在完成改造传统的三层系统之后,本文将讲解使用 Rafy ...

    用户1172223
  • 不小心给了小程序「授权」,怎么撤回?| 小程序问答 #49

    最常见的,大概就是请求「获取你的昵称、头像」。除此之外,当小程序想要使用你的地理位置、麦克风等的时候,也需要你的授权才能获取。

    知晓君
  • 小程序可以缓存视频吗?| 小程序问答 #24

    小程序为何不能缓存视频?那又如何安全地清理小程序中的缓存数据呢?知晓程序(微信号 zxcx0101)今天就来为你解答这两个问题。

    知晓君
  • 400% 的飞跃-web 页面加载速度优化实战

    一个网站的加载速度有多重要? 反正我相信之前来博主网站的人至少有 50% 在加载完成前关闭了本站。 为啥捏? 看图

    前端博客 : alili.tech
  • 一个不会代码、设计的小编,怎么制作一个专业的微信小程序

    摆脱APP,微信小程序轻装上阵 微信小程序“无需安装、用完即走”,所耗内存也只有几M,甚至可以忽略不计。相比每一个APP都在几十M以上,微信小程序更加的“小而美...

    企鹅号小编
  • 移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

    本系列文章引用了腾讯技术专家樊华恒《海量之道系列文章之弱联网优化》的部分章节,感谢原作者。

    JackJiang

扫码关注云+社区

领取腾讯云代金券