C12-OpenStack 網路服務 1:Neutron 架構與 OpenStack 網路模型

0. 環境與準備

0.1 本課環境

主機角色管理網 IP
jmp001學員操作機(OpenStack CLI),同時接在外部網段 192.168.100.0/2410.127.0.3
ctl001 / ctl002 / ctl003控制節點(neutron-server、OVN 控制元件、對外閘道)10.127.0.4 / .14 / .15
scp001 / scp002運算節點10.127.0.7 / .18
—VIP10.127.0.250

本課要建立的拓樸(藍色字母是建立該元件的小節):

C12 本課要建立的網路拓樸 外部網路 public1(192.168.100.0/24)上有 jmp001(.10)與實體路由器(.1,通往 Internet)。c12-stuNN-router 以 Gateway Port 接 public1、以 Router Interface(10.12.N.1)接租戶網路 c12-stuNN-net。VM 經 c12-stuNN-port 接上租戶網路,Port 套用 c12-stuNN-sg;Floating IP 在 router 上以 1:1 NAT 對應到 VM 的 fixed IP。 external network public1(flat) public1-subnet 192.168.100.0/24 FIP / 閘道位址池 .100–.200 jmp001 學員操作機 .10 Internet 實體路由器 .1 FIP .1xx 1:1 NAT(在 router 上做 DNAT / SNAT) F .1xx router_gateway .1 router_interface SNAT:沒有 FIP 的 VM 共用 .1xx 出去 c12-stuNN-router OpenStack 邏輯路由器 E tenant network c12-stuNN-net(geneve) c12-stuNN-subnet 10.12.N.0/24 B .2 network:distributed(DHCP / metadata) .x c12-stuNN-vm cirros · m1.tiny port:c12-stuNN-port D c12-stuNN-sg egress 全部允許(預設) ingress ICMP ← F3 ingress TCP 22 ← F4 C 套用在 Port 上,不是 VM
本課要建立的網路拓樸

0.2 連線方式

全班與講師共用 jmp001 與控制節點上的 ubuntu 帳號(具 sudo 權限)。先登入 jmp001,所有指令都在 jmp001 執行。

⚠️ 規則

  • 你使用的是和講師相同的管理員權限,只操作名稱有你編號的資源
  • 不要使用或修改 default security group:它已被講師加了 ICMP、SSH 等規則,用它就看不到本課要觀察的現象
  • 預期輸出是示意,UUID、IP、數字可能與你看到的不同

0.3 準備

指令
# [jmp001]
export NN=01                                     # ← 換成你的學員編號(01–20)
source ~/venv/bin/activate
source ~/creds/stu${NN}-openrc.sh
export SUB=10.12.$((10#$NN))
echo "c12-stu${NN}  ${SUB}.0/24"

預期輸出:

預期輸出
c12-stu01  10.12.1.0/24

Part A:後端與外部網路(p.5、8)

指令
# [jmp001]
ssh 10.127.0.4 "sudo grep mechanism_drivers /etc/kolla/neutron-server/ml2_conf.ini"
openstack network list --external
openstack subnet show public1-subnet -c cidr -c gateway_ip -c allocation_pools

預期輸出:

預期輸出
mechanism_drivers = ovn
+--------------------------------------+---------+--------------------------------------+
| ID                                   | Name    | Subnets                              |
+--------------------------------------+---------+--------------------------------------+
| 351d82a1-2a0e-42d5-a428-3c7baa0be512 | public1 | b7dabca1-dc52-47dd-b3ba-22e03e7f2851 |
+--------------------------------------+---------+--------------------------------------+
+------------------+---------------------------------+
| Field            | Value                           |
+------------------+---------------------------------+
| allocation_pools | 192.168.100.100-192.168.100.200 |
| cidr             | 192.168.100.0/24                |
| gateway_ip       | 192.168.100.1                   |
+------------------+---------------------------------+

Part B:Network 與 Subnet(p.8、9、14)

指令
# [jmp001]
openstack network create c12-stu${NN}-net
openstack subnet create c12-stu${NN}-subnet --network c12-stu${NN}-net \
  --subnet-range ${SUB}.0/24 --gateway ${SUB}.1

預期輸出(節錄 subnet create):

預期輸出
+----------------------+--------------------------------------+
| Field                | Value                                |
+----------------------+--------------------------------------+
| allocation_pools     | 10.12.99.2-10.12.99.254              |
| cidr                 | 10.12.99.0/24                        |
| enable_dhcp          | True                                 |
| gateway_ip           | 10.12.99.1                           |
| name                 | c12-stu99-subnet                     |
| network_id           | 2c057a7e-4c9d-459a-9aef-6bdef3ea9f48 |
...
+----------------------+--------------------------------------+
指令
# [jmp001]
openstack network show c12-stu${NN}-net -c mtu -c provider:network_type -c provider:segmentation_id -c router:external -c subnets
openstack port list --network c12-stu${NN}-net --long -c "Fixed IP Addresses" -c "Device Owner" -c Status

預期輸出:

預期輸出
+--------------------------+--------------------------------------+
| Field                    | Value                                |
+--------------------------+--------------------------------------+
| mtu                      | 8492                                 |
| provider:network_type    | geneve                               |
| provider:segmentation_id | 1967                                 |
| router:external          | Internal                             |
| subnets                  | c0a24db3-c603-474b-8770-8f77aed3e1b6 |
+--------------------------+--------------------------------------+
+---------------------------------------------------------------------------+---------------------+--------+
| Fixed IP Addresses                                                        | Device Owner        | Status |
+---------------------------------------------------------------------------+---------------------+--------+
| ip_address='10.12.99.2', subnet_id='c0a24db3-c603-474b-8770-8f77aed3e1b6' | network:distributed | DOWN   |
+---------------------------------------------------------------------------+---------------------+--------+
欄位意義
provider:network_type = genevetype driver 用 Geneve tunnel 隔離各租戶網路(p.6)
provider:segmentation_id這個網路在 Geneve 中的識別碼(VNI),每個網路不同
mtu = 8492底層 MTU 8550 扣掉 Geneve 封裝的開銷
router:external = Internal一般租戶網路,不是外部網路

Part C:Security Group(p.11)

指令
# [jmp001]
openstack security group create c12-stu${NN}-sg -c name -c stateful
openstack security group rule list c12-stu${NN}-sg

預期輸出:

預期輸出
+----------+--------------+
| Field    | Value        |
+----------+--------------+
| name     | c12-stu99-sg |
| stateful | True         |
+----------+--------------+
+--------------------------------------+-------------+-----------+-----------+------------+-----------+-----------------------+----------------------+
| ID                                   | IP Protocol | Ethertype | IP Range  | Port Range | Direction | Remote Security Group | Remote Address Group |
+--------------------------------------+-------------+-----------+-----------+------------+-----------+-----------------------+----------------------+
| 1954e378-833b-402d-85c4-d8e2b4e450f9 | None        | IPv6      | ::/0      |            | egress    | None                  | None                 |
| 6de6267f-06cc-4016-9d94-75a125e86491 | None        | IPv4      | 0.0.0.0/0 |            | egress    | None                  | None                 |
+--------------------------------------+-------------+-----------+-----------+------------+-----------+-----------------------+----------------------+

Part D:Port 與 VM(p.9、10、14)

D1. 先建 Port

指令
# [jmp001]
openstack keypair create c12-stu${NN}-key --private-key ~/c12-stu${NN}-key.pem
chmod 600 ~/c12-stu${NN}-key.pem
openstack port create c12-stu${NN}-port --network c12-stu${NN}-net --security-group c12-stu${NN}-sg \
  -c fixed_ips -c mac_address -c status
openstack port show c12-stu${NN}-port -c status -c binding_host_id -c device_owner -c device_id

預期輸出:

預期輸出
+-------------+-----------------------------------------------------------------------------+
| Field       | Value                                                                       |
+-------------+-----------------------------------------------------------------------------+
| fixed_ips   | ip_address='10.12.99.195', subnet_id='c0a24db3-c603-474b-8770-8f77aed3e1b6' |
| mac_address | fa:16:3e:b3:a7:4e                                                           |
| status      | DOWN                                                                        |
+-------------+-----------------------------------------------------------------------------+
+-----------------+-------+
| Field           | Value |
+-----------------+-------+
| binding_host_id |       |
| device_id       |       |
| device_owner    |       |
| status          | DOWN  |
+-----------------+-------+

D2. 用這個 Port 建立 VM

指令
# [jmp001]
openstack server create c12-stu${NN}-vm --image cirros --flavor m1.tiny --key-name c12-stu${NN}-key \
  --nic port-id=c12-stu${NN}-port --wait -c status -c OS-EXT-SRV-ATTR:host -c addresses
openstack port show c12-stu${NN}-port -c status -c binding_host_id -c device_owner -c device_id

預期輸出(約 20 秒):

預期輸出
+----------------------+----------------------------+
| Field                | Value                      |
+----------------------+----------------------------+
| OS-EXT-SRV-ATTR:host | scp002-6164930-iaas        |
| addresses            | c12-stu99-net=10.12.99.195 |
| status               | ACTIVE                     |
+----------------------+----------------------------+
+-----------------+--------------------------------------+
| Field           | Value                                |
+-----------------+--------------------------------------+
| binding_host_id | scp002-6164930-iaas                  |
| device_id       | 5bfce014-dcc7-469b-99ff-41ab2f840f23 |
| device_owner    | compute:nova                         |
| status          | ACTIVE                               |
+-----------------+--------------------------------------+
欄位建立 VM 前建立 VM 後告訴你什麼(p.10)
device_owner空compute:nova這是 VM 的網卡
device_id空VM 的 UUID屬於哪一台 VM
binding_host_id空scp002-…下發到哪一台節點
statusDOWNACTIVE後端回報綁定完成

Part E:Router(p.10、15)

指令
# [jmp001]
openstack router create c12-stu${NN}-router -c name -c external_gateway_info -c status
openstack router add subnet c12-stu${NN}-router c12-stu${NN}-subnet
openstack router set --external-gateway public1 c12-stu${NN}-router

預期輸出(只有 router create 有輸出):

預期輸出
+-----------------------+------------------+
| Field                 | Value            |
+-----------------------+------------------+
| external_gateway_info | null             |
| name                  | c12-stu99-router |
| status                | ACTIVE           |
+-----------------------+------------------+
指令
# [jmp001]
openstack router show c12-stu${NN}-router -c external_gateway_info -f yaml
openstack port list --router c12-stu${NN}-router --long -c "Fixed IP Addresses" -c "Device Owner" -c Status

預期輸出:

預期輸出
external_gateway_info:
  enable_snat: true
  external_fixed_ips:
  - ip_address: 192.168.100.126
    subnet_id: b7dabca1-dc52-47dd-b3ba-22e03e7f2851
  network_id: 351d82a1-2a0e-42d5-a428-3c7baa0be512
+--------------------------------------------------------------------------------+--------------------------+--------+
| Fixed IP Addresses                                                             | Device Owner             | Status |
+--------------------------------------------------------------------------------+--------------------------+--------+
| ip_address='192.168.100.126', subnet_id='b7dabca1-dc52-47dd-b3ba-22e03e7f2851' | network:router_gateway   | ACTIVE |
| ip_address='10.12.99.1', subnet_id='c0a24db3-c603-474b-8770-8f77aed3e1b6'      | network:router_interface | ACTIVE |
+--------------------------------------------------------------------------------+--------------------------+--------+

加了 -f yaml 是因為 external_gateway_info 是一個 JSON 物件,表格格式會擠成一長行。


Part F:Floating IP 與 Security Group(p.11、20、22)

F1. 配發並綁定 Floating IP

指令
# [jmp001]
FIP=$(openstack floating ip create -f value -c floating_ip_address public1)
echo $FIP
openstack server add floating ip c12-stu${NN}-vm $FIP
openstack server show c12-stu${NN}-vm -c addresses
openstack floating ip show $FIP -c fixed_ip_address -c port_id -c status

預期輸出:

預期輸出
192.168.100.194
+-----------+---------------------------------------------+
| Field     | Value                                       |
+-----------+---------------------------------------------+
| addresses | c12-stu99-net=10.12.99.195, 192.168.100.194 |
+-----------+---------------------------------------------+
+------------------+--------------------------------------+
| Field            | Value                                |
+------------------+--------------------------------------+
| fixed_ip_address | 10.12.99.195                         |
| port_id          | 063cb631-4187-47a3-bbb4-27946f0e0759 |
| status           | ACTIVE                               |
+------------------+--------------------------------------+

F2. 從外部 ping:不通

指令
# [jmp001]
ping -c 3 $FIP

預期輸出:

預期輸出
PING 192.168.100.194 (192.168.100.194) 56(84) bytes of data.

--- 192.168.100.194 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2073ms

FIP 綁好了、位址也看得到,但就是 ping 不到。這是 p.22 最常見的卡點:Security Group 沒有開 ingress。

F3. 加上 ingress 規則:馬上通

指令
# [jmp001]
openstack security group rule create --ingress --protocol icmp c12-stu${NN}-sg -c direction -c protocol
ping -c 3 $FIP

預期輸出:

預期輸出
+-----------+---------+
| Field     | Value   |
+-----------+---------+
| direction | ingress |
| protocol  | icmp    |
+-----------+---------+
PING 192.168.100.194 (192.168.100.194) 56(84) bytes of data.
64 bytes from 192.168.100.194: icmp_seq=1 ttl=63 time=25.5 ms
64 bytes from 192.168.100.194: icmp_seq=2 ttl=63 time=2.99 ms
64 bytes from 192.168.100.194: icmp_seq=3 ttl=63 time=2.28 ms

--- 192.168.100.194 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms

F4.(選做)SSH 進 VM,從裡面看

再開 SSH:

指令
# [jmp001]
openstack security group rule create --ingress --protocol tcp --dst-port 22 c12-stu${NN}-sg -c direction -c protocol -c port_range_min
ssh -i ~/c12-stu${NN}-key.pem cirros@$FIP

第一次連線會問 Are you sure you want to continue connecting (yes/no/[fingerprint])?,輸入 yes。看到 $ 提示字元後,在 VM 裡執行:

指令
# [c12-stuNN-vm]
ip addr show eth0
ip route
ping -c 2 8.8.8.8
exit

預期輸出(ip addr 只節錄 IP 位址那幾行):

預期輸出
    inet 10.12.99.195/24 brd 10.12.99.255 scope global dynamic noprefixroute eth0
    inet6 fe80::f816:3eff:feb3:a74e/64 scope link
default via 10.12.99.1 dev eth0  src 10.12.99.195  metric 1002
10.12.99.0/24 dev eth0 scope link  src 10.12.99.195  metric 1002
169.254.169.254 via 10.12.99.2 dev eth0  src 10.12.99.195  metric 1002
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=112 time=57.8 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=112 time=6.11 ms
觀察說明
VM 裡只有 10.12.99.195,看不到 192.168.100.194FIP 是 Router 上的 1:1 NAT,VM 本身不知道自己有 FIP(p.21)
default via 10.12.99.1第一跳就是 Router Interface(子網的 gateway)
169.254.169.254 via 10.12.99.2metadata 服務走 B 節看到的 network:distributed Port
可以 ping 8.8.8.8egress 預設放行;這台 VM 有 FIP,所以出外網時來源位址是 FIP 而不是 Router 的 .126(p.28)

Part G:清除(p.14、15)

刪除順序要和建立順序相反,被別人依賴的資源要最後刪。

指令
# [jmp001]
openstack server remove floating ip c12-stu${NN}-vm $FIP
openstack floating ip delete $FIP
openstack server delete --wait c12-stu${NN}-vm
openstack port show c12-stu${NN}-port -c status -c device_owner -c device_id

預期輸出:

預期輸出
+--------------+-------+
| Field        | Value |
+--------------+-------+
| device_id    |       |
| device_owner |       |
| status       | DOWN  |
+--------------+-------+

VM 刪掉了,Port 還在,只是又變回沒有主人的狀態。Nova 只會刪除它自己代建的 Port;用 --nic port-id= 帶進去的 Port 要自己刪(p.14)。

指令
# [jmp001]
openstack port delete c12-stu${NN}-port
openstack router delete c12-stu${NN}-router

預期輸出:

預期輸出
Failed to delete router with name or ID 'c12-stu99-router': ConflictException: 409: Client Error for url: http://10.127.0.250:9696/v2.0/routers/66bea3a4-..., Router 66bea3a4-... has ports still attached: 9be455f1-547a-4e36-b93e-c85d43988f41
1 of 1 routers failed to delete.

Router 還有 Port 接著(錯誤訊息最後的 UUID 就是 E 節看到的 Router Interface),不能直接刪。先拆掉兩種介面:

指令
# [jmp001]
openstack router remove subnet c12-stu${NN}-router c12-stu${NN}-subnet
openstack router unset --external-gateway c12-stu${NN}-router
openstack router delete c12-stu${NN}-router
openstack network delete c12-stu${NN}-net
openstack security group delete c12-stu${NN}-sg
openstack keypair delete c12-stu${NN}-key
rm -f ~/c12-stu${NN}-key.pem
openstack network list --name c12-stu${NN}-net
openstack router list --name c12-stu${NN}-router

預期輸出:(最後兩行沒有輸出)

預期輸出
建立順序刪除順序
Network → Subnet → SG → Port → VM → Router → FIPFIP → VM → Port → Router(先拆介面)→ Network → SG