使用flannel+canal实现k8s的NetworkPolicy
1、NetworkPolicy概述
官方说明:网络策略(NetworkPolicy)是一种关于pod
间及pod
与其他网络端点间所允许的通信规则的规范。
简单来说,NetworkPolicy
就是对pod
进行网络策略控制。用于为Kubernetes
实现更为精细的流量控制,实现租户隔离机制。Kubernetes
使用标准的资源对象NetworkPolicy
供管理员按需定义网络访问控制策略。
2、NetworkPolicy策略模型
使用network policy
资源可以配置pod
的网络,networkPolicy
是namespace scoped
的,他只能影响某个namespace
下的pod
的网络出入站规则。
metadata
描述信息。podSelector
pod选择器,选定的pod
所有的出入站流量要遵循本networkpolicy
的约束。policyTypes
策略类型。包括了Ingress
和Egress
,默认情况下一个policyTypes
的值一定会包含Ingress
,当有egress
规则时,policyTypes
的值中会包含Egress
。ingress
入站,即由其他网络端点发往特定Pod
组的流量 ,通常由流量发出的源站点from
和流量的目标端口所定义 。egress
出站,即由特定的Pod
组发往其他网络端点的流量 ,通常由流量的目标网络端点to
和端口ports
来进行定义 。port
端口,TCP
或UDP
的端口号。to,from
端点,流量目标和流量源相关的组件, 它可以是CIDR
格式的IP
地址块ipBlock
、网络名称空间选择器namespaceSelector
匹配的名称空间, 或Pod
选择器podSelector
匹配的Pod
组。
对官方示例的说明:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
该例子的效果如下:
1、default namespace
下label
包含role=db
的pod
,都会被隔绝,他们只能建立满足networkPolicy
的ingress
和egress
描述的连接。即2-5点:
2、所有属于172.17.0.0/16
网段的ip,除了172.17.1.0/24
中的ip,其他的都可以与上述pod
的6379
端口建立tcp
连接。
3、所有包含label:project=myproject
的namespace
中的pod
可以与上述pod
的6379
端口建立tcp
连接;
4、所有default namespace
下的label
包含role=frontend
的pod
可以与上述pod
的6379
端口建立tcp
连接;
5、允许上述pod
访问网段为10.0.0.0/24
的目的ip
的5978
端口。
3、NetworkPolicy默认策略
默认情况下,如果名称空间中不存在任何策略,则所有进出该名称空间中的Pod的流量都被允许。以下示例用于更改该名称空间中的默认行为。
- 默认拒绝所有入口流量
通过创建选择所有容器但不允许任何进入这些容器的入口流量的NetworkPolicy
来为名称空间创建default
隔离策略。这样可以确保即使容器没有选择其他任何NetworkPolicy
,也仍然可以被隔离。此策略不会更改默认的出口隔离行为。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- 默认允许所有入口流量
如果要允许所有流量进入某个命名空间中的所有Pod
(即使添加了导致某些Pod
被视为“隔离”的策略),则可以创建一个策略来明确允许该命名空间中的所有流量。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
- 默认拒绝所有出口流量
通过创建选择所有容器但不允许来自这些容器的任何出口流量的NetworkPolicy
来为名称空间创建default egress
隔离策略。这样可以确保即使没有被其他任何NetworkPolicy
选择的Pod
也不会被允许流出流量。此策略不会更改默认的ingress
隔离行为。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Egress
- 默认允许所有出口流量
如果要允许来自命名空间中所有Pod
的所有流量(即使添加了导致某些Pod
被视为“隔离”的策略),则可以创建一个策略,该策略明确允许该命名空间中的所有出口流量。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
egress:
- {}
policyTypes:
- Egress
- 默认拒绝所有入口和所有出口流量
为名称空间创建default
策略,以通过在该名称空间中创建以下NetworkPolicy
来阻止所有入站和出站流量。这样可以确保即使没有被其他任何NetworkPolicy
选择的Pod
也不会被允许进入或流出流量。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
4、NetworkPolicy的实现
kubernetes
的网络策略功能本身并不支持,依赖其所使用的网络插件实现。因此,仅在使用那些支持网络策略功能的网络插件时才能够配置网络策略,企业内部可以使用简单的flannel
、weave
、kube-router
等,适合公有云的方案则有calico
等。不同的网络实现原理vethpair
、bridge
、macvlan
等并不能统一地支持network policy
。每种解决方案各有其特定的网络策略实现方式,它们的实现或依赖于节点自身的功能,或借助于Hypervisor
的特性,也可能是网络自身的功能 。究其最终的底层实现原理,目前是基于linux iptables
实现,使用类似于nf_conntrack
检查记录网络流量session
从而决定流量是否阻断。
5、使用flannel+canal实现k8s的NetworkPolicy
Flannel
是解决容器网络方案最为普遍和简单的方案,Canal
代表了针对云原生应用程序的最佳网络策略解决方案,旨在让用户轻松的将Calico
和Flannel
网络部署在一起作为统一的网络解决方案,将Calico
的网络策略执行和Flannel
的叠加及非叠加网络连接选项的丰富功能相结合。
在Calico
的官方文档的相应部分中描述到此种方案是:用于策略的Calico
和用于网络的Flannel
相组合。官方文档见:https://docs.projectcalico.org/v3.10/getting-started/kubernetes/installation/flannel
5.1、实验环境说明
实验k8s环境是kubeadm
搭建的1master+2node最新版本1.16.2版本k8s,cni
版本为0.3.1,flannel
版本为0.11.0,flannel
后端是vxlan
模式并且已经开启了Directrouting
。
[root@k8s-master-01 ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:18:23Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.2", GitCommit:"c97fe5036ef3df2967d086711e6c0c405941e14b", GitTreeState:"clean", BuildDate:"2019-10-15T19:09:08Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
[root@k8s-master-01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-01 Ready master 4d1h v1.16.2
k8s-node-01 Ready <none> 4d v1.16.2
k8s-node-02 Ready <none> 4d v1.16.2
[root@k8s-master-01 ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-58cc8c89f4-bd6s8 1/1 Running 2 4d1h
coredns-58cc8c89f4-bv5rl 1/1 Running 2 4d1h
etcd-k8s-master-01 1/1 Running 2 4d1h
kube-apiserver-k8s-master-01 1/1 Running 2 4d1h
kube-controller-manager-k8s-master-01 1/1 Running 2 4d1h
kube-flannel-ds-amd64-grzvh 1/1 Running 1 2d22h
kube-flannel-ds-amd64-hrd4h 1/1 Running 1 2d22h
kube-flannel-ds-amd64-l8rtk 1/1 Running 1 2d22h
kube-proxy-bp98z 1/1 Running 2 4d
kube-proxy-kvwgh 1/1 Running 2 4d
kube-proxy-n8lj6 1/1 Running 2 4d1h
kube-scheduler-k8s-master-01 1/1 Running 2 4d1h
5.2、安装canal
按照官方文档说明安装:https://docs.projectcalico.org/v3.10/getting-started/kubernetes/installation/flannel
部署时canal支持将数据存储于etcd中,支持选择专用的etcd存储,也能够以kubernetes api server作为后端存储,这里选择以后种方式进行。
结合flannel
工作时,Calico
提供的默认配置清单中是以flannel
默认使用的10.244.0.0/16
为Pod
网络,因此,请确保kube-controller-manager
程序在启动时通过--clustr-cidr
选项设置使用了此网络地址,并且--allocate-node-cidrs
的值应设置为true
。在使用kubeadm
安装的此版本集群中,此选项均已配置。
如果集群cidr网络地址不是默认值,需要修改配置再进行部署。
[root@k8s-master-01 canal]# curl https://docs.projectcalico.org/v3.10/manifests/canal.yaml -O
[root@k8s-master-01 canal]# kubectl apply -f canal.yaml
configmap/canal-config created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrole.rbac.authorization.k8s.io/flannel configured
clusterrolebinding.rbac.authorization.k8s.io/canal-flannel created
clusterrolebinding.rbac.authorization.k8s.io/canal-calico created
daemonset.apps/canal created
serviceaccount/canal created
[root@k8s-master-01 ~]# kubectl get pods -n kube-system -o wide|grep canal
canal-rxb97 2/2 Running 0 4h25m 192.168.2.12 k8s-node-02 <none> <none>
canal-tdcgf 2/2 Running 0 4h25m 192.168.2.10 k8s-master-01 <none> <none>
canal-vll8z 2/2 Running 0 4h25m 192.168.2.11 k8s-node-01 <none> <none>
5.3、应用示例
5.3.1、创建默认服务
运行一组nginx
pod并暴露80端口
[root@k8s-master-01 ~]# kubectl run nginx --image=nginx --replicas=3 --port=80 --expose
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
service/nginx created
deployment.apps/nginx created
[root@k8s-master-01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-5578584966-8spqk 1/1 Running 0 15s
nginx-5578584966-sjlvc 1/1 Running 0 15s
nginx-5578584966-xm4pb 1/1 Running 0 15s
[root@k8s-master-01 ~]# kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.1.8.146 <none> 80/TCP 16s
5.3.2、测试访问
[root@k8s-master-01 ~]# kubectl run busy1 --rm -it --image=busybox /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.1.8.146:80)
remote file exists ## 访问成功
5.3.4、创建默认policy
创建默认拒绝所有入站流量的networkpolicy,测试访问
[root@k8s-master-01 networkpolicy]# vim default-deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
[root@k8s-master-01 networkpolicy]# kubectl apply -f default-deny-ingress.yaml
networkpolicy.networking.k8s.io/default-deny created
[root@k8s-master-01 ~]# kubectl run busy1 --rm -it --image=busybox /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.1.8.146:80)
wget: download timed out ## 访问失败
5.3.5、创建一个允许带有access=true的Pod访问nginx的网络策略
[root@k8s-master-01 networkpolicy]# vim nginx-policy.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
run: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
[root@k8s-master-01 networkpolicy]# kubectl apply -f nginx-policy.yaml
networkpolicy.networking.k8s.io/access-nginx created
使用不带access=true标签的pod访问服务
[root@k8s-master-01 ~]# kubectl run busy1 --rm -it --image=busybox /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.1.8.146:80)
wget: download timed out ## 访问失败
使用带access=true标签的pod访问服务
[root@k8s-master-01 ~]# kubectl run busy2 --rm -it --labels="access=true" --image=busybox /bin/sh
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.1.8.146:80)
remote file exists ## 访问成功
5.4、生产使用场景
5.4.1、禁止访问指定服务
kubectl run web --image=nginx --labels app=web,env=prod --expose --port 80
网络策略
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-deny-all
spec:
podSelector:
matchLabels:
app: web
env: prod
5.4.2、只允许指定pod访问服务
kubectl run apiserver --image=nginx --labels app=bookstore,role=api --expose --port 80
网络策略
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: api-allow
spec:
podSelector:
matchLabels:
app: bookstore
role: api
ingress:
- from:
- podSelector:
matchLabels:
app: bookstore
5.4.3、禁止 namespace 中所有 Pod 之间的相互访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
5.4.4、禁止其他 namespace 访问服务
kubectl create namespace secondary
kubectl run web --namespace secondary --image=nginx \
--labels=app=web --expose --port 80
网络策略
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: secondary
name: web-deny-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
5.4.5、只允许指定namespace访问服务
kubectl run web --image=nginx \
--labels=app=web --expose --port 80
网络策略
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-prod
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: production
5.4.6、允许外网访问服务
kubectl run web --image=nginx --labels=app=web --port 80
kubectl expose deployment/web --type=LoadBalancer
网络策略
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: web
ingress:
- ports:
- port: 80
from: []
参考来源:
https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
https://docs.projectcalico.org/v3.10/getting-started/kubernetes/installation/flannel
https://github.com/ahmetb/kubernetes-network-policy-recipes
使用flannel+canal实现k8s的NetworkPolicy的更多相关文章
- 容器编排系统K8s之NetworkPolicy资源
前文我们了解了k8s的网络插件flannel的基础工作逻辑,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14225657.html:今天我们来聊一下k8s上 ...
- etcd,flannel,docker relationship---and k8s
journalctl -xe voidcn.com/article/p-qufvdmpq-bqn.html etcd more etcd.confETCD_NAME=default ETCD_DATA ...
- K8s二进制部署单节点 etcd集群,flannel网络配置 ——锥刺股
K8s 二进制部署单节点 master --锥刺股 k8s集群搭建: etcd集群 flannel网络插件 搭建master组件 搭建node组件 1.部署etcd集群 2.Flannel 网络 ...
- Kubernetes(k8s)底层网络原理刨析
目录 1 典型的数据传输流程图 2 3种ip说明 3 Docker0网桥和flannel网络方案 4 Service和DNS 4.1 service 4.2 DNS 5 外部访问集群 5.1 外部访问 ...
- flannel vxlan 实现原理【转】
flannel是coreos为kubernets提供的网络解决方案,主要为打通跨节点的容器通信,其中vxlan模式为flannel实现的一种后端模式,其他模式还包括udp, host-gw等,可以通过 ...
- kubernetes 配置网络插件 flannel
概述 在学习docker时知道docker有四种常用的网络模型 bridge:桥接式网络 joined:联盟式网络,共享使用另外一个容器的网络名称空间 opened:容器直接共享使用宿主机的网络名称空 ...
- Kubernetes 学习18配置网络插件flannel
一.概述 1.我们在学习docker时知道docker有四种常用的网络模型 a.bridge:桥接式网络 b.joined:联盟式网络,共享使用另外一个容器的网络名称空间 b.opened:容器直接共 ...
- k8s 网络模型解析之原理
今天研究了一下k8s的网络模型,该解析基于flannel vxlan+ kubeproxy iptables 模式. 一.Docker 首先分析一下Docker层面的网络模型,我们知道容器是基于内核的 ...
- K8s 实践 | 如何解决多租户集群的安全隔离问题?
作者 | 匡大虎 阿里巴巴技术专家 导读:如何解决多租户集群的安全隔离问题是企业上云的一个关键问题,本文主要介绍 Kubernetes 多租户集群的基本概念和常见应用形态,以及在企业内部共享集群的业 ...
随机推荐
- 使用MAT 分析内存泄漏实战
在分析前可以阅读下这篇文章,很多内容就都知道了https://www.jianshu.com/p/738b4f3bc44b,下面我来分析上一篇文章内存泄漏的为问题 1.上一篇中已经生成了hprf的文件 ...
- beetl模版for循环渲染字符串
beetl for循环渲染html字符串的方式, beetl if条件判断输出, beet自定义标签和标签引用, beetl html赋值, beetl渲染json,beetl注释.变量定义, 更多文 ...
- Git 克隆
工作中大家分工协作,共同开发维护一个项目,git仓库放在公共的服务器上,如github.Gitee等. 在这种情况使用git,需要先克隆仓库到本地. 克隆非常简单,使用命令git clone 将远程仓 ...
- [转帖]50 亿美元!微软签下毕马威!JEDI 100 亿美元订单之后又一大单!
50 亿美元!微软签下毕马威!JEDI 100 亿美元订单之后又一大单! https://mp.weixin.qq.com/s/K0SrFNSVK5aOu6TIzhN92Q 前段时间,微软击败亚马逊, ...
- [转帖]dfs和bfs
dfs和bfs https://www.cnblogs.com/wzl19981116/p/9397203.html 1.dfs(深度优先搜索)是两个搜索中先理解并使用的,其实就是暴力把所有的路径都搜 ...
- Jenkins+Gitlab配置Webhook实现提交自动部署
一.概述 在上一篇文章,链接如下: https://www.cnblogs.com/xiao987334176/p/11434849.html 已经实现了 Jenkins+harbor+gitlab+ ...
- jQuery格式化显示json数据
一.概述 JSONView 在gitlab上面,有一个jQuery JSONView插件,地址为:https://github.com/yesmeck/jquery-jsonview demo地址:h ...
- 打印从1到n位数的最大值
题目: 输入数字n,按顺序打印从1到最大的n位十进制数,如输入3,则打印从1.2.3一直到最大的3位数999 参考大数运算的方法.考虑到位数会很大,所以采用字符串的形式解决.对输入的n,创建一个长度为 ...
- 四种方法获取可执行程序的文件路径(.NET Core / .NET Framework)
原文:四种方法获取可执行程序的文件路径(.NET Core / .NET Framework) 本文介绍四种不同的获取可执行程序文件路径的方法.适用于 .NET Core 以及 .NET Framew ...
- 在虚拟机Linux安装Redis
在虚拟机上安装 CentOS 7 安装成功后登录Root用户进入 opt目录,下载Redis. 下载Redis 下载命令: wget http://download.redis.io/releases ...