近日见闻
- 自世界标准时间2024年4月1日00:00(中国时间2024年4月1日上午8时)起,任何 CNCF 相关认证的有效期缩短为24个月。持证人需在每24个月内重新认证一次,以确保其认证的有效性。此外,任何在 UTC 时间 2024 年 4 月 1 日 00:00 之前安排并通过考试的学员仍然将获得 36 个月的认证有效期。--CNCF
- XIAOJUSURVEY 源自滴滴内部问卷系统,已在集团内为各业务线提供在线调研服务,并为外部提供多种企业级调研场景解决方案。经过5年多的发展,它已发展成一个相对完整成熟的企业级平台。本次开源旨在为行业和社区提供一种轻量、安全的问卷系统解决方案,让调研更轻松。--滴滴
- 华中农业大学导师学术造假,对于这个事情,个人认为做科研的容不得半点虚假,1就是1,0就是0。
- 摘抄
代码语言:javascript
复制
你只管做自己的事, 把你的全部身心都投入到正在发生的事情中去, 而不是把你的全部身心都投入到个人的敏感多虑中去。 ——迈克尔·辛格《清醒地活》
Docker:容器化技术的普及者
容器化是一种轻量级、可移植、自给自足的软件打包技术,能够让软件运行在几乎任何地方。这听起来有点像虚拟机,但容器是更轻量级的,它不需要像虚拟机那样模拟整个操作系统。在去年的文章已经普及过docker的基础概念和命令行操作,不知道还记得否,今天就来复习下:
Docker的五个基础概念:
- 镜像(Images):容器的基础,它包含运行应用程序所需的代码、运行库、环境变量和配置文件。
- 容器(Containers):镜像的运行实例,它在操作系统级别虚拟出来的隔离环境中运行。
- 仓库(Repositories):存放镜像的地方,比如Docker Hub。
- Dockerfile:一个文本文件,包含了创建Docker镜像所需的指令。
- Docker Compose:一种工具,允许您定义和运行多容器Docker应用程序。
容器化的优势:
- 快速,轻量级:容器共享宿主机的系统内核,启动速度快。
- 一致的运行环境:开发、测试、生产环境保持一致,避免了“在我机器上可正常工作”的问题。
- 持续集成和持续部署(CI/CD):容器使得自动化测试和部署变得更加容易。
Docker vs Containerd
自从k8s-1.24版本之后,k8s采删除了内置支持Docker Engine(Docker引擎)容器运行时环境的功能,v1.24 之前的 Kubernetes 版本直接集成了 Docker Engine 的一个组件,名为 dockershim。所以现在containerd成为广泛使用的容器运行时,更为详细的操作建议直接官方查阅学习。https://github.com/containerd/containerd/blob/main/docs/getting-started.md
Docker 是一个完整的容器化平台,它不仅提供容器运行时,还包含了图形界面、命令行界面、镜像管理以及一个集成的容器编排工具(Docker Compose)。
containerd 是一个容器运行时守护进程,它专注于管理容器的生命周期,例如容器的创建、执行、暂停和销毁。它是一个更为“纯粹”的容器运行时,去除了很多Docker附加的功能,比如图形界面和编排。
最直接的区别在于:
- Docker提供了完整的“生态系统”,对开发者更为友好,容易上手和使用。
- containerd更为轻量级,通常用于需要较低系统开销的环境,比如生产环境中的Kubernetes,它会直接使用containerd来运行容器。
在linux系统上创建一个简单的模拟容器
创建一个简单一点的容器模拟器,我们可以按照以下几个步骤操作。会用到Linux的一些高级特性,如命名空间(namespaces)、控制组(Control Groups, cgroups)、文件系统隔离(chroot)等,以实现容器的基本功能。
但这只是一个简单示例,实际上Docker的实现要复杂得多,包括网络设置、存储卷管理、镜像分层、安全机制等等。
下面是在 CentOS 7.9 上创建一个简单容器并在其中运行进程的步骤:
步骤1: 安装必要的软件
代码语言:javascript
复制
sudo yum install -y yum-utils
步骤2: 创建容器的根文件系统
代码语言:javascript
复制
# 创建一个目录作为容器的根文件系统
sudo mkdir -p /path/to/container-rootfs
# 安装一个最小的CentOS系统
sudo yum --releasever=7 --installroot=/path/to/container-rootfs --setopt=tsflags=nodocs install -y bash coreutils yum
步骤3: 进入新的命名空间
CentOS 7 使用的是旧版本的unshare
,可能不支持 --mount-proc
选项, 但你可以手动挂载 proc
系统。
代码语言:javascript
复制
# 创建新的网络、进程、IPC、挂载点命名空间
sudo unshare --fork --pid --net --ipc --uts --mount
然后,另外开一个终端,继续以下步骤:
步骤4: 挂载必要的文件系统
代码语言:javascript
复制
# 为新的PID命名空间挂载proc文件系统
sudo mount -t proc proc /path/to/container-rootfs/proc
# 为容器挂载sys文件系统(可选)
sudo mount -t sysfs sys /path/to/container-rootfs/sys
# 为容器挂载dev文件系统(可选)
sudo mount --rbind /dev /path/to/container-rootfs/dev
步骤5: 使用chroot切换到容器的根目录
代码语言:javascript
复制
# 切换到容器的根目录
sudo chroot /path/to/container-rootfs /bin/bash
步骤6: 创建cgroups并限制资源
代码语言:javascript
复制
# 创建cgroups(如果系统没有安装cgroups工具,需要先安装它)
sudo yum install -y libcgroup
sudo systemctl start cgconfig
# 创建cgroup并限制CPU和内存
sudo cgcreate -g cpu,memory:/mycontainer
echo 512 > /sys/fs/cgroup/cpu/mycontainer/cpu.shares
echo 100000000 > /sys/fs/cgroup/memory/mycontainer/memory.limit_in_bytes
步骤7: 将进程添加到cgroups
在chroot容器环境中执行以下命令:
代码语言:javascript
复制
# 获取当前shell的进程ID
echo $$
# 使用获取到的进程ID,替换下面命令中的<PID>
sudo cgclassify -g cpu,memory:/mycontainer <PID>
步骤8: 运行简单的进程
现在你可以在这个隔离环境中运行一个简单的进程,例如一个bash shell。
代码语言:javascript
复制
/bin/bash
至此,你已经在CentOS 7.9上使用Linux命名空间和控制组功能手动创建了一个简单的容器环境,并运行了一个简单的bash进程。对于学习容器原理而言,这是一个不错的开始。
问题
- 运行以上步骤的时候会遇到安装cgroups失败的问题,因为网络的问题。
所以简化以下流程:
更新系统:
代码语言:javascript
复制
sudo yum update -y
安装必要的依赖:
代码语言:javascript
复制
sudo yum install -y epel-release
sudo yum install -y libcgroup libcgroup-tools
启动 cgroup 服务:
代码语言:javascript
复制
sudo systemctl start cgconfig
创建 cgroup:
代码语言:javascript
复制
sudo cgcreate -g cpu,memory:/mycontainer
设置资源限制(可选,但推荐):
- 为
mycontainer
容器设置CPU资源限制:echo 512 | sudo tee /sys/fs/cgroup/cpu/mycontainer/cpu.shares
- 为
mycontainer
容器设置内存资源限制:echo $((100*1024*1024)) | sudo tee /sys/fs/cgroup/memory/mycontainer/memory.limit_in_bytes
创建一个隔离的文件系统:
代码语言:javascript
复制
mkdir -p ~/mycontainer/{bin,lib64}
安装必要的程序和库:
- 使用
ldd
来检查需要哪些库,例如安装bash
:ldd /bin/bash
- 把
bash
和它所需要的库复制到容器的文件系统中:cp /bin/bash ~/mycontainer/bin/
cp -v $(ldd /bin/bash | grep -o '/lib.*[ ].so[^ ]*' | sort | uniq) ~/mycontainer/lib64/
注意:这里如果复制不成功,就手动复制
代码语言:javascript
复制
linux-vdso.so.1 => (0x00007fffd7f2b000) libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f9b76f4e000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f9b76d4a000) libc.so.6 => /lib64/libc.so.6 (0x00007f9b7697c000) /lib64/ld-linux-x86-64.so.2 (0x00005620622cc000)
代码语言:javascript
复制
cp /lib64/libtinfo.so.5 ~/mycontainer/lib64/
cp /lib64/libdl.so.2 ~/mycontainer/lib64/
cp /lib64/libc.so.6 ~/mycontainer/lib64/
cp /lib64/ld-linux-x86-64.so.2 ~/mycontainer/lib64/
运行一个隔离的进程:命令解释:
cgexec
用于在指定的cgroup中启动程序。unshare
用于创建隔离的命名空间。-u
,-m
,-p
分别用于隔离UTS, 挂载点, 和进程。-f
表示创建新的会话。chroot
更改根目录到~/mycontainer
。/bin/bash
是隔离环境中运行的shell。- 使用
cgexec
命令在mycontainer
cgroup中启动一个隔离的进程:sudo cgexec -g cpu,memory:/mycontainer unshare -u -m -p -f chroot ~/mycontainer /bin/bash
通过这些步骤,您就能够在CentOS 7.9上模拟出一个基本的容器环境了。
检查:
在这个新的PID命名空间中,bash进程将有一个PID为1。您可以通过运行echo $$来检查当前bash会话的PID,如果返回1,则表示您在新的PID命名空间中。
通过以上步骤,虽然不能完全模拟,但也能大致明白其中流程了,希望对各位读者有用,觉得有用的话,关注下希里安!