尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

OpenStack Keystone手动安装与身份治理原理详解

OpenStack Keystone手动安装与身份治理原理详解
📅 发布时间:2026/7/17 23:04:39

1. 这不是“装个软件”:Keystone手动安装背后的OpenStack身份治理逻辑

很多人看到“Keystone手动安装与配置”这个标题,第一反应是:“哦,又一个Linux服务安装教程,改改配置文件、跑几条命令、重启下服务就完事了。”我当年第一次在实训课上也是这么想的——直到我把keystone-manage db_sync执行了三遍,数据库里还是空空如也,而openstack user list报出一长串Connection refused。那一刻我才真正意识到:Keystone不是Apache或Nginx那种“开箱即用”的Web服务;它是一套运行在OpenStack心脏位置的身份治理引擎,它的安装过程,本质上是在为整个云平台铺设信任地基。

为什么必须手动安装?因为自动化脚本(比如DevStack)会把所有依赖、证书、数据库初始化全包圆,你点个回车就完事。但实训项目要训练的,恰恰是你对这套机制的“解剖能力”:当你亲手敲下openssl rand -hex 10生成admin_token,你是在理解服务间通信的密钥协商机制;当你手动编辑/etc/keystone/keystone.conf里的connection字段,你是在建立对OpenStack服务网格拓扑的具象认知;当你执行keystone-manage pki_setup,你不是在运行一个黑盒命令,而是在亲手部署一套微型PKI(公钥基础设施),为后续所有API调用签发和验证JWT令牌。这就像学开车,自动挡能让你上路,但只有摸过离合、踩过油门、感受过发动机转速与车速的咬合关系,你才算真正懂了“驱动”。

关键词里反复出现的“Keystone”绝非一个孤立名词。它和“MySQL安装配置教程”“git安装及配置教程”这些并列热词的本质区别在于:后两者是工具链的起点,而Keystone是整个OpenStack服务生态的守门人。没有它,Nova无法验证虚拟机创建请求是否来自合法租户,Glance无法确认镜像上传者是否有权限,Horizon控制台连登录框都弹不出来。所以,本次实训的底层目标,从来不是“让Keystone进程跑起来”,而是让你建立起一个清晰的判断链:当OpenStack某个服务报401 Unauthorized时,问题90%不在那个服务本身,而在Keystone的token签发、验证或数据库状态上。这种系统级排错思维,才是企业云平台运维工程师的核心竞争力。

我带过的几十届学生里,80%的人卡在第一步——环境准备。他们习惯性地跳过getent hosts controller这行命令,直接在配置文件里写死127.0.0.1,结果Keystone服务启动后,其他OpenStack服务(比如Nova)根本连不上它,因为它们被配置成通过主机名controller访问。这不是笔误,这是对OpenStack分布式架构最基础的信任模型缺乏认知。Keystone要求所有服务节点通过可解析的、一致的主机名进行通信,这是为了支持未来横向扩展——当你的云平台从单节点发展到多节点时,controller这个逻辑名称将指向一个VIP或负载均衡器,而不是某台物理机的IP。所以,实训的第一课,其实是教你如何像一个云架构师那样思考:每一个配置项,都是在为未来的弹性伸缩埋下伏笔。

提示:不要急于复制粘贴命令。在敲下pkg install keystone(Solaris)或apt install keystone(Ubuntu)之前,请先确认你的操作系统版本与OpenStack发行版的兼容性。Havana、Juno、Queens各版本对Python版本、数据库驱动、SSL库的要求差异极大。我见过太多人因为用Ubuntu 22.04硬装OpenStack Queens,结果pip依赖冲突到凌晨三点——这不是技术问题,是项目规划问题。

2. 环境筑基:从主机名解析到数据库授权的七道关卡

