Publish Virtual Machine Image
Publishing a VirtualMachine as a new VM image enables you to capture the current state of a VM and make it available as a reusable image template. VM Operator provides the VirtualMachinePublishRequest API to facilitate this process, allowing you to create custom VM images from running or powered-off VirtualMachines.
Overview
The VirtualMachinePublishRequest API enables you to:
- Capture VM State: Create a snapshot of a VirtualMachine's current configuration and disk state
- Publish to Content Library: Store the captured image in a vSphere Content Library for reuse
- Automate Image Creation: Integrate with tools like Packer for automated image building workflows
- Version Control: Maintain multiple versions of VM images with descriptive metadata
How VM Publishing Works
The VM publishing process follows these steps:
- Request Creation: A VirtualMachinePublishRequest is created specifying the source VM and target location
- Validation: The controller validates that the source VM exists and the target Content Library is accessible
- VM Capture: The VM is captured as an OVF template using vSphere APIs
- Upload: The captured template is uploaded to the specified Content Library
- Image Creation: A new VirtualMachineImage resource is created referencing the published template
- Completion: The request is marked as complete and optionally cleaned up based on TTL settings
VirtualMachinePublishRequest API
Basic Structure
apiVersion: vmoperator.vmware.com/v1alpha5
kind: VirtualMachinePublishRequest
metadata:
name: my-vm-publish-request
namespace: my-namespace
spec:
source:
name: source-vm-name
apiVersion: vmoperator.vmware.com/v1alpha5
kind: VirtualMachine
target:
item:
name: my-custom-image
description: "Custom VM image created from my-vm"
location:
name: my-content-library
apiVersion: imageregistry.vmware.com/v1alpha1
kind: ContentLibrary
ttlSecondsAfterFinished: 3600
Field Reference
Source Configuration
source.name: Name of the VirtualMachine to publish (defaults to the VirtualMachinePublishRequest name)source.apiVersion: API version of the source object (default:vmoperator.vmware.com/v1alpha5)source.kind: Kind of the source object (default:VirtualMachine)
Target Configuration
target.item.name: Display name for the published image (defaults to{source.name}-image)target.item.description: Optional description for the published imagetarget.location.name: Name of the target ContentLibrary resourcetarget.location.apiVersion: API version of the target (default:imageregistry.vmware.com/v1alpha1)target.location.kind: Kind of the target (default:ContentLibrary)
TTL Configuration
ttlSecondsAfterFinished: Time-to-live for the request after completion (optional)
Examples
Basic VM Publishing
apiVersion: vmoperator.vmware.com/v1alpha5
kind: VirtualMachinePublishRequest
metadata:
name: ubuntu-golden-image
namespace: default
spec:
source:
name: ubuntu-vm-template
target:
item:
name: ubuntu-22.04-golden
description: "Ubuntu 22.04 golden image with security patches"
location:
name: default-content-library
Publishing with Automatic Cleanup
apiVersion: vmoperator.vmware.com/v1alpha5
kind: VirtualMachinePublishRequest
metadata:
name: temp-build-publish
namespace: ci-cd
spec:
source:
name: build-vm
target:
item:
name: app-server-v2.1.0
description: "Application server image v2.1.0"
location:
name: production-images
ttlSecondsAfterFinished: 300 # Clean up after 5 minutes
Minimal Configuration (Using Defaults)
apiVersion: vmoperator.vmware.com/v1alpha5
kind: VirtualMachinePublishRequest
metadata:
name: web-server
namespace: default
# Uses defaults:
# - source.name: web-server (same as metadata.name)
# - target.item.name: web-server-image
# - target.location: ContentLibrary with label "imageregistry.vmware.com/default"
Integration with Packer
VM Operator integrates seamlessly with HashiCorp Packer's vSphere Supervisor builder, enabling automated image building workflows.
Packer Configuration Example
source "vsphere-supervisor" "ubuntu-image" {
# Source image configuration
image_name = "ubuntu-22.04-base"
class_name = "best-effort-large"
storage_class = "wcplocal-storage-profile"
# Bootstrap configuration for guest customization
bootstrap_provider = "CloudInit"
bootstrap_data_file = "cloud-init-config.yaml"
# Publish configuration
publish_location_name = "golden-images-library"
}
build {
sources = ["source.vsphere-supervisor.ubuntu-image"]
# Provisioning steps
provisioner "shell" {
scripts = [
"scripts/install-security-updates.sh",
"scripts/install-monitoring-agent.sh",
"scripts/cleanup.sh"
]
}
# Post-processing
post-processor "manifest" {
output = "manifest.json"
}
}
Bootstrap Provider Support
The Packer vSphere Supervisor builder supports all VM Operator bootstrap providers:
CloudInit Bootstrap
source "vsphere-supervisor" "linux-vm" {
bootstrap_provider = "CloudInit"
bootstrap_data_file = "cloud-init.yaml"
# ... other configuration
}
Sysprep Bootstrap (Windows)
source "vsphere-supervisor" "windows-vm" {
bootstrap_provider = "Sysprep"
bootstrap_data_file = "sysprep.xml"
# ... other configuration
}
vAppConfig Bootstrap
source "vsphere-supervisor" "appliance-vm" {
bootstrap_provider = "vAppConfig"
bootstrap_data_file = "vapp-properties.json"
# ... other configuration
}
Status and Monitoring
Checking Publication Status
# Check the status of a publish request
kubectl get vmpub ubuntu-golden-image -o yaml
# Watch the progress
kubectl get vmpub ubuntu-golden-image -w
Status Conditions
The VirtualMachinePublishRequest reports its progress through status conditions:
SourceValid: Source VM exists and is accessibleTargetValid: Target Content Library exists and is accessibleUploaded: VM has been successfully uploaded to the Content LibraryImageAvailable: VirtualMachineImage resource has been createdComplete: All operations completed successfully
Example Status
status:
ready: true
imageName: ubuntu-22.04-golden
startTime: "2024-01-15T10:00:00Z"
completionTime: "2024-01-15T10:15:00Z"
attempts: 1
conditions:
- type: SourceValid
status: "True"
lastTransitionTime: "2024-01-15T10:00:30Z"
- type: TargetValid
status: "True"
lastTransitionTime: "2024-01-15T10:01:00Z"
- type: Uploaded
status: "True"
lastTransitionTime: "2024-01-15T10:12:00Z"
- type: ImageAvailable
status: "True"
lastTransitionTime: "2024-01-15T10:14:00Z"
- type: Complete
status: "True"
lastTransitionTime: "2024-01-15T10:15:00Z"
Best Practices
VM Preparation
- Power Off VMs: While publishing powered-on VMs is supported, powering off ensures consistency
- Clean Up Temporary Files: Remove logs, temporary files, and sensitive data before publishing
- Generalize the Image: Remove machine-specific configurations (hostnames, SSH keys, etc.)
- Install VMware Tools: Ensure VMware Tools are installed for optimal performance
Content Library Management
- Use Descriptive Names: Choose meaningful names for published images
- Add Metadata: Include comprehensive descriptions and version information
- Organize by Purpose: Use separate Content Libraries for different image types (base images, application images, etc.)
- Regular Cleanup: Remove unused images to manage storage consumption
Automation Considerations
- Use TTL: Set appropriate
ttlSecondsAfterFinishedvalues for automated workflows - Monitor Progress: Implement proper status checking in CI/CD pipelines
- Handle Failures: Plan for retry logic and error handling
- Version Control: Maintain consistent naming conventions for image versions
Troubleshooting
Common Issues
Source VM Not Found
conditions:
- type: SourceValid
status: "False"
reason: "SourceNotFound"
message: "VirtualMachine 'missing-vm' not found in namespace 'default'"
Solution: Verify the source VM name and namespace are correct.
Target Content Library Unavailable
conditions:
- type: TargetValid
status: "False"
reason: "TargetLocationNotFound"
message: "ContentLibrary 'missing-library' not found"
Solution: Ensure the ContentLibrary resource exists and is accessible.
Upload Failures
conditions:
- type: Uploaded
status: "False"
reason: "UploadFailure"
message: "Failed to upload VM to content library: insufficient storage"
Solution: Check Content Library storage capacity and vCenter connectivity.
Debugging Commands
# Get detailed status
kubectl describe vmpub my-publish-request
# Check related VirtualMachineImage
kubectl get vmi -l "virtualmachinepublishrequest.vmoperator.vmware.com/name=my-publish-request"
# View controller logs
kubectl logs -n vmware-system-vmop deployment/vmware-system-vmop-controller-manager
Related Resources
- VirtualMachine Images - Learn about VM image management
- Content Libraries - vSphere Content Library documentation
- Packer vSphere Supervisor Builder - Packer integration guide