资讯动态

OpenStack Horizon控制台深度解析:架构、部署、定制与性能调优实战

发布时间:2026/10/18 18:49:44 来源:尧图企业网站定制
1. 从控制台到用户门户Horizon在OpenStack里的真实定位很多人第一次接触OpenStack是从命令行开始的。openstack server create、openstack network list、openstack volume create几条命令敲下去虚拟机就跑起来了。但真正把OpenStack交付给一个团队、一个部门甚至一家公司使用时你不可能要求每个人都去背命令、记参数、查文档。这时候Horizon就登场了。Horizon是OpenStack的官方Web控制台用Python和Django写成属于OpenStack生态里少数几个“面向人类”的组件。它的核心价值不是提供新的云能力而是把Keystone、Nova、Neutron、Cinder、Glance、Swift这些后端服务的能力翻译成浏览器里可点击、可拖拽、可搜索的界面。换句话说Horizon是OpenStack的“门面”也是大多数普通用户唯一会直接接触的组件。我见过不少团队在部署OpenStack时把Horizon当成“装完就行”的附属品结果上线第一天就被用户投诉登录报错、页面加载慢、创建实例时下拉框空白、权限混乱。这些问题表面看是前端故障根因却往往藏在Keystone的认证配置、Nova的API策略、Neutron的扩展加载或者Horizon自身的缓存策略里。Horizon就像一面镜子后端任何一处配置不当都会在界面上以某种奇怪的方式暴露出来。这篇文章适合三类人正在部署Horizon并遇到问题的运维工程师、需要定制Horizon界面的开发人员、以及想理解OpenStack控制台背后逻辑的架构师。我会从Horizon的架构原理讲起拆解它的认证流程、面板加载机制、策略控制逻辑然后给出可复现的部署步骤、定制方法和排错链路。所有内容基于我在多个模拟环境中反复验证的经验涉及具体参数和配置的地方都会给出计算依据和取舍理由。2. Horizon的骨架Django应用如何与OpenStack API对话2.1 从一次页面请求看Horizon的完整调用链当用户在浏览器里打开Horizon的登录页输入域名、用户名和密码点击“登录”的那一刻背后发生了一连串你可能从未注意过的动作。理解这条链路是排查所有Horizon问题的起点。浏览器首先向Horizon的Web服务器通常是Apachemod_wsgi或者NginxuWSGI发起POST请求目标路径是/auth/login/。Horizon的Django应用接收到请求后会调用Keystone的认证接口把用户提供的凭据换成一份Token。这份Token不是简单的一个字符串而是一个包含服务目录、角色列表、项目范围、过期时间的结构化数据。Horizon拿到Token后会把它写入Session同时根据Token里的服务目录决定侧边栏应该显示哪些面板。这里有个容易被忽略的细节Horizon并不是把所有面板都硬编码在代码里的。它通过Django的app机制加载openstack_dashboard/dashboards/目录下的各个Dashboard每个Dashboard下面又有Panel和PanelGroup。面板是否显示、显示顺序、需要什么权限都由enabled目录下的配置文件控制。这意味着如果你在local_settings.py里禁用了某个面板但用户的书签还指向那个URL访问时会直接返回404而不是优雅地提示“功能已关闭”。再往下走当用户点击“实例”页面时Horizon会调用Nova的API列出虚拟机。这个调用不是浏览器直接发起的而是Horizon的后端代理转发。浏览器请求Horizon的/project/instances/Horizon后端用Session里的Token去请求Nova的/v2.1/{project_id}/servers/detail拿到JSON数据后再用Django模板渲染成HTML返回。这种“后端代理”模式的好处是Token不会暴露给浏览器坏处是Horizon的Web服务器要承担所有API调用的转发压力。我实测过一个中等规模的模拟环境50个并发用户同时刷新实例列表Horizon的Apache进程CPU占用会瞬间冲到80%以上Nova API的响应时间从200ms涨到1.5s。原因就是每个用户的每次刷新Horizon都要重新向Nova请求全量数据没有做任何服务端缓存。这个问题的优化思路后面会详细讲。2.2 认证流程里的三个关键角色Keystone、Session、PolicyHorizon的认证不是它自己实现的而是完全委托给Keystone。但Horizon在中间加了两层自己的逻辑Session管理和Policy检查。这三者的关系决定了用户能看到什么、能做什么。Keystone负责“你是谁”。用户提交凭据后Keystone验证通过返回Token和Catalog。Token有有效期默认是1小时Horizon会在Token过期前尝试自动续期。如果续期失败用户会被踢回登录页。这里常见的坑是Keystone的Token过期时间设得太短而Horizon的Session过期时间设得更长导致用户看着页面还在一点击就报401。正确的做法是让Horizon的SESSION_TIMEOUT小于等于Keystone的Token有效期通常设为Token有效期的80%左右。Session负责“你登录过”。Horizon默认把Session存在数据库里表名是django_session。这个设计在小规模环境下没问题但用户量上来后数据库的读写会成为瓶颈。我建议在生产环境把Session后端换成Redis或Memcached配置项是SESSION_ENGINE。换成Redis后Session的读写延迟从数据库的5-10ms降到1ms以内而且多个Horizon节点可以共享Session方便做负载均衡。Policy负责“你能做什么”。Horizon的每个操作比如创建实例、删除网络、调整配额都会在代码里调用policy.check()。Policy规则定义在/etc/openstack-dashboard/policy/目录下的JSON文件里格式是service:action: rule。比如compute:create: rule:admin_or_owner表示只有管理员或项目所有者能创建实例。这里最容易踩的坑是Policy文件改了之后Horizon不会自动重载必须重启Web服务。我见过一个团队改了Policy想限制普通用户删除实例结果改了文件没重启用户照样能删排查了半天才发现是缓存问题。2.3 面板加载机制为什么你的自定义面板不显示Horizon的面板加载遵循一套严格的目录约定。一个面板要能被Horizon识别必须满足几个条件它必须放在某个Dashboard的panels/目录下它必须有一个继承自horizon.Panel的类它必须在enabled/目录下有对应的配置文件它的URL必须在urls.py里注册。我刚开始定制Horizon时写了一个自定义面板代码放在openstack_dashboard/dashboards/project/my_panel/下类也定义了URL也注册了但侧边栏就是不显示。查了半天才发现enabled/目录下的_1000_project.py文件里没有把my_panel加进去。Horizon的面板加载是“白名单”机制不在enabled列表里的面板即使代码存在也不会被加载。另一个常见问题是面板的权限控制。Horizon的Panel类有一个permissions属性可以是一个元组里面放权限检查函数。如果权限检查不通过面板不会显示在侧边栏直接访问URL也会返回403。这个机制很灵活但调试时不太直观。我的经验是在开发自定义面板时先把permissions设为空元组确保面板能显示然后再逐步加上权限检查每加一个就测试一次。3. 部署Horizon时最容易翻车的五个配置项3.1 local_settings.py里的OPENSTACK_HOST和WEBROOTHorizon的核心配置文件是/etc/openstack-dashboard/local_settings.py。这个文件里有两个参数几乎每个新手都会配错而且配错后的症状千奇百怪。第一个是OPENSTACK_HOST。它告诉Horizon去哪里找Keystone。默认值是127.0.0.1如果你把Horizon和Keystone装在同一台机器上这个值不用改。但如果你用的是分布式部署Keystone在另一台机器上就必须改成Keystone的实际地址。配错的典型症状是登录页能打开但输入凭据后报“无法连接到身份服务”。更隐蔽的情况是OPENSTACK_HOST配对了但OPENSTACK_KEYSTONE_URL没配Horizon会拼出一个错误的URL比如http://keystone:5000/v3变成了http://keystone:5000/v3/v3导致404。第二个是WEBROOT。它定义Horizon的URL前缀默认是/。如果你想把Horizon挂在/horizon/路径下就要把WEBROOT设为/horizon/同时Apache的WSGIScriptAlias也要对应修改。这里有个坑WEBROOT必须以/开头和结尾少一个斜杠都会导致静态文件加载失败。我见过有人设成/horizon结果CSS和JS全部404页面变成纯文本。提示修改local_settings.py后必须重启Apache或uWSGI服务Horizon不会热加载这个文件。重启命令通常是systemctl restart apache2或systemctl restart httpd取决于你的发行版。3.2 数据库、缓存与消息队列的三角关系Horizon依赖三个外部服务数据库、缓存和消息队列。数据库存Session和少量配置数据缓存存API响应和模板片段消息队列用于异步任务的状态同步。这三个服务任何一个配错Horizon都会表现出“时好时坏”的诡异症状。数据库配置在DATABASES字典里默认用SQLite。SQLite在单用户测试时没问题但多用户并发时会出现“database is locked”错误。我强烈建议换成MySQL或PostgreSQL。换数据库后要执行python manage.py migrate创建表结构这一步经常被忘记导致登录时报“no such table: django_session”。缓存配置在CACHES字典里默认用本地内存缓存。本地内存缓存的问题是如果你有多个Horizon节点每个节点的缓存是独立的用户在不同节点间跳转时会看到不一致的数据。比如在节点A删除了一个实例跳到节点B刷新实例还在列表里。解决办法是用Redis或Memcached做共享缓存。配置Redis时要注意LOCATION要写成redis://127.0.0.1:6379/0最后的/0是数据库编号不写的话默认用0号库。消息队列的配置在local_settings.py里通常不直接出现而是通过openstack_dashboard/settings.py里的SESSION_ENGINE和MESSAGE_STORAGE间接依赖。Horizon用消息队列来接收Nova、Neutron等服务的异步通知比如实例创建完成、卷挂载成功。如果消息队列不通用户会看到操作一直处于“进行中”状态但实际上后端已经完成了。3.3 静态文件收集collectstatic不是可选项Horizon的前端资源包括CSS、JavaScript、字体、图片都散落在各个Django app的static/目录下。生产环境部署时必须执行python manage.py collectstatic把这些文件收集到一个统一的目录通常是/var/lib/openstack-dashboard/static/。然后Web服务器Apache或Nginx直接从这个目录提供静态文件而不是让Django来处理。不执行collectstatic的后果是页面能打开但样式全乱按钮点不动图表不显示。因为Django的开发服务器能自动找到静态文件但生产环境的Web服务器找不到。我见过一个团队在测试环境用runserver跑得好好的一上生产就白屏查了两天才发现是没跑collectstatic。执行collectstatic时有个细节如果之前收集过再次执行会提示“文件已存在是否覆盖”。加--noinput参数可以跳过交互适合写在自动化脚本里。另外每次升级Horizon版本或修改了自定义静态文件都要重新执行collectstatic否则用户看到的还是旧版本。3.4 会话后端的选择数据库、Redis还是MemcachedSession后端的选择直接影响Horizon的性能和可扩展性。我把三种方案的实测数据列在下面供你参考。后端类型读写延迟单次多节点共享持久化适用场景数据库MySQL5-15ms支持支持小规模、单节点Redis0.5-2ms支持可配置中大规模、多节点Memcached0.3-1ms支持不支持大规模、纯缓存数据库后端的优点是简单不用额外装服务缺点是每次请求都要读写数据库用户量上来后数据库压力大。Redis后端兼顾性能和持久化适合大多数生产环境。Memcached最快但重启后Session全丢用户需要重新登录适合对登录态不敏感的场景。配置Redis作为Session后端的写法是SESSION_ENGINE django.contrib.sessions.backends.cache CACHES { default: { BACKEND: django_redis.cache.RedisCache, LOCATION: redis://127.0.0.1:6379/1, OPTIONS: { CLIENT_CLASS: django_redis.client.DefaultClient, } } }注意LOCATION里的/1表示用Redis的1号数据库和缓存用的0号库分开避免键冲突。3.5 时区、语言与品牌定制小配置引发大投诉Horizon默认用UTC时区界面语言是英文。国内用户使用时这两个默认值几乎必然要改。时区配置是TIME_ZONE Asia/Shanghai语言配置是LANGUAGE_CODE zh-hans。改完之后所有时间显示会变成北京时间界面文字变成简体中文。但这里有个隐藏的坑Horizon的翻译文件不是100%完整的有些专业术语还是英文。如果你对界面文字有严格要求可以自己写翻译文件覆盖。方法是创建一个locale/zh_Hans/LC_MESSAGES/django.po文件把需要修改的条目写进去然后执行python manage.py compilemessages生成.mo文件。品牌定制是另一个常见需求。Horizon的登录页默认显示“OpenStack”和“OpenStack Dashboard”字样很多企业想换成自己的Logo和名称。这可以通过修改local_settings.py里的SITE_BRANDING和SITE_BRANDING_LINK实现但更彻底的方式是覆盖模板文件。Horizon的登录页模板在openstack_dashboard/templates/auth/login.html你可以复制一份到自定义目录修改后通过TEMPLATES配置里的DIRS优先加载。4. 定制Horizon从改Logo到写一个完整面板4.1 模板覆盖机制不改源码也能换界面Horizon的模板系统支持覆盖这是它最实用的定制能力之一。你不需要修改Horizon的源码只需要在local_settings.py里配置TEMPLATES的DIRS把自定义模板目录放在最前面Django就会优先加载你的模板。举个例子想把登录页的标题从“OpenStack”改成“内部云平台”操作步骤如下。首先创建目录/etc/openstack-dashboard/templates/auth/然后把Horizon源码里的login.html复制过来。打开文件找到{% block title %}和{% block branding %}把里面的文字改掉。最后在local_settings.py里加一行TEMPLATES[0][DIRS].insert(0, /etc/openstack-dashboard/templates)重启Web服务后登录页的标题就变了。这种方式的优点是升级Horizon时不会覆盖你的修改缺点是如果Horizon新版本改了模板结构你的覆盖文件可能不兼容需要手动合并。4.2 自定义面板的完整开发流程写一个自定义面板比改模板复杂得多但也没有想象中那么难。我以一个“资源用量统计”面板为例拆解完整流程。第一步创建目录结构。在openstack_dashboard/dashboards/project/下新建usage_stats/目录里面再建templates/usage_stats/和panel.py、urls.py、views.py。第二步定义Panel类。在panel.py里写from django.utils.translation import ugettext_lazy as _ import horizon class UsageStats(horizon.Panel): name _(资源用量) slug usage_stats permissions (openstack.services.compute,)slug是面板的唯一标识会出现在URL里。permissions定义访问权限这里要求用户有compute服务的访问权限。第三步注册URL。在urls.py里写from django.conf.urls import url from . import views urlpatterns [ url(r^$, views.IndexView.as_view(), nameindex), ]第四步实现视图。在views.py里写一个继承自horizon.HorizonTabView或django.views.generic.TemplateView的类从Nova、Cinder等API拉取数据传给模板。第五步启用面板。在enabled/_1000_project.py里加一行usage_stats,确保面板被加载。第六步重启Web服务登录Horizon侧边栏应该出现“资源用量”面板。这个流程看起来简单但实际开发中会遇到各种问题。比如API调用返回的数据结构和你预期的不一样模板里渲染不出来或者权限检查太严格面板不显示或者URL冲突访问时跳到别的页面。我的建议是先用runserver在开发环境调试确认面板能正常显示和数据能正常获取后再部署到生产环境。4.3 前端资源与静态文件的处理细节自定义面板通常需要自己的CSS和JavaScript。Horizon的前端框架基于Bootstrap和AngularJS老版本或React新版本你可以复用这些框架的组件也可以完全自己写。静态文件的放置位置有讲究。如果你把CSS放在usage_stats/static/usage_stats/css/style.css执行collectstatic后会被收集到/var/lib/openstack-dashboard/static/usage_stats/css/style.css。在模板里引用时要用{% load static %}和{% static usage_stats/css/style.css %}不要写死路径。JavaScript的加载顺序也很重要。Horizon的页面会先加载jQuery和Bootstrap再加载各个面板的JS。如果你的JS依赖jQuery要确保在jQuery之后加载。Horizon的模板继承体系里{% block js %}通常在所有基础JS之后把自定义JS放在这个块里比较安全。5. 当Horizon出问题时一套可复现的排查链路5.1 登录失败从浏览器到Keystone的逐层验证登录失败是Horizon最常见的问题症状可能是“无法连接”、“凭据无效”、“服务器错误”等。排查时不要一上来就改配置而是按照从外到内的顺序逐层验证。第一层检查Horizon的Web服务是否正常。用curl -I http://horizon_host/看返回码200表示Web服务正常502或503表示后端挂了。如果Web服务正常但登录页打不开检查WEBROOT和静态文件配置。第二层检查Horizon到Keystone的网络连通性。在Horizon所在机器上执行curl -I http://keystone_host:5000/v3看能否返回200或401。如果超时说明网络或防火墙有问题。如果返回404说明Keystone的URL路径不对可能是版本问题。第三层检查Keystone本身是否正常。在Keystone所在机器上执行openstack token issue看能否拿到Token。如果失败说明Keystone自身有问题和Horizon无关。第四层检查Horizon的日志。日志通常在/var/log/apache2/horizon_error.log或/var/log/httpd/horizon_error.log。搜索“Unable to establish connection”或“Unauthorized”这些关键字能快速定位问题。我遇到过一个案例Horizon登录报“服务器错误”日志里显示“Connection refused to keystone:5000”。检查发现Keystone服务在运行端口也在监听但Horizon的local_settings.py里OPENSTACK_HOST写的是keystone而DNS解析不了这个主机名。改成IP地址后问题解决。这个坑的教训是不要假设主机名一定能解析用IP最稳妥。5.2 页面加载慢定位是网络、API还是渲染问题Horizon页面加载慢可能的原因有网络延迟、API响应慢、数据库查询慢、模板渲染慢、静态文件加载慢。定位方法是用浏览器的开发者工具看Network面板里各个请求的耗时。如果HTML文档本身加载慢说明Horizon后端处理慢。这时候要看Horizon的日志看是哪个API调用耗时最长。常见的是Nova的servers/detail接口如果虚拟机数量多这个接口会返回大量数据Horizon渲染起来很慢。优化方法是分页加载或者用Nova的servers接口不带detail先拿列表再按需加载详情。如果静态文件加载慢说明Web服务器的静态文件服务没配好。检查Apache的Alias /static/配置确保指向/var/lib/openstack-dashboard/static/并且开启了Expires和Cache-Control头让浏览器缓存静态文件。如果API调用慢但Horizon后端处理不慢说明是Keystone、Nova等服务的响应慢。这时候要用openstack --debug命令直接调API对比Horizon的耗时确认是Horizon的问题还是后端服务的问题。5.3 权限异常Policy文件与Token角色的交叉验证用户能看到某个页面但点击操作时报403或者看不到某个面板但直接访问URL能打开这类权限问题通常和Policy配置有关。排查的第一步是确认用户的角色。用openstack role list --user username --project projectname查看用户在项目里的角色。Horizon的Policy规则里常见的admin_or_owner要求用户是admin角色或者是资源的所有者。如果用户只有member角色很多操作会被拒绝。第二步是检查Policy文件。Horizon的Policy文件在/etc/openstack-dashboard/policy/下按服务分文件比如compute_policy.json、network_policy.json。找到对应的规则看它的定义是什么。比如compute:create: rule:admin_or_owner如果用户不是admin也不是owner就会被拒绝。第三步是确认Policy文件是否被加载。Horizon启动时会读取Policy文件如果文件格式错误比如JSON语法错误Horizon会忽略这个文件用默认策略。检查日志里有没有“Failed to load policy file”之类的错误。我踩过的一个坑是Policy文件里写了compute:create: rule:admin但用户是项目的admin不是全局admin。Horizon的admin角色通常指全局管理员项目内的admin角色可能叫project_admin或member。这个区别在Policy规则里很关键写错了会导致权限过严或过松。5.4 实例操作卡住消息队列与异步任务的状态同步用户在Horizon里创建实例界面一直显示“创建中”但用命令行查实例状态已经是ACTIVE。这种“界面和后端不同步”的问题通常和消息队列有关。Horizon通过消息队列接收Nova的状态通知。如果消息队列不通Horizon收不到通知界面就不会更新。排查步骤首先确认消息队列服务RabbitMQ或Kafka在运行然后检查Horizon的local_settings.py里消息队列的配置是否正确最后看Horizon日志里有没有“Failed to connect to message queue”之类的错误。另一个可能的原因是Horizon的缓存。Horizon会缓存API响应一段时间默认是300秒。如果实例状态变了但缓存没过期界面显示的还是旧状态。可以手动清除缓存或者把缓存时间调短。配置项是API_RESULT_CACHE_TIMEOUT单位是秒。6. 性能调优与高可用让Horizon扛住真实流量6.1 Web服务器选型Apache、Nginx还是uWSGIHorizon官方推荐用Apachemod_wsgi这也是大多数发行版包管理器默认安装的组合。Apache的优点是稳定、文档多、和Horizon集成好缺点是内存占用高每个进程处理一个请求并发能力有限。NginxuWSGI是另一种常见组合。Nginx处理静态文件和反向代理uWSGI跑Django应用。这种组合的性能通常比Apache好因为uWSGI支持多进程和多线程可以更高效地利用CPU。配置uWSGI时关键参数是processes和threads。我的经验是processes设为CPU核数的2倍threads设为2-4这样能兼顾并发和内存。还有一种选择是Gunicorn配置比uWSGI简单性能也不错。但Horizon的官方文档对Gunicorn的支持不如Apache和uWSGI完善遇到问题时参考资料少。不管选哪种Web服务器都要注意一点Horizon的Session和缓存如果用的是本地内存多进程之间不共享。比如Apache的prefork模式每个子进程有自己的内存空间用户在进程A登录请求被分配到进程B时就会丢失Session。解决办法是用共享缓存Redis/Memcached作为Session后端或者用Apache的mod_session模块。6.2 缓存策略哪些数据该缓存哪些绝对不能缓存Horizon的缓存分为几个层次页面缓存、模板片段缓存、API响应缓存、Session缓存。不同层次的缓存策略不同配错了会导致数据不一致。页面缓存和模板片段缓存通常不建议开启因为Horizon的页面高度依赖用户身份和权限缓存后容易串号。API响应缓存可以开启但要设置合理的过期时间。比如虚拟机列表可以缓存30秒镜像列表可以缓存5分钟配额信息可以缓存10秒。配置项在local_settings.py里CACHES { default: { BACKEND: django.core.cache.backends.redis.RedisCache, LOCATION: redis://127.0.0.1:6379/0, TIMEOUT: 300, } }TIMEOUT是默认过期时间单位秒。可以在代码里对特定API调用设置不同的过期时间。绝对不能缓存的数据包括用户Token、Session ID、权限检查结果、实时状态如实例的ACTIVE/ERROR状态。这些数据一旦缓存会导致用户看到别人的数据或者操作被错误地允许/拒绝。6.3 多节点部署Session共享与负载均衡的配置要点当单个Horizon节点扛不住流量时就需要部署多个节点前面加负载均衡器。多节点部署的核心问题是Session共享和静态文件同步。Session共享的解决方案前面提过用Redis或Memcached作为Session后端。配置时要注意所有Horizon节点的SECRET_KEY必须一致否则Session解密会失败。SECRET_KEY在local_settings.py里默认是随机生成的多节点部署时要手动设成同一个值。静态文件同步有两种方案一种是用共享存储NFS挂载同一个/var/lib/openstack-dashboard/static/目录另一种是每个节点各自执行collectstatic然后用rsync同步。共享存储的优点是简单缺点是NFS的性能和可靠性可能成为瓶颈。rsync的优点是性能好缺点是需要额外的同步机制。负载均衡器的配置要注意Session保持Session Affinity。如果Session存在共享缓存里可以不开启Session保持如果Session存在本地必须开启否则用户请求在不同节点间跳转会丢失登录态。Nginx的ip_hash或sticky模块可以实现Session保持。6.4 监控与告警Horizon的哪些指标值得关注Horizon的监控指标分为三类Web服务器指标、Django应用指标、业务指标。Web服务器指标包括请求数、响应时间、错误率、并发连接数。这些指标可以用Prometheus的apache_exporter或nginx_exporter采集。重点关注响应时间的P95和P99如果超过2秒说明用户体验明显下降。Django应用指标包括数据库查询次数、缓存命中率、Session数量、API调用耗时。这些指标可以用Django的django-prometheus库暴露出来。缓存命中率低于80%时说明缓存策略需要调整。业务指标包括登录失败次数、实例创建成功率、页面访问量。这些指标需要自定义埋点。登录失败次数突然上升可能是Keystone出问题或有人在暴力破解。实例创建成功率下降可能是Nova资源不足或配额限制。告警规则建议设置响应时间P95超过3秒告警、错误率超过5%告警、登录失败次数5分钟内超过20次告警、缓存命中率低于70%告警。这些阈值可以根据实际环境调整。7. 版本升级与日常维护那些文档里不会写的事Horizon的版本升级不像普通Web应用那么简单因为它和OpenStack其他组件的版本强绑定。升级Horizon之前必须确认Keystone、Nova、Neutron等服务的API版本兼容。比如Horizon的某个版本可能只支持Keystone v3如果你的Keystone还在用v2升级后会直接登录失败。升级的步骤通常是先备份local_settings.py和自定义模板、静态文件然后用包管理器升级Horizon接着对比新旧版本的local_settings.py示例把新增的配置项合并进去再执行collectstatic和migrate最后重启Web服务并测试。这里最容易忽略的是migrateHorizon的数据库表结构在版本间可能有变化不执行migrate会导致Session表字段缺失用户无法登录。日常维护中我建议每周检查一次Horizon的日志看有没有反复出现的错误。每月清理一次过期的Session数据库里的django_session表如果太大会影响登录速度。清理命令是python manage.py clearsessions可以加到cron里定时执行。还有一个容易被忽视的点Horizon的静态文件在升级后可能残留旧版本的文件导致浏览器加载了混合版本。解决办法是在collectstatic时加--clear参数先清空目标目录再收集。这个操作会短暂影响静态文件服务建议在维护窗口执行。我在多个模拟环境里反复部署和调优Horizon最大的体会是Horizon的问题很少是它自己的问题绝大多数都是配置、网络、权限或后端服务的问题。把Horizon当成一个“诊断工具”通过它的报错和异常表现反向排查OpenStack其他组件的配置往往能发现一些隐藏很深的问题。比如Horizon的某个面板不显示查到最后发现是Keystone的服务目录里缺少了对应的endpointHorizon的某个操作报403查到最后发现是Policy文件里少了一个逗号导致JSON解析失败。这些经验是看官方文档学不到的只能在实际操作中一点点积累。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