当前位置: 首页 > news >正文

杭州滨江网站建设公司网站模板库官网

杭州滨江网站建设公司,网站模板库官网,做网站设计用什么软件最好,广州网站建设studstu前言 Linux容器的本质,是一个被限制和隔离的进程。它通过Linux内核提供的命名空间(Namespaces)实现资源隔离,通过控制组(Cgroups)实现资源限制,通过联合文件系统(UnionFS&#xff0…

前言

Linux容器的本质,是一个被限制和隔离的进程。它通过Linux内核提供的命名空间(Namespaces)实现资源隔离,通过控制组(Cgroups)实现资源限制,通过联合文件系统(UnionFS)实现轻量化的镜像分层。与传统虚拟机不同,容器共享宿主机内核,仅通过内核特性隔离进程视图(如PID、网络、用户等命名空间),因此启动更快、开销更小。典型实现如 Docker,实质是通过 runC 等运行时工具调用内核 API,将应用及其依赖打包为可移植的标准化单元。

本文基于 Linux 内核 API 实现一个简易版容器,通过 shell 脚本的开发方式。

容器三板斧

命名空间(Namespaces)—— 实现资源隔离

Namespaces 是 Linux 内核提供的一种资源隔离机制,它使得进程拥有独立的视图,让进程“看起来”自己拥有独立的 网络栈、文件系统挂载、主机名域名、用户和 PID 等资源。

这种隔离有什么用呢?

举个例子,你通过容器部署多个后端服务,服务均占用 8080 端口,如果容器没有独立的网络栈,容器服务的端口之间就会冲突,这显然不是容器应该出现的问题。

再举个例子,在宿主机上,你只有普通用户的权限,但你想在容器里以 root 用户折腾一下,这完全是可以的。在容器里,你甚至可以有单独的文件系统,随意折腾都不会影响到宿主机。

控制组(Cgroups)—— 实现资源限制

Namespaces 更像是逻辑上的隔离,容器本质上和宿主机上其它进程没有任何区别。这就会带来一个问题,如果某个容器失控,耗尽了所有的内存、CPU、IO 资源,就会导致宿主机上的其它进程或容器“饿死”,甚至宿主机本身崩溃,这肯定不是我们想看到的。

所以 Linux 内核提供了 Cgroups 来限制进程对资源的占用限制。

举个例子,在一台 16c 64g 的机器上通过容器部署服务,限制每个容器最多占用 2c 4g,这样即使某个容器失控,它最多也只会占用 2c 4g 的资源,影响不会很大。

根文件系统(Rootfs)—— 独立的文件系统

要想让容器隔离的更彻底,容器应该具备一个独立的根文件系统。在这个根文件系统里,具备容器服务运行的所有依赖和三方库,这就避免因为运行环境不同而带来各种各样的问题。

举个例子,我开发的一个服务应该运行在 centos 上,同时要求其已经安装了 Tomcat 和 JDK。那么在启动这个容器时,宿主机就应该为容器准备好这么一个根文件系统,在这个根文件系统里,已经装好了 Tomcat 和 JDK,同时具备 centos 的基础依赖和库。最后把容器进程的根文件系统,切到这个下面即可。

实现简易容器

有了上述前置知识,实现一个简易容器还是很容易的。为了方便,这里采用 shell 脚本的方式。

要实现一个简易版容器,首先你要有一台 Linux 机器,然后它必须支持 Namespaces 和 Cgroups ,同时你还要准备一个镜像文件,也就是容器的根文件系统。

如下所示,在/pocker目录下有2个文件

  • image.tar 镜像文件,解压后是一个基础的Ubuntu文件系统,同时它里面安装了 nginx
  • pocker 实现容器的脚本文件(参考 docker 命名方式)

pocker 脚本代码如下所示:

  • 定义了容器运行的基础工作目录、和 cgroup 的目录
  • image_file 是容器镜像文件,通过命令行参数指定
  • container_name 容器的名字,随机8位字符
  • container_path 容器的路径,在工作目录下,以容器名创建的目录
  • container_rootfs_path 容器根文件系统路径,镜像文件会解压到这里
  • cgroup_path 容器关联的 cgroup 路径,容器启动会创建这个目录,然后配置 CPU、内存的限制
  • netns_name 容器网络命名空间的名称,"netns_"加上容器名
  • 变量赋值后,解压镜像文件到容器根文件系统
  • 创建容器关联的 cgroup 目录,配置 CPU、内存的限制
  • 创建 veth peer,可以把它看作是一根网线,一端 veth0 插在容器上,一端 veth1 插在宿主机上,宿主机通过 veth1 访问容器内的 nginx 服务
  • 调用 unshare 让容器进程拥有独立的命名空间
  • chroot 切换容器进程的根目录到容器的根文件系统
  • 最后,挂载 proc,修改 hostname,启动nginx,再启动一个 bash 方便和容器交互
  • 最后容器进程推出,释放相关资源
                                                                                                                                                                                                          #!/bin/bash
base_path='/var/pocker'
cgroup_base_path="/sys/fs/cgroup"
image_file=''
container_name=''run(){image_file="$1"container_name="$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 8)"container_path="$base_path/$container_name"container_rootfs_path="$base_path/$container_name/rootfs"cgroup_path="$cgroup_base_path/$container_name"netns_name="netns_$container_name"print_initmkdir -p "$container_rootfs_path"tar -xf "$image_file" -C "$container_rootfs_path"printf "The image file has been successfully decompressed."echo $cmd > "$container_path/init.cmd"mkdir -p $cgroup_pathecho '20000 100000' > $cgroup_path/cpu.maxecho '256M' > $cgroup_path/memory.maxecho $$ > $cgroup_path/cgroup.procsprintf "cgroup configuration successful.\n"veth0="veth0-$container_name"veth1="veth1-$container_name"sudo ip netns add $netns_namesudo ip link add $veth0 type veth peer name $veth1sudo ip link set $veth0 netns $netns_namesudo ip netns exec $netns_name ip link set $veth0 name eth0sudo ip netns exec $netns_name ip addr add 10.1.1.1/24 dev eth0sudo ip netns exec $netns_name ip link set eth0 upsudo ip addr add 10.1.1.2/24 dev $veth1sudo ip link set $veth1 upprintf "Network configuration successful.\n"sudo ip netns exec $netns_name \unshare -fmuip \chroot $container_rootfs_path bash -c "mount -t proc proc /proc && hostname $container_name && mknod -m 666 /dev/null c 1 3 && /sbin/nginx && bash"sudo ip netns delete $netns_namerm -rf $container_pathprintf 'quit...\n'
}print_init(){printf "prepare to start the container: $container_name \n"printf "container image: $image_file \n"printf "container path: $container_path \n"
}case "$1" inrun)shiftrun "$@";;*)echo "Unknown command: $1";;
esac

启动容器

在启动容器前,先看下宿主机的网络设备,发现是没有 veth 设备的。

接着,在/pocker目录下,执行下述命令,即可启动一个部署了nginx的容器

$ ./pocker run image.tar

如上所示,没有报错,就启动成功了。

现在当前bash终端是运行在容器内的,同时可以看到,hostname 已经是容器名1h0MuJlK了。 当前bash是容器内的1号进程,容器进程PID是和宿主机隔离的。

容器的网络栈也是和宿主机隔离的,只有一个eth0,它其实是我配置的veth0,只不过被我改名成 eth0了。

容器内 nginx 也已经部署成功了

先别着急访问服务,先看下 cgroup 是否生效。在脚本里,我们对 CPU 的配置是20000 100000,也就是在 100000 微秒内,允许容器占用 20000 微秒的 CPU,即允许容器最多使用 1/5 颗CPU核心。

在容器内执行while : ; do : ; done死循环耗光CPU,另开一个bash,top 命令查看,发现容器进程占用了单颗CPU核心的20%,cgroup 确实生效了,再也不担心单个容器把资源耗光了。

接下来,在宿主机上开一个bash。为了体现“容器的本质就是进程”这句话,可以看到,容器内运行的nginx,在宿主机上就是一个普通的进程,和其它进程并无二致。

事实上,nginx 的实际进程PID=51256,但是在容器看来,它的进程PID=6,这就是 Namespace 视图的“障眼法”在起作用。

最后,我们访问容器服务。因为容器服务绑定的端口是在自己独立的网络栈里面的,也就是 veth0,要访问它必须通过 veth1,因为它俩是相互连接的。

在宿主机上,也能看到 veth 设备了,它的IP是 10.1.1.2,对端 veth0 的 IP 是 10.1.1.1。

因为nginx默认绑定的是80端口,要想访问容器nginx服务,直接通过10.1.1.1:80访问即可。

容器退出后,相关的资源都会被释放掉。

至此,容器启动演示完毕。

尾巴

容器的本质是进程,只不过它是被 Namespaces 视图隔离,同时被 cgroups 资源限制的进程,它拥有自己的根文件系统 Rootfs,根文件系统包含容器运行的除内核外所有依赖的文件,这些文件打包以后就是容器镜像。

通过 shell 脚本,利用 Linux 内核特性可以很轻松实现一个简易版的容器,本文重点是帮助大家理解容器是怎么一回事儿,这种方式实现的容器远不到可用的程度。

不过话说回来,容器本身没有什么价值,有价值的是容器编排。

http://www.zhongyajixie.com/news/22952.html

相关文章:

  • app制作工具手机版seo资源网站排名
  • 建设网站需要客户提供什么资料换友情链接的网站
  • 网页制作框架模板的步骤巩义关键词优化推广
  • 动态网站开发实例自己怎么做网站网页
  • 买了个网站后怎么做的网站建设方案外包
  • 电子商务网站建设的步骤一般为搭建网站流程
  • 保定网站建设方案厦门谷歌seo公司有哪些
  • 网站建设一对一培训班全国疫情最新消息今天新增
  • 新疆网站开发报价seo同行网站
  • 怎么做网页自我介绍广州seo教程
  • wordpress 3.1seo案例分析100例
  • 个人网站主题百度公司有哪些部门
  • 邢台市住房和城乡建设局网站sem与seo的区别
  • 网站怎么做动态切图新东方在线网上课程
  • 全国疫情最新资讯关键词优化哪家强
  • 拿word如何做网站网站建设的数字化和互联网化
  • 李连杰做的功夫网站semi
  • 加强政府网站建设长春网站建设方案推广
  • 什么作为国内的主要门户网站成都网络推广哪家好
  • 做网站百度新闻源网络推广怎么做
  • 蛋糕网站设计郑州网站公司哪家好
  • 用自己照片做衣服_杯子的是哪个网站武汉百度网站优化公司
  • 武汉建筑公司网站厦门人才网最新招聘信息
  • 莱西网站建设哪家好网站设计
  • 建站平台费用搜索引擎优化的办法有哪些
  • 淘宝上做网站可信吗上海全国关键词排名优化
  • wordpress日主题下载深圳关键词推广整站优化
  • 外贸独立站有哪些平台如何设计一个网页
  • 网站logo如何做清晰seo云优化
  • 个人网站没人访问搜索词