Пример использования Cruise Control

В статье описывается использование Cruise Control с Kafka в кластере ADS, в том числе примеры запросов на REST API при помощи инструмента командной строки cURL.

Предварительные требования

Ниже описано окружение, используемое для работы Cruise Control с Kafka в ADS.

Установка Cruise Control в ADS

Начиная с ADS 3.9.0.1.b1 Cruise Control может быть добавлен как компонент Kafka Cruise Control после добавления и перед установкой сервиса Kafka в составе кластера ADS.

В случае, если сервис Kafka уже установлен, после обновления кластера до нужной версии, компонент Kafka Cruise Control может быть добавлен при помощи действия Add/Remove components сервиса Kafka.

Настройка Cruise Control

При необходимости настройка параметров Cruise Control может быть выполнена в интерфейсе ADCM на странице конфигурирования компонента Kafka Cruise Control. Для настройки переведите в активное состояние переключатель Show advanced.

Для работы Cruise Control могут быть настроены:

  • Kонфигурационный файл основных параметров Cruise Control.

    Для настройки основных параметров раскройте узел cruisecontrol.properties в дереве конфигурационных настроек и введите новое значение для параметров. Описания параметров приведены в разделе Kafka → Конфигурационные параметры компонента Kafka Cruise Control статьи Конфигурационные параметры ADS.

  • Используемые ресурсы брокеров Kafka.

    Перед началом работы с Cruise Control пользователем может быть настроено мягкое ограничение ресурсов, доступных кластеру Kafka. Для этого используется пользовательский шаблон файла capacity.json — capacity.json config template.

    Для брокера могут быть переопределены параметры пространства диска, как показано ниже (для brokerId = -1 — значения указаны по умолчанию, для brokerId = 0 — значения переопределены):

    {
      "brokerCapacities":[
        {
          "brokerId": "-1",
          "capacity": {
            "DISK": "100000",
            "CPU": "100",
            "NW_IN": "10000",
            "NW_OUT": "10000"
          },
          "doc": "This is the default capacity. Capacity unit used for disk is in MB, cpu is in percentage, network throughput is in KB."
        },
        {
          "brokerId": "0",
          "capacity": {
            "DISK": "500000",
            "CPU": "100",
            "NW_IN": "50000",
            "NW_OUT": "50000"
          },
          "doc": "This overrides the capacity for broker 0."
        }
      ]
    }

    Настройка capacity.json не устанавливает жестких ограничений, а предоставляет Cruise Control информацию об объеме ресурсов хоста (процессор, память, дисковое пространство), выделенных кластеру Kafka, и система предлагает варианты оптимизации, основанные преимущественно на этих ограничениях.

После изменения параметров при помощи интерфейса ADCM перезагрузите сервис Kafka. Для этого примените действие Restart, нажав на иконку actions default dark actions default light в столбце Actions.

Запуск Cruise Control

Cruise Control автоматически запускается после установки в интерфейсе ADCM.

После завершения настройки и запуска Cruise Control должно пройти некоторое время, чтобы Metrics Reporter собрал начальные метрики, а Analyzer подготовил первые предложения по оптимизации. Для тестовых кластеров достаточно 10—​20 минут, но для рабочих кластеров, в зависимости от характера нагрузки кластера, рекомендуется 1—​2 часа.

Использование REST API Cruise Control

Взаимодействие с Cruise Control осуществляется при помощи запросов GET и POST, отправляемых на его REST API.

Запросы отправляются на адрес http://<hostname>:<port>, где:

  • <hostname> — имя хоста, на котором установлен компонент Kafka Cruise Control. Имя хоста для Cruise Control отображается на вкладке Info меню сервиса Kafka.

    Вкладка Info меню сервиса Kafka
    Вкладка Info меню сервиса Kafka
  • <port> — порт для подключения к Cruise Control. Указывается в качестве значения параметра webserver.http.port во время настройки компонента Kafka Cruise Control. Значение по умолчанию в ADS — 9181.

ПРИМЕЧАНИЕ

