云原生|kubernetes|networkPolicy网络策略详解

简介: 云原生|kubernetes|networkPolicy网络策略详解

前言:

networkPolicy是kubernetes集群的一个重要安全特性。顾名思义,网络策略,控制网络流量的一个资源。

那么,kubernetes集群的网络是由docker虚拟网卡,cni网络插件,flannel网络插件(也可能会使用calico,weaver等等其它网络插件)这些模块组成的。

主要还是基于Linux内核层面的iptables或者ipvs通过上述的网络插件使得整个集群的网络成为网络层次有若干个子网的,内部是可以跨节点,跨子网段的一个整体网络。

例如,我有一个kubeadm部署的集群,集群内部网络如下:

两个子网段,10.244.36 和10.244.169

root@k8s-master:~# kubectl get po -A -owide
NAMESPACE       NAME                                       READY   STATUS    RESTARTS         AGE     IP                NODE         NOMINATED NODE   READINESS GATES
a               a                                          1/1     Running   1 (5m27s ago)    13h     10.244.36.76      k8s-node1    <none>           <none>
b               b                                          1/1     Running   1 (5m27s ago)    13h     10.244.36.69      k8s-node1    <none>           <none>
default         busybox                                    1/1     Running   0                49s     10.244.36.79      k8s-node1    <none>           <none>
default         front-end-5f64577768-tsq76                 1/1     Running   14 (5m27s ago)   9d      10.244.36.75      k8s-node1    <none>           <none>
default         guestbook-86bb8f5bc9-2nk6c                 1/1     Running   13 (5m27s ago)   8d      10.244.36.82      k8s-node1    <none>           <none>
default         guestbook-86bb8f5bc9-2xrh6                 1/1     Running   13 (5m27s ago)   8d      10.244.36.78      k8s-node1    <none>           <none>
default         guestbook-86bb8f5bc9-78pq5                 1/1     Running   13 (5m27s ago)   8d      10.244.36.73      k8s-node1    <none>           <none>
default         guestbook-86bb8f5bc9-m4wr4                 1/1     Running   14 (5m21s ago)   9d      10.244.169.153    k8s-node2    <none>           <none>
default         guestbook-86bb8f5bc9-pkzpl                 1/1     Running   14 (5m21s ago)   9d      10.244.169.152    k8s-node2    <none>           <none>
default         guestbook-86bb8f5bc9-sq4xf                 1/1     Running   13 (5m21s ago)   8d      10.244.169.155    k8s-node2    <none>           <none>
剩下的略略略

OK,此时在集群内部启动一个临时的pod,以上的集群内部IP是都可以ping通的:

kubectl run busybox -it --rm  --image=busybox -- /bin/sh
/ # ping 10.244.36.80 -c 2
PING 10.244.36.80 (10.244.36.80): 56 data bytes
64 bytes from 10.244.36.80: seq=0 ttl=63 time=0.119 ms
64 bytes from 10.244.36.80: seq=1 ttl=63 time=0.129 ms
--- 10.244.36.80 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.119/0.124/0.129 ms
ping 10.244.169.147 -c 2
PING 10.244.169.147 (10.244.169.147): 56 data bytes
64 bytes from 10.244.169.147: seq=0 ttl=62 time=0.737 ms
64 bytes from 10.244.169.147: seq=1 ttl=62 time=0.802 ms

那就说明了一个问题,kubernetes集群的网络是一个自由的,无任何限制的网络,很显然,这样的网络是没有安全性可言的,因为,任意一个pod都可以连接到其它的pod,那么,如果有某一个不受控制的黑客部署的pod在集群内,不是非常的不安全吗?

其实说了这么多,基于网络插件比如calico的networkPolicy会对集群内的网络做一个细粒度的控制,例如,控制某类带有特定标签的pod能够访问其它的指定的pod,简单的说人话就是能够做一定的网络隔离。

Kubernetes提供了NetworkPolicy,支持按Namespace和按Pod级别的网络访问控制。它利用label指定namespaces或pod,底层用iptables实现。不是所有的 Kubernetes 网络方案都支持 Network Policy。比如 Flannel 就不支持,Calico 是支持的。

例如,calico网络方案的networkPolicy工作流程是这样的:

