01 · OpenStack的认证管理 Keystone

01 · 认证管理 Keystone

本篇导读:Keystone 是 OpenStack 的「身份证中心 + 服务目录」。任何用户或服务想使用 OpenStack,第一步都要先找 Keystone 报到。本篇从「它是谁、管什么」切入,逐个讲透九大核心概念,再带你走一遍 Dashboard 与 CLI 的完整操作,最后用两张时序图把「登录」和「创建虚拟机」背后发生的认证/鉴权链路钉死。学完你应当能独立创建域、用户、组、项目、角色、配额,并说清 Token 在各服务之间是怎么被反复校验的。

学习目标:

  1. 说清 Keystone 在 OpenStack 中的定位与三件核心工作。
  2. 准确复述九大概念(Domain / User / Group / Project / Role / Service / Endpoint / Token / Credential)的一句话定义与唯一性范围。
  3. 区分 Authentication(认证)与 Authorization(鉴权),理解 policy 基于 Role 的访问控制。
  4. 能用 Dashboard 和 CLI 两种方式完成:创建角色、用户、用户组、项目、改配额、禁用/删除用户。
  5. 画得出「点击登入」和「创建一台 VM」时 Token 在 Keystone / Nova / Glance / Neutron 之间的流转时序。
  6. 知道 Keystone 日志、配置文件位置,会开 debug。

