-
Notifications
You must be signed in to change notification settings - Fork 70
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
Create a CLI for uploading and downloading blocks #760
Changes from 8 commits
5ec24b8
90f5025
bad1d94
1876028
1e141c2
79a3b3a
d01a5d7
db44635
540fc28
0ef32ea
8232940
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: s3-secret | ||
namespace: prombench-{{ .PR_NUMBER }} # Replace with your actual namespace | ||
type: Opaque | ||
stringData: | ||
object-config.yml: | | ||
type: S3 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is going to be configured differently for each installation - |
||
config: | ||
bucket: {{ .BUCKET_KEY }} | ||
endpoint: minio:9000 | ||
access_key: {{ .ACCESS_KEY }} | ||
secret_key: {{ .SECRET_KEY }} | ||
insecure: true | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,7 @@ spec: | |
runAsUser: 0 | ||
initContainers: | ||
- name: prometheus-builder | ||
image: docker.io/prominfra/prometheus-builder:master | ||
image: kushalshukla/builder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guessing this one is built from the change in this PR. |
||
imagePullPolicy: Always | ||
env: | ||
- name: PR_NUMBER | ||
|
@@ -44,10 +44,35 @@ spec: | |
- name: GITHUB_ORG | ||
value: "{{ .GITHUB_ORG }}" | ||
- name: GITHUB_REPO | ||
value: "{{ .GITHUB_REPO }}" | ||
value: "{{ .GITHUB_REPO }}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. spurious change |
||
volumeMounts: | ||
- name: prometheus-executable | ||
mountPath: /prometheus-builder | ||
- name: key | ||
mountPath: /config | ||
- name: data-downloader | ||
image: kushalshukla/writer | ||
imagePullPolicy: Always | ||
env: | ||
- name: ACCESS_KEY | ||
value: "{{ .ACCESS_KEY }}" | ||
- name: SECRET_KEY | ||
value: "{{ .SECRET_KEY }}" | ||
- name: BUCKET_KEY | ||
value: "{{ .BUCKET_KEY }}" | ||
volumeMounts: | ||
- name: instance-ssd | ||
mountPath: /data | ||
- name: s3-config | ||
mountPath: /config | ||
- name: key | ||
mountPath: /key | ||
args: [ | ||
"download", | ||
"--tsdb-path=/data", | ||
"--objstore.config-file=/config/object-config.yml", | ||
"--key=/key/key.yml" | ||
] | ||
containers: | ||
- name: prometheus | ||
image: quay.io/prometheus/busybox:latest | ||
|
@@ -88,6 +113,11 @@ spec: | |
path: /mnt/disks/ssd0 #gke ssds | ||
- name: prometheus-executable | ||
emptyDir: {} | ||
- name: s3-config # Define the Secret volume | ||
secret: | ||
secretName: s3-secret | ||
- name: key | ||
emptyDir: {} | ||
terminationGracePeriodSeconds: 300 | ||
nodeSelector: | ||
node-name: prometheus-{{ .PR_NUMBER }} | ||
|
@@ -144,6 +174,46 @@ spec: | |
- prometheus | ||
securityContext: | ||
runAsUser: 0 | ||
initContainers: | ||
- name: git-fetcher | ||
image: alpine/git | ||
command: | ||
- /bin/sh | ||
- -c | ||
- | | ||
apk add --no-cache bash && \ | ||
git clone --depth 1 https://github.com/{{ .GITHUB_ORG }}/{{ .GITHUB_REPO }}.git /repo1 && \ | ||
cd /repo1 && \ | ||
git fetch origin pull/{{ .PR_NUMBER }}/head:pr-branch && \ | ||
git checkout pr-branch && \ | ||
cp key.yml /config/key.yml && \ | ||
rm -rf /repo1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This multi-line command is getting unwieldly. Pull it out to a |
||
volumeMounts: | ||
- name: key | ||
mountPath: /config | ||
- name: data-downloader | ||
image: kushalshukla/writer | ||
imagePullPolicy: Always | ||
env: | ||
- name: ACCESS_KEY | ||
value: "{{ .ACCESS_KEY }}" | ||
- name: SECRET_KEY | ||
value: "{{ .SECRET_KEY }}" | ||
- name: BUCKET_KEY | ||
value: "{{ .BUCKET_KEY }}" | ||
volumeMounts: | ||
- name: instance-ssd | ||
mountPath: /data | ||
- name: s3-config | ||
mountPath: /config | ||
- name: key | ||
mountPath: /key | ||
args: [ | ||
"download", | ||
"--tsdb-path=/data", | ||
"--objstore.config-file=/config/object-config.yml", | ||
"--key=/key/key.yml" | ||
] | ||
containers: | ||
- name: prometheus | ||
image: quay.io/prometheus/prometheus:{{ .RELEASE }} | ||
|
@@ -172,6 +242,14 @@ spec: | |
# /mnt is where GKE keeps it's SSD | ||
# don't change this if you want Prometheus to take advantage of these local SSDs | ||
path: /mnt/disks/ssd0 | ||
- name: config | ||
hostPath: | ||
path: /object-config | ||
- name: s3-config # Define the Secret volume | ||
secret: | ||
secretName: s3-secret | ||
- name: key | ||
emptyDir: {} | ||
terminationGracePeriodSeconds: 300 | ||
nodeSelector: | ||
node-name: prometheus-{{ .PR_NUMBER }} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
FROM alpine:latest | ||
LABEL maintainer="The Prometheus Authors <[email protected]>" | ||
|
||
RUN apk --no-cache add libc6-compat | ||
|
||
COPY ./block-sync /bin/block-sync | ||
|
||
RUN chmod +x /bin/block-sync | ||
|
||
ENTRYPOINT ["/bin/block-sync"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
|
||
# block-sync - TSDB Data Synchronization Tool | ||
|
||
|
||
The `block-sync` command is a CLI tool designed to synchronize TSDB data with an object storage system. | ||
|
||
## Table of Contents | ||
|
||
1. [Upload](#upload) | ||
2. [Download](#download) | ||
|
||
## Command Flags | ||
|
||
- ``` -h , --help```:Displays context-sensitive help | ||
- ``` - tsdb-path```: Path for The TSDB data in prometheus | ||
- ```- objstore.config-file```: Path for The Config file | ||
- ```- Key```: Path for the Key where to store block data , i.e a Directory. | ||
|
||
## Upload | ||
|
||
The `upload` command allows you to upload TSDB data from a specified path to an object storage bucket. This command is essential for backing up your TSDB data or migrating it to an object storage solution for future use. | ||
|
||
### Usage | ||
|
||
```bash | ||
./block-sync upload --tsdb-path=<path-to-tsdb> --objstore.config-file=<path-to-config> --key=<object-key> | ||
|
||
|
||
``` | ||
## Download | ||
|
||
The `download` command allows you to retrieve TSDB data from an object storage bucket to a specified local path. This command is essential for restoring your TSDB data or retrieving it for local analysis and processing. | ||
|
||
### Usage | ||
|
||
```bash | ||
./block-sync download --tsdb-path=<path-to-tsdb> --objstore.config-file=<path-to-config> --key=<object-key> | ||
``` | ||
## Config File | ||
|
||
The configuration file is essential for connecting to your object storage solution. Below are basic templates for different object storage systems. | ||
|
||
```yaml | ||
type: s3, GCS , AZURE , etc. | ||
config: | ||
bucket: your-bucket-name | ||
endpoint: https://your-endpoint | ||
access_key: your-access-key | ||
secret_key: your-secret-key | ||
insecure: false # Set to true if using HTTP instead of HTTPS | ||
``` | ||
You can customize the config file , follow this link [Storage.md](https://thanos.io/tip/thanos/storage.md/) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright 2024 The Prometheus Authors | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"fmt" | ||
"log/slog" | ||
"os" | ||
) | ||
|
||
func main() { | ||
var ( | ||
tsdbPath string | ||
objectConfig string | ||
objectKey string | ||
) | ||
uploadCmd := flag.NewFlagSet("upload", flag.ExitOnError) | ||
downloadCmd := flag.NewFlagSet("download", flag.ExitOnError) | ||
|
||
uploadCmd.StringVar(&tsdbPath, "tsdb-path", "", "Uploading data to objstore") | ||
uploadCmd.StringVar(&objectConfig, "objstore.config-file", "", "Path for The Config file") | ||
uploadCmd.StringVar(&objectKey, "key", "", "Path for the Key where to store block data") | ||
|
||
downloadCmd.StringVar(&tsdbPath, "tsdb-path", "", "Downloading data to objstore") | ||
downloadCmd.StringVar(&objectConfig, "objstore.config-file", "", "Path for The Config file") | ||
downloadCmd.StringVar(&objectKey, "key", "", "Path from the Key where to download the block data") | ||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) | ||
|
||
flag.Usage = func() { | ||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | ||
fmt.Println(" upload Uploads data to the object store") | ||
fmt.Println(" download Downloads data from the object store") | ||
fmt.Println("Flags:") | ||
fmt.Println(" --tsdb-path Path to TSDB data") | ||
fmt.Println(" --objstore.config-file Path to the object store config file") | ||
fmt.Println(" --key Key path for storing or downloading data") | ||
fmt.Println() | ||
fmt.Println("Use 'block-sync [command] --help' for more information about a command.") | ||
} | ||
|
||
if len(os.Args) < 2 { | ||
logger.Error("Expected 'upload' or 'download' subcommands") | ||
flag.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
switch os.Args[1] { | ||
case "upload": | ||
if err := uploadCmd.Parse(os.Args[2:]); err != nil { | ||
fmt.Println("Error parsing upload command:", err) | ||
os.Exit(1) | ||
} | ||
case "download": | ||
if err := downloadCmd.Parse(os.Args[2:]); err != nil { | ||
fmt.Println("Error parsing download command:", err) | ||
os.Exit(1) | ||
} | ||
default: | ||
logger.Error("Expected 'upload' or 'download' subcommands") | ||
flag.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
if tsdbPath == "" || objectConfig == "" || objectKey == "" { | ||
fmt.Println("error: all flags --tsdb-path, --objstore.config-file, and --key are required.") | ||
os.Exit(1) | ||
} | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
store, err := newStore(tsdbPath, objectConfig, objectKey, logger) | ||
if err != nil { | ||
logger.Error("Failed to create store", "error", err) | ||
os.Exit(1) | ||
} | ||
|
||
switch os.Args[1] { | ||
case "upload": | ||
err = store.upload(ctx) | ||
if err != nil { | ||
logger.Error("Failed to upload data", "Error", err) | ||
os.Exit(1) | ||
} | ||
case "download": | ||
err = store.download(ctx) | ||
if err != nil { | ||
logger.Error("Failed to download data", "error", err) | ||
os.Exit(1) | ||
} | ||
} | ||
} |
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 see you put the Secret in the namespace for the PR, but I see the same bucket being used across many runs.