手动安装Keystone,前30分钟的工作量,可能占整个项目50%的精力。这不是夸张,而是因为OpenStack对环境的“洁癖”程度远超常规应用。它要求一个高度可控、命名规范、权限分明的基础环境。任何一处疏忽,都会在后续keystone-manage db_sync或openstack user create阶段以晦涩的错误码爆发出来。下面这七道关卡,是我用三年生产环境排障经验总结出的“必过清单”,漏掉任意一道,后面全是坑。

2.1 主机名解析:不只是/etc/hosts那么简单

OpenStack所有服务间的通信,强制使用主机名(hostname),而非IP地址。这看似简单,但实操中陷阱重重。很多同学会直接在/etc/hosts里加一行:

127.0.0.1 controller

这在单机测试时看似可行,但一旦你尝试从另一台机器(比如计算节点)访问Keystone,就会失败。原因在于:127.0.0.1是本地回环地址,只对本机有效。正确的做法,是让controller这个主机名解析到你的实际管理网络IP,比如192.168.1.10。

更关键的是,你需要验证解析的双向一致性。执行以下两条命令,输出必须完全相同:

# 查看本机hostname hostname # 查看hostname对应的IP getent hosts $(hostname) | awk '{print $1}'

如果hostname输出是controller,而getent hosts controller返回的是127.0.0.1,那你就掉坑里了。修复方法是:修改/etc/hosts,确保controller映射到真实IP,并且/etc/hostname文件里写的也是controller。在Solaris系统中,还需检查/etc/nodename文件。这一步的哲学意义在于:OpenStack不信任“我”,它只信任“controller”这个身份标识。你的机器必须向整个网络宣告自己就是controller,且这个宣告必须被所有节点准确接收。

2.2 MySQL数据库:创建专用用户与库的精确指令

Keystone需要一个独立的MySQL数据库来存储用户、租户、角色、服务端点等核心元数据。很多人图省事,直接用root用户连接,这是严重违反安全原则的。Keystone官方文档明确要求创建专用用户,其权限必须严格限定。

在MySQL中,执行以下命令(注意替换YOUR_PASSWORD):

-- 创建keystone数据库,字符集必须为utf8mb4,否则中文用户名会乱码 CREATE DATABASE keystone CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 创建keystone用户,密码强度必须符合MySQL 5.7+的默认策略(至少8位,含大小写字母、数字、特殊符号) CREATE USER 'keystone'@'localhost' IDENTIFIED BY 'YOUR_PASSWORD'; CREATE USER 'keystone'@'%' IDENTIFIED BY 'YOUR_PASSWORD'; -- 授予keystone用户对keystone数据库的全部权限(仅此库!) GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost'; GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%'; -- 刷新权限,使配置立即生效 FLUSH PRIVILEGES;

这里有两个极易被忽略的细节:第一,'keystone'@'%'这个用户是必须的。因为Keystone服务本身可能运行在controller节点,但其他OpenStack服务(如Nova)可能运行在不同节点,它们需要通过网络连接MySQL,'localhost'用户只允许本机socket连接。第二,utf8mb4字符集是硬性要求。OpenStack Queens及以后版本大量使用Unicode emoji和生僻字作为资源描述,utf8(实际是utf8mb3)无法支持四字节UTF-8字符,会导致keystone-manage db_sync中途报错Incorrect string value。

2.3 Python环境与依赖:避开pip地狱的务实方案

Keystone是一个Python应用,但它对Python版本和第三方库的版本有极其苛刻的要求。例如,OpenStack Victoria要求Python 3.6+,而Queens则要求Python 2.7或3.5。盲目升级pip或用pip install --upgrade全局更新,极可能导致系统Python环境崩溃(尤其在Ubuntu/Debian上,apt和pip混用是大忌)。

我的建议是:永远优先使用系统包管理器安装Keystone主程序,仅用pip管理其特定依赖。在Ubuntu 20.04上:

