没有合适的资源?快使用搜索试试~ 我知道了~
07 _ 白话容器基础(三):深入理解容器镜像1
需积分: 0 0 下载量 88 浏览量
2022-08-04
12:42:14
上传
评论
收藏 3.16MB PDF 举报
温馨提示
试读
13页
07 | 白话容器基础(三):深入理解容器镜像07 | 白话容器基础(三):深入理解容器镜像07 | 白话容器基础(三):深入理解容器镜像张磊 2018-09-
资源详情
资源评论
资源推荐
2019/10/16 07 | 白话容器基础(三):深入理解容器镜像
file:///C:/Users/qiaochaowen/Desktop/k8s/07%20%20%E7%99%BD%E8%AF%9D%E5%AE%B9%E5%99%A8%E5%9F%BA%E7%A1%80%E
…
1/13
07 | 白话容器基础(三):深入理解容器镜像
07 | 白话容器基础(三):深入理解
容器镜像
张磊 2018-09-07
19:34
讲述:张磊 大小:8.97M
你好,我是张磊。我在今天这篇文章的最后,放置了一张 Kubernetes 的技能图
谱,希望对你有帮助。
在前两次的分享中,我讲解了 Linux 容器最基础的两种技术:Namespace 和
Cgroups。希望此时,你已经彻底理解了“容器的本质是一种特殊的进程”这个
最重要的概念。
而正如我前面所说的,Namespace 的作用是“隔离”,它让应用进程只能看到该
Namespace 内的“世界”;而 Cgroups 的作用是“限制”,它给这个“世
界”围上了一圈看不见的墙。这么一折腾,进程就真的被“装”在了一个与世隔绝
的房间里,而这些房间就是 PaaS 项目赖以生存的应用“沙盒”。
可是,还有一个问题不知道你有没有仔细思考过:这个房间四周虽然有了墙,但是
如果容器进程低头一看地面,又是怎样一副景象呢?
换句话说,容器里的进程看到的文件系统又是什么样子的呢?
可能你立刻就能想到,这一定是一个关于 Mount Namespace 的问题:容器里的
应用进程,理应看到一份完全独立的文件系统。这样,它就可以在自己的容器目录
(比如 /tmp)下进行操作,而完全不会受宿主机以及其他容器的影响。
2019/10/16 07 | 白话容器基础(三):深入理解容器镜像
file:///C:/Users/qiaochaowen/Desktop/k8s/07%20%20%E7%99%BD%E8%AF%9D%E5%AE%B9%E5%99%A8%E5%9F%BA%E7%A1%80%E
…
2/13
那么,真实情况是这样吗?
“左耳朵耗子”叔在多年前写的一篇关于 Docker 基础知识的博客里,曾经介绍过
一段小程序。这段小程序的作用是,在创建子进程时开启指定的 Namespace。
下面,我们不妨使用它来验证一下刚刚提到的问题。
#define _GNU_SOURCE
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];
char* const container_args[] = {
"/bin/bash",
NULL
};
int container_main(void* arg)
{
printf("Container - inside the container!\n");
execv(container_args[0], container_args);
printf("Something's wrong!\n");
return 1;
}
int main()
{
printf("Parent - start a container!\n");
int container_pid = clone(container_main, container_stack+STACK_SIZE,
CLONE_NEWNS | SIGCHLD , NULL);
waitpid(container_pid, NULL, 0);
printf("Parent - container stopped!\n");
return 0;
}
复制代码
这段代码的功能非常简单:在 main 函数里,我们通过 clone() 系统调用创建了一
个新的子进程 container_main,并且声明要为它启用 Mount
Namespace(即:CLONE_NEWNS 标志)。
2019/10/16 07 | 白话容器基础(三):深入理解容器镜像
file:///C:/Users/qiaochaowen/Desktop/k8s/07%20%20%E7%99%BD%E8%AF%9D%E5%AE%B9%E5%99%A8%E5%9F%BA%E7%A1%80%E
…
3/13
而这个子进程执行的,是一个“/bin/bash”程序,也就是一个 shell。所以这个
shell 就运行在了 Mount Namespace 的隔离环境中。
我们来一起编译一下这个程序:
$ gcc -o ns ns.c
$ ./ns
Parent - start a container!
Container - inside the container!
复制代码
这样,我们就进入了这个“容器”当中。可是,如果在“容器”里执行一下 ls 指
令的话,我们就会发现一个有趣的现象: /tmp 目录下的内容跟宿主机的内容是一
样的。
$ ls /tmp
# 你会看到好多宿主机的文件
复制代码
也就是说:
即
使
开
启
了
Mount Namespace
,
容
器
进
程看
到
的
文
件
系统
也
跟
宿
主
机
完
全
一
样
。
这是怎么回事呢?
仔细思考一下,你会发现这其实并不难理解:Mount Namespace 修改的,是容
器进程对文件系统“挂载点”的认知。但是,这也就意味着,只有在“挂载”这个
操作发生之后,进程的视图才会被改变。而在此之前,新创建的容器会直接继承宿
主机的各个挂载点。
这时,你可能已经想到了一个解决办法:创建新进程时,除了声明要启用 Mount
Namespace 之外,我们还可以告诉容器进程,有哪些目录需要重新挂载,就比如
这个 /tmp 目录。于是,我们在容器进程执行前可以添加一步重新挂载 /tmp 目录
的操作:
int container_main(void* arg)
{
printf("Container - inside the container!\n");
// 如果你的机器的根目录的挂载类型是 shared,那必须先重新挂载根目录
// mount("", "/", NULL, MS_PRIVATE, "");
mount("none", "/tmp", "tmpfs", 0, "");
execv(container_args[0], container_args);
printf("Something's wrong!\n");
return 1;
}
复制代码
剩余12页未读,继续阅读
Xhinking
- 粉丝: 24
- 资源: 320
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0