etcd-io / etcd-io/etcd-operator
bug: TLS volumes created but never mounted
- Dominant language
- Go
- Stars
- 164
- Forks
- 72
- Avg merge
- 22h 46m
- Merged PRs (30d)
- 34
Description
The operator creates TLS secret volumes but doesn't actually mount them into the etcd container.
## What's happening
Applied this manifest with TLS configured:
```yaml
apiVersion: operator.etcd.io/v1alpha1
kind: EtcdCluster
metadata:
name: etcd-cluster
spec:
imageRegistry: quay.io/coreos/etcd
podTemplate:
metadata:
labels:
app: etcd
component: database
size: 3
storageSpec:
accessModes: ReadWriteOnce
storageClassName: openebs-lvm-vm-0
volumeSizeRequest: 10Gi
tls:
provider: cert-manager
providerCfg:
certManagerCfg:
issuerKind: ClusterIssuer
issuerName: themelio
validityDuration: 2160h
version: v3.5.28
```
Certificates get created fine. Secrets exist. But look at the resulting pod spec - the volumes are there:
```yaml
volumes:
- name: server-secret
secret:
defaultMode: 420
secretName: etcd-cluster-server-tls
- name: peer-secret
secret:
defaultMode: 420
secretName: etcd-cluster-peer-tls
```
But the container volumeMounts? Only has the data volume:
```yaml
containers:
- name: etcd
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
subPathExpr: $(POD_NAME)
```
So etcd starts with HTTP only and logs this:
```
{"level":"info","ts":"2026-03-25T20:28:50.860555Z","caller":"embed/serve.go:210","msg":"serving client traffic insecurely; this is strongly discouraged!","traffic":"grpc+http","address":"[::]:2379"}
```
## Why this happens
Looking at [`internal/controller/utils.go`](https://github.com/etcd-io/etcd-operator/blob/b97e11f5ce97ac5854cf8cdeec932f2248cacb27/internal/controller/utils.go):
The operator adds TLS volumes at [lines 195-211](https://github.com/etcd-io/etcd-operator/blob/b97e11f5ce97ac5854cf8cdeec932f2248cacb27/internal/controller/utils.go#L195-L211) but never creates corresponding volumeMounts.
When the container spec is built at [lines 144-188](https://github.com/etcd-io/etcd-operator/blob/b97e11f5ce97ac5854cf8cdeec932f2248cacb27/internal/controller/utils.go#L144-L188), there's no VolumeMounts field.
Then at [line 248](https://github.com/etcd-io/etcd-operator/blob/b97e11f5ce97ac5854cf8cdeec932f2248cacb27/internal/controller/utils.go#L248), when storage is configured:
```go
stsSpec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{{
Name: volumeName,
MountPath: etcdDataDir,
SubPathExpr: "$(POD_NAME)",
}}
```
It just replaces the whole VolumeMounts array with only the storage mount. No TLS mounts ever get added.
Commit [b97e11f5](https://github.com/etcd-io/etcd-operator/commit/b97e11f5ce97ac5854cf8cdeec932f2248cacb27) says "Also, mount certificate secrets to member pods" but it only added the volumes, not the mounts.
## What needs to happen
Need to actually mount the TLS volumes. Something like:
```go
// After line 188, add TLS volume mounts if configured
volumeMounts := []corev1.VolumeMount{}
if ec.Spec.TLS != nil {
volumeMounts = append(volumeMounts,
corev1.VolumeMount{
Name: "server-secret",
MountPath: "/etc/etcd/tls/server",
ReadOnly: true,
},
corev1.VolumeMount{
Name: "peer-secret",
MountPath: "/etc/etcd/tls/peer",
ReadOnly: true,
},
)
}
// Then at line 250, append instead of replace:
if ec.Spec.StorageSpec != nil {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: volumeName,
MountPath: etcdDataDir,
SubPathExpr: "$(POD_NAME)",
})
stsSpec.Template.Spec.Containers[0].VolumeMounts = volumeMounts
}
```
And then append the storage mount instead of replacing:
```go
if ec.Spec.StorageSpec != nil {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: volumeName,
MountPath: etcdDataDir,
SubPathExpr: "$(POD_NAME)",
})
stsSpec.Template.Spec.Containers[0].VolumeMounts = volumeMounts
}
```
Also unclear if the operator should automatically add TLS flags to the etcd args when `spec.tls` is set, or if users are expected to use `spec.etcdOptions` for that. Either way, the mounts need to exist first.
---
**Environment:**
- etcd-operator: v0.2.0
- Kubernetes: 1.33
- etcd: v3.5.28
- TLS provider: cert-manager
Contributor guide
Assessment
This issue has not been assessed yet.