Skip to content
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 @@ -16,6 +16,7 @@
* [ENHANCEMENT] Update mixin to use new backend metric [#1151](https://github.com/grafana/tempo/pull/1151) (@zalegrala)
* [ENHANCEMENT] Make `TempoIngesterFlushesFailing` alert more actionable [#1157](https://github.com/grafana/tempo/pull/1157) (@dannykopping)
* [ENHANCEMENT] Switch open-telemetry/opentelemetry-collector to grafana/opentelemetry-collectorl fork, update it to 0.40.0 and add missing dependencies due to the change (@tete17)
* [ENHANCEMENT] Allow environment variables for Azure storage credentials [#1147](https://github.com/grafana/tempo/pull/1147) (@zalegrala)
* [BUGFIX] Fix defaults for MaxBytesPerTrace (ingester.max-bytes-per-trace) and MaxSearchBytesPerTrace (ingester.max-search-bytes-per-trace) (@bitprocessor)
* [BUGFIX] Ignore empty objects during compaction [#1113](https://github.com/grafana/tempo/pull/1113) (@mdisibio)
* [BUGFIX] Add process name to vulture traces to work around display issues [#1127](https://github.com/grafana/tempo/pull/1127) (@mdisibio)
Expand Down
1 change: 1 addition & 0 deletions docs/tempo/website/configuration/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ The storage block is used to configure TempoDB. It supports S3, GCS, Azure, loca
The following example shows common options. For further platform-specific information refer to the following:
* [GCS](gcs/)
* [S3](s3/)
* [Azure](azure/)

```yaml
# Storage configuration for traces
Expand Down
87 changes: 87 additions & 0 deletions docs/tempo/website/configuration/azure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Azure Permissions and Management
weight: 3
---

# Azure Blob Storage Permissions and Management

In order for Tempo to authenticate to Azure blob storage, the following is
required to access the container.

* Storage account
* Storage account access key
* Storage account management policy

The `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_KEY` environment variables can
be used instead of setting the credentials in the Tempo configuration file.

The following storage account management policy shows an example of cleaning up
files from the container after they have been deleted for a period of time.

```json
{
"id": "/subscriptions/00000000-0000-0000000000000000000000/resourceGroups/resourceGroupName/providers/Microsoft.Storage/storageAccounts/accountName/managementPolicies/default",
"lastModifiedTime": "2021-11-30T19:19:54.855455+00:00",
"name": "DefaultManagementPolicy",
"policy": {
"rules": [
{
"definition": {
"actions": {
"baseBlob": {
"delete": {
"daysAfterLastAccessTimeGreaterThan": null,
"daysAfterModificationGreaterThan": 60.0
},
"enableAutoTierToHotFromCool": null,
"tierToArchive": null,
"tierToCool": null
},
"snapshot": null,
"version": null
},
"filters": {
"blobIndexMatch": null,
"blobTypes": [
"blockBlob"
],
"prefixMatch": [
"tempo-data"
]
}
},
"enabled": true,
"name": "TempoBlobRetention",
"type": "Lifecycle"
},
{
"definition": {
"actions": {
"baseBlob": null,
"snapshot": null,
"version": {
"delete": {
"daysAfterCreationGreaterThan": 7.0
},
"tierToArchive": null,
"tierToCool": null
}
},
"filters": {
"blobIndexMatch": null,
"blobTypes": [
"blockBlob"
],
"prefixMatch": []
}
},
"enabled": true,
"name": "VersionRetention",
"type": "Lifecycle"
}
]
},
"resourceGroup": "resource-group-name",
"type": "Microsoft.Storage/storageAccounts/managementPolicies"
}
```
18 changes: 15 additions & 3 deletions tempodb/backend/azure/azure_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
"time"

Expand All @@ -20,7 +21,18 @@ const (
)

func GetContainerURL(ctx context.Context, cfg *Config, hedge bool) (blob.ContainerURL, error) {
c, err := blob.NewSharedKeyCredential(cfg.StorageAccountName.String(), cfg.StorageAccountKey.String())
accountName := cfg.StorageAccountName.String()
accountKey := cfg.StorageAccountKey.String()

if accountName == "" {
accountName = os.Getenv("AZURE_STORAGE_ACCOUNT")
}

if accountKey == "" {
accountKey = os.Getenv("AZURE_STORAGE_KEY")
}

c, err := blob.NewSharedKeyCredential(accountName, accountKey)
if err != nil {
return blob.ContainerURL{}, err
}
Expand Down Expand Up @@ -63,12 +75,12 @@ func GetContainerURL(ctx context.Context, cfg *Config, hedge bool) (blob.Contain
HTTPSender: httpSender,
})

u, err := url.Parse(fmt.Sprintf("https://%s.%s", cfg.StorageAccountName, cfg.Endpoint))
u, err := url.Parse(fmt.Sprintf("https://%s.%s", accountName, cfg.Endpoint))

// If the endpoint doesn't start with blob.core we can assume Azurite is being used
// So the endpoint should follow Azurite URL style
if !strings.HasPrefix(cfg.Endpoint, "blob.core") {
u, err = url.Parse(fmt.Sprintf("http://%s/%s", cfg.Endpoint, cfg.StorageAccountName))
u, err = url.Parse(fmt.Sprintf("http://%s/%s", cfg.Endpoint, accountName))
}

if err != nil {
Expand Down
35 changes: 29 additions & 6 deletions tempodb/backend/azure/azure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,37 @@ import (
"context"
"net/http"
"net/http/httptest"
"os"
"sync/atomic"
"testing"
"time"

"github.com/google/uuid"
"github.com/grafana/dskit/flagext"
"github.com/grafana/tempo/tempodb/backend"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCredentials(t *testing.T) {
_, _, _, err := New(&Config{})
require.Error(t, err)

os.Setenv("AZURE_STORAGE_ACCOUNT", "testing")
os.Setenv("AZURE_STORAGE_KEY", "dGVzdGluZwo=")
Comment thread
joe-elliott marked this conversation as resolved.

defer os.Unsetenv("AZURE_STORAGE_ACCOUNT")
defer os.Unsetenv("AZURE_STORAGE_KEY")

count := int32(0)
server := fakeServer(t, 1*time.Second, &count)

_, _, _, err = New(&Config{
Endpoint: server.URL[7:], // [7:] -> strip http://,
})
require.NoError(t, err)
}

func TestHedge(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -45,12 +66,14 @@ func TestHedge(t *testing.T) {
server := fakeServer(t, tc.returnIn, &count)

r, w, _, err := New(&Config{
MaxBuffers: 3,
BufferSize: 1000,
ContainerName: "blerg",
Endpoint: server.URL[7:], // [7:] -> strip http://,
HedgeRequestsAt: tc.hedgeAt,
HedgeRequestsUpTo: 2,
StorageAccountName: flagext.Secret{Value: "testing"},
StorageAccountKey: flagext.Secret{Value: "YQo="},
MaxBuffers: 3,
BufferSize: 1000,
ContainerName: "blerg",
Endpoint: server.URL[7:], // [7:] -> strip http://,
HedgeRequestsAt: tc.hedgeAt,
HedgeRequestsUpTo: 2,
})
require.NoError(t, err)

Expand Down