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 9, 2020
1 parent de12484 commit 68d0006
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 concurrency-utilization option for `service create` and `service update` (`--concurrency-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.
--concurrency-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.
--concurrency-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 != "" {
concurrencyUtilization := clientserving.ConcurrencyTargetUtilization(&revision.ObjectMeta)
if target != nil || limit != nil && *limit != 0 || autoscaleWindow != "" || concurrencyUtilization != 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 concurrencyUtilization != nil {
section.WriteAttribute("TargetUtilization", strconv.Itoa(*concurrencyUtilization))
}
}

}
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
ConcurrencyUtilization 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.ConcurrencyUtilization, "concurrency-utilization", 70,
"Percentage of concurrent requests utilization before scaling up.")
p.markFlagMakesRevision("concurrency-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("concurrency-utilization") {
err = servinglib.UpdateConcurrencyUtilization(template, p.ConcurrencyUtilization)
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 @@ -377,6 +377,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",
"--concurrency-utilization", "50",
"--no-wait"}, false)

if err != nil {
Expand All @@ -392,6 +393,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 @@ -319,7 +319,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", "--concurrency-utilization", "50", "--no-wait"})

if err != nil {
t.Fatal(err)
Expand All @@ -337,6 +337,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))
}

// UpdateConcurrencyUtilization updates container target utilization percentage annotation
func UpdateConcurrencyUtilization(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(r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300")
serviceCreateWithOptions(r, "svc1", "--concurrency-limit", "250", "--concurrency-target", "300", "--concurrency-utilization", "50")
validateServiceConcurrencyTarget(r, "svc1", "300")
validateServiceConcurrencyLimit(r, "svc1", "250")
validateServiceConcurrencyUtilization(r, "svc1", "50")

t.Log("update and validate service with concurrency limit")
serviceUpdate(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(r, "svc1", "300")
validateServiceConcurrencyTarget(r, "svc1", "300")
validateServiceConcurrencyUtilization(r, "svc1", "50")

t.Log("delete service")
serviceDelete(r, "svc1")
Expand Down Expand Up @@ -135,6 +137,13 @@ func validateServiceConcurrencyTarget(r *test.KnRunResultCollector, serviceName,
r.AssertNoError(out)
}

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

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

0 comments on commit 68d0006

Please sign in to comment.