OpenStack运维案例

开放镜像权限

理论基础

在 OpenStack Glance 中,镜像可见性分为:

  • Public(公有):所有租户可见。
  • Private(私有):仅镜像所属项目可见。
  • Shared(共享):镜像所有者可将镜像共享给指定项目(Image Member 机制)。

多租户隔离是云的默认安全边界。共享私有镜像的正确做法是由管理员(或镜像所有者)通过”添加成员”把目标项目加入镜像成员列表,从而在保持隔离的同时精确授权。

案例描述

需求:管理员上传的镜像仅共享给 A 租户(projectA),B 租户(projectB)不可见。

策略:镜像保持私有(Private),再通过 openstack image add project 将镜像成员授权给 projectA。

案例实施

  1. 认证环境

    # 加载管理员凭据,后续 openstack/keystone/glance 命令无需重复传参
    [root@controller ~]# source /etc/keystone/admin-openrc.sh
  2. 创建项目与用户

    # 创建项目 projectB(--domain 指定域名)
    [root@controller ~]# openstack project create --domain xiandian projectB
    
    # 创建用户 userB(--project 指定默认项目,--password 设置密码)
    [root@controller ~]# openstack user create --domain xiandian --project projectB --password 000000 userB
    
    # 为 userB 分配角色(--project 指定项目,--user 指定用户)
    [root@controller ~]# openstack role add --project projectB --user userB user

    提示:按相同步骤创建 projectA 和 userA。

  3. 管理员上传镜像并保持私有

    在 Horizon 管理员菜单上传 cirros 镜像,保持”私有”可见性。

  4. 将镜像共享给 projectA

    # 将私有镜像 cirros 共享给项目 projectA(image 镜像名,project 项目名)
    [root@controller ~]# openstack image add project cirros projectA
  5. 验证可见性

    • 使用 userA 登录(隶属 projectA):应能看到 cirros 镜像。
    • 使用 userB 登录(隶属 projectB):不应看到该镜像。

作业1:使用 userA 登录 Horizon,截图镜像列表。

负载均衡服务配置与测试

理论基础

Octavia(LBaaS)核心组件:

  • Load Balancer:承载 VIP 的负载均衡实例。
  • Listener:监听协议/端口,接收流量。
  • Pool:后端服务器组。
  • Member:资源池中的具体后端节点。
  • Health Monitor:健康检查,剔除不健康节点。

常见调度算法:ROUND_ROBIN(轮询)、LEAST_CONNECTIONS(最少连接)、SOURCE_IP(源地址哈希)。本例使用 ROUND_ROBIN。

案例实施

Heat 模板快速建网与主机

  1. 创建 Heat 模板

    新建模板文件 demo.yaml,将以下内容写入:

    heat_template_version: 2015-04-30
    description: 创建负载均衡实验环境
    
    resources:
        # 定义私有网络
        my_network:
            type: OS::Neutron::Net
            properties:
                name: private-iso-net
    
        # 定义子网
        my_subnet:
            type: OS::Neutron::Subnet
            properties:
                name: private-iso-net-subnet
                network_id: { get_resource: my_network }
                cidr: 192.168.200.0/24
                gateway_ip: 192.168.200.1
                dns_nameservers: ["114.114.114.114", "8.8.8.8"]
                ip_version: 4
                enable_dhcp: true
    
        # 定义云主机实例 web01
        # 注意:实际需要增加 my_instance2 和 my_instance3,一共创建三个实例
        my_instance1:
            type: OS::Nova::Server
            depends_on: my_subnet
            properties:
                name: web01
                image: cirros
                flavor: m1.tiny
                networks:
                    - network: { get_resource: my_network }
  2. 创建堆栈

    根据模板创建堆栈并观察资源状态:

    # 使用 demo.yaml 模板创建名为 test 的堆栈(-t 指定模板文件)
    [root@controller ~]# openstack stack create -t demo.yaml test
    +---------------------+--------------------------------------+
    | Field               | Value                                |
    +---------------------+--------------------------------------+
    | id                  | 1013dc6d-c87c-41d5-8203-36bd11ea1fb2 |
    | stack_name          | test                                 |
    | description         | 创建负载均衡实验环境                 |
    | creation_time       | 2025-12-16T10:06:08                  |
    | updated_time        | None                                 |
    | stack_status        | CREATE_IN_PROGRESS                   |
    | stack_status_reason |                                      |
    +---------------------+--------------------------------------+
    
    # 资源创建完成可能需要一两分钟
    # 查看堆栈 test 的资源列表
    [root@controller ~]# openstack stack resource list test 
    +---------------+--------------------------------------+---------------------+-----------------+---------------------+
    | resource_name | physical_resource_id                 | resource_type       | resource_status | updated_time        |
    +---------------+--------------------------------------+---------------------+-----------------+---------------------+
    | my_instance1  | 6fd71cda-b607-4159-b7bc-8a312d53bd07 | OS::Nova::Server    | CREATE_COMPLETE | 2025-12-16T10:06:08 |
    | my_instance2  | 1801f35c-e4d9-43ea-a4ff-437176b5922f | OS::Nova::Server    | CREATE_COMPLETE | 2025-12-16T10:06:08 |
    | my_subnet     | 6e5bd340-4cfc-4e78-858c-d3021889f6cf | OS::Neutron::Subnet | CREATE_COMPLETE | 2025-12-16T10:06:08 |
    | my_instance3  | db903ede-5965-43fd-bf59-71ab263488b5 | OS::Nova::Server    | CREATE_COMPLETE | 2025-12-16T10:06:08 |
    | my_network    | 7f936ef6-a7b5-46b7-90a6-514ecf40699d | OS::Neutron::Net    | CREATE_COMPLETE | 2025-12-16T10:06:08 |
    +---------------+--------------------------------------+---------------------+-----------------+---------------------+