В запросах, приведенных ниже, для вывода ответов в JSON-формате используется параметр json, а для удобства чтения на хосте, на котором формируются REST-запросы, установлена утилита ./jq.

Состояние Cruise Control

Состояние Cruise Control можно получить, отправив запрос GET /kafkacruisecontrol/state:

$ curl -X GET 'http://10.92.40.27:9181/kafkacruisecontrol/state?json=true' |jq

Ниже приведен пример ответа о состоянии Cruise Control.

Состояние Cruise Control
{
  "AnalyzerState": {
    "isProposalReady": true,
    "readyGoals": [
      "NetworkInboundUsageDistributionGoal",
      "CpuUsageDistributionGoal",
      "PotentialNwOutGoal",
      "LeaderReplicaDistributionGoal",
      "NetworkInboundCapacityGoal",
      "LeaderBytesInDistributionGoal",
      "DiskCapacityGoal",
      "ReplicaDistributionGoal",
      "RackAwareGoal",
      "TopicReplicaDistributionGoal",
      "NetworkOutboundCapacityGoal",
      "CpuCapacityGoal",
      "DiskUsageDistributionGoal",
      "NetworkOutboundUsageDistributionGoal",
      "ReplicaCapacityGoal"
    ]
  },
  "MonitorState": {
    "trainingPct": 20,
    "trained": false,
    "numFlawedPartitions": 0,
    "state": "RUNNING",
    "numTotalPartitions": 190,
    "numMonitoredWindows": 5,
    "monitoringCoveragePct": 100,
    "reasonOfLatestPauseOrResume": "Resumed-By-Cruise-Control-Before-Starting-Execution (Date: 2025-08-25T07:28:21Z)",
    "numValidPartitions": 190
  },
  "ExecutorState": {
    "state": "NO_TASK_IN_PROGRESS"
  },
  "AnomalyDetectorState": {
    "recentBrokerFailures": [
      {
        "anomalyId": "cdfed8c7-b5a7-47cb-9733-9e7585166e3d",
        "failedBrokersByTimeMs": {
          "2": 1756105916891
        },
        "detectionMs": 1756105916899,
        "statusUpdateMs": 1756105916901,
        "status": "CHECK_WITH_DELAY"
      }
    ],
    "recentGoalViolations": [],
    "selfHealingDisabled": [
      "DISK_FAILURE",
      "BROKER_FAILURE",
      "GOAL_VIOLATION",
      "METRIC_ANOMALY",
      "TOPIC_ANOMALY",
      "MAINTENANCE_EVENT"
    ],
    "balancednessScore": 100,
    "selfHealingEnabled": [],
    "recentDiskFailures": [],
    "metrics": {
      "meanTimeBetweenAnomaliesMs": {
        "GOAL_VIOLATION": 0,
        "TOPIC_ANOMALY": 0,
        "MAINTENANCE_EVENT": 0,
        "METRIC_ANOMALY": 0.3756093819295242,
        "DISK_FAILURE": 0,
        "BROKER_FAILURE": 0.18780465267895471
      },
      "ongoingAnomalyDurationMs": 0,
      "numSelfHealingStarted": 0,
      "numSelfHealingFailedToStart": 0,
      "meanTimeToStartFixMs": 2072139
    },
    "recentMetricAnomalies": [
      {
        "anomalyId": "364e7ae2-6b4c-44ba-8ac6-e065706122bc",
        "detectionMs": 1756104828843,
        "description": "Metric value 16.250 of BROKER_PRODUCE_LOCAL_TIME_MS_50TH for brokerId=1,host=sov-ads-1.ru-central1.internal in window 2025-08-25T06:55:00Z is out of the normal range for percentile: [10.00, 90.00] (value: [0.000, 10.031] with margins (lower: 0.200, upper: 0.500)) in 20 history windows from 2025-08-25T06:50:00Z to 2025-08-25T05:15:00Z.",
        "statusUpdateMs": 1756104828845,
        "status": "IGNORED"
      },
      {
        "anomalyId": "7584c388-189b-40a7-b013-6f81fded6df8",
        "detectionMs": 1756104828845,
        "description": "Metric value 18.917 of BROKER_PRODUCE_LOCAL_TIME_MS_50TH for brokerId=2,host=sov-ads-5.ru-central1.internal in window 2025-08-25T06:55:00Z is out of the normal range for percentile: [10.00, 90.00] (value: [0.000, 2.700] with margins (lower: 0.200, upper: 0.500)) in 20 history windows from 2025-08-25T06:50:00Z to 2025-08-25T05:15:00Z.",
        "statusUpdateMs": 1756104828845,
        "status": "IGNORED"
      }
    ],
    "recentTopicAnomalies": [],
    "selfHealingEnabledRatio": {
      "DISK_FAILURE": 0,
      "BROKER_FAILURE": 0,
      "GOAL_VIOLATION": 0,
      "METRIC_ANOMALY": 0,
      "TOPIC_ANOMALY": 0,
      "MAINTENANCE_EVENT": 0
    },
    "recentMaintenanceEvents": []
  },
  "version": 1
}

В приведенном примере ответа отображается состояние всех компонентов Cruise Control (статусы, готовность предложений, используемые цели, найденные аномалии), в том числе описаны недавно обнаруженные аномалии метрик (recentMetricAnomalies), связанные с брокерами.

Нагрузка кластера

Информацию о нагрузке кластера и состоянии брокеров можно получить, отправив запрос GET /kafkacruisecontrol/load:

$ curl -X GET 'http://10.92.40.27:9181/kafkacruisecontrol/load?json=true' |jq

Ниже приведен пример ответа о нагрузке кластера.

Нагрузка кластера
{
  "brokers": [
    {
      "FollowerNwInRate": 0,
      "BrokerState": "ALIVE",
      "Broker": 1,
      "NwOutRate": 0.03215755149722099,
      "NumCore": 1,
      "Host": "sov-ads-1.ru-central1.internal",
      "CpuPct": 0.6822174191474915,
      "Replicas": 83,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-1.ru-central1.internal",
      "Leaders": 60,
      "DiskCapacityMB": 20000,
      "DiskMB": 13.415552139282227,
      "PnwOutRate": 0.03215755149722099,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.043243322521448135,
      "DiskPct": 0.06707776069641114
    },
    {
      "FollowerNwInRate": 0,
      "BrokerState": "ALIVE",
      "Broker": 2,
      "NwOutRate": 0.0601540207862854,
      "NumCore": 1,
      "Host": "sov-ads-5.ru-central1.internal",
      "CpuPct": 7.6233110427856445,
      "Replicas": 88,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-5.ru-central1.internal",
      "Leaders": 57,
      "DiskCapacityMB": 20000,
      "DiskMB": 12.10150146484375,
      "PnwOutRate": 0.0601540207862854,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.038225192576646805,
      "DiskPct": 0.06050750732421875
    },
    {
      "FollowerNwInRate": 0,
      "BrokerState": "ALIVE",
      "Broker": 3,
      "NwOutRate": 0.019182980060577393,
      "NumCore": 1,
      "Host": "sov-ads-9.ru-central1.internal",
      "CpuPct": 0.7776201963424683,
      "Replicas": 99,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-9.ru-central1.internal",
      "Leaders": 73,
      "DiskCapacityMB": 20000,
      "DiskMB": 6.148280143737793,
      "PnwOutRate": 0.019182980060577393,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.019607990980148315,
      "DiskPct": 0.030741400718688965
    }
  ],
  "hosts": [
    {
      "FollowerNwInRate": 0,
      "NwOutRate": 0.03215755149722099,
      "NumCore": 1,
      "Host": "sov-ads-1.ru-central1.internal",
      "CpuPct": 0.6822174191474915,
      "Replicas": 83,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-1.ru-central1.internal",
      "Leaders": 60,
      "DiskCapacityMB": 20000,
      "DiskMB": 13.415552139282227,
      "PnwOutRate": 0.03215755149722099,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.043243322521448135,
      "DiskPct": 0.06707776069641114
    },
    {
      "FollowerNwInRate": 0,
      "NwOutRate": 0.0601540207862854,
      "NumCore": 1,
      "Host": "sov-ads-5.ru-central1.internal",
      "CpuPct": 7.6233110427856445,
      "Replicas": 88,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-5.ru-central1.internal",
      "Leaders": 57,
      "DiskCapacityMB": 20000,
      "DiskMB": 12.10150146484375,
      "PnwOutRate": 0.0601540207862854,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.038225192576646805,
      "DiskPct": 0.06050750732421875
    },
    {
      "FollowerNwInRate": 0,
      "NwOutRate": 0.019182980060577393,
      "NumCore": 1,
      "Host": "sov-ads-9.ru-central1.internal",
      "CpuPct": 0.7776201963424683,
      "Replicas": 99,
      "NetworkInCapacity": 50000,
      "Rack": "sov-ads-9.ru-central1.internal",
      "Leaders": 73,
      "DiskCapacityMB": 20000,
      "DiskMB": 6.148280143737793,
      "PnwOutRate": 0.019182980060577393,
      "NetworkOutCapacity": 50000,
      "LeaderNwInRate": 0.019607990980148315,
      "DiskPct": 0.030741400718688965
    }
  ],
  "version": 1
}
ПРИМЕЧАНИЕ

