Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neighbour app custom metrics #3211

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ci/autoscaler/scripts/deploy-autoscaler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ function check_ops_files(){

function deploy() {
# Try to silence Prometheus but do not fail deployment if there's an error
${script_dir}/silence_prometheus_alert.sh "BOSHJobEphemeralDiskPredictWillFill" || true
${script_dir}/silence_prometheus_alert.sh "BOSHJobProcessUnhealthy" || true
${script_dir}/silence_prometheus_alert.sh "BOSHJobUnhealthy" || true
#${script_dir}/silence_prometheus_alert.sh "BOSHJobEphemeralDiskPredictWillFill" || true
#${script_dir}/silence_prometheus_alert.sh "BOSHJobProcessUnhealthy" || true
#${script_dir}/silence_prometheus_alert.sh "BOSHJobUnhealthy" || true

create_manifest

Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions jobs/metricsforwarder/spec
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ templates:
policy_db.crt.erb: config/certs/policy_db/crt
policy_db.key.erb: config/certs/policy_db/key

binding_db_ca.crt.erb: config/certs/binding_db/ca.crt
binding_db.crt.erb: config/certs/binding_db/crt
binding_db.key.erb: config/certs/binding_db/key

storedprocedure_db_ca.crt.erb: config/certs/storedprocedure_db/ca.crt
storedprocedure_db.crt.erb: config/certs/storedprocedure_db/crt
storedprocedure_db.key.erb: config/certs/storedprocedure_db/key
Expand Down Expand Up @@ -126,6 +130,37 @@ properties:
autoscaler.policy_db_connection_config.connection_max_lifetime:
default: 60s

autoscaler.binding_db.address:
description: "IP address on which the bindingdb server will listen"
default: "autoscalerpostgres.service.cf.internal"
autoscaler.binding_db.databases:
description: "The list of databases used in bindingdb database including name"
autoscaler.binding_db.db_scheme:
description: "Database scheme to be used to access bindingdb"
default: postgres
autoscaler.binding_db.port:
description: "Port on which the bindingdb server will listen"
autoscaler.binding_db.roles:
description: "The list of database roles used in bindingdb database including name/password"
autoscaler.binding_db.tls.ca:
default: ''
description: 'PEM-encoded ca certificate for TLS database server'
autoscaler.binding_db.tls.certificate:
default: ''
description: 'PEM-encoded certificate for TLS database client'
autoscaler.binding_db.tls.private_key:
default: ''
description: 'PEM-encoded key for TLS database client'
autoscaler.binding_db.sslmode:
default: disable
description: "sslmode to connect to postgres server"
autoscaler.binding_db_connection_config.max_open_connections:
default: 20
autoscaler.binding_db_connection_config.max_idle_connections:
default: 10
autoscaler.binding_db_connection_config.connection_max_lifetime:
default: 60s

autoscaler.storedprocedure_db.address:
description: "IP address on which the storedproceduredb server will listen"
default: ""
Expand Down
3 changes: 3 additions & 0 deletions jobs/metricsforwarder/templates/binding_db.crt.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if_p("autoscaler.binding_db.tls.certificate") do |value| %>
<%= value %>
<% end %>
3 changes: 3 additions & 0 deletions jobs/metricsforwarder/templates/binding_db.key.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if_p("autoscaler.binding_db.tls.private_key") do |value| %>
<%= value %>
<% end %>
3 changes: 3 additions & 0 deletions jobs/metricsforwarder/templates/binding_db_ca.crt.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if_p("autoscaler.binding_db.tls.ca") do |value| %>
<%= value %>
<% end %>
6 changes: 6 additions & 0 deletions jobs/metricsforwarder/templates/metricsforwarder.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ end
###########################################
job_name = 'metricsforwarder'
policy_db_url = build_db_url('policy_db', job_name)
binding_db_url = build_db_url('binding_db', job_name)
if p("autoscaler.storedprocedure_db.address") != ''
storedprocedure_db_url = build_db_url('storedprocedure_db', job_name)
end
Expand Down Expand Up @@ -80,6 +81,11 @@ db:
max_open_connections: <%= p("autoscaler.policy_db_connection_config.max_open_connections") %>
max_idle_connections: <%= p("autoscaler.policy_db_connection_config.max_idle_connections") %>
connection_max_lifetime: <%= p("autoscaler.policy_db_connection_config.connection_max_lifetime") %>
binding_db:
url: <%= binding_db_url %>
max_open_connections: <%= p("autoscaler.binding_db_connection_config.max_open_connections") %>
max_idle_connections: <%= p("autoscaler.binding_db_connection_config.max_idle_connections") %>
connection_max_lifetime: <%= p("autoscaler.binding_db_connection_config.connection_max_lifetime") %>
<% if p("autoscaler.storedprocedure_db.address") != '' %>
storedprocedure_db:
url: <%= storedprocedure_db_url %>
Expand Down
24 changes: 24 additions & 0 deletions new-test-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"configuration": {
"custom_metrics": {
"auth": {
"credential_type": ""
},
"metric_submission_strategy": {
"allow_from": "bound_app"
}
}
},
"instance_min_count": 1,
"instance_max_count": 2,
"scaling_rules": [
{
"metric_type": "test_metric",
"breach_duration_secs": 60,
"threshold": 500,
"operator": ">=",
"cool_down_secs": 60,
"adjustment": "+1"
}
]
}
2 changes: 1 addition & 1 deletion scripts/generate_test_certs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ if [[ "$OPENSSL_VERSION" == LibreSSL* ]]; then
echo "OpenSSL needs to be used rather than LibreSSL"
exit 1
fi
# valid certificate
# valid client certificates
echo "${depot_path}"
openssl req -new -newkey rsa:2048 -nodes -subj "/CN=sap.com/O=SAP SE/OU=organization:AB1234ORG/OU=app:an-app-id/OU=space:AB1234SPACE" -out "${depot_path}"/validmtls_client-1.csr
openssl x509 -req -in "${depot_path}"/validmtls_client-1.csr -CA "${depot_path}"/valid-mtls-local-ca-1.crt -CAkey "${depot_path}"/valid-mtls-local-ca-1.key -CAcreateserial -out "${depot_path}"/validmtls_client-1.crt -days 365 -sha256
Expand Down
15 changes: 15 additions & 0 deletions spec/fixtures/metricsforwarder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ autoscaler:
ca: BEGIN---CA---END
certificate: BEGIN---CERT---END
private_key: BEGIN---KEY---END
binding_db:
address: 10.11.137.101
databases:
- name: foo
tag: default
db_scheme: postgres
port: 5432
roles:
- name: foo
password: default
tag: default
tls:
ca: BEGIN---CA---END
certificate: BEGIN---CERT---END
private_key: BEGIN---KEY---END
cf:
api: https://api.cf.domain
auth_endpoint: https://login.cf.domain
Expand Down
14 changes: 14 additions & 0 deletions spec/jobs/metricsforwarder/metricsforwarder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@
end
end
end
context "binding_db" do
it "includes the ca, cert and key in url when configured" do
rendered_template["db"]["binding_db"]["url"].tap do |url|
check_if_certs_in_url(url, "binding_db")
end
end

it "does not include the ca, cert and key in url when not configured" do
properties["autoscaler"]["binding_db"]["tls"] = nil
rendered_template["db"]["binding_db"]["url"].tap do |url|
check_if_certs_not_in_url(url, "binding_db")
end
end
end
end
end
end
16 changes: 10 additions & 6 deletions src/acceptance/app/app_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ var (
instanceName string
initialInstanceCount int

appName string
appGUID string
appToScaleName string
appToScaleGUID string

neighbourAppName string

neighbourAppGUID string
)

const componentName = "Application Scale Suite"
Expand Down Expand Up @@ -59,10 +63,10 @@ func AppAfterEach() {
if os.Getenv("SKIP_TEARDOWN") == "true" {
fmt.Println("Skipping Teardown...")
} else {
DebugInfo(cfg, setup, appName)
if appName != "" {
DeleteService(cfg, instanceName, appName)
DeleteTestApp(appName, cfg.DefaultTimeoutDuration())
DebugInfo(cfg, setup, appToScaleName)
if appToScaleName != "" {
DeleteService(cfg, instanceName, appToScaleName)
DeleteTestApp(appToScaleName, cfg.DefaultTimeoutDuration())
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/acceptance/app/cf_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ var _ = Describe("AutoScaler CF metadata support", func() {
)
BeforeEach(func() {
policy = GenerateDynamicScaleOutAndInPolicy(1, 2, "test_metric", 500, 500)
appName = CreateTestApp(cfg, "labeled-go_app", 1)
appGUID, err = GetAppGuid(cfg, appName)
appToScaleName = CreateTestApp(cfg, "labeled-go_app", 1)
appToScaleGUID, err = GetAppGuid(cfg, appToScaleName)
Expect(err).NotTo(HaveOccurred())
instanceName = CreatePolicy(cfg, appName, appGUID, policy)
StartApp(appName, cfg.CfPushTimeoutDuration())
instanceName = CreatePolicy(cfg, appToScaleName, appToScaleGUID, policy)
StartApp(appToScaleName, cfg.CfPushTimeoutDuration())
})
AfterEach(AppAfterEach)

When("the label app-autoscaler.cloudfoundry.org/disable-autoscaling is set", func() {
It("should not scale out", func() {
By("Set the label app-autoscaler.cloudfoundry.org/disable-autoscaling to true")
SetLabel(cfg, appGUID, "app-autoscaler.cloudfoundry.org/disable-autoscaling", "true")
scaleOut := sendMetricToAutoscaler(cfg, appGUID, appName, 550, true)
SetLabel(cfg, appToScaleGUID, "app-autoscaler.cloudfoundry.org/disable-autoscaling", "true")
scaleOut := sendMetricToAutoscaler(cfg, appToScaleGUID, appToScaleName, 550, true)
Consistently(scaleOut).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Expand Down
91 changes: 79 additions & 12 deletions src/acceptance/app/custom_metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"acceptance"
"acceptance/config"
. "acceptance/helpers"
"fmt"
"time"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -17,11 +18,11 @@ var _ = Describe("AutoScaler custom metrics policy", func() {
)
BeforeEach(func() {
policy = GenerateDynamicScaleOutAndInPolicy(1, 2, "test_metric", 500, 500)
appName = CreateTestApp(cfg, "node-custom-metric", 1)
appGUID, err = GetAppGuid(cfg, appName)
appToScaleName = CreateTestApp(cfg, "node-custom-metric", 1)
appToScaleGUID, err = GetAppGuid(cfg, appToScaleName)
Expect(err).NotTo(HaveOccurred())
instanceName = CreatePolicy(cfg, appName, appGUID, policy)
StartApp(appName, cfg.CfPushTimeoutDuration())
instanceName = CreatePolicy(cfg, appToScaleName, appToScaleGUID, policy)
StartApp(appToScaleName, cfg.CfPushTimeoutDuration())
})
AfterEach(AppAfterEach)

Expand All @@ -30,14 +31,14 @@ var _ = Describe("AutoScaler custom metrics policy", func() {
Context("when scaling by custom metrics", func() {
It("should scale out and scale in", Label(acceptance.LabelSmokeTests), func() {
By("Scale out to 2 instances")
scaleOut := sendMetricToAutoscaler(cfg, appGUID, appName, 550, false)
scaleOut := sendMetricToAutoscaler(cfg, appToScaleGUID, appToScaleName, 550, false)
Eventually(scaleOut).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(2))

By("Scale in to 1 instances")
scaleIn := sendMetricToAutoscaler(cfg, appGUID, appName, 100, false)
scaleIn := sendMetricToAutoscaler(cfg, appToScaleGUID, appToScaleName, 100, false)
Eventually(scaleIn).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Expand All @@ -49,30 +50,96 @@ var _ = Describe("AutoScaler custom metrics policy", func() {
Context("when scaling by custom metrics via mtls", func() {
It("should scale out and scale in", Label(acceptance.LabelSmokeTests), func() {
By("Scale out to 2 instances")
scaleOut := sendMetricToAutoscaler(cfg, appGUID, appName, 550, true)
scaleOut := sendMetricToAutoscaler(cfg, appToScaleGUID, appToScaleName, 550, true)
Eventually(scaleOut).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(2))

By("Scale in to 1 instance")
scaleIn := sendMetricToAutoscaler(cfg, appGUID, appName, 100, true)
scaleIn := sendMetricToAutoscaler(cfg, appToScaleGUID, appToScaleName, 100, true)
Eventually(scaleIn).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(1))

})
})
Describe("Custom metrics policy with neighbour app", func() {
JustBeforeEach(func() {
neighbourAppName = CreateTestApp(cfg, "go-neighbour-app", 1)
neighbourAppGUID, err = GetAppGuid(cfg, neighbourAppName)
Expect(err).NotTo(HaveOccurred())
err := BindServiceToAppWithPolicy(cfg, neighbourAppName, instanceName, policy)
Expect(err).NotTo(HaveOccurred())
StartApp(neighbourAppName, cfg.CfPushTimeoutDuration())
})
Context("neighbour app send custom metrics for app B via mtls", func() {
BeforeEach(func() {
policy = GenerateBindingsWithScalingPolicy("bound_app", 1, 2, "test_metric", 500, 100)
})
It("should scale out and scale in app B", Label(acceptance.LabelSmokeTests), func() {
By(fmt.Sprintf("Scale out %s to 2 instance", appToScaleName))
scaleOut := sendMetricToAutoscaler(cfg, appToScaleGUID, neighbourAppName, 550, true)
Eventually(scaleOut).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(2))

By(fmt.Sprintf("Scale in %s to 1 instance", appToScaleName))
scaleIn := sendMetricToAutoscaler(cfg, appToScaleGUID, neighbourAppName, 100, true)
Eventually(scaleIn).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(1))

})
})
Context("neighbour app send metrics if metrics strategy is not set i.e same_app", func() {
BeforeEach(func() {
policy = GenerateBindingsWithScalingPolicy("", 1, 2, "test_metric", 100, 550)
})
When("policy is attached with neighbour app", func() {
It("should scale out and scale the neighbour app", func() {
By(fmt.Sprintf("Scale out %s to 2 instance", neighbourAppName))
scaleOut := sendMetricToAutoscaler(cfg, neighbourAppGUID, neighbourAppName, 550, true)
Eventually(scaleOut).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(2))

By(fmt.Sprintf("Scale in %s to 1 instance", neighbourAppName))
scaleIn := sendMetricToAutoscaler(cfg, neighbourAppGUID, neighbourAppName, 90, true)
Eventually(scaleIn).
WithTimeout(5 * time.Minute).
WithPolling(15 * time.Second).
Should(Equal(1))

})
})
When("no policy is attached with neighbour app", func() {
BeforeEach(func() {
policy = ""
})
It("should not scale neighbour app", func() {
sendMetricToAutoscaler(cfg, neighbourAppGUID, neighbourAppName, 550, true)
Expect(RunningInstances(neighbourAppGUID, 5*time.Second)).To(Equal(1))

})
})

})
})
})

func sendMetricToAutoscaler(config *config.Config, appGUID string, appName string, metricThreshold int, mtls bool) func() (int, error) {
func sendMetricToAutoscaler(config *config.Config, appToScaleGUID string, neighbourAppName string, metricThreshold int, mtls bool) func() (int, error) {
return func() (int, error) {

if mtls {
SendMetricMTLS(config, appName, metricThreshold)
SendMetricMTLS(config, appToScaleGUID, neighbourAppName, metricThreshold)
} else {
SendMetric(config, appName, metricThreshold)
SendMetric(config, neighbourAppName, metricThreshold)
}
return RunningInstances(appGUID, 5*time.Second)
return RunningInstances(appToScaleGUID, 5*time.Second)
}
}
Loading
Loading