# 使用apt安装keystone及其核心依赖(它会自动处理Python版本兼容性) sudo apt update sudo apt install keystone apache2-utils # 检查keystone安装的Python路径,通常是/usr/bin/keystone-manage which keystone-manage # 如果需要额外安装某个库(比如pymysql),指定Python解释器 sudo /usr/bin/python3 -m pip install pymysql

这样做的好处是,apt安装的包经过了发行版维护者的严格测试,版本锁死,不会与系统其他组件冲突。而pip只用于补充那些apt仓库里没有的、Keystone运行时必需的库。我曾帮一个团队解决过一个持续两周的bug:他们的keystone-manage db_sync总在sqlalchemy库上失败,最后发现是有人用pip3 install --upgrade sqlalchemy把版本升到了2.0,而Keystone Wallaby只兼容1.4.x。降级回1.4.48后,问题瞬间消失。教训就是:在OpenStack世界里,新版本不等于好版本,稳定压倒一切。

2.4 网络与防火墙:为API端口打开一扇合规的门

Keystone默认监听两个端口:5000(public API)和35357(admin API)。在旧版OpenStack(如Juno)中,这两个端口是分开的;新版(Queens+)已合并为5000,但35357仍需保留兼容性。很多同学装完后curlhttp://controller:5000返回Connection refused,第一反应是服务没起来,其实90%的情况是防火墙拦住了。

在Ubuntu上,使用ufw:

# 允许5000和35357端口的TCP入站连接 sudo ufw allow 5000/tcp sudo ufw allow 35357/tcp # 重新加载防火墙规则 sudo ufw reload

在CentOS/RHEL上,使用firewalld:

sudo firewall-cmd --permanent --add-port=5000/tcp sudo firewall-cmd --permanent --add-port=35357/tcp sudo firewall-cmd --reload

但比开放端口更重要的是理解端口背后的服务分层逻辑。5000端口面向所有租户用户,提供标准的OpenStack Identity API;35357端口则只应暴露给管理员和内部服务,它提供了更高级的管理接口(如keystone-manage的某些功能)。因此,在生产环境中,35357端口绝不应该对公网开放,甚至不应该对普通计算节点开放,只应允许controller节点自身和network节点访问。这体现了OpenStack最小权限原则:每个服务只拥有完成其任务所必需的最低限度网络权限。

2.5 时间同步:NTP服务是信任链的隐形基石

这是一个绝大多数新手会忽略,但却是导致Keystone最诡异故障的根源——时间不同步。Keystone颁发的JWT(JSON Web Token)包含exp(过期时间)和nbf(生效时间)声明,这些时间戳是基于UTC的。如果controller节点和compute节点的系统时间相差超过5分钟(这是OpenStack的默认容忍阈值),compute节点收到的token就会被判定为“尚未生效”或“已过期”,从而拒绝所有API请求,错误日志里只会显示模糊的Invalid token。

解决方案是强制所有OpenStack节点使用同一个NTP服务器:

# Ubuntu/Debian sudo timedatectl set-ntp on sudo systemctl restart systemd-timesyncd # 或者手动配置NTP客户端(推荐使用国内NTP池) echo "server ntp.aliyun.com iburst" | sudo tee -a /etc/systemd/timesyncd.conf sudo systemctl restart systemd-timesyncd

验证同步状态:

timedatectl status | grep "System clock synchronized" # 输出应为 "yes" ntpq -p # 应能看到一个*号标记的活动NTP源

这个步骤的重要性怎么强调都不为过。它不像数据库或网络配置那样有直观的错误提示,但它会让整个云平台处于一种“亚健康”状态:服务看似都在运行,但资源创建成功率忽高忽低,日志里充斥着无法复现的认证失败。我把它称为“幽灵故障”,而NTP就是驱散这个幽灵的唯一咒语。

2.6 SELinux/AppArmor:安全模块的温柔一刀

