惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
B
Blog RSS Feed
宝玉的分享
宝玉的分享
腾讯CDC
博客园_首页
T
Tailwind CSS Blog
月光博客
月光博客
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
SecWiki News
SecWiki News
美团技术团队
P
Privacy International News Feed
H
Help Net Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Security Blog
Microsoft Security Blog
Know Your Adversary
Know Your Adversary
Y
Y Combinator Blog
D
DataBreaches.Net
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
Cyberwarzone
Cyberwarzone
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
S
Schneier on Security
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
Cisco Talos Blog
Cisco Talos Blog
小众软件
小众软件
Forbes - Security
Forbes - Security
D
Docker
T
Tenable Blog
S
Secure Thoughts
雷峰网
雷峰网
S
Security @ Cisco Blogs
T
The Exploit Database - CXSecurity.com
The Cloudflare Blog
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
阮一峰的网络日志
阮一峰的网络日志

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程
Kubernetes 之网络隔离(内附十多种使用场景)
微信公众号 · 2021-05-18 · via 陈少文的网站

Please enable Javascript to view the contents

1. Kubernetes 中的网络隔离

Kuberntes 自 1.3 引入了 Network Policy(网络策略) ,通过 ipBlock、podSelector、namespaceSelector 定义实体,控制其 From(Ingress)、To(Egress)的流量行为。

但 Kubernetes 只是定义了网络策略,具体实现依赖网络插件。目前,Calico、Cilium、Weave Net 等网络插件都支持网络隔离功能。

不同的 Kubernetes 版本对网络隔离支持的程度不一样。1.3~1.6 需要在 kube-apiserver 中开启 extensions/v1beta1/networkpolicies ,1.7 之后可以直接使用,1.8 新增了 Egress 、IPBlock 支持。

如果没有配置任何网络策略,默认情况下流量行为将没有任何限制。

2. 网络隔离对象的字段属性

下面是官方文档中的示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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

为了更直观地看到网络策略的组成,我画了一张示意图:

一个 NetworkPolicy 包含四个部分:

  • 需要控制的 Pods
  • 策略类型,Ingress、Egress 可选
  • Ingress 策略,包括 Entity 和端口、协议定义
  • Egress 策略,包括 Entity 和端口、协议定义

其中的 Entity 有三种类型可选,ipBlock 指定一个 IP 范围,namespaceSelector 指定匹配的命名空间,podSelector 指定匹配的 Pods 。

如果针对同一个实体,定义了多个 NetworkPolicy,那么命中其中一项即可通行。

3. 网络隔离示例

在 Ingress 和 Egress 的配置过程中会遇到两个特殊对象 []{}。如果是 [],那么表示不指向任何实体,通常用于禁用流量;而 {} 表示全部实体,通常用于放行流量。

另外一个值得注意的地方是,列表表示或的关系。

1
2
3
4
5
6
egress:
  - ports:
      - port: 443
        protocol: TCP
  - to:
      - namespaceSelector: {}

表示允许全部的 443 端口 TCP 流量,同时允许全部命名空间的任意端口流量。

1
2
3
4
5
6
egress:
  - ports:
      - port: 443
        protocol: TCP
    to:
      - namespaceSelector: {}

表示允许指向全部命名空间的 443 端口 TCP 流量。

3.1 拒绝访问 Pod 的全部流量

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --labels app=web --expose --port 80
  • 运行一个临时的 Pod 测试网络

验证默认情况下,Kubernetes 对流量没有进行限制。

1
2
3
4
5
6
7
kubectl run --generator=run-pod/v1 --rm -i -t --image=alpine test-$RANDOM -- sh

/ # wget -qO- http://web
<!DOCTYPE html>
<html>
<head>
...
  • 创建网络策略

包含 app=web 标签的 Pods 将拒绝全部访问流量。Ingress 为 [] 的含义是匹配的实体为空。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-deny-all
spec:
  podSelector:
    matchLabels:
      app: web
  ingress: []
EOF
  • 测试网络策略
1
2
3
4
kubectl run --generator=run-pod/v1 --rm -i -t --image=alpine test-$RANDOM -- sh

/ # wget -qO- --timeout=2 http://web
wget: download timed out
  • 清理环境
1
2
3
kubectl delete pod web
kubectl delete service web
kubectl delete networkpolicy web-deny-all

3.2 仅允许指定的 Pods 访问应用

  • 创建负载
1
kubectl run --generator=run-pod/v1 apiserver --image=nginx --labels app=bookstore,role=api --expose --port 80
  • 创建网络策略

