AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 957761
Accepted
moutonjr
moutonjr
Asked: 2019-03-12 07:09:34 +0800 CST2019-03-12 07:09:34 +0800 CST 2019-03-12 07:09:34 +0800 CST

使用 Systemd machinectl 发布网络服务

  • 772

TL;DR:如何通过 machinectl/nspawn 容器向主机公开网络服务?

我正在努力使事情变得完美适合我的设置,即将我的服务安装在单独的chroot实例中。

systemd-nspawn要启动它们,我想使用and遵守 SystemD 管理machinectl:

# debootstrap stretch /var/lib/machines/mymachine
# machinectl start mymachine # works well!
# machinectl shell root@mymachine bash

然后我在上面安装 dummy apache2:

 (jail)# apt install -y apache2 && systemctl enable apache2 && systemctl start apache2
 (jail)# ss -tnlp | grep 80 # yields apache2 running.

但是,在主机上侦听时,80 端口(甚至任何端口,例如 8080)都不可见。如何使它工作?

谢谢团队,

systemd
  • 2 2 个回答
  • 1009 Views

2 个回答

  • Voted
  1. Best Answer
    Mark Wagner
    2019-03-12T10:07:45+08:002019-03-12T10:07:45+08:00

    您需要一个用于公开端口的机器的nspawn文件。

    [网络] 部分选项

    Port= 在主机上公开容器的 TCP 或 UDP 端口。此选项对应于 --port= 命令行开关,请参阅 systemd-nspawn(1) 了解此选项采用的参数的精确语法。此选项是特权(见上文)。

    从 systemd-nspawn(1):

    -p, --port= 如果启用了私有网络,则将主机上的 IP 端口映射到容器上的 IP 端口。采用协议说明符(“tcp”或“udp”),由冒号与主机端口号分隔,范围为 1 到 65535,由冒号与容器端口号分隔,范围为 1 到 65535。协议说明符及其分隔冒号可以省略,在这种情况下假定为“tcp”。容器端口号及其冒号可以省略,在这种情况下暗示与主机端口相同的端口。仅当使用专用网络时才支持此选项,例如使用 --network-veth、--network-zone= --network-bridge=。

    systemd- nspawn @.service 单元使用--network-veth

    所以像

    [Network]
    Port=80
    

    应该管用。

    • 1
  2. AveryFreeman
    2021-05-14T11:56:37+08:002021-05-14T11:56:37+08:00

    我只是在systemd-nspawn没有任何网络标志的情况下运行,它使用主机网络 - 然后使用 nginx 路由我的网络应用程序的端口。

    假设$MACHINE_NAME在webapp这种情况下:

    systemd-nspawn -D /var/lib/machines/webapp -M webapp --chdir=/ ./entrypoint &
    
    • -D是文件系统根目录,
    • -M是机器名称,
    • --chdir更改容器内的目录和
    • ./entrypoint是我要运行的脚本(可以是任何命令、脚本等)
    • &在后台运行它(因此您可以在运行命令的特定 tty 中执行其他操作)。

    该entrypoint脚本最初来自从该文件系统导出的 podman 容器。这是它正在做的事情(非常简单):

    #!/usr/bin/env bash
    cd /home/localuser/webapp
    npm run start
    

    所以这只是运行我在容器内开发的网络应用程序。它被指定在端口上运行3000。

    然后,将 nginx 设置为代理80,3000它在防火墙中有一个开放端口:

    # cat /etc/nginx/sites-available/webapp
    server {
        listen 80;
        server_name webapp.xyz;
    
        location / {
            proxy_set_header   X-Forwarded-For $remote_addr;
            proxy_set_header   Host $http_host;
            proxy_pass         "http://127.0.0.1:3000";
        }
    }
    

    您可以看到它正在使用环回设备 - 但是当在没有和没有systemd-nspawn的情况下运行时,您的任何主机网络都可以在容器内使用。这与这种方式非常相似。 --boot --network-{bridge,interface,ipvlan,macvlan,veth}chroot

    然后,一旦systemd-nspawn运行(在后台,因为&在命令的末尾),可以运行:

    machinectl enable $MACHINE_NAME
    

    它将从.nspawn模板生成带有机器名称的符号链接。

    .nspawn模板在这里:/lib/systemd/system/[email protected]

    $MACHINE_NAME.nspawn此处将添加链接:/etc/systemd/system/machines.target.wants/systemd-nspawn@$MACHINE_NAME.service

    如果您想默认使用主机网络运行新机器,只需备份原始并删除一些运行时参数:

    /* backup original unit file */
    
    # mv /lib/systemd/system/[email protected] \
         /lib/systemd/system/[email protected]
    
    /* echo a more simple file into its place */
    
    # echo '[Unit]
    Description=Container %i
    Documentation=man:systemd-nspawn(1)
    [email protected]
    PartOf=machines.target
    Before=machines.target
    After=systemd-resolved.service [email protected]
    RequiresMountsFor=/var/lib/machines/%i
    
    [Service]
    ExecStart=systemd-nspawn --quiet --keep-unit --link-journal=try-host --machine=%i --chdir=/ ./entrypoint
    KillMode=mixed
    Type=notify
    RestartForceExitStatus=133
    SuccessExitStatus=133
    Slice=machine.slice
    Delegate=yes
    TasksMax=16384
    WatchdogSec=3min
    
    DeviceAllow=char-pts rw
    DeviceAllow=/dev/loop-control rw
    DeviceAllow=block-loop rw
    DeviceAllow=block-blkext rw
    
    # these two only nec. for LUKS - can remove 
    DeviceAllow=/dev/mapper/control rw
    DeviceAllow=block-device-mapper rw
    
    [Install]
    WantedBy=machines.target' > /lib/systemd/system/[email protected]
    

    您可以在这里看到在单元文件中运行的命令基本相同,我只是添加了 flag --link-journal=try-host,它放置了一个/var/log/journal/$MACHINE_UUID用于监视容器的日志。

    由于这是一个模板,它假设我将调用一个entrypoint从每个容器的根目录命名的脚本,这给了它们更多的“命令调用容器”行为(例如 Docker 风格而不是 LXC 风格)。

    关于问题的说明:

    我想使用--user标志,但它似乎是非功能性 ATM。这里有一些关于标志回归的讨论,但它与 CentOS 上的 v237 相关,所以不确定它是否与 Ubuntu 20.04 上的 241 相关,这就是我正在使用的 ATM。无论如何,容器现在将使用 root UID 运行......

    systemd-networkd应该与--network-veth创建 DHCP 主机host0和客户端一起使用ve-$MACHINE_NAME(限制 16 个字符) -如果主机和客户端都使用systemd-networkd. 但是,在 Ubuntu 20.04 上,我无法让它在实践中正常工作。我猜有一个错误:我的 systemd 版本中有这个功能,并将在以后的版本中做进一步的测试。

    环境信息:

    # cat /etc/os-release && systemd --version
    NAME="Ubuntu"
    VERSION="20.04.2 LTS (Focal Fossa)"
    ID=ubuntu
    ID_LIKE=debian
    PRETTY_NAME="Ubuntu 20.04.2 LTS"
    VERSION_ID="20.04"
    HOME_URL="https://www.ubuntu.com/"
    SUPPORT_URL="https://help.ubuntu.com/"
    BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
    PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
    VERSION_CODENAME=focal
    UBUNTU_CODENAME=focal
    systemd 245 (245.4-4ubuntu3.6)
    +PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid
    

    进一步阅读:

    • man systemd-nspawn
    • man systemd.nspawn(.nspawn 文件规范)
    • 人机控制
    • systemd-nspawn 上的 arch wiki
    • 1

相关问题

  • SSH 会话在关机/重启时挂起

  • 我可以使用 systemd 重新启动依赖服务吗?

  • 让我的旧初始化脚本在 systemd 中工作的最简单方法是什么?

  • 在 CentOS 7 上为 systemd 启动的进程增加 nproc

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve