云原生|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搭建和管理企业级网站应用
目录
相关文章
|
30天前
|
负载均衡 容灾 Cloud Native
云原生应用网关进阶:阿里云网络ALB Ingress 全能增强
在过去半年,ALB Ingress Controller推出了多项高级特性,包括支持AScript自定义脚本、慢启动、连接优雅中断等功能,增强了产品的灵活性和用户体验。此外,还推出了ingress2Albconfig工具,方便用户从Nginx Ingress迁移到ALB Ingress,以及通过Webhook服务实现更智能的配置校验,减少错误配置带来的影响。在容灾部署方面,支持了多集群网关,提高了系统的高可用性和容灾能力。这些改进旨在为用户提供更强大、更安全的云原生网关解决方案。
414 19
|
2月前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
154 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
3月前
|
Kubernetes Cloud Native 微服务
云原生入门与实践:Kubernetes的简易部署
云原生技术正改变着现代应用的开发和部署方式。本文将引导你了解云原生的基础概念,并重点介绍如何使用Kubernetes进行容器编排。我们将通过一个简易的示例来展示如何快速启动一个Kubernetes集群,并在其上运行一个简单的应用。无论你是云原生新手还是希望扩展现有知识,本文都将为你提供实用的信息和启发性的见解。
|
3月前
|
Kubernetes Cloud Native 开发者
云原生入门:Kubernetes的简易指南
【10月更文挑战第41天】本文将带你进入云原生的世界,特别是Kubernetes——一个强大的容器编排平台。我们将一起探索它的基本概念和操作,让你能够轻松管理和部署应用。无论你是新手还是有经验的开发者,这篇文章都能让你对Kubernetes有更深入的理解。
|
3月前
|
消息中间件 运维 Cloud Native
云原生架构下的微服务优化策略####
本文深入探讨了云原生环境下微服务架构的优化路径,针对服务拆分、通信效率、资源管理及自动化运维等核心环节提出了具体的优化策略。通过案例分析与最佳实践分享,旨在为开发者提供一套系统性的解决方案,以应对日益复杂的业务需求和快速变化的技术挑战,助力企业在云端实现更高效、更稳定的服务部署与运营。 ####
|
3月前
|
运维 Kubernetes Cloud Native
云原生技术入门:Kubernetes和Docker的协同工作
【10月更文挑战第43天】在云计算时代,云原生技术成为推动现代软件部署和运行的关键力量。本篇文章将带你了解云原生的基本概念,重点探讨Kubernetes和Docker如何协同工作以支持容器化应用的生命周期管理。通过实际代码示例,我们将展示如何在Kubernetes集群中部署和管理Docker容器,从而为初学者提供一条清晰的学习路径。
|
3月前
|
Kubernetes 负载均衡 Cloud Native
探索Kubernetes:云原生应用的基石
探索Kubernetes:云原生应用的基石
|
2月前
|
Cloud Native API 持续交付
云原生架构下的微服务治理策略与实践####
本文旨在探讨云原生环境下微服务架构的治理策略,通过分析当前面临的挑战,提出一系列实用的解决方案。我们将深入讨论如何利用容器化、服务网格(Service Mesh)等先进技术手段,提升微服务系统的可管理性、可扩展性和容错能力。此外,还将分享一些来自一线项目的经验教训,帮助读者更好地理解和应用这些理论到实际工作中去。 ####
60 0
|
3月前
|
Kubernetes Cloud Native 云计算
云原生入门:Kubernetes 和容器化基础
在这篇文章中,我们将一起揭开云原生技术的神秘面纱。通过简单易懂的语言,我们将探索如何利用Kubernetes和容器化技术简化应用的部署和管理。无论你是初学者还是有一定经验的开发者,本文都将为你提供一条清晰的道路,帮助你理解和运用这些强大的工具。让我们从基础开始,逐步深入了解,最终能够自信地使用这些技术来优化我们的工作流程。
|
24天前
|
缓存 容灾 网络协议
ACK One多集群网关:实现高效容灾方案
ACK One多集群网关可以帮助您快速构建同城跨AZ多活容灾系统、混合云同城跨AZ多活容灾系统,以及异地容灾系统。

热门文章

最新文章