Показанная нагрузка относится только к нагрузке от партиций с достаточным количеством образцов метрик. Поэтому всегда проверяйте состояние LoadMonitor (через конечную точку state, как показано выше), чтобы решить, является ли рабочая нагрузка достаточно представительной.

Просмотр предложений

Предложения по оптимизации от Cruise Control можно получить, отправив запрос GET /kafkacruisecontrol/proposals:

$ curl -X GET 'http://10.92.40.27:9181/kafkacruisecontrol/proposals?json=true' |jq

Для наглядности перед просмотром предложений в кластер был добавлен новый брокер и партиции были автоматически перераспределены.

Ниже приведен ответ после запроса предложений Cruise Control.

Предложения по оптимизации
{  "summary": {
    "numIntraBrokerReplicaMovements": 0,
    "numReplicaMovements": 97,
    "onDemandBalancednessScoreAfter": 79.74705957325753,
    "intraBrokerDataToMoveMB": 0,
    "monitoredPartitionsPercentage": 100,
    "provisionRecommendation": "",
    "excludedBrokersForReplicaMove": [],
    "excludedBrokersForLeadership": [],
    "provisionStatus": "RIGHT_SIZED",
    "onDemandBalancednessScoreBefore": 74.5020336497431,
    "recentWindows": 5,
    "dataToMoveMB": 0,
    "excludedTopics": [],
    "numLeaderMovements": 0
  },
  "goalSummary": [
   ...
    {
      "clusterModelStats": {
        "statistics": {
          "AVG": {
            "disk": 8.032857894897461,
            "replicas": 67.5,
            "leaderReplicas": 47.5,
            "cpu": 1.4941092729568481,
            "networkOutbound": 0.02796957641839981,
            "networkInbound": 0.026663552969694138,
            "topicReplicas": 7.5,
            "potentialNwOut": 0.027969577349722385
          },
          "STD": {
            "disk": 5.044990525164198,
            "replicas": 3.774917217635375,
            "leaderReplicas": 8.440971508067067,
            "cpu": 1.7554403795885893,
            "networkOutbound": 0.02202569000419393,
            "networkInbound": 0.010510778657732341,
            "topicReplicas": 4.514831618707495,
            "potentialNwOut": 0.02202569000419391
          },
          "MIN": {
            "disk": 0.5629663467407227,
            "replicas": 61,
            "leaderReplicas": 38,
            "cpu": 0.1823471486568451,
            "networkOutbound": 0,
            "networkInbound": 0.011331086046993732,
            "topicReplicas": 0,
            "potentialNwOut": 0
          },
          "MAX": {
            "disk": 12.988670349121094,
            "replicas": 70,
            "leaderReplicas": 61,
            "cpu": 4.5058794021606445,
            "networkOutbound": 0.06056395173072815,
            "networkInbound": 0.03814876452088356,
            "topicReplicas": 20,
            "potentialNwOut": 0.06056395173072815
          }
        },
        "metadata": {
          "topics": 9,
          "replicas": 270,
          "brokers": 4
        }
      },
      "optimizationTimeMs": 5,
      "status": "VIOLATED",
      "goal": "DiskUsageDistributionGoal"
    },
    ...
    ...
    {
      "clusterModelStats": {
        "statistics": {
          "AVG": {
            "disk": 8.032857894897461,
            "replicas": 67.5,
            "leaderReplicas": 47.5,
            "cpu": 1.4941092729568481,
            "networkOutbound": 0.02796957641839981,
            "networkInbound": 0.026663552969694138,
            "topicReplicas": 7.5,
            "potentialNwOut": 0.027969577349722385
          },
          "STD": {
            "disk": 5.044990525164198,
            "replicas": 3.774917217635375,
            "leaderReplicas": 8.440971508067067,
            "cpu": 1.748044132782149,
            "networkOutbound": 0.02202569000419393,
            "networkInbound": 0.007883814130179204,
            "topicReplicas": 4.656829177051786,
            "potentialNwOut": 0.02202569000419391
          },
          "MIN": {
            "disk": 0.5629663467407227,
            "replicas": 61,
            "leaderReplicas": 38,
            "cpu": 0.2709278166294098,
            "networkOutbound": 0,
            "networkInbound": 0.016833635047078133,
            "topicReplicas": 0,
            "potentialNwOut": 0
          },
          "MAX": {
            "disk": 12.988670349121094,
            "replicas": 70,
            "leaderReplicas": 61,
            "cpu": 4.5058794021606445,
            "networkOutbound": 0.06056395173072815,
            "networkInbound": 0.03814876452088356,
            "topicReplicas": 21,
            "potentialNwOut": 0.06056395173072815
          }
        },
        "metadata": {
          "topics": 9,
          "replicas": 270,
          "brokers": 4
        }
      },
      "optimizationTimeMs": 1,
      "status": "VIOLATED",
      "goal": "CpuUsageDistributionGoal"
    },
   ...
   ...
    {
      "clusterModelStats": {
        "statistics": {
          "AVG": {
            "disk": 8.032857894897461,
            "replicas": 67.5,
            "leaderReplicas": 47.5,
            "cpu": 1.4941092729568481,
            "networkOutbound": 0.02796957641839981,
            "networkInbound": 0.026663552969694138,
            "topicReplicas": 7.5,
            "potentialNwOut": 0.027969577349722385
          },
          "STD": {
            "disk": 5.044990525164198,
            "replicas": 3.774917217635375,
            "leaderReplicas": 8.440971508067067,
            "cpu": 1.748044132782149,
            "networkOutbound": 0.02202569000419393,
            "networkInbound": 0.007883814130179204,
            "topicReplicas": 4.656829177051786,
            "potentialNwOut": 0.02202569000419391
          },
          "MIN": {
            "disk": 0.5629663467407227,
            "replicas": 61,
            "leaderReplicas": 38,
            "cpu": 0.2709278166294098,
            "networkOutbound": 0,
            "networkInbound": 0.016833635047078133,
            "topicReplicas": 0,
            "potentialNwOut": 0
          },
          "MAX": {
            "disk": 12.988670349121094,
            "replicas": 70,
            "leaderReplicas": 61,
            "cpu": 4.5058794021606445,
            "networkOutbound": 0.06056395173072815,
            "networkInbound": 0.03814876452088356,
            "topicReplicas": 21,
            "potentialNwOut": 0.06056395173072815
          }
        },
        "metadata": {
          "topics": 9,
          "replicas": 270,
          "brokers": 4
        }
      },
      "optimizationTimeMs": 1,
      "status": "VIOLATED",
      "goal": "LeaderBytesInDistributionGoal"
    }
  ],
  "loadAfterOptimization": {
    "brokers": [
      {
        "FollowerNwInRate": 0,
        "BrokerState": "ALIVE",
        "Broker": 1,
        "NwOutRate": 0.032181717455387115,
        "NumCore": 1,
        "Host": "sov-ads-1.ru-central1.internal",
        "CpuPct": 0.767410159111023,
        "Replicas": 61,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-1.ru-central1.internal",
        "Leaders": 61,
        "DiskCapacityMB": 20000,
        "DiskMB": 12.988670349121094,
        "PnwOutRate": 0.032181717455387115,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.028894560411572456,
        "DiskPct": 0.06494335174560546
      },
      {
        "FollowerNwInRate": 0,
        "BrokerState": "ALIVE",
        "Broker": 2,
        "NwOutRate": 0.06056395173072815,
        "NumCore": 1,
        "Host": "sov-ads-5.ru-central1.internal",
        "CpuPct": 4.5058794021606445,
        "Replicas": 69,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-5.ru-central1.internal",
        "Leaders": 38,
        "DiskCapacityMB": 20000,
        "DiskMB": 12.313807487487793,
        "PnwOutRate": 0.06056395173072815,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.03814876452088356,
        "DiskPct": 0.06156903743743897
      },
      {
        "FollowerNwInRate": 0,
        "BrokerState": "ALIVE",
        "Broker": 3,
        "NwOutRate": 0.019132640212774277,
        "NumCore": 1,
        "Host": "sov-ads-9.ru-central1.internal",
        "CpuPct": 0.4322197437286377,
        "Replicas": 70,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-9.ru-central1.internal",
        "Leaders": 44,
        "DiskCapacityMB": 20000,
        "DiskMB": 6.265987396240234,
        "PnwOutRate": 0.019132640212774277,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.0227772518992424,
        "DiskPct": 0.03132993698120117
      },
      {
        "FollowerNwInRate": 0,
        "BrokerState": "ALIVE",
        "Broker": 4,
        "NwOutRate": 0,
        "NumCore": 1,
        "Host": "sov-ads-6.ru-central1.internal",
        "CpuPct": 0.2709278166294098,
        "Replicas": 70,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-6.ru-central1.internal",
        "Leaders": 47,
        "DiskCapacityMB": 20000,
        "DiskMB": 0.5629663467407227,
        "PnwOutRate": 0,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.016833635047078133,
        "DiskPct": 0.0028148317337036133
      }
    ],
    "hosts": [
      {
        "FollowerNwInRate": 0,
        "NwOutRate": 0.032181717455387115,
        "NumCore": 1,
        "Host": "sov-ads-1.ru-central1.internal",
        "CpuPct": 0.767410159111023,
        "Replicas": 61,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-1.ru-central1.internal",
        "Leaders": 61,
        "DiskCapacityMB": 20000,
        "DiskMB": 12.988670349121094,
        "PnwOutRate": 0.032181717455387115,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.028894560411572456,
        "DiskPct": 0.06494335174560546
      },
      {
        "FollowerNwInRate": 0,
        "NwOutRate": 0.06056395173072815,
        "NumCore": 1,
        "Host": "sov-ads-5.ru-central1.internal",
        "CpuPct": 4.5058794021606445,
        "Replicas": 69,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-5.ru-central1.internal",
        "Leaders": 38,
        "DiskCapacityMB": 20000,
        "DiskMB": 12.313807487487793,
        "PnwOutRate": 0.06056395173072815,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.03814876452088356,
        "DiskPct": 0.06156903743743897
      },
      {
        "FollowerNwInRate": 0,
        "NwOutRate": 0,
        "NumCore": 1,
        "Host": "sov-ads-6.ru-central1.internal",
        "CpuPct": 0.2709278166294098,
        "Replicas": 70,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-6.ru-central1.internal",
        "Leaders": 47,
        "DiskCapacityMB": 20000,
        "DiskMB": 0.5629663467407227,
        "PnwOutRate": 0,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.016833635047078133,
        "DiskPct": 0.0028148317337036133
      },
      {
        "FollowerNwInRate": 0,
        "NwOutRate": 0.019132640212774277,
        "NumCore": 1,
        "Host": "sov-ads-9.ru-central1.internal",
        "CpuPct": 0.4322197437286377,
        "Replicas": 70,
        "NetworkInCapacity": 50000,
        "Rack": "sov-ads-9.ru-central1.internal",
        "Leaders": 44,
        "DiskCapacityMB": 20000,
        "DiskMB": 6.265987396240234,
        "PnwOutRate": 0.019132640212774277,
        "NetworkOutCapacity": 50000,
        "LeaderNwInRate": 0.0227772518992424,
        "DiskPct": 0.03132993698120117
      }
    ]
  },
  "version": 1
}

