零入门kubernetes网络实战-16->使用golang给docker环境下某个容器里添加一个额外的网卡

news2024/11/13 13:40:23

《零入门kubernetes网络实战》视频专栏地址
https://www.ixigua.com/7193641905282875942

本篇文章视频地址(稍后上传)


上一篇文章,我们使用了golang在veth pair链接的网络命名空间里添加了网卡,

本篇文章,我尝试,在docker环境下的容器里,添加额外的网卡,使得容器实例变为多网卡环境。

1、测试环境介绍

一台centos虚拟机

# 查看操作系统版本
cat /etc/centos-release
# 内核版本
uname -a
uname -r 
# 查看网卡信息
ip a s eth0

在这里插入图片描述

2、在测试服务上,创建测试容器

这里就以busybox镜像为例了。

主要过程如下:
编写启动容器启动脚本–>启动容器–>查看容器是否启动–>进入容器里查看容器当前网卡情况

编写创建测试容器的脚本

start-busybox.sh

docker stop my-busybox
docker rm my-busybox
docker run -itd --name my-busybox docker.io/busybox /bin/sh

主要过程如下:

在这里插入图片描述

3、获取容器实例my-busybox的进程号

docker inspect my-busybox | grep -w Pid

在这里插入图片描述

4、golang代码

编写代码,为ns1网络命名空间,添加veth2虚拟网卡,并设置IP


package main

import (
	"flag"
	"fmt"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	"golang.org/x/sys/unix"
	"net"
	"os"
	"runtime"
)

const (
	veth1Name = "veth1"
	veth2Name = "veth2"
)

var pid int

func main() {

	flag.IntVar(&pid, "pid", 0, "Use -pid xxx")
	flag.Parse()

	l, err := netlink.LinkByName(veth1Name)
	if err == nil {
		// 删除掉 已经存在的 veth pair
		netlink.LinkDel(l)
	}

	vethpeer := &netlink.Veth{
		LinkAttrs: netlink.LinkAttrs{
			Name:  veth1Name,
			Flags: net.FlagUp,
			MTU:   1500,
		},
		PeerName: veth2Name,
	}
	err = netlink.LinkAdd(vethpeer)
	if err != nil {
		panic(err)
	}

	// 获取到某个容器,如11101容器对应的网络命名空间
	// 11101是容器的PID,就是容器的进程号
	// /proc/11101/ns/net
	// 如何获取到某个容器的Pid呢?
	// 假设,容器名称是 my-sw
	// docker inspect my-sw | grep -w Pid
	// 将得到的值,复制过来
	nsPath := fmt.Sprintf("/proc/%d/ns", pid)
	ns, err := netns.GetFromPath(fmt.Sprintf("%s/%s", nsPath, "net"))
	if err != nil {
		panic(err)
	}
	// 因为是打开文件的,是一个句柄,因此必须close
	defer ns.Close()

	veth2, err := netlink.LinkByName(veth2Name)
	if err != nil {
		panic(err)
	}

	// ip link set veth2 netns
	//  /proc/11101/ns/net命名空间里
	// 就是将veth2网卡,移动到容器里的网络空间里
	err = netlink.LinkSetNsFd(veth2, int(ns))
	if err != nil {
		panic(err)
	}

	// 再切换到容器网络命名空间里前,先获取当前主网络命名空间;
	// 以便能切换回来
	hostNS, err := GetCurrentNS()
	if err != nil {
		panic(err)
	}

	// 设置当前网络命名空间
	// 假设,已经将veth2移动了容器里了
	// 此时在物理机上,直接ifconfig是查看不到veth2网卡的
	// 而你的二进制文件是在物理机上的,此二进制文件想操作veth2网卡的话
	// 只能先设置网络命名空间了
	err = netns.Set(ns)
	if err != nil {
		panic(err)
	}

	// 因为网络命名空间切换了,进入到容器网络命名空间里,必须再获取一次veth2r设备
	veth2, err = netlink.LinkByName(veth2Name)
	if err != nil {
		panic(err)
	}

	// 仅仅是设置IP
	addr, _ := netlink.ParseAddr("10.244.1.2/24")
	err = netlink.AddrAdd(veth2, addr)
	if err != nil {
		panic(err)
	}

	// 可以将容器里的网卡名称,改为通用的名称,如eth0; 非必须步骤
	//netlink.LinkSetName(veth2, "eth0")

	// 将容器里的网卡eth0启动
	err = netlink.LinkSetUp(veth2)
	if err != nil {
		panic(err)
	}

	// 切换回到主网络命名空间里
	err = unix.Setns(int(hostNS.Fd()), unix.CLONE_NEWNET)
	if err != nil {
		panic(err)
	}

	addr, _ = netlink.ParseAddr("10.244.1.3/24")
	veth1, err := netlink.LinkByName(veth1Name)
	if err != nil {
		panic(err)
	}

	// 在主网络命名空间里设置veth1网卡的IP
	err = netlink.AddrAdd(veth1, addr)
	if err != nil {
		panic(err)
	}

	// 将veth1网卡设置为up状态
	netlink.LinkSetUp(veth1)
}

