为什么写这篇文章
最近在整理K8s安全相关的资料,发现大部分文章都是在罗列"应该做什么",但很少有人告诉你"为什么要做"以及"怎么做会踩坑"。
我自己在生产环境中踩过不少坑,有的甚至导致了线上事故。今天就把这些经验分享出来,希望能帮大家少走一些弯路。
💡 本文特色:每个配置都有真实的踩坑经历,不是简单的复制粘贴
坑1:RBAC没配好,实习生删了生产环境
问题描述:
我们刚上K8s的时候,为了方便,给了所有开发人员管理员权限。当时觉得,都是自己人,应该没问题。
结果有个实习生在测试命令的时候,不小心执行了:
kubectl delete namespace production
直接把生产环境删了...
解决方案:
# 给普通开发人员只读权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
# 绑定给具体用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: developer # 换成你的用户名
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
怎么验证配置对不对:
# 用developer用户测试
kubectl auth can-i list pods --as=developer
# 应该输出:yes
kubectl auth can-i delete pods --as=developer
# 应该输出:no
我的思考:
RBAC配置看起来麻烦,但比起出事后的损失,这点麻烦算什么呢?建议一开始就配好,别等到出事了才后悔。
坑2:容器以root运行,被扫描出高危漏洞
问题描述:
我们有个Java应用,容器启动后默认是root用户。当时也没在意,觉得反正容器是隔离的。
结果安全扫描发现,攻击者可以利用这个漏洞逃逸到宿主机...
解决方案:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true # 强制非root运行
runAsUser: 1000 # 指定用户ID
fsGroup: 2000
containers:
- name: app
image: your-app:latest
securityContext:
allowPrivilegeEscalation: false # 禁止提权
readOnlyRootFilesystem: true # 只读文件系统
capabilities:
drop:
- ALL # 去掉所有权限
add:
- NET_BIND_SERVICE # 只保留绑定端口的权限
踩坑经验:
一开始我们设置了readOnlyRootFilesystem: true,结果应用启动失败,因为它需要写日志到本地目录。
怎么解决的?用emptyDir挂载一个临时目录:
volumes:
- name: tmp-dir
emptyDir: {}
containers:
- name: app
volumeMounts:
- name: tmp-dir
mountPath: /tmp
我的思考:
容器安全不是可选项,而是必须项。虽然配置起来有点麻烦,但能避免很多潜在的风险。
坑3:Pod之间随便通信,一个被攻全军覆没
问题描述:
我们的微服务架构里有十几个服务,默认情况下它们可以互相访问。
有一次,一个测试环境的服务被攻破,攻击者横向移动,直接打到了生产数据库...
解决方案:用NetworkPolicy限制Pod通信
# 先禁止所有通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 再按需开放
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-web-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: web # 只允许web访问api
ports:
- protocol: TCP
port: 8080
效果:配置完后,只有web可以访问API,其他服务都被隔离了。虽然配置过程有点麻烦,但安全感直接拉满。
我的思考:
最小权限原则在K8s中特别重要。不要觉得"都是自己人"就放松警惕,攻击者可能就在你身边。
坑4:Secret直接写在配置文件里,差点被Git记录
问题描述:
当时为了赶进度,直接把数据库密码写在了deployment.yaml里,然后提交到了Git仓库。
后来被安全扫描发现了,幸好还没上线...
解决方案:用Sealed Secrets加密存储
# 安装Sealed Secrets
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
# 加密Secret
echo -n 'my-database-password' | kubectl create secret generic db-password \
--from-file=password=/dev/stdin \
--dry-run=client -o yaml | kubeseal -o yaml > sealed-secret.yaml
# 使用时会自动解密
血泪教训:
- 永远不要把Secret提交到Git
- 用加密存储方案
- 定期轮换密钥
我的思考:
Secret管理是K8s安全中最容易被忽视的一环。很多团队为了方便,直接把密码写在配置文件里,这是非常危险的行为。
坑5:镜像有漏洞都不知道,出了事才后悔
问题描述:
我们有个老项目,用的是两年前的nginx镜像。当时觉得能跑就行,没去管它。
结果安全扫描发现这个镜像有十几个高危漏洞...
解决方案:在CI/CD里集成镜像扫描
# GitHub Actions示例
- name: 扫描镜像漏洞
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
format: 'table'
exit-code: '1' # 发现高危漏洞就失败
severity: 'CRITICAL,HIGH'
建议:
- 定期扫描所有在用镜像
- 发现漏洞及时更新
- 建立镜像更新机制
我的思考:
镜像安全是K8s安全的基础。如果基础镜像有漏洞,上面跑的所有服务都是不安全的。
坑6:没有审计日志,出事了查不到
问题描述:
有一次线上出了问题,我们怀疑是人为操作导致的,但查了半天日志,什么都没查到。
后来才知道,K8s默认没开审计日志...
解决方案:启用审计日志
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 记录所有对Pod的操作
- level: Metadata
resources:
- group: ""
resources: ["pods", "services"]
# 重点记录Secret的操作
- level: RequestResponse
resources:
- group: ""
resources: ["secrets", "configmaps"]
verbs: ["create", "update", "delete"]
然后用ELK收集分析:
# 安装Filebeat收集日志
helm install filebeat elastic/filebeat
# 用Kibana查看
# 访问 http://localhost:5601
我的思考:
审计日志是事后追溯的关键。虽然配置起来有点麻烦,但出事时能帮你快速定位问题。
我的安全检查清单
每次部署前,我都会过一遍这个清单:
部署前检查
- 镜像扫描过了吗?
- Secret加密存储了吗?
- RBAC配好了吗?
- NetworkPolicy启用了吗?
- 资源限制设了吗?
- 审计日志开了吗?
运行时检查
- 监控告警配了吗?
- 日志收集了吗?
- 定期审计做了吗?
每月必做
- 检查镜像漏洞
- 更新依赖版本
- 审查RBAC权限
- 检查安全配置
写在最后
Kubernetes安全是个持续的过程,不是配一次就完事了。
我建议:
- 从简单的开始 - 先把RBAC和NetworkPolicy配好
- 逐步完善 - 每次迭代加一点安全措施
- 持续监控 - 建立告警,及时发现问题
- 定期审计 - 每月检查一次安全配置
安全确实麻烦,但比起出事后的损失,这点麻烦算什么呢?
你遇到过哪些K8s安全问题?欢迎在评论区分享你的经验!