容器相当于你运行了一个接近于裸机的虚拟机。这项技术始于2008年,LXC的大部分功能来自于Solaris容器(又叫做Solaries Zones)以及之前的FreeBSD jails技术。LXC并不是创建一个成熟的虚拟机,而是创建了一个拥有自己进程程和网络空间的虚拟环境,使用命名空间来强制进程隔离并利用内核的控制组(cgroups)功能,该功能可以限制,计算和隔离一个或多个进程的CPU,内存,磁盘I / O和网络使用情况。您可以将这种用户空间框架想像成是 chroot的高级形式。
chroot 是一个改变当前运行进程以及其子进程的根目录的操作。一个运行在这种环境的程序无法访问根目录外的文件和命令。
注意:LXC使用命名空间来强制进程隔离,同时利用内核的控制组来计算以及限制一个或多个进程的CPU,内存,磁盘I / O和网络使用。
但容器究竟是什么?简短的答案是容器将软件应用程序与操作系统分离,为用户提供干净且最小的Linux环境,与此同时在一个或多个隔离的“容器”中运行其他所有内容。容器的目的是启动一组有限数量的应用程序或服务(通常称为微服务),并使它们在独立的沙盒环境中运行。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/b378ef175d918c1ef6ec3385d1853c56.png)
这种隔离可防止在给定容器内运行的进程监视或影响在另一个容器中运行的进程。此外,这些集装箱化服务不会影响或干扰主机。能够将分散在多个物理服务器上的许多服务合并为一个的想法是数据中心选择采用该技术的众多原因之一。
容器有以下几个特点:
安全性:容器里可以运行网络服务,这可以限制安全漏洞或违规行为造成的损害。那些成功利用那个容器的一个或多个应用的安全漏洞的入侵者将会被限制在只能在那个容器中做一些操作。
隔离性:容器允许在同一物理机器上部署一个或多个应用程序,即使这些应用程序必须在不同的域下运行,每个域都需要独占访问其各自的资源。例如,通过将每个容器关联的不同IP地址,在不同容器中运行的多个应用程序可以绑定到同一物理网络接口。
虚拟化和透明性:容器为系统提供虚拟化环境,这个环境可以隐藏或限制系统底层的物理设备或系统配置的可见性。容器背后的一般原则是避免更改运行应用程序的环境,但解决安全性或隔离问题除外。
使用LXC的工具
如果您使用的是Red Hat或CentOS,则需要先安装EPEL仓库。对于其他发行版,例如Ubuntu或Debian,只需键入:
$ sudo apt-get install lxc
现在,在开始使用这些工具之前,您需要配置您的环境。在此之前,您需要验证当前用户是否同时在/ etc / subuid和/ etc / subgid中定义了uid和gid:
$ cat /etc/subuid
petros:100000:65536
$ cat /etc/subgid
petros:100000:65536
如果 ~/.config/lxc directory不存在,则创建该目录,并且把配置文件 /etc/lxc/default.conf复制到 ~/.config/lxc/default.conf.,将以下两行添加到文件末尾:
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
结果如下:
$ cat ~/.config/lxc/default.conf
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
将以下命令添加到 /etc/lxc/lxc-usernet文件末尾(把第一列换成你的username):
petros veth lxcbr0 10
最快使这些配置生效的方法是重启节点或者将用户登出再登入。
重新登录后,请验证当前是否已加载veth网络驱动程序:
$ lsmod|grep veth
veth 16384 0
如果没有,请输入:
$ sudo modprobe veth
现在您可以使用LXC工具集来下载,运行,管理Linux容器。
接下来,下载容器镜像并将其命名为“example-container”。当您键入以下命令时,您将看到一长串许多Linux发行版和版本支持的容器:
$ sudo lxc-create -t download -n example-container
将会有三个弹出框让您分别选择发行版名称(distribution),版本号(release)以及架构(architecture)。请选择以下三个选项:
Distribution: ubuntu
Release: xenial
Architecture: amd64
选择后点击 Enter,rootfs将在本地下载并配置。出于安全原因,每个容器不附带OpenSSH服务器或用户帐户。同时也不会提供默认的root密码。要更改root密码并登录,必须在容器目录路径中运行lxc-attach或chroot(在启动之后)。
启动容器:
$ sudo lxc-start -n example-container -d
-d选项表示隐藏容器,它会在后台运行。如果您想要观察boot的过程,只需要将 -d换成 -F。那么它将在前台运行,登录框出现时结束。
你可能会遇到如下错误:
$ sudo lxc-start -n example-container -d
lxc-start: tools/lxc_start.c: main: 366 The container
failed to start.
lxc-start: tools/lxc_start.c: main: 368 To get more details,
run the container in foreground mode.
lxc-start: tools/lxc_start.c: main: 370 Additional information
can be obtained by setting the --logfile and --logpriority
options.
如果你遇到了,您需要通过在前台运行lxc-start服务来调试它:
$ sudo lxc-start -n example-container -F
lxc-start: conf.c: instantiate_veth: 2685 failed to create veth
pair (vethQ4NS0B and vethJMHON2): Operation not supported
lxc-start: conf.c: lxc_create_network: 3029 failed to
create netdev
lxc-start: start.c: lxc_spawn: 1103 Failed to create
the network.
lxc-start: start.c: __lxc_start: 1358 Failed to spawn
container "example-container".
lxc-start: tools/lxc_start.c: main: 366 The container failed
to start.
lxc-start: tools/lxc_start.c: main: 370 Additional information
can be obtained by setting the --logfile and --logpriority
options.
从以上示例,你可以看到模块 veth没有被引入,在引入之后,将会解决这个问题。
之后,打开第二个terminal窗口,验证容器的状态。
$ sudo lxc-info -n example-container
Name: example-container
State: RUNNING
PID: 1356
IP: 10.0.3.28
CPU use: 0.29 seconds
BlkIO use: 16.80 MiB
Memory use: 29.02 MiB
KMem use: 0 bytes
Link: vethPRK7YU
TX bytes: 1.34 KiB
RX bytes: 2.09 KiB
Total bytes: 3.43 KiB
也可以通过另一种方式来查看所有安装的容器,运行命令:
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6
example-container RUNNING 0 - 10.0.3.28 -
但是问题是你仍然不能登录进去,你只需要直接attach到正在运行的容器,创建你的用户,使用 passwd命令改变相关的密码。
$ sudo lxc-attach -n example-container
root@example-container:/#
root@example-container:/# useradd petros
root@example-container:/# passwd petros
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
更改密码后,您将能够从控制台直接登录到容器,而无需使用 lxc-attach命令:
$ sudo lxc-console -n example-container
如果要通过网络连接到此运行容器,请安装OpenSSH服务器:
root@example-container:/# apt-get install openssh-server
抓取容器的本地IP地址:
root@example-container:/# ip addr show eth0|grep inet
inet 10.0.3.25/24 brd 10.0.3.255 scope global eth0
inet6 fe80::216:3eff:fed8:53b4/64 scope link
然后在主机的新的控制台窗口中键入:
$ ssh 10.0.3.25
瞧!您现在可以SSH到正在运行的容器并键入您的用户名和密码。
在主机系统上,而不是在容器内,可以观察在启动容器后启动和运行的LXC进程:
$ ps aux|grep lxc|grep -v grep
root 861 0.0 0.0 234772 1368 ? Ssl 11:01
↪0:00 /usr/bin/lxcfs /var/lib/lxcfs/
lxc-dns+ 1155 0.0 0.1 52868 2908 ? S 11:01
↪0:00 dnsmasq -u lxc-dnsmasq --strict-order
↪--bind-interfaces --pid-file=/run/lxc/dnsmasq.pid
↪--listen-address 10.0.3.1 --dhcp-range 10.0.3.2,10.0.3.254
↪--dhcp-lease-max=253 --dhcp-no-override
↪--except-interface=lo --interface=lxcbr0
↪--dhcp-leasefile=/var/lib/misc/dnsmasq.lxcbr0.leases
↪--dhcp-authoritative
root 1196 0.0 0.1 54484 3928 ? Ss 11:01
↪0:00 [lxc monitor] /var/lib/lxc example-container
root 1658 0.0 0.1 54780 3960 pts/1 S+ 11:02
↪0:00 sudo lxc-attach -n example-container
root 1660 0.0 0.2 54464 4900 pts/1 S+ 11:02
↪0:00 lxc-attach -n example-container
要停止容器,请键入(在主机):
$ sudo lxc-stop -n example-container
停止后,验证容器的状态:
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6
example-container STOPPED 0 - - -
$ sudo lxc-info -n example-container
Name: example-container
State: STOPPED
要彻底销毁容器 - 即从主机system—type清除它:
$ sudo lxc-destroy -n example-container
Destroyed container example-container
销毁后,可以验证是否已将其删除:
$ sudo lxc-info -n example-container
example-container doesn't exist
$ sudo lxc-ls -f
$
注意:如果您尝试销毁正在运行的容器,该命令将失败并告知您容器仍在运行:
$ sudo lxc-destroy -n example-container
example-container is running
在销毁容器前必须先停止它。
高级配置
$ sudo su
# cd /var/lib/lxc
# ls
example-container
容器的父目录将包含至少两个文件:1)容器配置文件和2)容器的整个rootfs:
# cd example-container/
# ls
config rootfs
假设您想要在主机系统启动时自动启动名称为 example-container的容器。那么您需要将以下行添加到容器的配置文件`/ var / lib / lxc / example-container / config`的尾部:
# Enable autostart
lxc.start.auto = 1
重新启动容器或重新启动主机系统后,您应该看到如下内容:
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6
example-container RUNNING 1 - 10.0.3.25 -
注意 AUTOSTART 字段现在被设置为“1”。
如果在容器启动时,您希望容器绑定装载主机上的目录路径,请将以下行添加到同一文件的尾部:
# 将挂载系统路径绑定到本地路径
lxc.mount.entry = /mnt mnt none bind 0 0
通过上面的示例,当容器重新启动时,您将看到容器本地的 / mnt目录可访问的主机/ mnt目录的内容。
特权与非特权容器
根据设计,无特权容器被认为比特权容器更安全,更保密。无特权容器运行时,容器的root UID映射到主机系统上的非root UID。这使得攻击者即使破解了容器,也难以获得对底层主机的root权限。简而言之,如果攻击者设法通过已知的软件漏洞破坏了您的容器,他们会立即发现自己无法获取任何主机权限。
特权容器可能使系统暴露于此类攻击。这就是为什么我们最好在特权模式下运行尽量少的容器。确定需要特权访问的容器,并确保付出额外的努力来定期更新并以其他方式锁定它们。
然而,Docker又是什么呢?
Docker主要关注于:
可移植性:Docker提供基于镜像的部署模型。这种类型的可移植性允许更简单的方式在多个环境中共享应用程序或服务集合(以及它们的所有依赖)。
版本控制:单个Docker镜像由一系列组合层组成。每当镜像被更改时,都会创建一个新层。例如,每次用户指定命令(例如运行或复制)时,都会创建一个新层。Docker将重用这些层用于新的容器构建。分层到Docker是它自己的版本控制方法。
回滚:再次,每个Docker镜像都有很多层。如果您不想使用当前运行的层,则可以回滚到以前的版本。这种敏捷性使软件开发人员可以更轻松地持续集成和部署他们的软件技术。
快速部署:配置新硬件通常需要数天时间。并且,安装和配置它的工作量和开销是非常繁重的。使用Docker,您可以在几秒钟将镜像启动并运行,相比于之前,节省了大量的时间。当你使用完一个容器时,你可以轻松地销毁它。
从本质上说,Docker和LXC都非常相似。它们都是用户空间和轻量级虚拟化平台,它们利用cgroup和命名空间来管理资源隔离。但是,两者之间也存在许多明显的差异。
进程管理
Docker将容器限制为单个进程运行。如果您的应用程序包含X个并发进程,Docker将要求您运行X个容器,每个容器都有自己单独的进程。LXC不是这样,LXC运行具有传统init进程的容器,反过来,可以在同一容器内托管多个进程。例如,如果要托管LAMP(Linux + Apache + MySQL + PHP)服务器,每个应用程序的每个进程都需要跨越多个Docker容器。
状态管理
Docker被设计为无状态,意味着它不支持持久存储。有很多方法可以解决这个问题,但同样,只有在进程需要时才需要它。创建Docker镜像时,它将包含只读层。这不会改变。在运行时,如果容器的进程对其内部状态进行任何更改,则将保持内部状态和镜像的当前状态之间的差异,直到对Docker镜像进行提交(创建新层)或直到容器被删除,差异也会消失。
可移植性
在讨论Docker时,这个词往往被过度使用——因为它是Docker相对于LXC的最重要的优势。Docker从应用程序中抽象出网络,存储和操作系统细节方面做得更好。这样就形成了一个真正独立于配置的应用程序,保证应用程序的环境始终保持不变,无论启用它的机器配置环境如何。
Docker旨在使开发人员和系统管理员都受益。它已成为许多DevOps(开发人员+维护人员)工具链中不可或缺的一部分。开发人员可以专注于编写代码,而无需担心最终托管它的系统是什么。使用Docker,无需安装和配置复杂数据库,也无需担心在不兼容的语言工具链版本之间切换。Docker为维护人员提供了更多的灵活性,通常可以减少托管一些较小和更基本的应用程序所需的物理系统数量。Docker简化了软件交付。新功能和错误/安全修复程序可以快速到达客户,无需任何麻烦,意外或停机。
总结
在本系列的第三部分中,我将讲述如何使用Kubernetes的容器编排。
原文链接:https://www.linuxjournal.com/content/everything-you-need-know-about-linux-containers-part-ii-working-linux-containers-lxc
基于Kubernetes的DevOps实战培训
![640?wx_fmt=jpeg](https://i-blog.csdnimg.cn/blog_migrate/966b0700475f93c3540ce8f3caa4e4ae.jpeg)