Bootstrap

K8s的API资源对象NetworkPolicy

NetworkPolicy用来控制Pod与Pod之间的网络通信,它也支持针对Namespace进行限制。基于白名单模式,符合规则的对象通过,不符合的拒绝。

应用场景举例:

  • Pod A不能访问Pod B;

  • 开发环境所有Pod不能访问测试命名空间;

  • 提供对外访问时,限制外部IP;

官方NetworkPolicy YAML示例

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
说明:必需字段:apiVersion、 kind 和 metadata 字段。
podSelector:定义目标Pod的匹配标签,即哪些Pod会生效此策略;
policyTypes:表示给定的策略是应用于目标Pod的入站流量(Ingress)还是出站流量(Egress),或两者兼有。 如果NetworkPolicy未指定policyTypes则默认情况下始终设置Ingress。
ingress:定义入流量限制规则,from用来定义白名单对象,比如网段、命名空间、Pod标签,Ports定义目标端口。
egress:定义出流量限制规则,定义可以访问哪些IP和端口

该 YAML 文件定义了一个 Kubernetes 网络策略(NetworkPolicy),用于控制特定 Pod 的网络访问权限。下面是对这个文件的详细解释:

基本信息

  • apiVersionnetworking.k8s.io/v1 - 指定了使用的 Kubernetes API 版本。
  • kindNetworkPolicy - 表明这是一个网络策略资源。
  • metadata:
    • nametest-network-policy - 网络策略的名称。
    • namespacedefault - 网络策略所属的命名空间。

规范(spec)

  • podSelector:

    • matchLabels:
      • roledb - 这个选择器指定网络策略应用于所有带有标签 role=db 的 Pod。
  • policyTypes:

    • Ingress - 表明这个策略包含对进入选定 Pod 的流量的规则。
    • Egress - 表明这个策略包含对从选定 Pod 流出的流量的规则。

进入流量规则(Ingress)

  • ingress:
    • from:
      • ipBlock:
        • cidr172.17.0.0/16 - 允许从这个 CIDR 块的 IP 地址范围进入流量。
        • except:
          • 172.17.1.0/24 - 从上述 CIDR 块中排除这个子网,即这个子网中的 IP 地址不允许访问。
      • namespaceSelector:
        • matchLabels:
          • projectmyproject - 允许来自带有标签 project=myproject 的命名空间中的所有 Pod 的流量。
      • podSelector:
        • matchLabels:
          • rolefrontend - 允许来自带有标签 role=frontend 的 Pod 的流量。
    • ports:
      • protocolTCP - 指定允许 TCP 协议。
      • port6379 - 指定允许访问端口 6379(通常为 Redis 服务端口)。

流出流量规则(Egress)

  • egress:
    • to:
      • ipBlock:
        • cidr10.0.0.0/24 - 允许流向这个 CIDR 块的 IP 地址范围的流出流量。
    • ports:
      • protocolTCP - 指定允许 TCP 协议。
      • port5978 - 指定允许访问端口 5978。

案例一:

需求:aming命名空间下所有Pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问aming命名空间Pod。

首先创建几个Pod:
root@k8s-master:/home/vagrant# kubectl run busybox --image=busybox -- sleep 3600  ## default命名空间里创建busybox Pod
pod/busybox created
root@k8s-master:/home/vagrant# kubectl create namespace aming
namespace/aming created
root@k8s-master:/home/vagrant# kubectl run busybox --image=busybox -n aming -- sleep 3600    ## aming命名空间里创建busybox Pod
pod/busybox created
root@k8s-master:/home/vagrant# kubectl run web --image=nginx:latest -n aming  ## aming命名空间里创建web pod
pod/web created
在没有创建NetworkPolicy的情况下测试:
root@k8s-master:/home/vagrant# kubectl get pods -n aming -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
busybox   1/1     Running   0          78s   172.16.126.28   k8s-worker2   <none>           <none>
web       1/1     Running   0          56s   172.16.194.88   k8s-worker1   <none>           <none>
root@k8s-master:/home/vagrant# kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
busybox                       1/1     Running   0          76s   172.16.126.27   k8s-worker2   <none>           <none>
#aming空间的Pod  ping default的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec -it busybox -n aming -- ping 172.16.126.27
PING 172.16.126.27 (172.16.126.27): 56 data bytes
64 bytes from 172.16.126.27: seq=0 ttl=63 time=0.159 ms
64 bytes from 172.16.126.27: seq=1 ttl=63 time=0.059 ms
#aming空间的Pod  ping 本命名空间的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec -it busybox -n aming -- ping 172.16.194.88
PING 172.16.194.88 (172.16.194.88): 56 data bytes
64 bytes from 172.16.194.88: seq=0 ttl=62 time=0.633 ms
64 bytes from 172.16.194.88: seq=1 ttl=62 time=0.751 ms
#default命名空间ping aming命名空间的Pod可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -- ping 172.16.126.28
PING 172.16.126.28 (172.16.126.28): 56 data bytes
64 bytes from 172.16.126.28: seq=0 ttl=63 time=0.064 ms
64 bytes from 172.16.126.28: seq=1 ttl=63 time=0.107 ms

