源码解读bucket 删除中的一些细节

时间:2022-04-25
本文章向大家介绍源码解读bucket 删除中的一些细节,主要内容包括问题描述、原因分析、解决方案、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

问题描述

社区群里有人说删除bucket以后还有部分数据残留,用的ceph 10.2.x版本做的验证

测试用例

from boto.s3.connection import S3Connection
import boto

conn = boto.connect_s3(
            aws_access_key_id = '',
            aws_secret_access_key = '',
            host = 's3.cephbook.com',
            port = 80,
            is_secure = False,
            calling_format = boto.s3.connection.OrdinaryCallingFormat(),
            )
bucket = conn.create_bucket('foo')
#bucket.delete()

删除前

root@demohost:/home/user# rados ls -p rgw.root
foo
.bucket.meta.foo:70af9a54-20bb-480b-92f4-cbdeef0b775c.217357.1

删除后

root@demohost:/home/user# rados ls -p rgw.root
.bucket.meta.foo:70af9a54-20bb-480b-92f4-cbdeef0b775c.217357.1 #残留

原因分析

对meta file的删除操作需要根据是否开启了多集群同步来决定

# src/rgw/rgw_rados.cc
    op_ret = store->delete_bucket(s->bucket, ot);#入口
    ....

  /* if the bucket is not synced we can remove the meta file */
  if (!is_syncing_bucket_meta(bucket)) {
    RGWObjVersionTracker objv_tracker;
    string entry = bucket.get_key();
    r= rgw_bucket_instance_remove_entry(this, entry, &objv_tracker);
    if (r < 0) {
      return r;
    }
    /* remove bucket index objects*/
    map<int, string>::const_iterator biter;
    for (biter = bucket_objs.begin(); biter != bucket_objs.end(); ++biter) {
      index_ctx.remove(biter->second);
    }
  }

满足下面4种情况是不会进行meta file的删除操作 当前period不是最新版本 zonegroup为非master zonegroup 当前集群只有单个zonegroup,且只有一个zone 当前zone不是master zone

/**
  * Check to see if the bucket metadata could be synced
  * bucket: the bucket to check
  * Returns false is the bucket is not synced
  */
bool RGWRados::is_syncing_bucket_meta(rgw_bucket& bucket)
{

  /* no current period  */
  if (current_period.get_id().empty()) {
    return false;
  }

  /* zonegroup is not master zonegroup */
  if (!get_zonegroup().is_master) {
    return false;
  }

  /* single zonegroup and a single zone */
  if (current_period.is_single_zonegroup(cct, this) && get_zonegroup().zones.size() == 1) {
    return false;
  }

  /* zone is not master */
  if (get_zonegroup().master_zone.compare(zone_public_config.id) != 0) {
    return false;
  }

  return true;
}

解决方案

  1. rados命令手工删除对应的obj,但是要注意相应的bucket一定是不再需要的,最好是在多个集群上确认最终操作,确保数据一致性。
  2. 修改集群配置,满足上面4点需求之一。

最后非标准操作去删除bucket可能破坏底层数据一致性,起手无悔,一定要慎重。