Compare commits

...

17 Commits

Author SHA1 Message Date
Wenkai Yin(尹文开)
76670e940c Merge pull request #7351 from ywk253100/240124_log
Log the error details
2024-01-24 13:54:27 +08:00
Wenkai Yin(尹文开)
25d977e5bc Log the error details
Log the error details

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-24 12:43:59 +08:00
qiuming
94c7d4b6d4 Merge pull request #7346 from ywk253100/240122_changelog
Check whether the API resource exists before creating the informer cache
2024-01-24 10:47:16 +08:00
Wenkai Yin(尹文开)
09401c8454 Check whether the API resource exists before creating the informer cache
Check whether the API resource exists before creating the informer cache

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-23 17:19:09 +08:00
qiuming
981d64a1b8 Merge pull request #7338 from ywk253100/240122_changelog
Move unreleased changelogs to 1.13 changelog
2024-01-23 10:19:56 +08:00
Wenkai Yin(尹文开)
16b8b8da72 Move unreleased changelogs to 1.13 changelog
Move unreleased changelogs to 1.13 changelog

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-23 10:06:15 +08:00
lyndon-li
9fd73b2d13 Merge pull request #7339 from ywk253100/240122_log_erro
Log the error got from the discovery helper
2024-01-22 14:11:38 +08:00
Wenkai Yin(尹文开)
c377e472e8 Log the error got from the discovery helper
Log the error got from the discovery helper

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-22 11:12:00 +08:00
Wenkai Yin(尹文开)
f5714cb636 [cherry-pick]Do not attempt restore resource with no available GVK in cluster (#7336)
* Specify the Kind explicitly in the API resource

Specify the Kind explicitly in the API resource to avoid wrong Kind conversion


* Do not attempt restore resource with no available GVK in cluster (#7322)

Check for GVK before attempting restore.


---------

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
Co-authored-by: Tiger Kaovilai <tkaovila@redhat.com>
2024-01-22 10:51:36 +08:00
Wenkai Yin(尹文开)
5ffa12189b Merge pull request #7328 from ywk253100/240118_release_node
Add release note for the informer cache memory consumption
2024-01-18 15:27:43 +08:00
Wenkai Yin(尹文开)
1882be763e Add release note for the informer cache memory consumption
Add release note for the informer cache memory consumption

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-18 13:47:34 +08:00
Wenkai Yin(尹文开)
42bbf87197 Merge pull request #7325 from ywk253100/240116_informer
Create informer per resources to avoid huge memory consumption
2024-01-18 10:44:15 +08:00
Wenkai Yin(尹文开)
8aa6a8e59d Create informer per resources to avoid huge memory consumption
Create informer per resources to avoid huge memory consumption

Fixes #7323

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-17 22:37:49 +08:00
Xun Jiang/Bruce Jiang
fdb29819b4 Merge pull request #7304 from blackpiglet/fix_7268_release_1.13
Add detail for parameter s3ForcePathStyle in MinIO page.
2024-01-15 13:31:30 +08:00
Xun Jiang
74f225037c Add detail for parameter s3ForcePathStyle in MinIO page.
Signed-off-by: Xun Jiang <blackpigletbruce@gmail.com>
2024-01-12 16:55:38 +08:00
Wenkai Yin(尹文开)
6e90e628aa Merge pull request #7303 from ywk253100/240110_pin
Pin the version of Golang and base image
2024-01-10 17:52:51 +08:00
Wenkai Yin(尹文开)
46f64f2f98 Pin the version of Golang and base image
Pin the version of Golang and base image

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
2024-01-10 17:35:28 +08:00
16 changed files with 98 additions and 89 deletions

View File

@@ -14,7 +14,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.21.6'
id: go
# Look for a CLI that's made for this PR
- name: Fetch built CLI

View File

@@ -14,7 +14,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.21.6'
id: go
# Look for a CLI that's made for this PR
- name: Fetch built CLI
@@ -72,7 +72,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.21.6'
id: go
- name: Check out the code
uses: actions/checkout@v2

View File

@@ -10,7 +10,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.21.6'
id: go
- name: Check out the code
uses: actions/checkout@v2

View File

@@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.21.6'
id: go
- uses: actions/checkout@v3

View File

@@ -13,7 +13,7 @@
# limitations under the License.
# Velero binary build section
FROM --platform=$BUILDPLATFORM golang:1.21-bookworm as velero-builder
FROM --platform=$BUILDPLATFORM golang:1.21.6-bookworm as velero-builder
ARG GOPROXY
ARG BIN
@@ -47,7 +47,7 @@ RUN mkdir -p /output/usr/bin && \
go clean -modcache -cache
# Restic binary build section
FROM --platform=$BUILDPLATFORM golang:1.21-bookworm as restic-builder
FROM --platform=$BUILDPLATFORM golang:1.21.6-bookworm as restic-builder
ARG BIN
ARG TARGETOS
@@ -70,7 +70,7 @@ RUN mkdir -p /output/usr/bin && \
go clean -modcache -cache
# Velero image packing section
FROM paketobuildpacks/run-jammy-tiny:latest
FROM paketobuildpacks/run-jammy-tiny:0.2.19
LABEL maintainer="Xun Jiang <jxun@vmware.com>"

View File

@@ -52,7 +52,7 @@ git_sha = str(local("git rev-parse HEAD", quiet = True, echo_off = True)).strip(
tilt_helper_dockerfile_header = """
# Tilt image
FROM golang:1.21 as tilt-helper
FROM golang:1.21.6 as tilt-helper
# Support live reloading with Tilt
RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/restart.sh && \

View File

@@ -64,11 +64,15 @@ To fix CVEs and keep pace with Golang, Velero made changes as follows:
### Limitations/Known issues
* The backup's VolumeInfo metadata doesn't have the information updated in the async operations. This function could be supported in v1.14 release.
### Note
* Velero introduces the informer cache which is enabled by default. The informer cache improves the restore performance but may cause higher memory consumption. Increase the memory limit of the Velero pod or disable the informer cache by specifying the `--disable-informer-cache` option when installing Velero if you get the OOM error.
### Deprecation announcement
* The generated k8s clients, informers, and listers are deprecated in the Velero v1.13 release. They are put in the Velero repository's pkg/generated directory. According to the n+2 supporting policy, the deprecated are kept for two more releases. The pkg/generated directory should be deleted in the v1.15 release.
* After the backup VolumeInfo metadata file is added to the backup, Velero decides how to restore the PV resource according to the VolumeInfo content. To support the backup generated by the older version of Velero, the old logic is also kept. The support for the backup without the VolumeInfo metadata file will be kept for two releases. The support logic will be deleted in the v1.15 release.
### All Changes
* Check resource Group Version and Kind is available in cluster before attempting restore to prevent being stuck (#7336, @kaovilai)
* Make "disable-informer-cache" option false(enabled) by default to keep it consistent with the help message (#7294, @ywk253100)
* Fix issue #6928, remove snapshot deletion timeout for PVB (#7282, @Lyndon-Li)
* Do not set "targetNamespace" to namespace items (#7274, @reasonerjt)

2
go.mod
View File

@@ -2,7 +2,7 @@ module github.com/vmware-tanzu/velero
go 1.21
toolchain go1.21.3
toolchain go1.21.6
require (
cloud.google.com/go/storage v1.33.0

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM --platform=linux/amd64 golang:1.21-bookworm
FROM --platform=linux/amd64 golang:1.21.6-bookworm
ARG GOPROXY

View File

@@ -35,8 +35,8 @@ type DynamicFactory interface {
// ClientForGroupVersionResource returns a Dynamic client for the given group/version
// and resource for the given namespace.
ClientForGroupVersionResource(gv schema.GroupVersion, resource metav1.APIResource, namespace string) (Dynamic, error)
// DynamicSharedInformerFactoryForNamespace returns a DynamicSharedInformerFactory for the given namespace.
DynamicSharedInformerFactoryForNamespace(namespace string) dynamicinformer.DynamicSharedInformerFactory
// DynamicSharedInformerFactory returns a DynamicSharedInformerFactory.
DynamicSharedInformerFactory() dynamicinformer.DynamicSharedInformerFactory
}
// dynamicFactory implements DynamicFactory.
@@ -55,8 +55,8 @@ func (f *dynamicFactory) ClientForGroupVersionResource(gv schema.GroupVersion, r
}, nil
}
func (f *dynamicFactory) DynamicSharedInformerFactoryForNamespace(namespace string) dynamicinformer.DynamicSharedInformerFactory {
return dynamicinformer.NewFilteredDynamicSharedInformerFactory(f.dynamicClient, time.Minute, namespace, nil)
func (f *dynamicFactory) DynamicSharedInformerFactory() dynamicinformer.DynamicSharedInformerFactory {
return dynamicinformer.NewDynamicSharedInformerFactory(f.dynamicClient, time.Minute)
}
// Creator creates an object.

View File

@@ -45,7 +45,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/informers"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/cache"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -309,8 +308,6 @@ func (kr *kubernetesRestorer) RestoreWithResolvers(
resourceTerminatingTimeout: kr.resourceTerminatingTimeout,
resourceTimeout: kr.resourceTimeout,
resourceClients: make(map[resourceClientKey]client.Dynamic),
dynamicInformerFactories: make(map[string]*informerFactoryWithContext),
resourceInformers: make(map[resourceClientKey]informers.GenericInformer),
restoredItems: req.RestoredItems,
renamedPVs: make(map[string]string),
pvRenamer: kr.pvRenamer,
@@ -362,8 +359,7 @@ type restoreContext struct {
resourceTerminatingTimeout time.Duration
resourceTimeout time.Duration
resourceClients map[resourceClientKey]client.Dynamic
dynamicInformerFactories map[string]*informerFactoryWithContext
resourceInformers map[resourceClientKey]informers.GenericInformer
dynamicInformerFactory *informerFactoryWithContext
restoredItems map[itemKey]restoredItemStatus
renamedPVs map[string]string
pvRenamer func(string) (string, error)
@@ -447,11 +443,16 @@ func (ctx *restoreContext) execute() (results.Result, results.Result) {
// Need to stop all informers if enabled
if !ctx.disableInformerCache {
context, cancel := signal.NotifyContext(go_context.Background(), os.Interrupt)
ctx.dynamicInformerFactory = &informerFactoryWithContext{
factory: ctx.dynamicFactory.DynamicSharedInformerFactory(),
context: context,
cancel: cancel,
}
defer func() {
// Call the cancel func to close the channel for each started informer
for _, factory := range ctx.dynamicInformerFactories {
factory.cancel()
}
ctx.dynamicInformerFactory.cancel()
// After upgrading to client-go 0.27 or newer, also call Shutdown for each informer factory
}()
}
@@ -579,28 +580,29 @@ func (ctx *restoreContext) execute() (results.Result, results.Result) {
// initialize informer caches for selected resources if enabled
if !ctx.disableInformerCache {
// CRD informer will have already been initialized if any CRDs were created,
// but already-initialized informers aren't re-initialized because getGenericInformer
// looks for an existing one first.
factoriesToStart := make(map[string]*informerFactoryWithContext)
for _, informerResource := range selectedResourceCollection {
gr := schema.ParseGroupResource(informerResource.resource)
if informerResource.totalItems == 0 {
continue
}
version := ""
for _, items := range informerResource.selectedItemsByNamespace {
// don't use ns key since it represents original ns, not mapped ns
if len(items) == 0 {
continue
}
// use the first item in the list to initialize the informer. The rest of the list
// should share the same gvr and namespace
_, factory := ctx.getGenericInformerInternal(gr, items[0].version, items[0].targetNamespace)
if factory != nil {
factoriesToStart[items[0].targetNamespace] = factory
}
version = items[0].version
break
}
gvr := schema.ParseGroupResource(informerResource.resource).WithVersion(version)
_, _, err := ctx.discoveryHelper.ResourceFor(gvr)
if err != nil {
ctx.log.Infof("failed to create informer for %s: %v", gvr, err)
continue
}
ctx.dynamicInformerFactory.factory.ForResource(gvr)
}
for _, factoryWithContext := range factoriesToStart {
factoryWithContext.factory.WaitForCacheSync(factoryWithContext.context.Done())
}
ctx.dynamicInformerFactory.factory.Start(ctx.dynamicInformerFactory.context.Done())
ctx.log.Info("waiting informer cache sync ...")
ctx.dynamicInformerFactory.factory.WaitForCacheSync(ctx.dynamicInformerFactory.context.Done())
}
// reset processedItems and totalItems before processing full resource list
@@ -1061,47 +1063,23 @@ func (ctx *restoreContext) getResourceClient(groupResource schema.GroupResource,
return client, nil
}
// if new informer is created, non-nil factory is returned
func (ctx *restoreContext) getGenericInformerInternal(groupResource schema.GroupResource, version, namespace string) (informers.GenericInformer, *informerFactoryWithContext) {
var returnFactory *informerFactoryWithContext
func (ctx *restoreContext) getResourceLister(groupResource schema.GroupResource, obj *unstructured.Unstructured, namespace string) (cache.GenericNamespaceLister, error) {
_, _, err := ctx.discoveryHelper.KindFor(obj.GroupVersionKind())
if err != nil {
return nil, err
}
informer := ctx.dynamicInformerFactory.factory.ForResource(groupResource.WithVersion(obj.GroupVersionKind().Version))
// if the restore contains CRDs or the RIA returns new resources, need to make sure the corresponding informers are synced
if !informer.Informer().HasSynced() {
ctx.dynamicInformerFactory.factory.Start(ctx.dynamicInformerFactory.context.Done())
ctx.log.Infof("waiting informer cache sync for %s, %s/%s ...", groupResource, namespace, obj.GetName())
ctx.dynamicInformerFactory.factory.WaitForCacheSync(ctx.dynamicInformerFactory.context.Done())
}
key := getResourceClientKey(groupResource, version, namespace)
factoryWithContext, ok := ctx.dynamicInformerFactories[key.namespace]
if !ok {
factory := ctx.dynamicFactory.DynamicSharedInformerFactoryForNamespace(namespace)
informerContext, informerCancel := signal.NotifyContext(go_context.Background(), os.Interrupt)
factoryWithContext = &informerFactoryWithContext{
factory: factory,
context: informerContext,
cancel: informerCancel,
}
ctx.dynamicInformerFactories[key.namespace] = factoryWithContext
}
informer, ok := ctx.resourceInformers[key]
if !ok {
ctx.log.Infof("[debug] Creating factory for %s in namespace %s", key.resource, key.namespace)
informer = factoryWithContext.factory.ForResource(key.resource)
factoryWithContext.factory.Start(factoryWithContext.context.Done())
ctx.resourceInformers[key] = informer
returnFactory = factoryWithContext
}
return informer, returnFactory
}
func (ctx *restoreContext) getGenericInformer(groupResource schema.GroupResource, version, namespace string) informers.GenericInformer {
informer, factoryWithContext := ctx.getGenericInformerInternal(groupResource, version, namespace)
if factoryWithContext != nil {
factoryWithContext.factory.WaitForCacheSync(factoryWithContext.context.Done())
}
return informer
}
func (ctx *restoreContext) getResourceLister(groupResource schema.GroupResource, obj *unstructured.Unstructured, namespace string) cache.GenericNamespaceLister {
informer := ctx.getGenericInformer(groupResource, obj.GroupVersionKind().Version, namespace)
if namespace == "" {
return informer.Lister()
} else {
return informer.Lister().ByNamespace(namespace)
return informer.Lister(), nil
}
return informer.Lister().ByNamespace(namespace), nil
}
func getResourceID(groupResource schema.GroupResource, namespace, name string) string {
@@ -1113,7 +1091,10 @@ func getResourceID(groupResource schema.GroupResource, namespace, name string) s
}
func (ctx *restoreContext) getResource(groupResource schema.GroupResource, obj *unstructured.Unstructured, namespace, name string) (*unstructured.Unstructured, error) {
lister := ctx.getResourceLister(groupResource, obj, namespace)
lister, err := ctx.getResourceLister(groupResource, obj, namespace)
if err != nil {
return nil, errors.Wrapf(err, "Error getting lister for %s", getResourceID(groupResource, namespace, name))
}
clusterObj, err := lister.Get(name)
if err != nil {
return nil, errors.Wrapf(err, "error getting resource from lister for %s, %s/%s", groupResource, namespace, name)
@@ -1123,6 +1104,7 @@ func (ctx *restoreContext) getResource(groupResource schema.GroupResource, obj *
ctx.log.WithError(errors.WithStack(fmt.Errorf("expected *unstructured.Unstructured but got %T", u))).Error("unable to understand entry returned from client")
return nil, fmt.Errorf("expected *unstructured.Unstructured but got %T", u)
}
ctx.log.Debugf("get %s, %s/%s from informer cache", groupResource, namespace, name)
return u, nil
}

View File

@@ -19,9 +19,6 @@ package test
import (
"strings"
"golang.org/x/text/cases"
"golang.org/x/text/language"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
discoveryfake "k8s.io/client-go/discovery/fake"
@@ -76,7 +73,7 @@ func (c *DiscoveryClient) WithAPIResource(resource *APIResource) *DiscoveryClien
Namespaced: resource.Namespaced,
Group: resource.Group,
Version: resource.Version,
Kind: cases.Title(language.Und).String(strings.TrimSuffix(resource.Name, "s")),
Kind: resource.Kind,
Verbs: metav1.Verbs([]string{"list", "create", "get", "delete"}),
ShortNames: []string{resource.ShortName},
})

View File

@@ -38,8 +38,8 @@ func (df *FakeDynamicFactory) ClientForGroupVersionResource(gv schema.GroupVersi
return args.Get(0).(client.Dynamic), args.Error(1)
}
func (df *FakeDynamicFactory) DynamicSharedInformerFactoryForNamespace(namespace string) dynamicinformer.DynamicSharedInformerFactory {
args := df.Called(namespace)
func (df *FakeDynamicFactory) DynamicSharedInformerFactory() dynamicinformer.DynamicSharedInformerFactory {
args := df.Called()
return args.Get(0).(dynamicinformer.DynamicSharedInformerFactory)
}

View File

@@ -27,6 +27,7 @@ type APIResource struct {
Group string
Version string
Name string
Kind string
ShortName string
Namespaced bool
Items []metav1.Object
@@ -50,6 +51,7 @@ func Pods(items ...metav1.Object) *APIResource {
ShortName: "po",
Namespaced: true,
Items: items,
Kind: "Pod",
}
}
@@ -59,6 +61,7 @@ func PVCs(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "persistentvolumeclaims",
ShortName: "pvc",
Kind: "PersistentVolumeClaim",
Namespaced: true,
Items: items,
}
@@ -70,6 +73,7 @@ func PVs(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "persistentvolumes",
ShortName: "pv",
Kind: "PersistentVolume",
Namespaced: false,
Items: items,
}
@@ -81,6 +85,7 @@ func Secrets(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "secrets",
ShortName: "secrets",
Kind: "Secret",
Namespaced: true,
Items: items,
}
@@ -92,6 +97,7 @@ func Deployments(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "deployments",
ShortName: "deploy",
Kind: "Deployment",
Namespaced: true,
Items: items,
}
@@ -103,6 +109,7 @@ func ExtensionsDeployments(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "deployments",
ShortName: "deploy",
Kind: "Deployment",
Namespaced: true,
Items: items,
}
@@ -115,6 +122,7 @@ func VeleroDeployments(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "deployments",
ShortName: "deploy",
Kind: "Deployment",
Namespaced: true,
Items: items,
}
@@ -126,6 +134,7 @@ func Namespaces(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "namespaces",
ShortName: "ns",
Kind: "Namespace",
Namespaced: false,
Items: items,
}
@@ -137,6 +146,7 @@ func ServiceAccounts(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "serviceaccounts",
ShortName: "sa",
Kind: "ServiceAccount",
Namespaced: true,
Items: items,
}
@@ -148,6 +158,7 @@ func ConfigMaps(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "configmaps",
ShortName: "cm",
Kind: "ConfigMap",
Namespaced: true,
Items: items,
}
@@ -159,6 +170,7 @@ func CRDs(items ...metav1.Object) *APIResource {
Version: "v1beta1",
Name: "customresourcedefinitions",
ShortName: "crd",
Kind: "CustomResourceDefinition",
Namespaced: false,
Items: items,
}
@@ -169,6 +181,7 @@ func VSLs(items ...metav1.Object) *APIResource {
Group: "velero.io",
Version: "v1",
Name: "volumesnapshotlocations",
Kind: "VolumeSnapshotLocation",
Namespaced: true,
Items: items,
}
@@ -179,6 +192,7 @@ func Backups(items ...metav1.Object) *APIResource {
Group: "velero.io",
Version: "v1",
Name: "backups",
Kind: "Backup",
Namespaced: true,
Items: items,
}
@@ -190,6 +204,7 @@ func Services(items ...metav1.Object) *APIResource {
Version: "v1",
Name: "services",
ShortName: "svc",
Kind: "Service",
Namespaced: true,
Items: items,
}
@@ -200,6 +215,7 @@ func DataUploads(items ...metav1.Object) *APIResource {
Group: "velero.io",
Version: "v2alpha1",
Name: "datauploads",
Kind: "DataUpload",
Namespaced: true,
Items: items,
}

View File

@@ -81,11 +81,16 @@ These instructions start the Velero server and a Minio instance that is accessib
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000
```
This example assumes that it is running within a local cluster without a volume provider capable of snapshots, so no `VolumeSnapshotLocation` is created (`--use-volume-snapshots=false`). You may need to update AWS plugin version to one that is [compatible](https://github.com/vmware-tanzu/velero-plugin-for-aws#compatibility) with the version of Velero you are installing.
* This example assumes that it is running within a local cluster without a volume provider capable of snapshots, so no `VolumeSnapshotLocation` is created (`--use-volume-snapshots=false`). You may need to update AWS plugin version to one that is [compatible](https://github.com/vmware-tanzu/velero-plugin-for-aws#compatibility) with the version of Velero you are installing.
Additionally, you can specify `--use-node-agent` to enable File System Backup support, and `--wait` to wait for the deployment to be ready.
* Additionally, you can specify `--use-node-agent` to enable File System Backup support, and `--wait` to wait for the deployment to be ready.
This example also assumes you have named your Minio bucket "velero".
* This example also assumes you have named your Minio bucket "velero".
* Please make sure to set parameter `s3ForcePathStyle=true`. The parameter is used to set the Velero integrated AWS SDK data query address style. There are two types of the address: [virtual-host and path-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html). If the `s3ForcePathStyle=true` is not set, the default value is false, then the AWS SDK will query in virtual-host style, but the MinIO server only support path-style address by default. The miss match will mean Velero can upload data to MinIO, but **cannot download from MinIO**. This [link](https://github.com/vmware-tanzu/velero/issues/7268) is an example of this issue.
It can be resolved by two ways:
* Set `s3ForcePathStyle=true` for parameter `--backup-location-config` when installing Velero. This is the preferred way.
* Make MinIO server support virtual-host style address. Add the [MINIO_DOMAIN environment variable](https://min.io/docs/minio/linux/reference/minio-server/settings/core.html#id5) for MinIO server will do the magic.
1. Deploy the example nginx application:

View File

@@ -81,11 +81,16 @@ These instructions start the Velero server and a Minio instance that is accessib
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000
```
This example assumes that it is running within a local cluster without a volume provider capable of snapshots, so no `VolumeSnapshotLocation` is created (`--use-volume-snapshots=false`). You may need to update AWS plugin version to one that is [compatible](https://github.com/vmware-tanzu/velero-plugin-for-aws#compatibility) with the version of Velero you are installing.
* This example assumes that it is running within a local cluster without a volume provider capable of snapshots, so no `VolumeSnapshotLocation` is created (`--use-volume-snapshots=false`). You may need to update AWS plugin version to one that is [compatible](https://github.com/vmware-tanzu/velero-plugin-for-aws#compatibility) with the version of Velero you are installing.
Additionally, you can specify `--use-node-agent` to enable File System Backup support, and `--wait` to wait for the deployment to be ready.
* Additionally, you can specify `--use-node-agent` to enable File System Backup support, and `--wait` to wait for the deployment to be ready.
This example also assumes you have named your Minio bucket "velero".
* This example also assumes you have named your Minio bucket "velero".
* Please make sure to set parameter `s3ForcePathStyle=true`. The parameter is used to set the Velero integrated AWS SDK data query address style. There are two types of the address: [virtual-host and path-style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html). If the `s3ForcePathStyle=true` is not set, the default value is false, then the AWS SDK will query in virtual-host style, but the MinIO server only support path-style address by default. The miss match will mean Velero can upload data to MinIO, but **cannot download from MinIO**. This [link](https://github.com/vmware-tanzu/velero/issues/7268) is an example of this issue.
It can be resolved by two ways:
* Set `s3ForcePathStyle=true` for parameter `--backup-location-config` when installing Velero. This is the preferred way.
* Make MinIO server support virtual-host style address. Add the [MINIO_DOMAIN environment variable](https://min.io/docs/minio/linux/reference/minio-server/settings/core.html#id5) for MinIO server will do the magic.
1. Deploy the example nginx application: