diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 1c7f27c..148852a 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -47,6 +47,10 @@ jobs: [ "${GITHUB_EVENT_NAME}" == 'release' ] && echo "tag=${GITHUB_REF##*/}" >> $GITHUB_ENV || true [ "${GITHUB_EVENT_NAME}" == 'push' ] && echo "tag=latest" >> $GITHUB_ENV || true + - name: Build + run: + make all + - name: Build and push image uses: docker/build-push-action@v4 with: diff --git a/Dockerfile b/Dockerfile index 2b78269..79d5e6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,12 @@ -FROM golang:1.21 as builder -WORKDIR /work -COPY .git .git -COPY api api -COPY cmd cmd -COPY go.mod . -COPY go.sum . -COPY Makefile . -RUN make - +# TODO: remove tini in a future release, not required anymore since pre- and post-exec-cmd flags FROM krallin/ubuntu-tini as ubuntu-tini -# rethinkdb backup/restore requires the python client library -# let's make small binaries of these commands in order not to blow up the image size -FROM rethinkdb:2.4.1 as rethinkdb-python-client-builder -WORKDIR /work -RUN apt update && apt install -y python3-pip -RUN pip3 install pyinstaller==4.3.0 rethinkdb -COPY build/rethinkdb-dump.spec rethinkdb-dump.spec -COPY build/rethinkdb-restore.spec rethinkdb-restore.spec -RUN pyinstaller rethinkdb-dump.spec \ - && pyinstaller rethinkdb-restore.spec +FROM ghcr.io/metal-stack/rethinkdb-backup-tools-build:v2.4.1 as rethinkdb-backup-tools FROM alpine:3.18 +# TODO: remove tini in a future release, not required anymore since pre- and post-exec-cmd flags RUN apk add --no-cache tini ca-certificates -COPY --from=builder /work/bin/backup-restore-sidecar /backup-restore-sidecar +COPY bin/backup-restore-sidecar /backup-restore-sidecar COPY --from=ubuntu-tini /usr/local/bin/tini-static /ubuntu/tini -COPY --from=rethinkdb-python-client-builder /work/dist/rethinkdb-dump /work/dist/rethinkdb-restore /rethinkdb/ +COPY --from=rethinkdb-backup-tools /rethinkdb-dump /rethinkdb-restore /rethinkdb/ CMD ["/backup-restore-sidecar"] diff --git a/Makefile b/Makefile index 5ffe8c9..4916174 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ BACKUP_PROVIDER := $(or ${BACKUP_PROVIDER},local) SHA := $(shell git rev-parse --short=8 HEAD) GITVERSION := $(shell git describe --long --all) -BUILDDATE := $(shell GO111MODULE=off go run ${COMMONDIR}/time.go) +BUILDDATE := $(shell date --rfc-3339=seconds) VERSION := $(or ${VERSION},$(shell git describe --tags --exact-match 2> /dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD)) GO111MODULE := on @@ -25,7 +25,7 @@ proto: make -C proto protoc .PHONY: dockerimage -dockerimage: +dockerimage: all docker build -t ghcr.io/metal-stack/backup-restore-sidecar:${DOCKER_TAG} . .PHONY: dockerpush diff --git a/build/rethinkdb-dump.spec b/build/rethinkdb-dump.spec deleted file mode 100644 index 622c260..0000000 --- a/build/rethinkdb-dump.spec +++ /dev/null @@ -1,28 +0,0 @@ -# -*- mode: python -*- - -block_cipher = None - - -a = Analysis(['/usr/local/bin/rethinkdb-dump'], - pathex=['/work'], - binaries=[], - datas=[], - hiddenimports=[], - hookspath=[], - runtime_hooks=[], - excludes=[], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher) -pyz = PYZ(a.pure, a.zipped_data, - cipher=block_cipher) -exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - name='rethinkdb-dump', - debug=False, - strip=False, - upx=True, - console=True ) \ No newline at end of file diff --git a/build/rethinkdb-restore.spec b/build/rethinkdb-restore.spec deleted file mode 100644 index 4c5f677..0000000 --- a/build/rethinkdb-restore.spec +++ /dev/null @@ -1,28 +0,0 @@ -# -*- mode: python -*- - -block_cipher = None - - -a = Analysis(['/usr/local/bin/rethinkdb-restore'], - pathex=['/work'], - binaries=[], - datas=[], - hiddenimports=[], - hookspath=[], - runtime_hooks=[], - excludes=[], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher) -pyz = PYZ(a.pure, a.zipped_data, - cipher=block_cipher) -exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - name='rethinkdb-restore', - debug=False, - strip=False, - upx=True, - console=True ) \ No newline at end of file diff --git a/cmd/internal/backup/backup.go b/cmd/internal/backup/backup.go index 94bbc9f..a5ff627 100644 --- a/cmd/internal/backup/backup.go +++ b/cmd/internal/backup/backup.go @@ -1,6 +1,7 @@ package backup import ( + "context" "os" "path" @@ -14,7 +15,7 @@ import ( ) // Start starts the backup component, which is periodically taking backups of the database -func Start(log *zap.SugaredLogger, backupSchedule string, db database.DatabaseProber, bp backuproviders.BackupProvider, metrics *metrics.Metrics, comp *compress.Compressor, stop <-chan struct{}) error { +func Start(ctx context.Context, log *zap.SugaredLogger, backupSchedule string, db database.DatabaseProber, bp backuproviders.BackupProvider, metrics *metrics.Metrics, comp *compress.Compressor) error { log.Info("database is now available, starting periodic backups") c := cron.New() @@ -70,7 +71,7 @@ func Start(log *zap.SugaredLogger, backupSchedule string, db database.DatabasePr c.Start() log.Infow("scheduling next backup", "at", c.Entry(id).Next.String()) - <-stop + <-ctx.Done() c.Stop() return nil } diff --git a/cmd/internal/database/rethinkdb/rethinkdb.go b/cmd/internal/database/rethinkdb/rethinkdb.go index d3348ae..ea3c56f 100644 --- a/cmd/internal/database/rethinkdb/rethinkdb.go +++ b/cmd/internal/database/rethinkdb/rethinkdb.go @@ -1,6 +1,7 @@ package rethinkdb import ( + "context" "fmt" "net" "os" @@ -40,11 +41,13 @@ type RethinkDB struct { passwordFile string log *zap.SugaredLogger executor *utils.CmdExecutor + ctx context.Context } // New instantiates a new rethinkdb database -func New(log *zap.SugaredLogger, datadir string, url string, passwordFile string) *RethinkDB { +func New(ctx context.Context, log *zap.SugaredLogger, datadir string, url string, passwordFile string) *RethinkDB { return &RethinkDB{ + ctx: ctx, log: log, datadir: datadir, url: url, @@ -125,13 +128,18 @@ func (db *RethinkDB) Recover() error { }() db.log.Infow("waiting for rethinkdb database to come up") - restoreDB := New(db.log, db.datadir, "localhost:1", "") - stop := make(chan struct{}) + + restoreDB := New(db.ctx, db.log, db.datadir, "localhost:1", "") + done := make(chan bool) defer close(done) + + probeCtx, probeCancel := context.WithTimeout(context.Background(), restoreDatabaseStartupTimeout) + defer probeCancel() + var err error go func() { - err = probe.Start(restoreDB.log, restoreDB, stop) + err = probe.Start(probeCtx, restoreDB.log, restoreDB) done <- true }() select { @@ -140,8 +148,7 @@ func (db *RethinkDB) Recover() error { return fmt.Errorf("error while probing: %w", err) } db.log.Infow("rethinkdb in sidecar is now available, now triggering restore commands...") - case <-time.After(restoreDatabaseStartupTimeout): - close(stop) + case <-probeCtx.Done(): return errors.New("rethinkdb database did not come up in time") } @@ -149,6 +156,9 @@ func (db *RethinkDB) Recover() error { if db.url != "" { args = append(args, "--connect="+restoreDB.url) } + if db.passwordFile != "" { + args = append(args, "--password-file="+db.passwordFile) + } args = append(args, rethinkDBRestoreFilePath) out, err := db.executor.ExecuteCommandWithOutput(rethinkDBRestoreCmd, nil, args...) diff --git a/cmd/internal/initializer/initializer.go b/cmd/internal/initializer/initializer.go index 5037b53..ec214fc 100644 --- a/cmd/internal/initializer/initializer.go +++ b/cmd/internal/initializer/initializer.go @@ -1,6 +1,7 @@ package initializer import ( + "context" "fmt" "net" "os" @@ -30,24 +31,26 @@ type Initializer struct { db database.Database bp providers.BackupProvider comp *compress.Compressor + dbDataDir string } -func New(log *zap.SugaredLogger, addr string, db database.Database, bp providers.BackupProvider, comp *compress.Compressor) *Initializer { +func New(log *zap.SugaredLogger, addr string, db database.Database, bp providers.BackupProvider, comp *compress.Compressor, dbDataDir string) *Initializer { return &Initializer{ currentStatus: &v1.StatusResponse{ Status: v1.StatusResponse_CHECKING, Message: "starting initializer server", }, - log: log, - addr: addr, - db: db, - bp: bp, - comp: comp, + log: log, + addr: addr, + db: db, + bp: bp, + comp: comp, + dbDataDir: dbDataDir, } } // Start starts the initializer, which includes a server component and the initializer itself, which is potentially restoring a backup -func (i *Initializer) Start(stop <-chan struct{}) { +func (i *Initializer) Start(ctx context.Context) { opts := []grpc.ServerOption{ grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( grpc_ctxtags.StreamServerInterceptor(), @@ -75,7 +78,7 @@ func (i *Initializer) Start(stop <-chan struct{}) { } go func() { - <-stop + <-ctx.Done() i.log.Info("received stop signal, shutting down") grpcServer.Stop() }() @@ -106,9 +109,15 @@ func (i *Initializer) Start(stop <-chan struct{}) { func (i *Initializer) initialize() error { i.log.Info("start running initializer") + i.log.Info("ensuring database data directory") + err := os.MkdirAll(i.dbDataDir, 0755) + if err != nil { + return fmt.Errorf("unable to ensure database data directory: %w", err) + } + i.log.Info("ensuring backup bucket") i.currentStatus.Message = "ensuring backup bucket" - err := i.bp.EnsureBackupBucket() + err = i.bp.EnsureBackupBucket() if err != nil { return fmt.Errorf("unable to ensure backup bucket: %w", err) } diff --git a/cmd/internal/probe/probe.go b/cmd/internal/probe/probe.go index 9ff233f..543ecad 100644 --- a/cmd/internal/probe/probe.go +++ b/cmd/internal/probe/probe.go @@ -1,6 +1,7 @@ package probe import ( + "context" "errors" "time" @@ -13,12 +14,12 @@ var ( ) // Start starts the database prober -func Start(log *zap.SugaredLogger, db database.DatabaseProber, stop <-chan struct{}) error { +func Start(ctx context.Context, log *zap.SugaredLogger, db database.DatabaseProber) error { log.Info("start probing database") for { select { - case <-stop: + case <-ctx.Done(): return errors.New("received stop signal, stop probing") case <-time.After(probeInterval): err := db.Probe() diff --git a/cmd/internal/signals/signal.go b/cmd/internal/signals/signal.go deleted file mode 100644 index 6bddfdd..0000000 --- a/cmd/internal/signals/signal.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 signals - -import ( - "os" - "os/signal" -) - -var onlyOneSignalHandler = make(chan struct{}) - -// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned -// which is closed on one of these signals. If a second signal is caught, the program -// is terminated with exit code 1. -func SetupSignalHandler() (stopCh <-chan struct{}) { - close(onlyOneSignalHandler) // panics when called twice - - stop := make(chan struct{}) - c := make(chan os.Signal, 2) - signal.Notify(c, shutdownSignals...) - go func() { - <-c - close(stop) - <-c - os.Exit(1) // second signal. Exit directly. - }() - - return stop -} diff --git a/cmd/internal/signals/signal_posix.go b/cmd/internal/signals/signal_posix.go deleted file mode 100644 index 9bdb4e7..0000000 --- a/cmd/internal/signals/signal_posix.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !windows - -/* -Copyright 2017 The Kubernetes 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 signals - -import ( - "os" - "syscall" -) - -var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} diff --git a/cmd/internal/signals/signal_windows.go b/cmd/internal/signals/signal_windows.go deleted file mode 100644 index 4907d57..0000000 --- a/cmd/internal/signals/signal_windows.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2017 The Kubernetes 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 signals - -import ( - "os" -) - -var shutdownSignals = []os.Signal{os.Interrupt} diff --git a/cmd/internal/utils/cmd.go b/cmd/internal/utils/cmd.go index f700f88..d8e2fdc 100644 --- a/cmd/internal/utils/cmd.go +++ b/cmd/internal/utils/cmd.go @@ -1,6 +1,7 @@ package utils import ( + "context" "fmt" "os" "os/exec" @@ -45,3 +46,20 @@ func runCommandWithOutput(cmd *exec.Cmd, combinedOutput bool) (string, error) { return out, err } + +func (c *CmdExecutor) ExecWithStreamingOutput(ctx context.Context, command string) error { + command = os.ExpandEnv(command) + + parts := strings.Fields(command) + + cmd := exec.CommandContext(ctx, parts[0], parts[1:]...) // nolint:gosec + + c.log.Debugw("running command", "command", cmd.Path, "args", cmd.Args) + + cmd.Env = os.Environ() + + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + + return cmd.Run() +} diff --git a/cmd/internal/wait/wait.go b/cmd/internal/wait/wait.go index 4e8b9c8..480ad03 100644 --- a/cmd/internal/wait/wait.go +++ b/cmd/internal/wait/wait.go @@ -14,9 +14,7 @@ const ( ) // Start starts a wait component that will return when the initializer server has done its job -func Start(log *zap.SugaredLogger, addr string, stop <-chan struct{}) error { - ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second) - defer cancel() +func Start(ctx context.Context, log *zap.SugaredLogger, addr string) error { client, err := initializer.NewInitializerClient(ctx, addr, log) if err != nil { return err @@ -26,11 +24,11 @@ func Start(log *zap.SugaredLogger, addr string, stop <-chan struct{}) error { for { select { - case <-stop: + case <-ctx.Done(): log.Info("received stop signal, shutting down") return nil case <-time.After(waitInterval): - resp, err := client.Status(context.Background(), &v1.Empty{}) + resp, err := client.Status(ctx, &v1.Empty{}) if err != nil { log.Errorw("error retrieving initializer server response", "error", err) continue diff --git a/cmd/main.go b/cmd/main.go index c8bd384..7f856fa 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,10 +1,12 @@ package main import ( + "context" "errors" "fmt" "log" "os" + "os/signal" "strings" "github.com/metal-stack/backup-restore-sidecar/cmd/internal/backup" @@ -21,7 +23,6 @@ import ( "github.com/metal-stack/backup-restore-sidecar/cmd/internal/initializer" "github.com/metal-stack/backup-restore-sidecar/cmd/internal/metrics" "github.com/metal-stack/backup-restore-sidecar/cmd/internal/probe" - "github.com/metal-stack/backup-restore-sidecar/cmd/internal/signals" "github.com/metal-stack/backup-restore-sidecar/cmd/internal/utils" "github.com/metal-stack/backup-restore-sidecar/cmd/internal/wait" "github.com/metal-stack/v" @@ -46,6 +47,9 @@ const ( databaseFlg = "db" databaseDatadirFlg = "db-data-directory" + preExecCommandsFlg = "pre-exec-cmds" + postExecCommandsFlg = "post-exec-cmds" + postgresUserFlg = "postgres-user" postgresHostFlg = "postgres-host" postgresPasswordFlg = "postgres-password" @@ -87,13 +91,14 @@ var ( logger *zap.SugaredLogger db database.Database bp providers.BackupProvider - stop <-chan struct{} + stop context.Context ) var rootCmd = &cobra.Command{ - Use: moduleName, - Short: "a backup restore sidecar for databases managed in K8s", - Version: v.V.String(), + Use: moduleName, + Short: "a backup restore sidecar for databases managed in K8s", + Version: v.V.String(), + SilenceUsage: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { initLogging() initConfig() @@ -113,6 +118,17 @@ var startCmd = &cobra.Command{ return initBackupProvider() }, RunE: func(cmd *cobra.Command, args []string) error { + for _, cmd := range viper.GetStringSlice(preExecCommandsFlg) { + logger.Infow("running pre-exec command", "cmd", cmd) + + executor := utils.NewExecutor(logger.Named("pre-executor")) + + err := executor.ExecWithStreamingOutput(stop, cmd) + if err != nil { + return err + } + } + addr := fmt.Sprintf("%s:%d", viper.GetString(bindAddrFlg), viper.GetInt(portFlg)) logger.Infow("starting backup-restore-sidecar", "version", v.V, "bind-addr", addr) @@ -121,13 +137,13 @@ var startCmd = &cobra.Command{ if err != nil { return err } - initializer.New(logger.Named("initializer"), addr, db, bp, comp).Start(stop) - if err := probe.Start(logger.Named("probe"), db, stop); err != nil { + initializer.New(logger.Named("initializer"), addr, db, bp, comp, viper.GetString(databaseDatadirFlg)).Start(stop) + if err := probe.Start(stop, logger.Named("probe"), db); err != nil { return err } metrics := metrics.New() metrics.Start(logger.Named("metrics")) - return backup.Start(logger.Named("backup"), viper.GetString(backupCronScheduleFlg), db, bp, metrics, comp, stop) + return backup.Start(stop, logger.Named("backup"), viper.GetString(backupCronScheduleFlg), db, bp, metrics, comp) }, } @@ -153,7 +169,7 @@ var restoreCmd = &cobra.Command{ if err != nil { return err } - return initializer.New(logger.Named("initializer"), "", db, bp, comp).Restore(version) + return initializer.New(logger.Named("initializer"), "", db, bp, comp, viper.GetString(databaseDatadirFlg)).Restore(version) }, } @@ -185,12 +201,29 @@ var waitCmd = &cobra.Command{ Use: "wait", Short: "waits for the initializer to be done", RunE: func(cmd *cobra.Command, args []string) error { - return wait.Start(logger.Named("wait"), viper.GetString(serverAddrFlg), stop) + if err := wait.Start(stop, logger.Named("wait"), viper.GetString(serverAddrFlg)); err != nil { + return err + } + + for _, cmd := range viper.GetStringSlice(postExecCommandsFlg) { + logger.Infow("running post-exec command", "cmd", cmd) + executor := utils.NewExecutor(logger.Named("post-executor")) + + err := executor.ExecWithStreamingOutput(stop, cmd) + if err != nil { + return err + } + } + + return nil }, } func main() { if err := rootCmd.Execute(); err != nil { + if logger == nil { + panic(err) + } logger.Fatalw("failed executing root command", "error", err) } } @@ -211,6 +244,8 @@ func init() { startCmd.Flags().StringP(bindAddrFlg, "", "127.0.0.1", "the bind addr of the api server") startCmd.Flags().IntP(portFlg, "", 8000, "the port to serve on") + startCmd.Flags().StringSlice(preExecCommandsFlg, nil, "runs given commands prior to executing the backup-restore-sidecar functionality") + startCmd.Flags().StringP(postgresUserFlg, "", "postgres", "the postgres database user (will be used when db is postgres)") startCmd.Flags().StringP(postgresHostFlg, "", "127.0.0.1", "the postgres database address (will be used when db is postgres)") startCmd.Flags().IntP(postgresPortFlg, "", 5432, "the postgres database port (will be used when db is postgres)") @@ -251,6 +286,8 @@ func init() { waitCmd.Flags().StringP(serverAddrFlg, "", "http://127.0.0.1:8000/", "the url of the initializer server") + waitCmd.Flags().StringSlice(postExecCommandsFlg, nil, "runs given commands after finished waiting for the backup-restore-sidecar's initializer (typically used for starting the database)") + err = viper.BindPFlags(waitCmd.Flags()) if err != nil { fmt.Printf("unable to construct wait command: %v", err) @@ -316,7 +353,8 @@ func initLogging() { } func initSignalHandlers() { - stop = signals.SetupSignalHandler() + // don't need to store + stop, _ = signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) } func initDatabase() error { @@ -326,6 +364,7 @@ func initDatabase() error { } dbString := viper.GetString(databaseFlg) + switch dbString { case "postgres": db = postgres.New( @@ -338,6 +377,7 @@ func initDatabase() error { ) case "rethinkdb": db = rethinkdb.New( + stop, logger.Named("rethinkdb"), datadir, viper.GetString(rethinkDBURLFlg), @@ -356,7 +396,9 @@ func initDatabase() error { default: return fmt.Errorf("unsupported database type: %s", dbString) } + logger.Infow("initialized database adapter", "type", dbString) + return nil } diff --git a/deploy/etcd-local.yaml b/deploy/etcd-local.yaml index 7596406..0def8a0 100644 --- a/deploy/etcd-local.yaml +++ b/deploy/etcd-local.yaml @@ -25,16 +25,12 @@ spec: role: main spec: containers: - - image: quay.io/coreos/etcd:v3.5.4 + - image: quay.io/coreos/etcd:v3.5.7 # can also be gcr.io/etcd-development/etcd name: etcd command: - - tini - - -- - args: - - sh - - -c - - backup-restore-sidecar wait && etcd --data-dir=/data/etcd --listen-metrics-urls http://0.0.0.0:2381 + - backup-restore-sidecar + - wait imagePullPolicy: IfNotPresent livenessProbe: exec: @@ -81,18 +77,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - - image: quay.io/coreos/etcd:v3.5.4 + - image: quay.io/coreos/etcd:v3.5.7 name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/etcd/ && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug env: [] volumeMounts: - name: etcd @@ -102,9 +92,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini initContainers: - name: backup-restore-sidecar-provider image: ghcr.io/metal-stack/backup-restore-sidecar:latest @@ -112,7 +99,6 @@ spec: command: - cp - /backup-restore-sidecar - - /ubuntu/tini - /bin-provision ports: - containerPort: 2112 @@ -149,3 +135,5 @@ data: backup-provider: local backup-cron-schedule: "*/1 * * * *" object-prefix: etcd-test + post-exec-cmds: + - etcd --data-dir=/data/etcd --listen-metrics-urls http://0.0.0.0:2381 diff --git a/deploy/etcd-s3.yaml b/deploy/etcd-s3.yaml index 7a65a59..f3733e3 100644 --- a/deploy/etcd-s3.yaml +++ b/deploy/etcd-s3.yaml @@ -29,12 +29,8 @@ spec: # can also be gcr.io/etcd-development/etcd name: etcd command: - - tini - - -- - args: - - sh - - -c - - backup-restore-sidecar wait && etcd --data-dir=/data/etcd --listen-metrics-urls http://0.0.0.0:2381 + - backup-restore-sidecar + - wait imagePullPolicy: IfNotPresent livenessProbe: exec: @@ -81,9 +77,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: quay.io/coreos/etcd:v3.5.4 name: backup-restore-sidecar env: @@ -113,12 +106,9 @@ spec: key: secret-key name: backup-restore-sidecar-backup-provider-config command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/etcd && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug volumeMounts: - name: etcd mountPath: /data @@ -127,9 +117,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: bin-provision subPath: certs mountPath: /etc/ssl/certs @@ -142,7 +129,6 @@ spec: - -r - /etc/ssl/certs - /backup-restore-sidecar - - /ubuntu/tini - /bin-provision ports: - containerPort: 2112 @@ -177,3 +163,5 @@ data: backup-cron-schedule: "*/1 * * * *" object-prefix: etcd-test compression-method: tarlz4 + post-exec-cmds: + - etcd --data-dir=/data/etcd --listen-metrics-urls http://0.0.0.0:2381 diff --git a/deploy/postgres-gcp.yaml b/deploy/postgres-gcp.yaml index 5d747f0..60cc7c3 100644 --- a/deploy/postgres-gcp.yaml +++ b/deploy/postgres-gcp.yaml @@ -20,12 +20,8 @@ spec: - image: postgres:12-alpine name: postgres command: - - tini - - -- - args: - - sh - - -c - - backup-restore-sidecar wait && docker-entrypoint.sh postgres + - backup-restore-sidecar + - wait ports: - containerPort: 5432 env: @@ -57,18 +53,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: postgres:12-alpine name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/postgres && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug env: - name: BACKUP_RESTORE_SIDECAR_GCP_PROJECT valueFrom: @@ -105,9 +95,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: gcp-credentials mountPath: /gcp/credentials readOnly: true @@ -118,7 +105,6 @@ spec: command: - cp - /backup-restore-sidecar - - /sbin/tini - /bin-provision ports: - containerPort: 2112 @@ -161,6 +147,8 @@ data: backup-provider: gcp backup-cron-schedule: "*/1 * * * *" object-prefix: postgres-test + post-exec-cmds: + - docker-entrypoint.sh postgres --- apiVersion: v1 kind: Secret diff --git a/deploy/postgres-local.yaml b/deploy/postgres-local.yaml index 9d200df..0a5e0bc 100644 --- a/deploy/postgres-local.yaml +++ b/deploy/postgres-local.yaml @@ -20,12 +20,8 @@ spec: - image: postgres:12-alpine name: postgres command: - - tini - - -- - args: - - sh - - -c - - backup-restore-sidecar wait && docker-entrypoint.sh postgres + - backup-restore-sidecar + - wait ports: - containerPort: 5432 env: @@ -57,18 +53,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: postgres:12-alpine name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/postgres && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug env: - name: BACKUP_RESTORE_SIDECAR_POSTGRES_PASSWORD valueFrom: @@ -88,9 +78,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini initContainers: - name: backup-restore-sidecar-provider image: ghcr.io/metal-stack/backup-restore-sidecar:latest @@ -98,7 +85,6 @@ spec: command: - cp - /backup-restore-sidecar - - /sbin/tini - /bin-provision ports: - containerPort: 2112 @@ -136,6 +122,8 @@ data: backup-cron-schedule: "*/1 * * * *" object-prefix: postgres-test compression-method: tar + post-exec-cmds: + - docker-entrypoint.sh postgres --- apiVersion: v1 kind: Secret diff --git a/deploy/postgres-s3.yaml b/deploy/postgres-s3.yaml index 502abb9..1885475 100644 --- a/deploy/postgres-s3.yaml +++ b/deploy/postgres-s3.yaml @@ -20,12 +20,8 @@ spec: - image: postgres:12-alpine name: postgres command: - - tini - - -- - args: - - sh - - -c - - backup-restore-sidecar wait && docker-entrypoint.sh postgres + - backup-restore-sidecar + - wait ports: - containerPort: 5432 env: @@ -57,18 +53,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: postgres:12-alpine name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/postgres && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug env: - name: BACKUP_RESTORE_SIDECAR_S3_BUCKET_NAME valueFrom: @@ -113,9 +103,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini initContainers: - name: backup-restore-sidecar-provider image: ghcr.io/metal-stack/backup-restore-sidecar:latest @@ -123,7 +110,6 @@ spec: command: - cp - /backup-restore-sidecar - - /sbin/tini - /bin-provision ports: - containerPort: 2112 @@ -160,6 +146,8 @@ data: backup-provider: s3 backup-cron-schedule: "*/1 * * * *" object-prefix: postgres-test + post-exec-cmds: + - docker-entrypoint.sh postgres --- apiVersion: v1 kind: Secret diff --git a/deploy/postgres_manual_restore.yaml b/deploy/postgres_manual_restore.yaml index b5ad5e5..d3b0a5b 100644 --- a/deploy/postgres_manual_restore.yaml +++ b/deploy/postgres_manual_restore.yaml @@ -20,12 +20,9 @@ spec: - image: postgres:12-alpine name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/postgres && tail -f /etc/os-release + - tail + - -f + - /etc/os-release env: - name: BACKUP_RESTORE_SIDECAR_GCP_PROJECT valueFrom: @@ -62,9 +59,6 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: gcp-credentials mountPath: /gcp/credentials readOnly: true @@ -75,7 +69,6 @@ spec: command: - cp - /backup-restore-sidecar - - /sbin/tini - /bin-provision volumeMounts: - name: bin-provision diff --git a/deploy/rethinkdb-gcp.yaml b/deploy/rethinkdb-gcp.yaml index 08c8239..1e3161e 100644 --- a/deploy/rethinkdb-gcp.yaml +++ b/deploy/rethinkdb-gcp.yaml @@ -20,13 +20,8 @@ spec: - image: rethinkdb:2.4.0 name: rethinkdb command: - - tini - - -- - args: - - sh - - -c - # IMPORTANT: the --directory needs to point to the exact sidecar data dir, otherwise the database will be restored to the wrong location - - backup-restore-sidecar wait && rethinkdb --bind all --directory /data/rethinkdb --initial-password ${RETHINKDB_PASSWORD} + - backup-restore-sidecar + - wait env: - name: RETHINKDB_PASSWORD valueFrom: @@ -44,18 +39,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: rethinkdb:2.4.0 name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/rethinkdb && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug env: - name: BACKUP_RESTORE_SIDECAR_GCP_PROJECT valueFrom: @@ -84,9 +73,6 @@ spec: - name: bin-provision subPath: backup-restore-sidecar mountPath: /usr/local/bin/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: bin-provision subPath: rethinkdb-dump mountPath: /usr/local/bin/rethinkdb-dump @@ -103,7 +89,6 @@ spec: command: - cp - /backup-restore-sidecar - - /ubuntu/tini - /rethinkdb/rethinkdb-dump - /rethinkdb/rethinkdb-restore - /bin-provision @@ -155,6 +140,9 @@ data: rethinkdb-passwordfile: /rethinkdb-secret/rethinkdb-password.txt backup-cron-schedule: "*/1 * * * *" object-prefix: rethinkdb-test + post-exec-cmds: + # IMPORTANT: the --directory needs to point to the exact sidecar data dir, otherwise the database will be restored to the wrong location + - rethinkdb --bind all --directory /data/rethinkdb --initial-password ${RETHINKDB_PASSWORD} --- apiVersion: v1 kind: Secret diff --git a/deploy/rethinkdb-local.yaml b/deploy/rethinkdb-local.yaml index ce1b6df..9342ab9 100644 --- a/deploy/rethinkdb-local.yaml +++ b/deploy/rethinkdb-local.yaml @@ -20,13 +20,8 @@ spec: - image: rethinkdb:2.4.0 name: rethinkdb command: - - tini - - -- - args: - - sh - - -c - # IMPORTANT: the --directory needs to point to the exact sidecar data dir, otherwise the database will be restored to the wrong location - - backup-restore-sidecar wait && rethinkdb --bind all --directory /data/rethinkdb --initial-password ${RETHINKDB_PASSWORD} + - backup-restore-sidecar + - wait env: - name: RETHINKDB_PASSWORD valueFrom: @@ -44,18 +39,12 @@ spec: mountPath: /usr/local/bin/backup-restore-sidecar - name: backup-restore-sidecar-config mountPath: /etc/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - image: rethinkdb:2.4.0 name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/rethinkdb && backup-restore-sidecar start --log-level debug + - backup-restore-sidecar + - start + - --log-level=debug volumeMounts: - name: rethinkdb mountPath: /data @@ -66,9 +55,6 @@ spec: - name: bin-provision subPath: backup-restore-sidecar mountPath: /usr/local/bin/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: bin-provision subPath: rethinkdb-dump mountPath: /usr/local/bin/rethinkdb-dump @@ -82,7 +68,6 @@ spec: command: - cp - /backup-restore-sidecar - - /ubuntu/tini - /rethinkdb/rethinkdb-dump - /rethinkdb/rethinkdb-restore - /bin-provision @@ -128,6 +113,9 @@ data: rethinkdb-passwordfile: /rethinkdb-secret/rethinkdb-password.txt backup-cron-schedule: "*/1 * * * *" object-prefix: rethinkdb-test + post-exec-cmds: + # IMPORTANT: the --directory needs to point to the exact sidecar data dir, otherwise the database will be restored to the wrong location + - rethinkdb --bind all --directory /data/rethinkdb --initial-password ${RETHINKDB_PASSWORD} --- apiVersion: v1 kind: Secret diff --git a/deploy/rethinkdb_manual_restore.yaml b/deploy/rethinkdb_manual_restore.yaml index de75032..698e106 100644 --- a/deploy/rethinkdb_manual_restore.yaml +++ b/deploy/rethinkdb_manual_restore.yaml @@ -20,12 +20,9 @@ spec: - image: rethinkdb:2.4.0 name: backup-restore-sidecar command: - - tini - - -- - args: - - sh - - -c - - mkdir -p /data/rethinkdb && tail -f /etc/os-release + - tail + - -f + - /etc/os-release env: - name: BACKUP_RESTORE_SIDECAR_GCP_PROJECT valueFrom: @@ -54,9 +51,6 @@ spec: - name: bin-provision subPath: backup-restore-sidecar mountPath: /usr/local/bin/backup-restore-sidecar - - name: bin-provision - subPath: tini - mountPath: /usr/local/bin/tini - name: bin-provision subPath: rethinkdb-dump mountPath: /usr/local/bin/rethinkdb-dump @@ -73,7 +67,6 @@ spec: command: - cp - /backup-restore-sidecar - - /ubuntu/tini - /rethinkdb/rethinkdb-dump - /rethinkdb/rethinkdb-restore - /bin-provision