Feat: add pre-dispatch dryrun check (#5277)

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Somefive
2023-01-06 10:46:50 +08:00
committed by GitHub
parent 78f5827fa6
commit 693eb3cb1d
7 changed files with 30 additions and 15 deletions
+2 -1
View File
@@ -99,6 +99,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
| `featureGates.multiStageComponentApply` | if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply. | `false` |
| `featureGates.gzipApplicationRevision` | compress apprev using gzip (good) before being stored. This is reduces network throughput when dealing with huge apprevs. | `false` |
| `featureGates.zstdApplicationRevision` | compress apprev using zstd (fast and good) before being stored. This is reduces network throughput when dealing with huge apprevs. Note that zstd will be prioritized if you enable other compression options. | `true` |
| `featureGates.preDispatchDryRun` | enable dryrun before dispatching resources. Enable this flag can help prevent unsuccessful dispatch resources entering resourcetracker and improve the user experiences of gc but at the cost of increasing network requests. | `true` |
### MultiCluster parameters
@@ -110,7 +111,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.4.0` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.7.0-alpha.3` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
@@ -274,6 +274,7 @@ spec:
- "--feature-gates=MultiStageComponentApply= {{- .Values.featureGates.multiStageComponentApply | toString -}}"
- "--feature-gates=GzipApplicationRevision={{- .Values.featureGates.gzipResourceTracker | toString -}}"
- "--feature-gates=ZstdApplicationRevision={{- .Values.featureGates.zstdResourceTracker | toString -}}"
- "--feature-gates=PreDispatchDryRun={{- .Values.featureGates.preDispatchDryRun | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}
- "--authentication-with-user"
+3 -1
View File
@@ -113,6 +113,7 @@ optimize:
##@param featureGates.multiStageComponentApply if enabled, the multiStageComponentApply feature will be combined with the stage field in TraitDefinition to complete the multi-stage apply.
##@param featureGates.gzipApplicationRevision compress apprev using gzip (good) before being stored. This is reduces network throughput when dealing with huge apprevs.
##@param featureGates.zstdApplicationRevision compress apprev using zstd (fast and good) before being stored. This is reduces network throughput when dealing with huge apprevs. Note that zstd will be prioritized if you enable other compression options.
##@param featureGates.preDispatchDryRun enable dryrun before dispatching resources. Enable this flag can help prevent unsuccessful dispatch resources entering resourcetracker and improve the user experiences of gc but at the cost of increasing network requests.
##@param
featureGates:
enableLegacyComponentRevision: false
@@ -122,6 +123,7 @@ featureGates:
multiStageComponentApply: false
gzipApplicationRevision: false
zstdApplicationRevision: true
preDispatchDryRun: true
## @section MultiCluster parameters
@@ -146,7 +148,7 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.4.0
tag: v1.7.0-alpha.3
pullPolicy: IfNotPresent
resources:
limits:
@@ -94,17 +94,9 @@ var _ = Describe("Test application controller finalizer logic", func() {
By("Verify latest app revision is also recorded in status")
Expect(checkApp.Status.LatestRevision).ShouldNot(BeNil())
By("Verify ResourceTracker is created")
rt := &v1beta1.ResourceTracker{}
Expect(k8sClient.Get(ctx, getTrackerKey(checkApp.Namespace, checkApp.Name, "v1"), rt)).Should(Succeed())
By("Delete Application")
Expect(k8sClient.Delete(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
By("Verify ResourceTracker is deleted")
rt = &v1beta1.ResourceTracker{}
Expect(k8sClient.Get(ctx, getTrackerKey(checkApp.Namespace, checkApp.Name, "v1"), rt)).Should(util.NotFoundMatcher{})
})
It("Test cross namespace workload, then delete the app", func() {
+6
View File
@@ -84,6 +84,11 @@ const (
// MultiStageComponentApply enable multi-stage feature for component
// If enabled, the dispatch of manifests is performed in batches according to the stage
MultiStageComponentApply featuregate.Feature = "MultiStageComponentApply"
// PreDispatchDryRun enable dryrun before dispatching resources
// Enable this flag can help prevent unsuccessful dispatch resources entering resourcetracker and improve the
// user experiences of gc but at the cost of increasing network requests.
PreDispatchDryRun featuregate.Feature = "PreDispatchDryRun"
)
var defaultFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
@@ -102,6 +107,7 @@ var defaultFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
MultiStageComponentApply: {Default: false, PreRelease: featuregate.Alpha},
GzipApplicationRevision: {Default: false, PreRelease: featuregate.Alpha},
ZstdApplicationRevision: {Default: false, PreRelease: featuregate.Alpha},
PreDispatchDryRun: {Default: true, PreRelease: featuregate.Alpha},
}
func init() {
+15 -5
View File
@@ -18,7 +18,9 @@ package resourcekeeper
import (
"context"
"fmt"
velaslices "github.com/kubevela/pkg/util/slices"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -67,15 +69,23 @@ func (h *resourceKeeper) Dispatch(ctx context.Context, manifests []*unstructured
if err = h.AdmissionCheck(ctx, manifests); err != nil {
return err
}
// 1. record manifests in resourcetracker
if err = h.record(ctx, manifests, options...); err != nil {
return err
}
// 2. apply manifests
// 1. pre-dispatch check
opts := []apply.ApplyOption{apply.MustBeControlledByApp(h.app), apply.NotUpdateRenderHashEqual()}
if len(applyOpts) > 0 {
opts = append(opts, applyOpts...)
}
if utilfeature.DefaultMutableFeatureGate.Enabled(features.PreDispatchDryRun) {
if err = h.dispatch(ctx,
velaslices.Map(manifests, func(manifest *unstructured.Unstructured) *unstructured.Unstructured { return manifest.DeepCopy() }),
append([]apply.ApplyOption{apply.DryRunAll()}, opts...)); err != nil {
return fmt.Errorf("pre-dispatch dryrun failed: %w", err)
}
}
// 2. record manifests in resourcetracker
if err = h.record(ctx, manifests, options...); err != nil {
return err
}
// 3. apply manifests
if err = h.dispatch(ctx, manifests, opts); err != nil {
return err
}
@@ -528,6 +528,9 @@ var _ = Describe("Test multicluster scenario", func() {
g.Expect(app.Status.Phase).Should(Equal(common.ApplicationRunningWorkflow))
g.Expect(len(app.Status.Workflow.Steps) > 0).Should(BeTrue())
g.Expect(app.Status.Workflow.Steps[0].Message).Should(ContainSubstring("is invalid"))
rts := &v1beta1.ResourceTrackerList{}
g.Expect(k8sClient.List(hubCtx, rts, client.MatchingLabels{oam.LabelAppName: app.Name, oam.LabelAppNamespace: app.Namespace})).Should(Succeed())
g.Expect(len(rts.Items)).Should(Equal(0))
}, 20*time.Second).Should(Succeed())
Expect(k8sClient.Delete(ctx, app)).Should(Succeed())
Eventually(func(g Gomega) {