[platform] Fix VM MAC address not preserved during migration#2169
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue where Virtual Machine MAC addresses were not preserved during the platform migration from v0.41 to v1.0, leading to network connectivity problems for VMs configured with MAC-based network settings. The solution involves enhancing the migration process to automatically inject necessary OVN MAC and IP annotations into the VM's pod template at Helm render time, thereby ensuring consistent network identity across the migration. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
📝 WalkthroughWalkthroughInjects a Helm lookup into the VM template to find a pre-created Kube-OVN IP resource and, if present, add Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request addresses an issue where VM MAC addresses are not preserved during migration, causing network connectivity problems, by using a Flux postRenderers kustomize patch to inject ovn.kubernetes.io/mac_address and ovn.kubernetes.io/ip_address annotations. However, the current approach introduces a critical YAML injection vulnerability in the migration script due to improper escaping of user-influenced data, potentially leading to privilege escalation. It's recommended to use safer methods like jq or yq for YAML manifest construction. Furthermore, an edge case where the IP address might not be preserved if a MAC address is unavailable should be addressed for a more robust solution.
| ovn.kubernetes.io/mac_address: \"${OVN_MAC}\" | ||
| ovn.kubernetes.io/ip_address: \"${OVN_IP}\"" |
There was a problem hiding this comment.
YAML Injection in Migration Script
The newly added POST_RENDERERS block is vulnerable to YAML injection. The script extracts MAC and IP addresses from ip.kubeovn.io resources and interpolates them directly into a string that defines a Flux postRenderers kustomize patch.
Specifically, on lines 494 and 495, ${OVN_MAC} and ${OVN_IP} are used inside double quotes within the patch string. If these values contain a double quote followed by a newline and arbitrary YAML, an attacker can break out of the intended field and inject additional fields or even entire patches into the HelmRelease specification.
Since the migration script is executed with cluster-admin privileges during a platform migration, and MAC addresses can be influenced by users via their VirtualMachine specifications, this allows a tenant to escalate privileges. For example, an attacker could inject a patch that makes their VirtualMachine privileged or mounts host paths, bypassing security isolation.
Remediation:
Avoid using string interpolation to build YAML patches. Instead, use a tool like jq or yq to safely construct the YAML structure, or ensure that the variables are properly escaped for YAML (e.g., using jq -Rs . to escape the strings).
| # Without this, migrated VMs receive a new random MAC address, breaking | ||
| # OS-level network config that matches by MAC (e.g. netplan). | ||
| POST_RENDERERS="" | ||
| if [ -n "$OVN_MAC" ]; then |
There was a problem hiding this comment.
The current logic only creates the postRenderers patch if $OVN_MAC is set. This means if a VM has a static IP ($OVN_IP) but no static MAC, the IP address will not be preserved during the migration. To ensure that the IP address is also preserved in such cases, the condition should be updated to trigger the patch creation if either $OVN_MAC or $OVN_IP is present.
if [ -n "$OVN_MAC" ] || [ -n "$OVN_IP" ]; then
71cf230 to
26d0a7a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/apps/vm-instance/templates/vm.yaml`:
- Around line 37-41: The template is reading the deprecated Kube-OVN field
spec.ipAddress; change the IP selection logic for the
ovn.kubernetes.io/ip_address annotation to prefer spec.v4IpAddress, then
spec.v6IpAddress, and only fall back to spec.ipAddress if neither v4 nor v6 is
present. Locate the variables $ovnIPName and $ovnIP in the vm.yaml template and
update the annotation rendering to choose the first non-empty of
spec.v4IpAddress / spec.v6IpAddress / spec.ipAddress so live-migration preserves
IPs when v4/v6 fields are set.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: bab8d94d-020a-4e02-a24f-d88fb8beddba
📒 Files selected for processing (1)
packages/apps/vm-instance/templates/vm.yaml
| {{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }} | ||
| {{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }} | ||
| {{- if $ovnIP }} | ||
| ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }} | ||
| ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Kube-OVN IP CRD fields:"
sed -n '2507,2585p' packages/system/kubeovn/charts/kube-ovn/templates/kube-ovn-crd.yaml \
| rg -n 'ipAddress|v4IpAddress|v6IpAddress|macAddress'
echo
echo "Current template usage:"
sed -n '35,42p' packages/apps/vm-instance/templates/vm.yamlRepository: cozystack/cozystack
Length of output: 892
Use the canonical Kube-OVN IP field instead of the deprecated ipAddress.
The vendored Kube-OVN CRD marks spec.ipAddress as deprecated and recommends using spec.v4IpAddress or spec.v6IpAddress. Rendering ovn.kubernetes.io/ip_address from the deprecated field risks silently dropping the IP address when ipAddress is empty, even though a valid v4IpAddress exists. This can break IP preservation during VM live migration.
Suggested fix
{{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }}
{{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }}
{{- if $ovnIP }}
ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }}
- ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }}
+ {{- $ovnIPAddress := coalesce $ovnIP.spec.v4IpAddress $ovnIP.spec.ipAddress }}
+ ovn.kubernetes.io/ip_address: {{ $ovnIPAddress | quote }}
{{- end }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }} | |
| {{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }} | |
| {{- if $ovnIP }} | |
| ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }} | |
| ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }} | |
| {{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }} | |
| {{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }} | |
| {{- if $ovnIP }} | |
| ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }} | |
| {{- $ovnIPAddress := coalesce $ovnIP.spec.v4IpAddress $ovnIP.spec.ipAddress }} | |
| ovn.kubernetes.io/ip_address: {{ $ovnIPAddress | quote }} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/apps/vm-instance/templates/vm.yaml` around lines 37 - 41, The
template is reading the deprecated Kube-OVN field spec.ipAddress; change the IP
selection logic for the ovn.kubernetes.io/ip_address annotation to prefer
spec.v4IpAddress, then spec.v6IpAddress, and only fall back to spec.ipAddress if
neither v4 nor v6 is present. Locate the variables $ovnIPName and $ovnIP in the
vm.yaml template and update the annotation rendering to choose the first
non-empty of spec.v4IpAddress / spec.v6IpAddress / spec.ipAddress so
live-migration preserves IPs when v4/v6 fields are set.
…instance migration Kube-OVN reads MAC address exclusively from the pod annotation ovn.kubernetes.io/mac_address, not from the IP resource spec.macAddress. Without pod-level annotations, migrated VMs receive a new random MAC, breaking OS-level network config that matches by MAC (e.g. netplan). Add a Helm lookup for the Kube-OVN IP resource in the vm-instance chart template. When the IP resource exists, its macAddress and ipAddress are automatically injected as pod annotations. This removes the need for fragile Flux postRenderers on the HelmRelease — the chart itself handles MAC/IP preservation based on actual cluster state. Remove the postRenderers approach from migration 29 since the chart now handles this natively. Co-Authored-By: Claude <[email protected]> Signed-off-by: Kirill Ilin <[email protected]>
26d0a7a to
9a4f492
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/apps/vm-instance/templates/vm.yaml (1)
37-41:⚠️ Potential issue | 🟠 MajorPrefer the canonical Kube-OVN IP fields here.
Line 41 still reads the deprecated
spec.ipAddressfield. If the IP CR only hasv4IpAddress/v6IpAddresspopulated, the annotation stays wrong and the migration fix only preserves MAC, not IP.Suggested fix
{{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }} {{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }} {{- if $ovnIP }} ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }} - ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }} + {{- $ovnIPAddress := coalesce $ovnIP.spec.v4IpAddress $ovnIP.spec.v6IpAddress $ovnIP.spec.ipAddress }} + ovn.kubernetes.io/ip_address: {{ $ovnIPAddress | quote }} {{- end }}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/apps/vm-instance/templates/vm.yaml` around lines 37 - 41, The annotation generation uses the deprecated spec.ipAddress field; update the vm.yaml template where $ovnIP is used to set ovn.kubernetes.io/ip_address so it prefers canonical fields (ovnIP.spec.v4IpAddress or ovnIP.spec.v6IpAddress) and falls back to ovnIP.spec.ipAddress only if neither v4/v6 is present, ensuring the annotation is correct for IP CRs that only populate v4IpAddress/v6IpAddress while maintaining backward compatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/apps/vm-instance/templates/vm.yaml`:
- Around line 37-41: The annotation generation uses the deprecated
spec.ipAddress field; update the vm.yaml template where $ovnIP is used to set
ovn.kubernetes.io/ip_address so it prefers canonical fields
(ovnIP.spec.v4IpAddress or ovnIP.spec.v6IpAddress) and falls back to
ovnIP.spec.ipAddress only if neither v4/v6 is present, ensuring the annotation
is correct for IP CRs that only populate v4IpAddress/v6IpAddress while
maintaining backward compatibility.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c5bfb8d2-f868-4e8c-9c8d-62713d321911
📒 Files selected for processing (1)
packages/apps/vm-instance/templates/vm.yaml
|
Successfully created backport PR for |
|
Successfully created backport PR for |
What this PR does
During the virtual-machine → vm-instance migration (script 29), VM MAC addresses
are not preserved. Kube-OVN reads MAC exclusively from the pod annotation
ovn.kubernetes.io/mac_address, not from the IP resourcespec.macAddress.Without the annotation, migrated VMs get a new random MAC, breaking OS-level
network config that matches by MAC (e.g. netplan).
This adds a Helm
lookupfor the Kube-OVN IP resource in the vm-instance charttemplate. When the resource exists, its
macAddressandipAddressareautomatically injected as pod annotations. This approach is reliable across
HelmRelease reconciliations — unlike postRenderers, the annotations cannot be
accidentally lost.
Fixes #2166
Release note
Summary by CodeRabbit