在CentOS/RHEL(SELinux)或Ubuntu(AppArmor)上,安全模块默认会阻止Keystone进程访问其所需的文件和端口。如果你在systemctl status keystone里看到Permission denied,或者journalctl -u keystone里有avc: denied字样,那基本可以确定是SELinux在作祟。

临时禁用(仅用于调试):

# CentOS/RHEL sudo setenforce 0 # Ubuntu (AppArmor) sudo systemctl stop apparmor

但这只是治标。永久解决方案是为Keystone创建自定义策略:

# CentOS/RHEL: 生成并安装策略模块 sudo ausearch -m avc -ts recent | audit2allow -M keystone sudo semodule -i keystone.pp

对于实训项目,我建议采用折中方案:在/etc/selinux/config中将SELINUX=enforcing改为SELINUX=permissive。permissive模式下,SELinux依然会记录所有违规操作(写入/var/log/audit/audit.log),但不会阻止进程执行。这既能保证服务正常运行,又能为你提供一份详尽的“安全审计报告”,告诉你Keystone到底需要哪些权限。这份报告,就是你理解OpenStack安全模型的最佳教材。

2.7 管理员凭据:admin_token不是密码,而是启动密钥

admin_token是Keystone安装过程中最常被误解的概念。很多人把它当成一个“管理员密码”,随意设置一个字符串,甚至写在配置文件里明文保存。这是巨大的安全隐患。admin_token的真实身份,是Keystone服务启动时,用于初始化自身数据库和内部服务注册的“一次性启动密钥”。

它的生命周期极短:仅在keystone-manage db_sync和keystone-manage bootstrap(新版)执行期间有效。一旦初始化完成,Keystone就会切换到基于数据库的token持久化机制,admin_token便彻底失效。因此,它的安全性要求是:足够随机,但无需长期保密。

生成方式必须使用密码学安全的随机数生成器:

# 正确:使用openssl生成10字节(20字符)十六进制随机串 ADMIN_TOKEN=$(openssl rand -hex 10) echo $ADMIN_TOKEN # 输出类似:a1b2c3d4e5f678901234 # 错误:使用date或$RANDOM,它们不具备密码学安全性 WRONG_TOKEN=$(date +%s%N | sha256sum | cut -c1-20)

将$ADMIN_TOKEN填入/etc/keystone/keystone.conf的[DEFAULT]区段:

[DEFAULT] admin_token = a1b2c3d4e5f678901234

记住,这只是启动钥匙。初始化完成后,你必须立即删除这一行,或将其注释掉,并改用openstack命令行工具通过admin用户和密码进行认证。这就像汽车的点火钥匙——启动后,你就该把它拔下来收好,而不是一直插在点火开关上。

3. 配置深潜:keystone.conf文件中每一行代码的生存意义

/etc/keystone/keystone.conf不是一份静态的说明书,而是一份动态的“服务契约”。它定义了Keystone如何与外部世界(数据库、消息队列、缓存、其他OpenStack服务)交互,以及它内部各个组件如何协同工作。逐行解读这份文件,是理解OpenStack身份认证体系的捷径。下面,我将带你穿透表层语法,直击每一类配置项背后的设计哲学与实战考量。

3.1[database]区段:连接字符串里的信任与隔离

这是Keystone配置中最核心的一环,决定了它能否“活下来”。连接字符串connection = mysql+pymysql://keystone:YOUR_PASSWORD@controller/keystone,表面看只是数据库地址,实则蕴含三层关键信息:

第一层:协议与驱动选择
mysql+pymysql明确指定了使用PyMySQL这个纯Python实现的MySQL驱动,而非mysqlclient(C扩展)。在容器化或受限环境(如某些Alpine Linux镜像)中,mysqlclient因依赖C编译器而难以安装,PyMySQL就成了唯一可靠的选择。如果你遇到ImportError: No module named 'MySQLdb',十有八九是驱动不匹配。