a.通过kubectl client创建network policy资源;
b.calico的policy-controller监听network policy资源,获取到后写入calico的etcd数据库;
c.node上calico-felix从etcd数据库中获取policy资源,调用iptables做相应配置。

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

你首先需要有一个支持网络策略的 Kubernetes 集群。已经有许多支持 NetworkPolicy 的网络提供商,包括:




一,

ingress和egress

ingress 表示进口流量,egress表示出口流量,入口流量和出口流量都是相对networkPolcy所指定的namespace来说的,例如下面这个policy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-nginx
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - from:
    - podSelector:
        matchLabels:
          access: "true"

以上这个policy意思是所有具有标签 access=true的pod才可以访问namespace为default的所有具有pod 标签 app=nginx的pod

OK,此时查看default这个命名空间下的所有pod的具有app=nginx的pod:

root@k8s-master:~# kubectl get po -owide --show-labels |grep nginx
nginx-6799fc88d8-ktjxh                    1/1     Running   5 (80m ago)    8d      10.244.169.140   k8s-node2    <none>           <none>            access=true,app=nginx,pod-template-hash=6799fc88d8
nginx-kusc0041                            1/1     Running   11 (80m ago)   12d     10.244.169.141   k8s-node2    <none>           <none>            run=nginx-kusc0041
task-2-ds-fcm5l                           1/1     Running   13 (80m ago)   14d     10.244.235.193   k8s-master   <none>           <none>            controller-revision-hash=688c88fb84,nginx=task-2-ds,pod-template-generation=1
task-2-ds-nwdlv                           1/1     Running   19 (80m ago)   18d     10.244.169.135   k8s-node2    <none>           <none>            controller-revision-hash=688c88fb84,nginx=task-2-ds,pod-template-generation=1
task-2-ds-pmlqw                           1/1     Running   19 (80m ago)   18d     10.244.36.81     k8s-node1    <none>           <none>            controller-revision-hash=688c88fb84,nginx=task-2-ds,pod-template-generation=1

此时,带标签access=true的pod可以访问140,如果不带access=true,将不可以访问140

不带标签的时候:

kubectl run test -it --rm --image=busybox  -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget 10.244.169.141
Connecting to 10.244.169.141 (10.244.169.141:80)
saving to 'index.html'
index.html           100% |***************************************************************************************************************************************|   615  0:00:00 ETA
'index.html' saved
/ # wget 10.244.169.140
Connecting to 10.244.169.140 (10.244.169.140:80)
^C

带符合的标签的时候:

root@k8s-master:~# kubectl run test -it --rm --image=busybox --labels="access=true" -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget 10.244.169.140
Connecting to 10.244.169.140 (10.244.169.140:80)
saving to 'index.html'
index.html           100% |***************************************************************************************************************************************|   615  0:00:00 ETA
'index.html' saved

那么,有一点需要注意了,podSelector 前面加  -号和 不加-号的,如有-号表示范围扩大,这个时候是两个条件任意一个符合即可(逻辑关系是或)。如无-号表示精确匹配pod的label标签(逻辑关系是与),还是以上面的例子为例:

无减号,表示精确的匹配

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-nginx
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          access: "true"

有减号,表示或者,范围匹配

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-nginx
spec:
  podSelector:
    matchLabels:
      app: nginx
  ingress:
  - from:
    - namespaceSelector: {}
    - podSelector:
        matchLabels:
          access: "true"

二,

实验1:

创建一个networkPolicy,使得名为a的namespace内的pod全部隔离,只有具有标签 access=true的pod才可以访问a namespace内的其它pod

网络策略未创建前:

OK,先创建名为a的namespace,并且在该namespace内创建两个都使用nginx镜像的名称分别为nginx1和nginx2

kubectl create ns a
kubectl run nginx1 --image=nginx -n a
kubectl run nginx2 --image=nginx -n a

查看pod的状态,可以看到有绑定两个IP,分别是10.244.36.86,10.244.36.96

root@k8s-master:~# kubectl get po -n   a  -owide 
NAME     READY   STATUS    RESTARTS       AGE     IP             NODE        NOMINATED NODE   READINESS GATES
nginx1   1/1     Running   1 (123m ago)   4h39m   10.244.36.86   k8s-node1   <none>           <none>
nginx2   1/1     Running   0              97m     10.244.36.96   k8s-node1   <none>           <none>

OK,这个时候我们进入nginx1,看看a 这个namespace内的pod是否互相隔离:

进入pod的命令:

kubectl exec -it po -n a nginx1 -- /bin/sh

可以发现,两个pod之间是可以直接互相访问的,没有任何的阻碍,当然了,其它的namespace内的pod也是没有任何阻碍的可以访问到

# curl 10.244.36.96
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
# curl 10.244.36.86
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

网络策略创建后:

root@k8s-master:~# cat test.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: access-nginx
  namespace: a
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector:
        matchLabels:
          access: "true"

OK,这个网络策略表示名为a的namespace内的所有pod互相直接隔离,只有具有access=true的pod才可以访问a 这个namespace内的其它的pod。

上述文件执行后,此时,在进入nginx1,可以发现无法访问nginx2了:

# curl 10.244.36.96        
^C

但可以自由的访问其它的namespace内的pod,证明网络策略的作用范围只在a 这个namespace内:

root@k8s-master:~# kubectl get po -A -owide |grep  10.244.169.151
default         nginx-6799fc88d8-ktjxh                     1/1     Running   2 (141m ago)    22h     10.244.169.151    k8s-node2    <none>           <none>
curl 10.244.169.151
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }

OK,现在给nginx1增加符合网络策略进入策略的标签acces=true,然后登陆nginx1,再次访问nginx2,可以发现可以正常访问了:

给nginx1添加标签:

kubectl label po -n a nginx1 access=true
root@k8s-master:~# kubectl get po -n a nginx1 --show-labels 
NAME     READY   STATUS    RESTARTS       AGE    LABELS
nginx1   1/1     Running   1 (152m ago)   5h8m   access=true,run=nginx1

再次访问,可以发现恢复正常了,证明网络策略是生效了。

# curl 10.244.36.96
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

由以上实验我们可以得出一个结论:

1,namespace是networkPolicy的作用域

2,from表示方向,因此,上面的例子,标签是打在了nginx1,然后登陆的nginx1,那么,如果标签打到了nginx2上,就需要使用nginx2访问nginx1了。

三,

实验2

某个namespace(这里还是使用a这个namespace),拒绝所有的入站流量和出站流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: a
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

此时,在default这个namespace里有一个nginx,登陆这个pod,可以发现a这个namespace里的所有pod都无法访问了:

root@k8s-master:~# kubectl get po -owide
NAME                                      READY   STATUS    RESTARTS         AGE     IP               NODE         NOMINATED NODE   READINESS GATES
busybox                                   1/1     Running   1 (3h12m ago)    7h25m   10.244.36.105    k8s-node1    <none>           <none>
front-end-5f64577768-tsq76                1/1     Running   15 (3h12m ago)   10d     10.244.36.99     k8s-node1    <none>           <none>
nfs-client-provisioner-56dd5765dc-9z772   1/1     Running   30 (3h12m ago)   10d     10.244.169.162   k8s-node2    <none>           <none>
nginx-6799fc88d8-ktjxh                    1/1     Running   2 (3h12m ago)    23h     10.244.169.151   k8s-node2    <none>           <none>
root@k8s-master:~# kubectl exec -it -n default nginx-6799fc88d8-ktjxh -- /bin/sh
# curl 10.244.36.96
curl: (28) Failed to connect to 10.244.36.96 port 80: Connection timed out
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
14天前
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
3天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
18 2
|
1月前
|
存储 运维 Kubernetes
K8s业务迁移最佳实践: 灵活管理资源备份与调整策略,实现高效简便的应用恢复
在当今快速变化的云原生领域,Kubernetes(K8s)集群的运维面临着诸多挑战,其中灾备与业务迁移尤为关键。ACK备份中心支持丰富的资源调整策略,在数据恢复阶段即可自动适配目标集群环境,确保业务无缝重启。
|
1月前
|
Kubernetes 监控 Java
如何设置 Kubernetes的垃圾回收策略为定期
如何设置 Kubernetes的垃圾回收策略为定期
|
1月前
|
Kubernetes Java 调度
Kubernetes中的Pod垃圾回收策略是什么
Kubernetes中的Pod垃圾回收策略是什么
|
2月前
|
Kubernetes 网络协议 网络安全
k8s中网络连接问题
【10月更文挑战第3天】
206 7
|
2月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
977 1
|
2月前
|
Kubernetes 容器
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
173 0
|
22天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
20天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。