gVisor介绍
所知,容器的应用程序可以直接访问Linux内核的系统调用,容器在安全隔离上还是比较弱,虽然内核在不断的增强自身的安全特性,但由于内核自身代码极端复杂,CVE漏洞层出不穷。
所以要想减少这方面安全风险,就是做好安全隔离,阻断容器内程序对物理机内核的依赖。
Google开源的一种gVisor容器沙箱技术就是采用这种思路,gVisor隔离容器和内核之间访问,提供了大部分内核的系统调用,巧妙的将容器内进程的系统调用转为给gViosr的访问。
gVisor兼容OCI,与Docker和K8s无缝集成,很方便使用
容器中的OCI指的是Open Container Initiative即开放容器计划
项目地址:https://github.com/goole/gvisor
和其他安全防范措施对比:
seccomp:系统调用过滤
app armor:限制容器里进程访问文件系统,网络等权限
capability:限制容器进程拥有的访问内核能力(逻辑上对系统调用做了一个分组)
非root用户运行容器,减少容器进程拥有的能力
防止容器进程拥有大权限,但只是一定程度,无法避免容器中的进程访问linux内核,而gVisor是在容器和内核之间。避免了容器之间访问内核
缺点:增加对系统调用时间,和开销。但技术相对成熟,消耗不大。阿里云部分产品已加入容器沙箱机制
gVisor架构:
gVisor由3个组件构成:
Runsc是一种Runtime引擎,负责容器的创建与销毁
Sentry负责容器内程序的系统调用处理
Gofer负责文件系统的操作代理,IO请求都会由他转接到HOST上
gVisor与Docker集成:
gVisor内核要求:Linux 3.17+
如果用的是CentOS7则需要升级内核,Ubuntu不需要。
CentOS7内核升级步骤(一个节点也行):
【】rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
【】rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
【】yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml –y
【】awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg #查看可用内核
【】grub2-set-default 0
【】reboot
【】uname -r
https://blog.csdn.net/inthat/article/details/117074180
Centos 7 rpm升级到指定内核
rpm 去
https://pkgs.org/download/kernel(list_del) 找 kernel-xxx.rpm
https://pkgs.org/download/kernel-devel 找 kernel-devel-xxxx.rpm
yum -y install kernel-3.10.0-1160.el7.x86_64 kernel-devel-3.10.0-1160.el7.x86_64 && grub2-set-default 0 && reboot
下载指定版本用rpm -Uvh安装或者用yum安装
1.准备二进制文件
【】sha512sum -c runsc.sha512
【】rm -f *.sha512
【】chmod a+rx runsc containerd-shim-runsc-v1
【】mv runsc containerd-shim-runsc-v1 /usr/local/bin
2、Docker配置使用gVisor
【】runsc install
# 查看加的配置/etc/docker/daemon.json
【】systemctl restart docker
参考文档:https://gvisor.dev/docs/user_guide/install/
使用runsc运行容器:
【】docker run -d --runtime=runsc nginx
使用dmesg验证
docker run --runtime=runsc -it nginx dmesg
进入容器与不指定runtime的容器对比,观察内核,发现vgisor会使用沙箱的独立内核
已经测试过的应用和工具:https://gvisor.dev/docs/user_guide/compatibility/
gVisor与Containerd集成:
1、准备配置(装docker时已经启用)
【】cat > /etc/sysctl.d/99-kubernetes-cri.conf << EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
【】sysctl -system
2、安装
【】cd /etc/yum.repos.d
【】wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
【】yum install -y containerd.io #此处执行这一条就行前面的都配置好了
装好之后停掉docker只用containerd做容器运行时
3、修改配置文件
• pause镜像地址
• Cgroup驱动改为systemd
• 增加runsc容器运行时
• 配置docker镜像加速器
3、修改配置文件
#创建配置文件并修改
https://gvisor.dev/docs/user_guide/containerd/quick_start/
【】mkdir -p /etc/containerd
【】containerd config default > /etc/containerd/config.toml
vi /etc/containerd/config.toml
...
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.2"
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
runtime_type = "io.containerd.runsc.v1"
#runtime类型,增加了runsc是gVios
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://b9pmyelo.mirror.aliyuncs.com"]
...
【】systemctl stop docker
【】systemctl stop docker.socket
【】systemctl restart containerd
4、配置kubelet使用containerd
【】vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd
上面的配置中我们增加了两个参数,--container-runtime
参数是用来指定使用的容器运行时的,可选值为 docker
或者 remote
,默认是 docker
,由于我们这里使用的是 containerd 这种容器运行时,所以配置为 remote
值(也就是除 docker
之外的容器运行时都应该指定为 remote
),然后第二个参数 --container-runtime-endpoint
是用来指定远程的运行时服务的 endpiont 地址的,在 Linux 系统中一般都是使用 unix 套接字的形式,比如这里我们就是指定连接 containerd 的套接字地址
【】systemctl restart kubelet
5、验证
kubectl get node -o wide
#注意之前docker创建的容器containerd无法使用会导致该节点上的pod异常,会重新调度,并下载镜像。非平滑切换
K8s使用gVisor运行容器:
gvisor与containerd比docker集成更好,K8S目前没有适配docker的gvisor
RuntimeClass是一个用于选择容器运行时配置的特性,容器运行时配置用于运行Pod中的容器。
创建RuntimeClass:
创建pod:
依次应用
kubectl get pod nginx-gvisor -o wide
kubectl exec nginx-gvisor -- dmesg