游戏服务全生命周期管理:代码提交镜像构建完成→配置同步→环境部署→运行监控→故障恢复的完整链路
运维API功能说明、使用场景和调用方式:
生命周期管理入口:统一处理开发、测试、部署、运维全阶段的操作请求
轻量级 Python Web 框架,提供 RESTful API 接口服务。通过装饰器模式定义路由,支持请求参数验证和响应格式化。
基于文件锁的并发控制,防止同一环境的操作冲突。每个接口操作创建独立的锁文件,确保操作的原子性。
Supervisor 守护进程管理,支持自动重启、日志轮转。配置多 Worker 进程处理并发请求。
生命周期核心控制:编排配置变更、版本发布、环境切换、数据管理等关键流程
管理 Kustomize 配置仓库,支持动态修改 YAML 配置文件。实现配置版本控制、自动提交推送,是 GitOps 的基础。
通过 ArgoCD API 实现应用同步控制。监听 Git 仓库变更,自动触发 K8s 资源更新,实现声明式部署。
管理游戏服务启停顺序,实现优雅关闭。通过多线程并发监控 Pod 日志,确保服务状态正确。
生命周期基础支撑:提供容器运行、数据存储、网络通信等服务运行的底层保障
游戏服务容器化运行平台。通过 SSH 远程执行 kubectl 命令,管理 GameServerSet、Deployment、Service、ConfigMap 等资源。
MySQL 存储游戏数据,Redis 提供高速缓存。支持自动备份、恢复、清档、增量更新等数据管理操作。
<company2> <storage1> 存储游戏资源文件,CDN 加速内容分发。支持资源预热、刷新,优化玩家访问体验。
实际运维中的典型场景和技术实现细节 - 新运维人员胜任该岗位的必知必会(4个场景5个故障)
当游戏需要新增战斗服务器组件时,需要在多个配置点进行修改,确保新组件能被正确管理。
# 1. 修改 Flask 应用配置,添加新组件到服务列表
app.config['server'] = (
'gforge-gateway',
'gforge-game',
'gforge-battle', # 新增战斗服务
'gforge-chat',
...
)
# 2. 在 Git 仓库中添加 K8s 部署配置
# overlays/dev/deploy-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gforge-battle
spec:
replicas: 2
template:
spec:
containers:
- name: gforge-battle
image: <registry1>/<company1>/gforge-battle
env:
- name: SERVER_ID
value: "battle"
# 3. 添加初始化 SQL(如需要)
# init_db_sql/init_server_battle.sql
CREATE TABLE IF NOT EXISTS `battle_room` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`room_id` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
添加新的运维接口时,需要遵循现有的装饰器模式和错误处理机制,确保接口的一致性和可靠性。
# 添加新的 API 接口示例:游戏活动管理
@app.route('/activity-manage', methods=["POST"])
@file_lock() # 使用文件锁装饰器防止并发
def activity_manage():
''' 管理游戏活动的开启和关闭 '''
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
_results = {}
# 获取请求参数
project = flask.request.values.get('project')
env = flask.request.values.get('env')
activity_id = flask.request.values.get('activity_id')
action = flask.request.values.get('action') # start/stop
try:
# 参数验证
if not project in current_app.config['project']:
raise CommandExecutionError(
error_info=f"project参数有误"
)
# 获取环境配置
namespace = current_app.config[project]['env_namespace'][env]
host = current_app.config[project]['env_node'][env]
# 初始化配置管理器
ins = GitCloner(project, env)
mysql_info, redis_info = ins.get_config()
# 执行活动管理逻辑
ins_mysql = MysqlCrud(host, namespace, mysql_info)
if action == 'start':
# 更新活动状态
sql = f"UPDATE activity SET status=1 WHERE id={activity_id}"
flag, msg = ins_mysql.execute_sql(sql)
_results['activity_start'] = msg
# 清理相关缓存
ins_redis = RedisCrud(host, namespace, redis_info)
ins_redis.delete_pattern(f"activity:{activity_id}:*")
# 发送通知
send_dingtalk(
project=project,
env=env,
success=True,
活动ID=activity_id,
操作=action
)
except CommandExecutionError as e:
_results['error'] = e.error_info
return json.dumps({
"status_code": 500,
"message": "error",
"data": _results
})
return json.dumps({
"status_code": 200,
"message": "Success",
"data": _results
})
新增游戏环境时,需要在配置字典中添加完整的环境映射关系,包括命名空间、节点地址、Git目录等。
# 添加新环境配置示例:压测环境2
app.config['<project1>'] = {
# 添加命名空间映射
"env_namespace": {
...,
"yace2": "<project1>-yace2" # 新增压测环境2
},
# 添加节点IP映射
"env_node": {
...,
"yace2": "<IP1>" # 指定K8s节点
},
# Git仓库子目录
"env_git_subdir": {
...,
"yace2": "yace2" # 对应Git目录
},
# ArgoCD应用名称
"env_appname": {
...,
"yace2": "<project1>-yace2"
},
# COS资源目录
"env_cosdir": {
...,
"yace2": "yace" # 复用压测资源
}
}
# 添加环境中文名称(用于钉钉通知)
app.config['alertname']['yace2'] = "压测环境2(yace2)"
当服务部署失败时,系统会自动收集相关日志和事件信息,帮助快速定位问题原因。
# 服务启动失败时的诊断逻辑
if not flag: # 启动失败
app.logger.error(f"启动时检测日志'{loginfo}'失败")
# 1. 获取 K8s 事件
cmd = f"""kubectl get events -n {namespace} \
--field-selector 'involvedObject.namespace={namespace},\
reason=~Failed' -o json"""
flag, get_event = execute_remote_command(host=host, command=cmd)
if flag:
reason = json.loads(get_event)
if reason['items']:
# 优先使用K8s事件信息
msg = reason['items'][0]['message']
else:
# 2. 获取Pod最新日志
cmd = f"""kubectl logs {pod_name} -c {server} \
-n {namespace} --tail=20"""
flag, logs = execute_remote_command(host=host, command=cmd)
# 3. 提取错误信息
error_lines = [
line for line in logs.split('\n')
if 'ERROR' in line or 'FATAL' in line
]
msg = '\n'.join(error_lines[-5:]) # 最后5条错误
# 4. 保存诊断信息到日志
diagnostic_info = {
'pod': pod_name,
'namespace': namespace,
'error': msg,
'time': datetime.now()
}
app.logger.error(f"诊断信息: {json.dumps(diagnostic_info)}")
raise CommandExecutionError(error_info=msg)
配置表在CI阶段异步上传到COS,通过PVC挂载到容器。常见问题:传输不完整、版本不匹配导致游戏启动失败。
# 1. 检查PVC挂载目录
kubectl exec -it pod-name -c container-name -- ls -la /data/config/
# 2. 比对配置文件版本
kubectl exec -it pod-name -c container-name -- cat /data/config/version.txt
# 3. 查看COS同步日志
kubectl logs pod-name -c sidecar-container
# 解决方案:联系开发重新触发CI或手动同步配置
处理流程:
1. 确认配置表版本号与镜像tag是否匹配
2. 检查COS桶中配置文件更新时间
3. 联系开发重新上传或调整CI流程
新环境搭建时,CI阶段未及时适配正确的版本tag,导致部署非预期版本或启动失败。
# 1. 检查当前部署的镜像版本
kubectl get deployment -n namespace -o yaml | grep image:
# 2. 查看Git仓库配置的版本
cat overlays/env/kustomization.yaml | grep newTag
# 3. 修正版本标签
解决步骤:
1. 确认应部署的正确版本号
2. 修改Git仓库中kustomization.yaml的newTag
3. 提交变更并等待ArgoCD同步
4. 或手动调用 /argocd-sync 接口强制更新
游戏组件停止超时未响应时,不得已需强制杀进程,需先与主程序确认无风险后,再用 crictl 相关命令处理容器级问题。
# 1. 获取超时Pod的宿主机IP
kubectl get pod pod-name -n namespace -o jsonpath='{.status.hostIP}'
# 2. SSH到宿主机,查找容器ID
ssh root@host-ip
crictl ps | grep pod-name
# 3. 强制停止容器
crictl stopp container-id
crictl rmp container-id
# 4. 备份容器日志(重要)
cp -rf /var/log/pods/namespace_pod-name* /tmp/
注意事项:
- 强杀前务必备份日志用于问题定位
- 一定、务必、千万要跟服务端程序确认过可以操作
- 确认数据已保存,避免数据丢失
当资源类型、结构或元数据发生不兼容变更时,需要在ArgoCD WebUI中删除旧资源再重新同步新类型。
# 操作流程(必须按顺序执行)
1. ArgoCD WebUI操作:
- 进入应用详情页面
- 选择要变更的资源(如Deployment)
- 点击Delete删除旧资源
- 等待资源完全清理
2. Git仓库更新:
- 修改YAML文件kind字段
- 提交并推送到远程仓库
3. 重新同步:
- ArgoCD自动检测到变更
- 或手动触发Sync同步
- 调用接口: /argocd-sync?project=<project1>&env=dev
注意:只修改kind重新同步argo是解决不了问题的,必须先删除旧资源
新环境初始化步骤遗漏导致的各类问题:区服ID缺失、域名解析错误、跨站问题、安全组配置遗漏等。
# 初始化检查清单
1. 初始化:
- 区服ID是否正确配置
- 域名配置是否完整或遗漏
- cdn跨域白名单是否添加
2. 网络连通性:
- 安全组规则检查
- 发版平台到游戏环境连通性
- CI平台到镜像仓库连通性
- CI到ArgoCD同步接口连通性
# 常用测试命令
telnet target-host target-port
curl -v http://argo-api/sync
nslookup domain-name
解决方案:
- 按环境初始化SOP逐项检查
- 补充遗漏的安全组规则
- 开通必要端口
常用运维操作、故障排查
tail -f /tmp/gametool.logcat record_interface.txtgrep -i error /tmp/gametool.loggrep "env=dev" /tmp/gametool.logkubectl logs pod-name -c container/var/log/pods/namespace_pod*/tmp/.*_env.lock确认无其他操作后谨慎删除