第二层:用户与权限的精准映射
keystone:YOUR_PASSWORD这部分,必须与你在MySQL中创建的keystone用户完全一致。这里有个反直觉的细节:keystone用户在MySQL中的主机名是'%',但在连接字符串里,@controller中的controller必须能被Keystone进程正确解析为一个IP地址。如果controller解析失败,连接会超时,错误日志里只会显示OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'controller'"),非常误导人。因此,getent hosts controller的验证必须在此步之前完成。

第三层:数据库名的语义约束
/keystone末尾的数据库名,必须与MySQL中CREATE DATABASE keystone的名称严格一致,且区分大小写(在Linux文件系统上)。我曾见过一个案例:管理员在MySQL里创建的是KEYSTONE(全大写),而配置文件里写的是keystone(小写),结果keystone-manage db_sync静默失败,没有任何错误提示,数据库里空空如也。这是因为MySQL在Linux上对数据库名是大小写敏感的。这个细节,完美诠释了OpenStack配置的“零容错”特性——它不帮你做任何智能转换,你给什么,它就信什么。

3.2[token]区段:JWT令牌的生命周期与存储策略

OpenStack Queens之后,Keystone默认使用fernet令牌格式,取代了旧版的uuid和pki。fernet是一种对称加密的轻量级令牌,性能远超pki,且无需复杂的证书管理。配置如下:

[token] provider = fernet driver = sql expiration = 3600
  • provider = fernet:告诉Keystone,生成和验证token时,使用Fernet对称加密算法。这意味着所有运行Keystone服务的节点,必须共享同一套Fernet密钥。密钥存放在/etc/keystone/fernet-keys/目录下,由keystone-manage fernet_setup命令生成。
  • driver = sql:指示Keystone将token的元数据(如创建时间、所属用户)存储在SQL数据库中,而不是内存或memcached。这是为了保证高可用性——即使某个Keystone实例宕机,其他实例也能从数据库中查询到有效的token状态。
  • expiration = 3600:设置token有效期为3600秒(1小时)。这个值不能设得过大,否则一旦管理员密码泄露,攻击者持有的token会长期有效;也不能过小,否则客户端(如Horizon)会频繁要求用户重新登录,体验极差。3600是社区公认的平衡点。

一个关键的实操心得:fernet密钥轮换是必须掌握的技能。密钥文件夹/etc/keystone/fernet-keys/里会有多个编号的密钥文件(如0、1、2)。0号是当前主密钥,用于签发新token;1号是次密钥,用于验证旧token。当执行keystone-manage fernet_rotate时,1号会变成新的0号,旧的0号会变成2号。这个机制保证了在密钥轮换期间,新旧token都能被正确验证,实现了无缝切换。在实训中,你可以手动执行一次轮换,然后观察openstack token issue生成的token是否依然能被openstack user list成功验证。

3.3[cache]区段:Redis不是可选项,而是性能加速器

虽然Keystone可以不配置缓存而运行,但一旦你的云平台用户量超过100,没有缓存的Keystone会成为整个系统的性能瓶颈。[cache]区段的配置,直接决定了API响应速度:

[cache] backend = dogpile.cache.redis backend_argument = url:redis://127.0.0.1:6379/0 expiration_time = 300
  • backend = dogpile.cache.redis:指定了使用Redis作为缓存后端。dogpile.cache是Python的一个通用缓存库,redis是其具体实现。这里不能写成redis,必须是完整的dogpile.cache.redis。
  • backend_argument = url:redis://127.0.0.1:6379/0:Redis连接URL。/0表示使用Redis的第0号数据库。OpenStack官方建议为每个服务分配独立的Redis DB,避免key冲突。例如,Nova用DB 1,Glance用DB 2。
  • expiration_time = 300:缓存项的过期时间,单位为秒。这个值需要根据你的业务场景调整。对于用户信息(user info),300秒(5分钟)很合理,因为用户资料很少实时变更;但对于服务目录(service catalog),可以设为600秒(10分钟),因为服务端点的变更频率更低。

