0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Kubernetes 集群的功能

马哥Linux运维 来源:马哥Linux运维 作者:马哥Linux运维 2022-09-05 10:58 次阅读

Telepresence 是一个开源工具,可让您在本地运行单个服务,同时将该服务连接到远程 Kubernetes 集群。

为什么需要 Telepresence

k8s pod IP 由 CNI 分配, 通信是走 overlay 网络, 容器之间的通信都是基于 cluser IP.

cluser IP 并不像我们平常所用的 IP. 它只能在 k8s 集群内部使用.

虽然我们可以通过配置 overlay 网络的网段 跟 k8s node 的网段在一个大的子网段, 然后通过 vpn 把对应网段的流量路由到 overlay 网络, 我们完全可以通过 kubectl get po -o wide 获取到 pod IP, 然后访问服务.

也就是说, 如果我们在本机想运行一个服务, 不依赖 Telepresence 这种工具是完全可行的.

但是, 其实我们每个服务都有配置, 配置里面写的 grpc 服务地址可能像这样: xxxx.svc.cluster.local:1234, 如果我们想要服务的配置不经过任何修改, 直接在本机运行.

有没有办法呢? 答案当然是有的, 设置 hosts 啊. kubectl get po -o wide 获取到 pod IP 和 pod name, (假设 pod name 和 service name 命名是一致的,即从 pod name 我们可以字面上得到 service name) 然后拼接成 k8s 里面的 DNS name xxxx.svc.cluster.local, 将这个域名映射到 pod IP 即可. 假设我们写了这样一个脚本, 但是当 pod 被调度到不同的 node, 或者 pod 重建之后, 其 pod IP 必然会改变, 这个时候我们又要手动去重新生成这个 hosts 文件. 总体操作来说, 还是挺麻烦的.

另一个问题是, 团队内部有很多人, 要让所有人都学会这一招操作, 可能会有些困难, 或者说, 这种方式, 对用户不太好友.

这个时候, Telepresence 横空出世.

在 k8s 官方文档中, “ 本地开发和调试服务[1]” 一节, Telepresence 是唯一介绍的工具.

对于用户来说, Telepresence 提供了 3 个非常重要的功能:

cluster 域名解析

cluster 流量代理

cluster 流量拦截

域名解析 可以使我们在本地开发机器直接解析如 xxxx.svc.cluster.local 这种域名.

(注: mac 下面机制不太一样, 不可以使用 dig 测试,但是可以用 curl)

你可以像查询其它域名一样使用命令行 dig 工具进行查询, 如 dig kubernetes.default

光有域名解析还不够, 我们还是没法连接集群内的其它服务, 因此 流量代理 功能的作用就体验出来了.

Linux 下面, Telepresence 会建立一个名叫 tel0 的 tun 设备. 然后通过 systemd-resolved 服务将集群命令空间的 cluster domain 添加到这个设备. 通过resolvectl status tel0可以查看到当前有哪些命令空间被添加进来了:

resolvectlstatustel0
Link66(tel0)
CurrentScopes:DNSLLMNR/IPv4LLMNR/IPv6
Protocols:-DefaultRoute+LLMNR-mDNS-DNSOverTLSDNSSEC=no/unsupported
CurrentDNSServer:10.0.165.145
DNSServers:10.0.165.145
DNSDomain:~ambassador~argocd~cluster.local~db~default~devops~istio-system~jaeger~kube-public~kube-system~nacos~observability

流量拦截 可以将集群里指定服务的流量拦截并转发到本地开发机器, 比如调试复杂的 app 业务接口时,非常方便.

这个非常有用, 但是老灯平常一般都不用这个. 因为我们的服务都有注入 istio side car. 而 Telepresence 的拦截原理其实也跟 istio 类似, 也是利用 side car 注入然后代理流量. 但是同一个 pod 的流量, 不能同时被 istio 接管, 然后又被 Telepresence 接管. 这一点我后面再详细说怎么解决.

日常使用

telepresence connect 连接

telepresence status 查看连接状态

