Collect Amazon MSK consumer-group metrics
With a managed Kafka exporter, an Amazon Managed Service for Prometheus collector collects consumer-group metrics from your Amazon MSK cluster, such as consumer lag, committed offsets, and the number of members in each consumer group. Amazon Managed Service for Prometheus runs the exporter for you, so you do not have to install or operate an exporter yourself. Your destination can be an Amazon Managed Service for Prometheus workspace or Amazon CloudWatch. These metrics complement the JMX and Node Exporter metrics that the collector scrapes from Open Monitoring.
The scraper connects to your cluster with AWS Identity and Access Management (IAM) authentication. You grant the scraper access to the cluster with an Amazon MSK cluster policy. To collect consumer-group metrics, create a scrape configuration, create a scraper, and then grant the scraper access to your cluster, as described in the following sections.
For information about the metrics, see Consumer-group metrics. To send the metrics to Amazon CloudWatch, see Collect Amazon MSK consumer-group metrics in CloudWatch.
Prerequisites
There are a few prerequisites for collecting consumer-group metrics:
An active Amazon MSK Provisioned cluster with Standard brokers and Apache Kafka version 3.6.0 or later, in the same account and AWS Region as the scraper.
IAM access control turned on for the cluster. You can keep TLS client authentication turned on at the same time, so clients that use certificates can continue to connect.
At least two subnets in different Availability Zones in the cluster's Amazon VPC, with DNS enabled.
Security groups that allow the scraper to reach the cluster's private IAM broker endpoints on port 9098. Add an inbound rule to the cluster's security group that allows TCP traffic on port 9098 from the security group that you provide for the scraper.
An Amazon Managed Service for Prometheus workspace in the scraper's Region, and an AWS CLI version that supports
kafkaConfigurationincreate-scraperandupdate-scraper.Permission to create or update a scraper and to validate the cluster:
kafka:DescribeClusterV2,kafka:GetBootstrapBrokers,kafka-cluster:Connect, andkafka-cluster:DescribeTopic. To add the cluster policy, you also needkafka:GetClusterPolicyandkafka:PutClusterPolicy. For the permissions to create the scraper's service-linked role, see Service-linked role permissions.
The scraper uses its service-linked role to connect to the cluster, so you do not provide a role for the exporter. By default, the role has no permissions for your cluster. You grant them in Grant the scraper access to the cluster.
The managed Kafka exporter does not support the following clusters:
Amazon MSK Serverless clusters. Serverless clusters do not accept cluster policies with
kafka-clusteractions. Use the metrics that Amazon MSK sends to CloudWatch instead.Clusters that do not have IAM authentication turned on.
Clusters in a different account or Region from the scraper.
Open Monitoring and broker ports 11001 and 11002 are needed only if you also collect JMX and Node Exporter metrics.
Create a scrape configuration
You provide a scrape configuration when you create the scraper. The managed
collector connects to the cluster that you specify and collects its metrics
automatically, so you do not specify scrape targets in the configuration. The
configuration must include a scrape_configs section with a job whose
job_name is exactly kafka-exporter. A configuration that
does not contain a job named kafka-exporter is rejected. The collector
sets the scrape interval for this job.
Use the scrape configuration to add labels and to filter the collected metrics.
The following example keeps consumer lag, committed offsets, and group membership.
It also adds a clusterArn label so that you can tell clusters apart
when you query. Replace the cluster ARN with your cluster's ARN, and save the
configuration as msk-consumer.yaml. Use the same cluster ARN
when you create the scraper.
global: scrape_interval: 30s scrape_configs: - job_name: kafka-exporter relabel_configs: - target_label: clusterArn replacement: 'arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id' metric_relabel_configs: - source_labels: [__name__] regex: kafka_consumergroup_(current_offset|members|lag) action: keep
The exporter can also send other metrics, such as topic and partition offsets
and partition counts. Amazon MSK already provides some of this information through Open
Monitoring and the metrics that Amazon MSK sends to
CloudWatch. To collect more exporter metrics, add them to the
regex, for example
kafka_consumergroup_(current_offset|members|lag)|kafka_topic_partitions.
Each metric that you add increases the number of series that you ingest.
To add the exporter to an existing scraper, add the kafka-exporter job
to the scraper's full scrape configuration, and keep its other jobs. Then update the
scraper as described in Update or
remove the exporter. You can relabel metrics in this job, but you cannot use
relabel rules to change how the collector connects to the exporter.
Create a scraper
To tell the scraper which cluster to collect from, you specify the cluster in the
exporters field of the request. For an Amazon MSK cluster, provide a
kafkaConfiguration with the clusterArn of the cluster. You
can also set a topicFilter and a consumerGroupFilter to
select topics and consumer groups by name. You provide the
networking (subnets and security group) separately in the source
field.
Use the create-scraper command to create a scraper using the
AWS Command Line Interface. The following example selects topics that start with
orders and consumer groups that start with payments.
Replace the example content, including both filters,
with your own cluster, networking, workspace, and filter values. To select all
topics or all consumer groups, omit the filter.
Note
Configure the security group and subnets to match the Amazon VPC of your Amazon MSK cluster. Include at least two subnets across two Availability Zones.
aws amp create-scraper \ --regionus-west-2\ --alias msk-consumer-metrics \ --source '{"vpcConfiguration":{"subnetIds":["subnet-subnet-id-1","subnet-subnet-id-2"],"securityGroupIds":["sg-security-group-id"]}}' \ --exporters '[{"kafkaConfiguration":{"clusterArn":"arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id","topicFilter":"^orders.*$","consumerGroupFilter":"^payments.*$"}}]' \ --cli-binary-format base64 \ --scrape-configuration "configurationBlob=$(base64 < msk-consumer.yaml | tr -d '\n')" \ --destination '{"ampConfiguration":{"workspaceArn":"arn:aws:aps:us-west-2:111122223333:workspace/workspace-id"}}'
Both filters are optional. If you omit a filter, the scraper selects all topics or
all consumer groups. Each filter must be a regular expression that starts with
^ and ends with $, with a maximum length of 256
characters. A scraper can have one exporter.
The topicFilter selects the topics that the exporter reads topic
metrics for. Consumer-group metrics can also include other topics that a selected
consumer group consumes. To control which metrics reach your destination, use
metric_relabel_configs in your scrape configuration.
Record the scraper ID. Check its status with the following command, and continue
when the status is ACTIVE:
aws amp describe-scraper \ --regionus-west-2\ --scraper-idscraper-id\ --query 'scraper.status.statusCode' --output text
The scraper does not collect Kafka metrics until you grant it access to the cluster.
Grant the scraper access to the cluster
The scraper needs permission to connect to your cluster and to read its topic and consumer-group metadata. Add an Amazon MSK cluster policy that allows the scraper's service-linked role the following actions:
kafka-cluster:Connecton the clusterkafka-cluster:DescribeTopicon its topicskafka-cluster:DescribeGroupon its consumer groups
Without this policy, the scraper is ACTIVE but does not collect Kafka
metrics. After you add the policy, the scraper starts collecting automatically, and
the first metrics can take a few minutes to appear. You do not need to update the
scraper.
Grant the scraper's service-linked role, even if the scraper uses
roleConfiguration to send metrics to a workspace in another account.
Do not grant the source role or the target role.
Grant one scraper
Get the scraper's role ARN with the following AWS CLI command:
aws amp describe-scraper \ --regionus-west-2\ --scraper-idscraper-id\ --query scraper.roleArn --output text
Each scraper has its own role,
AWSServiceRoleForAmazonPrometheusScraper_.
If you re-create a scraper, grant the new role.suffix
Save the following policy as policy.json. Replace the role
ARN, Region, account ID, cluster name, and cluster ID.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "scraper-role-arn" }, "Action": "kafka-cluster:Connect", "Resource": "arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id" }, { "Effect": "Allow", "Principal": { "AWS": "scraper-role-arn" }, "Action": "kafka-cluster:DescribeTopic", "Resource": "arn:aws:kafka:us-west-2:111122223333:topic/my-cluster/cluster-id/*" }, { "Effect": "Allow", "Principal": { "AWS": "scraper-role-arn" }, "Action": "kafka-cluster:DescribeGroup", "Resource": "arn:aws:kafka:us-west-2:111122223333:group/my-cluster/cluster-id/*" } ] }
To grant another scraper, add the three statements again with that scraper's role ARN. To grant fewer topics or consumer groups, edit the policy as described in Limit the topics and consumer groups before you apply it.
Apply the policy
Important
Do not use an account root principal, such as
arn:aws:iam::.
Amazon MSK accepts it, but it grants the scraper nothing. Do not use a wildcard
in a role ARN as the principal. Amazon MSK rejects it with the error
111122223333:rootThe cluster policy is not valid. To grant every scraper in
the account, see Optional:
Grant every scraper in the account.
To read and change the cluster policy, you need
kafka:GetClusterPolicy and
kafka:PutClusterPolicy.
To add the cluster policy
-
Check whether the cluster already has a policy:
aws kafka get-cluster-policy \ --regionus-west-2\ --cluster-arn arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-idA
NotFoundExceptionerror means that the cluster has no policy. -
If the cluster has no policy, add yours:
aws kafka put-cluster-policy \ --regionus-west-2\ --cluster-arn arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id\ --policy file://policy.json -
If the cluster already has a policy, merge the statements.
put-cluster-policyreplaces the whole policy document. ThePolicyvalue fromget-cluster-policyis the existing policy as a JSON string. Add its statements to theStatementlist inpolicy.json, so that the file has both the existing statements and the new ones. Then pass theCurrentVersionvalue fromget-cluster-policy:aws kafka put-cluster-policy \ --regionus-west-2\ --cluster-arn arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id\ --current-versioncurrent-version\ --policy file://policy.json
Optional: Grant every scraper in the account
We recommend that you grant access to individual scraper role ARNs. If you
need to grant every current and future scraper in the account, you can use the
following policy instead. You can add it before you create a scraper, and it
keeps working when you replace one. Keep both conditions in every statement.
Save the following policy
as policy.json. Replace the Region, account ID, cluster
name, and cluster ID in each statement, and apply it as described in
Apply the
policy.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "kafka-cluster:Connect", "Resource": "arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id", "Condition": { "StringEquals": { "aws:PrincipalAccount": "111122223333" }, "ArnLike": { "aws:PrincipalArn": "arn:aws:iam::111122223333:role/aws-service-role/scraper.aps.amazonaws.com/AWSServiceRoleForAmazonPrometheusScraper_*" } } }, { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "kafka-cluster:DescribeTopic", "Resource": "arn:aws:kafka:us-west-2:111122223333:topic/my-cluster/cluster-id/*", "Condition": { "StringEquals": { "aws:PrincipalAccount": "111122223333" }, "ArnLike": { "aws:PrincipalArn": "arn:aws:iam::111122223333:role/aws-service-role/scraper.aps.amazonaws.com/AWSServiceRoleForAmazonPrometheusScraper_*" } } }, { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "kafka-cluster:DescribeGroup", "Resource": "arn:aws:kafka:us-west-2:111122223333:group/my-cluster/cluster-id/*", "Condition": { "StringEquals": { "aws:PrincipalAccount": "111122223333" }, "ArnLike": { "aws:PrincipalArn": "arn:aws:iam::111122223333:role/aws-service-role/scraper.aps.amazonaws.com/AWSServiceRoleForAmazonPrometheusScraper_*" } } } ] }
This policy allows every current and future scraper in the account. The
aws:PrincipalAccount and ArnLike conditions are what
limit it. Do not remove either condition.
Limit the topics and consumer groups
Both policies grant all topics and consumer groups in the cluster. To grant
fewer, replace the final * in the topic and group ARNs, for
example
topic/.
These ARN patterns are IAM wildcards, not the my-cluster/cluster-id/orders-*topicFilter or
consumerGroupFilter regular expressions. If the policy grants
fewer topics or groups than the filters select, the scraper reports fewer
topics and offsets.
To narrow a policy that you already applied, replace your earlier statements with the narrowed ones. Do not merge them, because the earlier statements still grant all topics and groups.
Validate metrics collection
To confirm that the scraper is collecting metrics, run each of the following PromQL queries separately against your workspace. For more information, see Query your Prometheus metrics. Replace the cluster ARN. Metrics appear only for consumer groups that match your consumer-group filter and that have members or committed offsets.
kafka_consumergroup_members{clusterArn="arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id"}
kafka_consumergroup_current_offset{clusterArn="arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id"}
kafka_consumergroup_lag{clusterArn="arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id"}
The first metrics can take a few minutes to appear after you add the cluster policy. If no metrics appear after that, check the following. An empty result does not mean that consumer lag is zero.
If the scraper is
ACTIVE, butup{job="kafka-exporter"}is0and nokafka_*metrics appear, check the cluster policy. A successful create or update request does not mean that the scraper can access the cluster. Runaws kafka get-cluster-policy, and confirm that the policy grantskafka-cluster:Connect,kafka-cluster:DescribeTopic, andkafka-cluster:DescribeGroupto the scraper's current service-linked role ARN. If you re-created the scraper, its role ARN changed. If you use the account-wide policy, confirm that every statement keeps bothStringEqualsonaws:PrincipalAccountandArnLikeonaws:PrincipalArn. You do not need to update the scraper after you fix the policy.If creation or update fails with a permissions error, give the caller the scraper and cluster permissions in Prerequisites, then retry the command.
If the scraper cannot connect to the brokers, turn on IAM authentication for the cluster. Check VPC DNS and allow the scraper's security group to reach the private IAM broker endpoints on port 9098.
If the scraper is
ACTIVEbut the queries return no metrics, check thatconsumerGroupFiltermatches an existing consumer group. Keep the metric names and theclusterArn,consumergroup,topic, andpartitionlabels in the scrape configuration. Use the same cluster ARN in the configuration and query. If the cluster policy grants fewer topics or groups than the filters select, fewer topics and offsets appear.If the cluster policy is correct but
up{job="kafka-exporter"}is still0on a cluster with many topics and consumer groups, try narrowingtopicFilterandconsumerGroupFilter.
Update or remove the exporter
To change the filters, update the scraper with its full scrape configuration.
The following command selects one topic and one consumer group. Keep the
kafka-exporter job and the clusterArn label in your
scrape configuration.
aws amp update-scraper \ --regionus-west-2\ --scraper-idscraper-id\ --exporters '[{"kafkaConfiguration":{"clusterArn":"arn:aws:kafka:us-west-2:111122223333:cluster/my-cluster/cluster-id","topicFilter":"^orders$","consumerGroupFilter":"^payments$"}}]' \ --cli-binary-format base64 \ --scrape-configuration "configurationBlob=$(base64 < msk-consumer.yaml | tr -d '\n')"
Omitting exporters in an update keeps the current exporter. To
remove it, pass an empty list, --exporters '[]', and send the full
scrape configuration with the kafka-exporter job removed. Keep any
other jobs that you still need.
The following AWS CLI command deletes the scraper and stops all of its metric collection. It does not delete the Amazon MSK cluster or the destination workspace.
aws amp delete-scraper \ --regionus-west-2\ --scraper-idscraper-id
Remove the scraper's access to the cluster
Removing the cluster policy does not stop collection right away. To stop collection, remove the exporter or delete the scraper first. Then remove the policy statements.
To remove the scraper's access
-
Note the scraper's role ARN. Then remove the exporter or delete the scraper, as described earlier in this section.
-
Run
aws amp describe-scraper. Confirm that the scraper status isACTIVEand that the scraper has no exporter, or that the scraper no longer exists. Other scrapers can continue to send metrics for the same cluster. -
Run
aws kafka get-cluster-policy. Remove only the statements that you added for the scraper. Keep statements that grant access to other clients. If you used the account-wide policy and other scrapers still need access, replace its statements with statements that name the role ARN of each scraper that keeps access. -
Run
aws kafka put-cluster-policywith the remaining statements and theCurrentVersionvalue, as in Apply the policy. If no statements remain, delete the policy instead withaws kafka delete-cluster-policy. This command needs thekafka:DeleteClusterPolicypermission.