首页 > 系统相关 >linux容器基础-namespace-3(pid)

linux容器基础-namespace-3(pid)

时间:2024-08-21 14:52:27浏览次数:9  
标签:pid ubuntu namespace server linux root proc

pid namespace

pid namespace表示隔离一个具有独立PID的运行环境。
在每一个pid namespace中,进程的pid都从1开始,且和其他pid namespace中的PID互不影响。
这意味着,不同pid namespace中可以有相同的PID值。

在介绍pid namespace之前,先创建其他类型的namespace然后查看进程关系:

#在root namesapce查看当前进程的id是4048028
root@ubuntu-server:~# echo $$
4048028

root@ubuntu-server:~# pstree -p |grep 4048028
|-sshd(3944519)---sshd(4047935)---bash(4048028)-+-grep(4074182)

#进程的关系:
#systemd(1) |-sshd(3944519 这个是sshd服务server)|-sshd(4047935,这个是ssh连接的进程)|---bash(4048028)-+-grep(4074182)

root@ubuntu-server:~# ps -ef|grep 3944519
root     3944519       1  0 Jan15 ?        00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

创建一个uts namespace

root@ubuntu-server:~# unshare -u /bin/bash

在uts namespace中查看当前进程

root@ubuntu-server:~# pstree -p |grep grep
|-sshd(3944519)---sshd(4047935)---bash(4048028)---bash(4074716)-+-grep(4074764)

root@ubuntu-server:# ls -l /proc/4074716/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 15:07 uts -> uts:[4026532372]
root@ubuntu-server:# ls -l /proc/4048028/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 11:17 uts -> uts:[4026531838]
root@ubuntu-server:~# ls -l /proc/4047935/ns|grep uts
lrwxrwxrwx 1 root root 0 Jan 16 11:17 uts -> uts:[4026531838]

#从上面输出的结果可知,创建uts类型namespace时,unshare进程会在创建新的namespace后被该namespace中的第一个进程给替换掉。
#并且我们可以看到unshare创建的bash(4074716)进程与其父进程(4048028),2者的uts namespace是不一致的。

创建pid namespace:

unshare --pid --fork [--mount-proc] <CMD>
--pid(-p):    表示创建pid namespace
--mount-proc: 表示创建pid namespace时重新挂载procfs
--fork(-f):   表示创建pid namespace时,不是直接替换unshare进程,而是fork unshare进程,并使用CMD替换fork出来的子进程

我们使用fork的参数来验证一下:

root@ubuntu-server:~# echo $$
4048028

root@ubuntu-server:# unshare -p -f  --mount-proc /bin/bash
root@ubuntu-server:# pstree -p |grep grep
bash(1)-+-grep(9)

#终端2,重新打开一个终端
root@ubuntu-server:~# pstree -p 4048028
bash(4048028)───unshare(4090558)───bash(4090559)

root@ubuntu-server:# ls -l /proc/4048028/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 11:17 /proc/4048028/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:# ls -l /proc/4090558/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 17:27 /proc/4090558/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l /proc/4090559/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 17:27 /proc/4090559/ns/pid -> 'pid:[4026532379]'

#通过这个实验,我们可以看到unshare(4090558)这个进程还是在原来的namespace,并不会加入新的namespace,
而fork出来的bash(4090559)进程,他是加入到了一个新的namespace当中。

嵌套pid namespace

这个很容易理解,就是不同namespace之间可以相互嵌套,所有的子孙pid namespace中的进程信息都会保存在父级以及祖先级namespace中,
只不过在不同嵌套层级中,同一个进程对应的PID不同。

#我们这里在namespace1之中在创建一个namespace2看看进程的关系是什么样的
#------第一个终端------
#namespace1
root@ubuntu-server:~# unshare -p -f -u --mount-proc /bin/bash
root@ubuntu-server:~# hostname namespace1
root@ubuntu-server:~# exec bash

#在namespace1中创建namespace2
root@namespace1:~# unshare -p -f -u --mount-proc /bin/bash
root@namespace1:~# hostname namespace2
root@namespace1:~# exec bash
root@namespace2:~# pstree -p |grep grep
bash(1)-+-grep(16)

