1、NetworkPolicy概述

官方说明:网络策略(NetworkPolicy)是一种关于pod间及pod与其他网络端点间所允许的通信规则的规范。

简单来说,NetworkPolicy就是对pod进行网络策略控制。用于为Kubernetes实现更为精细的流量控制,实现租户隔离机制。Kubernetes使用标准的资源对象NetworkPolicy供管理员按需定义网络访问控制策略。

2、NetworkPolicy策略模型

使用network policy资源可以配置pod的网络,networkPolicynamespace scoped的,他只能影响某个namespace下的pod的网络出入站规则。

  • metadata 描述信息。
  • podSelector pod选择器,选定的pod所有的出入站流量要遵循本networkpolicy的约束。
  • policyTypes 策略类型。包括了IngressEgress,默认情况下一个policyTypes的值一定会包含Ingress,当有egress规则时,policyTypes的值中会包含Egress
  • ingress入站,即由其他网络端点发往特定Pod组的流量 ,通常由流量发出的源站点from和流量的目标端口所定义 。
  • egress出站,即由特定的Pod组发往其他网络端点的流量 ,通常由流量的目标网络端点to和端口ports来进行定义 。
  • port 端口,TCPUDP的端口号。
  • 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 namespacelabel包含role=dbpod,都会被隔绝,他们只能建立满足networkPolicyingressegress描述的连接。即2-5点:

2、所有属于172.17.0.0/16网段的ip,除了172.17.1.0/24中的ip,其他的都可以与上述pod6379端口建立tcp连接。

3、所有包含label:project=myprojectnamespace中的pod可以与上述pod6379端口建立tcp连接;

4、所有default namespace下的label包含role=frontendpod可以与上述pod6379端口建立tcp连接;

5、允许上述pod访问网段为10.0.0.0/24的目的ip5978端口。

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的网络策略功能本身并不支持,依赖其所使用的网络插件实现。因此,仅在使用那些支持网络策略功能的网络插件时才能够配置网络策略,企业内部可以使用简单的flannelweavekube-router等,适合公有云的方案则有calico等。不同的网络实现原理vethpairbridgemacvlan等并不能统一地支持network policy。每种解决方案各有其特定的网络策略实现方式,它们的实现或依赖于节点自身的功能,或借助于Hypervisor的特性,也可能是网络自身的功能 。究其最终的底层实现原理,目前是基于linux iptables实现,使用类似于nf_conntrack检查记录网络流量session从而决定流量是否阻断。

5、使用flannel+canal实现k8s的NetworkPolicy

Flannel是解决容器网络方案最为普遍和简单的方案,Canal代表了针对云原生应用程序的最佳网络策略解决方案,旨在让用户轻松的将CalicoFlannel网络部署在一起作为统一的网络解决方案,将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/16Pod网络,因此,请确保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的更多相关文章

  1. 容器编排系统K8s之NetworkPolicy资源

    前文我们了解了k8s的网络插件flannel的基础工作逻辑,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14225657.html:今天我们来聊一下k8s上 ...

  2. etcd,flannel,docker relationship---and k8s

    journalctl -xe voidcn.com/article/p-qufvdmpq-bqn.html etcd more etcd.confETCD_NAME=default ETCD_DATA ...

  3. K8s二进制部署单节点 etcd集群,flannel网络配置 ——锥刺股

    K8s 二进制部署单节点 master    --锥刺股 k8s集群搭建: etcd集群 flannel网络插件 搭建master组件 搭建node组件 1.部署etcd集群 2.Flannel 网络 ...

  4. Kubernetes(k8s)底层网络原理刨析

    目录 1 典型的数据传输流程图 2 3种ip说明 3 Docker0网桥和flannel网络方案 4 Service和DNS 4.1 service 4.2 DNS 5 外部访问集群 5.1 外部访问 ...

  5. flannel vxlan 实现原理【转】

    flannel是coreos为kubernets提供的网络解决方案,主要为打通跨节点的容器通信,其中vxlan模式为flannel实现的一种后端模式,其他模式还包括udp, host-gw等,可以通过 ...

  6. kubernetes 配置网络插件 flannel

    概述 在学习docker时知道docker有四种常用的网络模型 bridge:桥接式网络 joined:联盟式网络,共享使用另外一个容器的网络名称空间 opened:容器直接共享使用宿主机的网络名称空 ...

  7. Kubernetes 学习18配置网络插件flannel

    一.概述 1.我们在学习docker时知道docker有四种常用的网络模型 a.bridge:桥接式网络 b.joined:联盟式网络,共享使用另外一个容器的网络名称空间 b.opened:容器直接共 ...

  8. k8s 网络模型解析之原理

    今天研究了一下k8s的网络模型,该解析基于flannel vxlan+ kubeproxy iptables 模式. 一.Docker 首先分析一下Docker层面的网络模型,我们知道容器是基于内核的 ...

  9. K8s 实践 | 如何解决多租户集群的安全隔离问题?

    作者 | 匡大虎  阿里巴巴技术专家 导读:如何解决多租户集群的安全隔离问题是企业上云的一个关键问题,本文主要介绍 Kubernetes 多租户集群的基本概念和常见应用形态,以及在企业内部共享集群的业 ...

随机推荐

  1. 第一本docker书 学习笔记(一)

    Docker的核心组件: Docker客户端和服务端 Docker镜像 Registry Docker容器 # Docker客户端和服务端 docker 是一个 C/S架构程序.客户端只需要向dock ...

  2. Idea导入maven项目没有识别

    选中module的pom.xml,右键,选择" add as maven project",idea会识别该pom的项目  

  3. fail2ban的功能和特性(实测)

    fail2ban的功能和特性 https://fedoraproject.org/wiki/Fail2ban_with_FirewallD 1.支持大量服务.如sshd,apache,qmail,pr ...

  4. Windows Server 2008 R2 IIS7.5配置FTP图文教程

    本文为大家分享了IIS 配置FTP 网站的具体过程,供大家参考,具体内容如下 说明:服务器环境是Windows Server 2008 R2,IIS7.5. 1. 在 服务器管理器的Web服务器(II ...

  5. c#内存泄漏分析

    背景 给客户开发了一个WPF应用,每隔一段时间就会很卡,推测是内存泄漏引起.需要监测内存使用情况. 使用的工具 Ants Memory Profiler 百度网盘下载地址 使用教程 入门使用 参考文档 ...

  6. expect——通过编写自动化脚本实现信息交互(整理)

    本文简要介绍了expect工具语言的功能.用法,并以实例来具体说明 expect是什么 Expect是一个免费的编程工具语言,用来完成通信过程中的交互式任务,而无需人的干预. 通过shell虽然可以实 ...

  7. Spring整合Hibernate的两种方式

    在使用spring注解整合hibernate时出现"org.hibernate.MappingException: Unknown entity: com.ssh.entry.Product ...

  8. 【Linux】Ubuntu修改root用户密码

    使用vmware安装ubuntu的时候,安装完之后发现没有root用户密码,只有新建用户,这个时候需要重新设置root用户密码 在新建用户下面运行 sudo passwd root

  9. Springcloud的版本依赖问题(最全,包含springCloud所有的版本)

    版权声明:本文为博主原创文章,遵循CC 4.0 BY版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_42105629/article/detai ...

  10. 如何在Job中获取 IOC applicationcontext

    如何在Job中获取 IOC applicationcontext https://segmentfault.com/q/1010000008002800 SpringBoot之整合Quartz调度框架 ...