01 · 认证管理 Keystone
本篇导读:Keystone 是 OpenStack 的「身份证中心 + 服务目录」。任何用户或服务想使用 OpenStack,第一步都要先找 Keystone 报到。本篇从「它是谁、管什么」切入,逐个讲透九大核心概念,再带你走一遍 Dashboard 与 CLI 的完整操作,最后用两张时序图把「登录」和「创建虚拟机」背后发生的认证/鉴权链路钉死。学完你应当能独立创建域、用户、组、项目、角色、配额,并说清 Token 在各服务之间是怎么被反复校验的。
学习目标:
- 说清 Keystone 在 OpenStack 中的定位与三件核心工作。
- 准确复述九大概念(Domain / User / Group / Project / Role / Service / Endpoint / Token / Credential)的一句话定义与唯一性范围。
- 区分 Authentication(认证)与 Authorization(鉴权),理解 policy 基于 Role 的访问控制。
- 能用 Dashboard 和 CLI 两种方式完成:创建角色、用户、用户组、项目、改配额、禁用/删除用户。
- 画得出「点击登入」和「创建一台 VM」时 Token 在 Keystone / Nova / Glance / Neutron 之间的流转时序。
- 知道 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......)都要围着它转。它主要做三件事:
- 管理用户及其权限(谁能登录、能登到哪个项目、能干什么)。
- 维护 OpenStack 各 Service 的 Endpoint 目录(告诉别人「Nova 的 API 地址是多少」)。
- 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 创建用户组并加成员
- 路径:
身份管理 > 组→「创建组」→ 名称Group_web。 - 在组所在行点「管理成员」→ 右上角「添加用户」→ 勾选
User_web_01、User_web_02→「添加用户」。 - 验证:
身份管理 > 用户→ 点User_web_01进「概览」页 → 切到「角色分配」页签看角色;切到「组」页签看所属组。
6.4 不同角色登录后的界面差异(重点现象)
点右上角 admin →「退出」,再分别用两个用户登录:
**User_web_02(admin 角色)**:菜单齐全,能看到「管理员」整组菜单,以及「域 / 组 / 角色」等管理入口。**User_web_01(只有Role_web/ 普通_member_角色)**:导航栏明显变瘦------少了「管理员」整组,也看不到「域 / 组 / 角色」这些管理项。
这就是「鉴权决定菜单可见性」的直观表现:Horizon 拿到 Token 后,按其中 Role 渲染菜单。
6.5 禁用与删除用户(关键区别)
身份管理 > 组→Group_web的「管理成员」→ 勾选User_web_02→「删除用户」。
- 现象 :该用户只是从组里被移除,系统里用户仍然存在 ,用
User_web_02仍可登录。
身份管理 > 用户→User_web_02行「编辑」→「禁用用户」。
- 现象 :列表
Enabled列由Yes变No;此时再用该用户登录会被拒。
- 勾选
User_web_02→ 右上角「删除用户」→ 确认。这才是真正从系统删除。
记忆三连:移出组 ≠ 删人;禁用 = 冻结账号(Enabled No);删除 = 物理消失。
6.6 创建项目并改配额
身份管理 > 项目→「创建项目」→「项目信息」页签填名称Project_web,其他默认。- 切到「项目成员」页签 → 把
User_web_01选到右侧 → 点其角色框,只勾选admin→「创建项目」。 - 进项目概览 →「用户」页签可看到成员及角色。
- 改配额:项目列表
Project_web行 Actions 列「管理成员」旁的下拉 →「修改配额」→ 在「计算 / 卷 / 网络」页签分别改(如实例 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 查看镜像为例:
- 登录 :admin 输入用户名密码 → Dashboard 把 Credential 发给 Keystone → Keystone 校验通过,签发 Token(其中包含 User 的 Role 信息)。
- 显示操作界面 :顶部显示 admin 可访问的项目为
admin;这之前 admin 已经从 Keystone 拿到了各 Service 的 Endpoints,所以能看到实例、镜像、卷等服务入口。 - 显示镜像列表:
- 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 的认证链路
- 用户先向 Keystone 提交用户名密码换 Token。
- 用户向 Nova 发创建 VM 请求,请求 Header 携带 Token。
- Nova-api 收到后把 Token 转给 Keystone 校验;校验通过,Nova 才开始创建。
- 创建 VM 不仅要 CPU/内存,还要网络、存储、镜像等资源:
- Nova 向 Glance 申请镜像(Header 同样带 Token);
- Nova 向 Neutron 申请网络(Header 同样带 Token);
- Nova-api 还会把 Token 透传给 Nova-compute,compute 再向 Neutron 发网络操作请求。
- Glance、Neutron 收到请求后,无一例外都要把 Token 再拿去 Keystone 校验一次,通过才执行。
- 全部资源就绪、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. 名词解释
- Domain:一组 User/Group/Project 的容器,是虚拟管理边界,可对应一个机构或数据中心,必须全局唯一。
- Token:User 通过 Keystone 认证后获得的访问凭证(字符串),内含 Role 信息,后续访问各服务都要携带并被 Keystone 校验,默认有效期 24 小时。
- Endpoint:可访问某个具体 Service 的网络地址(通常是 URL),由 Keystone 统一登记维护。
- Role:一组预定义权限的集合,全局唯一,可授予 User/Group,可在项目树中继承;决定用户能干什么。
B. 选择题
- 下面哪个对象只需在「域内唯一」,不必全局唯一?(C)
- A. Domain B. Role C. Project D. 以上都不对
- 用户
_member_角色登录 Horizon 后,相比 admin 少看到哪一组菜单?(B)
- A. 镜像 B. 「管理员」及「域/组/角色」 C. 实例 D. 卷
- 关于从用户组里移除用户,正确的是?(A)
- A. 只是退出该组,用户本体仍存在、仍可登录
- B. 等同于删除用户
- C. 等同于禁用用户
- Keystone 校验完 Token 后,判断「能否执行某操作」依据的是?(C)
- A. 用户密码 B. Token 长度 C. 目标服务自己的 policy 文件与 Role D. 数据库大小
C. 简答题
- 说出点击 Horizon「登入」后内部发生的三步。
答:① 提交用户名密码给 Keystone,校验通过签发含 Role 的 Token;② 凭 Token 从 Keystone 拉取各 Service 的 Endpoints 目录,据此渲染顶部项目和服务菜单;③ 点具体服务(如镜像)时,请求带 Token 发到该服务 Endpoint,服务再去 Keystone 校验 Token、查自己的 policy,通过才返回数据。 - 为什么服务之间互相调用也要带 Token?只让 Keystone 校验不就够了吗?
答:Keystone 只回答「Token 有效吗、这个 User 有什么 Role」,不回答「Nova 能不能调 Neutron 建网」。每个服务要各自拿着 Token 回 Keystone 验证身份,再结合自己的 policy 决定是否执行------这样才能做到细粒度、可审计的鉴权。 - 写出把 ProjectA 配额改为「实例 3、vCPU 5、内存 5000MB」的命令。
答:openstack quota set --instance 3 --cores 5 --ram 5000 ProjectA - 思考拓展(教材思考题) :参照创建 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
- 实验手册思考题 :直接给组
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 批量授权的价值。