配置后端 Web 服务

# web01:返回标识 01 的响应
# 创建 HTTP 响应内容文件(-e 启用转义字符解释)
$  echo -e "HTTP/1.0 200 OK\n\nThis is Web Server 01" > /tmp/msg
# 启动监听 80 端口的循环(nc 监听端口,& 后台运行)
$  while true; do cat /tmp/msg | nc -l -p 80; done &

# web02:返回标识 02 的响应
# 创建 HTTP 响应内容文件
$  echo -e "HTTP/1.0 200 OK\n\nThis is Web Server 02" > /tmp/msg
# 启动监听 80 端口的循环
$  while true; do cat /tmp/msg | nc -l -p 80; done &

使用 nc 快速模拟 HTTP 服务,便于观察流量分配。

构建负载均衡器

  1. 创建负载均衡器

    在 Horizon 界面指定子网、协议、负载均衡算法(ROUND_ROBIN):

    1765854284961.png
  2. 添加后端成员

    依次添加 web01web02 两个成员到资源池:

    1765854452868.png
  3. 配置 VIP

    添加 VIP,查看 VIP 地址:

    1765854704457.png 1765854746072.png 1765854786821.png

验证与高可用

  1. 测试轮询负载

    打开 client 控制台,请求负载均衡器的 VIP:

    # 访问 VIP,观察返回结果(应轮询返回两个 Web 服务器的响应)
    $ curl 192.168.200.7
    This is Web Server 01
    $ curl 192.168.200.7
    This is Web Server 02
    $ curl 192.168.200.7
    This is Web Server 01
    $ curl 192.168.200.7
    This is Web Server 02

    作业2:截图负载均衡器轮询响应过程。

  2. 配置健康检查

    在 Horizon 界面配置健康检查(5 秒探测间隔,失败 3 次判定 DOWN):

    1765855061014.png
  3. 模拟故障测试

    在 web01 上停止 Web 服务:

    # 停止后台运行的 nc 进程(%1 表示第一个后台作业)
    $  kill %1
  4. 验证高可用

    再次访问 VIP,流量应全部命中 web02:

    # 访问 VIP,观察返回结果(应全部为 Web Server 02)
    $ curl 192.168.200.7
    This is Web Server 02
    $ curl 192.168.200.7
    This is Web Server 02
    $ curl 192.168.200.7
    This is Web Server 02
    $ curl 192.168.200.7
    This is Web Server 02

    结论:健康检查生效,故障节点被自动剔除,业务持续可用。

配置 NFS 作为 Glance 后端存储

理论基础

Glance 通过”存储后端”保存镜像文件,常见后端:本地文件、Cinder、Swift、Ceph RBD、NFS 等。

在多控制节点场景下,本地文件存储会导致镜像分散;使用 NFS 可让所有 Glance 节点共享同一目录,保证镜像一致性并便于扩容。

案例实施

  1. 配置 NFS 服务端

    编辑 /etc/exports,添加以下内容:

    # 共享目录 允许访问的网段(权限参数)
    # rw: 读写权限
    # no_root_squash: 客户端 root 用户保留 root 权限
    # no_all_squash: 不将所有用户映射为匿名用户
    # sync: 同步写入磁盘
    # anonuid/anongid: 指定匿名用户的 UID/GID
    /mnt/test 192.168.100.0/24(rw,no_root_squash,no_all_squash,sync,anonuid=501,anongid=501)

    重启服务并验证:

    # 重启 rpcbind 和 nfs 服务使配置生效
    [root@controller ~]# systemctl restart rpcbind
    [root@controller ~]# systemctl restart nfs
    # 查看 NFS 共享列表(-e 显示导出列表)
    [root@controller ~]# showmount -e 192.168.100.10
  2. Glance 节点挂载 NFS

    # 确认客户端工具已安装
    [root@controller ~]# rpm -qa | grep nfs-utils
    
    # 挂载 NFS 到 Glance 镜像目录(-t 指定文件系统类型)
    [root@controller ~]# mount -t nfs 192.168.100.10:/mnt/test /var/lib/glance/images/
    # 查看挂载情况
    [root@controller ~]# df -h | grep glance
  3. 权限修正

    [root@controller ~]# cd /var/lib/glance
    # 修改 images 目录的所有者为 glance 用户和组
    [root@controller glance]# chown glance:glance images
    # 查看目录权限
    [root@controller glance]# ll -d images
  4. 上传镜像并验证

    在 Horizon 或 CLI 上传镜像后,检查 NFS 目录:

    # 查看 NFS 共享目录下的文件
    [root@controller glance]# ll /mnt/test

    作业3:上传镜像后,截图 NFS 目录文件列表。

  5. Windows 访问(可选)

    启用 Windows “NFS 服务”后,可在资源管理器访问:\\192.168.100.10\mnt\test

    1702886652481.png