【发布时间】:2020-01-19 23:24:20
【问题描述】:
我想在 Kubernetes 集群中设计一个network policies,以便在模块之间进行细粒度的通用访问控制。
我已经准备了一个包含 2 个清单的 Kubernetes 设置:
- 2-container nginx pod,有2个端口监听并返回一些通用数据,一个是80端口,另一个是81
- 我有 3 个带有 2 个开/关标签的控制台 pod:“allow80”和“allow80”。因此,如果存在“allow80”,console pod 可以通过服务入口点 80 端口访问双 nginx。同样适用于端口 81
我有 3 个控制台 pod:
- console-full - 访问端口 80 和 81,[allow80,allow81]
- 控制台部分 - 端口 80 - 开启,81 - 关闭,[allow80]
- 控制台禁止访问 - 80 和 81 都 - 受限 []
测试设置。它将在“net-policy-test”命名空间中创建所有必要的组件。
创建:
kubectl apply -f net_policy_test.yaml
清理:
kubectl delete -f net_policy_test.yaml
apiVersion: v1
kind: Namespace
metadata:
name: net-policy-test
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx1
namespace: net-policy-test
data:
index.html: |
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance1</title>
</head>
<body>
<h1>nginx, instance 1, port 80</h1>
</body>
</html>
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx2
namespace: net-policy-test
data:
index.html: |
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance2</title>
</head>
<body>
<h1>nginx, instance 2, port 81</h1>
</body>
</html>
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf1
namespace: net-policy-test
data:
default.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf2
namespace: net-policy-test
data:
default.conf: |
server {
listen 81;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dual-nginx
namespace: net-policy-test
labels:
app: dual-nginx
environment: test
spec:
replicas: 1
selector:
matchLabels:
app: dual-nginx
template:
metadata:
labels:
app: dual-nginx
name: dual-nginx
spec:
containers:
- image: nginx
name: nginx1
ports:
- name: http1
containerPort: 80
volumeMounts:
- name: html1
mountPath: /usr/share/nginx/html
- name: config1
mountPath: /etc/nginx/conf.d
- image: nginx
name: nginx2
ports:
- name: http2
containerPort: 81
volumeMounts:
- name: html2
mountPath: /usr/share/nginx/html
- name: config2
mountPath: /etc/nginx/conf.d
volumes:
- name: html1
configMap:
name: nginx1
- name: html2
configMap:
name: nginx2
- name: config1
configMap:
name: nginx-conf1
- name: config2
configMap:
name: nginx-conf2
---
apiVersion: v1
kind: Service
metadata:
name: dual-nginx
namespace: net-policy-test
spec:
selector:
app: dual-nginx
ports:
- name: web1
port: 80
targetPort: http1
- name: web2
port: 81
targetPort: http2
---
# this console deployment will have full access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: console-full
namespace: net-policy-test
labels:
app: console-full
environment: test
nginx-access: full
spec:
replicas: 1
selector:
matchLabels:
app: console-full
template:
metadata:
labels:
app: console-full
name: console-full
allow80: "true"
allow81: "true"
spec:
containers:
- image: alpine:3.9
name: main
command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]
---
# this console deployment will have partial access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: console-partial
namespace: net-policy-test
labels:
app: console-partial
environment: test
nginx-access: partial
spec:
replicas: 1
selector:
matchLabels:
app: console-partial
template:
metadata:
labels:
app: console-partial
name: console-partial
allow80: "true"
spec:
containers:
- image: alpine:3.9
name: main
command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]
---
# this console deployment will have no access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: console-no-access
namespace: net-policy-test
labels:
app: console-no-access
environment: test
nginx-access: none
spec:
replicas: 1
selector:
matchLabels:
app: console-no-access
template:
metadata:
labels:
app: console-no-access
name: console-no-access
spec:
containers:
- image: alpine:3.9
name: main
command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]
还有政策, 再次申请:
kubectl apply -f policies.yaml
清理:
kubectl delete -f policies.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: nginx-restrict80
spec:
podSelector:
matchLabels:
app: "dual-nginx"
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
allow80: "true"
ports:
- protocol: TCP
port: 80
- from:
- podSelector:
matchLabels:
allow81: "true"
ports:
- protocol: TCP
port: 81
如果我只为一个端口留下“来自”的一个条件,它会按预期工作。我有或没有端口访问权限,取决于相应的标签是否存在,allow80 或 allow81
如果存在 2 个条件,则部分 pod 可以访问端口 80 和 81:
- 切换到正确的命名空间:
kubectl config set-context --current --namespace=net-policy-test
- 检查标签:
kubectl get pods -l allow80
NAME READY STATUS RESTARTS AGE
console-full-78d5499959-p5kbb 1/1 Running 1 4h14m
console-partial-6679745d79-kbs5w 1/1 Running 1 4h14m
kubectl get pods -l allow81
NAME READY STATUS RESTARTS AGE
console-full-78d5499959-p5kbb 1/1 Running 1 4h14m
- 检查来自 pod "console-partial-..." 的访问,它应该访问端口 80 而不是 81:
kubectl exec -ti console-partial-6679745d79-kbs5w curl http://dual-nginx:80
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance1</title>
</head>
<body>
<h1>nginx, instance 1, port 80</h1>
</body>
</html>
kubectl exec -ti console-partial-6679745d79-kbs5w curl http://dual-nginx:81
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance2</title>
</head>
<body>
<h1>nginx, instance 2, port 81</h1>
</body>
</html>
部分访问 pod 可以访问端口 80 和 81。
Pod,没有标签 (console-no-access-),无法访问任一端口,这是预期的
它类似于本演示文稿中描述的内容:Youtube, Securing Cluster Networking with Network Policies - Ahmet Balkan, Google。因此,至少有一个标志“allow80”或“allow81”可以访问所有内容。怎么会?
现在,问题:
- 这是预期的行为吗?
- 如何制作简单的基于标志的访问控制,以实现自动化或传递给管理员,谁可以轻松地大量生产这些?
【问题讨论】:
-
我已经应用了你的清单,所有东西都可以访问任何地方。
-
您需要让您的 Kubernetes 集群支持网络策略。如果没有,它们就没有效果。在我的具体情况下,我使用以下命令行键创建了一个 Azure 集群:
az aks create ... --network-plugin azure --network-policy azure
标签: kubernetes firewall kubernetes-networkpolicy