Merge branch 'main' into enhance/Make/help

This commit is contained in:
Uajjawal
2026-08-03 14:59:45 +05:30
committed by GitHub
18 changed files with 259 additions and 64 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
if: github.repository == 'velero-io/velero'
runs-on: ubuntu-latest
steps:
- uses: jpmcb/prow-github-actions@v1.1.3
- uses: jpmcb/prow-github-actions@f4d01dd4b13f289014c23fe5a19878a2479cb35b # v1.1.3
with:
# TODO: before allowing the /lgtm command, see if we can block merging if changelog labels are missing.
prow-commands: |
+25 -11
View File
@@ -1,18 +1,32 @@
on:
name: Automatic Rebase
on:
issue_comment:
types: [created]
name: Automatic Rebase
permissions: {}
jobs:
rebase:
name: Rebase
if: github.repository == 'velero-io/velero' && github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
if: >-
github.repository == 'velero-io/velero' &&
github.event.issue.pull_request != null &&
github.event.comment.body == '/rebase' &&
contains(
fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'),
github.event.comment.author_association
)
runs-on: ubuntu-latest
permissions:
# contents: write is required because updating the pull request branch
# pushes commits to the head branch.
contents: write
pull-requests: write
steps:
- name: Checkout the latest code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Rebase pull request
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
run: gh pr update-branch "$PR_NUMBER" --repo "$GH_REPO" --rebase
+1
View File
@@ -0,0 +1 @@
Replace rebase action with GitHub CLI
+1
View File
@@ -0,0 +1 @@
Use "" as parentSnapshot for DU when BackupType is incremental.
+3 -7
View File
@@ -536,14 +536,10 @@ func newDataUpload(
vsc *snapshotv1api.VolumeSnapshotContent,
fsType string,
) *velerov2alpha1.DataUpload {
var parentSnapshot string
switch backup.Spec.BackupType {
case velerov1api.BackupTypeFull:
parentSnapshot := ""
if backup.Spec.BackupType == velerov1api.BackupTypeFull {
parentSnapshot = veleroshared.DataUploadParentSnapshotNone
case velerov1api.BackupTypeIncremental:
parentSnapshot = veleroshared.DataUploadParentSnapshotAuto
default:
parentSnapshot = veleroshared.DataUploadParentSnapshotAuto
}
dataUpload := &velerov2alpha1.DataUpload{
+3 -4
View File
@@ -45,7 +45,6 @@ import (
crclient "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
veleroshared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/builder"
@@ -162,7 +161,7 @@ func TestExecute(t *testing.T) {
SourcePVC: "testPVC",
SourceNamespace: "velero",
OperationTimeout: metav1.Duration{Duration: 1 * time.Minute},
ParentSnapshot: veleroshared.DataUploadParentSnapshotAuto,
ParentSnapshot: "",
},
},
},
@@ -2199,7 +2198,7 @@ func TestNewDataUpload(t *testing.T) {
backupType: velerov1api.BackupTypeIncremental,
vsClassName: ptr.To("test-vs-class"),
uploaderConfig: &velerov1api.UploaderConfigForBackup{ParallelFilesUpload: 10},
expectedParentSnap: "auto",
expectedParentSnap: "",
expectedDataMoverCfg: map[string]string{
uploaderUtil.ParallelFilesUpload: "10",
},
@@ -2209,7 +2208,7 @@ func TestNewDataUpload(t *testing.T) {
backupType: "",
vsClassName: ptr.To("test-vs-class"),
uploaderConfig: &velerov1api.UploaderConfigForBackup{ParallelFilesUpload: 0},
expectedParentSnap: "auto",
expectedParentSnap: "",
expectedDataMoverCfg: nil,
},
}
+7 -1
View File
@@ -86,6 +86,12 @@ func (s *ServiceImpl) GetAllocatedBlocks(ctx context.Context, snapshot string, r
return err
}
saNamespace := ""
if s.SAName != "" {
// The SA is created in the same namespace as Velero server. vsNamespace is the namespace of Velero server.
saNamespace = s.vsNamespace
}
args := iterator.Args{
SnapshotName: snapshot,
Emitter: &emitterImpl{
@@ -95,7 +101,7 @@ func (s *ServiceImpl) GetAllocatedBlocks(ctx context.Context, snapshot string, r
Clients: clients,
Namespace: s.vsNamespace, // DataUpload is created in the same namespace as Velero server. vsNamespace is the namespace of the Velero server.
SANamespace: s.vsNamespace, // The SA is created in the same namespace as Velero server. vsNamespace is the namespace of Velero server.
SANamespace: saNamespace,
SAName: s.SAName,
TokenExpirySecs: iterator.DefaultTokenExpirySeconds,
MaxResults: 0, // If 0 then the CSI driver decides the value.
+1
View File
@@ -331,6 +331,7 @@ func (s *dataMoverBackup) createDataPathService() (dataPathService, error) {
s.config.changeID,
s.config.volumeID,
s.config.snapshotID,
s.cbtService,
s.logger,
), nil
}
+5 -1
View File
@@ -34,6 +34,7 @@ import (
"github.com/vmware-tanzu/velero/internal/credentials"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
"github.com/vmware-tanzu/velero/pkg/cbtservice"
"github.com/vmware-tanzu/velero/pkg/datapath"
"github.com/vmware-tanzu/velero/pkg/repository"
"github.com/vmware-tanzu/velero/pkg/uploader"
@@ -71,6 +72,7 @@ type BackupMicroService struct {
changeID string
volumeID string
snapshotID string
cbtService cbtservice.Service
}
type dataPathResult struct {
@@ -80,7 +82,7 @@ type dataPathResult struct {
func NewBackupMicroService(ctx context.Context, client client.Client, kubeClient kubernetes.Interface, dataUploadName string, namespace string, nodeName string,
sourceTargetPath datapath.AccessPoint, dataPathMgr *datapath.Manager, repoEnsurer *repository.Ensurer, cred *credentials.CredentialGetter,
duInformer cache.Informer, changeID string, volumeID string, snapshotID string, log logrus.FieldLogger) *BackupMicroService {
duInformer cache.Informer, changeID string, volumeID string, snapshotID string, cbtService cbtservice.Service, log logrus.FieldLogger) *BackupMicroService {
return &BackupMicroService{
ctx: ctx,
client: client,
@@ -98,6 +100,7 @@ func NewBackupMicroService(ctx context.Context, client client.Client, kubeClient
changeID: changeID,
volumeID: volumeID,
snapshotID: snapshotID,
cbtService: cbtService,
}
}
@@ -210,6 +213,7 @@ func (r *BackupMicroService) RunCancelableDataPath(ctx context.Context) (string,
VolumeID: r.volumeID,
ChangeID: r.changeID,
SnapshotID: r.snapshotID,
CBTService: r.cbtService,
}); err != nil {
return "", errors.Wrap(err, "error starting data path backup")
}
+2
View File
@@ -57,6 +57,7 @@ type BackupStartParam struct {
VolumeID string
ChangeID string
SnapshotID string
CBTService cbtservice.Service
}
// RestoreStartParam define the input param for restore start
@@ -203,6 +204,7 @@ func (dp *generalDataPath) StartBackup(source AccessPoint, uploaderConfig map[st
VolumeID: backupParam.VolumeID,
ChangeID: backupParam.ChangeID,
},
Service: backupParam.CBTService,
},
source.VolMode,
uploaderConfig,
+19 -23
View File
@@ -19,7 +19,6 @@ package kopialib
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"strings"
@@ -913,8 +912,7 @@ func (kow *kopiaObjectWriterEx) Write(p []byte) (int, error) {
kow.entryLock.Unlock()
buffOffset := curPos - offset
objName := fmt.Sprintf("%s-b%v", kow.description, entryID)
kow.writeObjectAsync(objName, entryID, p[buffOffset:buffOffset+kow.blockSize])
kow.writeObjectAsync(entryID, p[buffOffset:buffOffset+kow.blockSize])
curPos += kow.blockSize
}
@@ -922,38 +920,38 @@ func (kow *kopiaObjectWriterEx) Write(p []byte) (int, error) {
return length, nil
}
func (kow *kopiaObjectWriterEx) writeObject(objName string, p []byte) (object.ID, error) {
func (kow *kopiaObjectWriterEx) writeObject(p []byte) (object.ID, error) {
writer := kow.rawRepoWriter.NewObjectWriter(kopia.SetupKopiaLog(kow.ctx, kow.logger), object.WriterOptions{
Description: objName,
Description: kow.description,
Compressor: kow.compressor,
Splitter: kow.splitter,
})
if writer == nil {
return object.EmptyID, errors.Errorf("error opening writer for %s", objName)
return object.EmptyID, errors.New("error opening writer")
}
defer writer.Close()
written, err := writer.Write(p)
if err != nil {
return object.EmptyID, errors.Wrapf(err, "error writing for %s", objName)
return object.EmptyID, errors.Wrap(err, "error writing data")
}
if written != len(p) {
return object.EmptyID, errors.Errorf("short write for %s", objName)
return object.EmptyID, errors.New("short write")
}
objID, err := writer.Result()
if err != nil {
return object.EmptyID, errors.Wrapf(err, "error flushing data for %s", objName)
return object.EmptyID, errors.Wrap(err, "error flushing data")
}
return objID, nil
}
func (kow *kopiaObjectWriterEx) writeObjectSync(objName string, entry int, p []byte) error {
objID, err := kow.writeObject(objName, p)
func (kow *kopiaObjectWriterEx) writeObjectSync(entry int, p []byte) error {
objID, err := kow.writeObject(p)
if err != nil {
return err
}
@@ -965,10 +963,10 @@ func (kow *kopiaObjectWriterEx) writeObjectSync(objName string, entry int, p []b
return nil
}
func (kow *kopiaObjectWriterEx) writeObjectAsync(objName string, entryID int, p []byte) {
func (kow *kopiaObjectWriterEx) writeObjectAsync(entryID int, p []byte) {
if kow.asyncWritesSem == nil {
if err := kow.writeObjectSync(objName, entryID, p); err != nil {
kow.saveWriteError(errors.Wrapf(err, "error writing object for %s", objName))
if err := kow.writeObjectSync(entryID, p); err != nil {
kow.saveWriteError(errors.Wrapf(err, "error writing object for %s, entry %d", kow.description, entryID))
}
} else {
kow.asyncWritesSem <- struct{}{}
@@ -977,8 +975,8 @@ func (kow *kopiaObjectWriterEx) writeObjectAsync(objName string, entryID int, p
copy(buffer, p)
kow.asyncWritesGroup.Go(func() {
if err := kow.writeObjectSync(objName, entryID, buffer); err != nil {
kow.saveWriteError(errors.Wrapf(err, "error writing object for %s", objName))
if err := kow.writeObjectSync(entryID, buffer); err != nil {
kow.saveWriteError(errors.Wrapf(err, "error writing object for %s, entry %d", kow.description, entryID))
}
kow.asyncBuffer.Return(buffer)
@@ -987,10 +985,10 @@ func (kow *kopiaObjectWriterEx) writeObjectAsync(objName string, entryID int, p
}
}
func (kow *kopiaObjectWriterEx) writeZeroObject(objName string, entryID int) error {
func (kow *kopiaObjectWriterEx) writeZeroObject(entryID int) error {
if kow.zeroObject == object.EmptyID {
zeroBuffer := make([]byte, kow.blockSize)
objectID, err := kow.writeObject(objName, zeroBuffer)
objectID, err := kow.writeObject(zeroBuffer)
if err != nil {
return err
}
@@ -1071,9 +1069,8 @@ func (kow *kopiaObjectWriterEx) WriteAt(p []byte, offset int64) (int, error) {
})
kow.entryLock.Unlock()
objName := fmt.Sprintf("%s-b%v", kow.description, entryID)
if err := kow.writeZeroObject(objName, entryID); err != nil {
return 0, errors.Wrapf(err, "error writing zero object for %s", objName)
if err := kow.writeZeroObject(entryID); err != nil {
return 0, errors.Wrapf(err, "error writing zero object for %s, entry %v", kow.description, entryID)
}
curPos += kow.blockSize
@@ -1093,8 +1090,7 @@ func (kow *kopiaObjectWriterEx) WriteAt(p []byte, offset int64) (int, error) {
kow.entryLock.Unlock()
buffOffset := curPos - offset
objName := fmt.Sprintf("%s-b%v", kow.description, entryID)
kow.writeObjectAsync(objName, entryID, p[buffOffset:buffOffset+kow.blockSize])
kow.writeObjectAsync(entryID, p[buffOffset:buffOffset+kow.blockSize])
curPos += kow.blockSize
}
@@ -291,7 +291,7 @@ func TestKopiaObjectWriterEx_Write(t *testing.T) {
t.Helper()
err := kow.getWriteError()
require.Error(t, err)
assert.Contains(t, err.Error(), "error opening writer for -b0")
assert.Contains(t, err.Error(), "error writing object for , entry 0: error opening writer")
},
},
{
@@ -936,7 +936,7 @@ func TestKopiaObjectWriterEx_WriteAt(t *testing.T) {
},
inputData: make([]byte, 1024),
offset: 1024,
expectedErr: "error writing zero object for -b0: error writing for -b0: simulated zero object write error",
expectedErr: "error writing zero object for , entry 0: error writing data: simulated zero object write error",
},
{
name: "writeObject short write",
@@ -964,7 +964,7 @@ func TestKopiaObjectWriterEx_WriteAt(t *testing.T) {
t.Helper()
err := kow.getWriteError()
require.Error(t, err)
assert.Contains(t, err.Error(), "short write for -b0")
assert.Contains(t, err.Error(), "error writing object for , entry 0: short write")
},
},
}
+22 -8
View File
@@ -19,12 +19,14 @@ package block
import (
"bytes"
"context"
"fmt"
"io"
"os"
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/cockroachdb/errors"
"github.com/sirupsen/logrus"
@@ -61,10 +63,11 @@ type Uploader interface {
}
type blockUploader struct {
ctx context.Context
repoWriter udmrepo.BackupRepo
progress uploader.ProgressUpdater
log logrus.FieldLogger
ctx context.Context
repoWriter udmrepo.BackupRepo
progress uploader.ProgressUpdater
log logrus.FieldLogger
lastProgressUpdate time.Time
}
func NewUploader(ctx context.Context, repoWriter udmrepo.BackupRepo, progress uploader.ProgressUpdater, log logrus.FieldLogger) Uploader {
@@ -89,7 +92,7 @@ func (blkup *blockUploader) Backup(source sourceInfo, parentObject udmrepo.ID, b
}
destObj, err := blkup.repoWriter.NewObjectWriter(blkup.ctx, udmrepo.ObjectWriteOptions{
Description: "BDEV:" + getObjectName(source.realSource),
Description: fmt.Sprintf("BDEV:%s-%s", getObjectName(source.realSource), snapStart.Format("2006-01-02-15-04-05")),
DataType: udmrepo.ObjectDataTypeData,
AccessMode: udmrepo.ObjectDataAccessModeBlock,
ParentObject: parentObject,
@@ -197,6 +200,17 @@ func (blkup *blockUploader) backupObject(dev *os.File, dest udmrepo.ObjectWriter
return id, backupSize, objectSize, err
}
func (blkup *blockUploader) UpdateProgress(p *uploader.Progress) {
if blkup.progress == nil {
return
}
if time.Since(blkup.lastProgressUpdate) >= 10*time.Second || p.BytesDone == p.TotalBytes {
blkup.progress.UpdateProgress(p)
blkup.lastProgressUpdate = time.Now()
}
}
type readResult struct {
buffer []byte
offset int64
@@ -232,7 +246,7 @@ func (blkup *blockUploader) backupData(reader io.ReaderAt, writer udmrepo.Object
go func() {
defer wg.Done()
defer close(quit)
written, lastPos, writeErr = backupWriteProc(blkup.ctx, writer, resultChan, list, aligned, totalCount, int(blockSize), blkup.progress)
written, lastPos, writeErr = backupWriteProc(blkup.ctx, writer, resultChan, list, aligned, totalCount, int(blockSize), blkup)
}()
wg.Wait()
@@ -249,7 +263,7 @@ func (blkup *blockUploader) backupData(reader io.ReaderAt, writer udmrepo.Object
written += s
blkup.progress.UpdateProgress(&uploader.Progress{BytesDone: aligned, TotalBytes: aligned})
blkup.UpdateProgress(&uploader.Progress{BytesDone: aligned, TotalBytes: aligned})
}
return written, aligned, nil
@@ -418,7 +432,7 @@ func (blkup *blockUploader) restoreData(reader io.ReadSeeker, dest *os.File, bit
go func() {
defer wg.Done()
defer close(quit)
written, writeErr = restoreWriteProc(blkup.ctx, dest, resultChan, list, totalLength, totalCount, int(blockSize), destPath, blkup.progress, blkup.log)
written, writeErr = restoreWriteProc(blkup.ctx, dest, resultChan, list, totalLength, totalCount, int(blockSize), destPath, blkup, blkup.log)
}()
wg.Wait()
+2 -1
View File
@@ -21,6 +21,7 @@ import (
"context"
"io"
"os"
"strings"
"testing"
"time"
@@ -357,7 +358,7 @@ func TestBlockUploaderBackup(t *testing.T) {
}
repoWriter.On("NewObjectWriter", mock.Anything, mock.MatchedBy(func(opt udmrepo.ObjectWriteOptions) bool {
return opt.Description == "BDEV:data-volume1" && opt.BackupMode == backupMode
return strings.HasPrefix(opt.Description, "BDEV:data-volume1-") && opt.BackupMode == backupMode
})).Return(objWriter, tc.createObjErr)
}
+4 -1
View File
@@ -8,7 +8,7 @@ frontmatter:
params:
author: Velero Authors
logo: Velero.svg
cncf_logo: cncf-white.svg
cncf_logo: cncf-color.svg
hero:
backgroundColor: med-blue
versioning: true
@@ -63,6 +63,9 @@ params:
- title: Twitter
fa_icon: fab fa-twitter
url: https://twitter.com/projectvelero
- title: LinkedIn
fa_icon: fab fa-linkedin
url: https://www.linkedin.com/company/project-velero
- title: Slack
fa_icon: fab fa-slack
url: https://kubernetes.slack.com/messages/velero
+3 -3
View File
@@ -32,7 +32,7 @@ secondary_ctas:
url: /blog/Velero-is-an-Open-Source-Tool-to-Back-up-and-Migrate-Kubernetes-Clusters/ # Velero.io word list : ignore
content: Learn about Velero and how to protect your Kubernetes resources and volumes.
cta2:
title: How Do You Use Velero?
url: https://github.com/velero-io/velero/issues/1327
content: See how Velero is helping others and tell the world how you use Velero.
title: Join the Velero Community
url: /community/
content: Connect with other Velero users on Slack, attend community meetings, and contribute to the project.
---
@@ -0,0 +1,69 @@
---
title: "Velero Joins the CNCF Sandbox"
excerpt: Velero has been accepted into the Cloud Native Computing Foundation as a Sandbox project, bringing Kubernetes-native backup and disaster recovery under vendor-neutral, community-driven governance.
author_name: Shubham Pampattiwar
slug: Velero-Joins-CNCF-Sandbox
categories: ['velero','announcements']
image: /img/cncf-color.svg
tags: ['Velero Team', 'Shubham Pampattiwar', 'CNCF']
---
![CNCF Logo](/img/cncf-color.svg)
We are excited to announce that Velero has been accepted into the [Cloud Native Computing Foundation (CNCF)](https://www.cncf.io/) as a Sandbox project. This marks a significant milestone for the project, placing Velero under vendor-neutral, community-driven governance alongside other foundational cloud native tools.
The CNCF Technical Oversight Committee (TOC) accepted the [Sandbox application](https://github.com/cncf/sandbox/issues/457), and the transition was formally announced at KubeCon + CloudNativeCon Europe 2026 in Amsterdam.
## What This Means
Joining the CNCF Sandbox means Velero is now governed by the same open, vendor-neutral principles that guide projects like Kubernetes, Prometheus, and Envoy. In practice, this means:
- **Vendor-neutral governance**: No single company controls the project roadmap. Decisions are made through consensus-based processes with supermajority voting.
- **Community-driven development**: The project's direction is shaped by its maintainers and contributors, who represent multiple organizations.
- **Long-term sustainability**: CNCF provides a neutral home that ensures the project's continuity regardless of changes in any single company's priorities.
For existing Velero users, nothing changes in how you use the tool. Velero continues to operate at the Kubernetes API layer, providing backup, restore, disaster recovery, and migration capabilities for your clusters and applications.
## Our Journey
Velero's journey began at Heptio, the Kubernetes company founded by Joe Beda and Craig McLuckie, where it was originally known as Ark. After VMware acquired Heptio in 2019, the project continued to grow under VMware's stewardship. Following Broadcom's acquisition of VMware, the decision was made to contribute Velero to the CNCF, ensuring the project's future under community governance.
Throughout these transitions, one thing has remained constant: a growing and engaged open source community. Today, Velero has over 10,000 GitHub stars, 1,500+ forks, 500M+ Docker Hub pulls, and is used by organizations across industries for Kubernetes data protection.
We are grateful to Broadcom for contributing Velero to the CNCF and to everyone who has contributed to the project over the years.
## Current Maintainers
Velero is maintained by engineers from multiple organizations, reflecting the project's vendor-neutral nature:
| Maintainer | GitHub | Affiliation |
|---|---|---|
| Daniel Jiang | [@reasonerjt](https://github.com/reasonerjt) | Broadcom |
| Wenkai Yin | [@ywk253100](https://github.com/ywk253100) | Broadcom |
| Xun Jiang | [@blackpiglet](https://github.com/blackpiglet) | Broadcom |
| Yonghui Li | [@Lyndon-Li](https://github.com/Lyndon-Li) | Broadcom |
| Scott Seago | [@sseago](https://github.com/sseago) | Red Hat (OpenShift) |
| Shubham Pampattiwar | [@shubham-pampattiwar](https://github.com/shubham-pampattiwar) | Red Hat (OpenShift) |
| Tiger Kaovilai | [@kaovilai](https://github.com/kaovilai) | Red Hat (OpenShift) |
| Anshul Ahuja | [@anshulahuja98](https://github.com/anshulahuja98) | Microsoft (Azure) |
## What's Next
Joining the CNCF Sandbox is the beginning of a new chapter for Velero. Here is what we are focused on:
- **Growing the community**: We want more contributors, more adopters, and more voices shaping the project's direction. Whether you are a user, operator, or developer, there is a place for you in the Velero community.
- **Strengthening the project**: We are continuing to improve Velero's core capabilities around backup performance, data protection, and ecosystem integration.
- **Path to Incubation**: Our goal is to demonstrate the community health, adoption, and maturity needed to advance to CNCF Incubation status.
## Get Involved
We welcome contributions of all kinds -- code, documentation, bug reports, feature requests, and feedback.
- **Slack**: Join [#velero-users](https://kubernetes.slack.com/messages/velero) and [#velero-dev](https://kubernetes.slack.com/messages/velero-dev) on Kubernetes Slack
- **GitHub**: [github.com/velero-io/velero](https://github.com/velero-io/velero)
- **Community Meetings**: We hold bi-weekly community meetings alternating between US/Europe and US/Asia-friendly time zones. See the [community page](https://velero.io/community/) for details.
- **LinkedIn**: Follow us at [Project Velero](https://www.linkedin.com/company/project-velero)
- **Twitter/X**: [@projectvelero](https://twitter.com/projectvelero)
- **Contributing**: Check out our [contribution guide](https://velero.io/docs/main/start-contributing/) to get started.
We are excited about this new chapter and look forward to building the future of Kubernetes data protection together with the community.
+88
View File
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="a" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 399.1 76.1" style="enable-background:new 0 0 399.1 76.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0086FF;}
.st1{fill:#93EAFF;}
</style>
<g>
<g>
<g>
<path d="M98.9,33.4c1.5,0,2.9-0.3,4.3-0.9c1.3-0.6,2.5-1.6,3.4-2.8l4.1,4.2c-3.2,3.6-6.9,5.4-11.3,5.4c-2,0.1-3.9-0.2-5.8-1
c-1.8-0.7-3.5-1.8-5-3.1c-1.4-1.3-2.5-3-3.2-4.7c-0.7-1.8-1.1-3.7-1-5.6c-0.1-1.9,0.3-3.9,1-5.7c0.7-1.8,1.8-3.4,3.2-4.8
c1.5-1.4,3.3-2.5,5.2-3.2c1.9-0.7,4-1,6.1-0.9c2.1,0.1,4.1,0.6,6,1.5c1.9,0.9,3.5,2.2,4.9,3.8l-3.9,4.5c-0.9-1.2-2-2.1-3.3-2.7
c-1.3-0.6-2.7-1-4.2-1c-2.2,0-4.4,0.8-6.1,2.3c-0.9,0.8-1.5,1.8-2,2.9c-0.4,1.1-0.6,2.3-0.6,3.4c-0.1,1.2,0.1,2.3,0.5,3.4
c0.4,1.1,1,2.1,1.9,2.9C94.7,32.6,96.8,33.4,98.9,33.4L98.9,33.4z M115.5,38.9V10.7h6.3v22.6h12.1v5.6H115.5z M161.5,35
c-2.9,2.7-6.6,4.2-10.6,4.2s-7.7-1.5-10.6-4.2c-1.4-1.3-2.5-2.9-3.2-4.7c-0.7-1.8-1.1-3.7-1.1-5.6c-0.1-1.9,0.3-3.9,1-5.6
c0.7-1.8,1.8-3.4,3.2-4.7c2.9-2.7,6.6-4.2,10.6-4.2s7.7,1.5,10.6,4.2c1.4,1.3,2.5,2.9,3.2,4.7c0.7,1.8,1.1,3.7,1,5.6
c0.1,1.9-0.3,3.9-1,5.6C164,32.1,162.9,33.7,161.5,35z M159.3,24.7c0-2.4-0.9-4.7-2.5-6.5c-0.8-0.8-1.7-1.5-2.7-2
c-1-0.5-2.2-0.7-3.3-0.7c-1.1,0-2.2,0.2-3.3,0.7c-1,0.5-2,1.1-2.7,2c-1.6,1.8-2.5,4.1-2.5,6.5c0,2.4,0.9,4.7,2.5,6.5
c0.8,0.8,1.7,1.5,2.7,2c1,0.5,2.2,0.7,3.3,0.7c1.1,0,2.2-0.2,3.3-0.7c1-0.5,2-1.1,2.7-2c0.8-0.9,1.5-1.9,1.9-3
C159.2,27,159.4,25.9,159.3,24.7z M178.6,31.7c0.5,0.7,1.2,1.2,1.9,1.5c0.7,0.3,1.6,0.5,2.4,0.5c0.8,0,1.6-0.1,2.3-0.5
c0.7-0.3,1.4-0.9,1.8-1.5c1.1-1.6,1.6-3.4,1.5-5.3V10.8h6.3v15.8c0,4.1-1.1,7.2-3.4,9.4c-1.2,1.1-2.5,2-4,2.5
c-1.5,0.6-3.1,0.8-4.7,0.8c-1.6,0-3.2-0.2-4.7-0.8c-1.5-0.6-2.9-1.4-4-2.5c-2.3-2.2-3.4-5.3-3.4-9.4V10.8h6.3v15.6
C176.9,28.3,177.5,30.2,178.6,31.7z M223.1,14.4c2.7,2.5,4.1,5.9,4.1,10.3s-1.3,7.9-3.9,10.5c-2.6,2.6-6.7,3.8-12,3.8h-9.8V10.7
h10C216.5,10.7,220.4,11.9,223.1,14.4z M218.5,31.2c1.5-1.4,2.3-3.6,2.3-6.4s-0.8-4.9-2.3-6.4s-3.9-2.3-7.1-2.3h-3.5v17.2h4
C214.3,33.5,216.7,32.8,218.5,31.2z M263.1,10.7h6.3v28.3h-6.3l-13.5-17.7v17.7h-6.3V10.7h5.9l13.9,18.2V10.7z M296.5,38.9
l-2.7-6.1h-11.9l-2.7,6.1h-6.8l12.2-28.3h6.1L303,38.9H296.5z M288,19.1l-3.5,8.2h7L288,19.1z M316.5,16.2V39h-6.3V16.2h-8v-5.4
h22.4v5.4C324.6,16.2,316.5,16.2,316.5,16.2z M329,10.7h6.3v28.3H329C329,38.9,329,10.7,329,10.7z M352.8,28.7l7.2-18h6.9
l-11.3,28.3h-5.3l-11.3-28.3h6.9L352.8,28.7z M390.5,10.7v5.6h-14.1v5.8h12.7v5.4h-12.7v5.9H391V39h-20.8V10.8L390.5,10.7
C390.5,10.8,390.5,10.7,390.5,10.7z M91.6,63c0.8,0,1.6-0.2,2.4-0.5c0.7-0.4,1.4-0.9,1.9-1.6l2.3,2.4c-0.8,0.9-1.7,1.7-2.9,2.2
c-1.1,0.5-2.3,0.8-3.5,0.8c-1.1,0-2.2-0.1-3.2-0.5c-1-0.4-2-1-2.8-1.8c-0.8-0.7-1.4-1.6-1.8-2.6c-0.4-1-0.6-2.1-0.6-3.2
c0-1.1,0.2-2.2,0.6-3.2c0.4-1,1-1.9,1.8-2.7c0.8-0.8,1.7-1.4,2.7-1.8c1-0.4,2.1-0.6,3.2-0.6c1.2,0,2.5,0.2,3.6,0.7
c1.1,0.5,2.1,1.3,3,2.2l-2.2,2.5c-0.5-0.7-1.1-1.2-1.8-1.6c-0.7-0.4-1.5-0.5-2.4-0.5c-1.3,0-2.5,0.5-3.4,1.3
c-0.5,0.4-0.9,1-1.1,1.6c-0.2,0.6-0.4,1.3-0.3,1.9c0,0.6,0.1,1.3,0.3,1.9c0.2,0.6,0.6,1.2,1,1.6c0.4,0.4,0.9,0.8,1.5,1
S91,63,91.6,63L91.6,63z M113.9,63.9c-1.6,1.5-3.7,2.4-5.9,2.4c-1.1,0-2.2-0.2-3.2-0.6c-1-0.4-1.9-1-2.7-1.8
c-1.5-1.5-2.4-3.6-2.4-5.8s0.9-4.3,2.4-5.8c1.6-1.5,3.7-2.4,5.9-2.4c1.1,0,2.2,0.2,3.2,0.6s1.9,1,2.7,1.8
c1.5,1.5,2.4,3.6,2.4,5.8S115.4,62.4,113.9,63.9z M112.8,58.1c0-1.3-0.4-2.6-1.3-3.6c-0.4-0.5-0.9-0.8-1.5-1.1
c-0.6-0.3-1.2-0.4-1.8-0.4c-0.6,0-1.3,0.1-1.8,0.4c-0.6,0.3-1.1,0.7-1.5,1.2c-0.5,0.5-0.8,1-1,1.7c-0.2,0.6-0.3,1.3-0.3,1.9
c0,1.3,0.5,2.6,1.3,3.6c0.4,0.5,0.9,0.8,1.5,1.1c0.6,0.3,1.2,0.4,1.8,0.4c0.6,0,1.3-0.1,1.8-0.4c0.6-0.3,1.1-0.7,1.5-1.2
C112.3,60.8,112.8,59.5,112.8,58.1L112.8,58.1z M133.5,56.1l-4.3,8.7h-2.1l-4.3-8.7v10h-3.5V50.3h4.8l4.1,8.7l4.1-8.7h4.8v15.9
h-3.5L133.5,56.1L133.5,56.1z M151.9,51.8c0.6,0.5,1.1,1.2,1.4,2c0.3,0.8,0.4,1.6,0.3,2.4c0,2-0.6,3.4-1.7,4.3
c-1.1,1-2.9,1.3-5.2,1.3h-2.1v4.4H141V50.3h5.6C149,50.3,150.7,50.8,151.9,51.8z M149.3,58c0.5-0.6,0.7-1.3,0.7-2.1
c0-0.4,0-0.7-0.2-1.1c-0.2-0.3-0.4-0.6-0.7-0.8c-0.8-0.4-1.7-0.6-2.6-0.6h-2v5.3h2.4c0.4,0,0.9,0,1.3-0.1
C148.6,58.4,149,58.2,149.3,58z M160.6,62c0.3,0.4,0.6,0.6,1.1,0.8c0.4,0.2,0.9,0.3,1.3,0.3c0.5,0,0.9-0.1,1.3-0.3
c0.4-0.2,0.8-0.5,1.1-0.8c0.6-0.9,0.9-2,0.9-3v-8.8h3.5v8.8c0.1,1-0.1,1.9-0.4,2.9c-0.3,0.9-0.8,1.8-1.5,2.5
c-1.3,1.2-3.1,1.8-4.9,1.8c-1.8,0-3.5-0.7-4.8-1.9c-0.7-0.7-1.2-1.6-1.5-2.5c-0.3-0.9-0.5-1.9-0.4-2.9v-8.8h3.5v8.8
C159.6,60,159.9,61.1,160.6,62z M180.1,53.4v12.7h-3.5V53.4h-4.5v-3h12.6v3C184.6,53.4,180.1,53.4,180.1,53.4z M187.2,50.3h3.5
v15.9h-3.5C187.2,66.2,187.2,50.3,187.2,50.3z M205.7,50.3h3.5v15.9h-3.5l-7.5-9.9v9.9h-3.5V50.3h3.3l7.8,10.2L205.7,50.3
C205.8,50.3,205.7,50.3,205.7,50.3z M223.5,58.1h3.5v5.6c-0.8,0.9-1.9,1.6-3,2c-1.1,0.5-2.4,0.7-3.6,0.6c-2.2,0-4.3-0.8-5.9-2.3
c-0.8-0.7-1.4-1.6-1.8-2.6c-0.4-1-0.6-2.1-0.6-3.2c0-1.1,0.2-2.2,0.6-3.2c0.4-1,1-1.9,1.8-2.7s1.7-1.4,2.7-1.8
c1-0.4,2.1-0.6,3.2-0.6c2.2,0,4.3,0.8,5.9,2.3l-1.8,2.7c-0.5-0.6-1.2-1-2-1.2c-0.6-0.2-1.3-0.4-1.9-0.4c-1.3,0-2.5,0.5-3.4,1.3
c-0.5,0.5-0.9,1-1.1,1.7s-0.4,1.3-0.3,2c0,1.3,0.4,2.6,1.3,3.6c0.4,0.4,0.9,0.8,1.4,1c0.5,0.2,1.1,0.3,1.7,0.3
c1.1,0.1,2.1-0.2,3-0.7v-4.5H223.5z M247,50.3v3.1h-7.3v3.4h6.9V60h-6.9v6.2h-3.5V50.3C236.1,50.3,247,50.3,247,50.3z
M263.4,63.9c-1.6,1.5-3.7,2.4-5.9,2.4c-1.1,0-2.2-0.2-3.2-0.6c-1-0.4-1.9-1-2.7-1.8c-1.5-1.5-2.4-3.6-2.4-5.8s0.9-4.3,2.4-5.8
c1.6-1.5,3.7-2.4,5.9-2.4c1.1,0,2.2,0.2,3.2,0.6s1.9,1,2.7,1.8c1.5,1.5,2.4,3.6,2.4,5.8S264.9,62.4,263.4,63.9z M262.1,58.1
c0-1.3-0.4-2.6-1.3-3.6c-0.4-0.5-0.9-0.8-1.5-1.1c-0.6-0.3-1.2-0.4-1.8-0.4c-0.6,0-1.3,0.1-1.8,0.4c-0.6,0.3-1.1,0.7-1.5,1.2
c-0.5,0.5-0.8,1-1,1.7s-0.3,1.3-0.3,1.9c0,1.3,0.5,2.6,1.3,3.6c0.4,0.5,0.9,0.8,1.5,1.1c0.6,0.3,1.2,0.4,1.8,0.4
c0.6,0,1.3-0.1,1.8-0.4c0.6-0.3,1.1-0.7,1.5-1.2c0.5-0.5,0.8-1,1-1.7S262.2,58.8,262.1,58.1L262.1,58.1z M273,62
c0.3,0.4,0.6,0.6,1.1,0.8c0.4,0.2,0.9,0.3,1.3,0.3s0.9-0.1,1.3-0.3c0.4-0.2,0.8-0.5,1.1-0.8c0.6-0.9,0.9-2,0.9-3v-8.8h3.5v8.8
c0.1,1-0.1,1.9-0.4,2.9c-0.3,0.9-0.8,1.8-1.5,2.5c-1.3,1.2-3.1,1.8-4.9,1.8c-1.8,0-3.5-0.7-4.8-1.9c-0.7-0.7-1.2-1.6-1.5-2.5
c-0.3-0.9-0.5-1.9-0.4-2.9v-8.8h3.5v8.8C272,60,272.3,61.2,273,62z M296.9,50.3h3.5v15.9h-3.5l-7.5-9.9v9.9h-3.5V50.3h3.3
l7.8,10.2L296.9,50.3C297,50.3,296.9,50.3,296.9,50.3z M316.4,52.4c0.8,0.7,1.4,1.7,1.8,2.7s0.6,2.1,0.5,3.1
c0.1,1.1-0.1,2.1-0.5,3.1c-0.4,1-1,1.9-1.7,2.7c-1.4,1.4-3.7,2.2-6.8,2.2h-5.4V50.3h5.6C312.8,50.3,315,51,316.4,52.4z
M313.8,61.9c0.4-0.5,0.8-1,1-1.6c0.2-0.6,0.3-1.3,0.3-1.9c0-0.7-0.1-1.3-0.3-1.9s-0.6-1.2-1-1.7c-0.6-0.5-1.2-0.8-1.9-1
s-1.4-0.3-2.1-0.2h-2v9.6h2.3C311.4,63.1,312.8,62.7,313.8,61.9z M332.6,66.1l-1.4-3.4h-6.7l-1.4,3.4h-3.8l6.9-15.9h3.4l6.9,15.9
H332.6z M327.8,55l-2,4.6h4L327.8,55z M343.8,53.4v12.7h-3.5V53.4h-4.6v-3h12.6v3C348.3,53.4,343.8,53.4,343.8,53.4z M350.8,50.3
h3.5v15.9h-3.5C350.8,66.2,350.8,50.3,350.8,50.3z M371.6,63.9c-1.6,1.5-3.7,2.4-5.9,2.4c-1.1,0-2.2-0.2-3.2-0.6s-1.9-1-2.7-1.8
c-1.5-1.5-2.4-3.6-2.4-5.8s0.9-4.3,2.4-5.8c1.6-1.5,3.7-2.4,5.9-2.4c1.1,0,2.2,0.2,3.2,0.6c1,0.4,1.9,1,2.7,1.8
c1.5,1.5,2.4,3.6,2.4,5.8S373.1,62.4,371.6,63.9z M370.5,58.1c0-1.3-0.5-2.6-1.3-3.6c-0.4-0.5-0.9-0.8-1.5-1.1
c-0.6-0.3-1.2-0.4-1.8-0.4c-0.6,0-1.3,0.1-1.8,0.4c-0.6,0.3-1.1,0.7-1.5,1.2c-0.5,0.5-0.8,1-1,1.7s-0.3,1.3-0.3,1.9
c0,1.3,0.5,2.6,1.3,3.6c0.4,0.5,0.9,0.8,1.5,1.1c0.6,0.3,1.2,0.4,1.8,0.4c0.6,0,1.3-0.1,1.8-0.4c0.6-0.3,1.1-0.7,1.5-1.2
C370,60.8,370.5,59.5,370.5,58.1z M388.1,50.3h3.5v15.9h-3.5l-7.5-9.9v9.9H377V50.3h3.3l7.8,10.2
C388.2,60.5,388.1,50.3,388.1,50.3z"/>
</g>
</g>
</g>
<g>
<path class="st0" d="M16.2,47.3H7.5v20.3h20.3v-8.7H16.2V47.3z"/>
<path class="st0" d="M59.8,47.4v11.5H48.2v8.7h20.3V47.3L59.8,47.4L59.8,47.4z"/>
<path class="st0" d="M7.5,27.1h8.8L16.2,27V15.5h11.6V6.8H7.5V27.1z"/>
<path class="st0" d="M48.2,6.8v8.7h11.6v11.6h8.7V6.8C68.4,6.8,48.2,6.8,48.2,6.8z"/>
<path class="st1" d="M47,27.1L35.4,15.5h12.7V6.8H27.8v8.7l11.6,11.6H47z"/>
<path class="st1" d="M36.6,47.3H29l9.6,9.6l1.9,2H27.8v8.7h20.4v-8.8l-5.8-5.7L36.6,47.3z"/>
<path class="st1" d="M59.8,27.1v12.6l-2-2l-9.6-9.6v7.7l5.7,5.7l5.8,5.8h8.8V27.1H59.8L59.8,27.1z"/>
<path class="st1" d="M27.8,38.6L16.3,27.1H7.5v20.2h8.7V34.7l11.6,11.6V38.6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB