隔离中间件服务
示例
首先创建该项目所用的 Namespace
切换默认命名空间
隔离中间件服务
- 有一个项目,它有自己数据库 MySQL 和缓存 Redis 中间件,只希望这个项目的应用能够访问该中间件
- 假如有一个项目需要通过 Ingress 进行对外发布,想要除了 Ingress 外,其他任何 Namespace 下的 Pod 都不能访问该项目。
假设有一个项目叫 nw-demo,里面部署了三个微服务,分别是 MySQL、Redis 和 Nginx。现需要对 MySQL、Redis、Nginx 进行隔离,分别实现如下效果:
- MySQL、Redis 只能被该 Namespace 下的 Pod 访问;
- Nginx 可以被
ingress-nginx
命名空间下的 Pod 和该 Namespace 下的 Pod 访问;
创建 MySQL 服务,MySQL 以容器启动时,必须配置 root 的密码,或者设置密码为空,所以需要设置一个 MYSQL_ROOT_PASSWORD
的变量:
kubectl create deploy mysql --image=docker.io/library/mysql:8.0.31
kubectl set env deploy/mysql MYSQL_ROOT_PASSWORD=mysql
创建 redis 服务
确认容器是否启动:
> kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-664f9868b-5s6g9 1/1 Running 0 14s 10.160.199.5 dev-chhli <none> <none>
redis-6466b54d6d-8zpt6 0/1 ContainerCreating 0 69s 10.160.199.10 dev-chhli <none> <none>
在没有配置任何网络策略时,测试下网络的连通性,可以在任意 Kubernetes 节点上执行 telnet 命令:
# 进行测试的IP和Pod名字可能与实际测试的不一致,需要与实际情况为准
> telnet 10.160.199.5 3306
Trying 10.160.199.5...
Connected to 10.160.199.5.
Escape character is '^]'.
> telnet 10.160.199.10 6379
Trying 10.160.199.10...
Connected to 10.160.199.10.
Escape character is '^]'.
然后根据标签配置网络策略,本示例的配置将MySQL和Redis进行了拆分,配置了两个网络策略,当然也可以给两个Pod配置一个相同的标签,这样就可以使用同一个网络策略进行限制
但是在生产环境中,并不推荐使用同一个网络策略,因为有时候需要更细粒度的策略,同一个网络策略可能会有局限性,也会导致配置失败,所以本示例采用分开的网络策略进行配置:
mysql-nw.yaml
mysql-np 是对具有app=mysql
标签的 Pod 进行管理
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-np
namespace: nw-demo
spec:
podSelector:
matchLabels:
app: mysql
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
access-nw-mysql-redis: "true"
ports:
- protocol: TCP
port: 3306
redis-nw.yaml
redis-np 是对具有app=redis
标签的 Pod 进行管理
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: redis-np
namespace: nw-demo
spec:
podSelector:
matchLabels:
app: redis
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
access-nw-mysql-redis: "true"
ports:
- protocol: TCP
port: 6379
但是需要注意的是该网络策略的 ingress from 是以 namespaceSelector 的标签进行匹配的,并非 podSelector,或者是两者的结合。
因为在生产环境中,同一个 Namespace 下可能会有很多不同类型、不同标签的 Pod,并且它们可能并不具有一个相同的标签,所以如果通过 podSelector 进行选择,可能会比较麻烦,因为 Pod 一旦创建,对其标签的修改是很不方便的(apps/v1 一旦创建就不可修改)
而使用 namespaceSelector 另一个好处是,可以很方便的对某个 Namespace 下的 Pod 进行管控,直接给指定 Namespace 添加标签即可,当然,如果需要更细粒度的管控,也可以结合 podSelector 使用
创建后宿主机和任何 Pod 都已不能访问该 Namespace 下的 MySQL 和 Redis
> telnet 10.160.199.5 3306
Trying 10.160.199.5...
> telnet 10.160.199.10 6379
Trying 10.160.199.10...
在 nw-demo 命名空间下创建一个用于测试连通性的工具,然后进行测试,也是不能访问该服务的:
由于之前的 from 配置的是 namespaceSelector,所以如果想要某一个 Namespace 下的 Pod 能够访问,直接给该 Namespace 添加一个 NetworkPolicy 中配置的标签即可,比如允许 nw-demo
命名空间下的所以 Pod 访问该 NetworkPolicy 隔离的服务:
使用 nw-demo
命名空间下的 debug-tools 再次测试:
此时 nw-demo
下的 Pod 已经可以访问 MySQL 和 Redis,可以对其他 Namespace 下的 Pod 进行测试,比如在 default 命名空间进行测试:
可以看到此时 default 命名空间下的 Pod 并不能访问 nw-demo
的服务,如果想要 MySQL 和 Redis 对 default 命名空间开放,只需要添加一个 access-nw-mysql-redis=true
的标签即可。
相对于传统架构,对中间件的访问限制,在 Kubernetes 中实现同样的效果,可能配置更加方便且易于管理