一个血泪教训:在实训环境里,很多人会忽略Redis服务本身的安装和启动。keystone.conf里配好了,但systemctl status redis-server显示inactive。结果就是,Keystone启动时会疯狂重试连接Redis,日志刷屏,而openstack命令行却表现得“一切正常”,只是响应慢得像蜗牛。所以,在配置[cache]之前,请务必先执行:

sudo apt install redis-server sudo systemctl enable redis-server sudo systemctl start redis-server

3.4[identity]与[assignment]区段:用户与角色的权限骨架

这两个区段共同构建了OpenStack的RBAC(基于角色的访问控制)模型。[identity]管理“你是谁”,[assignment]管理“你能做什么”。

[identity] driver = sql # 这行告诉Keystone,用户、租户(project)、域(domain)等身份信息,都存在SQL数据库里 [assignment] driver = sql # 这行告诉Keystone,角色(role)、角色分配(role assignment)、组(group)等权限信息,也存在SQL数据库里

看起来很简单,但这里隐藏着一个重大设计决策:Keystone默认不支持LDAP或AD集成。driver = sql意味着所有用户和角色都必须通过openstack命令行或API手动创建。这对于实训项目是完美的,因为它强迫你亲手搭建起整个权限体系。你可以执行:

# 创建一个名为demo的域 openstack domain create --description "Demo Domain" demo # 在demo域下创建一个名为demo的项目(租户) openstack project create --domain demo --description "Demo Project" demo # 创建一个名为demo的用户,并为其设置密码 openstack user create --domain demo --password-prompt demo # 创建一个名为user的角色 openstack role create user # 将user角色分配给demo用户,在demo项目上 openstack role add --project demo --user demo user

这个过程,就是你在[identity]和[assignment]配置下,亲手绘制出的权限地图。每一条openstack命令,都在数据库里插入了一行记录。理解这一点,你就明白了为什么keystone-manage db_sync是初始化的第一步——它创建了这些数据表的结构,而openstack命令则是往这些表里填充血肉。

3.5[eventlet_server]区段:并发模型的无声革命

OpenStack从Newton版本开始,全面拥抱eventlet协程库,取代了传统的多线程/多进程模型。[eventlet_server]区段正是为此而生:

[eventlet_server] workers = 4 # 设置Keystone服务的worker进程数。通常设为CPU核心数的1-2倍 max_header_line = 16384 # 增大HTTP请求头的最大长度,以支持携带大量token信息的复杂请求

workers = 4这个配置,直接影响Keystone的吞吐量。在单核VM上,设为1即可;在4核的controller节点上,设为4是合理的。但切记,workers不是越多越好。每个worker进程都会消耗内存和数据库连接。如果MySQL的max_connections参数设得太低(默认151),当workers设为8时,Keystone可能因为拿不到数据库连接而卡死。因此,workers的值必须与MySQL的max_connections相匹配,公式是:max_connections >= workers * 2 + 10(预留10个连接给其他管理操作)。

max_header_line = 16384则是一个典型的“踩坑后才懂”的配置。当Keystone与某些前端代理(如HAProxy)或复杂的OAuth2网关集成时,HTTP请求头会变得异常庞大,里面可能嵌套了多层认证信息。默认的8192字节上限会被轻易突破,导致Keystone直接返回400 Bad Request,错误日志里只有一行Request header or cookie too large。把这个值翻倍,是应对现代云原生架构的必备操作。

4. 初始化与验证:从db_sync到openstack user list的完整闭环

当keystone.conf配置完毕,环境准备就绪,真正的考验才刚刚开始。初始化(Initialization)不是一键式的魔法,而是一个需要你全程监控、理解每一步意图的精密手术。下面,我将带你走完从空数据库到可验证API的完整闭环,每一步都附带“为什么这么做”和“如果失败了怎么办”的深度解析。

