聊聊如何让办公网络直连Kubernetes集群PodIP/ClusterIP/Service DNS等
想象一下,如果您日常使用的研发测试Kubernetes集群,能够有以下效果:
- 在办公网络下直接访问Pod IP
 - 在办公网络下直接访问Service Cluster IP
 - 在办公网络下直接访问集群内部域名,类似 service.namespace.svc.cluster.local
 
会不会很方便,很优雅?
笔者近期就给内部的一个新集群做过类似的调整,特此分享一些心得。
PS: 这里的 直接访问/直连 指的是不借助Ingress/hostnetwork:true/NodePort等常规方式,直接访问k8s内部IP or DNS,起到 网络拉平 的效果。
先决条件 - 三层路由方案
办公网段跟Kubernetes集群大概率是不同的网段,所以要想打通最自然的想法是依赖路由。相应的,Kubernetes 跨主机网络方案,我们最好也选择三层路由方案或者Host-GW,而非Overlay,不然数据包在封包解包过程中可能会失去路由方向。
我们的集群选用的是Calico,且关闭了 IPIP 模式。具体的IPPool配置如下:
-> calicoctl get IPPool -o yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    name: default-pool
  spec:
    blockSize: 24
    cidr: 10.233.64.0/18
    # 关闭IPIP模式
    ipipMode: Never
    natOutgoing: true
    nodeSelector: all()
    vxlanMode: Never
kind: IPPoolList
Calico RR(Route Reflectors)or Full-Mesh 模式?
网上的很多类似教程,上来都会引导大家先把集群改为RR模式,其实这不是必须的。大家可以思考下,RR模式解决的问题是什么?是为了防止所有节点间都做BGP连接交换,浪费资源。但如果你的集群很小, 且已经是按Full Mesh模式部署了,到也没必要非得改为RR模式。Full Mesh下所有的节点都是类似RR节点的效果,所以如果我们想选择作为 BGPPeer交换的节点,选择任意节点就行。 比如,笔者的集群就选择了Ingress所在的节点,作为BGPPeer。
~ calicoctl get BGPPeer -o yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: BGPPeer
  metadata:
    name: peer-switch
  spec:
  	# 交换机配置
    asNumber: 65200
    peerIP: 10.200.20.254
    # 这个label是Ingress节点特有的
    nodeSelector: node-role.kubernetes.io/ingress == 'ingress'
kind: BGPPeerList
从集群外部访问Pod IP vs 从集群内部访问?
这个问题很关键,如果我们想从外部直接访问到集群内部的Pod IP,那么首先需要搞清楚集群内的节点是如何畅通访问的。
以下面的节点为例,我们来看它的路由信息:
~ ip r
# 默认路由
default via 10.200.20.21 dev bond0 onlink
# 宿主机数据包路由
10.200.20.0/24 dev bond0 proto kernel scope link src 10.200.20.105
# 黑洞,防止成环
blackhole 10.233.98.0/24 proto bird
# 目的地址是10.233.98.3的数据包,走cali9832424c93e网卡
10.233.98.3 dev cali9832424c93e scope link
# 目的地址是10.233.98.4的数据包,走cali4f5c6d27f17网卡
10.233.98.4 dev cali4f5c6d27f17 scope link
# 目的地址是10.233.98.8的数据包,走cali8f10abc672f网卡
10.233.98.8 dev cali8f10abc672f scope link
# 目的地址是10.233.110.0/24网段的数据包,从bond0网卡出到下一跳10.200.20.107上
10.233.110.0/24 via 10.200.20.107 dev bond0 proto bird
# 目的地址是10.233.112.0/24网段的数据包,从bond0网卡出到下一跳10.200.20.106上
10.233.112.0/24 via 10.200.20.106 dev bond0 proto bird
# 目的地址是10.233.115.0/24网段的数据包,从bond0网卡出到下一跳10.200.20.108上
10.233.115.0/24 via 10.200.20.108 dev bond0 proto bird
相信看了笔者的注释,大家应该很容易了解到以下信息:
- 这台宿主机IP是10.200.20.105,集群内其他的宿主机还有10.200.20.106, 10.200.20.107, 10.200.20.108等
 - 主机10.200.20.105上的Pod IP段是10.233.98.0/24, 10.200.20.106上是10.233.112.0/24,10.200.20.107上是10.233.110.0/24
 - 目的地址是10.233.98.3的数据包走cali9832424c93e网卡,目的地址10.233.98.4的数据包走cali4f5c6d27f17网卡等
 
而这些信息实际解答了,容器数据包的 出和入 这个关键问题:
- 比如想访问Pod IP为10.233.110.7的容器,宿主机自然知道下一跳是10.200.20.107上
 - 比如接收到了目的地址是10.233.98.8的数据包,宿主机自然也知道要把这个包交给cali8f10abc672f网卡。而这个网卡是veth pair设备的一端,另一端必然在目标Pod里
 
那这些路由信息是哪里来的呢?自然是Calico借助BGP的能力实现的。我们进一步想,如果外部节点也有这些信息,是不是也就自然知道了Pod IP在哪里了? 答案确实如此,其实总结基于Calico的网络打平方案,核心原理就是 通过BGP能力,将集群路由信息广播给外部。
而在具体的配置上,就比较简单了,只需要在两端配置好BGP Peer即可。
先是集群这一侧,前面笔者已给出:
~ calicoctl get BGPPeer -o yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: peer-switch
spec:
# 交换机配置
asNumber: 65200
peerIP: 10.200.20.254
# 这个label就是Ingress节点特有的
nodeSelector: node-role.kubernetes.io/ingress == 'ingress'
kind: BGPPeerList
再就是外部,一般是交换机,使用类似下面的命令:
[SwitchC] bgp 64513 # 这是k8s集群的ASN
[SwitchC-bgp] peer 10.200.20.107 as-number 64513
[SwitchC-bgp] peer 10.200.20.108 as-number 64513
PS: 具体的交换机操作方式可以参考各品牌交换机官方文档
到这里,基本上我们已经打通了外部直接访问Pod IP的能力。当然,如果您的办公网络到交换机这一侧还有多个网关,您还需要在这些网关上设置合适的路由才行。
为什么 Service Cluster IP 还不能访问?
也许这时候您会发现,可以直连Pod IP,但 Cluster IP不可以,这是为什么呢?原来,默认情况Calico并没有广播Service IP,您可以在交换机这一侧通过查看交换过来的IP段来确认这一点。
PS: 您是否注意到,k8s主机节点上也没有service的ip路由,但为啥在集群内部访问service没有问题呢?
解决方案也简单,只要打开相关的设置即可, 类似如下:
~ calicoctl get bgpconfig default -o yaml
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  asNumber: 64513
  listenPort: 179
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: true
  # 这就是需要广播的service cluster IP 段
  serviceClusterIPs:
  - cidr: 10.233.0.0/18
打通内网DNS,直接访问Service域名
直连IP虽然方便,但有时若想记住某服务的具体IP却不是那么容易。所以,我们将K8s内部的DNS域名也暴漏出来了,类似下面:
<service>.<namespaces>.svc.cluster.local
而这块的设置也相对简单,一般企业都有内网DNS,只需要添加相应解析到K8s内部DNS Server即可。
总结
其实若想打造一个好用的研发测试集群,有很多的细节需要处理,笔者后续也会继续分享类似的经验,希望对大家有用。
参考链接
- https://projectcalico.docs.tigera.io/networking/bgp
 - https://projectcalico.docs.tigera.io/networking/advertise-service-ips
 
聊聊如何让办公网络直连Kubernetes集群PodIP/ClusterIP/Service DNS等的更多相关文章
- 在Kubernetes集群中使用calico做网络驱动的配置方法
		
参考calico官网:http://docs.projectcalico.org/v2.0/getting-started/kubernetes/installation/hosted/kubeadm ...
 - Kubernetes集群中Service的滚动更新
		
Kubernetes集群中Service的滚动更新 二月 9, 2017 0 条评论 在移动互联网时代,消费者的消费行为已经“全天候化”,为此,商家的业务系统也要保持7×24小时不间断地提供服务以满足 ...
 - Kubernetes(K8s) 安装(使用kubeadm安装Kubernetes集群)
		
背景: 由于工作发生了一些变动,很长时间没有写博客了. 概述: 这篇文章是为了介绍使用kubeadm安装Kubernetes集群(可以用于生产级别).使用了Centos 7系统. 一.Centos7 ...
 - vivo 公司 Kubernetes 集群 Ingress 网关实践
		
