-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zone aware ingesters #7923
Merged
Merged
Zone aware ingesters #7923
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
d433d7d
zone aware ingesters
manohar-koukuntla fa393e0
update change log
manohar-koukuntla 9a917a4
remove prof files
manohar-koukuntla 635d327
remove prof files
manohar-koukuntla c7a04d1
jsonnet fmt
manohar-koukuntla 9e05317
replace null with {}
manohar-koukuntla 10d43a0
replace null with {}
manohar-koukuntla 37f7335
Merge branch 'grafana:main' into zone_aware_ingesters
manohar-koukuntla File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
# Deploy Loki to Kubernetes | ||
|
||
See the [Tanka Installation Docs](../../docs/sources/installation/tanka.md) | ||
|
||
## Multizone ingesters | ||
To use multizone ingesters use following config fields | ||
``` | ||
_config+: { | ||
multi_zone_ingester_enabled: false, | ||
multi_zone_ingester_migration_enabled: false, | ||
multi_zone_ingester_replicas: 0, | ||
multi_zone_ingester_max_unavailable: 25, | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
{ | ||
local container = $.core.v1.container, | ||
local deployment = $.apps.v1.deployment, | ||
local statefulSet = $.apps.v1.statefulSet, | ||
local podDisruptionBudget = $.policy.v1beta1.podDisruptionBudget, | ||
local volume = $.core.v1.volume, | ||
local roleBinding = $.rbac.v1.roleBinding, | ||
local role = $.rbac.v1.role, | ||
local service = $.core.v1.service, | ||
local serviceAccount = $.core.v1.serviceAccount, | ||
local servicePort = $.core.v1.servicePort, | ||
local policyRule = $.rbac.v1.policyRule, | ||
local podAntiAffinity = deployment.mixin.spec.template.spec.affinity.podAntiAffinity, | ||
|
||
_config+: { | ||
multi_zone_ingester_enabled: false, | ||
multi_zone_ingester_migration_enabled: false, | ||
multi_zone_ingester_replicas: 0, | ||
multi_zone_ingester_max_unavailable: 25, | ||
|
||
loki+: { | ||
ingester+: { | ||
lifecycler+: { | ||
ring+: (if $._config.multi_zone_ingester_enabled then { zone_awareness_enabled: $._config.multi_zone_ingester_enabled } else {}), | ||
} + (if $._config.multi_zone_ingester_enabled then { availability_zone: '${AVAILABILITY_ZONE}' } else {}), | ||
}, | ||
}, | ||
}, | ||
|
||
// | ||
// Multi-zone ingesters. | ||
// | ||
|
||
ingester_zone_a_args:: {}, | ||
ingester_zone_b_args:: {}, | ||
ingester_zone_c_args:: {}, | ||
|
||
newIngesterZoneContainer(zone, zone_args):: | ||
local zone_name = 'zone-%s' % zone; | ||
|
||
$.ingester_container + | ||
container.withArgs($.util.mapToFlags( | ||
$.ingester_args + zone_args | ||
)) + | ||
container.withEnvMixin([{ name: 'AVAILABILITY_ZONE', value: zone_name }]), | ||
|
||
newIngesterZoneStatefulSet(zone, container):: | ||
local name = 'ingester-zone-%s' % zone; | ||
|
||
$.newIngesterStatefulSet(name, container) + | ||
statefulSet.mixin.metadata.withLabels({ 'rollout-group': 'ingester' }) + | ||
statefulSet.mixin.metadata.withAnnotations({ 'rollout-max-unavailable': std.toString($._config.multi_zone_ingester_max_unavailable) }) + | ||
statefulSet.mixin.spec.template.metadata.withLabels({ name: name, 'rollout-group': 'ingester' }) + | ||
statefulSet.mixin.spec.selector.withMatchLabels({ name: name, 'rollout-group': 'ingester' }) + | ||
statefulSet.mixin.spec.updateStrategy.withType('OnDelete') + | ||
statefulSet.mixin.spec.template.spec.withTerminationGracePeriodSeconds(1200) + | ||
statefulSet.mixin.spec.withReplicas(std.ceil($._config.multi_zone_ingester_replicas / 3)) + | ||
(if !std.isObject($._config.node_selector) then {} else statefulSet.mixin.spec.template.spec.withNodeSelectorMixin($._config.node_selector)) + | ||
if $._config.ingester_allow_multiple_replicas_on_same_node then {} else { | ||
spec+: | ||
// Allow to schedule 2+ ingesters in the same zone on the same node, but do not schedule 2+ ingesters in | ||
// different zones on the same node. In case of 1 node failure in the Kubernetes cluster, only ingesters | ||
// in 1 zone will be affected. | ||
podAntiAffinity.withRequiredDuringSchedulingIgnoredDuringExecution([ | ||
podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecutionType.new() + | ||
podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecutionType.mixin.labelSelector.withMatchExpressions([ | ||
{ key: 'rollout-group', operator: 'In', values: ['ingester'] }, | ||
{ key: 'name', operator: 'NotIn', values: [name] }, | ||
]) + | ||
podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecutionType.withTopologyKey('kubernetes.io/hostname'), | ||
]).spec, | ||
}, | ||
|
||
// Creates a headless service for the per-zone ingesters StatefulSet. We don't use it | ||
// but we need to create it anyway because it's responsible for the network identity of | ||
// the StatefulSet pods. For more information, see: | ||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#statefulset-v1-apps | ||
newIngesterZoneService(sts):: | ||
$.util.serviceFor(sts, $._config.service_ignored_labels) + | ||
service.mixin.spec.withClusterIp('None'), // Headless. | ||
|
||
ingester_zone_a_container:: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneContainer('a', $.ingester_zone_a_args), | ||
|
||
ingester_zone_a_statefulset: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneStatefulSet('a', $.ingester_zone_a_container), | ||
|
||
ingester_zone_a_service: if !$._config.multi_zone_ingester_enabled then {} else | ||
$.newIngesterZoneService($.ingester_zone_a_statefulset), | ||
|
||
ingester_zone_b_container:: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneContainer('b', $.ingester_zone_b_args), | ||
|
||
ingester_zone_b_statefulset: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneStatefulSet('b', $.ingester_zone_b_container), | ||
|
||
ingester_zone_b_service: if !$._config.multi_zone_ingester_enabled then {} else | ||
$.newIngesterZoneService($.ingester_zone_b_statefulset), | ||
|
||
ingester_zone_c_container:: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneContainer('c', $.ingester_zone_c_args), | ||
|
||
ingester_zone_c_statefulset: if !$._config.multi_zone_ingester_enabled then {} else | ||
self.newIngesterZoneStatefulSet('c', $.ingester_zone_c_container), | ||
|
||
ingester_zone_c_service: if !$._config.multi_zone_ingester_enabled then {} else | ||
$.newIngesterZoneService($.ingester_zone_c_statefulset), | ||
|
||
ingester_rollout_pdb: if !$._config.multi_zone_ingester_enabled then {} else | ||
podDisruptionBudget.new('ingester-rollout-pdb') + | ||
podDisruptionBudget.mixin.metadata.withLabels({ name: 'ingester-rollout-pdb' }) + | ||
podDisruptionBudget.mixin.spec.selector.withMatchLabels({ 'rollout-group': 'ingester' }) + | ||
podDisruptionBudget.mixin.spec.withMaxUnavailable(1), | ||
|
||
// | ||
// Single-zone ingesters shouldn't be configured when multi-zone is enabled. | ||
// | ||
|
||
ingester_statefulset: | ||
// Remove the default "ingester" StatefulSet if multi-zone is enabled and no migration is in progress. | ||
if $._config.multi_zone_ingester_enabled && !$._config.multi_zone_ingester_migration_enabled | ||
then {} | ||
else super.ingester_statefulset, | ||
|
||
ingester_service: | ||
// Remove the default "ingester" service if multi-zone is enabled and no migration is in progress. | ||
if $._config.multi_zone_ingester_enabled && !$._config.multi_zone_ingester_migration_enabled | ||
then {} | ||
else super.ingester_service, | ||
|
||
ingester_pdb: | ||
// Keep it if multi-zone is disabled. | ||
if !$._config.multi_zone_ingester_enabled | ||
then super.ingester_pdb | ||
// We don’t want Kubernetes to terminate any "ingester" StatefulSet's pod while migration is in progress. | ||
else if $._config.multi_zone_ingester_migration_enabled | ||
then super.ingester_pdb + podDisruptionBudget.mixin.spec.withMaxUnavailable(0) | ||
// Remove it if multi-zone is enabled and no migration is in progress. | ||
else {}, | ||
|
||
// | ||
// Rollout operator. | ||
// | ||
|
||
local rollout_operator_enabled = $._config.multi_zone_ingester_enabled, | ||
|
||
rollout_operator_args:: { | ||
'kubernetes.namespace': $._config.namespace, | ||
}, | ||
|
||
rollout_operator_container:: | ||
container.new('rollout-operator', $._images.rollout_operator) + | ||
container.withArgsMixin($.util.mapToFlags($.rollout_operator_args)) + | ||
container.withPorts([ | ||
$.core.v1.containerPort.new('http-metrics', 8001), | ||
]) + | ||
$.util.resourcesRequests('100m', '100Mi') + | ||
$.util.resourcesLimits('1', '200Mi') + | ||
container.mixin.readinessProbe.httpGet.withPath('/ready') + | ||
container.mixin.readinessProbe.httpGet.withPort(8001) + | ||
container.mixin.readinessProbe.withInitialDelaySeconds(5) + | ||
container.mixin.readinessProbe.withTimeoutSeconds(1), | ||
|
||
rollout_operator_deployment: if !rollout_operator_enabled then {} else | ||
deployment.new('rollout-operator', 1, [$.rollout_operator_container]) + | ||
deployment.mixin.metadata.withName('rollout-operator') + | ||
deployment.mixin.spec.template.spec.withServiceAccountName('rollout-operator') + | ||
// Ensure Kubernetes doesn't run 2 operators at the same time. | ||
deployment.mixin.spec.strategy.rollingUpdate.withMaxSurge(0) + | ||
deployment.mixin.spec.strategy.rollingUpdate.withMaxUnavailable(1), | ||
|
||
rollout_operator_role: if !rollout_operator_enabled then {} else | ||
role.new('rollout-operator-role') + | ||
role.mixin.metadata.withNamespace($._config.namespace) + | ||
role.withRulesMixin([ | ||
policyRule.withApiGroups('') + | ||
policyRule.withResources(['pods']) + | ||
policyRule.withVerbs(['list', 'get', 'watch', 'delete']), | ||
policyRule.withApiGroups('apps') + | ||
policyRule.withResources(['statefulsets']) + | ||
policyRule.withVerbs(['list', 'get', 'watch']), | ||
policyRule.withApiGroups('apps') + | ||
policyRule.withResources(['statefulsets/status']) + | ||
policyRule.withVerbs(['update']), | ||
]), | ||
|
||
rollout_operator_rolebinding: if !rollout_operator_enabled then {} else | ||
roleBinding.new('rollout-operator-rolebinding') + | ||
roleBinding.mixin.metadata.withNamespace($._config.namespace) + | ||
roleBinding.mixin.roleRef.withApiGroup('rbac.authorization.k8s.io') + | ||
roleBinding.mixin.roleRef.withKind('Role') + | ||
roleBinding.mixin.roleRef.withName('rollout-operator-role') + | ||
roleBinding.withSubjectsMixin({ | ||
kind: 'ServiceAccount', | ||
name: 'rollout-operator', | ||
namespace: $._config.namespace, | ||
}), | ||
|
||
rollout_operator_service_account: if !rollout_operator_enabled then {} else | ||
serviceAccount.new('rollout-operator'), | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this from mimir or did you add it yourself? if the latter, do you mind leaving a comment as to what the intended use is for the env var?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am using the same concept we are using in mimir. Since mimir does extra tweaks on top of standard cortex zone awareness, I am using default cortex setting for loki and tempo(grafana/tempo#1936).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if I was unclear, I am asking about the environment variable itself. I don't see a reason why we're adding it.