В разделе summary показан обзор предложения. В приведенном примере ответа предлагается перемещение 97 реплик (параметр numReplicaMovements).

В разделе goalSummary показан обзор целей, где приводится описание целей, которые нарушаются (в статусе VIOLATED). В данном примере оставлены только нарушенные цели, но отчет выводится по всем заданным целям, в том числе не нарушенным (в статусе NO-ACTION).

В приведенном примере ответа использование диска между брокерами нарушается, то есть у некоторых брокеров партиции занимают больше места, чем у других, а также распределение лидеров несбалансировано. Это основная причина, по которой анализатор хочет переместить 97 реплик.

В разделе loadAfterOptimization показана модель нагрузки кластера после предложенной оптимизации.

Принятие предложений

Предложения по оптимизации от Cruise Control можно принять, запустив перебалансировку при помощи запроса POST /kafkacruisecontrol/rebalance:

$ curl -X POST 'http://10.92.40.27:9181/kafkacruisecontrol/rebalance?dryrun=false&json=true' |jq

где при помощи параметра dryrun указывается, выполнить ли пробный запуск запроса.

Ответ на запрос приводится идентичный запросу получения предложений.

Если после перебалансировки выполнить запрос нагрузки кластера, в ответе на запрос можно увидеть, что имеющаяся нагрузка кластера совпадает с моделью нагрузки, показанной в предложении.

