<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      systemd-nspawn容器實戰【鏡像精簡到3MB,容器使用獨立網絡】




      前言

      以前我的樹莓派服務是放docker容器中的,但是后來docker訪問受限,于是就用systemd-nspawn容器替代。systemd-nspawn容器的功能相對docker而言沒那么豐富,但是勝在簡單、輕量、便利。
      本博文是作者“進取有樂”原創,僅發布于博客園,轉載請注明出處。


      需求

      容器大小:我不喜歡太大的容器,所以容器要精簡,經過我精簡后的鏡像只有幾MB大小。我的服務有花生殼、小米球、vlmcsd(KMS服務器)
      容器網絡:我希望不使用宿主機網絡空間,使用容器獨立的網絡。可以使用橋接、macvlan、ipvlan等,橋接網絡麻煩點,所以這里詳細介紹橋接網絡。其他如macvlan、ipvlan、network-zone、veth等操作比較簡單,在文末介紹。


      精簡容器體積

      為了精簡容器,開始時,我想要用alphine,但是后來發現我的某個服務在alpine下面無法運行,所以我使用了debian的initrd.gz,initrd是linux系統啟動過程中的一個最小化內存盤系統。
      !!注意: 下面操作容器的usr var etc等目錄的時候,不要在路徑前面加/, 否則會損壞宿主機的系統!!

      cd /tmp; wget https://mirrors.tuna.tsinghua.edu.cn/debian/dists/bookworm/main/installer-arm64/current/images/cdrom/initrd.gz #下載適用于arm64架構的debian12的initrd.gz。最近穩定版是debian13 https://mirrors.tuna.tsinghua.edu.cn/debian/dists/stable/main/installer-arm64/current/images/cdrom/initrd.gz
      mkdir -p /opt/unsafe/base; cd /opt/unsafe/base; # 創建一個目錄,用于后續操作
      gzip -dc /tmp/initrd.gz |cpio -idm; # 解包
      rm -v bin sbin lib; mv -v usr/{bin,sbin,lib} ./; rm -rfv initrd usr/* var/* # 刪掉根下的bin sbin lib三個軟連接,把usr/下的bin、sbin、lib三個目錄移動到根下。刪掉initrd/目錄,刪掉usr/ var/下的所有數據(而不刪除目錄本身)
      cd bin; ls -l |grep '^-' |awk '{print $NF}' # 查看bin/下有很多軟連接和常規文件,除了busybox這個常規文件外(busybox保證基本shell),其他常規文件用處不大,下面一條命令會刪除它們。
      rm -v $(ls -l |grep '^-' |awk '!/busybox/{print $NF}' |xargs) # bin/下除了busybox,其他的常規文件都刪除
      cd ../sbin; rm -v $(ls -l |grep '^-' |awk '{print $NF}') # sbin/下所有常規文件刪掉,保留軟連接
      ldd /tmp/phtunnel; ldd /tmp/xiaomiqiu; ldd /tmp/vlmcsd-armv7el-uclibc-static # 查看我的花生殼、小米球、vlmcsd需要依賴什么動態庫。執行后發現,后兩者是靜態可執行文件,花生殼(phtunnel)依賴的動態庫如下

             linux-vdso.so.1 
             libpthread.so.0
             libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 
             /lib/ld-linux-aarch64.so.1 
             libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6   
      

      cd ../lib; find . -regextype egrep -regex ".*(linux-vdso|libpthread|libc|ld-linux-aarch64|libm)\.so.*" # 在lib/下找一下這幾個文件
      find . -type f -regextype egrep ! -regex ".*(linux-vdso|libpthread|libc|ld-linux-aarch64|libm)\.so.*" -delete # find命令增加取反"!"操作,刪除lib/下除了上面依賴庫之外的所有文件
      cd ../etc; find . -regextype egrep ! -regex ".*(passwd|group|fstab)" -delete # 刪除etc/下除了passwd、group、fstab之外的所有文件或目錄
      cp -v /etc/os-release ./ # 把宿主機的os-release 復制到容器etc目錄,沒有這個文件,容器啟動不了。
      cd ../; while :; do x="$(find . -mindepth 2 -type d -empty |xargs)"; if [ -n "$x" ]; then rm -rfv $x; else break; fi; done # 回到容器的根,刪除深度至少是2層的空目錄,因為有些子目錄刪除后會導致父目錄也變成空目錄,所以要循環刪除
      du -sh # 查看容器的根,發現占用空間是3M。這個體積已經滿意了。但是精簡后也要缺點,就是容器啟動的時候不能使用-b參數(boot),一些網絡配置文件無法使用,只能容器啟動后動態執行網絡配置命令。


      創建目錄結構

      useradd -d /opt/unsafe unsafe # 創建unsafe用戶,家目錄是/opt/unsafe
      cd /var/lib/machines; ln -s /opt/unsafe/base hsk; ln -s /opt/unsafe/base xmq; ln -s /opt/unsafe/base vlmcsd # 在/var/lib/machines目錄下創建hsk、xmq、vlmcsd三個軟連接,三個軟連接都指向/opt/unsafe/base的容器文件根系統。
      mkdir /opt/unsafe/base/app # 在容器根下面創建一個app目錄用于綁定三個服務的二進制路徑
      mkdir /opt/unsafe/{hsk,xmq,vlmcsd} # 在/opt/unsafe目錄下創建hsk、xmq、vlmcsd目錄用來存放這三個服務的二進制文件和配置文件。
      chown -R unsafe:unsafe /opt/unsafe; chmod 755 /opt/unsafe # 遞歸修改unsafe目錄屬主。修改家目錄權限


      測試容器是否正常啟動

      systemd-nspawn --machine hsk --bind=/opt/unsafe/hsk:/app --read-only --private-users=2048:65535 # 啟動容器,這里的--machine hsk 也可以寫成--directory /var/lib/machines/hsk, 因為/var/lib/machines下有了hsk目錄,所以這里才可以寫成--machine hsk, 否則必須指明容器根目錄路徑。 --bind表示把宿主機的目錄綁定到容器的/app路徑下, --private-users 2048:65535表示容器是以這個范圍內的uid來啟動,宿主機執行ps auxf就能看到進程的uid是大于等于2048的。執行了這個命令后,就進入了容器的shell界面。
      /app/phtunnel -c /app/phtunnel.json # 在容器的shell命令下啟動花生殼,發現正常。同樣的步驟,小米球和vlmcsd測試都正常。(我是直接測試,建議先在宿主機測試好,調好配置文件,然后再在容器內測試)。敲Ctrl+]組合鍵3次退出容器


      創建并測試容器的獨立網絡

      我的樹莓派連接的網關是192.168.1.1;宿主系統的網絡是用NetworkManager管理網絡的,NetworkManager執行命令后會在/etc/NetworkManager/system-connections/形成配置文件。現在我的樹莓派是使用有線連接的(如果是wifi連接,需要特殊處理,見后文)。這里使用橋接網絡給容器使用。
      nmcli connection add type bridge con-name br1 ifname br1 ipv4.method manual ipv4.addresses "192.168.1.101/24" ipv4.gateway "192.168.1.1" ipv4.dns "223.5.5.5,119.29.29.29" # 創建一個橋接網絡接口br1
      nmcli connection add type bridge-slave con-name br1-slave-eth0 ifname eth0 master br1 # 把eth0接口加入br1
      nmcli connection show # 看看eth0對應的連接的NAME字段是什么,一般是"Wired connection 1",有那么就刪掉它 nmcli connection delete "Wired connection 1",防止該連接和br1的slave網口沖突
      nmcli connection up br1 # 使br1處于up狀態。此時nmcli connection show br1發現它是自動連接的。
      systemd-nspawn --machine hsk --bind=/opt/unsafe/hsk:/app --read-only --private-users=2048:65535 --network-bridge=br1 # 啟動hsk容器,進入容器shell,容器的host0網口和宿主機的br1是橋接在一起的
      ip link set host0 up; ip a a 192.168.1.102/24 dev host0 #在容器內的shell中啟用host0網口,并配上ip地址。大概在配好ip后30多秒才能ping通網關192.168.1.1
      ip route add default via 192.168.1.1 dev host0 # 添加默認路由,ping baidu.com通了。


      以systemd服務來管理

      上面的測試通過后,形成服務文件,服務文件的形式有兩種,一種是常規的"服務名.service"文件,一種是systemd-nspwan容器的"服務名.nspawn"文件。注意在/etc/systemd/nspawn/目錄下的 .nspawn配置文件是被信任的,/var/lib/machines/下的.nspawn文件是不被信任的(不信任場景下,執行systemd-nspawn -M name時,會忽略一些系統級命令)。.nspawn服務是使用類似"systemctl start systemd-nspawn@服務名.service"來管理服務的。我使用的是常規的.service文件。
      以花生殼的.service服務文件為例: cat /lib/systemd/system/hsk.service

          [Unit]
          Description=hsk(phtunnel) service
          After=network-online.target
          Wants=network-online.target
          
          [Service]
          # 如果想要服務啟動過程及運行日志,請執行journalctl -feu hsk ,下面啟動過程使用循環ping檢查網關連通性,通了之后再啟動服務。
          ExecStart=systemd-nspawn --bind=/opt/unsafe/hsk:/app --read-only --private-users=2048:65535\
                                   --machine hsk --network-bridge=br1 /bin/sh -c 'ip link set host0 up; ip addr add 192.168.1.111/24 dev host0;\
                                   ip route add default via 192.168.1.1 dev host0; echo "等待網絡..."; \
                                   while :; do ping -c1 -w1 -W1 192.168.1.1 >/dev/null 2>&1 && break; done;\
                                   /app/phtunnel -c /app/phtunnel.json;'
          
          Restart=always
          RestartSec=30s
          ProtectSystem=yes
          
          [Install]
          WantedBy=multi-user.target
      

      執行systemctl start hsk 啟動花生殼服務的容器,執行systemctl enable hsk 使花生殼服務開機啟動。小米球、vlmcsd服務也用類似步驟完成。只是容器ip地址和命令行不同:
      /app/xiaomiqiu -log stdout -log-level error -config /app/xiaomiqiu.conf
      /app/vlmcsd-armv7el-uclibc-static -D -l syslog


      通過wifi連接網關的容器配置

      • 如果使用wifi連接網關(我的wlan0的ip地址是192.168.1.X),由于wifi網絡接口無法加入橋接網口,所以網絡配置方法也和有線網連的不同。
        nmcli connection add type bridge con-name br0 ifname br0 ipv4.method manual ipv4.addresses "192.168.100.1/24" # 創建一個橋接網絡接口br0
        nmcli connection up br0 # 使br0處于up狀態。
        修改/etc/sysctl.conf文件,使net.ipv4.ip_forward=1 然后執行sysctl -p立即生效。我的樹莓派是Debian12,如果是Debian 13則默認不再讀取 /etc/sysctl.conf,需將配置分散到 /etc/sysctl.d/ 目錄下的獨立文件。
        增加nftables的NAT:讓容器中的花生殼、小米球和能經由wlan0訪問公網(masqurade),也讓外部網絡經由wlan0訪問容器中vlmcsd提供的KMS服務(DNAT)。下面是nftables.conf內容:cat /etc/nftables.conf

          flush ruleset
          
          table ip tb_pi {
                  chain ch_fwd {
                          type filter hook forward priority filter; policy accept;
                          iifname "br0" ip saddr 192.168.100.0/24 accept
                          ct state established,related accept
                  }
          
                  chain ch_snat {
                          type nat hook postrouting priority srcnat; policy accept;
                          oifname "wlan0" ip saddr 192.168.100.0/24  masquerade
                  }
          
                  chain ch_dnat {
                          type nat hook prerouting priority 100; policy accept;
                          tcp dport 1688 dnat to 192.168.100.13
                  }
          }
        

        上面的nftables配置文件要配合nftables服務生效,確保nftables服務是開機啟動的,確保nftables.service文件讀取的配置文件路徑是/etc/nftables.conf。沒問題后,執行systemctl restart nftables 重新載入配置文件。
        花生殼的.service文件和有線網連接的也不同,比如ip地址,默認路由、測試ping的地址等。服務配置文件內容如下,cat /lib/systemd/system/hsk.service

          [Unit]
          Description=hsk(phtunnel) service
          After=network-online.target
          Wants=network-online.target
          
          [Service]
          # 使用while ping檢查宿主機br0網口,通了之后再啟動服務。
          ExecStart=systemd-nspawn --bind=/opt/unsafe/hsk:/app --read-only --private-users=2048:65535\
                                   --directory /var/lib/machines/hsk --network-bridge=br0 \
                                   /bin/sh -c 'ip link set host0 up; ip addr add 192.168.100.11/24 dev host0;\
                                   ip route add default via 192.168.100.1 dev host0; echo "等待網絡..."; \
                                   while :; do ping -c1 -w1 -W1 192.168.100.1 >/dev/null 2>&1 && break; done;\
                                   /app/phtunnel -c /app/phtunnel.json;'
          
          Restart=always
          RestartSec=30s
          ProtectSystem=yes
          
          [Install]
          WantedBy=multi-user.target
        



      關于容器網絡的更多內容

      • 由于我是精簡鏡像,所以很多非常便利的功能不能實現。比如宿主機如果使用的是systemd-networkd服務管理網絡,則systemd-networkd.service默認包含 /usr/lib/systemd/network/80-container-ve.network , 此文件匹配所有通過該選項創建的虛擬以太網連接的宿主端接口, 此文件不但為這些接口啟用了DHCP功能,而且還為這些接口設置了通向宿主機外部網絡的路由(從而可以連通外網)。 該服務還默認包含 /usr/lib/systemd/network/80-container-host0.network , 此文件匹配所有通過該選項創建的虛擬以太網連接的容器端接口,并且為這些接口啟用了DHCP功能。 如果在宿主與容器內同時運行了systemd-networkd服務, 那么無須額外的配置,即可自動實現在容器與宿主之間進行IP通信,并且可以連接到外部網絡。

      • DHCP功能。如果宿主機開啟dnsmasq服務,并且把dhcp服務提供給指定網口(比如br0等),容器使用-b啟動,并且網口配置成dhcp自動獲取ip,則容器啟動后,即可獲取一個宿主機DHCP服務提供的IP地址

      • 容器的其他網絡選項
        --network-zone XX # 則宿主機產生一個叫"vz-XX"的網口,容器啟動后,生成一個host0網口。--network-zone XX 的形式穿件的網絡會自動在宿主機創建網絡接口(第一個容器啟動),自動銷毀(最后一個容器退出)。可以方便的將一組相關的本地容器,添加到基于虛擬以太網的同一個廣播域(也就是同一子網)之中。 這樣的廣播域就被稱為"區域"(zone)。如果結合前面的systemd-networkd的自動分配ip地址、聯通外網功能,會很方便。
        --network-veth-extra XX:YY # 容器啟動后,宿主機生產一個名字類似于XX@if2的虛擬網絡接口,這里的@if2表示宿主機的XX虛擬接口關聯的物理接口是序號為2的接口(ip link show命令查看發現序號2的接口是eth0)。使用ip address命令修改ip地址的時候,使用的接口名是XX,XX@if2后面的@if2要去掉。容器中的接口是YY@if39,這里的@if39表示容器的YY接口與宿主機的序號第39的接口關聯,在宿主機執行ip link show發現39號網絡接口的名字是XX。 當然參數也可以不用冒號和冒號后面的名字,表示宿主機和容器產生的網絡接口都是XX。
        --network-veth # 該選項不用帶參數,容器啟動后,宿主機會產生一個叫"ve-容器名"的虛擬網絡接口,虛擬機的網絡接口是host0。--network-veth 是使用 systemd-nspawn@容器名.service 模版配置文件是的默認選項。

        --network-macvlan 宿主機網口 # 該選項隱含--private-network。容器與宿主機的mac地址不同。例如--network-macvlan=eth0 進入容器后,我們會發現容器中mv-eth0的mac地址和宿主機eth0的mac地址不同。容器的mv-eth0需要設置up,并分配ip地址才可以使用(與宿主機的eth0同一個網段)。我測試發現不可以ping通宿主機ip,但是可以ping通同個局域網的其他主機。
        --network-ipvlan 宿主機網口 # 該選項隱含--private-network。容器與宿主機的mac地址相同。例如--network-ipvlan=eth0 進入容器后,我們會發現容器中iv-eth0的mac地址和宿主機eth0的mac地址相同。容器的iv-eth0需要設置up,并分配ip地址才可以使用(與宿主機的eth0同一個網段)。我測試發現不可以ping通宿主機ip,但是可以ping通同個局域網的其他主機。

      • 不管是哪種虛擬網絡,容器和宿主機的網口都要處于up狀態,想要通信就要分配ip地址。

      posted on 2025-09-24 16:09  進取有樂  閱讀(67)  評論(1)    收藏  舉報

      導航

      主站蜘蛛池模板: 91精品国产色综合久久| 日日噜噜夜夜爽爽| 久久久久无码中| 一个色综合色综合色综合| 高潮videossex潮喷| 田阳县| 亚洲精品自拍在线视频| 999国产精品一区二区| 亚洲国产综合自在线另类| 口爆少妇在线视频免费观看| 天天躁日日躁狠狠躁2018| 国精产品自偷自偷ym使用方法| 精品一区二区亚洲国产| 黄色特级片一区二区三区| 亚洲人成网站18禁止无码| 精品久久久久久无码专区不卡| 久久这里只精品热免费99| 四虎国产精品久久免费地址| 精品久久久久无码| 欧美人成在线播放网站免费| 丰满高跟丝袜老熟女久久| 国产老熟女国语免费视频| 国产中文字幕精品喷潮| 日本免费人成视频在线观看 | 合阳县| 亚洲一区二区av高清| 野花社区www视频日本| 2019nv天堂香蕉在线观看| 三级4级全黄60分钟| 日韩av天堂综合网久久| 亚洲a免费| 国产人妻精品午夜福利免费 | 亚洲鸥美日韩精品久久| 大地资源网中文第五页| 国产精品蜜臀av在线一区| 国内精品自线在拍| 成年午夜性影院| 国产一区二区三区不卡观| 亚洲成人av在线系列| 国产愉拍精品手机| 国产精品不卡一区二区三区|