接着前两篇的进度写。先电平台搭好以后,真正开始往上面跑业务的时候,坑基本都集中在网络和存储里,这篇操作笔记3就把这段时间的实践过程完整记录一下。平台本身相当于在底层那套云管理组件外面套了一层教学管理外壳,所以你在页面上点的很多操作,最后都要落到各个服务组件的API上。想看得更透、查错更准,我还是建议整一套命令行操作方式。这篇笔记默认你已经完成了平台部署、能正常登录管理页面,如果环境还没搭好,建议先回头看第一篇。下面要讲的内容有三个重点:网络规划与连通性、实例从创建到连接的完整链路、块存储的挂载与扩容,最后附一份我整理的排查清单。前后花了大概一周时间反复测,踩了不少坑,下面都是实测记录。
1. 动手之前:先摸清平台的骨架
1.1 其实你操作的是两个入口
先电平台的管理页面看起来很完整,但你看到的网络、镜像、实例这些菜单,本质都是对底层管理组件的封装。封装有个坏处:错误信息被截断了。比如说,在浏览器里创建一个网络报错,页面只会提示“创建失败”,具体原因一点不给;而在命令行里,服务端会直接告诉你哪一步出了问题,比如“物理网络不存在”“DHCP agent不可用”之类的关键词。
所以操作的第一步,不是急着点菜单,而是先把命令行入口准备好。一般是先source一下认证脚本,然后验证一下认证信息是否正常:
source /etc/keystone/admin-openrc.sh openstack endpoint list openstack token issue这里解释一下每条命令的意图:source是加载管理员账号的环境变量,后续openstack命令才能知道去哪个服务端认证;endpoint list是列出各个服务的访问地址,确认地址是否可通;token issue是实际向认证服务申请一个临时令牌,如果这条能成功,说明身份认证链路基本没问题。
我第一次操作时就遇到过这种情况:环境变量里的认证服务地址填的是主机名,但实验环境没有内部DNS解析,结果命令行全部超时。解决办法很简单,查看一下当前环境变量里的URL是不是IP:
env | grep OS_AUTH如果发现地址不对,直接修改admin-openrc.sh里的OS_AUTH_URL,把它改成管理节点的IP。这个文件通常放在/etc/keystone目录下,改完重新source一次就好。
1.2 服务进程正常,不代表链路正常
平台刚装完的时候,管理页面通常显示所有服务都是正常的,但“进程在跑”和“链路能通”是两件不同的事。我刚开始也天真地以为全部正常,直到创建第一个实例卡在调度阶段,才意识到要主动去验证服务状态。
建议在动手之前跑这两条命令:
openstack compute service list openstack network agent list第一条看计算服务,第二条看网络插件代理。输出里每一行的第三列是这个服务节点的运行状态,只有显示为UP才是可用状态。如果看到down或者XXX,后面创建实例大概率会出现各种“莫名奇妙”的问题,比如实例一直停留在创建中、虚拟机起来了但没有网络。
平台的教学场景里,经常有同学在实验环境里反复重置节点,到时候某个代理服务没跟着起来是很常见的。所以这里强调一遍:改任何配置前、做任何实验前,先把这两条列表截图或保留输出,后面排错会省很多时间。
2. 网络:实例上不了网,一半的锅都在这里
2.1 先搞清楚你建的是哪种网络
网络配置是整个平台里最容易让人懵圈的部分。实例创建出来拿不到IP、跨节点通信不通、外部访问不了虚拟机,这些问题十有八九都能追溯到网络类型没选对。
常见的网络类型有三种:flat、vlan、vxlan。我用自己的话给你翻译一下:
- flat网络:相当于一个二层大广播域,打个比方就是把一堆电脑插在同一个交换机上,谁都能直接通信。它的优点是无封装,性能损耗低;缺点是不隔离,适合做连接外部的链路,对外网络一般用它。
- vlan网络:在二层用802.1Q做了隔离,好比同一栋楼里分出多个房间,每个房间用了不同的门牌号。它需要交换机配置配合,适合有真实网络设备的机房。
- vxlan网络:用隧道封装实现隔离,相当于把不同楼层的房间通过一条虚拟走廊连起来。它不受物理交换机VLAN数量限制,适合多租户环境,但需要注意MTU,否则大包会被分片。
实验环境里通常至少要有两个网络:外部网络和内部网络。我自己的做法是,外部网络用flat类型,对应管理节点上物理网卡所在的那个物理网络,内部网络用vlan或vxlan,专门让实例之间的流量走这里。
创建外部网络的命令一般长这样:
openstack network create --share \ --provider:physical_network physnet1 \ --provider:network_type flat ext-net这里有两个参数特别容易踩坑。第一个是--share,表示这个网络可以被所有项目共用;如果不加,你可能在另一个项目里根本看不到这个网络。第二个是--provider:physical_network physnet1,它必须与底层配置文件里设置的物理网络名称完全一致。比如配置里写的是physnet2,你这里写成physnet1,创建不会报错,但后面实例上网就会变得时好时坏,日志里会有“Unknown physical network”的报错。
2.2 子网、网关和地址池到底怎么填
网络创建完,下一步是创建子网。这里涉及三个核心概念:网段、网关、地址池。
openstack subnet create --network ext-net \ --subnet-range 192.168.20.0/24 \ --gateway 192.168.20.1 \ --allocation-pool start=192.168.20.20,end=192.168.20.250 \ --dns-nameserver 223.5.5.5 ext-subnet这段命令含了几个关键决策点:
- --subnet-range是子网整体范围,决定了你能用多少个IP;
- --gateway是网关地址,负责把出去的流量交给路由器;
- --allocation-pool指定DHCP从哪个范围分配IP,这个范围要刻意跳过网关和静态主机地址。
我最初建地址池的时候,贪省事写成了start=192.168.20.1,结果192.168.20.1被动态分配给了某台实例,网关没人用了,网络一片混乱。后来改成start=192.168.20.20才恢复正常。其实网关和地址池不重叠,这是网络规划的基本纪律。
DNS服务器可以按实验环境选,如果一个网络既承担外网访问又承担内网解析,建议填一个你能确定的公共DNS地址,比如223.5.5.5,至少保证实例里面有域名解析能力。
2.3 内部网络、路由器和接口
有了外部网络还不够,实例一般要放在内部网络里,通过网络路由器连接到外部网络。创建流程并不复杂:
openstack router create router-test openstack router set router-test --external-gateway ext-net openstack network create inner-net openstack subnet create --network inner-net \ --subnet-range 10.0.2.0/24 \ --gateway 10.0.2.1 inner-subnet openstack router add subnet router-test inner-subnet为什么实例的网关是10.0.2.1而不是外部网络的192.168.20.1?因为底层有一台虚拟路由器在做地址转换,实例访问外网时,数据包会先到路由器,再由路由器把源地址换成外部网络的IP送出去。这个转换过程可以简单理解成小区门卫帮你转交快递:寄件人写的自己的名字,门卫会把发件人统一改成小区地址。
验证路由器是否正常工作,可以用这个命令看底层命名空间:
openstack router show router-test ip netns list如果路由器创建成功,ip netns list里会看到和路由器关联的命名空间。如果你看不到,说明路由代理没有正常工作,网络功能基本不可用。
3. 实例创建:从镜像到云主机的完整链路
3.1 上传镜像:qcow2好还是raw好
网络结构理清了,接下来才轮到创建实例。实例的第一步是镜像。先电环境里默认给的镜像格式一般是qcow2,这个选择不是没有原因的。
qcow2格式的镜像是稀疏文件,就是说它只占用实际数据大小的磁盘空间。比如一个镜像文件名义上是10GB,但里面装完系统可能只有1.8GB,放到本地磁盘就只占1.8GB。raw格式是完整裸数据,创建多大就占多大,虽然读取性能稍好一点,但在实验环境里会快速耗尽存储。
上传镜像的命令:
openstack image create --public \ --disk-format qcow2 \ --container-format bare \ --file /opt/images/centos7.qcow2 \ CentOS-7-Test--container-format bare表示镜像没有封装格式,是最常见的上传方式。上传完成后一定要看状态:
openstack image list只有显示active才是可用,如果显示saving或者error,多半是存储节点空间不够或镜像文件损坏,需要重新上传。
3.2 Flavor、安全组和创建实例的关键参数
镜像准备好后,需要选择实例规格。先电平台的管理页面里一般已经预置了几种Flavor,但命令行方式创建更可控。我习惯先自己建一个:
openstack flavor create --ram 4096 --disk 40 --vcpus 2 m2.medium这个是2核4G内存40G磁盘的规格,适合跑普通的业务镜像。选规格不是越大越好,要看你实验环境的物理资源。如果节点只有32G内存,你却一次性创建十台8G内存的实例,调度器会把节点资源耗尽,后面的实例一直处于创建中,这是很多新手搞不清的“资源超分”问题。
安全组也是新手最容易忽略的部分。平台默认的安全组会拒绝外部访问实例,如果不放行ICMP和SSH,实例就算有IP也ping不通、ssh不上:
openstack security group rule create --proto icmp default openstack security group rule create --proto tcp --dst-port 22 default这两条命令是给默认安全组放行ping和22端口。注意,这里只放行了从外面进来的访问,如果你的业务还要用80、443等端口,记得一并加进去。
正式创建实例的命令:
openstack server create --flavor m2.medium \ --image CentOS-7-Test \ --network inner-net \ --security-group default \ --wait test-vm加上--wait之后,命令会一直等待实例状态变为ACTIVE才返回。如果出现ERROR,多半是镜像格式不对、计算资源不足或网络创建有问题。创建完成后立刻用openstack server list查看状态。
3.3 实例ssh不通,先别乱重启
实例状态显示ACTIVE,并不代表你就能ssh上去。这个判断过程我建议按顺序排查,不要上来就重启实例。
第一步,先ping一下实例的浮动IP或内部网关,确认二层和三层联通性。ping不通的情况下,要区分是外网访问不到还是实例内部网络问题。
第二步,查看实例的控制台输出日志:
openstack console log show test-vm如果日志里能看到网卡启动了但没有获取到IP,基本可以肯定是DHCP环节出了问题,重点检查DHCP代理和子网地址池。
第三步,确认你有没有给实例绑定浮动IP。内部网络的IP是无法直接从外部访问的,你需要先创建一个浮动IP并绑定到实例:
openstack floating ip create ext-net openstack server add floating ip test-vm <浮动IP>浮动IP本质上就是在路由器上做一个端口转发,把外部IP映射到内部实例IP。如果你发现外网可以ping通外部网关地址,但怎么都联系不上实例,多半就是这一步漏了。
4. 存储:卷操作是慢功夫
4.1 卷创建和后端选择
实例有临时磁盘,但临时磁盘的生命周期跟实例绑定,实例删除数据就没了。想要持久化,就得用块存储卷。先电环境的默认后端一般是LVM,也就是在存储节点上创建一块逻辑卷提供给实例使用。你也可以在平台上看到其他后端选项,比如NFS,适合共享文件场景,但性能通常不如本地LVM。
创建卷的命令:
openstack volume type list openstack volume create --size 10 --type 普通卷>openstack server add volume test-vm>lsblk fdisk /dev/vdbfdisk里依次执行n创建分区、w保存。然后格式化并挂载:
mkfs.xfs /dev/vdb1 mkdir -p /mnt/data mount /dev/vdb1 /mnt/data关于是否分区,我的经验是不要偷懒直接整盘格式化。分区之后,后续扩容和快照处理都更灵活,而且文件系统大小和分区表对齐也更清晰。
这里有个新手特别容易翻车的点:写/etc/fstab永久挂载时抄错UUID。实例重启时会因为找不到挂载设备,直接卡在启动流程或者进入紧急模式。正确做法是先用blkid拿到分区的UUID,再把挂载表写好:
blkid /dev/vdb1UUID=xxxx-xxxx-xxxx /mnt/data xfs defaults 0 0写完之后,建议先执行mount -a测试一遍,确认无误再重启。
4.3 扩容与快照
卷扩容是块存储的高频操作。比如原来10GB的卷不够用了,想扩到20GB:
openstack volume set --size 20>growpart /dev/vdb 1 xfs_growfs /mnt/data如果是ext4文件系统,用resize2fs /dev/vdb1。注意,有些环境不允许在线扩容,强行扩会报错。稳妥的做法是先把卷从实例上卸载,扩容完成后再重新挂载,或者干脆先打个快照再操作。
快照也是存储里必练的技能。卷快照命令:
openstack volume snapshot create --volume>openstack server image create --name test-vm-bak --wait test-vm这里有一条个人经验:对运行中的实例直接做快照,得到的镜像可能不是完全一致的,内存里的数据并没有被完整保存。所以重要业务要打快照时,我习惯先停掉实例或者至少把服务停一会儿再做,虽然麻烦,但恢复时真正能用的概率高很多。如果条件不允许停机,也要保证业务数据已经落盘,不要只依赖实例快照。
5. 排障实录:我记下来的问题,你大概率也会碰上
5.1 问题速查表
这一个星期里,我把实际遇到的问题整理成一张表。遇到故障时,先对照一下现象,能省掉很多盲目尝试的时间。
| 现象 | 可能原因 | 验证手段 | 解决办法 |
|---|---|---|---|
| 管理页面打不开或空白 | Web服务或认证服务异常 | systemctl status httpd;检查认证服务日志 | 重启对应服务,查看认证服务日志定位 |
| 实例一直处于创建中 | 计算资源不足、调度失败、磁盘空间不够 | openstack compute service list;查看计算节点日志 | 清理节点磁盘,调整Flavor规格,修复计算服务状态 |
| 实例卡在spawning | 镜像数据未完全复制到计算节点 | 查看计算服务日志 | 等待镜像转换完成,或重新上传镜像 |
| 实例创建成功但ping不通 | 安全组未放行ICMP、浮动IP未绑定、网络类型不匹配 | openstack security group rule list;openstack floating ip list | 放行ICMP端口,绑定浮动IP,检查网络类型 |
| 能ping通但ssh不上 | 安全组未放行22端口,镜像内sshd未启动 | 查看控制台日志 | 放行TCP 22端口,或重置root密码 |
| 外部网络不通 | 路由器接口未配置、物理网络名不匹配 | openstack router show;查看网络日志 | 重新配置路由器接口,修改物理网络名 |
| DHCP获取不到地址 | DHCP代理未运行、地址池耗尽 | openstack network agent list;查看DHCP日志 | 启动代理,扩展地址池 |
| 卷创建一直处于creating | cinder卷服务异常、后端空间不足 | openstack volume service list;查看存储日志 | 重启卷服务,释放后端磁盘空间 |
| 卷扩容不生效 | 文件系统未扩展 | lsblk;df -h | 在实例内执行扩容命令 |
| 服务状态显示down | 节点宕机、服务未启动 | openstack compute service list | 登录对应节点,重启对应服务 |
5.2 按顺序排错,不要一上来就重启
排查问题最好遵循一个固定套路:先看服务状态,再看日志,最后才碰配置和重启。
第一步,查看关键服务状态:
systemctl status httpd mariadbrabbitmq-server memcached按实际情况替换服务名,比如在存储节点上要看存储卷服务的状态,在网络节点上看网络代理服务状态。
第二步,按照组件查日志。平台各服务的日志路径一般是固定位置,我列一下常用的:
| 组件 | 日志路径 |
|---|---|
| 认证服务 | /var/log/keystone/keystone.log |
| 计算服务 | /var/log/nova/nova-compute.log |
| 网络服务 | /var/log/neutron/network-agent.log |
| 存储服务 | /var/log/cinder/cinder-volume.log |
| 镜像服务 | /var/log/glance/api.log |
用tail -100查看最新的错误信息:
tail -100 /var/log/nova/nova-compute.log日志里通常直接写着失败的完整堆栈和触发条件。我见过很多人一遇到问题就先重启实例,重启后日志被覆盖,现场被破坏,问题也没解决,反而变成“重启了好多次但还是报错”的玄学状态。先看日志再动手,是运维最基本的原则。
第三步,想一下改动过什么。配置变更、清理文件、添加资源,这些操作都会有痕迹。回滚之前的改动,往往比重新安装配置快得多。
5.3 巡检脚本化,十分钟搞定日常检查
平台用久了,我建议把日常巡检脚本化。不需要复杂的监控,两三条命令就够了:
openstack token issue openstack compute service list openstack network agent list openstack volume service list把这几条命令写进脚本里,每次实验前跑一遍,输出文件保留日期后缀。只要看到所有列表里的服务状态都是UP,基本可以放心往下走。如果某列为down或XXX,再按前面5.2的顺序定位。
我自己的习惯是把巡检输出重定向到一个文件里:
openstack compute service list > /tmp/inspect-$(date +%Y%m%d).txt这样出问题的时候,能直接对比“昨天正常时”和“现在异常时”的输出差异,快速锁定是哪台节点在什么时间点出了状况。
我在这次连续几天的操作里,最大的体会是先电平台的上手门槛不算高,但如果你只依赖图形界面的提示,很多问题会变成“玄学”。反而后来所有操作我都保留命令行记录,等再次遇到问题时,不用回忆就能直接翻记录定位。最后再分享一个小技巧:给所有网络、路由器、卷这些资源的名字加上日期前缀,比如netext-0716、vol-data-0718。测试环境里这类资源特别多,如果全部叫test,过几天你根本分不清谁是谁,到时候排查问题就会多花好几倍时间。