通用数据库审计简介
通用数据库审计是日志服务提供的一种轻量级、低成本数据库安全方案,在之前的文章《自建数据库没有审计方案?试试这套轻量级低成本方案》中介绍了通过部署Logtail和Packetbeat在应用服务器或者数据库服务器上的方法抓取数据库操作行为流量,从而实现数据库审计数据的采集。日志服务提供了开箱即用的审计报表和告警配置。
随着云原生技术的成熟,越来越多的应用部署在云原生环境,云原生环境的动态及灵活性给抓包工具带来了一些困难,本文主要介绍在K8s环境下如何部署这套轻量级、低成本审计方案。
K8s场景下网络介绍
容器网络
众所周知,容器是一种操作系统的虚拟化环境,本质上是与系统其它部分隔离的一个或者一组进程。其实现主要借助了Cgroup和Namespace(命名空间)两个内核特性,其中Cgroup做资源的控制,Namespace做访问的隔离。
每个容器可以有自己单独的命名空间,命名空间下可以有CPU、PID、文件系统、网络、内存等资源,各类资源的命名空间可以让容器中的应用可以独立运行。
网络命名空间可以实现容器的网络隔离,在容器的命名空间内可以看到一个完整的网络协议栈的视图。包含网络设备接口、协议栈等。docker容器主要借助Linux veth pair和Bridge网桥来实现容器与Host的通信、容器与容器的通信。
如下图所示,Host宿主机中有两个容器,每个容器各自一个网络设备eth0,然后容器中的eth0通过对应的veth pair与宿主机进行通信,veth1和veth2又挂载在具有IP地址的网桥Docker0上。在容器环境下,看到的网络设备是自己的eth0;在Host宿主机环境中看到的是veth1、veth2、docker0和eth0;
在容器环境中的应用的网络包的进出是会通过veth pair;所以对于容器的网络包抓取可以通过veth pair的两端,一端是容器内的eth0,一段是宿主机内的veth1。
K8s网络
在K8s环境中,网络架构更加复杂,CNI(Container Network Interface)作为一个标准的通用接口,用于连续容器管理系统和网络插件,K8s需要处理不同容器间的通信、跨主机的通信。业界也有一些基于CNI的容器网络解决方案,如flannel、calico、weave、Terway等。
一个典型的CNI插件的开发流程如下:
图片来自溪恒文章。
与容器网络类似,K8s的CNI插件也需要在宿主机将veth pair的另一端暴露出来,这样pod中的eth0流量可以通过veth1来与外界互通,只不过容器网络中eth0是在一个容器的命名空间下,在K8s中,一个Pod中可以有多个容器,多个容器共享同一个网络命名空间。所以在宿主机上还是可以通过容器的对端veth1来对pod内的网络流量就行抓包。
K8s下通用数据库审计实践
日志服务通用数据库审计是通过网络流量抓取来收集数据库的操作行为,原理可以参考《自建数据库没有审计方案?试试这套轻量级低成本方案》,具体使用方法可以参考通用数据库审计。在K8s环境下由于不同场景的需求,这里以Packetbeat转包程序为例提供几种云原生的方式来部署抓包程序。
部署方式
通过上述K8s场景下网络的介绍,可以得知,有两种方式可以对Pod的网络进行抓包;
- 抓包程序与容器同属于同一个网络命名空间下。
- 抓包程序部署在容器的Host宿主机上,通过veth pair在宿主机上的一端进行抓包。
上述两种方式也就对应了K8s下的两种部署方式:
- Sidecar:由于sidecar天生与业务容器在同一个Pod下,共享网络命名空间,抓包程序作为sidecar部署是可以抓取到下业务容器的流量。
- Daemonset:由于Daemonset在每台宿主机上都会部署一个,通过让Daemonset拥有网络监听的能力,Daemonset就可以通过宿主机上的veth pair的一端来对业务容器进行抓包。
审计数据上报
上面可以看出可以通过sidecar或者daemonset的方式来部署抓包程序,抓包程序可以选择Packetbeat,Packetbeat可以输出到各类output,这里我们可以选择Kafka协议,将抓取到的流量数据通过Kafka上传都日志服务的Logstore。具体配置可以参考使用Kafka协议上传日志。
部署实践
接下来介绍下部署Sidecar和Daemonset的部署方式,两者都是用来部署抓包程序,可以根据业务需求选择其中一种。两者的部署都依赖Configmap的配置,包含如下流程:
- 前提已经开启通用数据库审计任务配置,配置可参考通用数据库审计。
- 配置configmap,主要包含packetbeat.yml的配置。
- 部署packetbeat,步骤2可选Daemonset和Sidecar模式。
- 以下所有配置文件可参考github链接:https://github.com/panawala/k8s-general-db-audit
步骤1:
编辑packetbeat.yml
- packetbeat.flows用来抓取网络设备的所有流量,如果不需要可以设置enabled:false,以减少数据的传输。
- output.kafka的配置需要参考使用Kafka协议上传日志进行配置修改。需要替换其中的{project},{region},{ak}, {sk}。
- 其他详细的配置可以参考packetbeat官方配置,Configure Packetbeat。
packetbeat.interfaces.device any # Set `enabled: false` or comment out all options to disable flows reporting.packetbeat.flows timeout 30s period 10s packetbeat.protocolstype mysql ports 3306 3307output.kafka hosts"{project}.{region}.log.aliyuncs.com:10012" username"{project}" password"{ak}#{sk}" ssl.certificate_authorities topic'general-db-logstore' partition.round_robin reachable_only false required_acks1 compression gzip max_message_bytes1000000
创建configmap,通过文件方式创建configmap
kubectl create configmap packetbeat-config --from-file=packetbeat.yml=packetbeat.yml
步骤2选1:Daemonset模式
配置packetbeat-daemonset.yaml文件
- 需要开启hostNetwork,让daemonset可以看到host机器上的网络设备。
- 增加NET_ADMIN的capability来让daemonset可以监听网络设备的流量。
- 通过resources来限制CPU和内存的占用。
apiVersion apps/v1 kind DaemonSet metadata name packetbeat-daemonset namespace default spec selector matchLabels app packetbeat-daemonset template metadata name packetbeat-daemonset labels app packetbeat-daemonset spec restartPolicy Always hostNetworktrue containersname packetbeat image docker.elastic.co/beats/packetbeat8.1.0 resources limits cpu 500m memory 200Mi requests cpu 100m memory 200Mi command"/bin/sh""-c" args"/usr/share/packetbeat/packetbeat --strict.perms=false -c /etc/packetbeat/config/packetbeat.yml" securityContext capabilities add NET_ADMIN volumeMountsname packetbeat-config mountPath /etc/packetbeat/config terminationGracePeriodSeconds30 volumesname packetbeat-config configMap name packetbeat-config itemskey packetbeat.yml path packetbeat.yml
创建daemonset
kubectl apply -f packetbeat-daemonset.yaml
步骤2选1:Sidecar模式
创建packetbeat-sidecar.yaml文件
其中mysql-test容器为测试容器,请根据业务容器修改。
apiVersion apps/v1 kind Deployment metadata name packetbeat-sidecar namespace default spec selector matchLabels app packetbeat-sidecar template metadata name packetbeat-sidecar labels app packetbeat-sidecar spec restartPolicy Always containersname mysql-test image imega/mysql-client command"/bin/sh""-c" args"mysql --host='xxx' --user=xxx --password='xxx' --database=mysql --execute='show tables;'; sleep 6000"name packetbeat-sidecar image docker.elastic.co/beats/packetbeat8.1.0 command"/bin/sh""-c" args"/usr/share/packetbeat/packetbeat --strict.perms=false -c /etc/packetbeat/config/packetbeat.yml" securityContext capabilities add NET_ADMIN volumeMountsname packetbeat-config mountPath /etc/packetbeat/config volumesname packetbeat-config configMap name packetbeat-config itemskey packetbeat.yml path packetbeat.yml
创建sidecar
kubectl apply -f packetbeat-sidecar.yaml
参考
- 日志服务(SLS):https://www.aliyun.com/product/sls
- 自建数据库轻量级审计方案:https://developer.aliyun.com/article/872947
- 配置通用数据库审计:https://help.aliyun.com/document_detail/410521.html
- 使用Kafka协议上传日志:https://help.aliyun.com/document_detail/112902.html
- 从零开始入门 K8s | 理解 CNI 和 CNI 插件:https://developer.aliyun.com/article/748866
- Configure Packetbeat:https://www.elastic.co/guide/en/beats/packetbeat/current/configuring-howto-packetbeat.html
- 完整示例文件:https://github.com/panawala/k8s-general-db-audit
- 欢迎扫群加入阿里云-日志服务(SLS)技术交流
- 后续系列直播与培训视频会同步到B站,敬请留意