仅允许包含标签 app=bookstore 的 Pods 访问应用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: api
  ingress:
  - from:
      - podSelector:
          matchLabels:
            app: bookstore
EOF
  • 测试网络策略
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://apiserver
wget: download timed out
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --rm -i -t --image=alpine --labels app=bookstore,role=frontend -- sh
/ # wget -qO- --timeout=2 http://apiserver
<!DOCTYPE html>
<html><head>
  • 清理环境
1
2
3
kubectl delete pod apiserver
kubectl delete service apiserver
kubectl delete networkpolicy api-allow

3.3 允许访问 Pod 的全部流量

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --labels=app=web --expose --port 80
  • 创建网络策略

Ingress 设置为 {} 空的含义是允许全部来源。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-all
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - {}
EOF
  • 测试网络策略
1
2
3
4
5
kubectl run --generator=run-pod/v1 test-$RANDOM --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web
<!DOCTYPE html>
<html><head>
  • 清理环境
1
2
kubectl delete pod,service web
kubectl delete networkpolicy web-allow-all

3.4 拒绝其他命名空间的访问流量

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --namespace default --image=nginx --labels=app=web --expose --port 80
  • 创建网络策略

仅允许 default 命名空间内的 Pods 相互访问,不允许其他命名空间的 Pods 访问。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: default
  name: deny-from-other-namespaces
spec:
  podSelector:
    matchLabels:
  ingress:
  - from:
    - podSelector: {}
EOF
  • 测试网络策略
1
2
3
4
5
kubectl create namespace foo
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=foo --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out
1
2
3
4
5
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=default --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
  • 清理环境
1
2
3
4
kubectl delete pod web
kubectl delete service web
kubectl delete networkpolicy deny-from-other-namespaces
kubectl delete namespace foo

3.5 允许全部命名空间访问指定的 Pods

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --namespace default --labels=app=web --expose --port 80
  • 创建网络策略

仅允许 default 命名空间下,标签为 app=web 的 Pod 被访问。default 下的其他 Pod 不允许被访问。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  namespace: default
  name: web-allow-all-namespaces
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector: {}
EOF
  • 测试网络策略
1
2
3
4
5
6
7
kubectl create namespace secondary
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=secondary --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
<head>
  • 清理环境
1
2
3
4
kubectl delete pod web -n default
kubectl delete service web -n default
kubectl delete networkpolicy web-allow-all-namespaces -n default
kubectl delete namespace secondary

3.6 允许指定命名空间访问指定的 Pods

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --labels=app=web --expose --port 80
  • 创建测试命名空间
1
2
3
4
kubectl create namespace dev
kubectl label namespace/dev purpose=testing
kubectl create namespace prod
kubectl label namespace/prod purpose=production
  • 创建网络策略

仅允许命名空间包含标签 purpose=production 的 Pod 访问指定的应用,其他应用不允许访问。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-prod
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          purpose: production
EOF
  • 测试网络策略
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=dev --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out
1
2
3
4
5
6
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=prod --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
<head>
  • 清理环境
1
2
3
4
kubectl delete networkpolicy web-allow-prod
kubectl delete pod web
kubectl delete service web
kubectl delete namespace {prod,dev}

3.7 仅允许指定空间中的指定 Pod 访问应用

此功能需要 Kubernetes 1.11 及以上版本。

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --labels=app=web --expose --port 80
  • 创建命名空间
1
2
kubectl create namespace other
kubectl label namespace/other team=operations
  • 创建网络策略

命名空间和 Pods 需要同时满足要求时,才可以访问指定的应用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: web-allow-all-ns-monitoring
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
    - from:
      - namespaceSelector:     # chooses all pods in namespaces labelled with team=operations
          matchLabels:
            team: operations
        podSelector:           # chooses pods with type=monitoring
          matchLabels:
            type: monitoring
EOF
  • 测试网络策略
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --labels type=monitoring --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out
1
2
3
4
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=other --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
wget: download timed out
1
2
3
4
5
6
kubectl run --generator=run-pod/v1 test-$RANDOM --namespace=other --labels type=monitoring --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://web.default
<!DOCTYPE html>
<html>
<head>
  • 清理环境
1
2
3
4
kubectl delete networkpolicy web-allow-all-ns-monitoring
kubectl delete namespace other
kubectl delete pod web
kubectl delete service web

3.8 仅允许访问 Pods 的指定端口

  • 创建负载
1
kubectl run --generator=run-pod/v1 apiserver --image=ahmet/app-on-two-ports --labels=app=apiserver

