mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-07 11:13:48 +00:00
Merge pull request #119166 from nilekhc/log-decryption-failure
feat: improves metric and logging
This commit is contained in:
commit
90c362b343
@ -61,7 +61,7 @@ var (
|
|||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Subsystem: subsystem,
|
Subsystem: subsystem,
|
||||||
Name: "transformation_operations_total",
|
Name: "transformation_operations_total",
|
||||||
Help: "Total number of transformations.",
|
Help: "Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption",
|
||||||
StabilityLevel: metrics.ALPHA,
|
StabilityLevel: metrics.ALPHA,
|
||||||
},
|
},
|
||||||
[]string{"transformation_type", "transformer_prefix", "status"},
|
[]string{"transformation_type", "transformer_prefix", "status"},
|
||||||
|
@ -56,7 +56,7 @@ func TestTotals(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
@ -69,7 +69,7 @@ func TestTotals(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
apiserver_storage_transformation_operations_total{status="OK",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="OK",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
@ -82,7 +82,7 @@ func TestTotals(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="FailedPrecondition",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="FailedPrecondition",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
apiserver_storage_transformation_operations_total{status="FailedPrecondition",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="FailedPrecondition",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
@ -95,7 +95,7 @@ func TestTotals(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="Internal",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="Internal",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
apiserver_storage_transformation_operations_total{status="Internal",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="Internal",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
@ -108,7 +108,7 @@ func TestTotals(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="NotFound",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="NotFound",transformation_type="from_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
apiserver_storage_transformation_operations_total{status="NotFound",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
apiserver_storage_transformation_operations_total{status="NotFound",transformation_type="to_storage",transformer_prefix="k8s:enc:kms:v1:"} 1
|
||||||
|
@ -25,6 +25,8 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/errors"
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -158,6 +160,7 @@ func (t *prefixTransformers) TransformFromStorage(ctx context.Context, data []by
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := errors.Reduce(errors.NewAggregate(errs)); err != nil {
|
if err := errors.Reduce(errors.NewAggregate(errs)); err != nil {
|
||||||
|
logTransformErr(ctx, err, "failed to decrypt data")
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
RecordTransformation("from_storage", "unknown", time.Since(start), t.err)
|
RecordTransformation("from_storage", "unknown", time.Since(start), t.err)
|
||||||
@ -171,6 +174,7 @@ func (t *prefixTransformers) TransformToStorage(ctx context.Context, data []byte
|
|||||||
result, err := transformer.Transformer.TransformToStorage(ctx, data, dataCtx)
|
result, err := transformer.Transformer.TransformToStorage(ctx, data, dataCtx)
|
||||||
RecordTransformation("to_storage", string(transformer.Prefix), time.Since(start), err)
|
RecordTransformation("to_storage", string(transformer.Prefix), time.Since(start), err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logTransformErr(ctx, err, "failed to encrypt data")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
prefixedData := make([]byte, len(transformer.Prefix), len(result)+len(transformer.Prefix))
|
prefixedData := make([]byte, len(transformer.Prefix), len(result)+len(transformer.Prefix))
|
||||||
@ -178,3 +182,32 @@ func (t *prefixTransformers) TransformToStorage(ctx context.Context, data []byte
|
|||||||
prefixedData = append(prefixedData, result...)
|
prefixedData = append(prefixedData, result...)
|
||||||
return prefixedData, nil
|
return prefixedData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logTransformErr(ctx context.Context, err error, message string) {
|
||||||
|
requestInfo := getRequestInfoFromContext(ctx)
|
||||||
|
if klogLevel6 := klog.V(6); klogLevel6.Enabled() {
|
||||||
|
klogLevel6.InfoSDepth(
|
||||||
|
1,
|
||||||
|
message,
|
||||||
|
"err", err,
|
||||||
|
"group", requestInfo.APIGroup,
|
||||||
|
"version", requestInfo.APIVersion,
|
||||||
|
"resource", requestInfo.Resource,
|
||||||
|
"subresource", requestInfo.Subresource,
|
||||||
|
"verb", requestInfo.Verb,
|
||||||
|
"namespace", requestInfo.Namespace,
|
||||||
|
"name", requestInfo.Name,
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.ErrorSDepth(1, err, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRequestInfoFromContext(ctx context.Context) *genericapirequest.RequestInfo {
|
||||||
|
if reqInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
|
||||||
|
return reqInfo
|
||||||
|
}
|
||||||
|
return &genericapirequest.RequestInfo{}
|
||||||
|
}
|
||||||
|
@ -19,12 +19,17 @@ package value
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/component-base/metrics/legacyregistry"
|
"k8s.io/component-base/metrics/legacyregistry"
|
||||||
"k8s.io/component-base/metrics/testutil"
|
"k8s.io/component-base/metrics/testutil"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testTransformer struct {
|
type testTransformer struct {
|
||||||
@ -129,7 +134,7 @@ func TestPrefixFromMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="identity"} 1
|
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="identity"} 1
|
||||||
`,
|
`,
|
||||||
@ -143,7 +148,7 @@ func TestPrefixFromMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="other:"} 1
|
apiserver_storage_transformation_operations_total{status="OK",transformation_type="from_storage",transformer_prefix="other:"} 1
|
||||||
`,
|
`,
|
||||||
@ -157,7 +162,7 @@ func TestPrefixFromMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="other:"} 1
|
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="other:"} 1
|
||||||
`,
|
`,
|
||||||
@ -171,7 +176,7 @@ func TestPrefixFromMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="unknown"} 1
|
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="from_storage",transformer_prefix="unknown"} 1
|
||||||
`,
|
`,
|
||||||
@ -215,7 +220,7 @@ func TestPrefixToMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="OK",transformation_type="to_storage",transformer_prefix="other:"} 1
|
apiserver_storage_transformation_operations_total{status="OK",transformation_type="to_storage",transformer_prefix="other:"} 1
|
||||||
`,
|
`,
|
||||||
@ -229,7 +234,7 @@ func TestPrefixToMetrics(t *testing.T) {
|
|||||||
"apiserver_storage_transformation_operations_total",
|
"apiserver_storage_transformation_operations_total",
|
||||||
},
|
},
|
||||||
want: `
|
want: `
|
||||||
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations.
|
# HELP apiserver_storage_transformation_operations_total [ALPHA] Total number of transformations. Successful transformation will have a status 'OK' and a varied status string when the transformation fails. This status and transformation_type fields may be used for alerting on encryption/decryption failure using transformation_type from_storage for decryption and to_storage for encryption
|
||||||
# TYPE apiserver_storage_transformation_operations_total counter
|
# TYPE apiserver_storage_transformation_operations_total counter
|
||||||
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="to_storage",transformer_prefix="other:"} 1
|
apiserver_storage_transformation_operations_total{status="unknown-non-grpc",transformation_type="to_storage",transformer_prefix="other:"} 1
|
||||||
`,
|
`,
|
||||||
@ -250,3 +255,63 @@ func TestPrefixToMetrics(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogTransformErr(t *testing.T) {
|
||||||
|
klog.InitFlags(nil)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ctx context.Context
|
||||||
|
err error
|
||||||
|
message string
|
||||||
|
expectedLog string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "log error with request info",
|
||||||
|
ctx: genericapirequest.WithRequestInfo(testContext(t), &genericapirequest.RequestInfo{
|
||||||
|
APIGroup: "awesome.bears.com",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Resource: "pandas",
|
||||||
|
Subresource: "status",
|
||||||
|
Namespace: "kube-system",
|
||||||
|
Name: "panda",
|
||||||
|
Verb: "update",
|
||||||
|
}),
|
||||||
|
err: errors.New("encryption failed"),
|
||||||
|
message: "failed to encrypt data",
|
||||||
|
expectedLog: "\"failed to encrypt data\" err=\"encryption failed\" group=\"awesome.bears.com\" version=\"v1\" resource=\"pandas\" subresource=\"status\" verb=\"update\" namespace=\"kube-system\" name=\"panda\"\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "log error without request info",
|
||||||
|
ctx: context.Background(),
|
||||||
|
err: errors.New("decryption failed"),
|
||||||
|
message: "failed to decrypt data",
|
||||||
|
expectedLog: "\"failed to decrypt data\" err=\"decryption failed\" group=\"\" version=\"\" resource=\"\" subresource=\"\" verb=\"\" namespace=\"\" name=\"\"\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
flag.Set("v", "6")
|
||||||
|
flag.Parse()
|
||||||
|
klog.SetOutput(&buf)
|
||||||
|
klog.LogToStderr(false)
|
||||||
|
defer klog.LogToStderr(true)
|
||||||
|
|
||||||
|
logTransformErr(tt.ctx, tt.err, tt.message)
|
||||||
|
|
||||||
|
// remove timestamp and goroutine id from log message to make it easier to compare
|
||||||
|
gotLog := regexp.MustCompile(`\w+ \d+:\d+:\d+\.\d+.*\d+.*transformer_test.go:\d+].`).ReplaceAllString(buf.String(), "")
|
||||||
|
|
||||||
|
if gotLog != tt.expectedLog {
|
||||||
|
t.Errorf("expected log message %q, got %q", tt.expectedLog, gotLog)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testContext(t *testing.T) context.Context {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
t.Cleanup(cancel)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user