本文目录导读:

- 清理 Docker 未使用标签(Dangling / Untagged Images)
- 清理 Git 仓库中的未使用标签(Git Tag Cleanup)
- 清理 AWS 未使用的资源标签(EC2 Tag Cleanup)
- 清理 Kubernetes 未使用的 Helm Release 标签
- 清理数据库中的未使用标签(如 PostgreSQL / MySQL)
- ⚠️ 安全与最佳实践
针对自动化清理未使用标签的需求,具体实现方式取决于你使用的平台(如 GitHub、GitLab、AWS、Kubernetes)或技术栈(如 Docker、数据库),以下是几种常见场景的自动化脚本方案及代码示例:
清理 Docker 未使用标签(Dangling / Untagged Images)
Docker 中未使用的标签通常指 <none>:<none> 镜像(dangling images)。
脚本(Bash):
#!/bin/bash # 清理所有未使用的镜像(包括无标签和未被容器引用的) echo "Start cleaning unused Docker images..." # 清理 dangling 镜像(无标签) docker image prune -a -f # 或更彻底的清理:删除所有未被使用的镜像(注意:会删除未被任何容器引用的镜像) # docker system prune -a -f echo "Cleanup completed."
定时执行(cron):
# 每天凌晨2点执行 0 2 * * * /path/to/clean_docker.sh
清理 Git 仓库中的未使用标签(Git Tag Cleanup)
在 CI/CD 或长期项目中,Git 标签常因分支删除、版本迭代而失效。
预期行为: 删除所有不在远程某分支上的标签(或按模式筛选)。
脚本(Bash):
#!/bin/bash
# 定义远程名称(通常为 origin)
REMOTE="origin"
echo "Fetching latest remote refs..."
git fetch --prune $REMOTE
# 获取远程存在的所有标签(按需过滤)
echo "Listing remote tags..."
git tag -l | while read tag; do
# 检查该标签是否指向有效的远程提交(如果标签已被删除,此处会失败)
if ! git rev-parse --verify "$tag^{commit}" &>/dev/null; then
echo "Deleting invalid tag: $tag"
git push $REMOTE --delete "$tag"
git tag -d "$tag"
fi
done
# 另一种策略:删除所有本地已有但远程不存在的标签
echo "Pruning local tags not on remote..."
git tag -l | while read tag; do
if [ -z "$(git ls-remote --tags $REMOTE | grep "refs/tags/$tag")" ]; then
echo "Deleting local-only tag: $tag"
git tag -d "$tag"
fi
done
清理 AWS 未使用的资源标签(EC2 Tag Cleanup)
AWS 资源标签用于成本分配,未使用的旧标签会混乱管理。
前提: 需配置 AWS CLI 及适当权限。
脚本(Python + boto3):
import boto3
import sys
from datetime import datetime, timedelta
def cleanup_unused_ec2_tags(days_threshold=30):
ec2 = boto3.client('ec2')
# 获取所有已存在的标签(不局限于特定资源)
tags = ec2.describe_tags()['Tags']
# 找出最近30天未使用过的标签
cutoff_time = datetime.utcnow() - timedelta(days=days_threshold)
unused_tags = [tag for tag in tags
if tag['ResourceType'] in ['instance', 'volume'] # 只关注实例和卷
and tag['LastUpdateTime'] < cutoff_time]
if not unused_tags:
print("No unused tags found.")
return
print(f"Will delete {len(unused_tags)} unused tags...")
# 逐个删除(实际生产环境建议先review)
for tag in unused_tags:
ec2.delete_tags(
Resources=[tag['ResourceId']],
Tags=[{'Key': tag['Key']}]
)
print(f"Deleted tag {tag['Key']} from resource {tag['ResourceId']}")
if __name__ == '__main__':
cleanup_unused_ec2_tags(days_threshold=60) # 60天未更新视为未使用
清理 Kubernetes 未使用的 Helm Release 标签
Helm 部署后,可能残留旧的 Release 标签(如 release、app.kubernetes.io/managed-by)。
脚本(Bash + kubectl):
#!/bin/bash
# 清理所有没有对应 pod 的 Helm Release 标签(需要谨慎)
NAMESPACES=("default" "production")
for ns in "${NAMESPACES[@]}"; do
echo "Checking namespace: $ns"
# 列出所有 Helm Release 标签
kubectl get pods -n "$ns" -o jsonpath='{range .items[*]}{.metadata.labels.release}{"\n"}{end}' | \
sort | uniq | while read release; do
if [ -z "$release" ]; then continue; fi
# 检查该 release 是否还有其他 pod
count=$(kubectl get pods -n "$ns" -l "release=$release" --no-headers 2>/dev/null | wc -l)
if [ "$count" -eq 0 ]; then
# 确认该 release 已被完全删除(或异常残留)
echo "Found unused release label: $release in namespace $ns"
# 可执行清理(注释掉以防误操作)
# kubectl label pod --all -n "$ns" "release-$release-" # 删除特定标签
fi
done
done
清理数据库中的未使用标签(如 PostgreSQL / MySQL)
应用层常维护 tags 表,需删除未被任何资源引用的标签行。
确保参考完整性: 假设存在 post_tags 关联表。
SQL脚本(适用于定时任务):
-- 清理 Postgres 中的未使用标签
DELETE FROM tags
WHERE id NOT IN (
SELECT DISTINCT tag_id FROM post_tags
);
-- 或删除所有在最近90天内未使用的标签(需有最后使用时间字段)
DELETE FROM tags
WHERE last_used_at < NOW() - INTERVAL '90 days';
自动化任务(cron + psql):
0 3 * * 0 psql -U app_user -d mydb -c "DELETE FROM tags WHERE id NOT IN (SELECT DISTINCT tag_id FROM post_tags);"
⚠️ 安全与最佳实践
- 先模拟再执行: 使用
--dry-run或--what-if参数验证。 - 保留审计日志: 记录删除的标签、资源ID、时间。
- 版本控制: 将脚本放入 Git 仓库,确保可追溯。
- 分批次执行: 对大量资源(如 AWS 标签),每次处理100个,避免限速。
- 通知机制: 成功/失败时发送通知(Slack、邮件)。
需要针对具体平台(如 GitLab、Azure、Harbor)的定制方案,请补充说明。