文章目录

  • [01 · 认证管理 Keystone](#01 · 认证管理 Keystone)
    • [一、Keystone 的定位与作用](#一、Keystone 的定位与作用)
    • 二、九大核心概念(先背一句话定义)
      • [1. Domain(域)](#1. Domain(域))
      • [2. User(用户)](#2. User(用户))
      • [3. Group(用户组)](#3. Group(用户组))
      • [4. Project(项目 / 租户)](#4. Project(项目 / 租户))
      • [5. Role(角色)](#5. Role(角色))
      • [6. Service(服务)](#6. Service(服务))
      • [7. Endpoint(端点)](#7. Endpoint(端点))
      • [8. Token(令牌)](#8. Token(令牌))
      • [9. Credential(凭证)](#9. Credential(凭证))
      • 九大概念关系图
    • [三、Authentication 与 Authorization:安全的两件事](#三、Authentication 与 Authorization:安全的两件事)
      • [鉴权是怎么落地的:policy 文件](#鉴权是怎么落地的:policy 文件)
    • 四、架构与组件(补充)
    • 五、关键配置与环境变量
      • [5.1 命令行前置:source 环境变量](#5.1 命令行前置:source 环境变量)
      • [5.2 自定义用户的 openrc 环境变量文件(实验手册)](#5.2 自定义用户的 openrc 环境变量文件(实验手册))
      • [5.3 多域登录开关(Dashboard)](#5.3 多域登录开关(Dashboard))
      • [5.4 打开 debug 日志](#5.4 打开 debug 日志)
    • 六、Dashboard(Horizon)操作
      • [6.1 创建角色](#6.1 创建角色)
      • [6.2 创建用户](#6.2 创建用户)
      • [6.3 创建用户组并加成员](#6.3 创建用户组并加成员)
      • [6.4 不同角色登录后的界面差异(重点现象)](#6.4 不同角色登录后的界面差异(重点现象))
      • [6.5 禁用与删除用户(关键区别)](#6.5 禁用与删除用户(关键区别))
      • [6.6 创建项目并改配额](#6.6 创建项目并改配额)
    • [七、CLI 操作(命令 + 输出解读)](#七、CLI 操作(命令 + 输出解读))
      • [7.1 Domain 域](#7.1 Domain 域)
      • [7.2 User 用户](#7.2 User 用户)
      • [7.3 Group 用户组](#7.3 Group 用户组)
      • [7.4 Role 角色与授权](#7.4 Role 角色与授权)
      • [7.5 Project 项目与配额](#7.5 Project 项目与配额)
      • [7.6 Service 与 Endpoint](#7.6 Service 与 Endpoint)
    • 八、两个必背流程(时序图)
      • [8.1 点击「登入」背后发生了什么](#8.1 点击「登入」背后发生了什么)
      • [8.2 以「创建一台 VM」看整个 OpenStack 的认证链路](#8.2 以「创建一台 VM」看整个 OpenStack 的认证链路)
    • 九、易混点对比表
    • 十、补充内容(进阶拓展)
      • [10.1 【补充】Token 的种类与演进](#10.1 【补充】Token 的种类与演进)
      • [10.2 【补充】RBAC 与三种 scope、Secure RBAC](#10.2 【补充】RBAC 与三种 scope、Secure RBAC)
      • [10.3 【补充】联邦身份 Federation 与外部身份源](#10.3 【补充】联邦身份 Federation 与外部身份源)
      • [10.4 【补充】域 / 项目层级树与多租户隔离](#10.4 【补充】域 / 项目层级树与多租户隔离)
    • 十一、本篇小结
    • 十二、重点速记
    • 十三、自测题(附参考答案)
      • [A. 名词解释](#A. 名词解释)
      • [B. 选择题](#B. 选择题)
      • [C. 简答题](#C. 简答题)

一、Keystone 的定位与作用

Keystone(OpenStack Identity,身份服务)是 OpenStack 的基础支持服务,所有其他服务(Nova、Glance、Cinder、Neutron、Heat......)都要围着它转。它主要做三件事:

  1. 管理用户及其权限(谁能登录、能登到哪个项目、能干什么)。
  2. 维护 OpenStack 各 Service 的 Endpoint 目录(告诉别人「Nova 的 API 地址是多少」)。
  3. Authentication(认证)和 Authorization(鉴权):验证你是谁,再决定你能干什么。

一句话记忆:Keystone = 门卫 + 通讯录。门卫查身份证发通行证(Token),通讯录写着每家服务的门牌号(Endpoint)。

实验环境基线(贯穿全篇,务必记牢):

项目 值
操作系统 / 版本 CentOS-Stream-8 + OpenStack Victoria
controller 节点 192.168.108.10
compute 节点 192.168.108.11
Region RegionOne
默认域 Default(另有一个系统自带的 heat 域)
管理员账号 admin,密码统一 huawei
命令行前置动作 source keystonerc_admin(导入 admin 环境变量)
OS_AUTH_URL http://192.168.108.10:5000/v3
OS_IDENTITY_API_VERSION 3
日志目录 /var/log/keystone/keystone.log
配置目录 /etc/keystone/(主配置 keystone.conf)

二、九大核心概念(先背一句话定义)

学法提示:每个概念先背「一句话标准定义」(加粗句),再记唯一性范围和易错点。

1. Domain(域)

一个 Domain 是一组 User、Group 或 Project 的容器,是一个虚拟的管理边界。

  • 一个域可以对应一个大机构、一个数据中心,必须全局唯一。
  • 终端用户可以在自己的 Domain 里创建多个 Project、User、Group、Role,具备对多个 Project 统一管理的能力。
  • 系统默认自带 Default 域和一个 heat 域;不特别指定域时,对象都落在 default 域下。

2. User(用户)

User 是可以通过 Keystone 访问 OpenStack 服务的个人、系统或某个服务。

  • User 不要求全局唯一,只需在域内唯一。
  • Keystone 用 Credential(如密码)验证 User 请求合法性;通过验证后下发一个 Token,作为后续访问的「通行证」。
  • 除了真正的人 admin,OpenStack 还为 nova、cinder、glance、neutron、heat、placement、swift、ceilometer、aodh、gnocchi 等服务创建了对应的服务 User(服务间互相调用也靠身份认证)。admin 可以管理这些服务 User。

3. Group(用户组)

Group 是一组 User 的容器,可以直接给 Group 分配角色。

  • 给 Group 赋角色后,组内所有 User 自动拥有该角色权限------目的是批量管理一组用户的权限,而不是一个个单独授权。
  • 把用户从组里删掉 ≠ 删除用户本体,只是退出该组。

4. Project(项目 / 租户)

Project 是各个服务中一组可以访问的资源集合(计算、存储、网络),用于把资源分组和隔离。

  • 资源的所有权属于 Project,而不是 User。
  • Project 不必全局唯一,只需在某个域下唯一(对比:Domain、Role 才要求全局唯一)。
  • 创建 VM、创建卷时都必须指定 Project;每个 User(含 admin)必须挂在某个 Project 里、并在该项目下被赋予角色,才能访问其资源。一个 User 可以属于多个 Project。
  • 术语:界面和文档中 Tenant / Project / Account 通用,长期倾向叫 Project;公有云里叫「租户」。公有云场景 Project 对应一个客户,私有云场景对应一个部门或项目组。
  • admin 相当于 root,具有最高权限。

5. Role(角色)

Role 是一组预先定义的用户权限和特权,用于执行一组特定操作;角色不同,被赋予的权限不同。

  • 只有知道 User 被赋予了什么 Role,才能判断他是否有权访问某资源。
  • Role 可以被赋予在域 上(对域内所有项目都生效),也可以赋予在特定项目上(只对该项目生效)。
  • Role 必须全局唯一 ;Role 可以继承:在项目树中,拥有父项目的权限即自动拥有对子项目的权限。
  • 实验环境常见角色:admin、_member_(即 member,普通用户),此外还有 reader、ResellerAdmin、SwiftOperator、heat_stack_owner、heat_stack_user 等。

6. Service(服务)

Service 是一种 OpenStack 服务,它会对外暴露一个或多个 Endpoint,用户通过这些端点访问资源并执行操作。

典型 Service:Compute(Nova)、Block Storage(Cinder)、Object Storage(Swift)、Image(Glance)、Networking(Neutron)、Identity(Keystone 自己)、Orchestration(Heat)、Placement 等。

7. Endpoint(端点)

Endpoint 是一个可以用来访问某个具体服务的网络地址,通常就是一个 URL。

  • Service 通过 Endpoint 暴露自己的 API;Keystone 负责登记和维护每个 Service 的 Endpoint。
  • 每个服务历史上有三类入口:admin / internal / public(详见后文「补充」)。

8. Token(令牌)

Token 是允许访问特定资源的凭证,一串由数字和字母组成的字符串。

  • User 成功 Authentication 后,Keystone 生成并签发 Token。
  • Token 用作访问 Service 的 Credential;Service 收到请求后会拿着 Token 去 Keystone 校验有效性。
  • Token 中包含 User 的 Role 信息(这是后面鉴权能成立的关键)。
  • Token 默认有效期 24 小时(实际部署常用 1 小时,见「补充」)。

9. Credential(凭证)

Credential 是确认用户身份的数据,用来证明「我是谁」。

常见形式:① 用户名/密码;② Token;③ API Key;④ 其他高级方式(如证书、联邦身份)。

九大概念关系图

#mermaid-svg-U2Sbst6tilgJKdgn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-U2Sbst6tilgJKdgn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U2Sbst6tilgJKdgn .error-icon{fill:#552222;}#mermaid-svg-U2Sbst6tilgJKdgn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U2Sbst6tilgJKdgn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U2Sbst6tilgJKdgn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U2Sbst6tilgJKdgn .marker.cross{stroke:#333333;}#mermaid-svg-U2Sbst6tilgJKdgn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U2Sbst6tilgJKdgn p{margin:0;}#mermaid-svg-U2Sbst6tilgJKdgn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-U2Sbst6tilgJKdgn .cluster-label text{fill:#333;}#mermaid-svg-U2Sbst6tilgJKdgn .cluster-label span{color:#333;}#mermaid-svg-U2Sbst6tilgJKdgn .cluster-label span p{background-color:transparent;}#mermaid-svg-U2Sbst6tilgJKdgn .label text,#mermaid-svg-U2Sbst6tilgJKdgn span{fill:#333;color:#333;}#mermaid-svg-U2Sbst6tilgJKdgn .node rect,#mermaid-svg-U2Sbst6tilgJKdgn .node circle,#mermaid-svg-U2Sbst6tilgJKdgn .node ellipse,#mermaid-svg-U2Sbst6tilgJKdgn .node polygon,#mermaid-svg-U2Sbst6tilgJKdgn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U2Sbst6tilgJKdgn .rough-node .label text,#mermaid-svg-U2Sbst6tilgJKdgn .node .label text,#mermaid-svg-U2Sbst6tilgJKdgn .image-shape .label,#mermaid-svg-U2Sbst6tilgJKdgn .icon-shape .label{text-anchor:middle;}#mermaid-svg-U2Sbst6tilgJKdgn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-U2Sbst6tilgJKdgn .rough-node .label,#mermaid-svg-U2Sbst6tilgJKdgn .node .label,#mermaid-svg-U2Sbst6tilgJKdgn .image-shape .label,#mermaid-svg-U2Sbst6tilgJKdgn .icon-shape .label{text-align:center;}#mermaid-svg-U2Sbst6tilgJKdgn .node.clickable{cursor:pointer;}#mermaid-svg-U2Sbst6tilgJKdgn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-U2Sbst6tilgJKdgn .arrowheadPath{fill:#333333;}#mermaid-svg-U2Sbst6tilgJKdgn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-U2Sbst6tilgJKdgn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-U2Sbst6tilgJKdgn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U2Sbst6tilgJKdgn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-U2Sbst6tilgJKdgn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U2Sbst6tilgJKdgn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-U2Sbst6tilgJKdgn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-U2Sbst6tilgJKdgn .cluster text{fill:#333;}#mermaid-svg-U2Sbst6tilgJKdgn .cluster span{color:#333;}#mermaid-svg-U2Sbst6tilgJKdgn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-U2Sbst6tilgJKdgn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-U2Sbst6tilgJKdgn rect.text{fill:none;stroke-width:0;}#mermaid-svg-U2Sbst6tilgJKdgn .icon-shape,#mermaid-svg-U2Sbst6tilgJKdgn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U2Sbst6tilgJKdgn .icon-shape p,#mermaid-svg-U2Sbst6tilgJKdgn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-U2Sbst6tilgJKdgn .icon-shape .label rect,#mermaid-svg-U2Sbst6tilgJKdgn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U2Sbst6tilgJKdgn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-U2Sbst6tilgJKdgn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-U2Sbst6tilgJKdgn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 身份与资源(都在 Domain 内)
包含多个
批量授权
被授权到
提交验证
登录后获得
携带访问
可授予 User / Group / Project
Domain 域(全局唯一)
Group 用户组
User 用户(域内唯一)
Project 项目(域内唯一)
Role 角色(全局唯一,可继承)
Credential 凭证(密码/Token/API Key)
Token 令牌(含 Role)
Service 服务
Endpoint 端点(URL)


三、Authentication 与 Authorization:安全的两件事

OpenStack 的安全由两部分组成:

  • Authentication(认证)=「你是谁?」------提交用户名密码等 Credential,Keystone 核对通过后发 Token。
  • Authorization(鉴权)=「你能干什么?」 ------Keystone 借助 Role 实现:Keystone 定义 Role、给 User/Group 分配 Role;真正「每个 Role 能干什么」由各个 Service 自己决定。

鉴权是怎么落地的:policy 文件

  • 每个 Service 通过各自的 policy 文件 对 Role 做访问控制,规则以 JSON 格式写在 policy.json。
  • 策略文件路径规则:/etc/SERVICE_NAME/policy.json,例如 /etc/keystone/policy.json、/etc/nova/policy.json、/etc/glance/policy.json。
  • packstack 安装时,Dashboard 相关策略放在 /etc/openstack-dashboard/ 下,形如 cinder_policy.json、glance_policy.json、keystone_policy.json、neutron_policy.json、nova_policy.json。
  • OpenStack 默认配置只区分 admin 和非 admin 两类角色;若要给自定义角色精细授权,需要改 policy(一般不建议改)。

#mermaid-svg-MTCLwS4TTdYnYet3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MTCLwS4TTdYnYet3 .error-icon{fill:#552222;}#mermaid-svg-MTCLwS4TTdYnYet3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MTCLwS4TTdYnYet3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MTCLwS4TTdYnYet3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MTCLwS4TTdYnYet3 .marker.cross{stroke:#333333;}#mermaid-svg-MTCLwS4TTdYnYet3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MTCLwS4TTdYnYet3 p{margin:0;}#mermaid-svg-MTCLwS4TTdYnYet3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster-label text{fill:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster-label span{color:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster-label span p{background-color:transparent;}#mermaid-svg-MTCLwS4TTdYnYet3 .label text,#mermaid-svg-MTCLwS4TTdYnYet3 span{fill:#333;color:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 .node rect,#mermaid-svg-MTCLwS4TTdYnYet3 .node circle,#mermaid-svg-MTCLwS4TTdYnYet3 .node ellipse,#mermaid-svg-MTCLwS4TTdYnYet3 .node polygon,#mermaid-svg-MTCLwS4TTdYnYet3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MTCLwS4TTdYnYet3 .rough-node .label text,#mermaid-svg-MTCLwS4TTdYnYet3 .node .label text,#mermaid-svg-MTCLwS4TTdYnYet3 .image-shape .label,#mermaid-svg-MTCLwS4TTdYnYet3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-MTCLwS4TTdYnYet3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MTCLwS4TTdYnYet3 .rough-node .label,#mermaid-svg-MTCLwS4TTdYnYet3 .node .label,#mermaid-svg-MTCLwS4TTdYnYet3 .image-shape .label,#mermaid-svg-MTCLwS4TTdYnYet3 .icon-shape .label{text-align:center;}#mermaid-svg-MTCLwS4TTdYnYet3 .node.clickable{cursor:pointer;}#mermaid-svg-MTCLwS4TTdYnYet3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MTCLwS4TTdYnYet3 .arrowheadPath{fill:#333333;}#mermaid-svg-MTCLwS4TTdYnYet3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MTCLwS4TTdYnYet3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MTCLwS4TTdYnYet3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MTCLwS4TTdYnYet3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MTCLwS4TTdYnYet3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MTCLwS4TTdYnYet3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster text{fill:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 .cluster span{color:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MTCLwS4TTdYnYet3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MTCLwS4TTdYnYet3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-MTCLwS4TTdYnYet3 .icon-shape,#mermaid-svg-MTCLwS4TTdYnYet3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MTCLwS4TTdYnYet3 .icon-shape p,#mermaid-svg-MTCLwS4TTdYnYet3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MTCLwS4TTdYnYet3 .icon-shape .label rect,#mermaid-svg-MTCLwS4TTdYnYet3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MTCLwS4TTdYnYet3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MTCLwS4TTdYnYet3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MTCLwS4TTdYnYet3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有效,取出 Role
允许
拒绝
用户请求(携带 Token)
目标 Service(如 Glance)
去 Keystone 校验 Token 是否有效
读自己的 policy.json / policy.yaml
当前 Role 允许该操作?
执行并返回资源
返回 403 禁止访问


四、架构与组件(补充)

标注「补充」的内容理解本模块必需。

【补充】Keystone 部署形态: Keystone 本身不是一个长驻的独立守护进程,而是跑在 HTTPD(Apache)+ WSGI 上的一组应用。改完 Dashboard 或 Keystone 配置后,常需 systemctl restart httpd 生效。

【补充】Keystone 内部子系统(fronting services):

子系统 职责
identity 校验 User/Credential(用户名密码、域、用户)
assignment 管理 User/Group 与 Project/Domain 之间的角色绑定
resource 管理 Domain、Project 层级(parent/child)
token 签发与校验 Token(当前默认 Fernet)
catalog 维护 Service 与 Endpoint 目录
policy 提供策略规则

【补充】多站点 Region: 一个 OpenStack 部署可以有多个 Region(本实验是 RegionOne)。同一套 Keystone 可以登记分布在不同 Region 的服务,客户端按 Region 选择就近访问。

【补充】Endpoint 三类接口: 历史上每个服务登记三个 endpoint------

  • adminURL:供管理员操作,通常对内网开放;
  • internalURL:集群内部服务之间互访;
  • publicURL:终端用户从外部访问。
    新版 OpenStack 已逐步弱化三入口区分,日常 openstack catalog list 看到的一般是统一地址。

#mermaid-svg-1X80o4PFUCoSRSA8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1X80o4PFUCoSRSA8 .error-icon{fill:#552222;}#mermaid-svg-1X80o4PFUCoSRSA8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1X80o4PFUCoSRSA8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1X80o4PFUCoSRSA8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1X80o4PFUCoSRSA8 .marker.cross{stroke:#333333;}#mermaid-svg-1X80o4PFUCoSRSA8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1X80o4PFUCoSRSA8 p{margin:0;}#mermaid-svg-1X80o4PFUCoSRSA8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster-label text{fill:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster-label span{color:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster-label span p{background-color:transparent;}#mermaid-svg-1X80o4PFUCoSRSA8 .label text,#mermaid-svg-1X80o4PFUCoSRSA8 span{fill:#333;color:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 .node rect,#mermaid-svg-1X80o4PFUCoSRSA8 .node circle,#mermaid-svg-1X80o4PFUCoSRSA8 .node ellipse,#mermaid-svg-1X80o4PFUCoSRSA8 .node polygon,#mermaid-svg-1X80o4PFUCoSRSA8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1X80o4PFUCoSRSA8 .rough-node .label text,#mermaid-svg-1X80o4PFUCoSRSA8 .node .label text,#mermaid-svg-1X80o4PFUCoSRSA8 .image-shape .label,#mermaid-svg-1X80o4PFUCoSRSA8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-1X80o4PFUCoSRSA8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1X80o4PFUCoSRSA8 .rough-node .label,#mermaid-svg-1X80o4PFUCoSRSA8 .node .label,#mermaid-svg-1X80o4PFUCoSRSA8 .image-shape .label,#mermaid-svg-1X80o4PFUCoSRSA8 .icon-shape .label{text-align:center;}#mermaid-svg-1X80o4PFUCoSRSA8 .node.clickable{cursor:pointer;}#mermaid-svg-1X80o4PFUCoSRSA8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1X80o4PFUCoSRSA8 .arrowheadPath{fill:#333333;}#mermaid-svg-1X80o4PFUCoSRSA8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1X80o4PFUCoSRSA8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1X80o4PFUCoSRSA8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1X80o4PFUCoSRSA8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1X80o4PFUCoSRSA8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1X80o4PFUCoSRSA8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster text{fill:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 .cluster span{color:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1X80o4PFUCoSRSA8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1X80o4PFUCoSRSA8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-1X80o4PFUCoSRSA8 .icon-shape,#mermaid-svg-1X80o4PFUCoSRSA8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1X80o4PFUCoSRSA8 .icon-shape p,#mermaid-svg-1X80o4PFUCoSRSA8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1X80o4PFUCoSRSA8 .icon-shape .label rect,#mermaid-svg-1X80o4PFUCoSRSA8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1X80o4PFUCoSRSA8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1X80o4PFUCoSRSA8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1X80o4PFUCoSRSA8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} controller 节点
客户端侧
Horizon Dashboard 浏览器
openstack CLI / SDK
HTTPD + WSGI 入口(端口 5000)
identity 子系统
assignment 子系统
resource 子系统
token 子系统(Fernet)
catalog 子系统
policy 子系统
后端:MySQL(身份/项目/角色数据)
Memcached(Token 缓存)
fernet-keys 对称密钥库


五、关键配置与环境变量

5.1 命令行前置:source 环境变量

操作 OpenStack CLI 前必须先导入环境变量,否则 openstack 命令不知道往哪里连、以谁的身份连:

bash 复制代码
[root@controller ~]# source keystonerc_admin
# 导入后命令行提示符变成:[root@controller ~(keystone_admin)]#

5.2 自定义用户的 openrc 环境变量文件(实验手册)

以 User_cli_01 为例:从 admin 的环境变量复制一份,再改成自己的账号:

bash 复制代码
cp keystonerc_admin keystonerc_User_cli_01
vim keystonerc_User_cli_01

文件内容(关键项逐条解释):

bash 复制代码
unset OS_SERVICE_TOKEN
export OS_USERNAME=User_cli_01                 # 自己的用户名
export OS_PASSWORD='huawei'                   # 登录密码
export OS_REGION_NAME=RegionOne               # 所在 Region
export OS_AUTH_URL=http://192.168.108.10:5000/v3   # Keystone v3 地址
export PS1='[\u@\h \W(keystone_User_cli_01)]\$ '   # 提示符装饰
export OS_PROJECT_NAME=admin                  # 以哪个项目身份登录
export OS_USER_DOMAIN_NAME=Default            # 用户所属域
export OS_PROJECT_DOMAIN_NAME=Default         # 项目所属域
export OS_IDENTITY_API_VERSION=3              # 用 v3 API

生效:

bash 复制代码
source keystonerc_User_cli_01

5.3 多域登录开关(Dashboard)

bash 复制代码
cd /etc/openstack-dashboard/
vim local_settings
# 第 83 行改为:
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
systemctl restart httpd     # 改完必须重启 httpd

开启后登录界面会多出「域」输入框,可选择以不同域身份登录。

5.4 打开 debug 日志

bash 复制代码
cd /etc/keystone/
ls
# 常见文件:default_catalog.templates  fernet-keys  keystone.conf  logging.conf
#          policy.d  policy.json  puppet.conf  sso_callback_template.html
vim keystone.conf
# 第 94 行改为:
debug=True

日志位置:/var/log/keystone/keystone.log。排查问题第一手段就是看各服务自己的日志。


六、Dashboard(Horizon)操作

Horizon 左侧导航 「身份管理(Identity)」 下分三块:项目(Project)、用户(User)、组(Group)、角色(Role)。

6.1 创建角色

路径:身份管理 > 角色 → 右上角「创建角色」→ 输入名称如 Role_web →「提交」。

6.2 创建用户

路径:身份管理 > 用户 →「创建用户」,填写:

字段 示例值
用户名 User_web_01
密码 自行设置并记录
项目 选系统已有的 admin
角色 选刚建的 Role_web

照同样步骤再建 User_web_02,角色直接选 admin。

6.3 创建用户组并加成员

  1. 路径:身份管理 > 组 →「创建组」→ 名称 Group_web。
  2. 在组所在行点「管理成员」→ 右上角「添加用户」→ 勾选 User_web_01、User_web_02 →「添加用户」。
  3. 验证:身份管理 > 用户 → 点 User_web_01 进「概览」页 → 切到「角色分配」页签看角色;切到「组」页签看所属组。

6.4 不同角色登录后的界面差异(重点现象)

点右上角 admin →「退出」,再分别用两个用户登录:

  • **User_web_02(admin 角色)**:菜单齐全,能看到「管理员」整组菜单,以及「域 / 组 / 角色」等管理入口。
  • **User_web_01(只有 Role_web / 普通 _member_ 角色)**:导航栏明显变瘦------少了「管理员」整组,也看不到「域 / 组 / 角色」这些管理项。

这就是「鉴权决定菜单可见性」的直观表现:Horizon 拿到 Token 后,按其中 Role 渲染菜单。

6.5 禁用与删除用户(关键区别)

  1. 身份管理 > 组 → Group_web 的「管理成员」→ 勾选 User_web_02 →「删除用户」。
  • 现象 :该用户只是从组里被移除,系统里用户仍然存在 ,用 User_web_02 仍可登录。
  1. 身份管理 > 用户 → User_web_02 行「编辑」→「禁用用户」。
  • 现象 :列表 Enabled 列由 Yes 变 No;此时再用该用户登录会被拒。
  1. 勾选 User_web_02 → 右上角「删除用户」→ 确认。这才是真正从系统删除。

记忆三连:移出组 ≠ 删人;禁用 = 冻结账号(Enabled No);删除 = 物理消失。

6.6 创建项目并改配额

  1. 身份管理 > 项目 →「创建项目」→「项目信息」页签填名称 Project_web,其他默认。
  2. 切到「项目成员」页签 → 把 User_web_01 选到右侧 → 点其角色框,只勾选 admin →「创建项目」。
  3. 进项目概览 →「用户」页签可看到成员及角色。
  4. 改配额:项目列表 Project_web 行 Actions 列「管理成员」旁的下拉 →「修改配额」→ 在「计算 / 卷 / 网络」页签分别改(如实例 5、卷 5、网络 5)→「保存」。
  5. 验证:注销后用 User_web_01 登录,左上角切换当前项目到 Project_web,再到 项目 > 计算 > 概况 查看配额变化。

七、CLI 操作(命令 + 输出解读)

所有命令前都假定已 source keystonerc_admin。

7.1 Domain 域

列出域:

bash 复制代码
openstack domain list

输出字段:ID | Name | Enabled | Description。实验中默认有两条:heat(ID 一长串)和 default(Name 为 Default,描述 The default domain)。

创建域:

bash 复制代码
openstack domain create domain-test

输出字段:description(空)、enabled=True、id(新生成的 UUID)、name=domain-test、options={}、tags=[]。再 openstack domain list 即可看到新增的 domain-test。

删除域(两步,不能直接删):

bash 复制代码
openstack domain set --disable domain-test   # 先禁用
openstack domain delete domain-test           # 再删除
openstack domain list                        # 验证已消失

7.2 User 用户

列出所有用户:

bash 复制代码
openstack user list

输出字段:ID | Name。除 admin 外,能看到 heat_admin、glance、cinder、nova、placement、neutron、swift、heat、heat-cfn、gnocchi、ceilometer、aodh 等服务账号。

创建用户 user1(密码 HUAWEI):

bash 复制代码
openstack user create --password HUAWEI user1

输出字段:domain_id=default、enabled=True、id=新UUID、name=user1、options={}、password_expires_at=None(密码永不过期)。

实验手册里更规范的写法(建用户同时指定域、项目,交互输密码):

bash 复制代码
openstack user create --domain default --project admin --password-prompt User_cli_01
# 按提示输入并再次确认密码

查看用户详情:

bash 复制代码
openstack user show user1

输出与创建时字段一致;禁用后 enabled 会变为 False。

禁用 / 删除用户:

bash 复制代码
openstack user set --disable User_cli_02    # 禁用,Enabled 变 No
openstack user show User_cli_02             # 验证 enabled 字段
openstack user delete User_cli_02           # 真正删除
openstack user list                         # 验证列表里没了

7.3 Group 用户组

bash 复制代码
openstack group create group1                       # 创建组
openstack group list                                # 列出所有组(ID|Name)
openstack group show group1                         # 组详情:description/domain_id/id/name
openstack group add user group1 user1               # 把 user1 加入 group1
openstack group contains user group1 user1          # 验证成员关系
# 输出:user1 in group group1

实验手册中一次性加多个成员、以及从组中移除:

bash 复制代码
openstack group add user Group_cli User_cli_01 User_cli_02   # 一次加两人
openstack group remove user Group_cli User_cli_02            # 从组移除
openstack group contains user Group_cli User_cli_02          # 移除后不再提示 contains

7.4 Role 角色与授权

列出角色:

bash 复制代码
openstack role list

输出字段:ID | Name。实验环境可见:ResellerAdmin、SwiftOperator、admin、_member_、member、heat_stack_owner、reader、heat_stack_user。

创建角色:

bash 复制代码
openstack role create Role_cli

给「组」授权(在 admin 项目上给 group1 赋 admin 角色):

bash 复制代码
openstack role add --project admin --group group1 admin

给「用户」授权(在 ProjectA 里给 user1 赋 admin):

bash 复制代码
openstack role add --user user1 --project ProjectA admin

实验手册写法:

bash 复制代码
openstack role add --project admin --user User_cli_01 Role_cli
openstack role add --project admin --user User_cli_02 admin
openstack role add --project Project_cli --user User_cli_01 admin

查看角色分配:

bash 复制代码
openstack role assignment list --names --group group1

输出字段:Role | User | Group | Project | Domain | System | Inherited。例如给 group1 授 admin 后会显示:

复制代码
| admin |      | group1@Default | admin@Default |        |        | False |

Inherited=False 表示未跨项目树继承;@Default 表示在 Default 域下。

实验手册的过滤写法:

bash 复制代码
openstack role assignment list --names | grep User_cli
openstack role assignment list --names | grep User_cli_01
openstack role assignment list --names | grep Group_cli

7.5 Project 项目与配额

创建项目:

bash 复制代码
openstack project create ProjectA
# 或显式指定域(实验手册写法):
openstack project create --domain default Project_cli

输出字段:description、domain_id=default、enabled=True、id、is_domain=False、name、options={}、parent_id=default(父项目默认是 default 域)、tags=[]。

查看项目:

bash 复制代码
openstack project list
openstack project show ProjectA

把项目绑定给用户 / 给用户授项目角色:

bash 复制代码
openstack user set --project ProjectA user1
openstack role add --user user1 --project ProjectA admin

设置配额(教材示例:实例 3、vcpu 5、内存 5000MB):

bash 复制代码
openstack quota set --instance 3 --cores 5 --ram 5000 ProjectA

字段含义:--instance 实例个数、--cores vCPU 个数、--ram 内存 MB。

实验手册的配额写法(含卷、网络):

bash 复制代码
openstack quota show Project_cli                                    # 查看默认配额
openstack quota set --instance 5 --volumes 5 --networks 10 Project_cli
openstack quota show Project_cli | grep -E "instances|volumes|networks"

现象:用被改配额的用户登录、切到对应项目后,到 项目 > 计算 > 概况 能看到实例/CPU/内存/卷/网络上限随之变化;达到上限后再申请资源会被拒绝。

7.6 Service 与 Endpoint

列出所有服务:

bash 复制代码
openstack service list

输出字段:ID | Name | Type。常见对照:

Name Type
keystone identity
nova compute
glance image
cinderv2 / cinderv3 volumev2 / volumev3
neutron network
swift object-store
heat orchestration
heat-cfn cloudformation
placement placement
ceilometer metering
aodh alarming
gnocchi metric

查看 Endpoint 与服务目录:

bash 复制代码
openstack endpoint list      # 列出所有端点,可见 admin/internal/public 三个入口
openstack catalog list        # 以服务目录形式列出每个服务及其 endpoint URL

登录成功后 Keystone 返回给用户的「catalog」就是这张表,客户端靠它知道每个服务该往哪个 URL 发请求。


八、两个必背流程(时序图)

8.1 点击「登入」背后发生了什么

以 admin 登录 Horizon 查看镜像为例:

  1. 登录 :admin 输入用户名密码 → Dashboard 把 Credential 发给 Keystone → Keystone 校验通过,签发 Token(其中包含 User 的 Role 信息)。
  2. 显示操作界面 :顶部显示 admin 可访问的项目为 admin;这之前 admin 已经从 Keystone 拿到了各 Service 的 Endpoints,所以能看到实例、镜像、卷等服务入口。
  3. 显示镜像列表:
  • admin 把请求发到 Glance 的 Endpoint;
  • Glance 收到后先去 Keystone 询问 admin 的身份是否有效;
  • 再查 /etc/glance/policy.json 判断 admin 是否有「查看 image」权限;
  • 权限通过,Glance 才把镜像列表返回给 admin。

"Glance" "Keystone" "Horizon Dashboard" "Glance" "Keystone" "Horizon Dashboard" #mermaid-svg-MullKmxh3irwapfn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MullKmxh3irwapfn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MullKmxh3irwapfn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MullKmxh3irwapfn .error-icon{fill:#552222;}#mermaid-svg-MullKmxh3irwapfn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MullKmxh3irwapfn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MullKmxh3irwapfn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MullKmxh3irwapfn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MullKmxh3irwapfn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MullKmxh3irwapfn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MullKmxh3irwapfn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MullKmxh3irwapfn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MullKmxh3irwapfn .marker.cross{stroke:#333333;}#mermaid-svg-MullKmxh3irwapfn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MullKmxh3irwapfn p{margin:0;}#mermaid-svg-MullKmxh3irwapfn .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MullKmxh3irwapfn text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-MullKmxh3irwapfn .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MullKmxh3irwapfn .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-MullKmxh3irwapfn .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-MullKmxh3irwapfn .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-MullKmxh3irwapfn #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-MullKmxh3irwapfn .sequenceNumber{fill:white;}#mermaid-svg-MullKmxh3irwapfn #sequencenumber{fill:#333;}#mermaid-svg-MullKmxh3irwapfn #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-MullKmxh3irwapfn .messageText{fill:#333;stroke:none;}#mermaid-svg-MullKmxh3irwapfn .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MullKmxh3irwapfn .labelText,#mermaid-svg-MullKmxh3irwapfn .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-MullKmxh3irwapfn .loopText,#mermaid-svg-MullKmxh3irwapfn .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-MullKmxh3irwapfn .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MullKmxh3irwapfn .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-MullKmxh3irwapfn .noteText,#mermaid-svg-MullKmxh3irwapfn .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-MullKmxh3irwapfn .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MullKmxh3irwapfn .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MullKmxh3irwapfn .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MullKmxh3irwapfn .actorPopupMenu{position:absolute;}#mermaid-svg-MullKmxh3irwapfn .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-MullKmxh3irwapfn .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MullKmxh3irwapfn .actor-man circle,#mermaid-svg-MullKmxh3irwapfn line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-MullKmxh3irwapfn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "User admin" "输入用户名/密码,点登入" "提交 Credential(用户名密码)" "签发 Token(含 Role=admin)" "登录成功,顶部显示当前项目 admin" "按 Token 拉取 Service Endpoints 目录" "返回 catalog(Nova/Glance/Cinder... 地址)" "点击「镜像」" "请求镜像列表(携带 Token)" "校验 Token 是否有效" "有效,返回 Role=admin" "查 /etc/glance/policy.json 是否允许查看" "返回镜像列表" "渲染镜像列表" "User admin"

8.2 以「创建一台 VM」看整个 OpenStack 的认证链路

  1. 用户先向 Keystone 提交用户名密码换 Token。
  2. 用户向 Nova 发创建 VM 请求,请求 Header 携带 Token。
  3. Nova-api 收到后把 Token 转给 Keystone 校验;校验通过,Nova 才开始创建。
  4. 创建 VM 不仅要 CPU/内存,还要网络、存储、镜像等资源:
  • Nova 向 Glance 申请镜像(Header 同样带 Token);
  • Nova 向 Neutron 申请网络(Header 同样带 Token);
  • Nova-api 还会把 Token 透传给 Nova-compute,compute 再向 Neutron 发网络操作请求。
  1. Glance、Neutron 收到请求后,无一例外都要把 Token 再拿去 Keystone 校验一次,通过才执行。
  2. 全部资源就绪、VM 创建完成后,Nova 把成功结果返回给用户。

关键结论:Keystone 只校验 Token 是否有效(你是谁),而「这个 Token 能不能做这件事」由各服务自己的 policy 决定(你能干什么)。 服务之间互相调用也必须带 Token。
"Neutron" "Glance" "Nova-compute" "Nova-api" "Keystone" "Neutron" "Glance" "Nova-compute" "Nova-api" "Keystone" #mermaid-svg-54R6gs1aq36dIugE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-54R6gs1aq36dIugE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-54R6gs1aq36dIugE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-54R6gs1aq36dIugE .error-icon{fill:#552222;}#mermaid-svg-54R6gs1aq36dIugE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-54R6gs1aq36dIugE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-54R6gs1aq36dIugE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-54R6gs1aq36dIugE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-54R6gs1aq36dIugE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-54R6gs1aq36dIugE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-54R6gs1aq36dIugE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-54R6gs1aq36dIugE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-54R6gs1aq36dIugE .marker.cross{stroke:#333333;}#mermaid-svg-54R6gs1aq36dIugE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-54R6gs1aq36dIugE p{margin:0;}#mermaid-svg-54R6gs1aq36dIugE .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-54R6gs1aq36dIugE text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-54R6gs1aq36dIugE .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-54R6gs1aq36dIugE .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-54R6gs1aq36dIugE .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-54R6gs1aq36dIugE .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-54R6gs1aq36dIugE #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-54R6gs1aq36dIugE .sequenceNumber{fill:white;}#mermaid-svg-54R6gs1aq36dIugE #sequencenumber{fill:#333;}#mermaid-svg-54R6gs1aq36dIugE #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-54R6gs1aq36dIugE .messageText{fill:#333;stroke:none;}#mermaid-svg-54R6gs1aq36dIugE .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-54R6gs1aq36dIugE .labelText,#mermaid-svg-54R6gs1aq36dIugE .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-54R6gs1aq36dIugE .loopText,#mermaid-svg-54R6gs1aq36dIugE .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-54R6gs1aq36dIugE .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-54R6gs1aq36dIugE .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-54R6gs1aq36dIugE .noteText,#mermaid-svg-54R6gs1aq36dIugE .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-54R6gs1aq36dIugE .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-54R6gs1aq36dIugE .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-54R6gs1aq36dIugE .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-54R6gs1aq36dIugE .actorPopupMenu{position:absolute;}#mermaid-svg-54R6gs1aq36dIugE .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-54R6gs1aq36dIugE .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-54R6gs1aq36dIugE .actor-man circle,#mermaid-svg-54R6gs1aq36dIugE line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-54R6gs1aq36dIugE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "用户" "用户名/密码" "签发 Token" "创建 VM 请求(Header 带 Token)" "校验 Token" "有效" "申请镜像(带 Token)" "校验 Token" "有效,按 policy 放行" "返回镜像数据" "下发创建指令(透传 Token)" "申请网络资源(带 Token)" "校验 Token" "有效,按 policy 放行" "分配网络" "VM 建成" "创建成功" "用户"


九、易混点对比表

对比项 一句话区别
Domain vs Project Domain 是全局唯一 的大容器(机构/数据中心);Project 只需域内唯一,是被配额约束的资源集合。
User vs Group User 是单个实体;Group 是 User 的容器,给组授权 = 批量授权。
Authentication vs Authorization 认证=你是谁;鉴权=你能干什么。
Token vs Credential Credential 是「证明身份的数据」(密码/Token/API Key);Token 是认证成功后 Keystone 发的、用作后续凭证的字符串。
Service vs Endpoint Service 是一项能力(如 Nova);Endpoint 是访问这项能力的具体 URL。
域角色 vs 项目角色 域角色对域内所有项目生效;项目角色只对单个项目生效。
移出组 vs 禁用用户 vs 删除用户 移出组=退群;禁用=Enabled 变 No,不能登录但账号还在;删除=系统里彻底消失。
Tenant / Project / Account 同一概念不同叫法,官方长期统一为 Project,公有云叫租户。
admin 角色 vs 普通 _member_ admin 看到「管理员」菜单和域/组/角色管理;普通用户菜单精简,看不到这些管理入口。

十、补充内容(进阶拓展)

以下内容教材未讲透,是面试和进阶排障高频点,均标注「补充」。

10.1 【补充】Token 的种类与演进

Token 类型 特点
UUID Token 早期纯随机字符串,需 Keystone 数据库存储/查询,校验一次就回一次库,性能差。
PKI / PKIZ Token 基于签名的自包含 Token,信息多、体积大,PKIZ 做了压缩;仍需管理证书。
Fernet Token 当前默认 。不持久化到数据库,用对称密钥本地加解密;支持密钥轮转、体积小、性能高;本环境 /etc/keystone/fernet-keys/ 就是密钥库。
JWT JSON 格式自包含令牌,联邦/OIDC 场景常见。

Token 生命周期:默认 24 小时,生产常配为 1 小时;为减轻 Keystone 压力,校验结果常缓存到 Memcached。

10.2 【补充】RBAC 与三种 scope、Secure RBAC

  • OpenStack 授权模型是 RBAC(基于角色的访问控制)。
  • 角色绑定可以有三种作用范围(scope):
    • project:对某个项目资源生效(最常用);
    • domain:对整个域生效;
    • system:对整个云系统级资源生效(新版引入)。
  • 策略写法从传统 policy.json 演进为 policy in code(policy.yaml)。
  • Secure RBAC 是新规范,把角色收敛为三档:admin(管理)、member(普通项目成员)、reader(只读),替代过去「只分 admin / 非 admin」的粗粒度模型。

10.3 【补充】联邦身份 Federation 与外部身份源

  • Keystone 可作为 IdP(身份提供者) 或 SP(服务提供者) ,通过 SAML / OpenID Connect 对接企业统一身份,实现「一次登录访问多个云」。
  • 用户库可对接 LDAP(把公司 AD/LDAP 里的人直接映射成 OpenStack User),而不是在 Keystone 里重复建账号。
  • 应用凭证 Application Credential:给脚本/服务发一个长期凭证,避免把个人密码写进配置文件。

10.4 【补充】域 / 项目层级树与多租户隔离

Project 不是平的,而是一棵有父子关系的树:创建项目时 parent_id 默认是当前域;可把子项目挂在父项目下。角色可沿父子方向继承------授予父项目的角色自动作用于子项目。多租户隔离的本质就是:每个 Project 有自己的配额、自己的资源(VM、卷、网络),User 只有在某 Project 下被授了对应 Role,才能看到和操作那部分资源,天然互不可见。
#mermaid-svg-XqPmzTKBRr0vrHj8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XqPmzTKBRr0vrHj8 .error-icon{fill:#552222;}#mermaid-svg-XqPmzTKBRr0vrHj8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XqPmzTKBRr0vrHj8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .marker.cross{stroke:#333333;}#mermaid-svg-XqPmzTKBRr0vrHj8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XqPmzTKBRr0vrHj8 p{margin:0;}#mermaid-svg-XqPmzTKBRr0vrHj8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster-label text{fill:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster-label span{color:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster-label span p{background-color:transparent;}#mermaid-svg-XqPmzTKBRr0vrHj8 .label text,#mermaid-svg-XqPmzTKBRr0vrHj8 span{fill:#333;color:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .node rect,#mermaid-svg-XqPmzTKBRr0vrHj8 .node circle,#mermaid-svg-XqPmzTKBRr0vrHj8 .node ellipse,#mermaid-svg-XqPmzTKBRr0vrHj8 .node polygon,#mermaid-svg-XqPmzTKBRr0vrHj8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .rough-node .label text,#mermaid-svg-XqPmzTKBRr0vrHj8 .node .label text,#mermaid-svg-XqPmzTKBRr0vrHj8 .image-shape .label,#mermaid-svg-XqPmzTKBRr0vrHj8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-XqPmzTKBRr0vrHj8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .rough-node .label,#mermaid-svg-XqPmzTKBRr0vrHj8 .node .label,#mermaid-svg-XqPmzTKBRr0vrHj8 .image-shape .label,#mermaid-svg-XqPmzTKBRr0vrHj8 .icon-shape .label{text-align:center;}#mermaid-svg-XqPmzTKBRr0vrHj8 .node.clickable{cursor:pointer;}#mermaid-svg-XqPmzTKBRr0vrHj8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .arrowheadPath{fill:#333333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XqPmzTKBRr0vrHj8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XqPmzTKBRr0vrHj8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XqPmzTKBRr0vrHj8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster text{fill:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 .cluster span{color:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XqPmzTKBRr0vrHj8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XqPmzTKBRr0vrHj8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-XqPmzTKBRr0vrHj8 .icon-shape,#mermaid-svg-XqPmzTKBRr0vrHj8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XqPmzTKBRr0vrHj8 .icon-shape p,#mermaid-svg-XqPmzTKBRr0vrHj8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XqPmzTKBRr0vrHj8 .icon-shape .label rect,#mermaid-svg-XqPmzTKBRr0vrHj8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XqPmzTKBRr0vrHj8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XqPmzTKBRr0vrHj8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XqPmzTKBRr0vrHj8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Default 域
继承
继承
项目树根(default 域)
ProjectA(父项目)
ProjectB(父项目)
子项目 A1
子项目 A2
admin 角色(授予父项目 ProjectA)


十一、本篇小结

  • Keystone 是 OpenStack 的身份中心:管用户权限、管服务 Endpoint 目录、做认证与鉴权。
  • 九大概念要成对记:Domain/User/Group/Project 是「容器与人」,Role/Service/Endpoint 是「权限与地址」,Token/Credential 是「通行证与身份证明」。
  • 唯一性范围是高频考点:Domain、Role 全局唯一;User、Project 只需域内唯一。
  • 认证(你是谁)由 Keystone 发 Token;鉴权(你能干什么)由各服务 policy + Role 决定。
  • 一次请求的标准动作链:带 Token 访问服务 → 服务拿 Token 去 Keystone 校验 → 查 policy → 放行或拒绝。
  • 操作分 Dashboard 与 CLI 两条线,命令要形成肌肉记忆:openstack user/project/group/role/domain/service/endpoint/quota 各有 list/create/show/add/set/delete。

十二、重点速记

速记项 内容
三件事 管用户权限、维护 Endpoint、认证 + 鉴权
全局唯一 Domain、Role
域内唯一 User、Project
管理员账号 / 密码 admin / huawei
controller IP 192.168.108.10
OS_AUTH_URL http://192.168.108.10:5000/v3
Region RegionOne
日志 /var/log/keystone/keystone.log
配置目录 /etc/keystone/(keystone.conf,debug=True 在第 94 行)
Dashboard 多域开关 /etc/openstack-dashboard/local_settings 第 83 行 OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True,改完 systemctl restart httpd
配额三件套 openstack quota set --instance N --cores N --ram MB 项目名
登录前必做 source keystonerc_admin
默认角色二分 admin vs 非 admin(_member_/member)

口诀: 「域管容器、人在域中、组批量授权、项目分资源、角色定权限、服务挂端点、Token 当通行证、密码是凭证。」


十三、自测题(附参考答案)

A. 名词解释

  1. Domain:一组 User/Group/Project 的容器,是虚拟管理边界,可对应一个机构或数据中心,必须全局唯一。
  2. Token:User 通过 Keystone 认证后获得的访问凭证(字符串),内含 Role 信息,后续访问各服务都要携带并被 Keystone 校验,默认有效期 24 小时。
  3. Endpoint:可访问某个具体 Service 的网络地址(通常是 URL),由 Keystone 统一登记维护。
  4. Role:一组预定义权限的集合,全局唯一,可授予 User/Group,可在项目树中继承;决定用户能干什么。

B. 选择题

  1. 下面哪个对象只需在「域内唯一」,不必全局唯一?(C)
  • A. Domain B. Role C. Project D. 以上都不对
  1. 用户 _member_ 角色登录 Horizon 后,相比 admin 少看到哪一组菜单?(B)
  • A. 镜像 B. 「管理员」及「域/组/角色」 C. 实例 D. 卷
  1. 关于从用户组里移除用户,正确的是?(A)
  • A. 只是退出该组,用户本体仍存在、仍可登录
  • B. 等同于删除用户
  • C. 等同于禁用用户
  1. Keystone 校验完 Token 后,判断「能否执行某操作」依据的是?(C)
  • A. 用户密码 B. Token 长度 C. 目标服务自己的 policy 文件与 Role D. 数据库大小

C. 简答题

  1. 说出点击 Horizon「登入」后内部发生的三步。
    答:① 提交用户名密码给 Keystone,校验通过签发含 Role 的 Token;② 凭 Token 从 Keystone 拉取各 Service 的 Endpoints 目录,据此渲染顶部项目和服务菜单;③ 点具体服务(如镜像)时,请求带 Token 发到该服务 Endpoint,服务再去 Keystone 校验 Token、查自己的 policy,通过才返回数据。
  2. 为什么服务之间互相调用也要带 Token?只让 Keystone 校验不就够了吗?
    答:Keystone 只回答「Token 有效吗、这个 User 有什么 Role」,不回答「Nova 能不能调 Neutron 建网」。每个服务要各自拿着 Token 回 Keystone 验证身份,再结合自己的 policy 决定是否执行------这样才能做到细粒度、可审计的鉴权。
  3. 写出把 ProjectA 配额改为「实例 3、vCPU 5、内存 5000MB」的命令。
    答:openstack quota set --instance 3 --cores 5 --ram 5000 ProjectA
  4. 思考拓展(教材思考题) :参照创建 ProjectA 的方式,新建 ProjectB 分给 user2 并授 admin;再建 user3 并在 ProjectA 中授 member 角色。写出关键命令。
    答:
bash 复制代码
openstack project create ProjectB
openstack user create --password HUAWEI user2
openstack role add --user user2 --project ProjectB admin
openstack user create --password HUAWEI user3
openstack role add --user user3 --project ProjectA member
  1. 实验手册思考题 :直接给组 Group_cli 在 Project_cli 上授 admin 是否可行?
    答:可行。openstack role add --project Project_cli --group Group_cli admin,再用 openstack role assignment list --names | grep Group_cli 验证------组里的成员因此批量获得该项目的 admin 角色,这正是 Group 批量授权的价值。
相关推荐
分布式存储与RustFS1 小时前
模型权重散落在每台 GPU?用 RustFS 给 vLLM 做共享权重库
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
ai_xiaogui2 小时前
私有化部署大模型实战:PanelAI 一键搭建、Token 计费与多用户隔离
运维·私有化部署·大模型部署·大模型 token 计费·api key 统一管理·多用户实例隔离·应用市场一键部署
企鹅侠客2 小时前
Linux CPU 负载平均值(Load Average)详解:从原理到实践
linux·运维·服务器·服务器负载
易点云徐源2 小时前
HP 暗影精灵 PRO 16 安装双系统后,开机直接进入 Windows,按 F9 才能进入 Ubuntu:GRUB 菜单不显示的处理方法
linux·运维·ubuntu
吃一碗粉只付一碗钱2 小时前
10-令牌里的用户主键不要明文
服务器·数据库·sql·sqlserver·c#
木雷坞2 小时前
Baserow Docker部署:导入设备借用CSV,再用表单新增登记
运维·docker·容器
Linux运维技术栈2 小时前
WAF部署在防火墙后面,获取不到真实IP怎么办?
服务器·网络·tcp/ip·安全·防火墙·waf
程序员大雄学编程2 小时前
crontab 脚本不写日志?我把 7 个原因在 Ubuntu 上逐个复现了一遍
运维
广目软件2 小时前
HA分布式架构采集节点变更操作手册20261029
运维·服务器·ansible·zabbix·prometheus