Commit 625192b3 authored by Mik Vyatskov's avatar Mik Vyatskov

Covert Stackdriver Logging load tests to soak tests

parent c9ad8dcd
...@@ -14,7 +14,7 @@ go_library( ...@@ -14,7 +14,7 @@ go_library(
"es_utils.go", "es_utils.go",
"sd.go", "sd.go",
"sd_events.go", "sd_events.go",
"sd_load.go", "sd_soak.go",
"sd_utils.go", "sd_utils.go",
"utils.go", "utils.go",
], ],
......
...@@ -26,24 +26,24 @@ import ( ...@@ -26,24 +26,24 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
) )
var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver", func() {
f := framework.NewDefaultFramework("gcl-logging") f := framework.NewDefaultFramework("sd-logging")
BeforeEach(func() { BeforeEach(func() {
framework.SkipUnlessProviderIs("gce", "gke") framework.SkipUnlessProviderIs("gce", "gke")
}) })
It("should check that logs from containers are ingested in GCL", func() { It("should ingest logs from applications", func() {
podName := "synthlogger" podName := "synthlogger"
gclLogsProvider, err := newGclLogsProvider(f) sdLogsProvider, err := newSdLogsProvider(f)
framework.ExpectNoError(err, "Failed to create GCL logs provider") framework.ExpectNoError(err, "Failed to create Stackdriver logs provider")
err = gclLogsProvider.Init() err = sdLogsProvider.Init()
defer gclLogsProvider.Cleanup() defer sdLogsProvider.Cleanup()
framework.ExpectNoError(err, "Failed to init GCL logs provider") framework.ExpectNoError(err, "Failed to init Stackdriver logs provider")
err = ensureSingleFluentdOnEachNode(f, gclLogsProvider.FluentdApplicationName()) err = ensureSingleFluentdOnEachNode(f, sdLogsProvider.FluentdApplicationName())
framework.ExpectNoError(err, "Fluentd deployed incorrectly") framework.ExpectNoError(err, "Fluentd deployed incorrectly")
By("Running synthetic logger") By("Running synthetic logger")
...@@ -54,7 +54,7 @@ var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { ...@@ -54,7 +54,7 @@ var _ = framework.KubeDescribe("Cluster level logging using GCL", func() {
By("Waiting for logs to ingest") By("Waiting for logs to ingest")
config := &loggingTestConfig{ config := &loggingTestConfig{
LogsProvider: gclLogsProvider, LogsProvider: sdLogsProvider,
Pods: []*loggingPod{pod}, Pods: []*loggingPod{pod},
IngestionTimeout: 10 * time.Minute, IngestionTimeout: 10 * time.Minute,
MaxAllowedLostFraction: 0, MaxAllowedLostFraction: 0,
......
...@@ -40,26 +40,26 @@ const ( ...@@ -40,26 +40,26 @@ const (
eventCreationInterval = 10 * time.Second eventCreationInterval = 10 * time.Second
) )
var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver", func() {
f := framework.NewDefaultFramework("gcl-logging-events") f := framework.NewDefaultFramework("sd-logging-events")
BeforeEach(func() { BeforeEach(func() {
framework.SkipUnlessProviderIs("gce", "gke") framework.SkipUnlessProviderIs("gce", "gke")
}) })
It("should ingest events", func() { It("should ingest events", func() {
gclLogsProvider, err := newGclLogsProvider(f) sdLogsProvider, err := newSdLogsProvider(f)
framework.ExpectNoError(err, "Failed to create GCL logs provider") framework.ExpectNoError(err, "Failed to create Stackdriver logs provider")
err = gclLogsProvider.Init() err = sdLogsProvider.Init()
defer gclLogsProvider.Cleanup() defer sdLogsProvider.Cleanup()
framework.ExpectNoError(err, "Failed to init GCL logs provider") framework.ExpectNoError(err, "Failed to init Stackdriver logs provider")
stopCh := make(chan struct{}) stopCh := make(chan struct{})
successCh := make(chan struct{}) successCh := make(chan struct{})
go func() { go func() {
wait.Poll(eventPollingInterval, eventsIngestionTimeout, func() (bool, error) { wait.Poll(eventPollingInterval, eventsIngestionTimeout, func() (bool, error) {
events := gclLogsProvider.ReadEvents() events := sdLogsProvider.ReadEvents()
if len(events) > 0 { if len(events) > 0 {
framework.Logf("Some events are ingested, sample event: %v", events[0]) framework.Logf("Some events are ingested, sample event: %v", events[0])
close(successCh) close(successCh)
......
...@@ -18,6 +18,7 @@ package e2e ...@@ -18,6 +18,7 @@ package e2e
import ( import (
"fmt" "fmt"
"math"
"time" "time"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
...@@ -27,69 +28,33 @@ import ( ...@@ -27,69 +28,33 @@ import (
) )
const ( const (
loadTestMaxAllowedLostFraction = 0.01 // maxAllowedLostFraction is the fraction of lost logs considered acceptable.
loadTestMaxAllowedFluentdRestarts = 1 maxAllowedLostFraction = 0.01
// maxAllowedRestartsPerHour is the number of fluentd container restarts
// considered acceptable. Once per hour is fine for now, as long as it
// doesn't loose too much logs.
maxAllowedRestartsPerHour = 1.0
) )
var _ = framework.KubeDescribe("Cluster level logging using GCL [Feature:StackdriverLogging]", func() { var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver [Feature:StackdriverLogging] [Soak]", func() {
f := framework.NewDefaultFramework("gcl-logging-load") f := framework.NewDefaultFramework("sd-logging-load")
It("should create a constant load with long-living pods and ensure logs delivery", func() { It("should ingest logs from applications running for a prolonged amount of time", func() {
gclLogsProvider, err := newGclLogsProvider(f) sdLogsProvider, err := newSdLogsProvider(f)
framework.ExpectNoError(err, "Failed to create GCL logs provider") framework.ExpectNoError(err, "Failed to create Stackdriver logs provider")
err = gclLogsProvider.Init() err = sdLogsProvider.Init()
defer gclLogsProvider.Cleanup() defer sdLogsProvider.Cleanup()
framework.ExpectNoError(err, "Failed to init GCL logs provider") framework.ExpectNoError(err, "Failed to init Stackdriver logs provider")
nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items
nodeCount := len(nodes)
podCount := 30 * nodeCount
loggingDuration := 10 * time.Minute
linesPerSecond := 1000 * nodeCount
linesPerPod := linesPerSecond * int(loggingDuration.Seconds()) / podCount
ingestionTimeout := 20 * time.Minute
By("Running logs generator pods")
pods := []*loggingPod{}
for podIdx := 0; podIdx < podCount; podIdx++ {
node := nodes[podIdx%len(nodes)]
podName := fmt.Sprintf("logs-generator-%d-%d", linesPerPod, podIdx)
pods = append(pods, createLoggingPod(f, podName, node.Name, linesPerPod, loggingDuration))
defer f.PodClient().Delete(podName, &meta_v1.DeleteOptions{})
}
By("Waiting for all log lines to be ingested")
config := &loggingTestConfig{
LogsProvider: gclLogsProvider,
Pods: pods,
IngestionTimeout: ingestionTimeout,
MaxAllowedLostFraction: loadTestMaxAllowedLostFraction,
MaxAllowedFluentdRestarts: loadTestMaxAllowedFluentdRestarts,
}
err = waitForFullLogsIngestion(f, config)
if err != nil {
framework.Failf("Failed to ingest logs: %v", err)
} else {
framework.Logf("Successfully ingested all logs")
}
})
It("should create a constant load with short-living pods and ensure logs delivery", func() {
gclLogsProvider, err := newGclLogsProvider(f)
framework.ExpectNoError(err, "Failed to create GCL logs provider")
err = gclLogsProvider.Init()
defer gclLogsProvider.Cleanup()
framework.ExpectNoError(err, "Failed to init GCL logs provider")
nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items
maxPodCount := 10 maxPodCount := 10
jobDuration := 1 * time.Minute jobDuration := 1 * time.Hour
linesPerPodPerSecond := 100 linesPerPodPerSecond := 100
testDuration := 10 * time.Minute testDuration := 21 * time.Hour
ingestionTimeout := 20 * time.Minute ingestionTimeout := testDuration + 30*time.Minute
allowedRestarts := int(math.Ceil(float64(testDuration) /
float64(time.Hour) * maxAllowedRestartsPerHour))
podRunDelay := time.Duration(int64(jobDuration) / int64(maxPodCount)) podRunDelay := time.Duration(int64(jobDuration) / int64(maxPodCount))
podRunCount := int(testDuration.Seconds())/int(podRunDelay.Seconds()) - 1 podRunCount := int(testDuration.Seconds())/int(podRunDelay.Seconds()) - 1
...@@ -109,11 +74,11 @@ var _ = framework.KubeDescribe("Cluster level logging using GCL [Feature:Stackdr ...@@ -109,11 +74,11 @@ var _ = framework.KubeDescribe("Cluster level logging using GCL [Feature:Stackdr
By("Waiting for all log lines to be ingested") By("Waiting for all log lines to be ingested")
config := &loggingTestConfig{ config := &loggingTestConfig{
LogsProvider: gclLogsProvider, LogsProvider: sdLogsProvider,
Pods: pods, Pods: pods,
IngestionTimeout: ingestionTimeout, IngestionTimeout: ingestionTimeout,
MaxAllowedLostFraction: loadTestMaxAllowedLostFraction, MaxAllowedLostFraction: maxAllowedLostFraction,
MaxAllowedFluentdRestarts: loadTestMaxAllowedFluentdRestarts, MaxAllowedFluentdRestarts: allowedRestarts,
} }
err = waitForFullLogsIngestion(f, config) err = waitForFullLogsIngestion(f, config)
if err != nil { if err != nil {
......
...@@ -213,6 +213,11 @@ func waitForFullLogsIngestion(f *framework.Framework, config *loggingTestConfig) ...@@ -213,6 +213,11 @@ func waitForFullLogsIngestion(f *framework.Framework, config *loggingTestConfig)
if totalMissing > 0 { if totalMissing > 0 {
framework.Logf("After %v still missing %d lines, %.2f%% of total number of lines", framework.Logf("After %v still missing %d lines, %.2f%% of total number of lines",
config.IngestionTimeout, totalMissing, lostFraction*100) config.IngestionTimeout, totalMissing, lostFraction*100)
for podIdx, missing := range missingByPod {
if missing != 0 {
framework.Logf("Still missing %d lines for pod %v", missing, config.Pods[podIdx])
}
}
} }
if lostFraction > config.MaxAllowedLostFraction { if lostFraction > config.MaxAllowedLostFraction {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment