
简介这份PDF是中国传媒大学《媒体数据库与云存储》课程的实验四报告面向信息与通信工程等专业学生围绕OpenStack云计算平台与Swift对象存储展开适合正在学习云计算部署、云存储运维的初中级读者对照实践。报告完整记录了从VMware添加VMnet10虚拟网络、启动OpenStack主机、经Dashboard登录并创建Inst_demo等云主机实例到查看public与private子网及router-demo路由接口的网络配置过程Swift部分则涵盖CLI认证、容器新建、对象上传以及元数据查看、添加、修改、删除等操作并附有Holidays、Sports容器与对象的思考题实践及OpenStack对比、云架构问答。整包共1个PDF文件约3.66MB图文并排呈现操作界面与命令结果便于按步骤复现实验和复盘排错。目前已有84人学习可作为课程实验参考与考前复习材料。1. 从一份实验报告要解决的问题入手OpenStack 加 Swift 能解决什么把《媒体数据库与云存储》这份实验报告拆开看真正有价值的部分是它串起来的一条完整链路先在 VMware 里划出一张 VMnet10 虚拟网络把 OpenStack 主机跑起来用 Dashboard 以 demo 租户建实例、看路由再切到 test 账户用 Swift CLI 完成认证、建容器、上传对象、改元数据。这条链路走通一次云平台里计算、网络、存储三块是怎么结合的就有实际操作的手感了。适合两类人一类是要交实验报告、但只会照着截图敲命令的学生另一类是第一次接手私有云、需要一套能照抄的最小验证流程的运维。下面按报告里的实际步骤复现参数、命令、报错都按现场来能不省略的地方尽量不省略。2. 环境初始化VMnet10、Dashboard 登录与第一台云主机这一章把“能登进去”这件事做扎实。很多人卡在这一步往往觉得自己对 OpenStack 不熟其实是网络地址和用户角色没理清——虚拟网络选错模式、用 admin 去建实例、实例起在 private 网段却想直接从宿主机 ping这三件事占了大半的返工。2.1 虚拟网络与主机镜像先把地址规划固定下来VMware 里新建 VMnet10这一步的重点不在“加一张网卡”而在确定这张网用哪种模式。实验环境里 OpenStack 主机自己就是一台虚拟机宿主机上的浏览器要访问它的 Dashboard所以 VMnet10 通常按仅主机Host-Only模式配网段和物理局域网错开避免和公司或宿舍网段的 192.168.x 冲突。我一般先用ipconfigWindows或ifconfigmacOS/Linux看一遍宿主机的现有网段再决定 VMnet10 用 192.168.3.0/24因为报告里主机的地址是 192.168.3.40宿主机上再挂一张同网段的虚拟网卡浏览器才访问得到。虚拟机启动后用 test 账户登录先不要急着开浏览器先在终端把网络状态看清楚# 查看所有网卡的 IPv4 地址确认 VMnet10 对应的那张网卡拿到了 192.168.3.40 ip -4 addr show | grep -E inet # 看默认路由确认流量出口不是另一张 NAT 网卡 ip route show default # 确认 OpenStack 各服务端口在监听keystone 5000、nova 8774、glance 9292 # neutron 9696、horizon 80/8080、novnc 6080 ss -lntp | grep -E :(5000|8774|9292|9696|80|8080|6080)\b代码的逻辑很直白先确认地址再确认路由最后确认服务。参数上唯一需要改的是网段如果实验环境给的地址不是 192.168.3.x把 grep 的条件换掉即可。服务端口那段如果只出来一两个说明 OpenStack 没起全常见做法是systemctl status逐个看keystone、nova-api、glance-api、neutron-server不要一上来就重装。纯血泪经验端口没起来的时候去调 Horizon 的配置等于把时间花在错误的地方。镜像那一步报告里是“从已有镜像生成 OpenStack 主机”本质就是 VMware 打开一个已经装好 OpenStack 的 ovf/ova 或 vmdk克隆时选择“我已复制该虚拟机”否则网卡 MAC 冲突地址会飘。克隆完第一件事是改主机名和静态地址别让 DHCP 把 192.168.3.40 分给别人。2.2 Dashboard 的三种角色admin、demo、test 分别负责什么这套实验用了三个账户分工很明确混用就会出各种“看不到资源”的问题。下面这张表是按报告实际流程整理的账户认证域主要用途容易混淆的地方adminDefault管理镜像、卷、租户、用户在 admin 下创建的实例demo 用户默认看不见原因是租户隔离demoDefault建实例、建网络、建路由日常操作都在这一层建实例前必须确认当前项目是 demo否则资源建到了 admin 项目test系统本地用户登录 Swift 客户端主机执行 CLI它不是 Keystone 里的租户用户只是操作系统账户理解了这张表后面很多现象就说得通了。比如“我在 Dashboard 里建了实例换个人登录就没了”这通常不是数据丢失而是项目Project切换了。OpenStack 的隔离单位是项目不是用户同一项目里的用户互相能看见资源跨项目就是两套世界。认证这层由 Keystone 管你登录拿到的是一张 token后面所有 API 调用都带着它token 默认有效期不长实验做久了突然报 401八成是过期重新登录即可。用浏览器访问http://192.168.3.40/或带 8080 端口看环境输 demo 的凭据进去。上来先看三个位置项目 → 计算 → 实例看有没有遗留的旧实例项目 → 网络 → 网络拓扑看 public/private 两张网和 router-demo 是不是已经建好管理员 → 系统 → 卷看云存储里的卷信息。这三眼看下去环境是不是干净就心里有数了比上手就建实例靠谱。2.3 从镜像到实例Inst_demo 的创建参数与 Console 验证建实例这一步Dashboard 上填的东西不多但每一项都会在后面出问题。按报告流程用 demo 登录后进“计算 → 实例 → 创建实例”关键参数这么填参数取值说明实例名称Inst_demo / Inst_cirros / Inst_fedora名字带镜像特征后面排错一眼能认出来来源镜像 → cirros / fedora选“创建新卷”会多占存储实验环境选“否”直接起规格m1.tiny 或自定义小规格实验机内存有限别选 m1.small 以上网络private 网络选 public 会直接占宿主机网段地址安全组default默认组通常只放通同组内流量后面要按需加规则实例起来后不要只看状态是不是“运行中”要点进 Inst_cirros 的 Console 控制台用镜像自带的账号登进去看 IP。报告里 Inst_cirros 拿到 10.0.0.31、Inst_fedora 拿到 10.0.0.121两个地址都在 10.0.0.0/24 段内说明它们接的是 private 网络。在 Console 里互相 ping 通只能证明同网段二层通不能证明外网通这一点后面第 3 章还要再拆一次。创建过程中常见的失败有两种一是实例卡在“创建中”多半是 nova 调度不到计算节点去/var/log/nova/nova-scheduler.log看有没有No valid host二是实例起来了但 Console 黑屏通常是镜像本身不支持 VNC 或者 novncproxy 没起跟实例无关。判断方法很简单——同一个镜像建两台两台都黑屏就查服务只有一台黑屏就重建那一台。3. 网络拓扑解析public/private 双网与 router-demo 的连通方式3.1 两张网的地址切分与各自角色报告里的网络状态图信息量其实很大整个云有一个 public 子网和一个 private 子网private 里挂两台主机通过 router-demo 连到 public。把它翻译成地址表就是对象网段/地址角色public 网络192.168.3.0/24对接宿主机所在网络Dashboard 和管理流量走这里private 网络10.0.0.0/24实例的租户内网实例地址从这里分配router-demo 在 public 的接口192.168.3.77路由器的外网网关地址router-demo 在 private 的接口10.0.0.1实例的默认网关Inst_cirros10.0.0.31private 网内的实例Inst_fedora10.0.0.121private 网内的实例这张表的意义在于实例的默认网关必须是 10.0.0.1而不是 192.168.3.x。如果实例里ip route看到的默认路由指向别处那它出网一定失败。另外 10.0.0.0/24 是 RFC1918 私有段宿主机是访问不到的宿主机能访问的是 router 的 192.168.3.77。很多人在这里搞混以为建完实例就能从宿主机直连 10.0.0.31然后反复怀疑防火墙。3.2 router-demo 的两个接口与 SNAT/DNAT 的分工路由器在 OpenStack 里不是一个硬件盒子而是一个跑在网络节点上的网络命名空间两个接口就是两个 veth 对。它的作用有两个方向出方向做 SNAT把 10.0.0.x 的源地址改成 192.168.3.77 发出去入方向做 DNAT把外部访问某个浮动 IP 的流量转给内部的 10.0.0.x。实验里只验证了内部互通没有配浮动 IP所以宿主机访问不到实例是正常的不是配错了。要在命令行把这件事看清楚可以在控制节点上直接进路由器命名空间验证# 先拿到 router-demo 的 ID 和两个接口的地址 openstack router show router-demo -c id -c interfaces_info -f yaml # 列出所有网络命名空间路由器的命名空间形如 qrouter-router-id ip netns list # 进入路由器命名空间从 10.0.0.1 这一侧去 ping 实例 sudo ip netns exec qrouter-router-id ping -c 3 10.0.0.31 # 看命名空间里的 NAT 规则确认 SNAT 是否真的生效 sudo ip netns exec qrouter-router-id iptables -t nat -L -n -v | grep -i snatip netns exec这个用法值得记住它让你站到路由器内部去看世界ping通了说明 private 网络和路由器之间没问题不通就往实例的安全组和端口状态上查。iptables -t nat那行是看 SNAT 规则有没有下发如果一条都没有说明路由器的外部网关没设去 Dashboard 的“网络 → 路由 → 设置网关”补上。参数里唯一要替换的是router-id从第一条命令的输出里取。顺带说一句这套网络模型跟关系库里的事务边界有点像public 和 private 是两张表router 是那个外键实例的地址是行数据。理解了层级关系再看 Dashboard 的拓扑图就不会觉得是一堆线。3.3 连通性验证的排查顺序验证顺序我一般固定成四步避免东一榔头西一棒子先看实例的 IP 和默认路由再看同网段互 ping再看路由器命名空间里的连通性最后才看跨网段和外网。按报告的场景Inst_cirros 的 10.0.0.31 和 Inst_fedora 的 10.0.0.121 互 ping 通只完成了第二步。第一步在实例内部执行# cirros 镜像默认账号 cirros/gocubsgo登进去先看地址和路由 ip -4 addr show eth0 ip route show # 默认路由应该指向 10.0.0.1也就是 router-demo 的 private 接口第三步在控制节点上做用上面那段ip netns exec的命令。第四步才涉及安全组OpenStack 默认安全组只允许同组实例互访ICMP 是放通的但如果有人改过规则ping 不通就先去“项目 → 网络 → 安全组”看有没有 ICMP 的入方向规则。这里常见的错误是给实例加了新安全组但没重启端口规则不生效把端口 detach 再 attach 一次就好。4. Swift 对象存储实操认证、容器、上传与元数据4.1 认证与 CLI 环境token 从哪来、活多久Swift 的所有操作都要先过 Keystone 认证拿 token这一步在 CLI 上表现为一组环境变量加一条swift auth。实验环境如果是较新的版本用 v3 认证# Swift 客户端主机上用 test 账户登录后先导入认证环境变量 export OS_AUTH_URLhttp://192.168.3.40:5000/v3 export OS_PROJECT_NAMEdemo export OS_PROJECT_DOMAIN_NAMEDefault export OS_USERNAMEdemo export OS_PASSWORDdemo的口令 export OS_USER_DOMAIN_NAMEDefault # 认证并打印拿到的存储端点成功会输出 storage_url 和 auth_token swift auth # 查看当前账户的统计信息容器数、对象数、已用字节 swift stat参数里最容易出错的是OS_AUTH_URL的版本后缀。老环境是 v2.0路径写成http://192.168.3.40:5000/v2.0并且不需要OS_USER_DOMAIN_NAME和OS_PROJECT_DOMAIN_NAME这两个变量新环境是 v3不写域名会报401 Unauthorized而且错误信息只说认证失败不说缺哪个字段。这是典型的不容易看出来的问题我的习惯是认证不通先把环境变量全打出来对一遍别去翻服务端日志。swift stat的输出值得留意Account、Containers、Objects、Bytes四个字段。如果Containers一直是 0 但你确实建过容器那多半是认证到了另一个账户——demo 和 admin 的 Swift 账户是独立的名字看起来一样实际是两套命名空间。在媒体类项目里对象存储和关系库的分工要分清MySQL 那套本地用 XAMPP 起的那种存的是节目单、素材索引这类结构化字段几 MB 的视频、音频、图片原始文件扔给 Swift 更合适。两边的关联靠对象名做外键而不是把二进制塞进 BLOB 字段——那样备份和迁移都会很痛苦。4.2 容器与对象把本地文件变成云端对象容器的概念接近文件夹但没有真正的目录层级对象名里的斜杠只是名字的一部分。操作序列按报告走一遍# 建一个容器名字用业务语义别用 test1/test2 swift post media-demo # 列出当前账户下所有容器 swift list # 造一个 4MB 的本地文件当作上传素材 dd if/dev/urandom of./holiday.bin bs1M count4 # 上传对象第二个参数是容器名第三个是本地文件路径 swift upload media-demo ./holiday.bin # 确认对象在容器里能看到大小和最后修改时间 swift list media-demo -l # 看对象的详细元数据包括 Content-Type、ETag、时间戳 swift stat media-demo holiday.bin # 下载回来做一致性校验ETag 就是文件的 MD5 swift download media-demo holiday.bin -o ./holiday.download.bin md5sum ./holiday.bin ./holiday.download.binswift upload默认会按文件大小自动分段小于 5GB 的文件一般不触发分段上传超过阈值的会走 SLO/DLO 大对象机制这是后面排错时容易忽略的一点。swift list -l的-l是 long 格式多出来的是字节数和时间排查“传上去了但大小不对”时必看。下载后的md5sum对比是我每次都要做的动作因为 ETag 对普通对象就是 MD5两者对不上说明传输过程出了问题跟存储无关。对象名建议带时间或业务前缀比如2024/12/holiday.bin这不会真的建出目录但swift list media-demo --prefix2024/12/能按前缀过滤效果和目录浏览一样。这个技巧在对象数量上千以后特别有用因为swift list一次列全量会很慢。4.3 元数据查看、添加、修改和删除的完整命令组元数据是 Swift 里最容易被轻视、也最容易出错的部分。它分容器级和对象级两层都以 HTTP header 的形式存在容器级前缀是X-Container-Meta-对象级是X-Object-Meta-。CLI 上用swift post -m设置# 给容器加元数据 year2014 swift post -m year:2014 media-demo # 给某个对象加元数据 time0203 swift post -m time:0203 media-demo holiday.bin # 查看容器元数据只看 Meta 开头的行 swift stat media-demo | grep -i meta # 查看对象元数据 swift stat media-demo holiday.bin | grep -i meta # 修改就是同名 key 再写一次后写的覆盖先写的 swift post -m year:2015 media-demo # 删除某个元数据键把值留空部分版本有效 swift post -m year: media-demo # 如果上面那条不生效用 curl 显式发 X-Remove-Container-Meta- 头 swift stat -v media-demo | head -n 20最后两条是关键。-m year:这种留空写法在部分 python-swiftclient 版本里会被当成“设置一个空值”而不是删除swift stat一看还在。稳妥做法是用 curl 带上X-Remove-Container-Meta-Year: x这个头或者升级客户端到明确支持删除语义的版本。参数上注意-m后面的冒号是分隔 key 和 value 的key 里不能带冒号value 里可以。这一条踩过坑的人不少——元数据看着删了第二天做批量清理脚本时发现全在。元数据的实际用途是给对象打业务标签比如素材的拍摄时间、版权方、审核状态。它不进对象的字节流读取时走 HEAD 请求所以开销很小但也别塞太多单个对象元数据总量有上限超了会返回 400。4.4 思考题复现用脚本一次建完 Holidays 与 Sports报告最后的思考题要求建两个容器、六个对象、逐层加元数据。手工敲 12 条命令很低效写个脚本一把过#!/usr/bin/env bash # 用法./init_lab.sh 2021211013036 set -euo pipefail SID${1:?用法: $0 学号} # 容器级元数据year declare -A C_META( [Holidays_${SID}]2014 [Sports_${SID}]2016 ) # 对象级元数据格式 容器|对象|键|值 OBJECTS( Holidays_${SID}|Cambridge|time|0203 Holidays_${SID}|Oxford|time|0204 Holidays_${SID}|London|time|0205 Sports_${SID}|Tennis|team|yellow Sports_${SID}|Badminton|team|blue Sports_${SID}|Soccer|team|red ) # 第一步建容器并写容器元数据 for c in ${!C_META[]}; do swift post $c swift post -m year:${C_META[$c]} $c echo [容器] $c - year:${C_META[$c]} done # 第二步建空对象占位并写对象元数据 for row in ${OBJECTS[]}; do IFS| read -r c o k v $row # 用一个空文件上传得到零字节对象真实场景换成素材文件 : /tmp/${o}.txt swift upload $c /tmp/${o}.txt --object-name $o swift post -m ${k}:${v} $c $o echo [对象] $c/$o - ${k}:${v} done # 第三步回读验证逐条打印元数据 for row in ${OBJECTS[]}; do IFS| read -r c o _ _ $row printf %-22s %s\n $c/$o $(swift stat $c $o | grep -i Meta | tr \n ) done脚本逻辑分三段建容器写容器元数据、建对象写对象元数据、回读校验。参数上只接一个学号用来拼容器名避免多人共用一套环境时互相覆盖。--object-name是关键参数它让你上传本地文件时指定云端对象名不然对象名会带上/tmp/路径和.txt后缀跟题目要求对不上。第三步的回读是必须的因为swift post -m成功不代表元数据写对了键名打出来看一眼比事后翻账单省事。跑完对照检查容器容器元数据对象对象元数据Holidays_学号year:2014Cambridgetime:0203Holidays_学号year:2014Oxfordtime:0204Holidays_学号year:2014Londontime:0205Sports_学号year:2016Tennisteam:yellowSports_学号year:2016Badmintonteam:blueSports_学号year:2016Soccerteam:red清理的时候顺序反过来先删对象再删容器容器非空时swift delete会直接报 409这是设计如此不是 bug。批量删可以用swift delete 容器加循环但注意别在生产账户上试。5. 排查手册五个现场翻车记录5.1 Dashboard 登录报 401密码明明是对的现象浏览器输 demo 的账号密码页面提示认证失败终端swift auth也报 401但同样的口令在别的机器上能用。原因八成是时间不同步——Keystone 签发的 token 有严格的生效和过期时间窗控制节点和客户端的时间差超过几分钟token 就会被判无效。解决在控制节点和客户端都跑timedatectl看时间用chronyc sources -v确认时间源同步正常把两边拉齐后重登。虚拟机挂起再恢复特别容易触发这个属于典型的不容易看出来的问题查日志只会看到Unable to authenticate。5.2 swift list 报 503容器列表刷不出来现象认证成功swift stat有输出但swift list返回 503Dashboard 上对象存储页面也转圈。原因通常是 proxy server 连不上 account server或者 account 服务的 ring 文件跟实际设备对不上。解决顺序先在 proxy 节点看/var/log/swift/proxy-server.log里的具体报错如果是Timeout就去 account 节点查服务状态如果是Ring file not found就用swift-ring-builder account.builder确认 ring 里注册的设备数和实际磁盘数一致不一致要rebalance后把 ring 同步到所有节点。别急着重建 ring先看设备列表。5.3 实例之间 ping 不通安全组看着没问题现象同 private 网段的两台实例互 ping 超时安全组里 ICMP 规则是放通的。原因多半是端口没真正绑定到网络或者实例的默认网关指向了错误地址。解决先在实例里ip route确认默认路由是 10.0.0.1再在控制节点openstack port list --server 实例名看端口状态是不是 ACTIVE、绑定的 IP 对不对最后用ip netns exec qrouter-id ping从路由器侧验证。三步走完基本能定位到是实例侧还是网络侧。翻车最多的是克隆实例时带过来的旧网卡配置/etc/network/interfaces里写死了别的地址。5.4 对象元数据删不掉stat 一看还在现象执行swift post -m time: media-demo holiday.bin没报错但swift stat里time还在。原因是这个写法在部分客户端版本里被解释为“写入空值”。解决改用显式的移除头curl -X POST -H X-Auth-Token: token -H X-Remove-Object-Meta-Time: x storage_url/media-demo/holiday.bin或者把客户端升级到明确支持删除语义的版本。容器级同理把Object换成Container。这个问题的隐蔽之处在于命令返回码是 0批量脚本里根本发现不了。5.5 上传大文件卡住或超时现象几 MB 的文件秒传几百 MB 的文件传到一半超时重试还是断在差不多的地方。原因是单次 PUT 的时长超过了代理层或网关的超时阈值或者是分段上传的分片大小没设对。解决用swift upload --segment-size 1073741824 --segment-container media-segments media-demo bigfile.iso把分片设成 1GB让客户端走 SLO同时在 proxy 的配置里把node_timeout和client_timeout调大。参数上分片别设太小几百 MB 一片会产生大量小对象反而拖慢 manifest 的读取。传完用swift stat看Content-Length跟本地文件大小是否一致不一致就是分段没合并完整。6. 把思考题答成可验证的东西Ring、副本与数据模型最后落到报告里那几道需要“解释原理”的题。这部分光背文字没用得能和前面的操作对上。Swift 的逻辑结构是三层Account → Container → Object访问路径形如/v1/AUTH_account/container/object对象名里允许带斜杠但存储层是扁平的没有真正的目录。物理结构上则是另一套东西proxy server 收请求account/container/object server 管三类数据ring 负责“数据放哪”replicator、updater、auditor 三个后台进程负责副本同步、失败重试和完整性校验。组件职责和实测现象的对应关系Proxy Server对外唯一入口解析请求、查 ring、转发5.2 里的 503 就出在这一层Account Server管容器列表账户统计里的 Containers 字段来自这里Container Server管对象列表swift list的响应来自这里Object Server存实际字节ETag 与 MD5 一致说明这一层没动过数据Ring一致性哈希决定副本落点副本数、zone 分布都写在 ring 里Ring 的工作原理用一句话说就是“把存储空间摊到一个哈希环上对象哈希后顺时针找第一个虚节点”。细节是先对所有设备做一致性哈希哈希值落在 0 到 2³²−1 之间首尾相接成一个环每个设备被切成若干虚节点partition散布在环上对象名哈希后从落点顺时针走遇到的第一个虚节点负责存它为了副本继续顺时针找下一个不同 zone/device 的虚节点凑够 3 个。虚节点的作用是把数据打散避免某个设备容量大就把热点全吸过来。验证方法很直接swift-ring-builder object.builder能看到 ring 的 partition 数、副本数、各 zone 的设备权重swift-get-nodes object.ring.gz account container object能算出某个对象的三份副本落在哪几个节点上。我一般在上传完一个对象后跑一次这个命令比对着看三份副本是不是分布在不同设备上——如果三份都落在同一个 zone那高可用就是纸面上的机器一挂数据全没。副本数默认 3这个数字不是随便定的它能容忍两份副本同时失效还能读代价是存储利用率只有三分之一。实验环境为了省空间会改成 1 或 2改完一定记得重新 rebalance 并同步 ring否则新对象还是按旧规则落盘看着配置改了实际没生效。这一点跟前面 5.4 的元数据删除一样属于“命令成功但行为没变”的坑。从那以后我每次动 ring、动元数据、动安全组都强制走一遍“改完回读”的动作ring 用swift-get-nodes验证落点元数据用swift stat验证键值安全组用一次真实的 ping 验证连通。这三步多花不了两分钟但能挡掉大部分“我以为改好了”的事故。希望帮到你。本文还有配套的精品资源点击获取