##------第二个终端------,也就是root namespace下面
root@ubuntu-server:~# pstree -p 4048028
bash(4048028)───unshare(4097920)───bash(4097921)───unshare(4098083)───bash(4098084)

#在上面fork测试中我们知道unshare进程还在原来的namespace,而unshare创建的bash是在新的namespace中。
所以bash(4048028)───unshare(4097920)在同一个ns,bash(4097921)───unshare(4098083)在同一个ns,bash(4098084)在一个ns

root@ubuntu-server:~# ls -l -h  /proc/4048028/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 11:17 /proc/4048028/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l -h  /proc/4097920/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4097920/ns/pid -> 'pid:[4026531836]'
root@ubuntu-server:~# ls -l -h  /proc/4097921/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4097921/ns/pid -> 'pid:[4026532386]'
root@ubuntu-server:~# ls -l -h  /proc/4098083/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4098083/ns/pid -> 'pid:[4026532386]'
root@ubuntu-server:~# ls -l -h  /proc/4098084/ns/pid
lrwxrwxrwx 1 root root 0 Jan 16 18:31 /proc/4098084/ns/pid -> 'pid:[4026532391]'

pid namespace和procfs

/proc目录是内核对外暴露的可供用户查看或修改的内核中所记录的信息,包括内核自身的部分信息以及每个进程的信息。
比如对于pid=N的进程来说,它的信息保存在/proc/目录下。在操作系统启动的过程中,会挂载procfs到/proc目录,它存在于root namespace中。
但是,创建新的pid namespace时不会自动重新挂载procfs,而是直接拷贝父级namespace的挂载点信息。
这使得在新的pid namespace中仍然保留了父级namespace的/proc目录,也就是在新创建的这个pid namespace中仍然保留了父级的进程信息。

#不挂载 --mount-proc此时namespace还是继承宿主机的进程树
root@ubuntu-server:~# unshare -p -u -f /bin/bash
root@ubuntu-server:~# hostname namepsace1
root@ubuntu-server:~# exec bash
root@namepsace1:~# pstree
systemd─┬─ModemManager───2*[{ModemManager}]
        ├─agetty
        ├─cron
        ├─dbus-daemon
        ├─dnsmasq───dnsmasq
        ├─irqbalance───{irqbalance}
        ......

之所以有上述问题,其原因是在pid namespace中保留了root namespace中的/proc目录,而不是属于pid namespace自己的/proc。
但用户创建pid namespace时希望的是有完全独立的进程运行环境。
这时,需要在pid namespace中重新挂载procfs,或者在创建pid namespace时指定–mount-proc选项。

# 注意这儿添加了mount-proc参数
root@ubuntu-server:~# unshare -p -u -f --mount-proc /bin/bash
root@ubuntu-server:~# hostname namespace1
root@ubuntu-server:~# exec bash

# 进程树中展示了bash 为init进程
[root@namespace1 ~]# pstree -p
bash(1)───pstree(24)

pid namespace信号量

pid=1的进程是每一个pid namespace的核心进程(init进程),它不仅负责收养其所在pid namespace中的孤儿进程,还影响整个pid namespace。

当pid namespace中pid=1的进程退出或终止,内核默认会发送SIGKILL信号给该pid namespace中的所有进程以便杀掉它们(如果该pid namespace中有子孙namespace,也会直接被杀)。

在创建pid namespace时可以通过–kill-child选项指定pid=1的进程终止后内核要发送给pid namespace中进程的信号,其默认信号便是SIGKILL。

root@ubuntu-server:~# lsns
4026532379 pid         1 4099754 root             bash

root@ubuntu-server:~# kill -9 4099754
#在namespace1的进程,kill掉这个进程后这个namespace1整个namespace都被干掉了
root@namepsace1:~# Killed

#也可以指定为其他信号
unshare -p -f -m -u --mount-proc --kill-child=SIGHUP /bin/bash

我们在这里通过一些简单的例子来熟悉了一下pid namespace是如何工作的,当以后我们在玩k8s和docker的时候看到容器中的进程
是如何与宿主机隔离的就不会感到疑惑了。

