Skip to content

Commit

Permalink
Add "--target-utilization" to manage "autoscaling.knative.dev/targetU…
Browse files Browse the repository at this point in the history
…tilizationPercentage" annotation

* Support setting "autoscaling.knative.dev/targetUtilizationPercentage" annotation.
  • Loading branch information
MIBc committed Apr 8, 2020
1 parent 8a60d2e commit 9b4da8e
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
|===
| | Description | PR

| 🎁
| Add target-utilization option for `service create` and `service update` (`--target-utilization`)
| https://github.com/knative/client/pull/788[#788]

| 🐣
| Refactor `e2e` common code into `lib/test`
| https://github.com/knative/client/pull/765[#765]
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ kn service create NAME --image IMAGE [flags]
--requests-memory string The requested memory (e.g., 64Mi).
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
--service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace.
--target-utilization int Percentage of concurrent requests utilization before scaling up (default 70)
--user int The user ID to run the container (e.g., 1001).
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600)
Expand Down
1 change: 1 addition & 0 deletions docs/cmd/kn_service_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ kn service update NAME [flags]
--tag strings Set tag (format: --tag revisionRef=tagName) where revisionRef can be a revision or '@latest' string representing latest ready revision. This flag can be specified multiple times.
--traffic strings Set traffic distribution (format: --traffic revisionRef=percent) where revisionRef can be a revision or a tag or '@latest' string representing latest ready revision. This flag can be given multiple times with percent summing up to 100%.
--untag strings Untag revision (format: --untag tagName). This flag can be specified multiple times.
--target-utilization int Percentage of concurrent requests utilization before scaling up (default 70)
--user int The user ID to run the container (e.g., 1001).
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600)
Expand Down
6 changes: 5 additions & 1 deletion pkg/kn/commands/revision/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ func WriteConcurrencyOptions(dw printers.PrefixWriter, revision *servingv1.Revis
target := clientserving.ConcurrencyTarget(&revision.ObjectMeta)
limit := revision.Spec.ContainerConcurrency
autoscaleWindow := clientserving.AutoscaleWindow(&revision.ObjectMeta)
if target != nil || limit != nil && *limit != 0 || autoscaleWindow != "" {
targetUtilization := clientserving.ConcurrencyTargetUtilization(&revision.ObjectMeta)
if target != nil || limit != nil && *limit != 0 || autoscaleWindow != "" || targetUtilization != nil {
section := dw.WriteAttribute("Concurrency", "")
if limit != nil && *limit != 0 {
section.WriteAttribute("Limit", strconv.FormatInt(int64(*limit), 10))
Expand All @@ -142,6 +143,9 @@ func WriteConcurrencyOptions(dw printers.PrefixWriter, revision *servingv1.Revis
if autoscaleWindow != "" {
section.WriteAttribute("Window", autoscaleWindow)
}
if targetUtilization != nil {
section.WriteAttribute("TargetUtilization", strconv.Itoa(*targetUtilization))
}
}

}
Expand Down
12 changes: 12 additions & 0 deletions pkg/kn/commands/service/configuration_edit_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type ConfigurationEditFlags struct {
MaxScale int
ConcurrencyTarget int
ConcurrencyLimit int
TargetUtilization int
AutoscaleWindow string
Port int32
Labels []string
Expand Down Expand Up @@ -180,6 +181,10 @@ func (p *ConfigurationEditFlags) addSharedFlags(command *cobra.Command) {
"Hard Limit of concurrent requests to be processed by a single replica.")
p.markFlagMakesRevision("concurrency-limit")

command.Flags().IntVar(&p.TargetUtilization, "target-utilization", 70,
"Percentage of concurrent requests utilization before scaling up")
p.markFlagMakesRevision("target-utilization")

command.Flags().Int32VarP(&p.Port, "port", "p", 0, "The port where application listens on.")
p.markFlagMakesRevision("port")

Expand Down Expand Up @@ -404,6 +409,13 @@ func (p *ConfigurationEditFlags) Apply(
}
}

if cmd.Flags().Changed("target-utilization") {
err = servinglib.UpdateTargetUtilization(template, p.TargetUtilization)
if err != nil {
return err
}
}

if cmd.Flags().Changed("cluster-local") || cmd.Flags().Changed("no-cluster-local") {
if p.ClusterLocal {
labels := servinglib.UpdateLabels(service.ObjectMeta.Labels, map[string]string{serving.VisibilityLabelKey: serving.VisibilityClusterLocal}, []string{})
Expand Down
2 changes: 2 additions & 0 deletions pkg/kn/commands/service/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ func TestServiceCreateMaxMinScale(t *testing.T) {
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz",
"--min-scale", "1", "--max-scale", "5",
"--concurrency-target", "10", "--concurrency-limit", "100",
"--target-utilization", "50",
"--no-wait"}, false)

if err != nil {
Expand All @@ -385,6 +386,7 @@ func TestServiceCreateMaxMinScale(t *testing.T) {
"autoscaling.knative.dev/minScale", "1",
"autoscaling.knative.dev/maxScale", "5",
"autoscaling.knative.dev/target", "10",
"autoscaling.knative.dev/targetUtilizationPercentage", "50",
}

for i := 0; i < len(expectedAnnos); i += 2 {
Expand Down
3 changes: 2 additions & 1 deletion pkg/kn/commands/service/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ func TestServiceUpdateMaxMinScale(t *testing.T) {

action, updated, _, err := fakeServiceUpdate(original, []string{
"service", "update", "foo",
"--min-scale", "1", "--max-scale", "5", "--concurrency-target", "10", "--concurrency-limit", "100", "--no-wait"})
"--min-scale", "1", "--max-scale", "5", "--concurrency-target", "10", "--concurrency-limit", "100", "--target-utilization", "50", "--no-wait"})

if err != nil {
t.Fatal(err)
Expand All @@ -329,6 +329,7 @@ func TestServiceUpdateMaxMinScale(t *testing.T) {
"autoscaling.knative.dev/minScale", "1",
"autoscaling.knative.dev/maxScale", "5",
"autoscaling.knative.dev/target", "10",
"autoscaling.knative.dev/targetUtilizationPercentage", "50",
}

for i := 0; i < len(expectedAnnos); i += 2 {
Expand Down
5 changes: 5 additions & 0 deletions pkg/serving/config_changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ func UpdateConcurrencyTarget(template *servingv1.RevisionTemplateSpec, target in
return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetAnnotationKey, strconv.Itoa(target))
}

// UpdateTargetUtilization updates container target utilization percentage annotation
func UpdateTargetUtilization(template *servingv1.RevisionTemplateSpec, target int) error {
return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetUtilizationPercentageKey, strconv.Itoa(target))
}

// UpdateConcurrencyLimit updates container concurrency limit
func UpdateConcurrencyLimit(template *servingv1.RevisionTemplateSpec, limit int64) error {
if limit < 0 {
Expand Down
5 changes: 5 additions & 0 deletions pkg/serving/revision_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ func ConcurrencyTarget(m *metav1.ObjectMeta) *int {
return ret
}

func ConcurrencyTargetUtilization(m *metav1.ObjectMeta) *int {
ret, _ := annotationAsInt(m, autoscaling.TargetUtilizationPercentageKey)
return ret
}

func AutoscaleWindow(m *metav1.ObjectMeta) string {
return m.Annotations[autoscaling.WindowAnnotationKey]
}
Expand Down
11 changes: 10 additions & 1 deletion test/e2e/service_options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ func TestServiceOptions(t *testing.T) {
t.Log("create and validate service with concurrency options")
defer r.DumpIfFailed()

serviceCreateWithOptions(t, it, r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300")
serviceCreateWithOptions(t, it, r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300", "--target-utilization", "50")
validateServiceConcurrencyTarget(t, it, r, "svc1", "300")
validateServiceConcurrencyLimit(t, it, r, "svc1", "250")
validateServiceTargetUtilization(t, it, r, "svc1", "50")

t.Log("update and validate service with concurrency limit")
serviceUpdate(t, it, r, "svc1", "--concurrency-limit", "300")
Expand All @@ -62,6 +63,7 @@ func TestServiceOptions(t *testing.T) {
t.Log("returns steady concurrency options for service")
validateServiceConcurrencyLimit(t, it, r, "svc1", "300")
validateServiceConcurrencyTarget(t, it, r, "svc1", "300")
validateServiceTargetUtilization(t, it, r, "svc1", "50")

t.Log("delete service")
serviceDelete(t, it, r, "svc1")
Expand Down Expand Up @@ -134,6 +136,13 @@ func validateServiceConcurrencyTarget(t *testing.T, it *test.KnTest, r *test.KnR
r.AssertNoError(out)
}

func validateServiceTargetUtilization(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, targetUtilization string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/targetUtilizationPercentage}"
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(t, out.Stdout, targetUtilization)
r.AssertNoError(out)
}

func validateAutoscaleWindow(t *testing.T, it *test.KnTest, r *test.KnRunResultCollector, serviceName, window string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/window}"
out := it.Kn().Run("service", "list", serviceName, "-o", jsonpath)
Expand Down

0 comments on commit 9b4da8e

Please sign in to comment.