curl -ik https://kubernetes.default 测试连接成功与否( 有任意响应就是成功)

telepresence quit -u -r 断开连接并退出 user 和 root daemon

DNS 解析原理

这部分主要参考:

https://www.telepresence.io/docs/latest/reference/routing/

Linux systemd-resolved resolver

以 Linux 上面的实现为例, 简单来说, Telepresence 就是新建一 tun 设备, 这个设备的流量会代理到 k8s 里的 Telepresence traffic manager ( 负责流量转发等). tun 设备的 DNS 被设置成了 k8s 集群的 DNS (一般是 coredns 啦). Telepresence 会 watch 整个集群的所有命名空间, 因此, 当发生变量的时候, DNS link domain 会被自动更新.

然后, 设置哪此命令空间后缀要通过这个 DNS 查询 是通过 systemd-resolved 的服务的 dbus 接口[2] SetLinkDomains 操作的. 设置 DNS 是通过 SetLinkDNS

这种操作, 其实就相当于在 /etc/systemd/resolved.conf.d 下面新建一 k8s.conf 文件, 内容类似于:

#https://learn.hashicorp.com/tutorials/consul/dns-forwarding#systemd-resolved-setup
[Resolve]
DNS=10.0.165.145:53
DNSSEC=false
Domains=~ambassador~argocd~cluster.local~db~default~devops~istio-system~jaeger~kube-public~kube-system~nacos~observability

只不过, 通过 dbus 可以动态的修改, 更加方便.

Linux overriding resolver

Linux systems that aren’t configured withsystemd-resolvedwill use this resolver. A Typical case is when running Telepresence inside a docker container[3]. During initialization, the resolver will first establish afallbackconnection to the IP passed as--dns, the one configured aslocal-ipin the local DNS configuration[4], or the primarynameserverregistered in/etc/resolv.conf. It will then use iptables to actually override that IP so that requests to it instead end up in the overriding resolver, which unless it succeeds on its own, will use thefallback.

即, 对于不支持 systemd-resolved 的 Linux 系统(Centos7 默认就没安装), Telepresence 会自己起一个 DNS 代理服务, 一般是监听随机端口, 然后再将系统 DNS 设置成 TelepresenceDNS 代理服务的地址. 即解析的时候会先查集群, 没有结果会 fallback 到本机原来的 DNS, 比如 Google public DNS 等解析其它域名.这个会影响其它应用的使用, 这种实现方式不太好, 以老灯的使用经验来看, 这种方式也不太稳定. 容易造成问题.

进击云原生 注释:
通过 iptables DNAT 到 Telepresence 代理服务

macOS resolver

在 macOS 下面是通过 resolver hooks 实现的.

This resolver hooks into the macOS DNS system by creating files under/etc/resolver. Those files correspond to some domain and contain the port number of the Telepresence resolver. Telepresence creates one such file for each of the currently mapped namespaces andinclude-suffixesoption. The filetelepresence.localcontains a search path that is configured based on current intercepts so that single label names can be resolved correctly.

这个解析器通过在' /etc/resolver '下创建文件来钩子到 macOS DNS 系统。这些文件对应某个域,包含 Telepresence 解析器的端口号。Telepresence 会为每个当前映射的名称空间和“include-suffix”选项创建一个这样的文件。文件telepresence.local包含基于当前拦截配置的搜索路径,以便能够正确解析单个标签名称。

troubleshooting

1. 流量拦截不生效

测试过程中发现 流量拦截 与 注入的 istio-proxy 容器存在冲突,即当 istio-proxy 存在时,流量全部被 istio-proxy 接管了,traffic-agent 没有成功拦截到流量。

目前我暂时的一个 hack 方法是取消 istio-proxy sidecar 注入:

diff--gita/develop/overlays/my_app/deployment.yamlb/develop/overlays/my_app/deployment.yaml
index1049d335..26ee38d4100644
---a/develop/overlays/my_app/deployment.yaml
+++b/develop/overlays/my_app/deployment.yaml
@@-4,6+4,9@@metadata:
name:ttys3
spec:
template:
+metadata:
+annotations:
+sidecar.istio.io/inject:"false"
spec:
containers:
-name:my-app

traffic-agent 日志查看:stern --tail 100 ttys3-my-app -c traffic-agent

#公众号:进击云原生 注释:
stern是⎈Kubernetes的多 Pod 和容器日志跟踪命令行工具

如果是采用 argo cd rollout:

diff--gita/develop/overlays/my-app/rollout.yamlb/develop/overlays/my-app/rollout.yaml
index263eab87c..bbc44c378100644
---a/develop/overlays/my-app/rollout.yaml
+++b/develop/overlays/my-app/rollout.yaml
@@-6,6+6,9@@metadata:

spec:
template:
+metadata:
+annotations:
+sidecar.istio.io/inject:"false"
spec:
securityContext:
runAsUser:1000

2. 连接不上

使用新版本的 telepresence v2.x.x 如果“重复” 出现 (偶尔一次可能是意外)以下错误:

⁣telepresence: error: the port-forward connection to the traffic manager timed out. The current timeout 20s can be configured as timeouts.trafficManagerConnect

⁣ ⁣ 或 ⁣

⁣telepresence: error: the traffic manager gRPC API timed out. The current timeout 20s can be configured as timeouts.trafficManagerAPI in /Users/tomeee/Library/Application Support/telepresence/config.yml ⁣

⁣ 类似错误, ⁣ 说明同一集群里有多个人使用不同版本 v2 的客户端互相在打架。当 telepresence 连接的时候, 如果与当前版本匹配的 traffic manager 不存在, 则会自动安装与当前版本匹配的 traffic manager. 当不同的人, 从不同的地方, 下载了不同的版本, 都在连接同一个集群的时候, 问题就发生了.

解决方案:同一集群所有人统一使用相同版本的客户端 (版本号要完全相同,对于 nightly 版, 小版本号和 commit hash 都要相同) sys op 对整个集群的 rbac 做更加安全地配置, 禁止除 devops 组之外的其它开发人员拥有可以 ambassador 命名空间下资源的更新权限, 这样就可以阻止开发人员在使用 telepresence 连接的时候无意中错误地在不停地安装各种版本的 traffic manager. 但是为了保证开发人员可以正常使用, list resource “namespaces“权限一定要给, 然后就是 create resource “pods/portforward” in API group "” in the namespace “ambassador” 的权限. ⁣ Client / Root Daemon / User Daemon 3 个版本号一定要完全一致:

❯telepresenceversion
Client:v2.5.4(apiv3)
RootDaemon:v2.5.4(apiv3)
UserDaemon:v2.5.4(apiv3)

参考官方 issue:

https://github.com/telepresenceio/telepresence/issues/1652 > https://github.com/telepresenceio/telepresence/issues/1689

3. 如何彻底卸载

一般情况下可以直接 telepresence uninstall --everything 搞定.

如果需要手动卸载可以这样操作:

kdeletedeploy-nambassadortraffic-manager
kdeletesecretssh.helm.release.v1.traffic-manager.v1-nambassador

注意它并不会真正检查 pod 是否存在, 如果检查到 sh.helm.release.v1.traffic-manager.v1 这个 secrets 就会直接跳过安装了. 所以你要是删除了 traffic manger 的 deployment, 但是忘记删除了这个 secrets, 会导致下次连接的时候, traffic manger 不会被安装.

4. 调试问题

k8s 端问题查看:

先检查 pod 是不是正常:

k get po -n ambassador

k get deploy -n ambassador

查看 pod 日志:

k logs -n ambassador -f traffic-manager

5. 编译和构建容器镜像

traffic manager 的版本一定要匹配客户端的版本.

对于 nightly 版本, 其形式如 v2.5.4-2-g8ccf3c9d

对于正式版, 其形式如 v2.5.3

不同版本不能连接, 会提示错误. 即使是客户端, 不同版本的 daemon 也是不兼容的, 如:

version mismatch. Client v2.5.3 != User Daemon v2.5.4-2-g8ccf3c9d, please run ’telepresence quit -u’ and reconnect

计算当前 nightly 版本号: git describe --tags --match='v*'

build 的时候,必须通过 env 指定 TELEPRESENCE_VERSION, 不然 Makefile 会自动运行 go run build/genversion.go 生成一个带 unix timestamp 的版本号,这样客户端和 agent docker image 的版本号便没办法对应上了。

同时还要指定 TELEPRESENCE_REGISTRY , 这个主要是在构建时打 docker tag 用的,主要用于 docker push, 真正程序运行的时候,取的还是 env:"TELEPRESENCE_REGISTRY,default=docker.io/datawire" 因此,如果要防止客户端安装官方镜像, 这一行硬编码的代码必须修改.

#构建本地bin和容器镜像并push:
makebuildimagepush-imageTELEPRESENCE_VERSION=v2.5.4TELEPRESENCE_REGISTRY=docker.io/ttys3

#只构建本地bin
makebuildTELEPRESENCE_VERSION=v2.5.4TELEPRESENCE_REGISTRY=docker.io/ttys3

6. 突然无法访问的 Rust 文档站点 docs.rs

连接 telepresence 后, 发现 https://docs.rs/ 怎么也打不开了. dig docs.rs 发现超时, 并没有解析成功.

然后我想到了原因, 有人在集群里创建了一个名为 rs 的命名空间, 连接 telepresence 后, 导致所有 .rs 域名都无法解析了(除了 k8s 集群里面的 ).

经过查看源码, 老灯发现可以通过 patch updateLinkDomains 这个方法搞定. 思路就是, 如果一个命名空间, 是 ICANN 管理的通用 TLD 后缀, 则直接 skip 它, 不设置.

直接修改 telepresence 源码然后自己编译客户端即可:

diff--gita/pkg/client/rootd/dns/resolved_linux.gob/pkg/client/rootd/dns/resolved_linux.go
indexb2e8897bbeb5405170359f5318a7ae40dfc6e949..d90c2735ef9d4d421738fea533f7bfb244172b61100644
---a/pkg/client/rootd/dns/resolved_linux.go
+++b/pkg/client/rootd/dns/resolved_linux.go
@@-13,6+13,7@@import(
"github.com/datawire/dlib/dtime"
"github.com/telepresenceio/telepresence/v2/pkg/client/rootd/dbus"
"github.com/telepresenceio/telepresence/v2/pkg/vif"
+"golang.org/x/net/publicsuffix"
)

