在CentOS 8上使用LXC/LXD运行Linux容器
LXC
Linux容器项目(LXC)是一个开源容器平台,提供了一组工具,模板,库和语言绑定。它提供的容器包括一个完整的Linux系统,就像一个VM,具有自己的文件系统,网络和多个应用程序。 LXC具有简单的命令行界面,可改善启动容器时的用户体验(RedHat,2017年)。通过功能强大的API和简单的工具,它使Linux用户可以轻松创建和管理系统或者应用程序容器。在进行容器化之前,Docker是在LXC之上构建的,但是从那以后他们就开始使用容器化了。
LXC的特点
当前的LXC使用以下内核功能来包含进程:来源:LinuxContainers
内核名称空间(ipc,uts,mount,pid,网络和用户)Apparmor和SELinux配置文件安全策略Chroots(使用ivot_root)内核功能CGroups(控制组)
LXD
LXD是下一代系统容器管理器。它是用于管理LXC系统容器的惊人界面,不应将其误解为平台或者容器类型。 LXD的功能包括快照和图像控制。我们可以猜测,LXD增强了LXC技术的功能。它提供类似于虚拟机的用户体验,但是使用Linux容器。
LXD的功能来源:LinuxContainers
LXD的一些最大功能是:通过设计确保安全(无特权的容器,资源限制等等)可扩展的(从便携式计算机上的容器到数千个计算节点)直观的(简单,清晰的API和清晰的命令行体验)基于图像的(每天发布各种Linux发行版)支持跨主机容器和镜像传输(包括使用CRIU进行实时迁移)高级资源控制(CPU,内存,网络I/O,块I/O,磁盘使用率和内核资源)设备直通(USB,GPU,Unix字符和块设备,NIC,磁盘和路径)网络管理(网桥创建和配置,跨主机隧道)存储管理(支持多个存储后端,存储池和存储卷)
在CentOS 8上安装LXC/LXD
如果我们希望在CentOS 8服务器上试用LXC/LXD来运行某些应用程序,以下步骤将尽快准备好平台使用。
更新并准备服务器
这是非常关键的一步,在此步骤中,我们通过确保安装了最新的补丁程序和软件包来确保房屋装修良好。继续运行以下命令以准备服务器。
sudo dnf update -y && sudo dnf upgrade -y sudo dnf install -y vim curl nano
禁用SELinux
如果我们擅长管理SELinux上下文,那么这是一个可选步骤。要使其宽松,请运行以下命令
sudo setenforce 0 sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
启用并配置EPEL存储库
运行以下命令以在CentOS 8上安装并启用EPEL存储库,然后更新服务器以从Epel获取最新软件包。
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm sudo dnf update
在CentOS 8上安装快照
在此设置中,我们将安装Snappys LXD软件包,因为它具有Snap软件包所具有的简单性和支持。因此,我们需要在服务器上安装snapd,如下所示:
sudo yum install snapd -y
安装后,需要启用用于管理主快照通信套接字的systemd单元:
sudo systemctl enable --now snapd.socket
要启用经典快照支持,请输入以下内容在/var/lib/snapd/snap和/snap之间创建符号链接:
sudo ln -s /var/lib/snapd/snap /snap
注销并重新登录,或者重新启动系统以确保正确更新快照路径。一旦安装好快照,让我们继续下一步。
添加内核参数
LXD需要一些重要的内核选项,我们将在服务器上启用该选项。通过以root用户身份在终端上运行以下命令来配置它们。
$sudo su # grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)" # grubby --args="namespace.unpriv_enable=1" --update-kernel="$(grubby --default-kernel)" # echo "user.max_user_namespaces=3883" | sudo tee -a /etc/sysctl.d/99-userns.conf
配置这些设置后,由于核心内核功能已更改,因此需要重新引导服务器。重新启动服务器。
sudo reboot
在CentOS 8上安装lxd snap
最后,在服务器备份之后,就该退出从Snap存储中安装的目标软件包LXD。就像制作Snap一样简单,我们只需要运行以下命令,便会安装我们的LXD。
$sudo snap install --classic lxd
启动测试LXD容器
到目前为止,我们已经安装了LXC/LXD,但是还没有容器可以容纳我们感兴趣的应用程序。因此,在启动某些容器之前,让我们将用户帐户添加到组lxd中,以便它在没有权限限制的情况下管理LXD容器。
sudo usermod -aG lxd <your-username> newgrp lxd
注意:newgrp命令用于在登录会话期间更改当前组ID。如果给出了可选标志,则用户环境将被重新初始化,就像用户已登录一样,否则当前环境(包括当前工作目录)保持不变。 newgrp将当前的真实组ID更改为命名组。
接下来,让我们配置LXD环境或者通过运行以下命令对其进行初始化。它会带我们解决几个问题。请根据环境需求回答。我将默认值用于空白值。
$lxd init Would you like to use LXD clustering? (yes/no) [default=no]: Do you want to configure a new storage pool? (yes/no) [default=yes]: Name of the new storage pool [default=default]: Name of the storage backend to use (btrfs, dir, lvm, ceph) [default=btrfs]: lvm Create a new LVM pool? (yes/no) [default=yes]: Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]: Size in GB of the new loop device (1GB minimum) [default=9GB]: 5GB Would you like to connect to a MAAS server? (yes/no) [default=no]: Would you like to create a new local network bridge? (yes/no) [default=yes]: What should the new bridge be called? [default=lxdbr0]: What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: Would you like LXD to be available over the network? (yes/no) [default=no]: Would you like stale cached images to be updated automatically? (yes/no) [default=yes] Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
上面的命令将创建一个桥lxdbr0。我们将这个桥接接口添加到可信区域,以便连接通过。换句话说,我们将允许通过lxdbr0的所有传入流量。执行以下防火墙命令
sudo firewall-cmd --add-interface=lxdbr0 --zone=trusted --permanent sudo firewall-cmd --reload
创建容器
初始化lxd并通过lxc命令为用户授予启动和管理容器的权限后,让我们创建一个容器。以下语法可用作指导:
lxc launch images:[distro]/[version]/[architecture] [your-container-name]
现在我们已经足够开悟,并且不费吹灰之力,让我们通过运行以下命令来创建测试CentOS 8和Ubuntu 20.04容器:
$lxc launch images:centos/8/amd64 cent8 Creating cent8 Retrieving image: Unpack: 100% (4.22GB/s) Starting cent8
通过运行以下命令启动Ubuntu容器:
$lxc launch ubuntu:20.04 ubuntu20 Creating ubuntu20 Starting ubuntu20
一旦启动它们,我们可以轻松列出容器,从而:
$lxc list +-------+---------+---------------------+-----------------------------------------------+-----------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------+---------+---------------------+-----------------------------------------------+-----------+-----------+ | cent8 | RUNNING | 10.80.35.177 (eth0) | fd42:b3a2:efa8:5aa5:216:3eff:fe1d:38c3 (eth0) | CONTAINER | 0 | +-------+---------+---------------------+-----------------------------------------------+-----------+-----------+
我们还可以停止,启动,重新启动,删除以及检查容器的更多信息,如下所示,其中<container>是容器的名称,如lxc list命令所示。
lxc start <container> lxc stop <container> lxc restart <container> lxc delete <container>
例如
lxc stop ubuntu20 lxc delete ubuntu20
请注意,必须先停止正在运行的容器,然后才能将其删除。
使用info命令选项获取有关容器的信息
$lxc info container ##For example $lxc info cent8
示例出色的输出:
Name: cent8 Location: none Remote: unix:// Architecture: x86_64 Created: 2017/11/07 11:25 UTC Status: Running Type: container Profiles: default Pid: 2724 Ips: eth0: inet 10.80.35.177 veth975e84ff eth0: inet6 fd42:b3a2:efa8:5aa5:216:3eff:fe1d:38c3 veth975e84ff eth0: inet6 fe80::216:3eff:fe1d:38c3 veth975e84ff lo: inet 127.0.0.1 lo: inet6 ::1 Resources: Processes: 13 Disk usage: root: 737.98MB CPU usage: CPU usage (in seconds): 1 Memory usage: Memory (current): 93.32MB Memory (peak): 98.56MB Network usage: eth0: Bytes received: 3.57kB Bytes sent: 2.22kB Packets received: 30 Packets sent: 22 lo: Bytes received: 0B Bytes sent: 0B Packets received: 0 Packets sent: 0
在容器中执行临时命令:
就像可以在Docker容器中执行的方式一样,我们也可以在lxd容器内运行命令。语法是这样的。
$lxc exec <container-name> <command>
执行命令的示例如下:
$lxc exec cent8 -- yum -y update CentOS-8 - AppStream 538 kB/s | 5.8 MB 00:11 CentOS-8 - Base 619 kB/s | 2.2 MB 00:03 CentOS-8 - Extras 8.1 kB/s | 8.1 kB 00:01 Dependencies resolved. Nothing to do. Complete!
让我们在容器中安装Apache
$lxc exec cent8 -- yum -y install httpd Last metadata expiration check: 0:00:41 ago on Sat Nov 7 12:56:38 2017. Dependencies resolved. ====================================================================================================================================== Package Architecture Version Repository Size ======================================================================================================================================Installing: httpd x86_64 2.4.37-21.module_el8.2.0+494+1df74eae AppStream 1.7 M Installing dependencies: apr x86_64 1.6.3-9.el8 AppStream 125 k apr-util x86_64 1.6.1-6.el8 AppStream 105 k
安装后,我们可以登录到容器,创建示例页面,启动Web服务器并检查其状态
$lxc exec cent8 -- /bin/bash ##We are now in the container [theitroad@localhost ~]# systemctl start httpd [theitroad@localhost ~]# systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2017-11-07 12:58:09 UTC; 5s ago Docs: man:httpd.service(8) Main PID: 175 (httpd) Status: "Started, listening on: port 80" Tasks: 213 (limit: 11069) Memory: 27.6M CGroup: /system.slice/httpd.service ├─175 /usr/sbin/httpd -DFOREGROUND ├─176 /usr/sbin/httpd -DFOREGROUND ├─177 /usr/sbin/httpd -DFOREGROUND ├─178 /usr/sbin/httpd -DFOREGROUND └─179 /usr/sbin/httpd -DFOREGROUND
在容器中创建示例页面,以供Apache进行演示
[theitroad@localhost ~]# vi /var/www/html/index.html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" <title>hello</title> <LINK href="styles.css" rel="stylesheet" type="text/css"> </head> <body> hello </body> </html>
然后在容器内重新启动Apache并退出。
[theitroad@localhost ~]# systemctl restart httpd
从外部访问容器内的应用程序
好了,既然我们已经将应用程序部署在给定的容器上(例如,上述命令中的Apache),那么目标受众将如何准确地从外部访问我们托管的内容?我们可以使用防火墙规则,也可以更优雅地使用,可以部署反向代理以将流量路由到应用程序。
使用反向代理服务器,例如Nginx
在CentOS 8主机系统上安装Nginx Web服务器:
sudo yum -y install vim nginx
设置服务的Nginx HTTP代理
创建一个新的配置文件。
sudo nano /etc/nginx/conf.d/app1.conf
修改此配置代码段以适合设置。请注意,Nginx将在端口9090上侦听,然后将流量重定向到Apache在端口80运行的容器。
##App1 Upstreams upstream app1 { server 10.80.35.177:80; ##Notice the IP of the container here. } server { listen 9090; server_name app1.theitroad.local; access_log /var/log/nginx/app1_access.log; error_log /var/log/nginx/app1_error.log; # Proxy settings proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; # Request for root domain location/{ proxy_redirect off; proxy_pass http://app1; } # Gzip gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript; gzip on; }
有效的DNS记录对于应用程序的外部(公共)访问是必需的。
检查配置语法:
$sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
如果设置返回正反馈,请重新启动nginx服务。
sudo systemctl restart nginx
允许防火墙上的端口9090
sudo firewall-cmd --permanent --add-port=9090/tcp sudo firewall-cmd --reload
现在,我们准备访问我们的应用程序。打开我们喜欢的浏览器,并将其指向我们刚刚完成配置的FQDN或者Nginx代理的IP地址和端口。 http://<ip-or-fqdn>:9090。我们应该看到类似以下的页面。