文章转载自:https://mp.weixin.qq.com/s/qPqrJ3un1peeWgG9xO2m-Q 背景 vivo 人工智能计算平台小组从 2018 年底开始建设 AI 计算平台至今,已经 ...
 - 三十二、kubernetes集群的网络实现
		
Kubernetes集群的网络实现 CNI介绍及集群网络选型 容器网络接口(Container Network Interface),实现kubernetes集群的Pod网络通信及管理.包括: CNI ...
 - 高可用Kubernetes集群-5. 部署flannel网络
		
七.部署flannel网络 kubernetes支持基于vxlan方式的flannel与weave网络,基于BGP路由的Calico网络,本节采用flannel网络. Flannel网络采用etcd等 ...
 - k8s教程:Kubernetes集群使用网络存储NFS
		
NFS存储 NFS即网络文件系统Network File System,它是一种分布式文件系统协议,最初是由Sun MicroSystems公司开发的类Unix操作系统之上的一款经典网络存储方案,其功 ...
 - Kubernetes集群的部署方式及详细步骤
		
一.部署环境架构以及方式 第一种部署方式 1.针对于master节点 将API Server.etcd.controller-manager.scheduler各组件进行yum install.编译安 ...
 - 使用 Kubeadm+Containerd 部署一个 Kubernetes 集群
		
本文独立博客阅读地址:https://ryan4yin.space/posts/kubernetes-deployemnt-using-kubeadm/ 本文由个人笔记 ryan4yin/knowle ...
 - Docker 与 K8S学习笔记(二十三)—— Kubernetes集群搭建
		
小伙伴们,好久不见,这几个月实在太忙,所以一直没有更新,今天刚好有空,咱们继续k8s的学习,由于我们后面需要深入学习Pod的调度,所以我们原先使用MiniKube搭建的实验环境就不能满足我们的需求了, ...
 
随机推荐
- 安装docker及使用docker安装其他软件(手动挂载数据卷)
			
中秋明月,豪门有,贫家也有,极慰人心 Linux安装docker 可以参考官方的安装文档 centos安装docker: https://docs.docker.com/engine/install/ ...
 - Java SE final关键字
			
final关键字 final可以修饰类.属性.方法和局部变量 如下情况,可以使用final 当不希望类被继承时,可以用final修饰 当不希望父类的某个方法被子类覆盖/重写(override)时,可以 ...
 - 微信小程序-坑,wxml里wx:if 判断 数字 是否在一个数组中。
			
<view wx:if="{{item.index}} in {{vote_list}}"> 已赞 <image src="/static/zan_y. ...
 - SpringSecurity基本使用
			
SpringSecurity web 安全管理框架 需要依赖多 shiro 轻量 SSM+Shiro SpringBoot/SpringCloud+SpringSecurity 配置用户名密码 配置文 ...
 - harbor高可用部署
			
文章转载自:https://blog.csdn.net/networken/article/details/119704025 harbor高可用简介 harbor目前有两种主流的高可用方案: 多ha ...
 - 从 Yum 更新中排除特定/某些包的三种方法
			
方法 1:手动或临时用 yum 命令排除包 要排除单个包: # yum update --exclude=kernel 或者 # yum update -x 'kernel' 要排除多个包.以下命令将 ...
 - 对vue中的data进行数据初始化
			
this.$data:是表示当前的改变后的this中的数据 this.$options.data():是表示没有赋值前的this中的数据,表示 初始化的data 一般可以使用Object.assign ...
 - 为什么 MES 管理系统是智能制造的核心?
			
不能说MES 管理系统是智能制造的核心,只能说MES管理系统是智能制造的核心的一部分,并且是一小部分.智能制造的核心的为高端制造装备和工业互联网平台,引用工信部赛迪研究院软件所所长潘文的话" ...
 - spring cron表达式源码分析
			
spring cron表达式源码分析 在springboot中,我们一般是通过如下的做法添加一个定时任务 上面的new CronTrigger("0 * * * * *")中的参数 ...
 - 从 Paxos 到 ZooKeeper
			
分布式一致性 分布式文件系统.缓存系统和数据库等大型分布式存储系统中,分布式一致性都是一个重要的问题. 什么是分布式一致性?分布式一致性分为哪些类型?分布式系统达到一致性后将会是一个什么样的状态? 如 ...