文章目录
1. Calico
1.1 简介
Calico 是一个安全的 L3 网络和网络策略驱动。
- flannel实现的是网络通信 , calico的特性是在pod之间的隔离。
- 通过BGP路由,但大规模端点的拓扑计算和收敛往往需要一定的时间和
计算资源。 - 纯三层的转发,中间没有任何的NAT和overlay,转发效率最好。
- Calico仅依赖三层路由可达。Calico 较少的依赖性使它能适配所有VM、Container、白盒或者混合环境场景。
1.2 网络架构
Felix:监听ECTD中心的存储获取事件,用户创建pod后, Felix负责将其网卡、IP、 MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样 会将该策略创建到ACL中,以实现隔离。
BIRD:一个标准的路由程序,它会从内核里面获取哪-些IP的路由发生了 变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,路由的时候到这里来。
2. 部署网络插件Calico
2.1 准备
之前安装过Flannel插件,需要清理相关信息:
master端:
kubectl delete -f kube-flannel.yml
所有节点执行:
mv /etc/cni/net.d/10-flannel.conflist /mnt/
2.2 安装
1.建立目录
mkdir calico
cd calico/
2.下载yaml文件:
官网:wget https://docs.projectcalico.org/manifests/calico.yaml
这里使用自己定义的部署文件,还是在官网基础上修改的
#v3.16.1版本
需要修改一下内容及镜像版本
- name: CALICO_IPV4POOL_IPIP
value: "off"
3.部署
kubectl apply -f calico.yaml
3. 网络策略 NetworkPolicy
如果你希望在 IP 地址或端口层面(OSI 第 3 层或第 4 层)控制网络流量, 则你可以考虑为集群中特定应用使用 Kubernetes 网络策略(NetworkPolicy)。NetworkPolicy 是一种以应用为中心的结构,允许你设置如何允许 Pod 与网络上的各类网络“实体” (我们这里使用实体以避免过度使用诸如“端点”和“服务”这类常用术语, 这些术语在 Kubernetes 中有特定含义)通信。
Pod 可以通信的 Pod 是通过如下三个标识符的组合来辩识的:
- 其他被允许的 Pods(例外:Pod 无法阻塞对自身的访问)
- 被允许的命名空间
- IP 组块
3.1 隔离和非隔离的 Pod
默认情况下,Pod 是非隔离的,它们接受任何来源的流量。
Pod 在被某 NetworkPolicy 选中时进入被隔离状态。 一旦名字空间中有 NetworkPolicy 选择了特定的 Pod,该 Pod 会拒绝该 NetworkPolicy 所不允许的连接。 (名字空间下其他未被 NetworkPolicy 所选择的 Pod 会继续接受所有的流量)
网络策略不会冲突,它们是累积的。 如果任何一个或多个策略选择了一个 Pod, 则该 Pod 受限于这些策略的 入站(Ingress)/出站(Egress)规则的并集。因此评估的顺序并不会影响策略的结果。
为了允许两个 Pods 之间的网络数据流,源端 Pod 上的出站(Egress)规则和 目标端 Pod 上的入站(Ingress)规则都需要允许该流量。 如果源端的出站(Egress)规则或目标端的入站(Ingress)规则拒绝该流量, 则流量将被拒绝
3.2 选择器 to 和 from
可以在 ingress 的 from 部分或 egress 的 to 部分中指定四种选择器:
podSelector: 此选择器将在与 NetworkPolicy 相同的名字空间中选择特定的 Pod,应将其允许作为入站流量来源或出站流量目的地。
namespaceSelector:此选择器将选择特定的名字空间,应将所有 Pod 用作其 入站流量来源或出站流量目的地。
namespaceSelector 和 podSelector: 一个指定 namespaceSelector 和 podSelector 的 to/from 条目选择特定名字空间中的特定 Pod。
3.3 字段详解
必需字段:与所有其他的 Kubernetes 配置一样,NetworkPolicy 需要 apiVersion、 kind 和 metadata 字段
spec
:NetworkPolicy 规约 中包含了在一个名字空间中定义特定网络策略所需的所有信息。
podSelector
:每个 NetworkPolicy 都包括一个 podSelector,它对该策略所 适用的一组 Pod 进行选择。示例中的策略选择带有 “role=db” 标签的 Pod。 空的 podSelector 选择名字空间下的所有 Pod。
policyTypes
: 每个 NetworkPolicy 都包含一个 policyTypes 列表,其中包含 Ingress 或 Egress 或两者兼具。policyTypes 字段表示给定的策略是应用于 进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。 如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置 Egress。
ingress
: 每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。 每个规则都允许同时匹配 from 和 ports 部分的流量。示例策略中包含一条 简单的规则: 它匹配某个特定端口,来自三个来源中的一个,第一个通过 ipBlock 指定,第二个通过 namespaceSelector 指定,第三个通过 podSelector 指定。
egress
: 每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。 每个规则都允许匹配 to 和 port 部分的流量。该示例策略包含一条规则, 该规则将指定端口上的流量匹配到 10.0.0.0/24 中的任何目的地。
4. 创建网络策略
准备svc
创建带有标签:app=nginx 的服务nginx-svc
kubectl apply -f /root/ingress/nginx-svc.yml
# /root/ingress/nginx-svc.yml
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: myapp
image: myapp:v2
测试可以访问:
4.1 拒绝访问指定服务
设置带app=nginx标签的不能访问:
# deny-nginx.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-nginx
spec:
podSelector:
matchLabels:
app: nginx
创建:kubectl apply -f deny-nginx.yml
测试:curl访问失败
4.2 允许指定pod访问服务
允许标签 app: demo 访问带标签 app:nginx的服务:
# acces-demo.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
app: demo
未创建策略前pod访问app:nginx的服务被拒绝:
创建策略:kubectl apply -f acces-demo.yml
添加标签 app:demo:
测试:成功访问
4.3 禁止 namespace 中所有pod之间的相互访问
1.创建命名空间demo:
kubectl create namespace demo
2.创建两个pod并交互式(命名空间为demo)
kubectl run demo1 --image=radial/busyboxplus -it -n demo
kubectl run demo2 --image=radial/busyboxplus -it -n demo
命名空间demo中的pod可以相互访问:
创建策略:kubectl apply -f deny-pod.yml
# deny-pod.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: demo
spec:
podSelector: {
}
创建策略成功后:命名空间demo中的pod不能相互访问
4.4 禁止其他 namespace 访问服务
创建pod:可以访问
kubectl run nginx --image=myapp:v2
创建策略:kubectl apply -f deny-ns.yml
# deny-ns.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: deny-namespace
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {
}
测试:访问失败
4.5 允许指定namespace访问服务
- 允许 role=prod并且ns 为 test的 pod 可以访问 run=nginx
1.创建namespace为test
kubectl create namespace test
2.为test添加标签role:prod
kubectl label ns test role=prod
3.创建test下的pod并交互式
kubectl run test1 --image=radial/busyboxplus -it -n test
4.测试发现不能访问(在4.1中设置带app=nginx标签的不能访问)
curl 10.244.22.3
创建策略:kubectl apply -f acces-ns.yml
# acces-ns.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-namespace
spec:
podSelector:
matchLabels:
run: nginx
ingress:
- from:
- namespaceSelector:
matchLabels:
role: prod
测试:成功访问
4.6 允许外网访问服务
- 带标签 app=nginx 的pod可以从外网访问到
创建ingress:
kubectl apply -f /root/ingress/nginx.yml
# /root/ingress/nginx.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-demo
spec:
rules:
- host: www1.westos.org
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
外网测试访问失败(提前解析www1.westos.org)
curl www1.westos.org
创建策略:
kubectl apply -f acces-ex.yml
# acces-ex.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- ports:
- port: 80
from: []
外网可以成功访问: