大家好!今天我要和大家分享一项在Kubernetes(K8S)世界中的真正魔法——NetworkPolicy
。这个神奇的功能可以帮助你在K8S集群中管理网络流量,确保你的应用程序安全可靠运行。一起来揭开这个网络策略的神秘面纱吧!🔍💡
🌐 什么是NetworkPolicy?
K8S网络策略(NetworkPolicy)是一种强大的工具,它让你能够在Kubernetes集群中细致地管理Pod之间的网络通信。通过定义规则,你可以控制流量的进出,确保你的微服务架构安全、高效运行。🛡️🚀
🔒 NetworkPolicy的核心概念
- 选择器(Selectors): 通过标签选择器,你可以精确指定哪些Pod需要受到NetworkPolicy的控制,为你的应用建立一个网络保护墙。
- 规则(Rules): NetworkPolicy的灵魂所在!通过定义规则,你可以规定允许或拒绝的流量,创建自定义的网络流通策略。
- 命名空间(Namespaces): NetworkPolicy可以根据命名空间进行划分,使你能够在集群中实现多层次的网络隔离,保障不同应用的安全性。
- Pod隔离的两种类型:
- 出口隔离(Egress)
- 入口隔离(Ingress)
🚀 如何开始使用NetworkPolicy?
- 了解你的应用: 在定义NetworkPolicy之前,确保你深入了解你的应用之间的通信需求,这样才能更加精确地制定策略。
- 标签标识: 通过标签给Pod打上身份标识,然后在NetworkPolicy中使用这些标签,建立通信规则。
- 制定规则: 设计规则时,要考虑到应用的不同组件之间的通信方式,合理规划允许和拒绝的流量。
NetworkPolicy 配置详解
以下是一个NetworkPolicy
的示例,参阅 NetworkPolicy 来了解资源的完整定义。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default #策略应用在那个名称空间,就说对那个命名空间的pod做限制(目标)
spec:
podSelector: #选择匹配哪些标签的pod,选择一组pod做网络策略,写{}表示该命名空间下pod
matchLabels:
role: db
policyTypes:
- Ingress #入网,谁访问pod(即谁访问default名称空间下有role=db标签的pod)
- Egress #出网,role=db的pod可以访问谁
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
🌈 NetworkPolicy的实战应用
拒绝命名空间下所有pod入、出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: test
spec:
podSelector: {} #匹配本命名空间所有pod
policyTypes:
- Ingress
- Egress
上述网络策略是禁止test
命名空间的所有pod进出流量。
在没有创建网络策略时,test命名空间的Pod都能访问外网,如下:
root@k8s-master:~# kubectl run busybox --image=busybox -n test sleep 12h
pod/busybox created
root@k8s-master:~# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 31s 10.244.169.137 k8s-node2 <none> <none>
root@k8s-master:~# kubectl exec busybox -n test ping baidu.com
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING baidu.com (39.156.66.10): 56 data bytes
64 bytes from 39.156.66.10: seq=0 ttl=49 time=51.555 ms
64 bytes from 39.156.66.10: seq=1 ttl=49 time=51.611 ms
64 bytes from 39.156.66.10: seq=2 ttl=49 time=51.237 ms
64 bytes from 39.156.66.10: seq=3 ttl=49 time=51.056 ms
64 bytes from 39.156.66.10: seq=4 ttl=49 time=50.914 ms
64 bytes from 39.156.66.10: seq=5 ttl=49 time=51.145 ms
在deny-all网络策略后,test命名空间下的容器就不能访问外网
root@k8s-master:/home/yaml# kubectl apply -f deny-all.yml
networkpolicy.networking.k8s.io/deny-all created
root@k8s-master:/home/yaml# kubectl exec busybox -n test ping baidu.com
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
ping: bad address 'baidu.com'
command terminated with exit code 1
外部Pod之间相互也不能访问了。这里在test命名空间启动一个nginx容器作为测试。
root@k8s-master:/home/yaml# kubectl run web --image=nginx -n test
pod/web created
root@k8s-master:/home/yaml# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 9m33s 10.244.169.137 k8s-node2 <none> <none>
web 1/1 Running 0 76s 10.244.169.138 k8s-node2 <none> <none>
root@k8s-master:/home/yaml# kubectl exec busybox -n test ping 10.244.169.138
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
拒绝其他命名空间pod访问
在生成环境中或许有这样的需求,运行相同命名空间的pod相互访问,拒绝其他命名空间访问该命名空间的所有Pod。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-ingress
namespace: test
spec:
podSelector: {} #test下的所有pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} #匹配本命名空间所有pod
这里用两个命名空间进行模拟,一个是开发环境dev
,一个是生成环境pro
。现在有这样一个需求,生成环境的pro
下的所有Pod
不能访问dev开发环境的所有Pod
。
root@k8s-master:/home/yaml# kubectl create ns pro
namespace/pro created
root@k8s-master:/home/yaml# kubectl create ns dev
namespace/dev created
root@k8s-master:/home/yaml# kubectl run pro-busybox --image=busybox -n pro sleep 12h
pod/pro-busybox created
root@k8s-master:/home/yaml# kubectl run dev-busybox --image=busybox -n dev sleep 12h
pod/dev-busybox created
root@k8s-master:/home/yaml# kubectl run pro-web --image=nginx -n pro
pod/pro-web created
root@k8s-master:/home/yaml# kubectl run dev-web --image=nginx -n dev
root@k8s-master:/home/yaml# kubectl run pro-db --image=mysql --env="MYSQL_ROOT_PASSWORD=@root@" -n pro
pod/pro-db created
root@k8s-master:/home/yaml# kubectl run dev-db --image=mysql --env="MYSQL_ROOT_PASSWORD=@root@" -n dev
pod/dev-db created
root@k8s-master:/home/yaml# kubectl get pod -n pro -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pro-busybox 1/1 Running 0 21s 10.244.169.142 k8s-node2 <none> <none>
pro-db 1/1 Running 0 11m 10.244.36.72 k8s-node1 <none> <none>
pro-web 1/1 Running 0 20m 10.244.36.69 k8s-node1 <none> <none>
root@k8s-master:/home/yaml# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dev-busybox 1/1 Running 0 20s 10.244.36.75 k8s-node1 <none> <none>
dev-db 1/1 Running 0 10m 10.244.36.73 k8s-node1 <none> <none>
dev-web 1/1 Running 0 20m 10.244.169.139 k8s-node2 <none> <none>
在没有做网络策略时,pro命名空间下的pod可以与dev命名空间下的Pod相互通讯,如下:
root@k8s-master:/home/yaml# kubectl exec pro-busybox -n pro ping 10.244.36.73
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.73 (10.244.36.73): 56 data bytes
64 bytes from 10.244.36.73: seq=0 ttl=62 time=2.427 ms
64 bytes from 10.244.36.73: seq=1 ttl=62 time=1.235 ms
64 bytes from 10.244.36.73: seq=2 ttl=62 time=1.167 ms
^C
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.72
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.72 (10.244.36.72): 56 data bytes
64 bytes from 10.244.36.72: seq=0 ttl=63 time=0.511 ms
64 bytes from 10.244.36.72: seq=1 ttl=63 time=0.238 ms
创建网络策略,如下:
root@k8s-master:/home/yaml# cat deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-ingress
namespace: pro
spec:
podSelector: {} #test下的所有pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} #匹配本命名空间所有pod
root@k8s-master:/home/yaml# kubectl apply -f deny-ingress.yaml
networkpolicy.networking.k8s.io/deny-ingress created
验证结果,如下,dev命名空间下的pod不能访问pro命名空间下的所有pod,dev命名空间的pod可以相互访问
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.72
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
^C
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.73
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.73 (10.244.36.73): 56 data bytes
64 bytes from 10.244.36.73: seq=0 ttl=63 time=0.853 ms
64 bytes from 10.244.36.73: seq=1 ttl=63 time=0.336 ms
允许其他命名空间pod访问指定应用
现在有这样一个需求,允许其他命名空间访问pro命名空间指定pod,pod标签app=web
。
先给pro-web
pod 添加上标签,如下:
root@k8s-master:/home/yaml# kubectl label pods pro-web app=web -n pro
pod/pro-web labeled
root@k8s-master:/home/yaml# kubectl get pod -n pro --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pro-busybox 1/1 Running 0 16m run=pro-busybox
pro-db 1/1 Running 0 27m run=pro-db
pro-web 1/1 Running 0 36m app=web,run=pro-web
创建网络策略,网络策略内容如下,创建之前把之前测试的网络测试删除。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-nmespace
namespace: pro
spec:
podSelector:
matchLabels:
app: web #pro名称空间下的有app=web的标签
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: {} #匹配所有命名空间的pod
root@k8s-master:/home/yaml# kubectl delete -f deny-ingress.yaml
networkpolicy.networking.k8s.io "deny-ingress" deleted
root@k8s-master:/home/yaml# kubectl apply -f allow-all-namespace.yml
networkpolicy.networking.k8s.io/allow-all-nmespace created
即所有名称空间的pod都可以访问pro名称空间下的app=web的pod,和K8s默认一样,没意义。但和案列1搭配即可实现一个可访问,一个不可访问。
单独此规则,和K8S默认一样的,如下:
root@k8s-master:~# kubectl get pod -n pro -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pro-busybox 1/1 Running 0 69m 10.244.169.142 k8s-node2 <none> <none>
pro-db 1/1 Running 0 80m 10.244.36.72 k8s-node1 <none> <none>
pro-web 1/1 Running 0 89m 10.244.36.69 k8s-node1 <none> <none>
root@k8s-master:~# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dev-busybox 1/1 Running 0 69m 10.244.36.75 k8s-node1 <none> <none>
dev-db 1/1 Running 0 79m 10.244.36.73 k8s-node1 <none> <none>
dev-web 1/1 Running 0 89m 10.244.169.139 k8s-node2 <none> <none>
root@k8s-master:~# kubectl exec dev-busybox -n dev ping 10.244.36.69
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.69 (10.244.36.69): 56 data bytes
64 bytes from 10.244.36.69: seq=0 ttl=63 time=0.269 ms
64 bytes from 10.244.36.69: seq=1 ttl=63 time=0.245 ms
^C
root@k8s-master:~# kubectl exec dev-busybox -n dev ping 10.244.36.72
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.72 (10.244.36.72): 56 data bytes
64 bytes from 10.244.36.72: seq=0 ttl=63 time=0.301 ms
64 bytes from 10.244.36.72: seq=1 ttl=63 time=0.279 ms
结合案例1拒绝命名空间所以pod入,出站流量规则,如下:
root@k8s-master:/home/yaml# cat deny-all.yml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: pro
spec:
podSelector: {} #匹配本命名空间所有pod
policyTypes:
- Ingress
- Egress
root@k8s-master:/home/yaml# kubectl apply -f deny-all.yml
networkpolicy.networking.k8s.io/deny-all created
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.72
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
^C
root@k8s-master:/home/yaml# kubectl exec dev-busybox -n dev ping 10.244.36.69
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
PING 10.244.36.69 (10.244.36.69): 56 data bytes
64 bytes from 10.244.36.69: seq=0 ttl=63 time=0.372 ms
64 bytes from 10.244.36.69: seq=1 ttl=63 time=0.369 ms
CKA真题
题目1
切换 k8s 集群环境:
kubectl config use-context hk8s
Task
在现有的
namespace internal
中创建一个名为allow-port-from-namespace
的新 NetworkPolicy。确保新的
NetworkPolicy
允许namespace
中的Pods
连接到namespace internal
中的Pods 的9000
端口。进一步确保新的NetworkPolicy:
- 不允许对没有在监听端口 9000 的 Pods 的访问
- 不允许不来自namespace internal的pods的访问
kubectl config use-context hk8s
# 编写一个 yaml 文件,注意先输入 ":set paste",防止复制时 yaml 文件空格错序
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: internal
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
ports:
- protocol: TCP
port: 9000
# 创建网络策略资源
kubectl apply -f networkpolicy.yaml
题目2
[candidate@node-1] $ kubectl config use-context hk8s
Task
在现有的 namespace my-app 中创建一个名为
allow-port-from-namespace
的新 NetworkPolicy。确保新的 NetworkPolicy 允许 namespace echo 中的 Pods 连接到 namespace my-app 中的 Pods 的 9000 端口。
进一步确保新的 NetworkPolicy:
-- 不允许对没有在监听 端口 9000 的 Pods 的访问
-- 不允许非来自 namespace echo 中的 Pods 的访问
kubectl config use-context hk8s
# 编写一个 yaml 文件,注意先输入 ":set paste",防止复制时 yaml 文件空格错序
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: my-app
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLables:
app: echo
ports:
- protocol: TCP
port: 9000
# 创建网络策略资源
kubectl apply -f networkpolicy.yaml
🎉 小结
通过完成上述步骤,您已经学会了在CKA考试中使用NetworkPolicy的基础知识。掌握NetworkPolicy对于保障Kubernetes集群中应用程序的安全性和隔离性至关重要。在考试中,深入了解NetworkPolicy的工作原理和用法将帮助您更好地应对相关问题。祝您考试顺利!