这个应用将在 8000 端口返回 Hello 响应,而在 5000 端口返回监控数据。下面将 Pod 暴露到 Service 上:

1
kubectl create service clusterip apiserver --tcp 8001:8000 --tcp 5001:5000
  • 创建网络策略

仅允许包含标签 role=monitoring 的 Pod 访问应用的 5000 端口。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: api-allow-5000
spec:
  podSelector:
    matchLabels:
      app: apiserver
  ingress:
  - ports:
    - port: 5000
    from:
    - podSelector:
        matchLabels:
          role: monitoring
EOF
  • 测试网络策略
1
2
3
4
5
6
7
kubectl run --generator=run-pod/v1 test-$RANDOM --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
wget: download timed out
1
2
3
4
5
6
7
8
9
kubectl run --generator=run-pod/v1 test-$RANDOM --labels=role=monitoring --rm -i -t --image=alpine -- sh

/ # wget -qO- --timeout=2 http://apiserver:8001
wget: download timed out

/ # wget -qO- --timeout=2 http://apiserver:5001/metrics
http.requests=1
go.goroutines=5
go.cpus=4
  • 清理环境
1
2
3
kubectl delete pod apiserver
kubectl delete service apiserver
kubectl delete networkpolicy api-allow-5000

3.9 使用多个选择器指定访问来源

  • 创建负载
1
kubectl run --generator=run-pod/v1 db --image=redis:4 --port 6379 --expose --labels app=bookstore,role=db
  • 创建网络策略

可以同时配置多个允许的来源,只需要其中一个匹配即可访问。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cat <<EOF | kubectl apply -f -
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: redis-allow-services
spec:
  podSelector:
    matchLabels:
      app: bookstore
      role: db
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: bookstore
          role: search
    - podSelector:
        matchLabels:
          app: bookstore
          role: api
    - podSelector:
        matchLabels:
          app: inventory
          role: web
EOF
  • 测试网络策略
1
2
3
4
5
6
kubectl run --generator=run-pod/v1 test-$RANDOM --labels=app=inventory,role=web --rm -i -t --image=alpine -- sh

/ # nc -v -w 2 db 6379
db (10.59.242.200:6379) open

(works)
1
2
3
4
5
6
kubectl run --generator=run-pod/v1 test-$RANDOM --labels=app=other --rm -i -t --image=alpine -- sh

/ # nc -v -w 2 db 6379
nc: db (10.59.252.83:6379): Operation timed out

(traffic blocked)
  • 清理空间
1
2
3
kubectl delete pod db
kubectl delete service db
kubectl delete networkpolicy redis-allow-services

3.10 禁止 Pod 的出口流量

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --port 80 --expose --labels app=web
  • 创建网络策略

禁止包含标签 app=foo 的 Pod 任何出口流量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: foo-deny-egress
spec:
  podSelector:
    matchLabels:
      app: foo
  policyTypes:
  - Egress
  egress: []
EOF
  • 测试网络策略
1
2
3
4
5
6
7
kubectl run --generator=run-pod/v1 --rm --restart=Never --image=alpine -i -t -l app=foo test -- ash

/ # wget -qO- --timeout 1 http://web:80/
wget: bad address 'web:80'

/ # wget -qO- --timeout 1 http://www.example.com/
wget: bad address 'www.example.com'
  • 清理环境
1
2
kubectl delete pod,service web
kubectl delete networkpolicy foo-deny-egress

3.11 拒绝外部出口流量

  • 创建负载
1
kubectl run --generator=run-pod/v1 web --image=nginx --port 80 --expose --labels app=web
  • 创建网络策略

允许包含标签 app=foo 的 Pods 访问全部 53 端口的服务,同时允许访问全部命名空间的应用。这里的 ports 和 to 是或的关系。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: foo-deny-external-egress
spec:
  podSelector:
    matchLabels:
      app: foo
  policyTypes:
  - Egress
  egress:
  - ports:
    - port: 53
      protocol: UDP
    - port: 53
      protocol: TCP
  - to:
    - namespaceSelector: {}
EOF
  • 测试网络策略
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl run --generator=run-pod/v1 --rm --restart=Never --image=alpine -i -t -l app=foo test -- ash

/ # wget -O- --timeout 1 http://web:80
Connecting to web (10.59.245.232:80)
<!DOCTYPE html>
<html>

/ # wget -O- --timeout 1 http://www.example.com
Connecting to www.example.com (93.184.216.34:80)
wget: download timed out
  • 清理环境
1
2
kubectl delete pod,service web
kubectl delete networkpolicy foo-deny-external-egress

4. 参考


微信公众号