理解 neutron(15):Neutron Linux Bridge + VLAN/VXLAN 虛擬網路
學習 Neutron 系列文章:
雖然大部分的OpenStack 部署環境中,都會使用 Open vSwitch 來作為虛擬交換機來實現二層網路功能,但是Neutron 仍然支援使用 Linux bridge 作為虛擬交換機來實現二層網路。本文就此做些分析和說明。
同時要指出的是,OpenStack 官方已經把 linux bridge 實現標記為 legacy 的了,文件從 2016 年後也沒怎麼更新了。這是因為,linux bridge 和 OVS 相比,只支援基本的網路功能即二層交換,但不支援VLAN 標籤和隧道。因此,linux bridge agent 利用linux 核心功能(VLAN 子介面和 VXLAN 介面)來實現VLAN 標籤和隧道。
1. 測試環境
以下面的環境為例(網路節點上):
(1)linux bridge
[email protected]:/home/sammy# brctl show bridge name bridge id STP enabled interfaces brq85925305-b4 8000.563534c8d02d no tap0bb8efeb-10 tap798c87d1-a2 vxlan-25 brq96609bfa-0e 8000.0050569c4d94 no ens224 tap60dbdc2f-a0 brq971ffda2-e5 8000.a6acb08e4fd6 no tapb1eaae00-e5 tapf70543dd-0f vxlan-10
(2)OpenStack 網路和 network namespace:
[email protected]:/home/sammy# neutron net-list +--------------------------------------+---------+-----------------------------------------------------+ | id | name | subnets | +--------------------------------------+---------+-----------------------------------------------------+ | 96609bfa-0e22-4bb7-8dba-6ef532ea6076 | extnet | afa7d205-3026-439f-aca7-295a9f9b2a71 10.62.227.0/24 | | 971ffda2-e567-40a0-a2c8-b31a577fd4d3 | appnet | 4c68eacb-bf3e-408a-a941-94e93eddb22b 11.0.0.0/24 | | | | 3d596991-de8f-4ae4-8913-89426a8abbd7 10.0.0.0/24 | | 85925305-b477-4cc6-9654-67d9bf1e7cd8 | appnet2 | 4575c7f1-7f08-4917-9904-ec65af38619b 20.0.0.0/24 | +--------------------------------------+---------+-----------------------------------------------------+ [email protected]:/home/sammy# ip netns qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8 (id: 2) qdhcp-971ffda2-e567-40a0-a2c8-b31a577fd4d3 (id: 1) qrouter-39a77439-8a28-49c1-bf97-ac931510631b (id: 0)
(3)示意圖:
(4)說明:
- qdhcp 和 qrouter 都是 linux network namespace 例項
- qdhcp network namespace 的數量等於啟用了 DHCP 的 Neutron network 的數量。
- 當一個 network 中存在至少一個 subnet 啟用了 DHCP 之後,會有一個 qdhcp network namespace 被創建出來;
- 當一個 network 中多個 subnet 啟用了 DHCP 時,它們共用一個 qdhcp,以及 dnsmasq。
- 其 name 使用 network id,比如 qdhcp-85925305-b477-4cc6-9654-67d9bf1e7cd8
- qrouter network namespace 的數目等於 router 的數目,也就是說,系統中一共有幾個 router,那麼就存在幾個 qrouter network namespace
- brq linux bridge 的數目等於 neutron network 的數目,其 name 是 network id 的前幾位,比如 brq96609bfa-0e
- 一個 network 的 qdhcp network namespace 和其 brq linux bridge 一定有連線
- qrouter 之內的 network interface 分兩種,一種是 qr 開頭的,每個連線到 router 之上的 subnet 都有一個;還有一個是 qg,每個連線到 router 的 external subnetwork 有一個
- qrouter 的每個 network interface 都通過 veth 連線到所在網路的 qbr linux bridge 上
- qbr linux bridge 連連線兩種物理裝置,一種是 vxlan interface,每個 tenant network 有一個,另一種是在 physical network 對應的物理網絡卡上建立的子介面(sub-interface)
- 對於 physical network 的 qbr 來說,使用者可以指定它,並且在linuxbridge_agent.ini 中通過 bridge_mappings = List of <physical_network>:<physical_bridge> 進行配置;也可以不指定,此時 agent 會建立它。當同時配置了 physical bridge 和 physical interface 時,前者優先。
如果 external network 中有多個 subnet 的話:
(1)每個 qrouter 只允許有一個 External Gateway,也就是說它只有一個 qg network interface。當 external network 新增多個 subnet 之後,只有第一個被當作 external subnet,其餘的都會被當作 internal subnet。
(2)在 qrouter 的路由表之中,
[email protected]:/home/sammy# ip netns exec qrouter-39a77439-8a28-49c1-bf97-ac931510631b route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 10.62.227.1 0.0.0.0 UG 0 0 0 qg-e09fce07-cd 10.0.0.0 * 255.255.255.0 U 0 0 0 qr-b1eaae00-e5 10.62.227.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd 10.62.228.0 * 255.255.255.0 U 0 0 0 qg-e09fce07-cd 10.62.228.0 * 255.255.255.0 U 0 0 0 qr-124ff148-b7 11.0.0.0 * 255.255.255.0 U 0 0 0 qr-16d9b0cc-38 20.0.0.0 * 255.255.255.0 U 0 0 0 qr-0bb8efeb-10
2. linux-bridge-agent 工作過程分析
(1)linuxbridge-agent 會啟動一個迴圈,不斷掃描上面紅框中的 tap 裝置
def daemon_loop(self): ... while True: start = time.time() . .. device_info = self.scan_devices(previous=device_info, sync=sync) sync = False if (self._device_info_has_changes(device_info) or self.sg_agent.firewall_refresh_needed()): LOG.debug("Agent loop found changes! %s", device_info) try: sync = self.process_network_devices(device_info) except Exception: LOG.exception(_LE("Error in agent loop. Devices info: %s"), device_info) sync = True
這是它首先找到的 devices:
(Pdb) p bridge_lib.get_bridge_names()
['brq85925305-b4', 'virbr0', 'brq971ffda2-e5', 'virbr0-nic', 'tapb1eaae00-e5', 'tapf70543dd-0f', 'vxlan-25', 'vxlan-10', 'tap0bb8efeb-10', 'lo', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'ens224', 'ens192', 'ens160', 'tap798c87d1-a2']
然後過濾出 tap 裝置:
get_all_devices()->set(['tap0bb8efeb-10', 'tap60dbdc2f-a0', 'tap795e6e86-94', 'tap798c87d1-a2', 'tapb1eaae00-e5', 'tapf70543dd-0f'])
(2)根據 previous 中儲存的歷史資料,再接合伺服器端和本地更新時間,計算出需要更新的tap裝置列表:
{'current': set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap0bb8efeb-10', 'tap798c87d1-a2']), 'timestamps': {'tapf70543dd-0f': 1476956816.672447, 'tap60dbdc2f-a0': None, 'tapb1eaae00-e5': 1476956816.672447, 'tap795e6e86-94': None, 'tap0bb8efeb-10': 1476689797.1378036, 'tap798c87d1-a2': 1476689701.1349163}, 'removed': set([]), 'added': set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap0bb8efeb-10', 'tap798c87d1-a2']), 'updated': set([])}
(3) 通過 RPC 獲取 tap 裝置的詳細資訊
(Pdb) p devices set(['tapf70543dd-0f', 'tap60dbdc2f-a0', 'tapb1eaae00-e5', 'tap795e6e86-94', 'tap798c87d1-a2', 'tap0bb8efeb-10']) devices_details_list = self.plugin_rpc.get_devices_details_list (Pdb) p devices_details_list [{u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'971ffda2-e567-40a0-a2c8-b31a577fd4d3', u'segmentation_id': 10, u'device_owner': u'network:dhcp', u'physical_network': None, u'mac_address': u'fa:16:3e:5c:bf:11', u'device': u'tapf70543dd-0f', u'port_security_enabled': False, u'port_id': u'f70543dd-0f1b-4e1d-93c7-33f4f3d7a709', u'fixed_ips': [{u'subnet_id': u'3d596991-de8f-4ae4-8913-89426a8abbd7', u'ip_address': u'10.0.0.10'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'96609bfa-0e22-4bb7-8dba-6ef532ea6076', u'segmentation_id': None, u'device_owner': u'network:router_gateway', u'physical_network': u'provider', u'mac_address': u'fa:16:3e:77:78:86', u'device': u'tap60dbdc2f-a0', u'port_security_enabled': False, u'port_id': u'60dbdc2f-a01b-446d-bb5b-26ffac19a045', u'fixed_ips': [{u'subnet_id': u'afa7d205-3026-439f-aca7-295a9f9b2a71', u'ip_address': u'10.62.227.151'}], u'network_type': u'flat', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'971ffda2-e567-40a0-a2c8-b31a577fd4d3', u'segmentation_id': 10, u'device_owner': u'network:router_interface', u'physical_network': None, u'mac_address': u'fa:16:3e:81:1b:37', u'device': u'tapb1eaae00-e5', u'port_security_enabled': False, u'port_id': u'b1eaae00-e504-41f8-93a4-643687155bea', u'fixed_ips': [{u'subnet_id': u'3d596991-de8f-4ae4-8913-89426a8abbd7', u'ip_address': u'10.0.0.1'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'96609bfa-0e22-4bb7-8dba-6ef532ea6076', u'segmentation_id': None, u'device_owner': u'network:dhcp', u'physical_network': u'provider', u'mac_address': u'fa:16:3e:5f:94:7d', u'device': u'tap795e6e86-94', u'port_security_enabled': False, u'port_id': u'795e6e86-94af-4b72-ae1a-5a324a017774', u'fixed_ips': [{u'subnet_id': u'afa7d205-3026-439f-aca7-295a9f9b2a71', u'ip_address': u'10.62.227.150'}], u'network_type': u'flat', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'85925305-b477-4cc6-9654-67d9bf1e7cd8', u'segmentation_id': 25, u'device_owner': u'network:dhcp', u'physical_network': None, u'mac_address': u'fa:16:3e:25:27:99', u'device': u'tap798c87d1-a2', u'port_security_enabled': False, u'port_id': u'798c87d1-a2d8-4df7-b7fc-5ab30918a0de', u'fixed_ips': [{u'subnet_id': u'4575c7f1-7f08-4917-9904-ec65af38619b', u'ip_address': u'20.0.0.100'}], u'network_type': u'vxlan', u'security_groups': []}, {u'profile': {}, u'network_qos_policy_id': None, u'qos_policy_id': None, u'allowed_address_pairs': [], u'admin_state_up': True, u'network_id': u'85925305-b477-4cc6-9654-67d9bf1e7cd8', u'segmentation_id': 25, u'device_owner': u'network:router_interface', u'physical_network': None, u'mac_address': u'fa:16:3e:9f:18:a9', u'device': u'tap0bb8efeb-10', u'port_security_enabled': False, u'port_id': u'0bb8efeb-108f-409a-82e7-c4c20f0d4f69', u'fixed_ips': [{u'subnet_id': u'4575c7f1-7f08-4917-9904-ec65af38619b', u'ip_address': u'20.0.0.1'}], u'network_type': u'vxlan', u'security_groups': []}]
(4) 對需要處理的裝置,呼叫 self.process_network_devices(device_info) 函式進行處理
(5). 呼叫 plug_interface
interface_plugged = self.mgr.plug_interface(network_id, segment,device, device_details['device_owner'])
(6). 需要的話,使用已經配置的或者新建 linux brige,並將 physical interface 裝置加入其中
bridge_name = self.get_existing_bridge_name(physical_network) #獲取為 physical network 配置的 linux bridge bridge_name = self.get_bridge_name(network_id) #或者根據 network id 生成 bridge name
(7).根據不同的網路型別,分別處理 vxlan bridge,flat bridge 和 vlan bridge
def ensure_physical_in_bridge(self, network_id, network_type, physical_network, segmentation_id): if network_type == p_const.TYPE_VXLAN: if self.vxlan_mode == lconst.VXLAN_NONE: LOG.error(_LE("Unable to add vxlan interface for network %s"), network_id) return return self.ensure_vxlan_bridge(network_id, segmentation_id) # NOTE(nick-ma-z): Obtain mappings of physical bridge and interfaces physical_bridge = self.get_existing_bridge_name(physical_network) physical_interface = self.interface_mappings.get(physical_network) if not physical_bridge and not physical_interface: LOG.error(_LE("No bridge or interface mappings" " for physical network %s"), physical_network) return if network_type == p_const.TYPE_FLAT: return self.ensure_flat_bridge(network_id, physical_bridge, physical_interface) elif network_type == p_const.TYPE_VLAN: return self.ensure_vlan_bridge(network_id, physical_bridge, physical_interface, segmentation_id)
對於 flat 型別的網路,呼叫 ensure_physical_in_bridge
def ensure_physical_in_bridge(self, network_id,network_type,physical_network,segmentation_id) if network_type == p_const.TYPE_FLAT: return self.ensure_flat_bridge(network_id, physical_bridge,physical_interface)
如果有配置 physical bridge 的話,使用它;否則建立 bridge,並將物理網絡卡配置的 ip 地址和 gateway 從網絡卡挪到 linux bridge
def ensure_flat_bridge(self, network_id, phy_bridge_name,physical_interface): """Create a non-vlan bridge unless it already exists.""" if phy_bridge_name: return self.ensure_bridge(phy_bridge_name) #獲取預先配置好的 linux bridge else: bridge_name = self.get_bridge_name(network_id) ips, gateway = self.get_interface_details(physical_interface) if self.ensure_bridge(bridge_name, physical_interface, ips,gateway): #建立 bridge return physical_interface
對於 vxlan 型別的 network,需要建立 vxlan interface
def ensure_vxlan_bridge(self, network_id, segmentation_id): """Create a vxlan and bridge unless they already exist.""" interface = self.ensure_vxlan(segmentation_id) if not interface: LOG.error(_LE("Failed creating vxlan interface for " "%(segmentation_id)s"), {segmentation_id: segmentation_id}) return bridge_name = self.get_bridge_name(network_id) self.ensure_bridge(bridge_name, interface) return interface
建立 vxlan interface:
def ensure_vxlan(self, segmentation_id): """Create a vxlan unless it already exists.""" interface = self.get_vxlan_device_name(segmentation_id) if not ip_lib.device_exists(interface): LOG.debug("Creating vxlan interface %(interface)s for " "VNI %(segmentation_id)s", {'interface': interface, 'segmentation_id': segmentation_id}) args = {'dev': self.local_int} if self.vxlan_mode == lconst.VXLAN_MCAST: args['group'] = self.get_vxlan_group(segmentation_id) if cfg.CONF.VXLAN.ttl: args['ttl'] = cfg.CONF.VXLAN.ttl if cfg.CONF.VXLAN.tos: args['tos'] = cfg.CONF.VXLAN.tos if cfg.CONF.VXLAN.l2_population: args['proxy'] = cfg.CONF.VXLAN.arp_responder try: int_vxlan = self.ip.add_vxlan(interface, segmentation_id, **args)
(8). 將 tap 裝置加入到 linux bridge 中
bridge_lib.BridgeDevice(bridge_name).addif(tap_device_name)
(9). 如果將一個 tap 裝置被刪除,那麼 linux-bridge-agent 會發現:
2016-10-26 10:29:58.347 30219 INFO neutron.agent.securitygroups_rpc [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Remove device filter for set(['tap60dbdc2f-a0'])
2016-10-26 10:29:58.433 30219 INFO neutron.plugins.ml2.drivers.agent._common_agent [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Attachment tap60dbdc2f-a0 removed
2016-10-26 10:29:58.536 30219 INFO neutron.plugins.ml2.drivers.agent._common_agent [req-e3264065-6414-4b5a-8d2b-dfafad6fdde8 - - - - -] Port tap60dbdc2f-a0 updated.
3. 關於上述工作過程的簡單結論
3.1 簡單結論
- l3agent 和 dhcpagent 建立 network namespace 時建立 tap 裝置,和 network namespace 中的 interface 是一對 veth pair。當手工刪除 tap 裝置時,相應的 veth endpoint 也會被刪除。
- linuxbridgeagent 不斷掃描伺服器端和本地的 tap 裝置
- linuxbridgeagent 獲取需要增加和修改的tap裝置列表
- 對於需要增加的 tap 裝置,獲取其詳細資訊,主要是 network_id,network_type,physical_network,segmentation_id,device_owner 等,然後根據這些資訊,建立 linux bridge,並加入所需要的 interface
- 建立所需要的 linux bridge,並將 physical interface (provider network 的 physical interface 或者 tenant network 的 vxlan interface)加入 bridge,並且將 tap 裝置也加入該 bridge
- 如果發現某個 linux bridge 沒有創建出來,首先需要檢視有沒有相應的 tap 裝置存在;如果 tap 裝置不存在,則檢視相應的 qdhcp 或者 qrouter 中時候有interface
具有多個 VLAN 租戶網路時候的網路元素示意圖:
3.2 關於 unnumber interface
OpenStack 官方的 host networking 配置中,連線外網的 interface 可以是 unnumbered 的,從字面意思理解,就是該 interface 上不需要配置 IP 地址。
配置的時候,修改 /etc/network/interfaces:
# The provider network interface auto ens224 iface ens224 inet manual up ip link set dev $IFACE up down ip link set dev $IFACE down
配置好以後:
[email protected]:/home/sammy# ifconfig ens224 ens224 Link encap:Ethernet HWaddr 00:50:56:9c:4d:94 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:27300737 errors:0 dropped:0 overruns:0 frame:0 TX packets:61547 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:31951077598 (31.9 GB) TX bytes:5966060 (5.9 MB) [email protected]:/home/sammy# ifconfig brq96609bfa-0e brq96609bfa-0e Link encap:Ethernet HWaddr 00:50:56:9c:4d:94 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:32855 errors:0 dropped:0 overruns:0 frame:0 TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2731030 (2.7 MB) TX bytes:84 (84.0 B)
具體原理不詳,但是應該是因為 qrouter 的 qg network interface 和物理網路中的路由器的網絡卡之間是網路二層,因此中間的裝置都是屬於二層的,因此不需要處於網路三層的 IP 地址。
4. 使用 linux bridge 時的拓撲結構
4.1 網路節點上
為了更清楚,我們來對比著看 linux bridge 和 ovs 的兩種方案:
linux 方案:
網路服務:
- Linux bridge agent
- L3 agent
- DHCP agent
- Metadata agent
Linux bridge agent 會為每個 VLAN 虛擬網路建立一個 VLAN Bridge,它連線多個網元:
- VLAN 子介面,從物理網絡卡(圖中的 interface3)上建立,每個子介面對應一個VLAN ID,其名稱格式為 device.sid,其中 device 是物理網絡卡名字比如 eth0,sid 是 vlan id。
- 連線虛擬機器的 tap 介面
- 和 qrouter 連線的 tap 介面
- 和該網路的 qdhcp 連線的 tap 介面
如果同時有 VXLAN 虛擬網路的話(linux-bridge 不支援GRE 隧道模式),會為每個 VLAN 虛擬網路建立一個 Tunnel bridge。它連線多個網元:
- vxlan interface,這種介面每個虛擬網路一個,名字格式為 vxlan-sid,其中 sid 是分段ID。
- 連線虛擬機器的 tap 介面
- 和 qrouter 連線的 tap 介面
- 和該網路的 qdhcp 連線的 tap 介面
安全組規則在 tunnel bridge 和 vlan bridge 上。
OVS 方案:
這裡面,br-int 會負責加本地 VLAN 標籤,br-tun 會負責將 VLAN ID 轉換為 VXLAN ID。
4.2 計算節點上
同樣來對比著看。
linux bridge:
網路服務:
- Linux bridge agent
和網路節點類似,只不過沒有 qrouter 和 qdhcp,不在贅述。
OVS:
OVS 放在在 br-int 上實現 VLAN 標籤,在 br-tun 上實現隧道,在 qbr linux bridge 上實現安全組。
4.3 網路路徑 - 南北向網路流向
VLAN 網路和VXLAN 網路井水不犯河水。這圖上的配置中,計算節點和網路節點上的物理網絡卡都分開了。
4.4 網路路徑 - 東西向(不同網路)
4.5 網路路徑 - 東西向(同一個網路)
請詳細說明和配置,請參閱參考文件。
5. 一點結論
和基於 OVS 的二層網路相比,
- 功能和架構上:基於 linux bridge 的實現還是有一些短處,比如每個虛擬網路就需要一個網橋,這在大規模環境中會帶領資源使用和管理上的問題。其好處是本身架構比較清晰。
- 效能上:基本上差不多,如下圖所示,不管是 vxlan 還是 vlan。
參考資料:
歡迎大家關注我的個人公眾號:
相關推薦
理解 neutron(15):Neutron Linux Bridge + VLAN/VXLAN 虛擬網路
學習 Neutron 系列文章: 雖然大部分的OpenStack 部署環境中,都會使用 Open vSwitch 來作為虛擬交換機來實現二層網路功能,但是Neutron 仍然支援使用 Linux bridge 作為虛擬交換機來實現二層網路。
Neutron 理解(14):Neutron ML2 + Linux bridge + VxLAN 組網
學習 Neutron 系列文章: 1. 基礎知識 1.1 VXLAN 和 Linux 以及 Linux bridge 的關係 VXLAN 是一個新興的SDN 標準,它定義了一種新的 overlay 網路,它主要的創造者是 VMware,
理解OpenShift(1):網路之 Router 和 Route Neutron 理解 (7): Neutron 是如何實現負載均衡器虛擬化的
理解OpenShift(1):網路之Router 和 Route 1. OpenShift 為什麼需要 Router 和 Route? 顧名思義,Router 是路由器,Route 是路由器中配置的路由。OpenShift 中的這兩個概念是為了解決從叢集外部(就是從除了叢集節點
理解 OpenStack 高可用(HA)(3):Neutron 分散式虛擬路由(Neutron Distributed Virtual Routing)
本系列會分析OpenStack 的高可用性(HA)概念和解決方案: Neutron 作為 OpenStack 一個基礎性關鍵服務,高可用性(HA)和擴充套件性是它的基本需求之一。對 neutron server 來說,因為它是無狀態的,我們可以使用負載均衡器(Load B
理解 OpenStack 高可用(HA)(2):Neutron L3 Agent HA 之 虛擬路由冗餘協議(VRRP)
本系列會分析OpenStack 的高可用性(HA)概念和解決方案: 1. 基礎知識 1.1 虛擬路由冗餘協議 - VRRP 1.1.1 概念 路由器是整個網路的核心。一個網路內的所有主機往往都設定一條預設路由,這樣,主機發出的目的地址不在本網段的報文將被通過預設路由
理解Docker(3):Docker 使用 Linux namespace 隔離容器的執行環境
來源:http://www.cnblogs.com/sammyliu/p/5878973.html 1. 基礎知識:Linux namespace 的概念 Linux 核心從版本 2.4.19 開始陸續引入了 namespace 的概念。其目的是將某個特定的全域性
深入理解設計模式(15):訪問者模式
一、什麼是訪問者模式 定義:表示一個作用於其物件結構中的各元素的操作,它使你可以在不改變各元素類的前提下定義作用於這些元素的新操作。 可以對定義這麼理解:有這麼一個操作,它是作用於一些元素之上的,而這些元素屬於某一個物件結構。同時這個操作是在不改變各元素類的前提下,在這個前提下定義新操作是訪問者模式精髓中
深入理解JavaScript系列(15):函式(Functions)
詳情請檢視:https://www.cnblogs.com/TomXu/archive/2012/01/30/2326372.html 本章節我們要著重介紹的是一個非常常見的ECMAScript物件——函式(function),我們將詳細講解一下各種型別的函式
探索 OpenStack 之(7):Neutron 深入探索之 Open vSwitch (OVS) + GRE 之 Neutron節點篇
0. 測試環境 OpenStack配置: tenant:三個tenant:demo,tenant-one,tenant-two network:三個tenanet公用public network,每個tenant擁有自己的subnet,都有一個router連線自己的subnet到public n
學習OpenStack之(6):Neutron 深入學習之 OVS + GRE 之 Compute node 篇
0.環境 OpenStack網路配置:一個tenant, 2個虛機 Type driver: GRE, Mechanism driver: OVS 一個public network: ext-net 和相應的subnet ext-subnet 一個VM network:demo-net 和相應
探索 OpenStack 之(8):Neutron 深入探索之 OVS + GRE 之 完整網路流程 篇
前兩篇博文分別研究了Compute節點和Neutron節點內部的網路架構。本文通過一些典型流程案例來分析具體網路流程過程。 0. 環境 簡單總結一下: Compute 節點上由Neutron-OVS-Agent負責: br-int:每個虛機都通過一個Linux brige連到該OVS橋上
每天一個linux命令(15):tail 命令,實時列印TOMCAT日誌
tail 命令從指定點開始將檔案寫到標準輸出.使用tail命令的-f選項可以方便的查閱正在改變的日誌檔案,tail -f filename會把filename裡最尾部的內容顯示在螢幕上,並且不但重新整理,使你看到最新的檔案內容. 1.命令格式; tail[必要引數][選擇引數][檔案] 2.命令功能
OpenStack Neutron(3):建立instance分配floating IP及neutron原理分析
現在可以通過Dashboard建立instance並且分配floating IP,從而我們可以通過外網隨意訪問建立的instance,例如ping或者SSH。需要注意的是在分配security group的時候,如果要使用Default 的security group,需要新
Java 集合深入理解(15):AbstractMap
今天來了解下 AbstractMap。 什麼是 AbstractMap AbstractMap 是 Map 介面的的實現類之一,也是 HashMap, TreeMap, ConcurrentHashMap 等類的父類。 Abst
OpenStack Neutron(2):建立私有網路並與公網相連
在OpenStack中,建立instance之前必須建立網路。這裡通過Dashbord建立私有網路並且通過虛擬路由器與公網相連。私有網路即Tenant network。1. 建立私有網路及其子網登入Dashbord->Project->Network->Ne
每天一個linux命令(15):tail 命令
tail 命令從指定點開始將檔案寫到標準輸出.使用tail命令的-f選項可以方便的查閱正在改變的日誌檔案,tail -f filename會把filename裡最尾部的內容顯示在螢幕上,並且不但重新整理,使你看到最新的檔案內容. 1.命令格式;tail[必要引數][選擇引數]
Windows Phone開發(15):資源
樣式表 為什麽 sent name for cor 控件 tar resource 活字印刷術是我國“四大發明”之一,畢昇在發明活字印刷術之後,他很快發現一個問題,隨著要印刷資料的不斷增加,要用到的漢字數目越來越多,於是,他必須尋找一種有效的辦法去管理那些刻有漢字的立方體(
springBoot(15):集成Swagger
springboot 集成swagger 一、簡介Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。http://swagger.io/ Springfox 的前身是swagger-springmvc,是一個開源的API doc框架,可以將我們
多線程面試題系列(15):關鍵段,事件,互斥量,信號量的“遺棄”問題
creating 不為 char toc 效果 創建 cti 不能 false 一.什麽是“遺棄”問題 在第七篇講到了互斥量能處理“遺棄”問題,下面引用原文: 互斥量常用於多進程之間的線程互斥,所以它比關鍵段還多一個很有用的特性——“遺棄”情況的處理。比如有一個占用互斥量的
《Linux學習並不難》文件系統管理(3):在Linux系統中創建文件系統
Linux xfs 文件系統 18.3 《Linux學習並不難》文件系統管理(3):在Linux系統中創建文件系統使用mkfs命令可以在分區上創建各種文件系統。mkfs命令本身並不執行建立文件系統的工作,而是去調用相關的程序來執行。這裏的文件系統是要指定的,比如xfs、ext4、ext3、vfa