4.1 数据库同步:keystone-manage db_sync的成败之钥

这是Keystone启动前最关键的一步,它负责在MySQL中创建所有必需的数据表。命令本身只有一行:

sudo keystone-manage db_sync

但它的背后,是SQLAlchemy ORM(对象关系映射)将Python模型类(如User,Project,Role)翻译成SQL DDL(数据定义语言)语句,并在数据库中执行。这个过程的成败,直接取决于前面所有环境配置的正确性。

成功标志:命令执行后,终端无任何输出(静默成功),且MySQL中keystone数据库里出现了数十张表,如user,project,role,assignment,endpoint等。你可以用以下命令快速验证:

mysql -u keystone -p -D keystone -e "SHOW TABLES;" | wc -l # 输出应大于30

常见失败与排错:

  • 错误:ModuleNotFoundError: No module named 'pymysql'
    原因:Python环境缺少MySQL驱动。解决方案:sudo pip3 install pymysql(确保pip3对应的是Keystone使用的Python版本)。
  • 错误:pymysql.err.OperationalError: (1045, "Access denied for user ...")
    原因:keystone.conf中的数据库用户名或密码错误,或MySQL用户权限未正确授予。解决方案:回到2.2节,重新检查GRANT语句和FLUSH PRIVILEGES。
  • 错误:sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) (1146, "Table 'keystone.migrate_version' doesn't exist")
    原因:keystone数据库为空,但db_sync命令期望一个已存在的migrate_version表来跟踪迁移历史。这通常是因为你之前执行过db_sync但失败了,残留了一个不完整的数据库。解决方案:清空并重建数据库:
    DROP DATABASE keystone; CREATE DATABASE keystone CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    然后重试db_sync。

注意:db_sync命令本身不创建数据库,它只在已存在的数据库中创建表。创建数据库是DBA(数据库管理员)的职责,db_sync只是“装修工”。

4.2 Fernet密钥初始化:keystone-manage fernet_setup的不可逆操作

在db_sync成功后,下一步是为fernet令牌机制准备加密密钥。这一步是fernet模式启用的前提:

sudo keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone

这条命令会在/etc/keystone/fernet-keys/目录下生成一个初始密钥文件(通常是0号文件)。--keystone-user和--keystone-group参数确保了生成的密钥文件权限正确(属主为keystone用户),防止其他用户读取。

为什么必须做?
因为fernet令牌的签发和验证,依赖于一个共享的、对称的密钥。没有这个密钥,Keystone无法生成任何有效的token,所有API请求都会失败。fernet_setup就是这个密钥的“诞生仪式”。

一个关键细节:fernet_setup命令不会覆盖已存在的密钥。如果你已经有一个0号密钥,再次运行它,什么也不会发生。这保证了密钥的安全性——你不会因为手抖而意外丢失主密钥。如果你想强制重新生成,必须先手动删除/etc/keystone/fernet-keys/目录下的所有文件。

4.3 Bootstrap初始化:keystone-manage bootstrap的终极授权

这是整个初始化流程的高潮,也是最具“仪式感”的一步。bootstrap命令会执行一系列原子操作,创建管理员用户、服务项目、admin角色,并将admin角色赋予admin用户,同时注册Keystone自身的服务和端点。它相当于为整个OpenStack云平台举行了“加冕礼”。

sudo keystone-manage bootstrap \ --bootstrap-password ADMIN_PASS \ --bootstrap-admin-url http://controller:5000/v3/ \ --bootstrap-internal-url http://controller:5000/v3/ \ --bootstrap-public-url http://controller:5000/v3/ \ --bootstrap-region-id RegionOne
  • --bootstrap-password ADMIN_PASS:这是admin用户的密码,请务必牢记。这是你登录Horizon或使用openstack命令行的唯一凭证。
  • --bootstrap-*-url:这三个URL分别对应Keystone服务的Admin、Internal和Public API端点。在单节点实训中,它们都指向http://controller:5000/v3/。v3是OpenStack Identity API的最新稳定版本,必须显式指定。
  • --bootstrap-region-id RegionOne:RegionOne是OpenStack的默认区域ID。所有服务端点都必须注册到一个区域下,这是多区域部署的基础。

