mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 14:02:56 +09:00
Hidora's customers are leaving VMware now, and a tenant has to be able to import their own machines without a platform administrator. The chart approach could not express that: a tenant can neither create the Secret holding vCenter credentials nor name the VDDK image, so both had to come from somewhere they cannot reach. Two CRDs in a new `forklift.cozystack.io` group, split by lifecycle. A VMImportSource is a long-lived connection -- type, endpoint, credentials, readiness -- and a VMImportTask is the one-shot operation that names machines and produces VMDisks and VMInstances. The outputs carry no owner reference back to the task, so deleting a finished import leaves the machines alone. Konveyor Forklift does the transfer underneath; the controller renders its objects, mirrors its verdicts, and hands each finished volume into a VMDisk without copying it. What a live vCenter migration forced out, and no amount of source reading would have: - A guest copied verbatim keeps the drivers it had under VMware and no virtio, so on a virtio disk it does not fail the import -- it succeeds and then does not boot. Imported disks go on SATA. - VDDK connects straight to the ESXi host at the address vCenter advertises, which is routinely unreachable, and on the first cluster collided with the Service CIDR. `spec.hosts` redirects per host. - Firmware must be carried across or a UEFI guest imports as BIOS and never boots (stacked on #3002). - Deleting a task mid-transfer orphaned its DataVolume; a finalizer now removes the engine's volumes and leaves the outputs. The console gains a Migration section: connections are editable, and the VM field is a picker built from a machine list the controller publishes, since the aggregated API cannot reach the inventory and should not hold a source's credentials to try. Two general mechanisms fall out of that -- an option source may take an argument, and one named in a CRD annotation may reference a sibling field. Design: cozystack/community#62. Docs: cozystack/website#673. Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
86 lines
2.8 KiB
YAML
86 lines
2.8 KiB
YAML
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: migration-controller
|
|
labels:
|
|
app: migration-controller
|
|
spec:
|
|
replicas: {{ .Values.migrationController.replicas }}
|
|
selector:
|
|
matchLabels:
|
|
app: migration-controller
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: migration-controller
|
|
spec:
|
|
tolerations:
|
|
- key: "node-role.kubernetes.io/control-plane"
|
|
operator: "Exists"
|
|
effect: "NoSchedule"
|
|
- key: "node-role.kubernetes.io/master"
|
|
operator: "Exists"
|
|
effect: "NoSchedule"
|
|
serviceAccountName: migration-controller
|
|
{{- /*
|
|
A controller whose whole purpose is to keep an import inside the
|
|
restricted Pod Security Standard has no business violating it itself.
|
|
The image is a static binary in a scratch layer, so there is nothing to
|
|
give up here: without these fields the apiserver admits the pod with a
|
|
restricted-violation warning, which is both a bad example and noise in
|
|
every operator's audit log.
|
|
*/}}
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 65532
|
|
runAsGroup: 65532
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: migration-controller
|
|
image: "{{ .Values.migrationController.image }}"
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop: ["ALL"]
|
|
args:
|
|
- --leader-elect
|
|
{{- if .Values.migrationController.metrics.enabled }}
|
|
- --metrics-bind-address={{ .Values.migrationController.metrics.bindAddress }}
|
|
{{- end }}
|
|
{{- if .Values.migrationController.debug }}
|
|
- --zap-log-level=debug
|
|
{{- else }}
|
|
- --zap-log-level=info
|
|
{{- end }}
|
|
env:
|
|
{{- /*
|
|
The VDDK image reference travels as configuration, not as a tenant
|
|
value, and only a reference travels — never a credential. Empty is a
|
|
valid, documented state: the vSphere path then reports itself
|
|
unavailable on each VMImportSource instead of failing mid-transfer.
|
|
*/}}
|
|
- name: MIGRATION_VDDK_IMAGE
|
|
value: {{ .Values.vddkImage | default "" | quote }}
|
|
ports:
|
|
- name: metrics
|
|
containerPort: {{ splitList ":" .Values.migrationController.metrics.bindAddress | mustLast }}
|
|
- name: health
|
|
containerPort: 8081
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /readyz
|
|
port: health
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /healthz
|
|
port: health
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 20
|
|
{{- with .Values.migrationController.resources }}
|
|
resources: {{- . | toYaml | nindent 10 }}
|
|
{{- end }}
|