func(s*Server)tryResolveD(ccontext.Context,dev*vif.Device,configureDNSfunc(net.IP,*net.UDPAddr))error{
@@-102,28+103,36@@func(s*Server)tryResolveD(ccontext.Context,dev*vif.Device,configureDNSfu
func(s*Server)updateLinkDomains(ccontext.Context,paths[]string,dev*vif.Device)error{
namespaces:=make(map[string]struct{})
search:=make([]string,0)
-fori,path:=rangepaths{
+pathsFiltered:=make([]string,0)
+for_,path:=rangepaths{
ifstrings.ContainsRune(path,'.'){
search=append(search,path)
}else{
+//skipnamespacewhichconflictwitheTLDlike`im`,`rs`toavoidpolluteclientnormalDNSquery
+ifeTLD,icann:=publicsuffix.PublicSuffix(path);icann&&path==eTLD{
+dlog.Infof(c,"SkipsetLinkdomainsondevice%qfor[%s]duetoconflictwithICANNeTLD[%s]",
+dev.Name(),path,eTLD)
+continue
+}
namespaces[path]=struct{}{}
//Turnnamespaceintoaroute
-paths[i]="~"+path
+//paths[i]="~"+path
+pathsFiltered=append(pathsFiltered,"~"+path)
}
}
for_,sfx:=ranges.config.IncludeSuffixes{
-paths=append(paths,"~"+strings.TrimPrefix(sfx,"."))
+pathsFiltered=append(pathsFiltered,"~"+strings.TrimPrefix(sfx,"."))
}
-paths=append(paths,"~"+s.clusterDomain)
+pathsFiltered=append(pathsFiltered,"~"+s.clusterDomain)
namespaces[tel2SubDomain]=struct{}{}

s.domainsLock.Lock()
s.namespaces=namespaces
s.search=search
s.domainsLock.Unlock()
-iferr:=dbus.SetLinkDomains(dcontext.HardContext(c),int(dev.Index()),paths...);err!=nil{
+iferr:=dbus.SetLinkDomains(dcontext.HardContext(c),int(dev.Index()),pathsFiltered...);err!=nil{
returnfmt.Errorf("failedtosetlinkdomainson%q:%w",dev.Name(),err)
}
-dlog.Debugf(c,"Linkdomainsondevice%qsetto[%s]",dev.Name(),strings.Join(paths,","))
+dlog.Debugf(c,"Linkdomainsondevice%qsetto[%s]",dev.Name(),strings.Join(pathsFiltered,","))
returnnil
}

注意: telepresence 的 exclude-suffixes 选项并不能解决我们这里的问题.

https://www.telepresence.io/docs/latest/reference/config/#dns

其默认值为 [".arpa", ".com", ".io", ".net", ".org", ".ru"]

exclude-suffixes Suffixes for which the DNS resolver will always fail (or fallback in case of the overriding resolver)

由于我们用的都是基于 systemd-resolved 的 resover, 因此, 如果把 `.rs` 加入这个列表, 则会导致 `.rs` 域名总是解析失败(NXDomain)

所以其实这个默认列表也是有问题的, 为什么默认有 `.com`, 而 `google.com` 不会解析失败呢? 那是因为我们没有名为 `com` 的命名空间. 所以, 假设你有名为 `com` 的命名空间, 就要小心了.

7. DNS 解析特别慢或超时

我们同时在开发和测试环境部署了 telepresence (traffic manager).

使用中发现, 测试环境丝滑无比, 开发环境总是 DNS 解析超时.

通过查看 log 可发现类似日志:

LookupHost: lookup kubernetes.default on 10.0.165.145 dial udp 10.0.165.145 i/o timeout

暂时没排查出什么原因, 大概率是 coredns 出问题了.

干了 coredns pod 之后, 等 coredns pod 重新 ruuning 了, 再把 traffic manager 的 pod 干了,

重新测试, 发现正常了.

8. 某些网段或 IP 的流量不想走 tel0 tun 出去

这个也是通过 k8s 扩展配置实现的, 之所以放在这里, 我想 telepresence 是考虑到对于不同人集群, 可以方便支持不同的配置.

修改 ~/.kube/config 文件, 增加配置到 never-proxy 数组即可, 如要将 10.10.8.9 单个 IP 排除:

-cluster:
certificate-authority-data:xxxxxx
server:https://example.com
extensions:
-name:telepresence.io
extension:
never-proxy:
-10.10.8.9/32
name:cluster-001

k8s 集群 api server 的 IP telepresence 是会默认排除的(通过 telepresence status 你可以看到这一点), 除此之外 , 如果你有些外部服务, 因为网段跟 k8s cluster IP 段重合, 导致流量错误地走了 tel0 tun 设备, 就可以通过这个配置来修正.

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    481

    浏览量

    21883
  • 调试服务
    +关注

    关注

    0

    文章

    2

    浏览量

    6131
  • kubernetes
    +关注

    关注

    0

    文章

    219

    浏览量

    8568

原文标题:K8S 运维开发调试神器 Telepresence 实践及踩坑记

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    阿里云上Kubernetes集群联邦

    摘要: kubernetes集群让您能够方便的部署管理运维容器化的应用。但是实际情况中经常遇到的一些问题,就是单个集群通常无法跨单个云厂商的多个Region,更不用说支持跨跨域不同的云厂商。这样会给
    发表于 03-12 17:10

    Kubernetes Ingress 高可靠部署最佳实践

    摘要: 在Kubernetes集群中,Ingress作为集群流量接入层,Ingress的高可靠性显得尤为重要,今天我们主要探讨如何部署一套高性能高可靠的Ingress接入层。简介
    发表于 04-17 14:35

    kubernetes集群配置

    基于v1104版本手动搭建高可用kubernetes 集群
    发表于 08-19 08:07

    Kubernetes 从懵圈到熟练:集群服务的三个要点和一种实现

    ,也有我们自己加入的自定义链。默认链是数据的入口,默认链可以通过跳转到自定义链来完成一些复杂的功能。这里允许增加自定义链的好处是显然的。为了完成一个复杂过滤功能,比如实现 Kubernetes
    发表于 09-24 15:35

    kubernetes v112二进制方式集群部署

    kubernetes v112 二进制方式集群部署
    发表于 05-05 16:30

    请问鸿蒙系统上可以部署kubernetes集群吗?

    鸿蒙系统上可以部署kubernetes集群
    发表于 06-08 11:16

    如何部署基于Mesos的Kubernetes集群

    kubernetes是一个跨多个计算节点的管理容器化应用的系统,它提供了一系列基本的功能,如应用的自动化部署,维护和扩展等。Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统
    发表于 10-09 18:04 0次下载
    如何部署基于Mesos的<b class='flag-5'>Kubernetes</b><b class='flag-5'>集群</b>

    浅谈Kubernetes集群的高可用方案

    Kubernetes作为容器应用的管理中心,通过对Pod的数量进行监控,并且根据主机或容器失效的状态将新的Pod调度到其他Node上,实现了应用层的高可用性。针对Kubernetes集群,高可用性
    发表于 10-11 10:04 1次下载
    浅谈<b class='flag-5'>Kubernetes</b><b class='flag-5'>集群</b>的高可用方案

    Kubernetes API详解

    摘要:Kubernetes是Google开源的容器集群管理系统。它构建Ddocker技术之上,为容器化的应用提供资源调度、部署运行、服务发现、扩容缩容等整一套功能,本文节选自
    发表于 10-12 16:19 0次下载
    <b class='flag-5'>Kubernetes</b> API详解

    Kubernetes集群发生网络异常时如何排查

    本文将引入一个思路:“在 Kubernetes 集群发生网络异常时如何排查”。文章将引入 Kubernetes 集群中网络排查的思路,包含网络异常模型,常用工具,并且提出一些案例以供学
    的头像 发表于 09-02 09:45 3121次阅读

    Kubernetes集群内服务通信机制介绍

    现在在 Kubernetes 集群中,我们拥有构成集群管理组件和一组工作机器(称为节点)的控制平面。这些节点托管 Pod,这些 Pod 将后端微服务作为容器化服务运行。
    发表于 10-04 10:13 395次阅读

    Kubernetes集群的关闭与重启

    在日常对 Kubernetes 集群运行维护的过程中,您可能需要临时的关闭或者是重启 Kubernetes 集群集群进行维护,本文将介绍如
    的头像 发表于 11-07 09:50 8742次阅读

    在树莓派上搭建Kubernetes智能边缘集群

    电子发烧友网站提供《在树莓派上搭建Kubernetes智能边缘集群.zip》资料免费下载
    发表于 12-09 09:20 2次下载
    在树莓派上搭建<b class='flag-5'>Kubernetes</b>智能边缘<b class='flag-5'>集群</b>

    Kubernetes集群部署

    Kubeadm是一种Kubernetes集群部署工具,通过kubeadm init命令创建master节点,通过 kubeadm join命令把node节点加入到集群
    的头像 发表于 02-15 10:35 977次阅读

    Kubernetes集群中如何选择工作节点

    简要概述: 本文讨论了在Kubernetes集群中选择较少数量的较大节点和选择较多数量的较小节点之间的利弊。
    的头像 发表于 08-28 15:46 349次阅读
    <b class='flag-5'>Kubernetes</b><b class='flag-5'>集群</b>中如何选择工作节点