自动发现并编目代码库或组织中的所有服务——扫描 Dockerfile、docker‑compose、Kubernetes 资源清单、package.json、systemd 单元、P...
Service Catalog. 通过扫描基础设施的现成代码、配置文件和项目元数据来构建和维护一个综合服务目录是一项面向实际任务的技能,主要用于回答“我们运行哪些服务,谁拥有,什么服务”。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
通过扫描基础设施即代码(IaC)文件、配置文件及项目元数据,构建并持续维护一份全面的服务目录。回答以下关键问题:“我们运行了哪些服务?谁负责这些服务?它们依赖哪些组件?当前健康状态如何?”
适用场景包括:“列出我们所有的服务”、“我们有哪些微服务?”、“服务资产清单”、“该服务由谁负责?”、“绘制我们的基础设施拓扑图”、“服务间依赖关系分析”、“平台工程审计”,或搭建内部开发者门户(Internal Developer Portal)。
discover — 自动发现服务在工作区(workspace)中扫描所有常见模式下的服务定义。
# Docker Compose 服务
find . -maxdepth 4 \( -name "docker-compose.yml" -o -name "docker-compose.yaml" -o -name "compose.yml" -o -name "compose.yaml" \)
-not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | while read f; do
echo "=== $f ==="
# 提取服务名称
python3 -c "
import sys
in_services = False
indent = 0
for line in open('$f'):
stripped = line.rstrip()
if stripped == 'services:':
in_services = True
continue
if in_services:
if stripped and not stripped.startswith(' ') and not stripped.startswith('#'):
break
if stripped and not stripped.startswith(' ') or (len(stripped) > 0 and stripped[0] != ' ' and stripped != ''):
break
if stripped.endswith(':') and stripped.startswith(' ') and not stripped.startswith(' '):
name = stripped.strip().rstrip(':')
print(f' Service: {name}')
" 2>/dev/null || grep -E '^ \w+:' "$f" | grep -v '^ ' | sed 's/://;s/^ */ Service: /'
done
# Dockerfile(每个通常对应一个服务)
find . -maxdepth 4 \( -name "Dockerfile" -o -name "Dockerfile.*" -o -name "*.Dockerfile" \)
-not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | while read f; do
DIR=$(dirname "$f")
BASE=$(head -5 "$f" | grep -oP '(?<=FROM )\S+' | head -1)
echo "Dockerfile: $f (base: ${BASE:-unknown}) — dir: $DIR"
done
# K8s Deployment、StatefulSet、Service、CronJob 等资源 find . -maxdepth 5 -name "*.yaml" -o -name "*.yml" | xargs grep -l "kind:\s*(Deployment|StatefulSet|Service|CronJob|DaemonSet|Job)" 2>/dev/null | grep -v node_modules | while read f; do echo "=== $f ===" grep -E "^\\s*(kind|name|namespace|image):" "$f" | head -10 done # Helm Chart find . -maxdepth 4 -name "Chart.yaml" -not -path '*/node_modules/*' 2>/dev/null | while read f; do echo "=== Helm Chart: $f ===" grep -E "^(name|version|description|appVersion):" "$f" done
# Node.js 服务(含 start 脚本的 package.json)
find . -maxdepth 3 -name "package.json" -not -path '*/node_modules/*' 2>/dev/null | while read f; do
HAS_START=$(python3 -c "import json; d=json.load(open('$f')); print('yes' if 'start' in d.get('scripts',{}) else 'no')" 2>/dev/null)
if [ "$HAS_START" = "yes" ]; then
NAME=$(python3 -c "import json; print(json.load(open('$f')).get('name','unknown'))" 2>/dev/null)
echo "Node service: $NAME ($f)"
fi
done
# Python 服务(含主入口点)
find . -maxdepth 3 -name "pyproject.toml" -not -path '*/vendor/*' 2>/dev/null | while read f; do
DIR=$(dirname "$f")
echo "Python project: $f"
grep -E "^(name|version)" "$f" | head -2
done
# Go 服务
find . -maxdepth 3 -name "go.mod" 2>/dev/null | while read f; do
MODULE=$(head -1 "$f" | awk '{print $2}')
echo "Go module: $MODULE ($f)"
done
# Procfile(Heroku/Dokku)
find . -maxdepth 3 -name "Procfile" 2>/dev/null | while read f; do
echo "=== Procfile: $f ==="
cat "$f"
done
# Systemd Unit 文件
find . -maxdepth 4 -name "*.service" -not -path '*/.git/*' 2>/dev/null | while read f; do
echo "Systemd unit: $f"
grep -E "^(Description|ExecStart|After|Requires)=" "$f" 2>/dev/null
done
# GitHub Actions 部署工作流 find .github/workflows -name "*.yml" -o -name "*.yaml" 2>/dev/null | xargs grep -l "deploy" 2>/dev/null | while read f; do echo "Deploy workflow: $f" grep -E "^\\s*(name|runs-on|env):" "$f" | head -5 done # GitLab CI 部署阶段 grep -A5 "deploy" .gitlab-ci.yml 2>/dev/null | head -20
catalog — 生成服务目录完成服务发现后,将其汇总为结构化服务目录。对每个服务提取以下信息:
# 从环境变量和配置中检测服务依赖 rg -n "(DATABASE_URL|REDIS_URL|RABBITMQ_URL|KAFKA_BROKERS|MONGO_URI|API_URL|SERVICE_URL)" -g '!node_modules' -g '!vendor' -g '!dist' --type-not binary 2>/dev/null # 检测服务间通信行为 rg -n "(fetch|axios|http.get|requests.get|grpc|amqp|redis)" -g '!node_modules' -g '!vendor' -g '!dist' -g '!.test.' -g '!.spec.' --type-not binary 2>/dev/null | grep -oP 'https?://[a-zA-Z0-9._/-]+' | sort -u # 检查 CODEOWNERS 文件 cat CODEOWNERS .github/CODEOWNERS docs/CODEOWNERS 2>/dev/null # 检查健康检查端点 rg -n "(/health|/healthz|/ready|/status|/ping)" -g '!node_modules' -g '!vendor' --type-not binary 2>/dev/null | head -20
输出服务目录文档示例:
# Service Catalog Generated: [date] | Services: N | Owners: N teams ## Services ### api-gateway - **Type:** API Gateway - **Stack:** Node.js 20, Express - **Port:** 3000 - **Owner:** @platform-team - **Dependencies:** auth-service, user-service, redis - **Health:** GET /health - **Repo:** github.com/org/api-gateway - **Docs:** docs/api-gateway.md ### user-service ...
deps — 依赖关系图绘制服务到服务的依赖关系:
api-gateway → auth-service → postgres api-gateway → user-service → postgres, redis api-gateway → notification-service → redis, smtp worker → queue (rabbitmq) → notification-service frontend → api-gateway
自动识别以下风险模式:
health — 检查服务健康状态针对已知健康检查端点或本地 Docker 容器的服务执行探活:
# 检查本地 Docker 容器
docker ps --format "{{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null
# 检查 systemd 服务
systemctl list-units --type=service --state=running 2>/dev/null | grep -v systemd
# 探测健康检查端点
for endpoint in $(rg -o "https?://localhost:[0-9]+/(health|healthz|ready|status)" -g '*.{yml,yaml,json,env}' 2>/dev/null | sort -u); do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "$endpoint" 2>/dev/null)
echo "$endpoint → $STATUS"
done
owners — 所有权报告将服务映射至所属团队或个人:
# 来自 CODEOWNERS
cat CODEOWNERS .github/CODEOWNERS 2>/dev/null | grep -v '^#' | grep -v '^$'
# 来自 package.json 的 author/maintainers 字段
find . -maxdepth 3 -name "package.json" -not -path '*/node_modules/*' 2>/dev/null | while read f; do
python3 -c "
import json
d = json.load(open('$f'))
name = d.get('name', 'unknown')
author = d.get('author', 'unassigned')
if isinstance(author, dict): author = author.get('name', 'unassigned')
print(f'{name}: {author}')
" 2>/dev/null
done
# 来自 git blame(按目录统计最近 90 天最活跃贡献者)
find . -maxdepth 2 -type d -not -path '*/.git*' -not -path '*/node_modules*' | while read d; do
TOP=$(git log --since="90 days ago" --format="%an" -- "$d" 2>/dev/null | sort | uniq -c | sort -rn | head -1)
if [ -n "$TOP" ]; then
echo "$d: $TOP"
fi
done 2>/dev/null
将未明确归属的服务标记为风险项。
drift — 检测目录漂移(Catalog Drift)将当前生成的服务目录与先前保存的版本(.service-catalog.json)进行比对,识别变更:
建议在 CI 中运行该命令,及时捕获未文档化的基础设施变更。
{services: [{name, type, stack, port, deps, owner, health, repo}], graph: {edges: []}}.service-catalog.json,以启用 drift 检测能力相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134.1万人学习
共49课时 | 82.6万人学习