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

neonvm: add support for mounting service account tokens #1316

Draft
wants to merge 2 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
4 changes: 2 additions & 2 deletions neonvm-runner/cmd/disks.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func setupVMDisks(
discard = ",discard=unmap"
}
qemuCmd = append(qemuCmd, "-drive", fmt.Sprintf("id=%s,file=%s,if=virtio,media=disk,%s%s", disk.Name, dPath, diskCacheSettings, discard))
case disk.ConfigMap != nil || disk.Secret != nil:
case disk.ConfigMap != nil || disk.Secret != nil || disk.Projected != nil:
dPath := fmt.Sprintf("%s/%s.iso", mountedDiskPath, disk.Name)
mnt := fmt.Sprintf("/vm/mounts%s", disk.MountPath)
logger.Info("creating iso9660 image", zap.String("diskPath", dPath), zap.String("diskName", disk.Name), zap.String("mountPath", mnt))
Expand Down Expand Up @@ -206,7 +206,7 @@ func createISO9660runtime(
mounts = append(mounts, fmt.Sprintf(`/neonvm/bin/mount %s $(/neonvm/bin/blkid -L %s) %s`, opts, disk.Name, disk.MountPath))
// Note: chmod must be after mount, otherwise it gets overwritten by mount.
mounts = append(mounts, fmt.Sprintf(`/neonvm/bin/chmod 0777 %s`, disk.MountPath))
case disk.ConfigMap != nil || disk.Secret != nil:
case disk.ConfigMap != nil || disk.Secret != nil || disk.Projected != nil:
mounts = append(mounts, fmt.Sprintf(`/neonvm/bin/mount -t iso9660 -o ro,mode=0644 $(/neonvm/bin/blkid -L %s) %s`, disk.Name, disk.MountPath))
case disk.Tmpfs != nil:
mounts = append(mounts, fmt.Sprintf(`/neonvm/bin/chmod 0777 %s`, disk.MountPath))
Expand Down
11 changes: 10 additions & 1 deletion neonvm-runner/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ func run(logger *zap.Logger) error {
EmptyDisk: nil,
ConfigMap: nil,
Secret: nil,
Projected: nil,
Tmpfs: nil,
Implicit: nil,
},
})
}
Expand Down Expand Up @@ -699,7 +701,14 @@ func monitorFiles(ctx context.Context, logger *zap.Logger, wg *sync.WaitGroup, v
if disk.Watch != nil && *disk.Watch {
// secrets/configmaps are mounted using the atomicwriter utility,
// which loads the directory into `..data`.
dataDir := fmt.Sprintf("/vm/mounts%s/..data", disk.MountPath)
dataDir := fmt.Sprintf("%s/..data", disk.MountPath)

// when we mount the disk ourselves, it goes into /vm/mounts.
// when the volumemount is implicit, it exists where it exists.
if disk.DiskSource.Implicit == nil {
dataDir = fmt.Sprintf("/vm/mounts%s", dataDir)
}

secrets[dataDir] = disk.MountPath
secretsOrd = append(secretsOrd, dataDir)
}
Expand Down
9 changes: 9 additions & 0 deletions neonvm/apis/neonvm/v1/virtualmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,11 +559,20 @@ type DiskSource struct {
// Secret represents a secret that should populate this disk.
// +optional
Secret *corev1.SecretVolumeSource `json:"secret,omitempty"`
// Projected represents a projected volume that should populate this disk.
// +optional
Projected *corev1.ProjectedVolumeSource `json:"projected,omitempty"`
// TmpfsDisk represents a tmpfs.
// +optional
Tmpfs *TmpfsDiskSource `json:"tmpfs,omitempty"`
// Implicit represents an implicit volume that will be automatically mounted.
// Suitable for `aws-iam-token` or `azure-identity-token`, among other things.
// +optional
Implicit *ImplicitDiskSource `json:"implicit,omitempty"`
}

type ImplicitDiskSource struct{}

type EmptyDiskSource struct {
Size resource.Quantity `json:"size"`
// Discard enables the "discard" mount option for the filesystem
Expand Down
25 changes: 25 additions & 0 deletions neonvm/apis/neonvm/v1/zz_generated.deepcopy.go

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

354 changes: 354 additions & 0 deletions neonvm/config/crd/bases/vm.neon.tech_virtualmachines.yaml

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions pkg/neonvm/controllers/vm_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,14 @@ func podSpec(
},
},
})
case disk.Projected != nil:
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, mnt)
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
Name: disk.Name,
VolumeSource: corev1.VolumeSource{
Projected: disk.Projected,
},
})
case disk.EmptyDisk != nil:
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, mnt)
pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{
Expand Down
21 changes: 21 additions & 0 deletions tests/e2e/vm-projected/00-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: kuttl.dev/v1beta1
kind: TestAssert
timeout: 70
commands:
- script: |
set -eux
pod="$(kubectl get neonvm -n "$NAMESPACE" example -o jsonpath='{.status.podName}')"
kubectl exec -n "$NAMESPACE" $pod -- scp guest-vm:/var/run/secrets/tokens/token token
---
apiVersion: vm.neon.tech/v1
kind: VirtualMachine
metadata:
name: example
status:
phase: Running
restartCount: 0
conditions:
- type: Available
status: "True"
cpus: 250m
memorySize: 1Gi
39 changes: 39 additions & 0 deletions tests/e2e/vm-projected/00-create-vm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
unitTest: false
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-account
---
apiVersion: vm.neon.tech/v1
kind: VirtualMachine
metadata:
name: example
spec:
schedulerName: autoscale-scheduler
enableSSH: true
guest:
cpus:
min: 0.25
use: 0.25
max: 0.25
memorySlotSize: 1Gi
memorySlots:
min: 1
use: 1
max: 1
rootDisk:
image: vm-postgres:15-bullseye
size: 1Gi
serviceAccountName: "test-account"
disks:
- projected:
sources:
- serviceAccountToken:
expirationSeconds: 3600
path: token
mountPath: /var/run/secrets/tokens
name: token
watch: true
Loading