创建networkpolicy的YAML

root@k8s-master:/home/vagrant# cat deny-all-namespaces.yaml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: deny-all-namespaces
  namespace: aming
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}
root@k8s-master:/home/vagrant# kubectl get NetworkPolicy -n aming
NAME                  POD-SELECTOR   AGE
deny-all-namespaces   <none>         15s

验证效果

#aming命名空间 ping default命名空间的Pod 可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -n aming -- ping 172.16.126.27
PING 172.16.126.27 (172.16.126.27): 56 data bytes
64 bytes from 172.16.126.27: seq=0 ttl=63 time=0.095 ms
64 bytes from 172.16.126.27: seq=1 ttl=63 time=0.142 ms
^C
#default命名空间 ping aming命名空间的Pod 不可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox  -- ping 172.16.126.28
^C
root@k8s-master:/home/vagrant# kubectl exec busybox  -- ping 172.16.194.88
^C
#aming命名空间 ping 本命名空间的Pod 可以ping通
root@k8s-master:/home/vagrant# kubectl exec busybox -n aming -- ping 172.16.194.88
PING 172.16.194.88 (172.16.194.88): 56 data bytes
64 bytes from 172.16.194.88: seq=0 ttl=62 time=0.440 ms

案例二:

通过PodSelector限制

root@k8s-master:/home/vagrant# cat pod-selector.yaml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: pod-selector
  namespace: aming
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: dev
    ports:
    - port: 80
root@k8s-master:/home/vagrant# kubectl apply -f pod-selector.yaml 
networkpolicy.networking.k8s.io/pod-selector created

创建测试pod
 

root@k8s-master:/home/vagrant# kubectl run web01 --image=nginx:latest -n aming -l 'app=test' 
pod/web01 created
root@k8s-master:/home/vagrant# kubectl run app01 --image=nginx:latest -n aming -l 'app=dev' 
pod/app01 created
root@k8s-master:/home/vagrant# kubectl run app02 --image=nginx:1.23.2 -n aming  
pod/app02 created
#查看web01的IP
root@k8s-master:/home/vagrant# kubectl get pods -n aming -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP              NODE          NOMINATED NODE   READINESS GATES
app01   1/1     Running   0          61s    172.16.126.31   k8s-worker2   <none>           <none>
app02   1/1     Running   0          54s    172.16.194.89   k8s-worker1   <none>           <none>
web01   1/1     Running   0          2m1s   172.16.126.29   k8s-worker2   <none>           <none>
root@k8s-master:/home/vagrant# kubectl exec app01 -n aming -- curl 172.16.126.29
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100   615  100   615    0     0   265k      0 --:--:-- --:--:-- --:--:--  300k
root@k8s-master:/home/vagrant# kubectl exec app02 -n aming -- curl 172.16.126.29
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:16 --:--:--     0^C

案例三:

限制namespace

root@k8s-master:/home/vagrant# cat allow-ns.yaml 
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-ns
  namespace: aming
spec:
  policyTypes:
  - Ingress
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          app: test
    ports:
    - port: 80
root@k8s-master:/home/vagrant# kubectl create ns test
root@k8s-master:/home/vagrant# kubectl apply -f allow-ns.yaml 
networkpolicy.networking.k8s.io/allow-ns created
root@k8s-master:/home/vagrant# kubectl  label ns test app=test
namespace/test labeled
root@k8s-master:/home/vagrant# kubectl get ns test --show-labels
NAME   STATUS   AGE   LABELS
test   Active   71s   app=test,kubernetes.io/metadata.name=test

创建测试pod

kubectl run web01 --image=nginx:latest -n aming
kubectl run web02 --image=nginx:latest  -n test
kubectl run web03 --image=nginx:latest  
kubectl run web04 --image=nginx:latest  -n aming
#查看web01的IP
root@k8s-master:/home/vagrant# kubectl get pods -o wide -n aming
NAME    READY   STATUS    RESTARTS   AGE     IP              NODE          NOMINATED NODE   READINESS GATES
web01   1/1     Running   0          2m19s   172.16.126.32   k8s-worker2   <none>           <none>
web04   1/1     Running   0          51s     172.16.126.35   k8s-worker2   <none>           <none>
#可以访问
root@k8s-master:/home/vagrant# kubectl exec web02 -n test -- curl 172.16.126.32
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0  1011k      0 --:--:-- --:--:-- --:--:--  600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#不可以访问
root@k8s-master:/home/vagrant# kubectl exec web03 -- curl 172.16.126.32
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:09 --:--:--     0^C
##不可以访问,即使同一个命名空间也无法访问
root@k8s-master:/home/vagrant# kubectl exec web04 -n aming -- curl 172.16.126.32
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:04 --:--:--     0^C

;