private void initializeZKBasedSystemTrackers()
    throws IOException, KeeperException, ReplicationException, DeserializationException {
    if (maintenanceMode) {
      // in maintenance mode, always use MaintenanceLoadBalancer.
      conf.unset(LoadBalancer.HBASE_RSGROUP_LOADBALANCER_CLASS);
      conf.setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, MaintenanceLoadBalancer.class,
        LoadBalancer.class);
    }
    this.balancer = new RSGroupBasedLoadBalancer();
    this.loadBalancerStateStore = new LoadBalancerStateStore(masterRegion, zooKeeper);

    this.regionNormalizerManager =
      RegionNormalizerFactory.createNormalizerManager(conf, masterRegion, zooKeeper, this);
    this.configurationManager.registerObserver(regionNormalizerManager);
    this.regionNormalizerManager.start();

    this.splitOrMergeStateStore = new SplitOrMergeStateStore(masterRegion, zooKeeper, conf);

    // This is for backwards compatible. We do not need the CP for rs group now but if user want to
    // load it, we need to enable rs group.
    String[] cpClasses = conf.getStrings(MasterCoprocessorHost.MASTER_COPROCESSOR_CONF_KEY);
    if (cpClasses != null) {
      for (String cpClass : cpClasses) {
        if (RSGroupAdminEndpoint.class.getName().equals(cpClass)) {
          RSGroupUtil.enableRSGroup(conf);
          break;
        }
      }
    }
    this.rsGroupInfoManager = RSGroupInfoManager.create(this);

    this.replicationPeerManager = ReplicationPeerManager.create(this, clusterId);
    this.configurationManager.registerObserver(replicationPeerManager);
    this.replicationPeerModificationStateStore =
      new ReplicationPeerModificationStateStore(masterRegion);

    this.drainingServerTracker = new DrainingServerTracker(zooKeeper, this, this.serverManager);
    this.drainingServerTracker.start();

    this.snapshotCleanupStateStore = new SnapshotCleanupStateStore(masterRegion, zooKeeper);

    String clientQuorumServers = conf.get(HConstants.CLIENT_ZOOKEEPER_QUORUM);
    boolean clientZkObserverMode = conf.getBoolean(HConstants.CLIENT_ZOOKEEPER_OBSERVER_MODE,
      HConstants.DEFAULT_CLIENT_ZOOKEEPER_OBSERVER_MODE);
    if (clientQuorumServers != null && !clientZkObserverMode) {
      // we need to take care of the ZK information synchronization
      // if given client ZK are not observer nodes
      ZKWatcher clientZkWatcher = new ZKWatcher(conf,
        getProcessName() + ":" + rpcServices.getSocketAddress().getPort() + "-clientZK", this,
        false, true);
      this.metaLocationSyncer = new MetaLocationSyncer(zooKeeper, clientZkWatcher, this);
      this.metaLocationSyncer.start();
      this.masterAddressSyncer = new MasterAddressSyncer(zooKeeper, clientZkWatcher, this);
      this.masterAddressSyncer.start();
      // set cluster id is a one-go effort
      ZKClusterId.setClusterId(clientZkWatcher, fileSystemManager.getClusterId());
    }

    // Set the cluster as up. If new RSs, they'll be waiting on this before
    // going ahead with their startup.
    boolean wasUp = this.clusterStatusTracker.isClusterUp();
    if (!wasUp) this.clusterStatusTracker.setClusterUp();

    LOG.info("Active/primary master=" + this.serverName + ", sessionid=0x"
      + Long.toHexString(this.zooKeeper.getRecoverableZooKeeper().getSessionId())
      + ", setting cluster-up flag (Was=" + wasUp + ")");

    // create/initialize the snapshot manager and other procedure managers
    this.snapshotManager = new SnapshotManager();
    this.mpmHost = new MasterProcedureManagerHost();
    this.mpmHost.register(this.snapshotManager);
    this.mpmHost.register(new MasterFlushTableProcedureManager());
    this.mpmHost.loadProcedures(conf);
    this.mpmHost.initialize(this, this.metricsMaster);
  }
Initialize all ZK based system trackers. But do not include {@link RegionServerTracker}, it
should have already been initialized along with {@link ServerManager}.
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java