Проверка статуса запросов

Пользователь может просмотреть состояние запрашиваемых задач при помощи запроса GET /kafkacruisecontrol/user_tasks:

$ curl -X GET 'http://10.92.40.27:9181/kafkacruisecontrol/user_tasks?json=true' |jq

Ниже приведен ответ после запроса статусов запросов Cruise Control.

Статусы запросов
{
  "userTasks": [
    {
      "Status": "CompletedWithError",
      "ClientIdentity": "10.92.40.27",
      "RequestURL": "GET /kafkacruisecontrol/proposals?json=true",
      "UserTaskId": "b6bb21c1-23a3-4981-b051-a9a06a34fc73",
      "StartMs": "1756106056396"
    },
    {
      "Status": "Completed",
      "ClientIdentity": "10.92.40.27",
      "RequestURL": "GET /kafkacruisecontrol/load?json=true",
      "UserTaskId": "d246263f-b1f9-4c02-a84a-c916571a0982",
      "StartMs": "1756111195815"
    },
    {
      "Status": "Completed",
      "ClientIdentity": "10.92.40.27",
      "RequestURL": "POST /kafkacruisecontrol/rebalance?dryrun=false&json=true",
      "UserTaskId": "7997fd56-64d3-427b-874b-d99d08a0d9f5",
      "StartMs": "1756106900752"
    },
    {
      "Status": "Completed",
      "ClientIdentity": "10.92.40.27",
      "RequestURL": "GET /kafkacruisecontrol/state?json=true",
      "UserTaskId": "7007d120-1139-4b5f-a827-0be23ba33597",
      "StartMs": "1756105986205"
    }
  ],
  "version": 1
}
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней