diff --git a/config/core/200-roles/clusterrole.yaml b/config/core/200-roles/clusterrole.yaml
index 3fcca910ba43..e76a24f76652 100644
--- a/config/core/200-roles/clusterrole.yaml
+++ b/config/core/200-roles/clusterrole.yaml
@@ -67,3 +67,6 @@ rules:
resources: ["clusterroles"]
verbs: ["delete"]
resourceNames: ["knative-serving-certmanager"]
+ - apiGroups: ["*"]
+ resources: ["*/scale"]
+ verbs: ["patch"]
diff --git a/docs/serving-api.md b/docs/serving-api.md
index 77aad5ea6a63..1f6dd48d01da 100644
--- a/docs/serving-api.md
+++ b/docs/serving-api.md
@@ -565,18 +565,6 @@ Kubernetes meta/v1.LabelSelector
|
-
-
-template
-
-
-Kubernetes core/v1.PodTemplateSpec
-
-
- |
-
- |
-
@@ -633,18 +621,6 @@ Kubernetes meta/v1.LabelSelector
|
-
-
-template
-
-
-Kubernetes core/v1.PodTemplateSpec
-
-
- |
-
- |
-
PodScalableStatus
diff --git a/pkg/apis/autoscaling/v1alpha1/podscalable_types.go b/pkg/apis/autoscaling/v1alpha1/podscalable_types.go
index b667c7b593db..ee48f87635a8 100644
--- a/pkg/apis/autoscaling/v1alpha1/podscalable_types.go
+++ b/pkg/apis/autoscaling/v1alpha1/podscalable_types.go
@@ -17,7 +17,6 @@ limitations under the License.
package v1alpha1
import (
- corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"knative.dev/pkg/apis"
@@ -43,9 +42,8 @@ type PodScalable struct {
// PodScalableSpec is the specification for the desired state of a
// PodScalable (or at least our shared portion).
type PodScalableSpec struct {
- Replicas *int32 `json:"replicas,omitempty"`
- Selector *metav1.LabelSelector `json:"selector"`
- Template corev1.PodTemplateSpec `json:"template"`
+ Replicas *int32 `json:"replicas,omitempty"`
+ Selector *metav1.LabelSelector `json:"selector"`
}
// PodScalableStatus is the observed state of a PodScalable (or at
@@ -80,19 +78,6 @@ func (t *PodScalable) Populate() {
Values: []string{"baz", "blah"},
}},
},
- Template: corev1.PodTemplateSpec{
- ObjectMeta: metav1.ObjectMeta{
- Labels: map[string]string{
- "foo": "bar",
- },
- },
- Spec: corev1.PodSpec{
- Containers: []corev1.Container{{
- Name: "container-name",
- Image: "container-image:latest",
- }},
- },
- },
}
t.Status = PodScalableStatus{
Replicas: 42,
diff --git a/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go
index 5c328191ba80..38ba90053d18 100644
--- a/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go
@@ -299,7 +299,6 @@ func (in *PodScalableSpec) DeepCopyInto(out *PodScalableSpec) {
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
- in.Template.DeepCopyInto(&out.Template)
return
}
diff --git a/pkg/reconciler/autoscaling/kpa/kpa_test.go b/pkg/reconciler/autoscaling/kpa/kpa_test.go
index 107d232ff0c8..797af201c9aa 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa_test.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa_test.go
@@ -264,7 +264,7 @@ func TestReconcile(t *testing.T) {
minScalePatch := clientgotesting.PatchActionImpl{
ActionImpl: clientgotesting.ActionImpl{Namespace: testNamespace},
Name: deployName,
- Patch: []byte(fmt.Sprintf(`[{"op":"replace","path":"/spec/replicas","value":%d}]`, defaultScale)),
+ Patch: fmt.Appendf(nil, `[{"op":"add","path":"/spec/replicas","value":%d}]`, defaultScale),
}
inactiveKPAMinScale := func(g int32) *autoscalingv1alpha1.PodAutoscaler {
@@ -1030,7 +1030,7 @@ func TestReconcile(t *testing.T) {
WantPatches: []clientgotesting.PatchActionImpl{{
ActionImpl: clientgotesting.ActionImpl{Namespace: testNamespace},
Name: deployName,
- Patch: []byte(fmt.Sprintf(`[{"op":"replace","path":"/spec/replicas","value":%d}]`, 20)),
+ Patch: fmt.Appendf(nil, `[{"op":"add","path":"/spec/replicas","value":%d}]`, 20),
}},
}, {
Name: "initial scale reached, mark PA as active",
@@ -1058,7 +1058,7 @@ func TestReconcile(t *testing.T) {
WantPatches: []clientgotesting.PatchActionImpl{{
ActionImpl: clientgotesting.ActionImpl{Namespace: testNamespace},
Name: deployName,
- Patch: []byte(fmt.Sprintf(`[{"op":"replace","path":"/spec/replicas","value":%d}]`, 20)),
+ Patch: fmt.Appendf(nil, `[{"op":"add","path":"/spec/replicas","value":%d}]`, 20),
}},
}, {
Name: "initial scale zero: scale to zero",
diff --git a/pkg/reconciler/autoscaling/kpa/scaler.go b/pkg/reconciler/autoscaling/kpa/scaler.go
index 84dba5dc81d7..d542c73e8d9a 100644
--- a/pkg/reconciler/autoscaling/kpa/scaler.go
+++ b/pkg/reconciler/autoscaling/kpa/scaler.go
@@ -298,7 +298,10 @@ func (ks *scaler) handleScaleToZero(ctx context.Context, pa *autoscalingv1alpha1
}
}
-func (ks *scaler) applyScale(ctx context.Context, pa *autoscalingv1alpha1.PodAutoscaler, desiredScale int32,
+func (ks *scaler) applyScale(
+ ctx context.Context,
+ pa *autoscalingv1alpha1.PodAutoscaler,
+ desiredScale int32,
ps *autoscalingv1alpha1.PodScalable,
) error {
logger := logging.FromContext(ctx)
@@ -308,19 +311,15 @@ func (ks *scaler) applyScale(ctx context.Context, pa *autoscalingv1alpha1.PodAut
return err
}
- psNew := ps.DeepCopy()
- psNew.Spec.Replicas = &desiredScale
- patch, err := duck.CreatePatch(ps, psNew)
- if err != nil {
- return err
- }
- patchBytes, err := patch.MarshalJSON()
- if err != nil {
- return err
- }
+ patch := fmt.Sprintf(`[{"op":"add","path":"/spec/replicas","value":%d}]`, desiredScale)
- _, err = ks.dynamicClient.Resource(*gvr).Namespace(pa.Namespace).Patch(ctx, ps.Name, types.JSONPatchType,
- patchBytes, metav1.PatchOptions{})
+ _, err = ks.dynamicClient.Resource(*gvr).Namespace(pa.Namespace).Patch(
+ ctx,
+ ps.Name,
+ types.JSONPatchType,
+ []byte(patch),
+ metav1.PatchOptions{},
+ "scale")
if err != nil {
return fmt.Errorf("failed to apply scale %d to scale target %s: %w", desiredScale, name, err)
}
diff --git a/pkg/reconciler/autoscaling/kpa/scaler_test.go b/pkg/reconciler/autoscaling/kpa/scaler_test.go
index bf0b7f718b47..0ef2c3119643 100644
--- a/pkg/reconciler/autoscaling/kpa/scaler_test.go
+++ b/pkg/reconciler/autoscaling/kpa/scaler_test.go
@@ -785,7 +785,7 @@ func checkReplicas(t *testing.T, dynamicClient *fakedynamic.FakeDynamicClient, d
if patch.GetName() != deployment.Name {
continue
}
- want := fmt.Sprintf(`[{"op":"replace","path":"/spec/replicas","value":%d}]`, expectedScale)
+ want := fmt.Sprintf(`[{"op":"add","path":"/spec/replicas","value":%d}]`, expectedScale)
if got := string(patch.GetPatch()); got != want {
t.Errorf("Patch = %s, wanted %s", got, want)
}