许多场景下我们的OpenStack虚拟机实例需要关联多个浮动IP。Horizon Dashboard不支持这样的操作,但是我们可以通过命令行和API完成。
可以以两种形式关联:
- 实例配置多个NIC,每个NIC关联一个浮动IP
- 实例只配置一个NIC,NIC上配置多个fixed IP, 每个浮动IP关联一个fixed IP
首先看第一种形式:
列出所有网络,找到实例所在网络和子网:
1 | [root@localhost ~(keystone_admin)]# neutron net-list |
Keep learning, keep living...
许多场景下我们的OpenStack虚拟机实例需要关联多个浮动IP。Horizon Dashboard不支持这样的操作,但是我们可以通过命令行和API完成。
可以以两种形式关联:
首先看第一种形式:
列出所有网络,找到实例所在网络和子网:
1 | [root@localhost ~(keystone_admin)]# neutron net-list |
ARP: Address Resolution Protocol, 地址解析协议,主要用于根据IP获取对应的物理地址,它封装在数据链路协议上,如以太网帧封装。
以太网中,交换机根据数据包中源MAC地址与对应的交换机端口建立映射关系。当以太网帧到达交换机,交换机根据包中目的MAC地址在映射表查找对应的交换机端口。若找到,则直接从该端口转发,否则向除接收端口外的所有其他端口广播数据包。
以太网内的主机要发送数据包时首先判断目标IP地址是否是同一子网。若发送给本地网络主机,则根据目的主机IP获取对应的MAC地址。若发送到其他网络,则通过路由获取目的IP(一般为网关IP),根据该IP获取对应的目的MAC地址。收到ARP响应之后,发送相应的数据包。
iptables是Linux系统上的包过滤防火墙。它基于netfilter框架实现,分为内核模块和用户态程序。内核模块负责根据规则过滤数据包,用户态程序负责将规则写入内核模块。
iptables根据功能将过滤规则组织成表, 按处理时机组成链。每个表中含有多个链,每个链中包含一组规则。每条规则由数据包的匹配条件和匹配之后要执行的目标构成。iptables内核模块依次检查规则过滤数据包。
Linux默认情况下会丢掉不属于本机IP的数据包。将net.ipv4.ip_forward
设置为1后,会开启路由功能,Linux会像路由器一样对不属于本机的IP数据包进行路由转发。
路由的基本流程为: 收到数据包之后,解析出目的IP,判断是否是本机IP。如果是本机IP,则交由上层传输层处理。如果不是本机IP,则通过查找路由表找到合适的网络接口将IP数据包转发出去。
Linux上通过路由规则和路由表配合来实现路由流程, 处理逻辑如下:
更新(2020-05-06):
Redhat在2018年发表了一篇关于Linux虚拟网络设备的文章,内容比本文要更详细, 可以参考:
https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking
OpenStack虚拟化网络实现中大量应用了多种虚拟网络设备,了解这些设备是理解OpenStack虚拟网络实现的基础,本文来简单介绍这些虚拟网络设备。
TUN/TAP设备是Linux内核中实现的虚拟网卡。物理网卡是从物理线路上收发数据包,而TUN/TAP设备是从用户态应用程序上收发以太网帧或IP包。用户态进程对/dev/net/tun
文件调用open()
获取一个文件描述符,并调用ioctl()
挂接到该设备上,接着通过读写该文件描述符从TUN/TAP设备的收发数据包。收发的数据包由用户态进程构造好。TUN和TAP设备的区别在于TUN设备收发的是IP包,而TAP设备收发的是以太网帧。
在进程中创建及使用TUN/TAP设备可以参考官方文档:
https://www.kernel.org/doc/Documentation/networking/tuntap.txt
可以使用iproute2工具包中的ip命令创建TUN/TAP设备, 如:
1 | ip tuntap add dev tap0 mode tap |
我们的程序很多业务逻辑由Lua实现,为了防止业务逻辑被曝光,需要对Lua代码进行加密。
我们有两种思路:
本文主要介绍第二种思路的实现。
我们的程序使用LuaJIT来执行Lua代码,因而以LuaJIT来说明。
Citrix提供了DDK(Driver Development Kit)来支持在XenServer中要构建自定义的内核模块或硬件驱动。DDK是一个OVA格式的虚拟机镜像,包含了内核头文件和编译器等开发工具。
下面介绍使用DDK构建内核模块的步骤。
首先从官方下载相应版本DDK,这里选择6.5:
http://downloadns.citrix.com.edgesuite.net/10106/XenServer-6.5.0-DDK.iso
将下载的ISO文件上传到XenServer宿主机上
挂载ISO
1 | mkdir /mnt/tmp |
Lua通过标准库实现了核心之外的功能,如math库,I/O库等。本文来分析math标准库的实现, 代码位于lmathlib.c
。
math库提供了一组标准的数学函数,如绝对值函数, 三角函数,随机数函数等。调用方式为:
1 | a = math.abs(-1) |
标准库由C语言函数实现,提供给Lua程序使用。Lua程序与C函数通过虚拟栈交互。Lua将参数压入栈中,C函数从栈中获取参数,并将结果压入栈中,C函数返回入栈的结果数量。C函数无需在压入结果前清空栈,Lua会在函数执行完成后从栈中获取结果并自动清空结果下的内容。
Lua调用的C函数的格式是固定的,定义在lua.h中:
1 | typedef int (*lua_CFunction) (lua_State *L); |
默认情况下,Lua源码编译后会生成三个文件:
Lua 是一种解释型语言,执行方式如图:
首先将Lua源码编译成Lua字节码,然后由虚拟机来执行Lua字节码。
Thrift(https://thrift.apache.org/)是一个轻量级、语言无关的RPC框架。它定义了一套简单直观的IDL(Interface Definition Language)用于描述服务接口规范。 通过代码生成引擎将IDL描述的接口规范生成各种目标语言(如C++
,JAVA等)的源码文件。应用开发者基于这些源码构建服务端和客户端。通过这种方式,Thrift屏蔽了不同语言间的数据序列化/反序列化、数据传输、网络通信等与业务逻辑不相关的部分,使开发者只需关心业务逻辑实现。