首页 > 其他分享 >runc网络与systemd管理runc应用

runc网络与systemd管理runc应用

时间:2024-01-25 21:56:26浏览次数:21  
标签:systemd proc ip 网络 nginx runc netns type

1. 创建网络命名空间

ip netns add <ns>

# ns是自定义网络空间名

# 例如: ip netns add haproxy
# 创建一个给 haproxy使用的网络命名空间

# 新增一个网络空间会在 /var/run/netns/目录下生成和网络空间同名的文件

2. 创建虚拟网络设备对

ip link add <vname1> type veth peer name <vname2>

# vname1和vname2是虚拟网络设备对两端,类似pipeline
# 例如:ip link add haproxy-out type veth peer name haproxy-in'

3. 将虚拟网络设备对一端放入网络命名空间中

ip link set <vname2> netns <ns>

# 将虚拟网络设备对一端放入ns网络命名空间中
# 例如:ip link set haproxy-in netns haproxy

4. 分配IP地址给虚拟网络设备对并启动

ifconfig <vname1> <ip> netmask <mask> up
ip netns exec <ns> ifconfig <vname2> <ip> netmask <mask> up

# 注意两个网络设备对IP地址归属于同一个网段,子网掩码相同,up是启用网卡
# 例如:
# ifconfig haproxy-out 192.168.45.2 netmask 255.255.255.0 up
# ip netns exec haproxy ifconfig haproxy-in 192.168.45.3 netmask 255.255.255.0 ip

# ip 命令
ip netns exec <ns> ip addr add <ip>/<mask> dev <v2name> # 分配一个IP地址
ip netns exec <ns> ip link set <v2name> up # 启动网卡
ip netns exec <ns> ip link set lo up # 启动回环网卡

ip addr add <ip>/<mask> dev <v1name>
ip link set <v1name> up # 启动网卡

5. 命令空间中添加路由网关

ip netns exec <ns> route add default gw <vname1_ip>

# 路由网关是虚拟网络设备对其中一端放在主机端的IP地址
# 例如:
# ip netns exec haproxy route add default gw 192.168.45.2
# 查询:ip netns exec haproxy route -n

6. 主机开启路由转发 -- ip_forward

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p

7. 配置SNAT,将网络空间内的数据包源地址更改为主机网卡(eth0)地址

iptables -t nat -A POSTROUTING -s <ip/mask> -o eth0 -j MASQUERADE

# -o 指定出站网卡设备名
# -t 指定修改的规则表
# -s 指定匹配的源IP地址
# -A
# -j
# 例如:
# iptables -t nat -A POSTROUTING -s 192.168.45.0/24 -o eth0 -j MASQUERADE

8. 添加主机网络到虚拟网卡forward规则

iptables -t filter -A FORWARD -i eth0 -o <vname1> -j ACCEPT
iptables -t filter -A FORWARD -o eth0 -i <vname1> -j ACCEPT

# eth0是主机能够连接外网的网卡

9. 连接测试

# 1. 主机是否能够连接到命令空间内网络
ping 192.168.45.3

# 2. 命名空间内网卡是否能连接到主机网络
ip netns exec haproxy ping <eth0_ip>
# 主机外网网卡通过 ip a获取

# 3. 命名空间内网卡是否能连接内网-internet
ip netns exec haproxy ping 192.168.0.185

# 4. 测试是否可以连接外网
ping [www.python.org](http://www.python.org/) # 获取域名对应的IP地址
ip netns exec haproxy ping 151.101.108.223

10. runc部署nginx测试

# 1. 创建runc运行目录与文件 (需要装runc命令)
mkdir -p `pwd`/nginx/rootfs && cd `pwd`/nginx && runc spec

# 2.导出nginx容器中rootfs文件到 当前目录下 rootfs目录下
docker export $(docker run -d nginx) -o nginx-rootfs.tgz
tar -xf nginx-rootfs.tgz -C rootfs

# 3.编写配置config.json文件
# hostname --容器主机名 nginx
# args -- 容器中进程启动命令,可通过 docker inspect container_id中cmd获取
# namespace 需要添加network配置,将上面生成的网络空间文件配置到 path
# mount 存储卷挂载,主要挂载配置文件目录与静态文件目录
# env 环境变量

# 3. 创建nginx进程使用的用户
useradd nginx -s /sbin/nologin
# 4. 授权
chown -R nginx:nginx rootfs config.json

11. Nginx -- runc_config.json内容

{
  "ociVersion": "1.0.2-dev",
  "process": {
    "terminal": true,
    "user": {
      "uid": 1000,
      "gid": 1000
    },
    "args": [
      "/docker-entrypoint.sh",
      "nginx",
      "-g",
      "daemon off;"
    ],
    "env": [
      "PATH=/usr/local/[sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin](http://sbin/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin)",
      "TERM=xterm",
      "NGINX_VERSION=1.21.4",
      "NJS_VERSION=0.7.0",
      "PKG_RELEASE=1~bullseye"
    ],
    "cwd": "/",
    "capabilities": {
      "bounding": [
        "CAP_AUDIT_WRITE",
        "CAP_KILL",
        "CAP_NET_BIND_SERVICE"
      ],
      "effective": [
        "CAP_AUDIT_WRITE",
        "CAP_KILL",
        "CAP_NET_BIND_SERVICE"
      ],
      "inheritable": [
        "CAP_AUDIT_WRITE",
        "CAP_KILL",
        "CAP_NET_BIND_SERVICE"
      ],
      "permitted": [
        "CAP_AUDIT_WRITE",
        "CAP_KILL",
        "CAP_NET_BIND_SERVICE"
      ],
      "ambient": [
        "CAP_AUDIT_WRITE",
        "CAP_KILL",
        "CAP_NET_BIND_SERVICE"
      ]
    },
    "rlimits": [
      {
        "type": "RLIMIT_NOFILE",
        "hard": 102400,
        "soft": 102400
      },
      {
        "hard": 102400,
        "soft": 102400,
        "type": "RLIMIT_NPROC"
      }
    ],
    "noNewPrivileges": true
  },
  "root": {
    "path": "rootfs",
    "readonly": true
  },
  "hostname": "nginx",
  "mounts": [
    {
      "destination": "/proc",
      "type": "proc",
      "source": "proc"
    },
    {
      "destination": "/dev",
      "type": "tmpfs",
      "source": "tmpfs",
      "options": [
        "nosuid",
        "strictatime",
        "mode=755",
        "size=65536k"
      ]
    },
    {
      "destination": "/dev/pts",
      "type": "devpts",
      "source": "devpts",
      "options": [
        "nosuid",
        "noexec",
        "newinstance",
        "ptmxmode=0666",
        "mode=0620",
        "gid=5"
      ]
    },
    {
      "destination": "/dev/shm",
      "type": "tmpfs",
      "source": "shm",
      "options": [
        "nosuid",
        "noexec",
        "nodev",
        "mode=1777",
        "size=65536k"
      ]
    },
    {
      "destination": "/dev/mqueue",
      "type": "mqueue",
      "source": "mqueue",
      "options": [
        "nosuid",
        "noexec",
        "nodev"
      ]
    },
    {
      "destination": "/sys",
      "type": "sysfs",
      "source": "sysfs",
      "options": [
        "nosuid",
        "noexec",
        "nodev",
        "ro"
      ]
    },
    {
      "destination": "/sys/fs/cgroup",
      "type": "cgroup",
      "source": "cgroup",
      "options": [
        "nosuid",
        "noexec",
        "nodev",
        "relatime",
        "ro"
      ]
    },
    {
      "destination": "/etc/hostname",
      "options": [
        "rbind",
        "rprivate"
      ],
      "source": "/etc/hostname",
      "type": "bind"
    },
    {
      "destination": "/etc/hosts",
      "options": [
        "rbind",
        "rprivate"
      ],
      "source": "/etc/hosts",
      "type": "bind"
    }
  ],
  "linux": {
    "resources": {
      "devices": [
        {
          "allow": false,
          "access": "rwm"
        }
      ]
    },
    "namespaces": [
      {
        "type": "pid"
      },
      {
        "path": "/var/run/netns/haproxy",
        "type": "network"
      },
      {
        "type": "ipc"
      },
      {
        "type": "uts"
      },
      {
        "type": "mount"
      }
    ],
    "maskedPaths": [
      "/proc/acpi",
      "/proc/asound",
      "/proc/kcore",
      "/proc/keys",
      "/proc/latency_stats",
      "/proc/timer_list",
      "/proc/timer_stats",
      "/proc/sched_debug",
      "/sys/firmware",
      "/proc/scsi"
    ],
    "readonlyPaths": [
      "/proc/bus",
      "/proc/fs",
      "/proc/irq",
      "/proc/sys",
      "/proc/sysrq-trigger"
    ]
  }
}

12. 通过runc启动nginx

# 1. 启动nginx
runc run -d -b <path-to>/nginx <container_name>
# -d 以后台方式运行
# -b 指定保存了容器 config.json文件和rootfs目录的根目录
# <container_name> 指定容器名字
# 例如:
# runc run -d -b ~/work/nginx nginx

# 2. 查询容器
runc list

# 3. 查询容器状态
cat /run/runc/<container_name>/state.json

# 4. 发起curl请求,检查是否返回nginx欢迎页面
curl http://192.168.45.3:80

13. Runc 使用 host network

删除 config.json 中 namespace 配置中 network配置项
{
"path": "/var/run/netns/haproxy",
"type": "network"
},
如果不删除则:always put your container in a new network namespace

文档:https://github.com/opencontainers/runc/issues/1552

# 测试
curl [http://localhost:80](http://localhost/)

14. 使用systemd管理 – 编写service文件

[Unit]
Description=runc run nginx

[Service]
ExecStart=/usr/bin/runc run -d -b /root/work/nginx --pid-file /run/nginx.pid nginx
ExecStop=/usr/bin/runc kill nginx
ExecStopPost=/usr/bin/runc delete nginx
PIDFile=/run/nginx.pid

[Install]
WantedBy=multi-user.target

15. 保存并启动

# 1. 保存到 /usr/lib/systemd/system/目录下
vim /usr/lib/systemd/system/nginx.service

# 2. 使用systemctl工具启动
systemctl daemon-reload
# 重新加载dameon关联的service文件

# 3.设置开机自启并启动
systemctl enable nginx && systemctl start nginx

# 4. 启动时可能会报错: [emerg] 1#1: open() "/var/log/nginx/error.log" failed (6: No such device or address)
# 解决方案: 因为是从容器中导出,/var/log/nginx/error.log是一个链接文件,链接到/dev/stdout,需要将这个链接文件删除,创建一个新的 error.log文件

# 5. 查询状态
systemctl status nginx

# 6. 访问
curl [http://localhost:80](http://localhost/)
  • 关联文档
- Runc -- GitHub地址:GitHub - opencontainers/runc: CLI tool for spawning and running containers according to the OCI spec
- Host network issue:https://github.com/opencontainers/runc/issues/1552
- Runc -- linux-config文档地址:https://github.com/opencontainers/runtime-spec/blob/main/config.md

标签:systemd,proc,ip,网络,nginx,runc,netns,type
From: https://www.cnblogs.com/2bjiujiu/p/17988269

相关文章

  • 从 Greenplum 到 Databend,万全网络数据库平台架构演进
    作者:代城万全网络高级工程师,负责万全网络数据平台整体架构研发工作,拥有超过7年的大数据相关技术研发经验,一直关注着开源和云技术的发展。万全网络科技有限公司是一家专注于B端电商物流供应链的公司。致力于为客户提供全面的供应链解决方案,涵盖从产品采购到最终配送的全程......
  • 以下是一些在网络安全领域值得一读的书籍,涵盖了各个层次和方向:
    以下是一些在网络安全领域值得一读的书籍,涵盖了各个层次和方向:基础阶段:《计算机网络:自顶向下方法》(原书第7版)-JamesF.Kurose,KeithW.Ross《网络是怎样连接的》-户根勤《黑客与画家》-PaulGraham编程与安全编程:《Python编程:从入门到实践》-EricMatthes《C++Pr......
  • 再获认可|原点安全入选 FreeBuf《CCSIP 2023中国网络安全行业全景册》
    1月24日,FreeBuf咨询正式发布《CCSIP(China Cyber Security Industry Panorama)2023中国网络安全行业全景册(第六版)》(下称“全景册”)。全景册旨在为企业提供更好的网络安全产品选型参考,帮助企业了解中国网络安全技术与市场的发展趋势,受到行业的广泛关注与一致认可。原点安全凭借领......
  • 第一章 计算机网络概述——教案
    第一章计算机网络概述一、教学目标:了解计算机网络的定义和发展了解计算机网络的功能和应用了解计算机网络的系统组成掌握计算机网络的分类二、教学重点、难点网络的系统组成及分类三、技能培训重点、难点计算机网络的系统组成四、教学方法教师讲解、演示、提问;五、......
  • HTTP连接池在Java中的应用:轻松应对网络拥堵
    网络拥堵是现代生活中无法避免的问题,尤其是在我们这个“点点点”时代,网页加载速度直接影响到我们的心情。此时,我们需要一位“救世主”——HTTP连接池。今天,就让我们一起探讨一下,这位“救世主”如何在Java中大显神通。首先,我们要明白,什么是HTTP连接池?简单来说,它就像一个“连接银行”......
  • 探讨Go语言中的HTTP代理模式:看Go如何玩转网络中转站
    在互联网的海洋中,HTTP代理服务器像一座灯塔,为我们的网络冲浪提供了指引。而当Go语言遇上HTTP代理,会碰撞出怎样的火花呢?今天,让我们一起探讨Go语言中的HTTP代理模式,看看它如何玩转这个网络中转站!首先,让我们来了解一下什么是HTTP代理模式。简而言之,HTTP代理模式就是通过一个代理服务器......
  • 神经网络优化篇:详解为超参数选择合适的范围(Using an appropriate scale to pick hyper
    为超参数选择合适的范围假设要选取隐藏单元的数量\(n^{[l]}\),假设,选取的取值范围是从50到100中某点,这种情况下,看到这条从50-100的数轴,可以随机在其取点,这是一个搜索特定超参数的很直观的方式。或者,如果要选取神经网络的层数,称之为字母\(L\),也许会选择层数为2到4中的某个值,接着顺......
  • 基于GoogleNet深度学习网络的花朵类型识别matlab仿真
    1.算法运行效果图预览 2.算法运行软件版本matlab2022a 3.算法理论概述      花朵类型识别是计算机视觉领域中的一个重要任务。它在植物学研究、农业、园艺等领域有着广泛的应用。传统的花朵类型识别方法通常基于手工设计的特征提取器,这些方法的效果受限于特征提......
  • Linux网络编程基础API
    目录socket地址API创建socket命名socket监听socket接收连接发起连接关闭连接数据读写带外标记地址信息函数socket选项网络信息APIsocket地址API主机字节序和网络字节序在Linux系统中,主机字节序(HostByteOrder)和网络字节序(NetworkByteOrder)是两个重要的概念。主机字节序......
  • docker 网络
    docker网络Docker网络实现原理Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就......