当前位置: 首页 > news >正文

Kubernetes 中 ETCD 数据备份与恢复完整指南

ETCD作为Kubernetes(K8s)集群的“数据库”,存储了集群所有状态信息(如资源配置、工作负载、权限规则等)。一旦ETCD数据丢失或损坏,可能导致集群瘫痪,因此定期备份、可靠恢复是集群运维的核心环节。本文将从备份策略、手动备份/恢复、故障回滚、第三方工具(Velero)等维度,提供可落地的操作方案。

一、ETCD 数据备份:基础准备与手动操作

ETCD备份的核心是通过etcdctl工具生成快照文件(snapshot),需先完成环境配置,再执行备份操作。

1.1 备份前的核心准备

(1)确认 ETCD 版本与下载 etcdctl

etcdctl是ETCD官方命令行工具,需确保其版本与集群ETCD版本一致(避免兼容性问题)。

# 1. 查看集群 ETCD 版本(通过静态 Pod 配置文件)
cat /etc/kubernetes/manifests/etcd.yaml | grep image
# 输出示例:image: registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0(版本为 3.5.6)# 2. 下载对应版本的 etcdctl(从 GitHub 官方仓库)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.6/etcd-v3.5.6-linux-amd64.tar.gz# 3. 解压并安装 etcdctl
tar xf etcd-v3.5.6-linux-amd64.tar.gz
mv etcd-v3.5.6-linux-amd64/etcdctl /usr/local/sbin/# 4. 验证安装(需显示版本匹配)
etcdctl version
# 输出示例:etcdctl version: 3.5.6; API version: 3.5

(2)配置 ETCD API 版本

ETCD v3 是当前主流版本,需通过环境变量 ETCD_API指定使用v3 API(默认可能为v2,导致命令失效):

# 临时生效(当前终端)
export ETCDCTL_API=3# 永久生效(所有终端,写入 bash 配置)
echo "ETCDCTL_API=3" >> ~/.bashrc
source ~/.bashrc  # 立即生效# 验证
echo $ETCDCTL_API  # 输出:3

(3)获取 ETCD 认证凭证

K8s集群的ETCD启用了SSL认证,备份时需要指定CA证书、服务端证书、服务端私钥(默认路径在/etc/kubernetes/pki/etcd/):

  • CA证书:/etc/kubernetes/pki/etcd/ca.crt
  • 服务端证书:/etc/kubernetes/pki/etcd/server.crt
  • 服务端私钥:/etc/kubernetes/pki/etcd/server.key

1.2 执行 ETCD 数据备份

通过etcdctl snapshot save命令生成快照文件,建议将备份文件存储在非集群节点的安全位置(如远程存储、本地独立磁盘)。

# 1. 创建备份目录(建议按日期命名,便于管理)
mkdir -p /opt/etcd/backup/$(date +%Y%m%d)# 2. 执行备份(核心命令)
ETCDCTL_API=3 etcdctl \--endpoints=https://127.0.0.1:2379 \  # ETCD 监听地址(默认本地 2379)--cacert=/etc/kubernetes/pki/etcd/ca.crt \  # CA 证书路径--cert=/etc/kubernetes/pki/etcd/server.crt \  # 服务端证书路径--key=/etc/kubernetes/pki/etcd/server.key \  # 服务端私钥路径snapshot save /opt/etcd/backup/$(date +%Y%m%d)/etcd_snapshot_$(date +%H%M%S).db# 3. 验证备份文件(查看大小与元信息)
# 查看文件大小(需非空,通常几 MB 到几十 MB,取决于集群规模)
ll -h /opt/etcd/backup/$(date +%Y%m%d)/# 查看快照状态(确认版本、数据量等)
ETCDCTL_API=3 etcdctl --write-out=table snapshot status /opt/etcd/backup/$(date +%Y%m%d)/etcd_snapshot_*.db

快照状态输出示例(关键字段:TotalKey为总键数量,Version为ETCD版本):

filenamerevisionversiontotalKeytotalSize
etcd_snapshot_1730.db1234563.5.68903.8 MB

1.3 备份策略建议

为避免单一备份丢失或损坏,需制定规范的备份策略:

  • 备份频率:生产环境建议每日全量备份+每小时增量备份(增量需结合ETCD历史版本,需提前开启 --enable-v2=true)。
  • 存储位置:至少保留2份副本,分别存储在本地磁盘(集群节点外)和远程存储(如S3、NFS)。
  • 保留周期:按业务需求设置(如保留最近7天的每日备份,最近30天的每周备份)。
  • 校验机制:备份后定期通过 snapshot status 校验文件完整性,避免备份失效。

二、ETCD 数据恢复:手动恢复与故障验证

ETCD恢复需停止集群核心组件(避免数据写入冲突),再通过快照文件重建ETCD数据目录,最后重启集群。

2.1 恢复前的准备:标记验证资源

为确认恢复成功,建议先创建一个 “临时测试资源”,恢复后若该资源消失,说明恢复到备份前状态。

# 1. 创建测试 Pod(备份后新增的资源)
kubectl run test-nginx --image=nginx:alpine --image-pull-policy=IfNotPresent# 2. 确认资源存在
kubectl get pods | grep test-nginx
# 输出示例:test-nginx   1/1     Running   0          30s

2.2 核心步骤:停止集群组件 + 恢复数据

K8s核心组件(APIServer、Controller Manager、Scheduler、ETCD)通过静态Pod启动(配置文件在/etc/kubernetes/mainfests/),停止这些组件只需移动配置文件即可。

(1)停止集群核心组件

# 1. 创建临时目录,存放静态 Pod 配置文件(移动后组件会自动停止)
mkdir -p /opt/k8s-manifests-backup# 2. 移动配置文件(停止 APIServer、Controller Manager、Scheduler、ETCD)
mv /etc/kubernetes/manifests/* /opt/k8s-manifests-backup/# 3. 确认组件已停止(APIServer 停止后,kubectl 会无法连接)
kubectl get pods -n kube-system
# 输出示例:The connection to the server 192.168.100.10:6443 was refused...

(2)备份当前 ETCD 数据目录(故障回滚用)

为防止恢复失败,需先备份当前 ETCD 数据目录(默认路径 /var/lib/etcd):

# 重命名现有数据目录(保留原始数据,便于回滚)
mv /var/lib/etcd /var/lib/etcd_old_backup

(3)执行 ETCD 恢复

通过etcdctl snapshot restore 命令,从快照文件重建ETCD数据目录,需指定集群初始化参数(与备份的ETCD配置一致)。

# 核心恢复命令(参数需根据集群实际配置调整)
ETCDCTL_API=3 etcdctl snapshot restore \/opt/etcd/backup/20240928/etcd_snapshot_1730.db \  # 快照文件路径--name=etcd-master-01 \  # ETCD 节点名称(需与集群配置一致,查看 etcd.yaml 中的 --name 参数)--data-dir=/var/lib/etcd \  # 新的 ETCD 数据目录(恢复后的数据将存于此)--initial-cluster=etcd-master-01=https://192.168.100.10:2380 \  # ETCD 集群节点列表(单节点集群仅需自身)--initial-cluster-token=etcd-cluster-token \  # 集群令牌(需与 etcd.yaml 中的 --initial-cluster-token 一致)--initial-advertise-peer-urls=https://192.168.100.10:2380  # 节点对等通信地址(需与 etcd.yaml 中的 --initial-advertise-peer-urls 一致)

参数说明(需从 etcd.yaml 中获取准确值):

  • --name:ETCD节点名称,查看etcd.yaml中的--name字段。
  • --initial-cluster:集群节点列表,格式为“节点名=通信地址”(单节点仅填自身)。
  • --initial-cluster-token:集群唯一令牌,查看etcd.yaml中的--initial-cluster-token。
  • --initial-advertise-peer-urls:节点对等通信地址(用于集群内节点通信,默认2380端口)。

(4)重启集群核心组件

恢复数据目录后,将静态Pod配置文件移回原目录,组件会自动重启:

# 移动配置文件(重启 APIServer、ETCD 等组件)
mv /opt/k8s-manifests-backup/* /etc/kubernetes/manifests/# 等待 1-2 分钟,确认组件启动(需确保 ETCD 正常运行)
kubectl get pods -n kube-system | grep etcd
# 输出示例:etcd-master-01   1/1     Running   0          1m

2.3 验证恢复结果

恢复成功的核心标志是“备份后新增的资源消失”,且原有资源政策正常:

# 1. 检查测试资源(test-nginx 应消失,说明恢复到备份前状态)
kubectl get pods | grep test-nginx
# 输出:无结果(资源已消失)# 2. 检查原有资源(如备份前存在的 tomcat Pod,应正常运行)
kubectl get pods | grep tomcat
# 输出示例:tomcat-test   1/1     Running   0          8h

2.4 恢复失败的回滚方案

若恢复后集群异常(如ETCD无法启动),可通过“还原原始数据目录”回滚:

# 1. 再次停止集群组件
mv /etc/kubernetes/manifests/* /opt/k8s-manifests-backup/# 2. 删除恢复的数据目录,还原原始目录
rm -rf /var/lib/etcd
mv /var/lib/etcd_old_backup /var/lib/etcd# 3. 重启组件
mv /opt/k8s-manifests-backup/* /etc/kubernetes/manifests/

三、ETCD 备份的两种核心方式对比

除了上述“快照备份”,还可通过“目录备份”直接复制ETCD数据目录,两种方式各有使用场景:

备份方式备份源备份目标优点缺点适用场景
快照备份ETCD 数据库内容(通过 etcdctl单一快照文件(如 etcd_snapshot.db体积小、跨版本兼容(部分版本)、支持增量需安装 etcdctl、依赖 ETCD 服务正常日常定期备份、跨节点恢复
目录备份ETCD 数据目录(/var/lib/etcd复制目录(如 /var/lib/etcd_bak操作简单、无需依赖 etcdctl体积大(与数据目录一致)、跨版本兼容性差紧急故障备份(ETCD 无法启动时)

四、扩展:集群级备份(不止 ETCD)

仅备份 ETCD 不足以覆盖所有风险(如应用数据、自定义配置),需补充以下备份:

4.1 应用数据备份(持久卷 PV)

应用数据通常存储在PV中(如数据库数据、业务日志),需结合PV类型选择备份方式:

  • 宿主目录/本地磁盘PV:通过rsync或tar备份PV挂载目录(如/data/pv/mysql)。
  • 云存储PV(如AWS EBS、阿里云云盘):使用云厂商提供的“快照功能”(如aws ec2 create-snapshot)。
  • 分布式存储PV(如Ceph):使用存储自身的备份工具(如Ceph RBD快照)。

4.2 K8s 配置与资源定义备份

  • 静态配置文件:备份/etc/kubernetes/目录(包含证书、静态Pod配置):
tar zcvf /opt/backup/k8s_config_$(date +%Y%m%d).tar.gz /etc/kubernetes/
  • 资源定义YAML:导出所有集群资源的YAML配置(便于快速重建):
kubectl get all --all-namespaces -o yaml > /opt/backup/k8s_all_resources_$(date +%Y%m%d).yaml

五、第三方工具:使用 Velero 实现自动化备份

手动备份 / 恢复效率低且易出错,生产环境推荐使用 Velero(开源工具,支持集群资源、ETCD 数据、PV 备份的自动化)。

5.1 Velero 核心优势

  • 支持 定时备份(如每日凌晨 1 点自动备份)。
  • 支持 选择性备份(如仅备份特定命名空间、特定资源)。
  • 集成对象存储(如 MinIO、S3),备份文件存储更可靠。
  • 简化恢复流程(无需手动停止集群组件)。

5.2 部署 Velero 与 MinIO(本地对象存储)

Velero 需要对象存储存储备份文件,此处使用 MinIO(轻量级开源对象存储)作为本地存储。

(1)安装 MinIO(对象存储服务)

# 1. 下载 MinIO 二进制文件
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
mv minio /usr/local/bin/# 2. 创建数据目录
mkdir -p /mnt/minio-data# 3. 启动 MinIO(后台运行,设置访问密钥)
nohup MINIO_ROOT_USER=velero-admin MINIO_ROOT_PASSWORD=velero-pass123 \minio server /mnt/minio-data --console-address ":9001" > /var/log/minio.log 2>&1 &# 4. 验证 MinIO 启动(访问控制台:http://集群IP:9001,登录账号密码为上述设置)
curl http://127.0.0.1:9000/minio/health/live
# 输出:OK

(2)安装 Velero

# 1. 下载 Velero CLI(版本 1.12.0,兼容主流 K8s 版本)
wget https://github.com/vmware-tanzu/velero/releases/download/v1.12.0/velero-v1.12.0-linux-amd64.tar.gz
tar xf velero-v1.12.0-linux-amd64.tar.gz
mv velero-v1.12.0-linux-amd64/velero /usr/local/bin/# 2. 验证 CLI 安装
velero version
# 输出:Client Version: v1.12.0(仅客户端,服务端未安装)# 3. 创建 MinIO 访问凭证文件(Velero 需此文件访问 MinIO)
cat > credentials-velero << EOF
[default]
aws_access_key_id=velero-admin
aws_secret_access_key=velero-pass123
EOF# 4. 安装 Velero 服务端(关联 MinIO)
velero install \--provider aws \  # 兼容 MinIO(S3 协议)--plugins velero/velero-plugin-for-aws:v1.9.0 \  # S3 插件--bucket velero-backups \  # MinIO 中存储备份的桶名(会自动创建)--secret-file ./credentials

5.3 创建 Velero 备份(手动触发)

Velero 支持灵活的备份策略,可根据需求选择 “全集群备份”“指定命名空间备份” 或 “指定资源类型备份”,核心命令为 velero backup create

(1)全集群备份(备份所有命名空间与资源)

适用于集群级灾备,备份所有命名空间(包括 kube-system 系统命名空间)的资源和关联的持久卷(PV):

# 创建全集群备份,命名格式:backup-日期-时间(便于追溯)
velero backup create backup-full-$(date +%Y%m%d%H%M) \--include-namespaces=* \  # 包含所有命名空间(* 表示全部)--snapshot-volumes=true \  # 备份持久卷(PV)的快照(需存储支持快照功能)--wait  # 等待备份完成后再退出(便于查看结果)

(2)指定命名空间备份(如仅备份业务命名空间)

生产环境中,常需单独备份业务命名空间(如 prodtest),避免系统命名空间占用过多备份空间:

# 备份 prod 和 test 两个命名空间
velero backup create backup-prod-test-$(date +%Y%m%d) \--include-namespaces=prod,test \  # 逗号分隔多个命名空间--snapshot-volumes=true \--wait

(3)指定资源类型备份(如仅备份 Deployment 和 PVC)

若仅需备份特定资源(如避免备份临时 Pod),可通过 --include-resources 指定资源类型:

# 仅备份 prod 命名空间的 Deployment、StatefulSet 和 PVC
velero backup create backup-prod-resources-$(date +%Y%m%d) \--include-namespaces=prod \--include-resources=deployments.apps,statefulsets.apps,persistentvolumeclaims \  # 资源类型(格式:资源名.API组,核心资源无需API组)--snapshot-volumes=true \--wait

(4)排除特定资源备份

若需排除临时资源(如 Job、Pod),可通过 --exclude-resources 过滤:

# 备份 prod 命名空间,但排除 Job 和 Pod
velero backup create backup-prod-exclude-$(date +%Y%m%d) \--include-namespaces=prod \--exclude-resources=jobs.batch,pods \--snapshot-volumes=true \--wait

5.4 查看与校验备份状态

备份创建后,需确认备份是否成功,避免 “无效备份”(如存储连接失败、权限不足导致备份中断)。

(1)查看所有备份列表

velero backup get

输出示例(关键列说明):

NAMESTATUSERRORSWARNINGSCREATEDEXPIRESSTORAGE LOCATIONSELECTOR
backup-full-202409281030Completed002024-09-28 10:30:00 +0800 CST29ddefault<none>
backup-prod-202409281100Completed002024-09-28 11:00:00 +0800 CST29ddefault<none>
  • STATUSCompleted 表示成功,InProgress 表示正在执行,Failed 表示失败。
  • EXPIRES:备份过期时间(默认 30 天,可通过 --ttl 指定,如 --ttl=720h 表示 30 天)。

(2)查看单个备份详情(排查失败原因)

若备份状态为 Failed 或有 ERRORS,需查看详情定位问题:

# 替换为实际备份名
velero backup describe backup-prod-202409281100 --details

关键信息:

  • Phase:备份阶段(如 Completed)。
  • Errors/Warnings:错误或警告信息(如 “PV 快照失败,因存储不支持快照”)。
  • Included Resources:已包含的资源类型。
  • Volume Snapshots:持久卷快照状态(每个 PV 的快照是否成功)。

(3)校验备份文件完整性

Velero 支持通过 velero backup download 下载备份文件到本地,验证文件是否可正常读取:

# 下载备份文件(会生成一个压缩包)
velero backup download backup-prod-202409281100# 解压并查看内容(包含资源 YAML 和 PV 快照元数据)
unzip backup-prod-202409281100.zip
ls -l backup-prod-202409281100/

5.5 执行 Velero 恢复操作

当集群出现故障(如资源误删、ETCD 数据损坏)时,可通过 Velero 从备份中恢复数据,核心命令为 velero restore create

(1)全量恢复(从全集群备份恢复所有资源)

适用于集群整体故障,恢复所有命名空间和资源:

# 从全集群备份恢复,恢复任务命名格式:restore-备份名-时间
velero restore create restore-full-$(date +%Y%m%d%H%M) \--from-backup=backup-full-202409281030 \  # 指定备份源--wait  # 等待恢复完成

(2)选择性恢复(仅恢复特定命名空间 / 资源)

若仅需恢复部分资源(如误删 prod 命名空间的 Deployment),可通过参数过滤:

# 从全集群备份中,仅恢复 prod 命名空间的 Deployment
velero restore create restore-prod-deploy-$(date +%Y%m%d) \--from-backup=backup-full-202409281030 \--include-namespaces=prod \  # 仅恢复 prod 命名空间--include-resources=deployments.apps \  # 仅恢复 Deployment--wait

(3)恢复时排除特定资源

若需恢复大部分资源,但排除临时资源(如旧的 Job),可使用 --exclude-resources

# 恢复 prod 命名空间,但排除 Job 和 Pod(避免恢复旧的临时任务)
velero restore create restore-prod-exclude-$(date +%Y%m%d) \--from-backup=backup-prod-202409281100 \--exclude-resources=jobs.batch,pods \--wait

5.6 查看恢复状态与验证结果

恢复执行后,需确认恢复是否成功,并验证资源是否正常运行。

(1)查看恢复任务列表

velero restore get

输出示例:

NAMEBACKUPSTATUSERRORSWARNINGSCREATEDCOMPLETED
restore-prod-deploy-20240928backup-full-202409281030Completed002024-09-28 14:30:00 +0800 CST2024-09-28 14:30:30 +0800 CST

(2)查看恢复详情(排查失败原因)

若恢复状态为 Failed,需查看详情定位问题(如 “资源已存在导致恢复冲突”):

velero restore describe restore-prod-deploy-20240928 --details

(3)验证恢复结果

通过 kubectl 确认资源是否恢复正常:

# 1. 查看 prod 命名空间的 Deployment(确认恢复的资源存在)
kubectl get deployments -n prod# 2. 查看 PV/PVC(确认持久卷数据是否恢复)
kubectl get pvc -n prod
kubectl get pv# 3. 查看 Pod 状态(确认应用正常运行)
kubectl get pods -n prod

5.7 配置 Velero 定时备份(自动化运维)

手动备份难以保证及时性,Velero 支持通过 velero schedule create 创建定时任务,实现 “按周期自动备份”(如每日凌晨 1 点备份)。

(1)创建每日全集群定时备份

# 定时任务命名:schedule-full-daily(每日全量备份)
# 调度规则:0 1 * * *(Cron 表达式,每日凌晨 1 点执行)
# 备份保留时间:7 天(--ttl=168h)
velero schedule create schedule-full-daily \--schedule="0 1 * * *" \--include-namespaces=* \--snapshot-volumes=true \--ttl=168h \  # 备份保留 7 天,自动清理过期备份--wait

(2)创建每小时业务命名空间增量备份

对于核心业务命名空间(如 prod),可设置更频繁的增量备份(依赖存储支持增量快照):

# 定时任务命名:schedule-prod-hourly(每小时增量备份)
# 调度规则:0 * * * *(每小时整点执行)
# 备份保留时间:24 小时(--ttl=24h)
velero schedule create schedule-prod-hourly \--schedule="0 * * * *" \--include-namespaces=prod \--snapshot-volumes=true \--ttl=24h \--wait

(3)查看定时任务与历史备份

# 1. 查看所有定时任务
velero schedule get# 2. 查看某个定时任务的执行历史(如每日全量备份的历史结果)
velero schedule history schedule-full-daily# 3. 查看定时任务生成的备份列表
velero backup get --selector=velero.io/schedule-name=schedule-full-daily

六、ETCD 与 Velero 备份方案对比与选型建议

在实际运维中,需根据集群规模、业务需求选择合适的备份方案,以下是两种核心方案的对比:

对比维度ETCD 手动备份(快照 / 目录)Velero 自动化备份
备份范围仅 ETCD 数据(集群状态、资源配置)集群资源(Deployment/Pod 等)+ PV 数据 + ETCD 数据(间接)
自动化能力需手动编写脚本实现定时备份内置定时任务,支持自动清理过期备份
恢复灵活性仅支持全集群恢复(无法选择性恢复单个资源)支持选择性恢复(命名空间、资源类型、单个资源)
PV 备份支持不支持(需单独备份 PV 目录)支持 PV 快照(需存储支持),自动关联资源恢复
运维复杂度高(需手动管理备份文件、恢复时需停止集群)低(图形化控制台 + 命令行,无需停止集群)
适用场景小型集群、应急备份(ETCD 故障时)中大型集群、生产环境、日常自动化运维

选型建议:

  • 小型测试集群:可使用 ETCD 手动备份(快照),降低运维成本。
  • 生产环境集群:优先选择 Velero,结合 “每日全量备份 + 核心业务每小时增量备份”,确保数据可快速恢复,同时减少故障影响范围。
  • 核心业务场景:在 Velero 基础上,额外定期执行 ETCD 快照备份(作为 “最后一道防线”),避免 Velero 自身故障导致备份失效。

七、总结

Kubernetes 集群的数据安全依赖 “定期备份 + 可靠恢复”,核心结论如下:

  1. ETCD 是核心:ETCD 存储集群所有状态,需通过 etcdctl 定期生成快照,确保集群可回滚到历史状态。
  2. Velero 提升效率:Velero 实现了备份 / 恢复的自动化、灵活化,支持选择性恢复和 PV 数据备份,是生产环境的首选工具。
  3. 策略需适配业务:根据业务重要性制定备份频率(核心业务每小时增量,普通业务每日全量),备份文件需多副本存储(本地 + 远程)

点赞+收藏+关注,下期我们接着唠嗑

http://www.dtcms.com/a/419120.html

相关文章:

  • Go 语言中指针介绍
  • 权重的网站建设网站有哪些内容
  • vxe-grid @edit-closed方法不被执行或者叫不触发
  • CF Yamakasi (前缀和+双指针)
  • 机器学习-第三章 线性模型
  • 新手想做网站赚钱app制作开发公司怎么收费
  • 现代Web存储技术(二):存储容量规划与传统方案对比
  • PyTorch实战(8)——图像描述生成
  • App Store 上架完整流程解析,iOS 应用发布步骤、ipa 文件上传工具、TestFlight 测试与苹果审核经验
  • stm32和Zynq的中断抢占机制
  • iOS App 混淆实战,在源码不可用情况下的成品加固与测试流程
  • Python爬虫技术:招标信息抓取与关键词过滤 (1)
  • 莞城网站推广wordpress图片并列排
  • 塘厦仿做网站wordpress和jwplayer
  • 嵌入式 - 内核驱动3 - class/device | misc | ioctl |device/driver
  • Matlab通过GUI实现点云的双边(Bilateral)滤波(附最简版)
  • 4-5〔O҉S҉C҉P҉ ◈ 研记〕❘ WEB应用攻击▸远程文件包含漏洞
  • 怎么在淘宝上做网站中交建设集团网站
  • 在线查看网站源码中国最新新闻
  • 轴状态读取(运动控制系列)
  • quic的拥塞控制
  • 【模型系列】Human-in-the-Loop
  • AI项目问题总结大全
  • 【linux内核驱动day03】
  • Accelerate基本使用
  • Day75 基本情报技术者 单词表10 ネットワーク応用
  • 企业网站美化做常州美食网站首页的背景图
  • 网站建设设计的流程wordpress的搭建教程 pdf
  • 页网站腾讯云学生机做网站
  • C++ 模板(Template)基础与应用