分类 linux 下的文章

Ubuntu18.04 连不上网 报“有线连接未托管”

新来一台服务器,插上网线发现,没有弹出登录页面,ifconfig之后也只显示ipv6的地址,不显示ipv4的地址,在网络连接页面也不显示有线连接的配置。

ubuntu18.jpg

一开始按照ubuntu18,只显示ipv6不显示ipv4地址思路去查解决方案,网上有好多让自己设置ipv4等方法,个人感觉不怎么靠谱,之后又插着网线,重启了下服务器。发现显示以太网未托管。

393891516.jpg

解决方案:

sudo vim /etc/NetworkManager/NetworkManager.conf

将里面的

managed=false 改为true

最后

sudo service network-manager restart 

问题解决。

参考:https://blog.csdn.net/daerzei/article/details/85058130

概念

1.镜像(Image):类似于虚拟机中的镜像,是一个包含有文件系统的面向Docker引擎的只读模板。
2.容器(Container):类似于一个轻量级的沙盒,可以将其看作一个极简的Linux系统环境(包括root权限、进程空间、用户空间和网络空间等),以及运行在其中的应用程序。
3.仓库(Repository):类似于代码仓库,这里是镜像仓库,是Docker用来集中存放镜像文件的地方。

Docker镜像的分类

1.基础镜像,可以去docker.io上下载,也可以在国内的Docker仓库下载
2.自定义镜像,可以基于基础镜像实现镜像的自定义
Docker镜像的相关命令
1.docker images
2.docker search centos
3.docker pull centos:7
Docker仓库的配置/etc/docker/daemon.json,重启Docker
{
"registry-mirrors": ["http://hub-mirror.c.163.com/"]
}

国内仓库pull镜像

docker pull hub-mirror.c.163.com/library/centos:7
docker images
镜像导出备份,删除和导入
重命名:docker tag hub-mirror.c.163.com/library/centos:7 centos:7
导出镜像:docker save hub-mirror.c.163.com/library/centos:7 >/tmp/centos.tar
删除镜像:docker rmi centos:7
镜像导入:docker load < /tmp/centos7.tar

Docker 容器

可以使用镜像生成对应运行的容器,一个镜像可以生成多个容器
Centos7镜像生成的容器系统是Centos7,Ubuntu镜像生成的容器系统是Ubuntu的
使用Centos7镜像启动容器
docker run -it centos:7 /bin/bash
i表示交互式,t表示打开一个Shell窗口
宿主机上查看容器的相关操作
1.docker ps:查看运行的容器。docker ps -a:查看所有容器
2.docker inspect:查看容器详细信息
3.docker logs:查看容器日志
4.docker rm:删除容器,docker rm -f:强制删除容器

容器后台运行的特点
如果没有永久运行的程序,终端一退出容器就会马上退出
容器永久运行的条件:需要有永久运行的程序,并且使用run -d后台启动容器
启动后台容器:docker run -d centos:7 /bin/bash -c "while true;do echo helloworld; sleep 5; done"
进入后台容器:docker exec -it xxx /bin/bash
后台容器的停止
停止后台容器:docker stop xxx 或者 docker kill xxx
批量删除容器:docker rm -f xxx xxx

进入容器后ctrl+p+q可以退出终端而不关闭容器,也可以直接关闭终端,容器中pid为1的进程只要不被杀死,容器就不会被关闭。

自定义镜像

容器的临时性
1.容器里的操作当容器删除了就没了
2.最好不要把数据存储在容器里

可将宿主机文件挂载到docker中,或者使用docker数据卷操作 参见docker数据卷

Docker自定义镜像
一般自带的镜像无法满足特定的要求,需要基于基础镜像来自定义Docker镜像
Docker镜像制作的两种方法
1.基于Docker Commit制作镜像
2.基于Dockerfile制作镜像,Dockerfile方式为主流制作镜像的方式

Docker Commit

给基础镜像新增ifconfig命令
docker run --name helloworld -it centos /bin/bash
yum install net-tools -y

保存为镜像

docker commit xx(容器名称) myimage:v1.0
docker images

参考51 CTO 2019Docker入门实战视频

一个docker容器启动之后,我们进入可以看到一个操作系统的所有文件。

我们可以通过chroot这个命令可以更改一个程序运行时的根目录。

假设,我们现在有一个 $HOME/test 目录,想要把它作为一个 /bin/bash 进程的根目录。首先,创建一个 test 目录和几个 lib 文件夹:

$ mkdir -p $HOME/test
$ mkdir -p $HOME/test/{bin,lib64,lib}
$ cd $T

然后,把 bash 命令拷贝到 test 目录对应的 bin 路径下:

$ cp -v /bin/{bash,ls} $HOME/test/bin

接下来,把 bash 命令需要的所有 so 文件,也拷贝到 test 目录对应的 lib 路径下。

$ T=$HOME/test
$ list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
$ for i in $list; do cp -v "$i" "${T}${i}"; done

最后,执行 chroot 命令,告诉操作系统,我们将使用 $HOME/test 目录作为 /bin/bash 进程的根目录:

$ chroot $HOME/test /bin/bash

这时,你如果执行 "ls /",就会看到,它返回的都是 $HOME/test 目录下面的内容,而不是宿主机的内容。

这个挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的“容器镜像”。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。

Docker容器运行过程

  1. 启用 Linux Namespace 配置;
  2. 设置指定的 Cgroups 参数;
  3. 切换进程的根目录(Change Root)。

Cgroup和Namespace类似,也是将进程进行分组,但它的目的和namespace不一样,Namespace是为了隔离进程组之间的资源,而Cgroup是为了对一组进程进行统一的资源监控和限制。

它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

在Linux中,Cgroups给用户暴露出来的接口是文件系统,以文件与目录形式组织在/sys/fs/cgroup路径之下。

root@herefree:/sys/fs/cgroup# ls
blkio    cpu,cpuacct  freezer  net_cls           perf_event  systemd
cpu      cpuset       hugetlb  net_cls,net_prio  pids        unified
cpuacct  devices      memory   net_prio          rdma
  1. cpu 子系统,主要限制进程的 cpu 使用率。
  2. cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
  3. cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
  4. memory 子系统,可以限制进程的 memory 使用量。
  5. blkio 子系统,可以限制进程的块设备 io。
  6. devices 子系统,可以控制进程能够访问某些设备。
  7. net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
  8. net_prio — 这个子系统用来设计网络流量的优先级
  9. freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
  10. ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace
  11. hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统。
如何使用?

在对应子系统下面创建一个目录。

root@herefree:/sys/fs/cgroup/cpu# mkdir container
root@herefree:/sys/fs/cgroup/cpu# cd container/
root@herefree:/sys/fs/cgroup/cpu/container# ls
cgroup.clone_children  cpuacct.usage_percpu_sys   cpu.shares
cgroup.procs           cpuacct.usage_percpu_user  cpu.stat
cpuacct.stat           cpuacct.usage_sys          notify_on_release
cpuacct.usage          cpuacct.usage_user         tasks
cpuacct.usage_all      cpu.cfs_period_us
cpuacct.usage_percpu   cpu.cfs_quota_us

后台写一个死循环脚本,运行起来

 while : ; do : ; done &

查看cpu占用

jiaoben.png

使被该进程组限制的进程每100ms时间只能使用20ms的CPU时间。

echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us

将被限制进程的PID写入到container组里的task文件。

echo 11036 > /sys/fs/cgroup/cpu/container/tasks 

再次查看

jiaoben2.png

对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。

假设我们有了一个Docker项目,我们创建一个容器。

$ docker run -it ubuntu /bin/bash

-it 参数告诉了 Docker 项目在启动容器后,需要给我们分配一个文本输入 / 输出环境,也就是 TTY,跟容器的标准输入相关联,这样我们就可以和这个 Docker 容器进行交互了。而 /bin/bash 就是我们要在 Docker 容器里运行的程序。

所以上面这条指令的意思就是:

请帮我启动一个容器,在容器里执行 /bin/sh,并且给我分配一个命令行终端跟这个容器交互。

我们在容器中输入ps指令:

/ # ps
PID  USER   TIME COMMAND
  1 root   0:00 /bin/sh
  2 root   0:00 ps

在这里可以看到,我们在 Docker 里最开始执行的 /bin/sh,就是这个容器内部的第 1 号进程(PID=1),而这个容器里一共只有两个进程在运行。这就意味着,前面执行的 /bin/sh,以及我们刚刚执行的 ps,已经被 Docker 隔离在了一个跟宿主机完全不同的世界当中。

我们在宿主机上运行/bin/bash程序时,操作系统会给它分配一个进程编号pid。这个进程编号就是进程的唯一标识,我们在docker中运行/bin/bash时,给它施展了一个“障眼法”,让它看不到其他的进程,这样它就会自己认为自己的pid=1。

这种机制,其实就是对被隔离应用的进程空间做了手脚,使得这些进程只能看到重新计算过的进程编号,这就是Linux里面的Namespace机制。

Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。

目前,Linux内核里面实现了7种不同类型的namespace。

名称        宏定义             隔离内容
Cgroup      CLONE_NEWCGROUP   Cgroup root directory (since Linux 4.6)
IPC         CLONE_NEWIPC      System V IPC, POSIX message queues (since Linux 2.6.19)
Network     CLONE_NEWNET      Network devices, stacks, ports, etc. (since Linux 2.6.24)
Mount       CLONE_NEWNS       Mount points (since Linux 2.4.19)
PID         CLONE_NEWPID      Process IDs (since Linux 2.6.24)
User        CLONE_NEWUSER     User and group IDs (started in Linux 2.6.23 and completed in Linux 3.8)
UTS         CLONE_NEWUTS      Hostname and NIS domain name (since Linux 2.6.19)

PID Namespace

在 Linux 系统中创建进程的系统调用是 clone()

int pid = clone(main_function, stack_size, SIGCHLD, NULL);

这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。

我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);  

这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。

https://segmentfault.com/a/1190000006908272