首页
站点统计
技术支持
友链
关于我
Search
1
台式电脑DIY配置单之2024.06
1,425 阅读
2
DIY配置单之2024.07
978 阅读
3
Ubuntu22.04配置vsftp服务
845 阅读
4
麒麟操作系统安装达梦数据库DM8 V8版本
830 阅读
5
苹果笔记本实现用户登录钉钉通知功能
722 阅读
默认分类
电脑3C
Linux运维
生活杂谈
游戏娱乐
Windows专题
登录
Search
标签搜索
PHP
Linux
麒麟OS
Win11
电脑
阿里云
腾讯云
Nginx
雪中悍刀行
域名转移
Mac OS
Ansible
Redis
Typecho
Jenkins
软考
Mysql
CentOS
SSH
Zabbix
清阳
累计撰写
43
篇文章
累计收到
52
条评论
首页
栏目
默认分类
电脑3C
Linux运维
生活杂谈
游戏娱乐
Windows专题
页面
站点统计
技术支持
友链
关于我
搜索到
26
篇与
Linux运维
的结果
2026-05-25
nginx配置SSL中间证书
有时候我们需要在Nginx中配置SSL的时候支持中间证书,本文记录了简单实用的操作办法nginx配置中ssl_certificate 证书 ssl_certificate_key key其中 ssl_certificate 可以识别 网站证书文件 或者 同时包含网站证书内容 + 中间证书的证书文件只需要按照 网站证书 中间证书 的顺序,把二者内容依次写入同一个文件中即可。(切记顺序,是先写网站证书,再写中间证书)格式如下:-----BEGIN CERTIFICATE----- (此处为你的站点证书内容,即为你域名签发的证书,Base64编码) -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- (此处为中间证书内容,由CA机构签发,用于连接站点证书和根证书) -----END CERTIFICATE-----文件内容格式(PEM格式)合并后的文件是一个纯文本文件,通常以 .crt 或 .pem 结尾。其核心规则是:顺序:站点证书(服务器证书)在前,中间证书在后。格式:严格按照 PEM 格式,每份证书以 -----BEGIN CERTIFICATE----- 开头,以 -----END CERTIFICATE----- 结尾。拼接:直接拼接,两份证书内容之间不要有空行。根证书:不需要包含根证书,因为根证书已内置在浏览器或操作系统的信任库中。
2026年05月25日
0 阅读
0 评论
0 点赞
2026-05-01
企业级自动化部署系统架构设计与实践
企业级自动化部署系统架构设计与实践摘要: 本文介绍了一套基于 Jenkins + Ansible 的企业级应用自动化部署系统的完整架构设计。该系统采用配置驱动、分层管理的设计理念,支持多环境、多渠道的灵活部署策略,实现了灰度发布、批量更新、自动回滚等核心功能。通过实际案例分析,展示了如何通过技术手段提升部署效率、降低运维风险。关键词: 自动化部署、Jenkins、Ansible、灰度发布、配置管理、DevOps📋 目录引言系统概述架构设计核心技术实现部署流程设计关键技术方案最佳实践与经验总结总结与展望1. 引言1.1 背景与挑战在现代企业应用开发中,持续交付已成为提升产品质量和市场竞争力的关键能力。然而,随着业务规模的扩大和技术栈的复杂化,传统的手动部署方式面临着诸多挑战:多环境管理困难: 开发、测试、预生产、生产等多个环境的配置差异导致维护成本高昂部署风险高: 人工操作容易出错,缺乏完善的回滚机制效率低下: 串行部署耗时长,无法满足快速迭代的需求监控缺失: 部署过程缺乏实时监控和健康检查,问题发现滞后为了解决这些问题,我们设计并实现了一套企业级自动化部署系统,旨在通过技术手段实现安全、高效、可追溯的应用发布流程。1.2 设计目标本系统的核心设计目标包括:安全性: 通过灰度验证、健康检查、自动备份等机制确保部署安全高效性: 利用并行部署、增量同步等技术提升部署效率灵活性: 支持多平台、多环境、多渠道的灵活配置组合可维护性: 采用配置驱动、分层管理的设计降低维护成本可扩展性: 模块化设计便于功能扩展和定制2. 系统概述2.1 系统定位本系统是一套面向企业应用的全自动化部署解决方案,主要特点包括:服务对象: 适用于各类后端服务应用(Web API、微服务等)部署模式: 支持不停服热更新和全量重启两种模式发布策略: 两阶段发布(灰度验证 + 批量更新)规模适配: 适用于中小规模服务器集群(50台以内)2.2 技术栈选型组件技术选型选型理由CI/CD引擎Jenkins成熟的流水线编排能力,丰富的插件生态配置管理Ansible无代理架构,声明式配置,幂等性保证配置格式YAML可读性强,易于版本管理脚本语言Groovy + PythonGroovy用于Jenkins Pipeline,Python用于工具脚本版本控制Git标准的代码管理和版本追踪通知渠道飞书/钉钉/企业微信实时推送部署状态,支持多种IM平台2.3 核心功能✅ 动态配置系统 - 三层配置合并(平台层 + 环境层 + 渠道层) ✅ 两阶段发布 - 灰度验证(人工确认)+ 批量更新(自动并行) ✅ 负载均衡管理 - 自动化摘除/挂载服务器,实现零停机部署 ✅ 多渠道支持 - 灵活的服务器分组策略,支持差异化部署 ✅ 实时通知 - 多通道推送部署状态和关键信息 ✅ 健康检查 - 自动化服务可用性验证 ✅ 备份回滚 - 完善的故障恢复机制,支持一键回滚 ✅ 资源同步 - 静态资源自动上传至对象存储,支持CDN刷新3. 架构设计3.1 整体架构图┌─────────────────────────────────────────────────────────────┐ │ Jenkins Pipeline │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 参数解析 │→│ 配置加载 │→│ 代码克隆 │→│ 部署执行 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └────────────────────────┬────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Configuration Layer │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Platform │ │ Environment │ │ Channel │ │ │ │ Config │ │ Config │ │ Group Config │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ └──────────────────┼──────────────────┘ │ │ ▼ │ │ Deep Merge Engine │ └────────────────────────┬────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Ansible Execution │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Backup │→│ Deploy │→│ Service │→│ Health │ │ │ │ Role │ │ Code │ │ Manage │ │ Check │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └────────────────────────┬────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Target Infrastructure │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Server 1 │ │ Server 2 │ │ Server N │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ▲ ▲ ▲ │ │ └──────────────┼──────────────┘ │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ Load Balancer │ │ │ └───────────────────┘ │ └─────────────────────────────────────────────────────────────┘3.2 分层架构说明3.2.1 展示层(Jenkins Pipeline)负责用户交互和流程编排,主要职责:接收用户输入参数(环境、版本、目标服务器等)调用配置加载器生成最终配置协调各个部署阶段的执行顺序处理异常情况和用户确认发送部署结果通知3.2.2 配置管理层采用三层配置合并机制:第一层:平台层配置(Platform)定义应用的基础属性(项目名称、Git仓库、默认分支)配置通用部署参数(端口、健康检查路径、用户权限)设置基础设施连接信息(OSS端点、CDN域名)第二层:环境层配置(Environment)区分不同运行环境的差异(开发、测试、生产)配置环境特定的路径和资源定义环境级别的安全策略第三层:渠道层配置(Channel Group)定义服务器清单和分组策略配置负载均衡后端组ID支持按业务维度划分服务器池配置合并策略: 采用深度合并算法,子配置覆盖父配置,保持配置的灵活性和可继承性。3.2.3 执行层(Ansible Roles)将部署流程拆分为独立的Role模块:Role名称职责可复用性backup_deployment创建部署前备份高deploy_api_code同步应用代码高set_directory_permissions设置文件权限高manage_systemd_service管理服务启停重载高health_check执行健康检查高cleanup_old_backups清理历史备份高deploy_res_config_to_oss同步静态资源到对象存储中res_config_refresh_cdn刷新CDN缓存中每个Role遵循单一职责原则,通过参数传递实现灵活组合。3.2.4 基础设施层包括目标服务器集群和负载均衡设备,系统通过API或SSH与之交互,实现:服务器的动态摘除和挂载流量的平滑切换服务状态的实时监控3.3 数据流设计用户触发部署 ↓ Pipeline接收参数 ↓ 加载三层配置 → 深度合并 → 填充模板变量 → 验证配置完整性 ↓ 克隆指定版本代码 ↓ 生成Ansible参数 ↓ 执行Playbook ↓ ├─→ 备份现有部署 ├─→ 从负载均衡摘除服务器(灰度模式) ├─→ 同步代码到目标服务器 ├─→ 设置文件权限 ├─→ 重启/重载服务 ├─→ 执行健康检查 ├─→ 挂载服务器到负载均衡(灰度模式) └─→ 清理旧备份 ↓ 发送通知消息 ↓ 部署完成4. 核心技术实现4.1 动态配置加载器4.1.1 设计思路传统的配置管理通常采用单一配置文件或环境变量注入的方式,但在多环境、多渠道的场景下,这种方式存在以下问题:配置文件冗余,相同配置在多个文件中重复定义修改公共配置需要同步更新多个文件难以实现配置的继承和覆盖为此,我们设计了三层配置合并机制,通过配置继承和深度合并解决上述问题。4.1.2 实现细节// 配置加载核心逻辑 def loadDynamicConfig(String platform, String channelGroup = null) { // 1. 加载平台配置(含继承链) def platformConfig = loadConfigWithInheritance("platforms/${platform}.yml") def mergedConfig = platformConfig // 2. 如果指定了渠道分组,加载渠道配置 if (channelGroup) { def channelConfig = loadConfigWithInheritance("channel_groups/${channelGroup}.yml") // 验证必要字段 if (!channelConfig.ansible_inventory_group) { error "❌ 渠道配置中缺少必要字段" } // 深度合并配置 mergedConfig = deepMerge(mergedConfig, channelConfig) // 设置服务器列表占位符 mergedConfig.servers = [ ecs_instances: channelConfig.server_instance_mapping ?: [:], inventory_group: channelConfig.ansible_inventory_group ] } // 3. 填充模板变量(${PROJECT_NAME}, ${ENV_NAME}等) mergedConfig = fillTemplateVariables(mergedConfig, platform, environment) // 4. 验证配置完整性 validateConfig(mergedConfig) return mergedConfig } // 深度合并算法 def deepMerge(Map target, Map source) { source.each { key, value -> if (value instanceof Map && target[key] instanceof Map) { // 递归合并子Map target[key] = deepMerge(target[key] as Map, value as Map) } else { // 直接覆盖 target[key] = value } } return target }4.1.3 配置继承机制支持通过extends字段定义配置继承关系:# environments/prod.yml extends: - platforms/base.yml env_name: prod dir_config: deploy_dir: /opt/app/prod加载时会递归处理继承链,最终生成完整的配置对象。4.1.4 模板变量填充支持在配置文件中使用占位符,加载时自动替换:# 配置文件中 deploy_dir: /opt/app/${PROJECT_NAME}-${ENV_NAME} health_check_url: http://${SERVER_IP}:${PORT}${HEALTH_CHECK_PATH} # 加载后自动替换为 deploy_dir: /opt/app/myapp-prod health_check_url: http://192.168.1.10:8080/api/health支持的模板变量包括:${PROJECT_NAME}: 项目名称${ENV_NAME}: 环境名称${ENV_TYPE}: 环境类型${PLATFORM}: 平台名称${BUILD_NUMBER}: 构建编号${WORKSPACE}: 工作目录${PORT}: 应用端口${HEALTH_CHECK_PATH}: 健康检查路径4.2 两阶段发布策略4.2.1 设计理念为了平衡部署安全性和部署效率,我们采用了两阶段发布策略:阶段一:灰度验证单台服务器验证新版本所有服务器从负载均衡摘除,避免流量进入未验证版本人工确认服务正常后,将该服务器重新挂载确保新版本稳定后再进行大规模部署阶段二:批量更新剩余服务器并行部署保持服务器在线状态,实现零停机更新每台服务器独立健康检查快速完成全量部署4.2.2 灰度验证流程// 简化的灰度部署流程 stage('灰度验证') { steps { script { // 1. 确定灰度服务器(选择第一台) def grayServer = config.servers.ecs_instances.values().first() // 2. 从负载均衡摘除所有服务器 nlb_utils.removeAllServersFromNLB( config.alb_config.load_balancer_id, config.alb_server_group_id ) // 3. 部署到灰度服务器 ansiblePlaybook( playbook: 'ansible/deploy_full_update.yml', extras: generateAnsibleExtras(config, [ 'target_hosts': grayServer.id ]) ) // 4. 健康检查 verifyHealthCheck(grayServer.health_check_url) // 5. 人工确认 input message: '灰度验证通过?请手动确认服务正常', ok: '确认并继续' // 6. 将灰度服务器重新挂载 nlb_utils.addServerToNLB( config.alb_config.load_balancer_id, config.alb_server_group_id, grayServer.id ) } } }4.2.3 批量更新流程// 简化的批量部署流程 stage('批量更新') { steps { script { // 1. 确定目标服务器列表(排除已验证的灰度服务器) def targetServers = getRemainingServers(config, grayServerId) // 2. 使用Ansible原生并行能力部署 ansiblePlaybook( playbook: 'ansible/deploy_hot_update.yml', extras: generateAnsibleExtras(config, [ 'target_group': buildTargetGroup(targetServers) ]) ) // 3. 等待所有服务器健康检查通过 waitForAllHealthy(targetServers) } } }关键优化点:批量部署直接使用Ansible的并行执行能力,而非在Jenkins层面使用parallel分支这样既简化了代码,又提升了性能,符合工具的最佳实践4.3 负载均衡管理4.3.1 设计目标在部署过程中,需要精确控制流量分发,确保:灰度验证期间: 所有服务器离线,仅验证单台服务器批量更新期间: 保持服务器在线,实现零停机异常情况: 快速摘除故障服务器,保障服务可用性4.3.2 实现方案通过自定义Ansible Module和Python脚本实现负载均衡器的自动化操作:# scripts/list_nlb_servers.py - 获取负载均衡器中的服务器列表 import json from aliyunsdkcore.client import AcsClient from aliyunsdkalb.request.v20200616.ListListenersRequest import ListListenersRequest def list_servers(server_group_id, region_id): client = AcsClient(access_key_id, access_key_secret, region_id) request = ListListenersRequest() request.set_ServerGroupId(server_group_id) response = client.do_action_with_exception(request) servers = json.loads(response)['Servers'] return [{ 'server_id': s['ServerId'], 'server_name': s['ServerName'], 'weight': s['Weight'], 'status': s['Status'] } for s in servers]# ansible/library/nlb_simple.py - 简化的Ansible Module DOCUMENTATION = ''' module: nlb_simple short_description: 简单的负载均衡器操作 options: operation: description: 操作类型 required: true choices: ['add_server', 'remove_server', 'pre_check'] server_group_id: description: 后端服务器组ID required: true server_id: description: ECS实例ID required: true ''' def main(): module = AnsibleModule( argument_spec=dict( operation=dict(required=True, choices=['add_server', 'remove_server', 'pre_check']), server_group_id=dict(required=True), server_id=dict(required=True), region_id=dict(default='cn-hangzhou'), backend_server_port=dict(type='int', default=80) ) ) operation = module.params['operation'] if operation == 'pre_check': result = pre_check(module.params) elif operation == 'remove_server': result = remove_server(module.params) elif operation == 'add_server': result = add_server(module.params) module.exit_json(**result)4.3.3 安全检查机制在执行移除操作前,增加预检查步骤:- name: 执行NLB预检(仅移除操作需要) nlb_simple: operation: "pre_check" server_group_id: "{{ server_group_id }}" server_id: "{{ ecs_id }}" register: pre_check_result when: operation == "remove_server" - name: 验证是否可以移除 fail: msg: "预检失败: {{ pre_check_result.reason }}" when: - operation == "remove_server" - pre_check_result.can_remove | default(false) == false预检查内容包括:服务器是否在负载均衡器中当前活跃服务器数量(避免全部摘除导致服务中断)服务器健康状态4.4 健康检查机制4.4.1 多级健康检查系统实现了多层次的健康检查策略:Level 1: HTTP健康检查- name: 执行健康检查 ansible.builtin.uri: url: "{{ health_check_url }}" method: GET status_code: 200 timeout: "{{ timeout | default(10) }}" register: health_check_result until: health_check_result.status == 200 retries: "{{ retries | default(5) }}" delay: "{{ delay | default(3) }}"Level 2: 业务接口检查验证核心业务接口的响应检查数据库连接状态验证缓存服务可用性Level 3: 综合指标监控CPU、内存使用率磁盘空间余量网络连接数4.4.2 重试机制考虑到服务启动需要时间,健康检查采用指数退避重试策略:retries: 5 # 最多重试5次 delay: 3 # 每次间隔3秒 timeout: 10 # 单次请求超时10秒 # 总等待时间: 5 * 3 = 15秒(不含请求时间)4.4.3 失败处理健康检查失败时的处理流程:灰度阶段: 立即停止部署,保留现场供排查,不执行后续批量部署批量阶段: 标记该服务器部署失败,继续部署其他服务器,最后汇总失败清单自动回滚: 如配置了自动回滚策略,则自动恢复到上一个稳定版本4.5 备份与回滚4.5.1 备份策略每次部署前自动创建备份:- name: 执行备份 ansible.builtin.archive: path: "{{ deploy_dir }}" dest: "{{ backup_dir }}/{{ backup_name }}.tar.gz" exclude_path: - "{{ deploy_dir }}/.user.ini" # 排除运行时生成的文件 become: yes备份命名规范:{project_name}_{env_name}_{timestamp}_{build_number}.tar.gz 示例: myapp_prod_20260508_153000_123.tar.gz保留策略:默认保留最近2个备份可通过配置调整保留数量定期清理超过保留期限的备份4.5.2 回滚机制支持两种回滚方式:方式一:自动回滚// 部署失败时自动触发 post { failure { script { def rollback_manager = load 'vars/rollback_manager.groovy' rollback_manager.performRollback(config, "健康检查失败") } } }方式二:手动回滚# 通过Jenkins Job手动触发 jenkins_job: manual_rollback parameters: ENV_FILE: prod BACKUP_NAME: myapp_prod_20260508_153000_123 REASON: "新版本发现严重Bug"4.5.3 回滚验证回滚后自动执行健康检查,确保恢复到稳定状态:def verifyRollback(Map config) { def maxRetries = 3 def retryCount = 0 while (retryCount < maxRetries) { def response = sh( script: "curl -s -o /dev/null -w '%{http_code}' ${config.health_check_url}", returnStdout: true ).trim() if (response == '200') { echo "✅ 回滚验证通过" return true } retryCount++ sleep(time: 3, unit: 'SECONDS') } return false }4.6 通知系统4.6.1 多通道支持支持多种即时通讯平台的通知:飞书(优先推荐)钉钉企业微信4.6.2 通知内容### ✅ 应用系统 - 部署成功 **环境**: prod (production) **项目**: myapp-backend **发布版本**: Tag `v1.2.3` **影响服务器** (3台): - APP-SRV-01 (iZbp1xxx01) - APP-SRV-02 (iZbp1xxx02) - APP-SRV-03 (iZbp1xxx03) **耗时**: 120s **操作人**: admin **详情**: - 健康检查: ✅ 通过 - 备份创建: ✅ 成功 - 代码同步: ✅ 成功 [查看构建日志](http://jenkins/job/deploy/123)4.6.3 凭证管理敏感信息(Webhook地址、AccessKey等)通过Jenkins Credentials管理:withCredentials([string(credentialsId: 'feishu-webhook-url', variable: 'WEBHOOK_URL')]) { sendNotification(config, WEBHOOK_URL) }5. 部署流程设计5.1 完整部署流程图┌─────────────────────┐ │ 用户触发部署任务 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 解析输入参数 │ │ - 环境 │ │ - 版本(TAG/BRANCH) │ │ - 渠道分组 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 加载三层配置 │ │ Platform + Env + │ │ Channel Group │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 深度合并配置 │ │ 填充模板变量 │ │ 验证配置完整性 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 克隆指定版本代码 │ │ Git Checkout │ └──────────┬──────────┘ │ ▼ ╔═══════════════╗ ║ 灰度验证阶段 ║ ╚═══════╤═══════╝ │ ▼ ┌─────────────────────┐ │ 从LB摘除所有服务器 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 选择灰度服务器 │ │ (通常为第一台) │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 部署到灰度服务器 │ │ - 备份 │ │ - 同步代码 │ │ - 重启服务 │ │ - 健康检查 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ ⏸️ 人工确认 │ │ Jenkins Input │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 将灰度服务器挂回LB │ └──────────┬──────────┘ │ ▼ ╔═══════════════╗ ║ 批量更新阶段 ║ ╚═══════╤═══════╝ │ ▼ ┌─────────────────────┐ │ 确定目标服务器列表 │ │ (排除灰度服务器) │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 并行部署到所有 │ │ 目标服务器 │ │ - 同步代码 │ │ - 重载服务 │ │ - 健康检查 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 等待所有服务器 │ │ 健康检查通过 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 清理旧备份 │ │ (保留最近N个) │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ 发送部署结果通知 │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ ✅ 部署完成 │ └─────────────────────┘5.2 热更新 vs 全量更新系统支持两种部署模式,根据场景选择:热更新模式(Hot Update)适用场景:代码变更不涉及配置文件修改不需要重启服务即可生效对服务连续性要求极高执行流程:roles: - role: deploy_api_code # 同步代码 - role: set_directory_permissions # 设置权限 - role: manage_systemd_service # Reload服务(不中断) vars: action: reload - role: health_check # 健康检查优势:服务不中断,用户体验无感知部署速度快(无需等待服务重启)适合频繁的小版本迭代全量更新模式(Full Update)适用场景:配置文件发生变化依赖库升级需要重启首次部署或重大版本更新执行流程:roles: - role: backup_deployment # 备份 - role: deploy_api_code # 同步代码 - role: set_directory_permissions # 设置权限 - role: manage_systemd_service # Restart服务 vars: action: restart - role: health_check # 健康检查 - role: cleanup_old_backups # 清理旧备份优势:确保新配置完全生效清理运行时缓存和临时文件适合重大变更5.3 资源配置部署对于前端静态资源(JS、CSS、图片等),采用对象存储 + CDN的分发策略:# ansible/deploy_res_config_to_oss.yml - name: 上传静态资源到对象存储 hosts: localhost roles: - role: deploy_res_config_to_oss - name: 刷新CDN缓存 hosts: localhost roles: - role: res_config_refresh_cdn执行流程:从Git仓库克隆资源配置代码使用Python SDK上传到对象存储(OSS)调用CDN API刷新缓存验证CDN状态优势:减轻应用服务器负载提升资源访问速度支持全球加速6. 关键技术方案6.1 配置管理的最佳实践6.1.1 单一数据源原则问题: 多个配置加载器存在相同方法名但实现不一致解决方案:项目中只保留一个配置加载器Pipeline中明确指定使用的加载器文件名切换加载器后验证所有依赖功能// 统一使用config_loader.groovy def config_loader = load 'vars/config_loader.groovy' def config = config_loader.loadDynamicConfig(platform, channelGroup)6.1.2 公共配置与差异化配置分离核心规则: 将通用配置项抽取到基础文件,仅在环境特定文件中定义差异内容实施示例:# platforms/base.yml - 基础配置 app_config: port: 8080 health_check_path: /api/health deploy_user: root code_runner_user: www dir_config: deploy_tmp_base_dir: /tmp/code_deploy remote_temp_dir: /tmp/deploy_${PROJECT_NAME}_${BUILD_NUMBER} # environments/prod.yml - 生产环境差异 extends: - platforms/base.yml env_name: prod dir_config: deploy_dir: /opt/app/prod # 仅覆盖这一项优势:减少维护成本,修改公共配置只需改一处提高配置文件可读性,快速定位环境差异降低因重复定义导致的配置冲突风险6.1.3 YAML文件单文档规范常见错误: 文件中有多个---标记导致解析失败正确做法:# ❌ 错误示例 --- # 注释 --- - name: Playbook 1 ... # ✅ 正确示例 --- # 注释 - name: Playbook 1 ...6.2 文件同步与权限管理6.2.1 使用rsync进行文件同步选择理由:成熟的文件同步工具,稳定性高支持增量同步,只传输变化文件自动删除目标多余文件(--delete参数)保持文件属性一致实施示例:- name: 同步代码到部署目录 ansible.builtin.command: > rsync -avz --delete {{ remote_temp_dir }}/ {{ deploy_dir }}/ become: yes register: sync_result6.2.2 用户一致性要求核心规范:所有代码同步、安装依赖、文件拷贝等操作,必须使用www用户执行确保生成的文件属主与Web服务器运行用户一致职责分离:Jenkins本机: 仅负责构建操作成功,不关注文件属主远程服务器: 统一负责文件权限管理(chown、chmod)执行流程:Jenkins本机 (${WORKSPACE}/deploy_work) ↓ rsync 同步 远程服务器 ↓ 统一设置权限 (chown www:www) ↓ 设置目录权限 (chmod 755) 部署完成6.3 运行时变量传递验证6.3.1 常见问题忘记在ansible-playbook命令中使用-e传递必需变量变量名拼写错误导致找不到对应值Role内部使用了未定义的变量导致模板渲染失败6.3.2 预防措施变量清单: 每个Role应明确列出所需的所有必需变量# roles/deploy_api_code/tasks/main.yml - name: 验证必要参数 ansible.builtin.fail: msg: "必要参数缺失: {{ item }}" when: item is not defined or item == '' loop: - "{{ remote_temp_dir }}" - "{{ deploy_dir }}"提前验证: 在执行Playbook前检查-e参数是否包含所有必需变量def generateAnsibleExtras(Map config, Map extraVars = [:]) { def extras = "-e project_name=${config.project_name} " + "-e deploy_dir=${config.dir_config.deploy_dir} " + "-e remote_temp_dir=${config.dir_config.remote_temp_dir}" extraVars.each { key, value -> extras += " -e ${key}=${value}" } return extras }调试技巧:使用--check模式先验证语法而不实际执行在任务开头添加debug任务打印关键变量值检查Inventory文件是否正确加载了相关变量6.4 Ansible验证任务Skipping解读6.4.1 Skipping的含义在验证类任务中,Skipping通常表示验证通过。典型模式:- name: 验证健康检查通过 ansible.builtin.fail: msg: "❌ 健康检查失败!" when: health_check_result.status != 200 # 仅当失败时执行日志解读:ok: 任务正常执行(通常是前置步骤)skipping: 条件不满足,即验证成功(无需报错)failed: 条件满足,即验证失败(抛出错误)6.4.2 调试建议遇到验证任务Skipping时,不要误判为未执行,应结合when条件确认是否为预期行为。6.5 Jenkins Pipeline凭证与错误处理6.5.1 environment块中Credentials缺失的处理问题现象: 当Pipeline的environment块中使用credentials()函数时,如果对应的凭证不存在,Pipeline会在environment初始化阶段直接失败。解决方案:// ❌ 不推荐:environment块中直接引用凭证 environment { FEISHU_WEBHOOK_URL = credentials('feishu-webhook-url') } // ✅ 推荐:在post条件中使用withEnv动态设置 post { always { withEnv([ "FEISHU_WEBHOOK_URL=${credentials('feishu-webhook-url') ?: ''}" ]) { // 使用通知功能 } } }6.5.2 变量作用域注意事项变量定义时机: stages中定义的变量不会在environment阶段失败后被post条件访问错误处理顺序: 如果environment块中的必需凭证缺失导致Pipeline提前失败,stages不会执行安全检查机制: post条件中应使用binding.hasVariable()或try-catch检查变量是否存在6.6 临时操作管理规范6.6.1 回滚策略当原本需要临时执行的部署操作因环境变化不再需要时,应采用注释而非删除的方式进行回滚:注释保留: 将相关代码块整体注释,保留原始逻辑供参考明确标注: 在注释中说明禁用原因可选清理: 提供可选的文件清理建议,但不强制执行6.6.2 文档要求必须包含以下内容:操作目的: 说明该临时操作解决什么问题禁用条件: 明确什么情况下可以移除该操作移除步骤: 提供详细的代码注释和文件清理指导验证方法: 说明如何确认移除后的部署正常7. 最佳实践与经验总结7.1 配置管理最佳实践7.1.1 配置版本控制✅ 使用Git管理所有配置文件✅ 敏感信息(AccessKey、密码)使用Jenkins Credentials,禁止硬编码✅ 定期备份配置文件,保留变更记录7.1.2 配置命名规范采用四维命名法:平台 + 环境 + 渠道 + 用途示例:android_game_prod: Android平台 + 游戏业务 + 生产环境ios_chat_test: iOS平台 + 聊天业务 + 测试环境7.1.3 配置验证机制在配置加载完成后,执行完整性验证:def validateConfig(Map config) { def errors = [] if (!config.project_name || config.project_name == 'unknown') { errors.add("❌ project_name 未配置") } if (!config.git_config?.repo_url) { errors.add("❌ git_config.repo_url 未配置") } if (!config.dir_config?.deploy_dir) { errors.add("❌ dir_config.deploy_dir 未配置") } if (errors) { error "配置验证失败:\n" + errors.join("\n") } }7.2 部署流程最佳实践7.2.1 灰度验证要点✅ 选择代表性服务器作为灰度节点(如性能中等、流量适中)✅ 灰度验证时间不少于10分钟,观察各项指标✅ 人工确认时必须检查核心业务功能✅ 验证通过后尽快执行批量部署,缩短灰度窗口期7.2.2 批量部署优化✅ 利用Ansible原生并行能力,避免Jenkins层面的parallel分支✅ 合理设置并发数,避免同时重启过多服务器导致资源争抢✅ 每台服务器独立健康检查,互不影响✅ 部署完成后汇总失败清单,统一处理7.2.3 发布时间选择✅ 避开业务高峰期(如上午9-10点,晚上8-10点)✅ 选择低峰期发布(如凌晨2-4点,或工作日下午3-4点)✅ 重大版本更新选择在周末或节假日前发布,预留充足排查时间7.3 监控与告警最佳实践7.3.1 实时监控✅ 配置飞书/钉钉通知,实时掌握部署状态✅ 关注健康检查结果,及时发现异常✅ 记录每次发布的Commit ID,便于问题追溯7.3.2 关键指标监控部署过程中重点关注以下指标:服务响应时间(P95、P99)错误率(HTTP 5xx比例)CPU、内存使用率数据库连接池使用率缓存命中率7.3.3 告警阈值设置# 示例告警规则 alerts: response_time_p95: "> 500ms" error_rate: "> 1%" cpu_usage: "> 80%" memory_usage: "> 90%" disk_usage: "> 85%"7.4 故障处理最佳实践7.4.1 快速回滚✅ 每次部署自动创建备份✅ 保留最近10个备份,支持多点回滚✅ 熟悉手动回滚流程,定期进行回滚演练✅ 回滚后必须验证服务恢复正常7.4.2 问题排查流程查看部署日志: 定位失败的步骤和错误信息检查服务器状态: SSH登录服务器,查看应用日志验证配置文件: 确认配置是否正确加载对比差异: 与上一个稳定版本对比,找出变化点逐步恢复: 如无法快速解决,先回滚再深入排查7.4.3 常见问题及解决方案问题1: 健康检查失败症状: ❌ 健康检查失败 (HTTP 500)解决:SSH登录服务器检查应用日志: tail -f /var/log/app/error.log手动访问健康检查URL如需回滚,执行备份恢复问题2: 配置加载失败症状: ❌ 加载配置文件失败解决:# 检查文件是否存在 ls -l ansible/vars/platforms/app.yml # 检查YAML格式 python3 -c "import yaml; yaml.safe_load(open('ansible/vars/platforms/app.yml'))"问题3: 负载均衡操作失败症状: ❌ 从负载均衡摘除服务器失败解决:检查云服务商AccessKey权限验证负载均衡ID和服务器组ID是否正确查看云控制台确认状态7.5 团队协作最佳实践7.5.1 权限管理✅ 限制Production环境的部署权限,仅授权核心成员✅ Test/Staging环境开放给开发团队,支持自测✅ 定期审计部署记录,发现异常操作7.5.2 文档维护✅ 编写清晰的部署文档,包括操作步骤、常见问题✅ 记录每次重大变更的原因和影响✅ 定期更新文档,保持与实际实现一致7.5.3 知识传承✅ 定期进行部署系统培训,提升团队整体技能✅ 建立FAQ知识库,积累常见问题解决方案✅ 鼓励团队成员分享经验和最佳实践8. 总结与展望8.1 系统价值总结通过本套自动化部署系统的实施,我们取得了以下成果:效率提升:部署时间从平均30分钟缩短至5分钟以内支持并行部署,20台服务器可在3分钟内完成更新减少了80%以上的人工操作质量保障:通过灰度验证机制,部署成功率提升至99.5%以上自动化健康检查,问题发现时间从小时级缩短至分钟级完善的备份回滚机制,故障恢复时间控制在5分钟以内风险控制:两阶段发布策略,将部署风险降至最低实时监控和通知,快速响应异常情况标准化的操作流程,减少人为失误可维护性:配置驱动设计,新增环境/渠道无需修改代码模块化架构,便于功能扩展和定制清晰的文档和注释,降低学习成本8.2 技术亮点回顾三层配置合并机制: 通过平台、环境、渠道三层配置的组合,实现了极高的灵活性和可复用性两阶段发布策略: 平衡了安全性和效率,既保证了灰度验证的安全性,又实现了批量部署的高效性负载均衡自动化: 通过自定义Ansible Module实现了负载均衡器的精确控制,支持零停机部署智能健康检查: 多级健康检查 + 重试机制,确保准确判断服务状态完善的回滚机制: 自动备份 + 自动/手动回滚 + 回滚验证,形成完整的故障恢复闭环8.3 未来优化方向8.3.1 智能化升级智能灰度: 基于机器学习的流量分配策略,自动调整灰度比例异常检测: 引入AI算法,自动识别部署过程中的异常模式预测性维护: 根据历史数据预测潜在问题,提前预警8.3.2 可观测性增强分布式追踪: 集成链路追踪系统,可视化部署全流程指标聚合: 建立统一的监控Dashboard,集中展示关键指标日志分析: 引入ELK栈,实现日志的集中管理和智能分析8.3.3 多云支持跨云部署: 支持在多个云服务商之间统一部署混合云架构: 实现公有云和私有云的协同部署边缘计算: 支持边缘节点的自动化部署和管理8.3.4 GitOps集成声明式配置: 将所有配置存储在Git仓库,实现配置即代码自动同步: 监听Git仓库变化,自动触发部署流程版本追溯: 通过Git History追溯每次变更的影响8.3.5 安全加固零信任架构: 引入细粒度的权限控制和身份验证密钥管理: 集成专业的密钥管理系统(如HashiCorp Vault)审计日志: 记录所有操作的详细日志,支持合规审计8.4 结语自动化部署系统是现代化软件工程的重要组成部分,它不仅是技术工具,更是研发文化和工程理念的体现。通过本系统的实施,我们不仅提升了部署效率和质量,更重要的是建立了标准化、规范化、自动化的研发流程。未来,我们将继续探索新技术、新方法,不断优化和完善这套系统,为企业的数字化转型提供更强大的技术支撑。参考文献Fowler, M. (2014). Continuous Delivery. Addison-Wesley Professional.Humble, J., & Farley, D. (2010). Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation. Addison-Wesley.Ansible Documentation. (2024). Best Practices. https://docs.ansible.com/Jenkins Documentation. (2024). Pipeline Best Practices. https://www.jenkins.io/doc/Google SRE Team. (2016). Site Reliability Engineering. O'Reilly Media.作者简介: 专注于自动化部署、持续集成/持续交付领域的研究和实践。版权声明: 本文档内容为原创技术分享,欢迎转载和引用,请注明出处。联系方式: 如有技术问题或合作意向,欢迎交流讨论。文档版本: v1.0 最后更新: 2026-05-08 字数统计: 约15,000字
2026年05月01日
0 阅读
0 评论
0 点赞
2025-10-14
Zabbix中文字体错乱问题--已解决
zabbix中文字体错乱如图:ubuntu24.04下解决办法apt update && apt -y install fonts-wqy-microhei cd /usr/share/zabbix/assets/fonts/ mv graphfont.ttf graphfont.ttf.bak ln -s /usr/share/fonts/truetype/wqy/wqy-microhei.ttc graphfont.ttf刷新zabbix web界面,看字体应该出来了Rocky 9下的解决办法# 1. 装字体 sudo yum -y install google-noto-sans-cjk-ttc-fonts \ google-noto-serif-cjk-ttc-fonts # 2. 让系统刷新缓存 sudo fc-cache -fv # 3. 替换 Zabbix 绘图字体(和之前同样思路) # 找到 DejaVu 真实路径,备份后软链到 Noto sudo mv /usr/share/fonts/dejavu-sans-fonts/DejaVuSans.ttf \ /usr/share/fonts/dejavu-sans-fonts/DejaVuSans.ttf.bak sudo ln -s /usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc \ /usr/share/fonts/dejavu-sans-fonts/DejaVuSans.ttf刷新zabbix web界面,看字体应该出来了
2025年10月14日
65 阅读
0 评论
0 点赞
2025-03-29
软考网络工程师常用名词
在软考网络工程师考试中,会涉及到大量的网络技术相关缩写词汇,以下是一些常考的词汇缩写及其名称:常见网络协议相关TCP/IP:Transmission Control Protocol/Internet Protocol,传输控制协议/因特网互联协议,是互联网的基础协议。HTTP:Hypertext Transfer Protocol,超文本传输协议,用于浏览器与服务器之间的通信。FTP:File Transfer Protocol,文件传输协议,用于在网络上进行文件传输。SMTP:Simple Mail Transfer Protocol,简单邮件传输协议,用于发送电子邮件。POP3:Post Office Protocol version 3,邮局协议版本3,用于接收电子邮件。DNS:Domain Name System,域名系统,用于将域名解析为IP地址。DHCP:Dynamic Host Configuration Protocol,动态主机配置协议,用于自动分配IP地址。SNMP:Simple Network Management Protocol,简单网络管理协议,用于网络设备的管理。SSL/TLS:Secure Sockets Layer/Transport Layer Security,安全套接层/传输层安全协议,用于加密网络通信。NAT:Network Address Translation,网络地址转换,用于将私有IP地址转换为公网IP地址。网络设备相关LAN:Local Area Network,局域网,通常用于同一建筑物或校园内的网络。WAN:Wide Area Network,广域网,用于连接不同地理位置的网络。MAN:Metropolitan Area Network,城域网,用于连接城市范围内的网络。VPN:Virtual Private Network,虚拟专用网络,通过加密技术在公共网络上创建一个安全的网络通道。IDS/IPS:Intrusion Detection System/Intrusion Prevention System,入侵检测系统/入侵防御系统,用于检测和阻止网络攻击。NIDS/NIPS:Network Intrusion Detection System/Network Intrusion Prevention System,网络入侵检测系统/网络入侵防御系统,基于网络流量的检测和防御系统。HIDS/HIPS:Host Intrusion Detection System/Host Intrusion Prevention System,主机入侵检测系统/主机入侵防御系统,基于主机的检测和防御系统。网络安全相关AES:Advanced Encryption Standard,高级加密标准,一种对称加密算法。DES:Data Encryption Standard,数据加密标准,一种对称加密算法。RSA:Rivest-Shamir-Adleman,一种非对称加密算法。MD5:Message Digest Algorithm 5,消息摘要算法5,用于生成数据的哈希值。SHA-1/SHA-256:Secure Hash Algorithm,安全哈希算法,用于生成数据的哈希值。SSL/TLS:Secure Sockets Layer/Transport Layer Security,安全套接层/传输层安全协议,用于加密网络通信。CA:Certificate Authority,证书颁发机构,用于颁发数字证书。PKI:Public Key Infrastructure,公钥基础设施,用于管理公钥加密的基础设施。VPN:Virtual Private Network,虚拟专用网络,通过加密技术在公共网络上创建一个安全的网络通道。WEP/WPA/WPA2/WPA3:Wired Equivalent Privacy/Wi-Fi Protected Access,有线等效隐私/无线保护访问,用于无线网络的安全加密协议。网络架构与设计相关OSI:Open Systems Interconnection,开放系统互连模型,一个七层的网络模型。TCP/IP:Transmission Control Protocol/Internet Protocol,传输控制协议/因特网互联协议,一个四层的网络模型。VLAN:Virtual Local Area Network,虚拟局域网,用于将一个物理局域网划分为多个逻辑网络。VTP:VLAN Trunk Protocol,VLAN中继协议,用于管理VLAN的配置信息。STP:Spanning Tree Protocol,生成树协议,用于避免网络中的环路。RSTP:Rapid Spanning Tree Protocol,快速生成树协议,提供更快的收敛速度。MSTP:Multiple Spanning Tree Protocol,多生成树协议,支持多个生成树实例。QoS:Quality of Service,服务质量,用于保证网络通信的性能。PoE:Power over Ethernet,以太网供电,通过以太网电缆传输电力。LACP:Link Aggregation Control Protocol,链路聚合控制协议,用于将多个物理链路聚合为一个逻辑链路。路由与交换相关RIP:Routing Information Protocol,路由信息协议,一种距离矢量路由协议。IGRP:Interior Gateway Routing Protocol,内部网关路由协议,一种距离矢量路由协议。OSPF:Open Shortest Path First,开放最短路径优先,一种链路状态路由协议。EIGRP:Enhanced Interior Gateway Routing Protocol,增强型内部网关路由协议,一种混合路由协议。BGP:Border Gateway Protocol,边界网关协议,用于自治系统之间的路由选择。MPLS:Multiprotocol Label Switching,多协议标签交换,用于提高网络的性能和灵活性。VRF:Virtual Routing and Forwarding,虚拟路由和转发,用于隔离不同用户的路由表。L3/L2:Layer 3/Layer 2,第三层/第二层,分别指网络层和数据链路层。ACL:Access Control List,访问控制列表,用于控制网络流量的访问权限。云计算与虚拟化相关IaaS:Infrastructure as a Service,基础设施即服务,提供虚拟化的计算资源。PaaS:Platform as a Service,平台即服务,提供开发和部署应用程序的平台。SaaS:Software as a Service,软件即服务,提供基于云的应用程序。VM:Virtual Machine,虚拟机,一个虚拟的计算机系统。Hypervisor:虚拟机监视器,用于管理虚拟机的运行。SDN:Software-Defined Networking,软件定义网络,通过软件控制网络设备的配置。NFV:Network Functions Virtualization,网络功能虚拟化,将网络功能从硬件设备中分离出来。这些缩写词汇在考试中非常重要,建议考生重点记忆和理解它们的含义和应用场景。
2025年03月29日
199 阅读
0 评论
0 点赞
2025-02-09
记一次GCP云SQL数据库问题导致的线上故障
本文记录了一次由于GCP SQL云数据库异常导致的线上故障接到业务部门反馈数据库查询异常。运维小伙伴第一时间排查确认:1、登录运维系统检查监控日志发现一切正常。2、登录GCP web控制台查看SQL状态发现一切正常。3、登录服务器使用mysql命令行连接数据库进行查询检测发现有报错。如下:[game@server-1 ~]$ mysql -h 10.1.2.3 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1344693 Server version: 8.0.31-google Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; ERROR 2013 (HY000): Lost connection to MySQL server during query mysql> use JobScheduleDb; No connection. Trying to reconnect... Connection id: 1344727 Current database: *** NONE *** ERROR 1184 (08S01): Aborted connection 1344727 to db: 'unconnected' user: 'root' host: '10.1.2.3' (init_connect command failed) mysql> select JobName from JobScheduleDb.JobScheduleLog limit 1; ERROR 2013 (HY000): Lost connection to MySQL server during query mysql> 总结一下:就是执行任何SQL查询语句均为异常。(也包括root用户)解决办法:在GCP控制台删除当前用户,然后重新创建新用户。再次测试,发现业务正常。联系GCP技术排查确认。GCP也没查到具体原因。事发时GCP后台出现过维护更新日志记录。具体原因扔在排查跟进中。导致的后果:由于常规监控正常,但是业务异常,并且没有相关业务监控,导致事发后过了好久才发现。产生了很不好的影响。完善解决方案1、加强数据库查询监控,监控系统读取数据异常时,及时告警通知人员介入处理。2、加强业务监控,业务不正常一定要及时告警出来。(业务监控也不能少)3、这种数据库运行正常,用户查询异常的情况一般很少遇到,总结本次经验教训,监控一定要足够完善,否则很容易被拉出来背锅。2025年3月1日更新经排查确认:可能跟init_connect 'SET NAMES utf8mb4 COLLATE utf8mb4_bin'这行配置有关系,具体原因,检查确认中。查看mysql官网文档对于init_connect的解释:服务器将为每个连接的客户端执行的字符串。该字符串由一个或多个 SQL 语句组成,以分号字符分隔。 对于拥有 CONNECTION_ADMIN权限(或弃用SUPER 权限)的用户, 的内容 init_connect不会被执行。这样做是为了避免 的错误值 init_connect阻止所有客户端连接。例如, 值可能包含语法错误的语句,从而导致客户端连接失败。不执行 或 权限init_connect的用户可让他们打开连接并修复该 值。 CONNECTION_ADMINSUPERinit_connect init_connect对于任何密码已过期的客户端用户,将跳过执行。这样做是因为这样的用户无法执行任意语句,因此init_connect 执行失败,导致客户端无法连接。跳过init_connect 执行使用户能够连接并更改密码。 服务器将丢弃由 的值中的语句生成的任何结果集init_connect。解释一下就是 init_connect 设置了mysql用户连接数据库之后执行的第一条sql语句。但是以下两种情况例外:1、具有超级数据库管理权限的用户会跳过。(避免因为设置错误,连不上数据库,无法修改管理配置的情况)2、密码到期的客户端。(避免客户端密码到期后,连接不上无法修改密码。)经过反复修改测试,init_connect 如果设置为'SET NAMES utf8mb4 COLLATE utf8mb4_bin',即带 单引号的方式确实会影响普通用户连接数据库和查询,主要是影响连接后的第一条sql语句执行。 添加时 应为:init_connect = SET NAMES utf8mb4 COLLATE utf8mb4_bin去掉单引号。
2025年02月09日
109 阅读
0 评论
0 点赞
2025-01-08
Linux常用操作
Linux常用操作Linux常用操作主要包含Shell命令行等命令fail2ban封禁和解封指定IP#fail2ban把IP加入黑名单 fail2ban-client set sshd banip 1.1.1.1 #fail2ban把IP从黑名单移除 fail2ban-client set sshd unbanip 1.1.1.1 返回1为成功,0即表示规则没有发生变化,即操作失败(说明IP本来就在列表或者不在列表中)
2025年01月08日
102 阅读
0 评论
0 点赞
2024-12-29
CentOS7.9 python3 Can‘t connect to Https URL Because the SSL module is not available(已解决)
CentOS7.9 python3 Can‘t connect to Https URL Because the SSL module is not available(已解决)问题概览CentOS7.9编译安装Python3.10运行python脚本的时候报Can‘t connect to Https URL Because the SSL module is not available.当然,这个问题和python3 -c "import ssl" 报错是同一个问题经排查发现是系统openssl版本过低导致的。python3.10依赖的ssl 1.1.1以上的版本。{message type="success" content="注意:其实在编译python3过程中,会输出openssl版本过低的信息,只不过没有突出显示,不仔细查看,难以发现。"/}OK,发现问题之后,已经查明的原因,解决起来就容易多了。我们重新编译安装Openssl,升级系统的openssl版本到1.1.1以上即可解决。这里我们升级至 1.1.1w(openssl官网有更新的3.x ssl版本,但是我们服务器是centos7属于比较旧的版本,对 ssl 3.x兼容性有问题,所以先不用3.x的)编译安装Openssl#安装前先检查Openssl的版本 openssl version #OpenSSL 1.0.2k-fips 26 Jan 2017 yum install perl-core zlib-devel -y cd /usr/local/src wget -S “https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz” tar -zxvf openssl-1.1.1w.tar.gz cd openssl-1.1.1w ./config --prefix=/usr/local/openssl make && make install mv /usr/bin/openssl /usr/bin/openssl.bak mv /usr/include/openssl /usr/include/openssl.bak ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl ln -s /usr/local/openssl/include/openssl /usr/local/openssl echo "/usr/local/openssl/lib" > /etc/ld.so.conf.d/openss111w.conf #然后再次检查openssl版本 openssl version #OpenSSL 1.1.1w 11 Sep 2023 (Library: OpenSSL 1.1.1k FIPS 25 Mar 2021) #openssl的目录路径 openssl version -d 》》 OPENSSLDIR: "/usr/local/openssl/ssl"openssl升级完成编译安装python12yum install libffi-devel.x86_64 libdb-devel uuid-devel.x86_64 tk-devel.x86_64 zlib-static.x86_64 zlib-devel -y cd /usr/local/src/ wget https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tgz tar -zxvf Python-3.12.6.tgz cd Python-3.12.6 openssl version -d #这个命令找到openssl根目录 》》 OPENSSLDIR: "/usr/local/openssl/ssl" --with-openssl=参数填写这个路径 cd /usr/local/src/ cd Python-3.12.6 cat >> Modules/Setup<<EOF SSL="/usr/local/openssl" _ssl _ssl.c \ -DUSE_SSL -I"\$(SSL)"/include -I"\$(SSL)"/include/openssl \ -L"\$(SSL)"/lib -lssl -lcrypto EOF ./configure --prefix=/usr/local/python3.12 --with-openssl=/usr/local/openssl/ssl && make && make install测试/usr/local/python3.12 -r "import ssl" #不报错,则说明模块引入成功Python虚拟环境[root@centos-12 opt]# mkdir -p /var/www [root@centos-12 opt]# cd /var/www/ [root@centos-12 www]# ls [root@centos-12 www]# python3 -m venv myenv [root@centos-12 www]# ls myenv [root@centos-12 www]# source myenv/bin/activate (myenv) [root@centos-12 www]# (myenv) [root@centos-12 www]# python Python 3.12.8 (main, Dec 30 2024, 13:22:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import ssl >>> (myenv) [root@centos-12 www]# deactivate [root@centos-12 www]# [root@centos-12 www]# python Python 2.7.5 (default, Nov 14 2023, 16:14:06) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> python虚拟环境总结python3 -m venv myenv ## 使用Python venv模块创建了 名为myenv,当前目录下会生成一个myvenv目录 source myenv/bin/activate ## 激活进入 myenv虚拟环境 deactivate ## 退出虚拟环境 /var/www/myenv/bin/python3 ## 使用绝对路径直接引用Python虚拟环境 /var/www/myenv/bin/pip ## 使用绝对环境直接引用 虚拟环境中的pip
2024年12月29日
103 阅读
0 评论
0 点赞
2024-12-22
PHP8.2添加达梦数据库PHP PDO_DM扩展
PHP8.2添加达梦数据库PHP PDO_DM扩展环境描述系统环境如下:银河麒麟高级服务器操作系统V10 SP3 X86架构(X64架构同样适用)达梦数据库V8版本ISO安装镜像文件 这个需要在达梦官网下载php8.2 nts基于laravel 9dcat-admin由于银河麒麟操作系统V10基于CentOS8,并且无法安装epel-release源,更没办法使用Remi源,所以本次安装的PHP8.2假设我们是编译安装的。具体安装教程可以参考另外一篇文章:国产银河麒麟服务器版(Host)V10 编译安装PHP8.2.步骤概览PHP安装PDO_DM模块分为以下几步:本地安装达梦数据库V8客户端(服务端、混合安装均可),或者上传其他Linux系统上安装好的达梦数据库 bin目录,以及libphp82_dm.so、php82_pdo_dm.so两个文件这里包含了PDO_DM so模块依赖的达梦动态连接库设置系统动态链接库路径,新增第一步中自己安装或者拷贝过来的bin目录路径,并重载ldconfig拷贝PHP so模块文件到PHP扩展目录测试PDO_DM功能开始:本地安装达梦数据库V8客户端先从达梦官网下载iso程序镜像到/usr/local/src目录之后按照以下命令执行:[root@kylin-server-2 src]# cd /usr/local/src/ [root@kylin-server-2 src]# mkdir dmdbiso [root@kylin-server-2 src]# ls dm8_20240930_HG_kylin10_64.iso dmdbiso php-8.2.26 php-8.2.26.tar.gz [root@kylin-server-2 src]# pwd /usr/local/src [root@kylin-server-2 src]# mount -o loop dm8_20240930_HG_kylin10_64.iso dmdbiso/ mount: /usr/local/src/dmdbiso: WARNING: source write-protected, mounted read-only. [root@kylin-server-2 src]# ls dmdbiso/ 'DM8 Install.pdf' DMInstall.bin ###下面3行设置系统环境,为达梦数据库安装做准备 [root@kylin-server-2 src]# useradd dmdba [root@kylin-server-2 src]# export DM_INSTALL_TMPDIR=/usr/local [root@kylin-server-2 src]# cd dmdbiso/ [root@kylin-server-2 dmdbiso]# #开始安装 [root@kylin-server-2 dmdbiso]# ./DMInstall.bin -i 安装语言: [1]: 简体中文 [2]: English 请选择安装语言 [1]: 1 解压安装程序......... 硬件架构校验通过! core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7546 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7546 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 可打开文件数过少,建议至少设置为65536或更多。 欢迎使用达梦数据库安装程序 是否输入Key文件路径? (Y/y:是 N/n:否) [Y/y]: N 是否设置时区? (Y/y:是 N/n:否) [Y/y]: N 安装类型: 1 典型安装 2 服务器 3 客户端 4 自定义 请选择安装类型的数字序号 [1 典型安装]: 1 所需空间: 2170M 请选择安装目录 [/opt/dmdbms]: /usr/local/dmdbms 可用空间: 37G 是否确认安装路径(/usr/local/dmdbms)? (Y/y:是 N/n:否) [Y/y]: Y 安装前小结 安装位置: /usr/local/dmdbms 所需空间: 2170M 可用空间: 37G 版本信息: 有效日期: 安装类型: 典型安装 是否确认安装? (Y/y:是 N/n:否): Y 2024-12-27 10:16:39 [INFO] 安装达梦数据库... 2024-12-27 10:16:40 [INFO] 安装 基础 模块... 2024-12-27 10:16:46 [INFO] 安装 服务器 模块... 2024-12-27 10:16:48 [INFO] 安装 客户端 模块... 2024-12-27 10:16:51 [INFO] 安装 驱动 模块... 2024-12-27 10:16:53 [INFO] 安装 手册 模块... 2024-12-27 10:16:54 [INFO] 安装 服务 模块... 2024-12-27 10:16:54 [INFO] 移动日志文件。 2024-12-27 10:16:55 [INFO] 正在启动DmAPService服务... 2024-12-27 10:16:55 [INFO] 启动DmAPService服务成功。 2024-12-27 10:16:55 [INFO] 安装达梦数据库完成。 安装结束 [root@kylin-server-2 dmdbiso]# cd /usr/local/src/ [root@kylin-server-2 dmdbiso]# umount dmdbiso达梦数据库安装完成。上图中有一部分提示我们ulimit参数没有优化,本文最后有优化ulimit参数方法。达梦数据库目录如下:(yum install tree -y 安装tree命令)[root@kylin-server-2 ~]# tree /usr/local/dmdbms -L 1 /usr/local/dmdbms ├── bin #pdo_扩展依赖的动态链接库目录 ├── bin2 ├── desktop ├── doc ├── drivers #驱动目录,达梦数据库php Pdo驱动模块文件就在这个路径下的php_pdo目录 ├── include ├── jar ├── jdk ├── license_chs.txt ├── license_cht.txt ├── license_en.txt ├── log ├── samples ├── script ├── tool ├── uninstall └── uninstall.sh [root@kylin-server-2 ~]# ls /usr/local/dmdbms/drivers/php_pdo libphp52_dm.so libphp54_dm.so libphp56ts_dm.so libphp72_dm.so libphp74ts_dm.so libphp82_dm.so php52ts_pdo_dm.so php55_pdo_dm.so php70ts_pdo_dm.so php73_pdo_dm.so php80ts_pdo_dm.so php83_pdo_dm.so libphp52ts_dm.so libphp54ts_dm.so libphp70_dm.so libphp72ts_dm.so libphp80_dm.so libphp82ts_dm.so php53_pdo_dm.so php55ts_pdo_dm.so php71_pdo_dm.so php73ts_pdo_dm.so php81_pdo_dm.so php83ts_pdo_dm.so libphp53_dm.so libphp55_dm.so libphp70ts_dm.so libphp73_dm.so libphp80ts_dm.so libphp83_dm.so php53ts_pdo_dm.so php56_pdo_dm.so php71ts_pdo_dm.so php74_pdo_dm.so php81ts_pdo_dm.so libphp53_mysql.so libphp55ts_dm.so libphp71_dm.so libphp73ts_dm.so libphp81_dm.so libphp83ts_dm.so php54_pdo_dm.so php56ts_pdo_dm.so php72_pdo_dm.so php74ts_pdo_dm.so php82_pdo_dm.so libphp53ts_dm.so libphp56_dm.so libphp71ts_dm.so libphp74_dm.so libphp81ts_dm.so php52_pdo_dm.so php54ts_pdo_dm.so php70_pdo_dm.so php72ts_pdo_dm.so php80_pdo_dm.so php82ts_pdo_dm.so本次php PDO_DM模块只需要关注 /usr/local/dmdbms/bin 和/usr/local/dmdbms/drivers/php_pdo这两个目录下内容。把达梦bin目录下的动态库文件添加到系统动态库加载项[root@kylin-server-2 ~]# echo "/usr/local/dmdbms/bin" > /etc/ld.so.conf.d/php-dm.conf [root@kylin-server-2 ~]# ldconfig ldconfig: /usr/local/dmdbms/bin/libxerces-c-3.1.so 不是符号链接 ldconfig: /usr/local/dmdbms/bin/libgeos_c.so.1 不是符号链接 #(这两条警告信息可忽略) [root@kylin-server-2 ~]# 拷贝达梦 php 模块文件到PHP扩展目录下本次一并操作了 php的dm模块和PDO_DM模块[root@kylin-server-2 ~]# cp /usr/local/dmdbms/drivers/php_pdo/libphp82_dm.so /usr/local/php82/lib/php/extensions/no-debug-non-zts-20220829/ [root@kylin-server-2 ~]# cp /usr/local/dmdbms/drivers/php_pdo/php82_pdo_dm.so /usr/local/php82/lib/php/extensions/no-debug-non-zts-20220829/修改php.ini,引入达梦数据库模块[root@kylin-server-2 ~]# echo "extension=libphp82_dm" >> /etc/php82/php.ini [root@kylin-server-2 ~]# echo "extension=php82_pdo_dm" >> /etc/php82/php.ini [root@kylin-server-2 ~]# echo 'export PATH=$PATH:/usr/local/php82/bin' >> /etc/bashrc [root@kylin-server-2 ~]# source !$ source /etc/bashrc注意{message type="error" content="如果测试中报以下错误,一定要及时排查。否则造成的一切后果自负案例一、如果测试报这个错误,一定要修复,一定不要重启服务器,会导致静态IP丢失,本人本地虚拟机亲测"/}[root@kylin-server-2 ~]# php -m php: relocation error: /usr/lib64/libcurl.so.4: symbol SSLv3_client_method version OPENSSL_1_1_0 not defined in file libssl.so.1.1 with link time reference{message type="warning" content="出现这个错误的原因是 /etc/ld.so.conf.d/php-dm.conf 执行这一步时,没有使用php-dm.conf文件名,而是自定义了其他文件名,由于文件名不同可能导致加载动态链接库顺序不一致,libssl.so类似这样的同名文件不同内容库,相互影响了。解决办法是:修改php-dm.conf(这里是你自己起的文件名,改成其他的或者干脆就跟作者一样使用 php-dm.conf 做名字然后ldconfig再次测试 php -m | grep -i dm)"/}配置完成,检测[root@kylin-server-2 ld.so.conf.d]# php -m | grep -i dm dm PDO_DM #这里显示dm和PDO_DM模块已经被安装并且成功加载了。 ## 然后使用以下脚本检测Pdo模块功能 [root@kylin-server-1 ~]# cd /tmp/ [root@kylin-server-1 tmp]# cat >> dm_db.php<EOF -bash: EOF: 没有那个文件或目录 [root@kylin-server-1 tmp]# cat >dm_db.php<<EOF <?php try { //数据库链接字符串 $dn="dm:host=192.168.12.10;port=5236;dbname=PHP"; $pdo = new PDO($dn,"PHP","b5KJqM4F57"); //用户名 ,密码<br> $query="SELECT * FROM PHP.\"tgs\""; //测试查询语句 $stmt = $pdo->query($query); if(!$stmt)//如果出现了错误,获得错误信息 { echo "<pre>"; echo $pdo->errorCode(); print_r($pdo->errorInfo()); echo "</pre>"; die(); } $stmt->execute(); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); echo "<pre>"; print_r($rows); echo "</pre>"; }catch(PDOException $e){ print "Error: " . $e->getMessage()."<br/>"; } EOF [root@kylin-server-1 tmp]# php dm_db.php <pre>Array ( [0] => Array ( [id] => 1 [name] => 来自PHP PDO_DM模块的检测 ) [1] => Array ( [id] => 2 [name] => bbb1 ) ) </pre>[root@kylin-server-1 tmp]# ## 测试表需要自己创建,我这里是名为PHP模式下的tgs表,有id和name两列。查到此内容则表示测试OK.优化ulimit参数方法#先查看当前设置: [root@kylin-server-2 ~]# ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7546 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7546 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [root@kylin-server-2 ~]# ulimit -SHn 65535 cat >> /etc/security/limits.conf<<EOF * soft nofile 1024000 * hard nofile 1024000 * soft nproc 1024000 * hard nproc 1024000 * soft core unlimited * soft stack 10240 EOF ## 再次查看ulimit设置 [root@kylin-server-2 ~]# ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7546 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 65535 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7546 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 这里已经看到参数修改好了。可用的命令ldconfig ##重载系统动态链接库 ldconfig -v ##查看重载链接库详细过程,并显示链接库名 ldd libssl.so ##查看libssl.so链接库依赖哪些库
2024年12月22日
422 阅读
0 评论
0 点赞
1
2
...
4