前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【警惕】K8S下Telnet失效陷阱

【警惕】K8S下Telnet失效陷阱

作者头像
运维部落
发布2020-08-20 15:00:33
2.1K0
发布2020-08-20 15:00:33
举报
文章被收录于专栏:运维部落运维部落
  • 问题第一阶段
  • 问题第二阶段
  • 【必看】终于抓住大妖怪
    • 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命令时,总会报错,

代码语言:javascript
复制
[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

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

代码语言:javascript
复制
[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配置文件了,因为是二进制安装的,所以

代码语言:javascript
复制
kubeadmin config print-default

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

代码语言:javascript
复制

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 版本的配置对比后,也确认配置是生效的,但问题没有消除,依旧报错

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

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

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

代码语言:javascript
复制
[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接受并处理请求,最终的数据按原路返回给请求方

一个完整的请求流结束。

所以,我们

代码语言:javascript
复制
telnet pod1 30007

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

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

telnet

敲黑板!

敲黑板!

敲黑板!

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

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

01 有svc但无pod

  1. 创建svc
代码语言:javascript
复制
kubectl apply  -f tmp-svc.yml
代码语言:javascript
复制
# 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
代码语言:javascript
复制
# 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的网络架构是出了名的复杂!在这之前,要请大家需要做好一些基础网络知识技能储备。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维部落 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【警惕】K8S下Telnet失效陷阱
    • 问题第一阶段
      • 问题第二阶段
        • 【必看】终于抓住大妖怪
          • 01 有svc但无pod
          • 02 有svc 有pod
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档