K8s中的网络
Kubernetes的网络通信问题:
1. 容器间通信: 即同一个Pod内多个容器间通信,通常使用loopback来实现。
2. Pod间通信: K8s要求,Pod和Pod之间通信必须使用Pod-IP 直接访问另一个Pod-IP
3. Pod与Service通信: 即PodIP去访问ClusterIP,当然,clusterIP实际上是IPVS 或 iptables规则的虚拟IP,是没有TCP/IP协议栈支持的。但不影响Pod访问它.
4. Service与集群外部Client的通信,即K8s中Pod提供的服务必须能被互联网上的用户所访问到。
补充:
IPVS 能替代 iptables吗?
不能,因为ipvs并不能完全支持所有场景,这个我目前理解不深。不做详述
CNI(容器网络接口):
这是K8s中提供的一种通用网络标准规范,因为k8s本身不提供网络解决方案。
目前比较知名的网络解决方案有:
flannel
calico
canel
kube-router
.......
所有的网络解决方案,它们的共通性:
1. 虚拟网桥
2. 多路复用:MacVLAN
3. 硬件交换:SR-IOV(单根-I/O虚拟网络):它是一种物理网卡的硬件虚拟化技术,它通过输出VF(虚拟功能)来将网卡虚拟为多个虚拟子接口,每个VF绑定给一个VM后,该VM就可以直接操纵该物理网卡。
kubelet来调CNI插件时,会到 /etc/cni/net.d/目录下去找插件的配置文件,并读取它,来加载该插件,并让该网络插件来为Pod提供网络服务。
flannel网络插件要怎么部署?
1. flannel部署到那个节点上?
因为kubelet是用来管理Pod的,而Pod运行需要网络,因此凡是部署kubelet的节点,都需要部署flannel来提供网络,因为kubelet正是通过调用flannel来实现为Pod配置网络的(如:添加网络,配置网络,激活网络等)。
2. flannel自身要如何部署?
1》它支持直接运行为宿主机上的一个守护进程。
2》它也支持运行为一个Pod
对于运行为一个Pod这种方式:就必须将flannel配置为共享当前宿主机的网络名称空间的Pod,若flannel作为控制器控制的Pod来运行的话,它的控制器必须是DaemonSet,在每一个节点上都控制它仅能运行一个Pod副本,而且该副本必须直接共享宿主机的网络名称空间,因为只有这样,此Pod才能设置宿主机的网络名称空间,因为flannel要在当前宿主机的网络名称空间中创建CNI虚拟接口,还要将其他Pod的另一半veth桥接到虚拟网桥上,若不共享宿主机的网络名称空间,这是没法做到的。
3. flannel的工作方式有3种:
1) VxLAN:
而VxLAN有两种工作方式:
a. VxLAN: 这是原生的VxLAN,即直接封装VxLAN首部,UDP首部,IP,MAC首部这种的。
b. DirectRouting: 这种是混合自适应的方式, 即它会自动判断,若当前是相同二层网络
(即:不垮路由器,二层广播可直达),则直接使用Host-GW方式工作,若发现目标是需要跨网段
(即:跨路由器)则自动转变为使用VxLAN的方式。
2) host-GW: 这种方式是宿主机内Pod通过虚拟网桥互联,然后将宿主机的物理网卡作为网关,当需要访问其它Node上的Pod时,只需要将报文发给宿主机的物理网卡,由宿主机通过查询本地路由表,来做路由转发,实现跨主机的Pod通信,这种模式带来的问题时,当k8s集群非常大时,会导致宿主机上的路由表变得非常巨大,而且这种方式,要求所有Node必须在同一个二层网络中,否则将无法转发路由,这也很容易理解,因为如果Node之间是跨路由的,那中间的路由器就必须知道Pod网络的存在,它才能实现路由转发,但实际上,宿主机是无法将Pod网络通告给中间的路由器,因此它也就无法转发理由。
3) UDP: 这种方式性能最差的方式,这源于早期flannel刚出现时,Linux内核还不支持VxLAN,即没有VxLAN核心模块,因此flannel采用了这种方式,来实现隧道封装,其效率可想而知,因此也给很多人一种印象,flannel的性能很差,其实说的是这种工作模式,若flannel工作在host-GW模式下,其效率是非常高的,因为几乎没有网络开销。
4. flannel的网络配置参数:
1) Network: flannel使用的CIDR格式的网络地址,主要用于为Pod配置网络功能。
如: 10.10.0.0/16 --->
master: 10.10.0.0/24
node01: 10.10.1.0/24
.....
node255: 10.10.255.0/24
2) SubnetLen: 把Network切分为子网供各节点使用时,使用多长的掩码来切分子网,默认是24位.
3) SubnetMin: 若需要预留一部分IP时,可设置最小从那里开始分配IP,如:10.10.0.10/24 ,这样就预留出了10个IP
4) SubnetMax: 这是控制最多分配多个IP,如: 10.10.0.100/24 这样在给Pod分配IP时,最大分配到10.10.0.100了。
5) Backend: 指定后端使用的协议类型,就是上面提到的:vxlan( 原始vxlan,directrouter),host-gw, udp
flannel的配置:
.....
net-conf.json: |
{
"Network": "10.10.0.0/16",
"Backend": {
"Type": "vxlan", #当然,若你很确定自己的集群以后也不可能跨网段,你完全可以直接设置为 host-gw.
"Directrouting": true #默认是false,修改为true就是可以让VxLAN自适应是使用VxLAN还是使用host-gw了。
}
}
#在配置flannel时,一定要注意,不要在半道上,去修改,也就是说要在你部署k8s集群后,就直接规划好,而不要在k8s集群已经运行起来了,你再去修改,虽然可能也不会出问题,但一旦出问题,你就!!
#在配置好,flannel后,一定要测试,创建新Pod,看看新Pod是否能从flannel哪里获得IP地址,是否能通信。
Calico:
Calico是一种非常复杂的网络组件,它需要自己的etcd数据库集群来存储自己通过BGP协议获取的路由等各种所需要持久保存的网络数据信息,因此在部署Calico时,早期是需要单独为Calico部署etcd集群的,因为在k8s中,访问etcd集群只有APIServer可以对etcd进行读写,其它所有组件都必须通过APIServer作为入口,将请求发给APIServer,由APIServer来从etcd获取必要信息来返回给请求者,但Caclico需要自己写,因此就有两种部署Calico网络插件的方式,一种是部署两套etcd,另一种就是Calico不直接写,而是通过APIServer做为代理,来存储自己需要存储的数据。通常第二种使用的较多,这样可降低系统复杂度。
当然由于Calico本身很复杂,但由于很多k8s系统可能存在的问题是,早期由于各种原因使用了flannel来作为网络插件,但后期发现需要使用网络策略的需求,怎么办?
目前比较成熟的解决方案是:flannel + Calico, 即使用flannel来提供简单的网络管理功能,而使用Calico提供的网络策略功能。
Calico网络策略:
Egress:是出站的流量,即自己是源,远端为服务端,因此我自己的源IP可确定,但端口不可预知, 目标的端口和IP都是确定的,因此to 和 ports都是指目标的IP和端口。
Ingress:是入站的流量,即自己为目标,而远端是客户端,因此要做控制,就只能对自己的端口 和 客户端的地址 做控制。
我们通过Ingress 和 Egress定义的网络策略是对一个Pod生效 还是 对一组Pod生效?
这个就要通过podSelector来实现了。
而且在定义网络策略时,可以很灵活,如:入站都拒绝,仅允许出站的; 或 仅允许指定入站的,出站都允许等等。
另外,在定义网络策略时,也可定义 在同一名称空间中的Pod都可以自由通信,但跨名称空间就都拒绝。
网络策略的生效顺序:
越具体的规则越靠前,越靠前,越优先匹配
网络策略的定义:
kubectl explain networkpolicy
spec:
egress: <[]Object> :定义出站规则
ingress: <[]Object>: 定义入站规则
podSelector: 如论是入站还是出站,这些规则要应用到那些Pod上。
policyType:[Ingress|Egress| Ingress,Egress] :
它用于定义若同时定义了egress和ingress,到底那个生效?若仅给了ingress,则仅ingress生效,若设置为Ingress,Egress则两个都生效。
注意:policyType在使用时,若不指定,则当前你定义了egress就egress生效,若egress,ingress都定义了,则两个都生效!!
还有,若你定义了egress, 但policyType: ingress, egress ; egress定义了,但ingress没有定义,这种要会怎样?
其实,这时ingress的默认规则会生效,即:若ingress的默认规则为拒绝,则会拒绝所有入站请求,若为允许,则会允许所有入站请求,
所以,若你只想定义egress规则,就明确写egress !!
egress:<[]Object>
ports: <[]Object> :因为ports是有端口号 和 协议类型的,因此它也是对象列表
port :
protocol: 这两个就是用来定义目标端口和协议的。
to :<[]Object>
podSelector: <Object> : 在控制Pod通信时,可控制源和目标都是一组Pod,然后控制这两组Pod之间的访问。
ipBlock:<[]Object> : 指定一个Ip地址块,只要在这个IP范围内的,都受到策略的控制,而不区分是Pod还是Service。
namespaceSelector: 这是控制对指定名称空间内的全部Pod 或 部分Pod做访问控制。
Ingress:
from: 这个from指访问者访问的IP
ports: 也是访问者访问的Port
#定义网络策略:
vim networkpolicy-demo.yaml
apiVersion: networking.k8s.io/v1
#注意:虽然kubectl explain networkpolicy中显示为 extensions/v1beta1 ,但你要注意看说明部分.
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: dev
spec:
podSelector: {} #这里写空的含义是,选择指定名称空间中所有Pod
policyTypes:
- Ingress #这里指定要控制Ingress(进来的流量),但又没有指定规则,就表示全部拒绝,只有明确定义的,才是允许的。
#egress: 出去的流量不控制,其默认规则就是允许,因为不关心,所以爱咋咋地的意思。 #写一个简单的自主式Pod的定义:
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: myapp
image: harbor.zcf.com/k8s/myapp:v1 #创建dev名称空间,并应用规则
kubectl apply -f networkpolicy-demo.yaml -n dev # kubectl describe -n dev networkpolicies
Name: deny-all-ingress
Namespace: dev
........................
Spec:
PodSelector: <none> (Allowing the specific traffic to all pods in this namespace)
Allowing ingress traffic:
<none> (Selected pods are isolated for ingress connectivity)
Allowing egress traffic:
<none> (Selected pods are isolated for egress connectivity) #查看dev名称空间中的网络规则:
kubectl get networkpolicy -n dev
或
kubectl get netpol -n dev #然后在dev 和 prod 两个名称空间中分别创建pod
kubectl apply -f pod1.yaml -n dev
kubectl apply -f pod1.yaml -n prod #接着测试访问这两个名称空间中的pod
kubectl get pod -n dev -o wide #测试访问:
curl http://POD_IP kubectl get pod -n prod -o wide #测试访问:
curl http://POD_IP #通过以上测试,可以看到,dev名称空间中的pod无法被访问,而prod名称空间中的pod则可被访问。
#测试放行所有dev的ingress入站请求。
# vim networkpolicy-demo.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
namespace: dev
spec:
podSelector: {}
ingress:
- {} #这就表示允许所有,因为定义了规则,但规则是空的,即允许所有。
policyTypes:
- Ingress #接着测试,和上面测试一样,也是访问dev 和 prod两个名称空间中的pod,若能访问,则成功。
# kubectl describe -n dev netpol
Name: deny-all-ingress
Namespace: dev
.....................
Spec:
PodSelector: <none> (Allowing the specific traffic to all pods in this namespace)
Allowing ingress traffic:
To Port: <any> (traffic allowed to all ports)
From: <any> (traffic not restricted by source)
Allowing egress traffic:
<none> (Selected pods are isolated for egress connectivity)
Policy Types: Ingress
#测试定义一个仅允许访问dev名称空间中,pod标签 app=myapp 的一组pod的80端口
#先给pod1打上app=myapp的标签
#kubectl label pod pod1 app=myapp -n dev vim allow-dev-.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-myapp-ingress
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- from:
- ipBlock:
cidr: 10.10.0.0/
except:
- 10.10.1.2/
ports:
- protocol: TCP
port:
- protocol: TCP
port: #查看定义的ingress规则
kubectl get netpol -n dev #然后测试访问 dev 名称空间中的pod
curl http://Pod_IP
curl http://Pod_IP:443 curl http://Pod_IP:88
上图测试:
. 先给dev名称空间打上标签
kubectl label namespace dev ns=dev . 编写网络策略配置清单
vim allow-ns-dev.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ns-dev
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: dev
egress:
- to:
- namespaceSelector:
matchLabels:
ns: dev #要控制egress,也是如此,只是将ingress替换为egress即可,然后在做测试。
另外,关于网络策略,建议:
名称空间内:
拒绝所有出站,入站流量
仅放行出站目标为当前名称空间内各Pod间通信,因为网络策略控制的颗粒度是Pod级别的,不是名称空间级别。
具体的网络策略,要根据实际需求,来定义ingress 和 egress规则。
K8s中的网络的更多相关文章
- k8s中的网络(较详细汇总)
目录 一.网络前提条件-网络模型 二.需要解决的网络问题 1.容器和容器之间的网络 2.pod与pod之间的网络 同一台node节点上pod和pod通信 不同node节点上pod和pod通信 3.po ...
- 新版的K8S中的flannel.yaml文件中要注意的细节
部署flannel作为k8s中的网络插件,yaml文件都大小同异. 但在要注意以下细节. 以前,只需要前面master判断. 现在也需要有not-ready状态了. tolerations: - ke ...
- K8S中如何跨namespace 访问服务?为什么ping不通ClusterIP?
1.K8S中如何跨namespace 访问服务? 2.在Pod中为什么ping不通ClusterIP? 简述: Rancher2.0中的一个用户,在K8S环境中,创建两个namespace,对应用进行 ...
- 在k8s中的基本概念
在k8s中的基本概念 一.Pod1. podk8s下最重要也最基本的概念,由一个根容器Pause和许多用户业务容器组成,是容器的载体. 2. pod的yaml定义格式及字段 apiVersion: v ...
- Docker & k8s 系列三:在k8s中部署单个服务实例
本章将会讲解: pod的概念,以及如何向k8s中部署一个单体应用实例. 在上面的篇幅中,我们了解了docker,并制作.运行了docker镜像,然后将镜像发布至中央仓库了.然后又搭建了本机的k8s环境 ...
- 如何在K8S中优雅的使用私有镜像库 (Docker版)
前言 在企业落地 K8S 的过程中,私有镜像库 (专用镜像库) 必不可少,特别是在 Docker Hub 开始对免费用户限流之后, 越发的体现了搭建私有镜像库的重要性. 私有镜像库不但可以加速镜像的拉 ...
- 【转】K8S中部署Helm
K8S中的包管理工具 1. 客户端Helm(即Helm) 通过脚本安装:curl https://raw.githubusercontent.com/helm/helm/master/scripts ...
- k8s中部署springcloud
安装和配置数据存储仓库MySQL 1.MySQL简介 2.MySQL特点 3.安装和配置MySQL 4.在MySQL数据库导入数据 5.对MySQL数据库进行授权 1.MySQL简介 MySQL 是一 ...
- 不使用pvc的方式在K8S中部署apisix-gateway
不使用pvc的方式在K8S中部署apisix-gateway 简介 我的apisix使用etcd作为数据存储服务器,官方的使用pvc方式或者docker-compose的方式,对于新手不太友好,本篇是 ...
随机推荐
- python的import和form...import的区别
import和form...import的区别 参考链接 骏马金龙 https://www.cnblogs.com/lzc978/p/10105194.html 普通区别 import 使用impor ...
- lock、tryLock和lockInterruptibly的差別
lock():若lock被thread A取得,thread B会进入block状态,直到取得lock:tryLock():若当下不能取得lock,thread就会放弃,可以设置一个超时时间参数,等待 ...
- Vagrant 安装Oracle19c RAC测试环境的简单学习
1. 学习自网站: https://xiaoyu.blog.csdn.net/article/details/103135158 简单学习了下 能够将oracle RAC开起来了 但是 对后期的维护和 ...
- IDEA Rider 准备试用一段时间(1)
IDEA Rider是一个C#开发工具,目前最高版本支持C# 8.0语法. IDEA Rider2019.2月版本相比之前2018版本多了新功能,又支持Edit and Continue,所以准备试用 ...
- Mysql load data infile 导入数据出现:Data truncated for column
[1]Mysql load data infile 导入数据出现:Data truncated for column .... 可能原因分析: (1)数据库表对应字段类型长度不够或修改为其他数据类型( ...
- Web应急:门罗币恶意挖矿
门罗币(Monero 或 XMR),它是一个非常注重于隐私.匿名性和不可跟踪的加密数字货币.只需在网页中配置好js脚本,打开网页就可以挖矿,是一种非常简单的挖矿方式,而通过这种恶意挖矿获取数字货币是黑 ...
- 【ELK】7. elasticsearch linux上操作es命令详解
========== 1.检查ES节点是否正常启动 curl http://192.168.6.16:9200 正常状态: 非正常状态: 1>确保服务是不是正常启动了,端口用的是哪个 2> ...
- 转:Windows系统环境下安装dlib
原文链接 因为今天安装Face Recognition,需要先按照 dlib .需要在windows环境下做一些图片处理,所以需要在pycharm中配置环境,而其中需要的主要是dlib的安装: 下面说 ...
- Spring @Import注解源码解析
简介 Spring 3.0之前,创建Bean可以通过xml配置文件与扫描特定包下面的类来将类注入到Spring IOC容器内.而在Spring 3.0之后提供了JavaConfig的方式,也就是将IO ...
- 37.前台js登陆加密分析
开篇 由于现在的登陆接口如果明文传输的话,容易被暴力破解,越来越多的网站选择了前台js加密的方式,像这样: 或者这样: 枯了,对渗透造成一定的影响 本篇文章将系统的讲述使用Python对前台js加密爆 ...