Skip to content

Commit 9aa7310

Browse files
authored
Merge pull request #512 from tam7t/tam7t/config-message-size
feat: allow maxCallRecvMsgSize to be increased for large secret mounts
2 parents 4f9e3f6 + 99cf558 commit 9aa7310

File tree

8 files changed

+79
-9
lines changed

8 files changed

+79
-9
lines changed

cmd/secrets-store-csi-driver/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ import (
2929
"sigs.k8s.io/secrets-store-csi-driver/pkg/rotation"
3030
"sigs.k8s.io/secrets-store-csi-driver/pkg/version"
3131

32+
"google.golang.org/grpc"
3233
"k8s.io/apimachinery/pkg/fields"
3334
"k8s.io/apimachinery/pkg/runtime"
3435
"k8s.io/apimachinery/pkg/runtime/schema"
3536
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3637
json "k8s.io/component-base/logs/json"
3738
"k8s.io/klog/v2"
38-
3939
ctrl "sigs.k8s.io/controller-runtime"
4040

4141
"sigs.k8s.io/secrets-store-csi-driver/apis/v1alpha1"
@@ -58,6 +58,7 @@ var (
5858
rotationPollInterval = flag.Duration("rotation-poll-interval", 2*time.Minute, "Secret rotation poll interval duration")
5959
enableProfile = flag.Bool("enable-pprof", false, "enable pprof profiling")
6060
profilePort = flag.Int("pprof-port", 6065, "port for pprof profiling")
61+
maxCallRecvMsgSize = flag.Int("max-call-recv-msg-size", 1024*1024*4, "maximum size in bytes of gRPC response from plugins")
6162

6263
// enable filtered watch for NodePublishSecretRef secrets. The filtering is done on the csi driver label: secrets-store.csi.k8s.io/used=true
6364
// For Kubernetes secrets used to provide credentials for use with the CSI driver, set the label by running: kubectl label secret secrets-store-creds secrets-store.csi.k8s.io/used=true
@@ -148,7 +149,7 @@ func main() {
148149
ctx := withShutdownSignal(context.Background())
149150

150151
// create provider clients
151-
providerClients := secretsstore.NewPluginClientBuilder(*providerVolumePath)
152+
providerClients := secretsstore.NewPluginClientBuilder(*providerVolumePath, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(*maxCallRecvMsgSize)))
152153
defer providerClients.Cleanup()
153154

154155
// enable provider health check

docs/book/src/troubleshooting.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,13 @@ Secrets Store CSI Driver is deployed as a *DaemonSet*. The above error indicates
5353
NAME ATTACHREQUIRED PODINFOONMOUNT MODES AGE
5454
secrets-store.csi.k8s.io false true Ephemeral 110m
5555
```
56-
56+
57+
### Mount fails with `grpc: received message larger than max`
58+
59+
If the files pulled in by the `SecretProviderClass` are larger than 4MiB you may observe `FailedMount` warnings with a
60+
message that includes `grpc: received message larger than max`. You can configure the driver to accept responses larger
61+
than 4MiB by specifying the `--max-call-recv-msg-size=<size in bytes>` argument to the `secrets-store` container in the
62+
`csi-secrets-store` DaemonSet.
63+
64+
Note that this may also increase memory resource consumption of the `secrets-store` container, so you should also
65+
consider increasing the memory limit as well.

manifest_staging/charts/secrets-store-csi-driver/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ The following table lists the configurable parameters of the csi-secrets-store-p
7979
| `logFormatJSON` | Use JSON logging format | `false` |
8080
| `livenessProbe.port` | Liveness probe port | `9808` |
8181
| `livenessProbe.logLevel` | Liveness probe container logging verbosity level | `2` |
82+
| `maxCallRecvMsgSize` | Maximum size in bytes of gRPC response from plugins | `4194304` |
8283
| `rbac.install` | Install default rbac roles and bindings | true |
8384
| `rbac.pspEnabled` | If `true`, create and use a restricted pod security policy for Secrets Store CSI Driver pod(s) | `false` |
8485
| `syncSecret.enabled` | Enable rbac roles and bindings required for syncing to Kubernetes native secrets (the default will change to false after v0.0.14) | true |

manifest_staging/charts/secrets-store-csi-driver/templates/secrets-store-csi-driver-windows.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ spec:
8484
{{- if and (semverCompare ">= v0.0.22-0" .Values.windows.image.tag) .Values.providerHealthCheckInterval }}
8585
- "--provider-health-check-interval={{ .Values.providerHealthCheckInterval }}"
8686
{{- end }}
87+
{{- if .Values.maxCallRecvMsgSize }}
88+
- "--max-call-recv-msg-size={{ .Values.maxCallRecvMsgSize | int64 }}"
89+
{{- end }}
8790
env:
8891
{{- with .Values.windows.env }}
8992
{{- toYaml . | nindent 10 }}

manifest_staging/charts/secrets-store-csi-driver/templates/secrets-store-csi-driver.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ spec:
8484
{{- if and (semverCompare ">= v0.0.22-0" .Values.linux.image.tag) .Values.providerHealthCheckInterval }}
8585
- "--provider-health-check-interval={{ .Values.providerHealthCheckInterval }}"
8686
{{- end }}
87+
{{- if .Values.maxCallRecvMsgSize }}
88+
- "--max-call-recv-msg-size={{ .Values.maxCallRecvMsgSize | int64 }}"
89+
{{- end }}
8790
env:
8891
{{- with .Values.linux.env }}
8992
{{- toYaml . | nindent 10 }}

manifest_staging/charts/secrets-store-csi-driver/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ livenessProbe:
153153
port: 9808
154154
logLevel: 2
155155

156+
## Maximum size in bytes of gRPC response from plugins
157+
maxCallRecvMsgSize: 4194304
158+
156159
## Install Default RBAC roles and bindings
157160
rbac:
158161
install: true

pkg/secrets-store/provider_client.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type PluginClientBuilder struct {
7373
conns map[string]*grpc.ClientConn
7474
socketPath string
7575
lock sync.RWMutex
76+
opts []grpc.DialOption
7677
}
7778

7879
// NewPluginClientBuilder creates a PluginClientBuilder that will connect to
@@ -82,12 +83,23 @@ type PluginClientBuilder struct {
8283
// <path>/<plugin_name>.sock
8384
//
8485
// where <plugin_name> must match the PluginNameRe regular expression.
85-
func NewPluginClientBuilder(path string) *PluginClientBuilder {
86+
//
87+
// Additional grpc dial options can also be set through opts and will be used
88+
// when creating all clients.
89+
func NewPluginClientBuilder(path string, opts ...grpc.DialOption) *PluginClientBuilder {
8690
return &PluginClientBuilder{
8791
clients: make(map[string]v1alpha1.CSIDriverProviderClient),
8892
conns: make(map[string]*grpc.ClientConn),
8993
socketPath: path,
9094
lock: sync.RWMutex{},
95+
opts: append(opts, []grpc.DialOption{
96+
grpc.WithInsecure(), // the interface is only secured through filesystem ACLs
97+
grpc.WithContextDialer(func(ctx context.Context, target string) (net.Conn, error) {
98+
return (&net.Dialer{}).DialContext(ctx, "unix", target)
99+
}),
100+
grpc.WithDefaultServiceConfig(ServiceConfig),
101+
}...,
102+
),
91103
}
92104
}
93105

@@ -115,11 +127,7 @@ func (p *PluginClientBuilder) Get(ctx context.Context, provider string) (v1alpha
115127

116128
conn, err := grpc.Dial(
117129
fmt.Sprintf("%s/%s.sock", p.socketPath, provider),
118-
grpc.WithInsecure(), // the interface is only secured through filesystem ACLs
119-
grpc.WithContextDialer(func(ctx context.Context, target string) (net.Conn, error) {
120-
return (&net.Dialer{}).DialContext(ctx, "unix", target)
121-
}),
122-
grpc.WithDefaultServiceConfig(ServiceConfig),
130+
p.opts...,
123131
)
124132
if err != nil {
125133
return nil, err

pkg/secrets-store/provider_client_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ import (
2828
"time"
2929

3030
"github.com/google/go-cmp/cmp"
31+
"google.golang.org/grpc"
32+
"google.golang.org/grpc/codes"
33+
"google.golang.org/grpc/status"
3134

3235
"sigs.k8s.io/secrets-store-csi-driver/pkg/test_utils/tmpdir"
3336
"sigs.k8s.io/secrets-store-csi-driver/provider/fake"
@@ -157,6 +160,45 @@ func TestMountContent(t *testing.T) {
157160
}
158161
}
159162

163+
func TestMountContent_TooLarge(t *testing.T) {
164+
socketPath := tmpdir.New(t, "", "ut")
165+
targetPath := tmpdir.New(t, "", "ut")
166+
167+
// set a very small max message size
168+
pool := NewPluginClientBuilder(socketPath, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(5)))
169+
defer pool.Cleanup()
170+
171+
server, cleanup := fakeServer(t, socketPath, "provider1")
172+
defer cleanup()
173+
174+
server.SetObjects(map[string]string{"foo": "v1"})
175+
server.SetFiles([]*v1alpha1.File{
176+
{
177+
Path: "foo",
178+
Mode: 0644,
179+
Contents: []byte("foo"),
180+
},
181+
})
182+
server.Start()
183+
184+
client, err := pool.Get(context.Background(), "provider1")
185+
if err != nil {
186+
t.Fatalf("expected err to be nil, got: %+v", err)
187+
}
188+
189+
// rpc error: code = ResourceExhausted desc = grpc: received message larger than max (28 vs. 5)
190+
_, errorCode, err := MountContent(context.TODO(), client, "{}", "{}", targetPath, "777", nil)
191+
if err == nil {
192+
t.Errorf("expected err to be not nil")
193+
}
194+
if want := codes.ResourceExhausted; status.Code(err) != want {
195+
t.Errorf("expected error code: %v, got: %+v", want, status.Code(err))
196+
}
197+
if want := "GRPCProviderError"; errorCode != want {
198+
t.Errorf("expected error code: %v, got: %+v", want, errorCode)
199+
}
200+
}
201+
160202
func TestMountContentError(t *testing.T) {
161203
cases := []struct {
162204
name string

0 commit comments

Comments
 (0)