func GetCurrentNS() (*os.File, error) {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()
	return GetNS(getCurrentThreadNetNSPath())
}

func getCurrentThreadNetNSPath() string {
	currentNetNSPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
	return currentNetNSPath
}

func GetNS(nspath string) (*os.File, error) {

	fd, err := os.Open(nspath)
	if err != nil {
		return nil, err
	}

	return fd, nil
}

其实,代码还是上一篇文章的代码,完全没有变

5、Makefile 编译文档

build:
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o createveth main.go

scp:
	scp createveth root@10.211.55.122:/root

all:
	make build && make scp

执行运行

make all

6、登录到服务上,运行createveth

./createveth -pid=1614

ip a s veth1

docker exec -it my-busybox sh

在这里插入图片描述

7、总结

其实,kubernetes中,给Pod里添加网卡或者添加额外网卡时,操作类似。


点击 下面 返回 专栏目录

<<零入门kubernetes网络实战>>技术专栏之文章目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/358652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新建idea项目

目录IDEA系列之创建各种项目 https://blog.csdn.net/LOVEQD123/article/details/105886077 idea 创建项目的三种方式 https://blog.csdn.net/weixin_50034122/article/details/118754521 创建空项目 https://blog.csdn.net/qq_44537956/article/details/123075134 创建 spri…

百度百科词条怎么做?百度百科词条创建攻略分享

只要是想要将自己宣传出去的企业或是个人&#xff0c;都建议创建属于自己的百度百科词条&#xff0c;因为百度百科词条流量大、权重高、排名靠前&#xff0c;创建百度百科词条可以提高企业或是个人的知名度和口碑。 百度百科词条怎么做&#xff1f;每天都有用户在百度上搜索这…

携手亚马逊云科技,大地量子高精度功率预测系统助力清洁能源消纳提速增效

近年来&#xff0c;我国光伏和风电并网装机容量持续增长&#xff0c;截至2021年底&#xff0c;全国可再生能源装机规模突破10亿千瓦&#xff0c;占总发电装机容量的44.8%。其中&#xff0c;风电装机3.28亿千瓦、光伏发电装机3.06亿千瓦。风光电总装机和新增装机规模多年来位居全…

图解 script 标签中的 async 和 defer 属性

图解 script 标签中的 async 和 defer 属性 我们在工作中经常会碰到 script 标签,一般会有以下三种形式 <script srcxxx></script> <script srcxxx async></script> <script srcxxx defer></script>那么这三种形式的 script 标签有什么区…

java 多线程

1.什么是进程&#xff1f;什么是线程&#xff1f; 进程是:一个应用程序&#xff08;1个进程是一个软件&#xff09;。 线程是&#xff1a;一个进程中的执行场景/执行单元。 注意&#xff1a;一个进程可以启动多个线程。 我们在启动java程序的时候&#xff0c;会先启动JVM&am…

【2】MYSQL数据的导入与导出

文章目录 MYSQL-库(相同库名称)的导入导出MYSQL-库(不同库名称)的导入导出MYSQL-表的导入导出MYSQL-表的指定查询记录导入导出前提: 客户端工具是:SQLyog MYSQL-库(相同库名称)的导入导出 1、选中指定库——右键,选择【将数据库复制到不同的主机/数据库】 2、选中指…

分布式之Raft共识算法分析

写在前面 在分布式之Paxos共识算法分析 一文中我们分析了paxos算法&#xff0c;知道了其包括basic paxos和multi paxos&#xff0c;并了解了multi paxos只是一种分布式共识算法的思想&#xff0c;而非具体算法&#xff0c;但可根据其设计具体的算法&#xff0c;本文就一起来看…

SORT与DeepSORT简介

一、MOT( mutil-object tracking)步骤 在《DEEP LEARNING IN VIDEO MUTIL-OBJECT TEACKING: A SURVEY》这篇基于深度学习多目标跟踪综述中&#xff0c;描绘了MOT问题的四个主要步骤 1.跟定视频原始帧 2.使用目标检测器如Faster-rcnn, YOLO, SSD等进行检测&#xff0c;获取目标…

vue 3.0 Vue Router导航守卫的使用

目录前言&#xff1a;安装路由快速使用1. 创建路由模块2.规定路由模式3.使用路由规则4.声明路由链接和占位符5.重定向路由6.嵌套路由7.路径参数8. 声明式和编程式导航8.1 导航到不同的位置8.2 替换当前位置8.3 路由历史9.导航守卫9.1 全局前置守卫9.2全局路由守卫的语法参数9.3…

初阶C语言——操作符【详解】

文章目录1.算术操作符2.移位操作符2.1 左移操作符2.2 右移操作符3.位操作符按位与按位或按位异或4.赋值操作符复合赋值符5.单目操作符5.1单目操作符介绍6.关系操作符7.逻辑操作符8.条件操作符9.逗号表达式10.下标引用、函数调用和结构成员11表达式求值11.1 隐式类型转换11.2算术…

关于Java的深拷贝和浅拷贝

文章目录1.拷贝的引入1.1引用拷贝1.2对象拷贝2.深拷贝与浅拷贝2.1浅拷贝2.2深拷贝1.拷贝的引入 1.1引用拷贝 创建一个指向对象的引用变量的拷贝 Teacher teacher new Teacher("Taylor",26); Teacher otherteacher teacher; System.out.println(teacher); System…

vim常用命令

vim常用三种模式 命令模式&#xff08;Command mode&#xff09; 插入模式&#xff08;Insert mode&#xff09; 末行模式&#xff08;Last line mode&#xff09; &#xff08;一&#xff09;进入命令模式 vi 或者 vim&#xff08;二&#xff09;命令模式 -> 插入模式 &…

服务器部署流程与经验记录

服务器部署流程1.项目部署1.1 重置实例密码1.2 配置安全组规则1.3 远程连接服务器1.4 安装所需软件1.5 安装Tomcat1.6 配置宝塔安全组1.7 导入数据库和项目2. 域名注册3. 网站备案1.项目部署 1.1 重置实例密码 1.2 配置安全组规则 1.3 远程连接服务器 使用VNC远程连接&#…

实用调试技巧——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是实用调试技巧&#xff0c;其实小雅兰一开始&#xff0c;也不知道调试到底是什么&#xff0c;一遇到问题&#xff0c;首先就是观察程序&#xff0c;改改这里改改那里&#xff0c;最后导致bug越修越多&#xff0c;或者是问别…

51单片机——定时器中断实验,小白讲解,相互学习

定时器介绍 1&#xff0c;CPU时序的有关知识 震荡周期&#xff1a;为单片机提供定时信号的震荡源的周期&#xff08;晶振周期或外加震荡周期&#xff09;。状态周期&#xff1a;2个震荡周期为1个状态周期&#xff0c;用S表示。震荡周期又称S周期或时钟周期。机器周期&#xff…

Java-多线程并发-线程的实现、调度和状态转换

线程的实现 线程是比进程更轻量级的调度执行单位&#xff0c;线程的引入&#xff0c;可以把一个进程的资源分配和执行调度分开&#xff0c;各个线程既可以共享进程资源( 内存地址、文件I/O等 )&#xff0c;又可以独立调度( 线程是CPU调度的基本单位 )。 Java语言则提供了在不…

300行代码手写spring初体验v1.0版本

70%猜想30%验证 spring&#xff1a;IOC 、DI、AOP、MVC MVC作为入口 web.xml 内部依赖一个DispathcheServlet这样一个接口 先来说一下springMVC的一些基础知识 整体的一个思路&#xff1a; 在web.xml里面进行了一个核心servlet的一个配置 核心就是这个DispatcherServlet …

用列表y表示序列x中每个元素是否被选中 根据列表y返回序列x中被选中的元素 itertools.compress(x,y)

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 用列表y表示序列x中每个元素是否被选中 根据列表y返回序列x中被选中的元素 itertools.compress(x,y) [太阳]选择题 以下关于python代码表述错误的一项是? from itertools import compress …

2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A模块(4)

目录 二、竞赛注意事项 &#xff08;本模块20分&#xff09; 一、项目和任务描述&#xff1a; 二、服务器环境说明 三、具体任务&#xff08;每个任务得分以电子答题卡为准&#xff09; A-1任务一 登录安全加固&#xff08;Windows&#xff09; 1.密码策略 a.更改或创建…

未来的城市:智慧城市定义、特征、应用、场景

智慧城市是通过连接一个地区的物理、经济和社会基础设施&#xff0c;以创新、有效和高效的方式应用和实施技术来发展城市的概念&#xff0c;以改善服务并实现更好的生活质量。智慧城市是一个将信息和通信技术融入日常治理的城市区域&#xff0c;旨在实现效率、改善公共服务、增…