Skip to content
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

Move purger API endpoints to compactor #2644

Merged
merged 5 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* [CHANGE] Distributor: removed previously deprecated `extend_writes` (see #1856) YAML key and `-distributor.extend-writes` CLI flag from the distributor config. #2551
* [CHANGE] Ingester: removed previously deprecated `active_series_custom_trackers` (see #1188) YAML key from the ingester config. #2552
* [CHANGE] The tenant ID `__mimir_cluster` is reserved by Mimir and not allowed to store metrics. #2643
* [CHANGE] Purger: removed the purger component and moved its API endpoints `/purger/delete_tenant` and `/purger/delete_tenant_status` to the compactor at `/compactor/delete_tenant` and `/compactor/delete_tenant_status`. #2644
* [FEATURE] Compactor: Adds the ability to delete partial blocks after a configurable delay. This option can be configured per tenant. #2285
- `-compactor.partial-block-deletion-delay`, as a duration string, allows you to set the delay since a partial block has been modified before marking it for deletion. A value of `0`, the default, disables this feature.
- The metric `cortex_compactor_blocks_marked_for_deletion_total` has a new value for the `reason` label `reason="partial"`, when a block deletion marker is triggered by the partial block deletion delay.
Expand Down
8 changes: 0 additions & 8 deletions development/tsdb-blocks-storage-s3/docker-compose.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ std.manifestYamlDoc({
self.compactor +
self.rulers(2) +
self.alertmanagers(3) +
self.purger +
self.minio +
self.prometheus +
self.grafana_agent +
Expand Down Expand Up @@ -133,13 +132,6 @@ std.manifestYamlDoc({
}),
},

purger:: {
purger: mimirService({
target: 'purger',
httpPort: 8014,
}),
},

local all_rings = ['-ingester.ring', '-distributor.ring', '-compactor.ring', '-store-gateway.sharding-ring', '-ruler.ring', '-alertmanager.sharding-ring'],

// This function builds docker-compose declaration for Mimir service.
Expand Down
23 changes: 0 additions & 23 deletions development/tsdb-blocks-storage-s3/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,29 +228,6 @@
- "9090:9090"
"volumes":
- "./config:/etc/prometheus"
"purger":
"build":
"context": "."
"dockerfile": "dev.dockerfile"
"command":
- "sh"
- "-c"
- "sleep 3 && exec ./mimir -config.file=./config/mimir.yaml -target=purger -server.http-listen-port=8014 -server.grpc-listen-port=9014 -activity-tracker.filepath=/activity/purger-8014 -memberlist.nodename=purger -memberlist.bind-port=10014 -ingester.ring.store=memberlist -distributor.ring.store=memberlist -compactor.ring.store=memberlist -store-gateway.sharding-ring.store=memberlist -ruler.ring.store=memberlist -alertmanager.sharding-ring.store=memberlist"
"depends_on":
- "minio"
- "distributor-1"
"environment":
- "JAEGER_AGENT_HOST=jaeger"
- "JAEGER_AGENT_PORT=6831"
- "JAEGER_SAMPLER_PARAM=1"
- "JAEGER_SAMPLER_TYPE=const"
- "JAEGER_TAGS=app=purger"
"image": "mimir"
"ports":
- "8014:8014"
"volumes":
- "./config:/mimir/config"
- "./activity:/activity"
"querier":
"build":
"context": "."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ The following features are currently experimental:
- `-distributor.request-rate-limit`
- `-distributor.request-burst-limit`
- OTLP ingestion path
- Purger: Tenant deletion API
- Exemplar storage
- `-ingester.max-global-exemplars-per-user`
- `-ingester.exemplars-update-period`
Expand Down Expand Up @@ -96,6 +95,7 @@ The following features are currently experimental:
- `-ruler-storage.storage-prefix`
- Compactor
- HTTP API for uploading TSDB blocks
- Tenant deletion API

## Deprecated features

Expand Down
48 changes: 22 additions & 26 deletions docs/sources/operators-guide/reference-http-api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ This document groups API endpoints by service. Note that the API endpoints are e
| [Get Alertmanager configuration](#get-alertmanager-configuration) | Alertmanager | `GET /api/v1/alerts` |
| [Set Alertmanager configuration](#set-alertmanager-configuration) | Alertmanager | `POST /api/v1/alerts` |
| [Delete Alertmanager configuration](#delete-alertmanager-configuration) | Alertmanager | `DELETE /api/v1/alerts` |
| [Tenant delete request](#tenant-delete-request) | Purger | `POST /purger/delete_tenant` |
| [Tenant delete status](#tenant-delete-status) | Purger | `GET /purger/delete_tenant_status` |
| [Store-gateway ring status](#store-gateway-ring-status) | Store-gateway | `GET /store-gateway/ring` |
| [Store-gateway tenants](#store-gateway-tenants) | Store-gateway | `GET /store-gateway/tenants` |
| [Store-gateway tenant blocks](#store-gateway-tenant-blocks) | Store-gateway | `GET /store-gateway/tenant/{tenant}/blocks` |
Expand All @@ -81,6 +79,8 @@ This document groups API endpoints by service. Note that the API endpoints are e
| [Upload block file](#upload-block-file) | Compactor | `POST /api/v1/upload/block/{block}/files?path={path}` |
| [Complete block upload](#complete-block-upload) | Compactor | `POST /api/v1/upload/block/{block}/finish` |
| [Check block upload](#check-block-upload) | Compactor | `GET /api/v1/upload/block/{block}/check` |
| [Tenant delete request](#tenant-delete-request) | Compactor | `POST /compactor/delete_tenant` |
| [Tenant delete status](#tenant-delete-status) | Compactor | `GET /compactor/delete_tenant_status` |

### Path prefixes

Expand Down Expand Up @@ -862,30 +862,6 @@ Requires [authentication](#authentication).

> **Note:** To delete a tenant's Alertmanager configuration from Mimir, use [`mimirtool alertmanager delete` command]({{< relref "../tools/mimirtool.md#delete-alertmanager-configuration" >}}).

## Purger

The Purger service provides APIs for requesting tenant deletion.

### Tenant Delete Request

```
POST /purger/delete_tenant
```

Request deletion of ALL tenant data. Experimental.

Requires [authentication](#authentication).

### Tenant Delete Status

```
GET /purger/delete_tenant_status
```

Returns status of tenant deletion. Output format to be defined. Experimental.

Requires [authentication](#authentication).

## Store-gateway

### Store-gateway ring status
Expand Down Expand Up @@ -1014,3 +990,23 @@ Returns state of the block upload. State is returned as JSON object with field `
Requires [authentication](#authentication).

This API endpoint is experimental and subject to change.

### Tenant Delete Request

```
POST /compactor/delete_tenant
```

Request deletion of ALL tenant data. Experimental.

Requires [authentication](#authentication).

### Tenant Delete Status

```
GET /compactor/delete_tenant_status
```

Returns status of tenant deletion. Output format to be defined. Experimental.

Requires [authentication](#authentication).
2 changes: 0 additions & 2 deletions integration/asserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const (
AlertManager
Ruler
StoreGateway
Purger
)

var (
Expand All @@ -42,7 +41,6 @@ var (
AlertManager: {"cortex_alertmanager"},
Ruler: {},
StoreGateway: {"!cortex_storegateway_client", "cortex_storegateway"}, // The metrics prefix cortex_storegateway_client may be used by other components so we ignore it.
Purger: {"cortex_purger"},
}

// Blacklisted metrics prefixes across any Mimir service.
Expand Down
14 changes: 0 additions & 14 deletions integration/e2emimir/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,6 @@ func NewRuler(name string, consulAddress string, flags map[string]string, option
)
}

func NewPurger(name string, flags map[string]string, options ...Option) *MimirService {
return newMimirServiceFromOptions(
name,
map[string]string{
"-target": "purger",
"-log.level": "warn",
"-purger.object-store-type": "filesystem",
"-local.chunk-directory": e2e.ContainerSharedDir,
},
flags,
options...,
)
}

// Options holds a set of options for running services, they can be altered passing Option funcs.
type Options struct {
Image string
Expand Down
8 changes: 2 additions & 6 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
"github.com/grafana/mimir/pkg/frontend/v2/frontendv2pb"
"github.com/grafana/mimir/pkg/ingester/client"
"github.com/grafana/mimir/pkg/mimirpb"
"github.com/grafana/mimir/pkg/purger"
"github.com/grafana/mimir/pkg/querier"
"github.com/grafana/mimir/pkg/ruler"
"github.com/grafana/mimir/pkg/scheduler"
Expand Down Expand Up @@ -280,11 +279,6 @@ func (a *API) RegisterIngester(i Ingester, pushConfig distributor.Config) {
a.RegisterRoute("/ingester/push", push.Handler(pushConfig.MaxRecvMsgSize, a.sourceIPs, a.cfg.SkipLabelNameValidationHeader, i.PushWithCleanup), true, false, "POST") // For testing and debugging.
}

func (a *API) RegisterTenantDeletion(api *purger.TenantDeletionAPI) {
a.RegisterRoute("/purger/delete_tenant", http.HandlerFunc(api.DeleteTenant), true, true, "POST")
a.RegisterRoute("/purger/delete_tenant_status", http.HandlerFunc(api.DeleteTenantStatus), true, true, "GET")
}

// RegisterRuler registers routes associated with the Ruler service.
func (a *API) RegisterRuler(r *ruler.Ruler) {
a.indexPage.AddLinks(defaultWeight, "Ruler", []IndexPageLink{
Expand Down Expand Up @@ -351,6 +345,8 @@ func (a *API) RegisterCompactor(c *compactor.MultitenantCompactor) {
a.RegisterRoute("/api/v1/upload/block/{block}/files", http.HandlerFunc(c.UploadBlockFile), true, false, http.MethodPost)
a.RegisterRoute("/api/v1/upload/block/{block}/finish", http.HandlerFunc(c.FinishBlockUpload), true, false, http.MethodPost)
a.RegisterRoute("/api/v1/upload/block/{block}/check", http.HandlerFunc(c.GetBlockUploadStateHandler), true, false, http.MethodGet)
a.RegisterRoute("/compactor/delete_tenant", http.HandlerFunc(c.DeleteTenant), true, true, "POST")
a.RegisterRoute("/compactor/delete_tenant_status", http.HandlerFunc(c.DeleteTenantStatus), true, true, "GET")
}

type Distributor interface {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Cortex Authors.

package purger
package compactor

import (
"context"
"net/http"
"strings"
"time"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/oklog/ulid"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/thanos-io/thanos/pkg/objstore"

"github.com/grafana/dskit/tenant"

Expand All @@ -25,30 +22,7 @@ import (
"github.com/grafana/mimir/pkg/util"
)

type TenantDeletionAPI struct {
bucketClient objstore.Bucket
logger log.Logger
cfgProvider bucket.TenantConfigProvider
}

func NewTenantDeletionAPI(storageCfg mimir_tsdb.BlocksStorageConfig, cfgProvider bucket.TenantConfigProvider, logger log.Logger, reg prometheus.Registerer) (*TenantDeletionAPI, error) {
bucketClient, err := createBucketClient(storageCfg, logger, reg)
if err != nil {
return nil, err
}

return newTenantDeletionAPI(bucketClient, cfgProvider, logger), nil
}

func newTenantDeletionAPI(bkt objstore.Bucket, cfgProvider bucket.TenantConfigProvider, logger log.Logger) *TenantDeletionAPI {
return &TenantDeletionAPI{
bucketClient: bkt,
cfgProvider: cfgProvider,
logger: logger,
}
}

func (api *TenantDeletionAPI) DeleteTenant(w http.ResponseWriter, r *http.Request) {
func (c *MultitenantCompactor) DeleteTenant(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
userID, err := tenant.TenantID(ctx)
if err != nil {
Expand All @@ -58,15 +32,15 @@ func (api *TenantDeletionAPI) DeleteTenant(w http.ResponseWriter, r *http.Reques
return
}

err = mimir_tsdb.WriteTenantDeletionMark(r.Context(), api.bucketClient, userID, api.cfgProvider, mimir_tsdb.NewTenantDeletionMark(time.Now()))
err = mimir_tsdb.WriteTenantDeletionMark(r.Context(), c.bucketClient, userID, c.cfgProvider, mimir_tsdb.NewTenantDeletionMark(time.Now()))
if err != nil {
level.Error(api.logger).Log("msg", "failed to write tenant deletion mark", "user", userID, "err", err)
level.Error(c.logger).Log("msg", "failed to write tenant deletion mark", "user", userID, "err", err)

http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

level.Info(api.logger).Log("msg", "tenant deletion mark in blocks storage created", "user", userID)
level.Info(c.logger).Log("msg", "tenant deletion mark in blocks storage created", "user", userID)

w.WriteHeader(http.StatusOK)
}
Expand All @@ -76,7 +50,7 @@ type DeleteTenantStatusResponse struct {
BlocksDeleted bool `json:"blocks_deleted"`
}

func (api *TenantDeletionAPI) DeleteTenantStatus(w http.ResponseWriter, r *http.Request) {
func (c *MultitenantCompactor) DeleteTenantStatus(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
userID, err := tenant.TenantID(ctx)
if err != nil {
Expand All @@ -86,7 +60,7 @@ func (api *TenantDeletionAPI) DeleteTenantStatus(w http.ResponseWriter, r *http.

result := DeleteTenantStatusResponse{}
result.TenantID = userID
result.BlocksDeleted, err = api.isBlocksForUserDeleted(ctx, userID)
result.BlocksDeleted, err = c.isBlocksForUserDeleted(ctx, userID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
Expand All @@ -95,10 +69,10 @@ func (api *TenantDeletionAPI) DeleteTenantStatus(w http.ResponseWriter, r *http.
util.WriteJSONResponse(w, result)
}

func (api *TenantDeletionAPI) isBlocksForUserDeleted(ctx context.Context, userID string) (bool, error) {
func (c *MultitenantCompactor) isBlocksForUserDeleted(ctx context.Context, userID string) (bool, error) {
var errBlockFound = errors.New("block found")

userBucket := bucket.NewUserBucketClient(userID, api.bucketClient, api.cfgProvider)
userBucket := bucket.NewUserBucketClient(userID, c.bucketClient, c.cfgProvider)
err := userBucket.Iter(ctx, "", func(s string) error {
s = strings.TrimSuffix(s, "/")

Expand All @@ -123,12 +97,3 @@ func (api *TenantDeletionAPI) isBlocksForUserDeleted(ctx context.Context, userID
// No blocks found, all good.
return true, nil
}

func createBucketClient(cfg mimir_tsdb.BlocksStorageConfig, logger log.Logger, reg prometheus.Registerer) (objstore.Bucket, error) {
bucketClient, err := bucket.NewClient(context.Background(), cfg.Bucket, "purger", logger, reg)
if err != nil {
return nil, errors.Wrap(err, "create bucket client")
}

return bucketClient, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Provenance-includes-license: Apache-2.0
// Provenance-includes-copyright: The Cortex Authors.

package purger
package compactor

import (
"bytes"
Expand All @@ -13,7 +13,7 @@ import (
"path"
"testing"

"github.com/go-kit/log"
"github.com/grafana/dskit/services"
"github.com/stretchr/testify/require"
"github.com/thanos-io/thanos/pkg/objstore"
"github.com/weaveworks/common/user"
Expand All @@ -23,11 +23,14 @@ import (

func TestDeleteTenant(t *testing.T) {
bkt := objstore.NewInMemBucket()
api := newTenantDeletionAPI(bkt, nil, log.NewNopLogger())
cfg := prepareConfig(t)
c, _, _, _, _ := prepare(t, cfg, bkt)
require.NoError(t, services.StartAndAwaitRunning(context.Background(), c))
t.Cleanup(stopServiceFn(t, c))

{
resp := httptest.NewRecorder()
api.DeleteTenant(resp, &http.Request{})
c.DeleteTenant(resp, &http.Request{})
require.Equal(t, http.StatusUnauthorized, resp.Code)
}

Expand All @@ -37,7 +40,7 @@ func TestDeleteTenant(t *testing.T) {

req := &http.Request{}
resp := httptest.NewRecorder()
api.DeleteTenant(resp, req.WithContext(ctx))
c.DeleteTenant(resp, req.WithContext(ctx))

require.Equal(t, http.StatusOK, resp.Code)
objs := bkt.Objects()
Expand Down Expand Up @@ -85,9 +88,12 @@ func TestDeleteTenantStatus(t *testing.T) {
require.NoError(t, bkt.Upload(context.Background(), objName, bytes.NewReader(data)))
}

api := newTenantDeletionAPI(bkt, nil, log.NewNopLogger())
cfg := prepareConfig(t)
c, _, _, _, _ := prepare(t, cfg, bkt)
require.NoError(t, services.StartAndAwaitRunning(context.Background(), c))
t.Cleanup(stopServiceFn(t, c))

res, err := api.isBlocksForUserDeleted(context.Background(), username)
res, err := c.isBlocksForUserDeleted(context.Background(), username)
require.NoError(t, err)
require.Equal(t, tc.expectedBlocksDeleted, res)
})
Expand Down
Loading