标签:pid,ubuntu,namespace,server,linux,root,proc
From: https://blog.csdn.net/hiyun9/article/details/141393862

相关文章

  • 【Linux】gnome桌面环境切换KDE Plasma
    @目录安装KDEPlasma桌面环境添加软件源并更新apt安装kubuntu-desktop(作者没有成功)aptitude安装kubuntu-desktop多次aptitudeinstall(特别重要特别重要)其他kde软件包卸载gnome桌面Ubuntu自带的桌面环境是gnome,本文提供了安装KDEPlasma的教程,并解决了其中可能遇到的一些问题。......
  • 深入理解Linux内核进程的管理与调度
    一,前戏1.1进程调度内存中保存了对每个进程的唯一描述,并通过若干结构与其他进程连接起来.调度器面对的情形就是这样,其任务是在程序之间共享CPU时间,创造并行执行的错觉,该任务分为两个不同的部分,其中一个涉及调度策略,另外一个涉及上下文切换.1.2进程的分类linux把......
  • Linux系统构成
    一个完整的linux系统,通常包括Uboot,kernel,设备树以及跟文件系统。1.UbootU-boot是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,Uboot全称Universal bootLoader,是遵循GPL条款的开源项目,U-boot的主要作用是用来启动操作系统内核,分为两个阶段,即bo......
  • linux 网卡配置
    linux网卡可以通过命令和配置文件配置,如果是桌面环境还可以通过图形化界面配置.1.ifconfig(interfacesconfig)命令方式通常需要以root身份登录或使用sudo以便在Linux机器上使用ifconfig工具。依赖于ifconfig命令中使用一些选项属性,ifconfig工具不仅可以被用来简单地获取......
  • linux安装samba(ubuntu)
    samba简介samba的功能都是通过一个CIFS(CommonInternetFileSystem)协议套件来管理的,这个名字是由微软引入的。Samba是一个开源的CIFS实现,官网地址为 https://www.samba.org/samba/。SMB(ServerMessageBlockProtocol)协议是一种客户端/服务器通信协议,它主要包括smbd和nm......
  • RockyLinux使用dnf安装snap
    snap是一种用于安装和管理应用程序的软件包格式‌,它有助于简化Linux系统上的软件安装和更新过程,使得用户可以更轻松地管理他们的应用程序。‌snap的优势‌简化管理‌:通过Snap,用户可以更轻松地安装、更新和删除应用程序,无需担心依赖问题。‌提高安全性‌:由于应用程序被隔离在......
  • JetBrains PyCharm 2024.2 (macOS, Linux, Windows) - 面向专业开发者的 Python IDE
    JetBrainsPyCharm2024.2(macOS,Linux,Windows)-面向专业开发者的PythonIDEJetBrains跨平台开发者工具请访问原文链接:https://sysin.org/blog/jetbrains-pycharm/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgJetBrainsPyCharm-面向专业开发者的Pytho......
  • JetBrains Rider 2024.2 (macOS, Linux, Windows) - 快速且强大的跨平台 .NET IDE
    JetBrainsRider2024.2(macOS,Linux,Windows)-快速且强大的跨平台.NETIDEJetBrains跨平台开发者工具请访问原文链接:https://sysin.org/blog/jetbrains-rider/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgJetBrainsRider-快速且强大的跨平台.NETIDE......
  • 详解Linux命令--sudo
    sudo命令是Linux中最常用的命令之一,用于以其他用户的身份执行命令。本文将详细介绍sudo命令的用法,并给出具体的示例。1.基本语法sudo的基本语法如下:sudo[options]command[arguments...][options]:可选参数,用于控制sudo的行为。command:要执行的命令。[arguments...]......
  • java项目部署到linux
    手工部署打包获取打包的jar包将jar包放到linux中(可通过xftp软件)的usr/local/ruiji执行jar包java-jarjar包名称指定端口:java-jarjar包名称--server.port=端口号如果端口被占用,查看端口号命令netstat-tuln|grep:8080根据端口号杀死进程lsof-i:8......