成功标志:命令执行后,终端输出Bootstrap complete.,且openstack命令行可以开始工作。此时,你可以用admin用户获取一个token:

openstack --os-auth-url http://controller:5000/v3 \ --os-project-domain-name Default \ --os-user-domain-name Default \ --os-project-name admin \ --os-username admin \ --os-password ADMIN_PASS \ --os-identity-api-version 3 \ token issue

如果返回一个长长的JWT字符串,恭喜你,Keystone的核心功能已经打通!

4.4 环境变量脚本:admin-openrc的便捷与风险

每次执行openstack命令都输入一长串参数,显然不现实。admin-openrc脚本就是为了解决这个问题而生的。创建它:

cat > admin-openrc << 'EOF' export OS_PROJECT_DOMAIN_NAME=Default export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_NAME=admin export OS_USERNAME=admin export OS_PASSWORD=ADMIN_PASS export OS_AUTH_URL=http://controller:5000/v3 export OS_IDENTITY_API_VERSION=3 export OS_IMAGE_API_VERSION=2 EOF

然后加载它:

source admin-openrc

现在,openstack token issue就能直接工作了。

但这里有一个巨大的安全风险:admin-openrc文件里明文存储了admin密码。如果这个文件被未授权用户读取,整个云平台就沦陷了。因此,在生产环境中,绝对禁止将密码写入admin-openrc。正确的做法是使用OS_PASSWORD环境变量,但密码由用户在shell中手动输入,或者使用更安全的凭据管理工具(如HashiCorp Vault)。在实训环境中,为了教学便利,我们接受这个风险,但你必须清楚地知道:便利性与安全性永远是一对矛盾体,而生产环境必须向安全性妥协。

4.5 全链路验证:用openstack命令行构建你的第一个租户

初始化的最终验证,不是看某个命令是否成功,而是看能否用Keystone提供的API,构建出一个最小但完整的云租户环境。这包括四个核心实体:Domain(域)、Project(项目/租户)、User(用户)、Role(角色)。执行以下命令:

# 1. 创建一个名为demo的域 openstack domain create demo # 2. 在demo域下创建一个名为demo的项目 openstack project create --domain demo demo # 3. 创建一个名为demo的用户,并设置密码(系统会提示你输入) openstack user create --domain demo --password-prompt demo

相关新闻

  • 2026年7月最新宝珀呼和浩特玉泉万达广场维修保养服务电话 - 宝珀官方售后服务中心
  • RAG技术完整学习笔记:从0到1搭建生产级系统
  • 争夺注意力:视觉复杂性在竞争性亲社会众筹平台中的作用

最新新闻

  • VR-Reversal:基于MPV+Lua的实时3D VR视频转2D播放方案
  • MATLAB版车牌识别全流程工程:从图像读取到字符分类,含BP网络训练与实测样本
  • 浮躁的真相:信息战没有赢家,只有被收割的韭菜
  • LLM、Embedding、RAG、Agent、Function Calling、幻觉 完整详解
  • 为什么你的 Agentic AI 跑得快却不敢上生产?权限黑洞与全链路日志才是 2…
  • C++校园失物招领系统毕业设计:从数据库连接池到智能匹配算法

日新闻

  • 佛山青少年训练营推荐:军博营地实力顶尖 - 秋山寄远
  • 如何快速上手PvZ2 Gardendless:免费Web版植物大战僵尸2完整指南
  • jiuwen-deepsearch核心功能详解:规划-检索-反思三合一智能工作流

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号