PowerVS v1beta2 to v1beta3 Migration Guide
Overview
This guide helps you migrate from v1beta2 to v1beta3 PowerVS APIs. The v1beta3 API introduces significant improvements based on Kubernetes API best practices, including enhanced type safety, explicit intent declaration, and better GitOps compatibility.
Table of Contents
| # | Section | Resource |
|---|---|---|
| 1 | Cluster Topology | IBMPowerVSCluster |
| 2 | Zone and Resource Group | IBMPowerVSCluster |
| 3 | Workspace Configuration | IBMPowerVSCluster |
| 4 | Network Configuration | IBMPowerVSCluster |
| 5 | TransitGateway Configuration | IBMPowerVSCluster |
| 6 | VPC Configuration | IBMPowerVSCluster |
| 7 | VPC Subnet Configuration | IBMPowerVSCluster |
| 8 | LoadBalancer Configuration | IBMPowerVSCluster |
| 9 | VPC Security Groups Configuration | IBMPowerVSCluster |
| 10 | COS Instance Configuration | IBMPowerVSCluster |
| 11 | Ignition Configuration | IBMPowerVSCluster |
| 12 | IBMPowerVSMachine Configuration | IBMPowerVSMachine |
| 13 | IBMPowerVSImage Configuration | IBMPowerVSImage |
| 14 | Status Field Changes | All resources |
| 15 | Conversion Webhook | All resources |
What’s Changed
The v1beta3 API introduces several major improvements across PowerVS resources. This guide documents the changes for:
- IBMPowerVSCluster - Topology, Zone, Resource Group, Workspace, Network, TransitGateway, VPC, VPC Subnets, LoadBalancers, VPC Security Groups, COS Instance, and Ignition configuration
- IBMPowerVSMachine - Workspace, Network, Image (Reference/Import), SSH Key, System Type, Processor Type, Processors, Memory, and ProviderID
- IBMPowerVSImage - Workspace, Bucket, Object, Region, Storage Type (typed enum), and Delete Policy (typed enum)
Each section below provides detailed before/after examples and migration guidance.
1. Cluster Topology
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
annotations:
powervs.cluster.x-k8s.io/create-infra: "true" # Annotation-based
spec:
# Configuration implied by annotation
v1beta3 (New)
Option A: VirtualIP Topology (PowerVS)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
topology: VirtualIP # Explicit topology declaration
# No VPC/LoadBalancer configuration needed
Option B: LoadBalancer Topology (PowerVS + VPC)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
topology: LoadBalancer # Explicit topology declaration
zone: "wdc06" # Required for LoadBalancer topology
resourceGroup:
type: Reference
reference:
name: "my-resource-group" # Required for LoadBalancer topology
vpc:
type: Provision
region: "us-east"
# LoadBalancer will be automatically created
Key Points:
- The
topologyfield replaces the annotation-based approach. VirtualIPtopology: PowerVS network with Virtual IP.LoadBalancertopology: Integrates PowerVS with VPC and LoadBalancer.- The topology is explicit, required, and discoverable via
kubectl explain. - VirtualIP constraints (CEL-enforced): When
topology: VirtualIP,workspacemust betype: Reference,networkmust betype: Reference, andtransitGatewaymust not be set. - LoadBalancer constraints (CEL-enforced): When
topology: LoadBalancer, bothzoneandresourceGroup(withidorname) are required.
2. Zone and Resource Group (Data Type Enhancements)
In v1beta3, structural data types have been flattened to comply with standard Kubernetes API guidelines and prevent runtime errors.
v1beta2 (Deprecated)
In v1beta2, Zone and ResourceGroup used Go pointers (*string and *ResourceReference). This occasionally caused nil-pointer panics in the controller and required complex webhook validations.
# v1beta2 — zone as *string, resourceGroup as *IBMPowerVSResourceReference
spec:
zone: "wdc06"
resourceGroup:
id: "my-rg-id"
name: "my-resource-group"
v1beta3 (New)
In v1beta3, pointers have been removed in favor of strict value types and a structured ResourceGroupSource.
# v1beta3 — zone as plain string, resourceGroup as ResourceGroupSource
spec:
zone: "wdc06"
resourceGroup:
type: Reference # Only "Reference" is currently supported
reference:
id: "my-rg-id"
# OR use name
# name: "my-resource-group"
Key Points:
- Pointer-Free Zone:
zoneis now a standardstring, preventing nil-pointer exceptions. - Zone is immutable: Once set,
zonecannot be changed (CEL immutability rule). - ResourceGroupSource:
resourceGroupnow uses a structuredResourceGroupSourcetype withtypeandreferencefields. - Only
type: Referenceis supported forresourceGroup(provisioning a resource group via the API is not supported). - Conditional Validation: If
topology: LoadBalancer, CEL rules strictly enforce that bothzoneandresourceGroupare provided and non-empty. - Graceful Omission: If
topology: VirtualIP,zoneandresourceGroupcan be safely omitted.
3. Workspace Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
serviceInstanceID: "3229a94c-af54-4212-bf60-6202b6fd0a07" # Deprecated flat field
# OR the newer (but still v1beta2) form:
serviceInstance:
id: "3229a94c-af54-4212-bf60-6202b6fd0a07"
# OR
name: "my-existing-workspace"
v1beta3 (New)
Option A: Reference an Existing Workspace
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
workspace:
type: Reference
reference:
id: "3229a94c-af54-4212-bf60-6202b6fd0a07"
# OR use name instead of id
# name: "my-existing-workspace"
Option B: Provision a New Workspace
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
workspace:
type: Provision
provision:
name: "my-new-workspace" # Optional: defaults to <cluster-name>-workspace
Key Points:
- Both
serviceInstanceID(deprecated flat field) andserviceInstanceare replaced by theworkspacefield. - The
typefield explicitly declares your intent (ReferenceorProvision). - Workspace type is immutable: Once set,
workspace.typecannot be changed. - Use
reference.idorreference.nameto identify existing workspaces; exactly one must be specified (CEL-enforced). - When provisioning, the workspace name is optional and defaults to
<cluster-name>-workspace. - The controller will only delete workspaces it created (when
type: Provision).
4. Network Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
network:
name: "capi-test"
dhcpServer:
name: "DHCPSERVER-capi-test"
cidr: "192.168.0.0/24" # *string pointer
dnsServer: "8.8.8.8" # *string pointer, default "1.1.1.1"
snat: true # *bool pointer, default true
id: "existing-dhcp-server-id" # optional: reference existing DHCP server
v1beta3 (New)
Option A: Reference an Existing Network
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
network:
type: Reference
reference:
name: "capi-test"
# OR use id instead of name
# id: "network-id-12345"
Option B: Provision a New Network with DHCP Server
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
network:
type: Provision
provision:
dhcpServer:
name: "my-dhcp-server" # Optional: defaults to DHCPSERVER<cluster-name>_Private
cidr: "192.168.0.0/24" # Optional: plain string (no longer a pointer)
dnsServer: "8.8.8.8" # Optional: plain string (no longer a pointer)
snat: Enabled # Enum: Enabled or Disabled (default: Enabled)
Key Points:
- The
typefield explicitly declares whether to use an existing or create a new network. - Network type is immutable: Once set,
network.typecannot be changed. - The top-level
dhcpServerfield is removed; DHCP configuration is nested undernetwork.provision.dhcpServer. - SNAT is now an enum (
Enabled/Disabled) instead of a*boolpointer. - All DHCP fields (
name,cidr,dnsServer) are plainstringvalues instead of pointers. - The
idfield on DHCPServer (to reference an existing server) has been removed; usenetwork.type: Referenceinstead. - DHCP server configuration is only valid when
type: Provision. - The controller will only delete networks it created.
5. TransitGateway Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
transitGateway:
name: "my-transit-gateway" # OR use id
id: "tgw-id-123"
globalRouting: true # *bool pointer — true = Global, false = Local
v1beta3 (New)
Option A: Reference an Existing Transit Gateway
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
transitGateway:
type: Reference
reference:
id: "tgw-id-123"
# OR use name instead of id
# name: "my-transit-gateway"
Option B: Provision a New Transit Gateway
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
transitGateway:
type: Provision
provision:
name: "my-transit-gateway" # Optional: defaults to <cluster-name>-tgw
globalRouting: Global # Enum: Local or Global (auto-detected if omitted)
# Optionally control how VPC/PowerVS connections are sourced
vpcConnection:
type: Provision
provision:
name: "my-vpc-connection" # Optional: name for the VPC connection
powerVSConnection:
type: Provision
provision:
name: "my-powervs-connection" # Optional: name for the PowerVS connection
Option C: Reference Existing Connections within a Provisioned Transit Gateway
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
transitGateway:
type: Provision
provision:
name: "my-transit-gateway"
globalRouting: Local
vpcConnection:
type: Reference
reference:
id: "existing-vpc-connection-id"
powerVSConnection:
type: Reference
reference:
id: "existing-pvs-connection-id"
Key Points:
- The
typefield (Reference/Provision) replaces the flatname/idstruct. globalRoutingis now an enum (Local/Global) instead of a*bool.- When
globalRoutingis omitted, the system automatically selects routing based on PowerVS and VPC regions. - Individual connections (
vpcConnection,powerVSConnection) can each independently reference an existing connection or provision a new one. TransitGatewayConnectionSourceincludes bothtype,reference, andprovision.namefields.- The controller only deletes Transit Gateways and connections it created (
type: Provision).
6. VPC Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpc:
id: "vpc-id-123" # OR use name
name: "my-vpc"
region: "us-east" # Required only when create-infra annotation is set
v1beta3 (New)
Option A: Reference an Existing VPC
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpc:
type: Reference
region: "us-east" # Always required in v1beta3
reference:
id: "vpc-id-123"
# OR use name instead of id
# name: "my-vpc"
Option B: Provision a New VPC
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpc:
type: Provision
region: "us-east" # Always required in v1beta3
provision:
name: "my-new-vpc" # Optional: defaults to <cluster-name>-vpc
Key Points:
type(Reference/Provision) is now required and replaces the implicit behavior of v1beta2.regionis always required in v1beta3 (was only required under the create-infra annotation in v1beta2).- The
typefield is immutable once set. - The controller only deletes VPCs it created (
type: Provision).
7. VPC Subnet Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpcSubnets:
- name: "my-subnet"
id: "subnet-id-123" # *string pointer
zone: "us-east-1" # *string pointer
cidr: "10.0.0.0/24" # *string pointer (IPv4 CIDR block)
v1beta3 (New)
Option A: Reference Existing Subnets
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
subnets: # Field renamed from vpcSubnets to subnets
- type: Reference
zone: "us-east-1" # Optional: plain string (no longer a pointer)
reference:
id: "subnet-id-123"
# OR use name instead of id
# name: "my-subnet"
Option B: Provision New Subnets
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
subnets:
- type: Provision
zone: "us-east-1" # Optional: random zone picked if omitted
provision:
name: "my-subnet" # Optional: defaults to <cluster-name>-vpcsubnet-<INDEX>
Key Points:
- The field was renamed from
vpcSubnetstosubnets. - Each entry now requires a
typefield (Reference/Provision). - The
cidrfield from the v1beta2Subnetstruct has been removed in v1beta3. - All fields (
id,name,zone) are plain value types, not pointers. - When
type: Provisionandzoneis omitted, a random zone is selected from those available in the VPC region. - The controller only deletes subnets it created (
type: Provision).
8. LoadBalancer Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
loadBalancers:
- name: "my-lb"
id: "lb-id-123" # *string pointer
public: true # *bool pointer — true = public, false = private
additionalListeners:
- port: 443
protocol: TCP
defaultPoolName: "my-pool" # *string pointer
selector:
matchLabels:
role: worker
backendPools:
- name: "my-pool" # *string pointer
algorithm: round_robin
protocol: tcp
healthMonitor:
delay: 10
retries: 3
timeout: 5
type: tcp
port: 8080 # *int64 pointer (optional)
urlPath: "/healthz" # *string pointer (optional)
securityGroups:
- id: "sg-id-123"
name: "my-sg" # VPCResource struct with *string fields
subnets:
- id: "subnet-id-123"
name: "my-subnet" # VPCResource struct with *string fields
v1beta3 (New)
Option A: Reference an Existing Load Balancer
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
loadBalancers:
- type: Reference
reference:
id: "lb-id-123"
# OR use name instead of id
# name: "my-lb"
Option B: Provision a New Load Balancer
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
loadBalancers:
- type: Provision
provision:
name: "my-lb" # Optional: defaults to <cluster-name>-loadbalancer
type: Public # Enum: Public or Private (default: Public)
additionalListeners:
- port: 443
protocol: tcp
defaultPoolName: "my-pool" # plain string (no longer a pointer)
selector:
matchLabels:
role: worker
backendPools:
- name: "my-pool" # plain string (no longer a pointer)
algorithm: round_robin
protocol: tcp
healthMonitor:
delay: 10
retries: 3
timeout: 5
type: tcp
port: 8080 # plain int64 (no longer a pointer)
urlPath: "/healthz" # plain string (no longer a pointer)
securityGroups:
- id: "sg-id-123" # ResourceIdentifier: id or name (plain strings)
subnets:
- name: "my-subnet" # ResourceIdentifier: id or name (plain strings)
Key Points:
type(Reference/Provision) is now required at the top level of each entry.- The flat
id/namefields on a LoadBalancer entry have moved intoreference(whentype: Reference). - The
publicfield (*bool) is replaced byprovision.typeenum (Public/Private), defaulting toPublic. securityGroupsandsubnetsnow useResourceIdentifier(plainstringfields) instead of the v1beta2VPCResourcestruct (pointer fields).additionalListeners[].defaultPoolNamechanged from*string(pointer) to a plainstring.additionalListeners[].protocolchanged from*VPCLoadBalancerListenerProtocol(pointer) toLoadBalancerListenerProtocol(value).backendPools[].namechanged from*string(pointer) to a plainstring.healthMonitor.portchanged from*int64(pointer) to a plainint64.healthMonitor.urlPathchanged from*string(pointer) to a plainstring.- The controller only deletes load balancers it created (
type: Provision).
9. VPC Security Groups Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpcSecurityGroups:
- id: "sg-id-123" # *string pointer
name: "my-sg" # *string pointer
rules:
- direction: inbound
destination:
protocol: tcp
portRange:
minimumPort: 443
maximumPort: 443
remotes:
- remoteType: cidr
cidrSubnetName: "my-subnet" # *string pointer
securityGroupID: "sg-id-123" # *string pointer
tags:
- "env:prod" # []*string slice of pointers
v1beta3 (New)
Option A: Reference an Existing Security Group
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpcSecurityGroups:
- type: Reference
reference:
id: "sg-id-123"
# OR use name
# name: "my-sg"
Option B: Provision a New Security Group
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
vpcSecurityGroups:
- type: Provision
provision:
name: "my-sg"
tags:
- "env:prod" # []string (no longer []*string)
rules:
- direction: inbound
destination:
protocol: tcp
portRange:
minimumPort: 443
maximumPort: 443
remotes:
- remoteType: cidr
cidrSubnetName: "my-subnet" # plain string (no longer a pointer)
securityGroupID: "sg-id-123" # plain string (no longer a pointer)
Key Points:
vpcSecurityGroupsnow usesVPCSecurityGroupSourcewithtype/reference/provisionfields.VPCSecurityGroup.idandVPCSecurityGroup.namewere*stringpointers; nowResourceIdentifieruses plainstringvalues.VPCSecurityGroupProvision.tagschanged from[]*stringto[]string.VPCSecurityGroupRule.securityGroupIDchanged from*stringto a plainstring.VPCSecurityGroupRule.destination/.sourcechanged from*VPCSecurityGroupRulePrototype(pointer) toVPCSecurityGroupRulePrototype(value).VPCSecurityGroupRuleRemotestring fields (cidrSubnetName,address,securityGroupName) changed from*stringpointers to plainstringvalues.
10. COS Instance Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
cosInstance:
name: "my-cos-instance" # Required when create-infra annotation is set and Ignition is used
bucketName: "my-bucket" # Required when create-infra annotation is set and Ignition is used
bucketRegion: "us-south" # Required when create-infra annotation is set and Ignition is used
v1beta3 (New)
Option A: Reference an Existing COS Instance
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
cosInstance:
type: Reference
bucketName: "my-bucket" # Required in both Reference and Provision
bucketRegion: "us-south" # Required in both Reference and Provision
reference:
id: "cos-instance-id"
# OR use name
# name: "my-cos-instance"
Option B: Provision a New COS Instance
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
cosInstance:
type: Provision
bucketName: "my-bucket"
bucketRegion: "us-south"
provision:
name: "my-cos-instance" # Optional: name for the COS instance to create
Key Points:
cosInstancenow usesCOSInstanceSourcewith atype/reference/provisionstructure, consistent with other resources.bucketNameandbucketRegionare shared fields present at the top level ofCOSInstanceSource(required regardless of type).- The flat v1beta2
CosInstancestruct (withname,bucketName,bucketRegion) is replaced by this structured form. - The controller only deletes COS instances it created (
type: Provision).
11. Ignition Configuration
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
ignition:
version: "3.4" # +kubebuilder:default="2.3", enum: "2.3","2.4","3.0","3.1","3.2","3.3","3.4"
v1beta3 (New)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSCluster
metadata:
name: my-cluster
spec:
ignition:
version: "3.4" # enum: "2.3","2.4","3.0","3.1","3.2","3.3","3.4"
Key Points:
- The
Ignitionstruct has the same shape in both versions. - The
versionfield retains the same enum values. - In v1beta3, the type is now a plain value (not a pointer), consistent with the pointer-free API philosophy.
- CEL validation: If
ignitionis set,cosInstancemust also be configured (required by CEL rule).
12. IBMPowerVSMachine Configuration
The v1beta2 IBMPowerVSMachine spec had several structural issues: dual workspace references (serviceInstanceID + serviceInstance), dual image references (image + imageRef), and pointer-based identifiers. v1beta3 unifies all of these.
12.1 Complete Spec Comparison
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSMachine
metadata:
name: my-machine
spec:
# Workspace — two redundant fields:
serviceInstanceID: "workspace-id-123" # Deprecated flat field
serviceInstance: # Newer but still v1beta2 form
id: "workspace-id-123"
# OR: name: "my-workspace"
# OR: regex: "workspace-.*" # regex supported in v1beta2
# Image — two redundant fields:
image: # Direct PowerVS image reference
id: "image-id-123"
# OR: name: "rhcos-4.14"
# OR: regex: "rhcos-.*" # regex supported in v1beta2
imageRef: # Indirect reference via IBMPowerVSImage CRD
name: "my-ibmpowervsimage"
# Network
network:
id: "network-id-123"
# OR: name: "my-network"
# OR: regex: "network-.*" # regex supported in v1beta2
# SSH Key
sshKey: "my-ssh-key"
# System Type
# +kubebuilder:validation:Enum:="s922";"e980";"s1022";"e1050";"e1080";""
systemType: "s922"
# Processor Type
# +kubebuilder:validation:Enum:="Dedicated";"Shared";"Capped";""
processorType: "Shared"
# Processors (int or string for fractional values)
processors: "0.25"
# Memory (GiB)
memoryGiB: 4
# ProviderID
providerID: "ibmpowervs://us-south/my-workspace/my-instance-id" # *string pointer
v1beta3 (New)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSMachine
metadata:
name: my-machine
spec:
# Workspace — single unified field using ResourceIdentifier (id or name, exactly one)
workspace:
id: "workspace-id-123"
# OR (not both): name: "my-workspace"
# If omitted, workspace is inherited from IBMPowerVSCluster
# Image — single unified field with explicit type
image:
type: Reference # Use an existing PowerVS image
reference:
id: "image-id-123"
# OR (not both): name: "rhcos-4.14"
# OR: import via IBMPowerVSImage CRD
# image:
# type: Import
# import:
# name: "my-ibmpowervsimage" # name of the IBMPowerVSImage CRD resource
# Network — uses ResourceIdentifier (id or name, exactly one)
network:
id: "network-id-123"
# OR (not both): name: "my-network"
# If omitted, network is inherited from IBMPowerVSCluster
# SSH Key — unchanged
sshKey: "my-ssh-key"
# System Type — pattern-based validation (no longer a strict enum)
# Pattern: ^[a-z][0-9]+$ (e.g. s922, e980, s1022, s1122, e1050, e1080)
systemType: "s922"
# Processor Type — same enum values
# +kubebuilder:validation:Enum:="Dedicated";"Shared";"Capped";""
processorType: "Shared"
# Processors — unchanged (int or string for fractional values)
processors: "0.25"
# Memory — unchanged
memoryGiB: 4
# ProviderID — now a plain string (no longer a *string pointer)
providerID: "ibmpowervs://us-south/my-workspace/my-instance-id"
12.2 Workspace Reference
v1beta2 (Deprecated)
spec:
serviceInstanceID: "workspace-id-123" # Deprecated flat string
# OR
serviceInstance:
id: "workspace-id-123"
# OR: name: "my-workspace"
# OR: regex: "workspace-.*" # regex supported in v1beta2
v1beta3 (New)
spec:
workspace:
id: "workspace-id-123"
# OR (not both)
# name: "my-workspace"
Key Points:
- Both
serviceInstanceIDandserviceInstanceare replaced by the singleworkspacefield. - Uses
ResourceIdentifiertype withidorname(exactly one must be set; CEL-enforced). regexis not supported in v1beta3ResourceIdentifier; useidornameonly.- If omitted, workspace is inherited from the associated IBMPowerVSCluster.
12.3 Image Reference
v1beta2 (Deprecated)
spec:
# Option 1: Reference an existing PowerVS image directly
image:
id: "image-id-123"
name: "rhcos-4.14"
# Option 2: Reference via IBMPowerVSImage CRD (mutually exclusive with image above)
imageRef:
name: "my-ibmpowervsimage"
v1beta3 (New)
spec:
# Option 1: Reference an existing PowerVS image (id or name, exactly one)
image:
type: Reference
reference:
id: "image-id-123"
# OR (not both): name: "rhcos-4.14"
# Option 2: Import via IBMPowerVSImage CRD
image:
type: Import
import:
name: "my-ibmpowervsimage" # name of the IBMPowerVSImage CRD resource
Key Points:
- The dual
image/imageReffields are unified into a singleimagefield with an explicittype. type: Referencereplaces the v1beta2imagefield.type: Importreplaces the v1beta2imageReffield.- CEL validation ensures
referenceis present whentype: Referenceandimportis present whentype: Import. imageis a required field in v1beta3.
12.4 Network Reference
v1beta2 (Deprecated)
spec:
network: # Required field in v1beta2
id: "network-id-123"
# OR: name: "my-network"
# OR: regex: "network-.*" # regex supported in v1beta2
v1beta3 (New)
spec:
network: # Optional field in v1beta3
id: "network-id-123"
# OR (not both): name: "my-network"
Key Points:
- The
networkfield usesResourceIdentifier— the same type as other identifiers in v1beta3. networkis now optional in v1beta3 (was required in v1beta2); if omitted, the network is inherited from the cluster.- Supports
idorname(exactly one must be set; CEL-enforced).regexis not supported in v1beta3.
12.5 ProviderID
v1beta2 (Deprecated)
spec:
providerID: "ibmpowervs://us-south/my-workspace/my-instance-id" # *string (pointer)
v1beta3 (New)
spec:
providerID: "ibmpowervs://us-south/my-workspace/my-instance-id" # string (value)
Key Points:
providerIDchanged from*string(pointer) to a plainstring.
12.6 Machine Status Changes
v1beta2 Status
status:
ready: true # bool
instanceID: "my-instance-id"
addresses:
- type: InternalIP
address: "192.168.0.10"
health: "OK"
instanceState: "ACTIVE"
fault: "some fault message" # Removed in v1beta3
failureReason: "..." # Deprecated, removed in v1beta3
failureMessage: "..." # Deprecated, removed in v1beta3
region: "us-south" # *string pointer
zone: "us-south-1" # *string pointer
conditions:
- type: Ready
status: "True"
v1beta2:
conditions:
- type: Ready
status: "True"
v1beta3 Status
status:
conditions:
- type: Ready # Promoted to top-level []metav1.Condition
status: "True"
initialization:
provisioned: true # Replaces the ready bool field
instanceID: "my-instance-id"
addresses:
- type: InternalIP
address: "192.168.0.10"
health: "OK"
instanceState: "ACTIVE"
region: "us-south" # plain string (no longer a pointer)
zone: "us-south-1" # plain string (no longer a pointer)
deprecated:
v1beta2:
conditions: # Deprecated v1beta1-style conditions
- type: Ready
status: "True"
Key Points:
ready boolis replaced byinitialization.provisioned *bool.fault,failureReason,failureMessagehave been removed.regionandzonechanged from*stringpointers to plainstringvalues.- Top-level
conditionsare now[]metav1.Condition(metav1 structured conditions). - Old-style
Conditions(clusterv1beta1) are moved todeprecated.v1beta2.conditions.
13. IBMPowerVSImage Configuration
13.1 Complete Spec Comparison
v1beta2 (Deprecated)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: IBMPowerVSImage
metadata:
name: my-image
namespace: default
spec:
clusterName: "my-cluster"
# Workspace — two redundant fields:
serviceInstanceID: "workspace-id-123" # Deprecated flat field
serviceInstance: # Newer but still v1beta2 form
id: "workspace-id-123"
# OR: name: "my-workspace"
# COS Source
bucket: "my-cos-bucket" # *string pointer, required
object: "rhcos-image.ova.gz" # *string pointer, required
region: "us-south" # *string pointer, required
# Storage Type — plain string with enum validation
# +kubebuilder:default=tier1
# +kubebuilder:validation:Enum=tier0;tier1;tier3
storageType: "tier1"
# Delete Policy — plain string with enum validation
# +kubebuilder:default=delete
# +kubebuilder:validation:Enum=delete;retain
deletePolicy: "delete"
v1beta3 (New)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta3
kind: IBMPowerVSImage
metadata:
name: my-image
namespace: default
spec:
clusterName: "my-cluster" # plain string with MinLength/MaxLength validation
# Workspace — single unified ResourceIdentifier field
workspace:
id: "workspace-id-123"
# OR: name: "my-workspace"
# If omitted, workspace is derived from the IBMPowerVSCluster status
# COS Source — now plain strings (no longer *string pointers)
bucket: "my-cos-bucket" # plain string, required
object: "rhcos-image.ova.gz" # plain string, required
region: "us-south" # plain string, required
# Storage Type — now a typed enum (PowerVSStorageType)
# Values: tier0, tier1, tier3
storageType: tier1
# Delete Policy — now a typed enum (PowerVSImageDeletePolicy)
# Values: delete, retain
deletePolicy: delete
13.2 Workspace Reference
v1beta2 (Deprecated)
spec:
serviceInstanceID: "workspace-id-123" # Deprecated flat string
# OR
serviceInstance:
id: "workspace-id-123"
name: "my-workspace"
v1beta3 (New)
spec:
workspace:
id: "workspace-id-123"
# OR
name: "my-workspace"
Key Points:
- Both
serviceInstanceIDandserviceInstanceare replaced by the singleworkspacefield usingResourceIdentifier. - If
workspaceis omitted, the workspace is automatically derived from the associated IBMPowerVSCluster’s status.
13.3 COS Source Fields
v1beta2 (Deprecated)
spec:
bucket: "my-cos-bucket" # *string pointer
object: "rhcos-image.ova.gz" # *string pointer
region: "us-south" # *string pointer
v1beta3 (New)
spec:
bucket: "my-cos-bucket" # plain string, MinLength=1, MaxLength=63
object: "rhcos-image.ova.gz" # plain string, MinLength=1, MaxLength=1024
region: "us-south" # plain string, MinLength=1, MaxLength=32
Key Points:
- All three COS fields changed from
*stringpointers to plainstringvalues. - v1beta3 adds explicit
MinLength/MaxLengthvalidation markers on each field.
13.4 StorageType and DeletePolicy
v1beta2 (Deprecated)
spec:
storageType: "tier1" # plain string — validated by +kubebuilder:validation:Enum=tier0;tier1;tier3
deletePolicy: "delete" # plain string — validated by +kubebuilder:validation:Enum=delete;retain
v1beta3 (New)
spec:
storageType: tier1 # PowerVSStorageType — a named Go type: tier0 | tier1 | tier3
deletePolicy: delete # PowerVSImageDeletePolicy — a named Go type: delete | retain
Key Points:
storageTypechanged from an untypedstringto the named typePowerVSStorageType.deletePolicychanged from an untypedstringto the named typePowerVSImageDeletePolicy.- The allowed values remain the same (
tier0,tier1,tier3anddelete,retainrespectively). - Typed enums provide better discoverability via
kubectl explainand improved code safety.
13.5 Image Status Changes
v1beta2 Status
status:
ready: true # bool
imageID: "image-id-123"
imageState: "active"
jobID: "job-id-123"
conditions:
- type: Ready
status: "True"
v1beta2:
conditions:
- type: Ready
status: "True"
v1beta3 Status
status:
conditions:
- type: Ready # Promoted to top-level []metav1.Condition
status: "True"
imageID: "image-id-123" # with MinLength/MaxLength validation
imageState: "active" # with MinLength/MaxLength validation
jobID: "job-id-123" # with MinLength/MaxLength validation
deprecated:
v1beta2:
conditions: # Deprecated v1beta1-style conditions
- type: Ready
status: "True"
Key Points:
ready boolis removed; readiness is conveyed throughconditions.- Top-level
conditionsare now[]metav1.Condition. - Old-style
Conditionsmoved todeprecated.v1beta2.conditions. imageID,imageState, andjobIDnow have explicitMinLength/MaxLengthvalidation markers.
14. Status Field Changes
IBMPowerVSCluster v1beta2 Status
status:
ready: false # bool
resourceGroupID:
id: "rg-id"
controllerCreated: true # *bool pointer
serviceInstance:
id: "workspace-id"
controllerCreated: true
network:
id: "network-id"
controllerCreated: true
dhcpServer:
id: "dhcp-id"
controllerCreated: true
vpc:
id: "vpc-id"
controllerCreated: true
vpcSubnet: # map[string]ResourceReference
us-east-1:
id: "subnet-id"
controllerCreated: true
vpcSecurityGroups: # map[string]VPCSecurityGroupStatus
my-sg:
id: "sg-id"
ruleIDs: ["rule-id-1"]
controllerCreated: true
transitGateway:
id: "tgw-id"
controllerCreated: true
vpcConnection:
id: "conn-id"
controllerCreated: true
powerVSConnection:
id: "conn-id"
controllerCreated: true
cosInstance:
id: "cos-id"
controllerCreated: true
loadBalancers: # map[string]VPCLoadBalancerStatus
my-lb:
id: "lb-id"
hostname: "my-lb.example.com" # *string pointer
controllerCreated: true
conditions:
- type: Ready
status: "True"
v1beta2:
conditions:
- type: Ready
status: "True"
IBMPowerVSCluster v1beta3 Status
status:
conditions: # Promoted to top-level []metav1.Condition
- type: Ready
status: "True"
initialization:
provisioned: true # Replaces ready bool
workspace: # Renamed from serviceInstance; no controllerCreated
id: "workspace-id"
name: "my-workspace"
network: # No controllerCreated; DHCP nested here
id: "network-id"
name: "my-network"
dhcpServer:
id: "dhcp-id"
name: "my-dhcp"
resourceGroup:
id: "rg-id"
name: "my-resource-group"
vpc:
id: "vpc-id"
name: "my-vpc"
region: "us-east" # Added region to VPC status
vpcSubnets: # list (renamed from vpcSubnet map)
- id: "subnet-id"
name: "my-subnet"
zone: "us-east-1"
vpcSecurityGroups: # list (was map[string]VPCSecurityGroupStatus)
- id: "sg-id"
name: "my-sg"
rules:
- id: "rule-id-1"
transitGateway:
id: "tgw-id"
name: "my-tgw"
vpcConnection: # Connection status includes name and state
id: "conn-id"
name: "my-vpc-conn"
state: "attached"
powerVSConnection:
id: "conn-id"
name: "my-pvs-conn"
state: "attached"
cosInstance:
id: "cos-id"
name: "my-cos-instance"
bucketName: "my-bucket"
bucketRegion: "us-south"
loadBalancers: # list (was map[string]VPCLoadBalancerStatus)
- name: "my-lb"
id: "lb-id"
state: "active"
hostname: "my-lb.example.com" # plain string (no longer a pointer)
deprecated:
v1beta2:
conditions:
- type: Ready
status: "True"
Key Points:
controllerCreatedremoved from all status fields; ownership is determined solely by thetypefield in Spec.ready boolreplaced byinitialization.provisioned *bool.serviceInstancerenamed toworkspacein status.dhcpServerstatus moved from a top-level field to nested undernetwork.dhcpServer.resourceGroupIDfield key renamed toresourceGroupin status.- VPC status now includes
region. vpcSubnet(keyed map) renamed tovpcSubnets(ordered list); each entry includeszone.vpcSecurityGroupschanged frommap[string]VPCSecurityGroupStatusto[]VPCSecurityGroupStatus; each entry now exposesnameand per-ruleid.TransitGatewayconnection status now includesnameandstate(e.g.,attached,pending).loadBalancerschanged frommap[string]VPCLoadBalancerStatusto[]LoadBalancerStatus;hostnameis now a plainstring.COSInstancestatus now exposesname,bucketName, andbucketRegion.- Top-level
conditionsare[]metav1.Condition; old-style conditions moved todeprecated.v1beta2.conditions.
15. Conversion Webhook
The v1beta3 API includes automatic conversion webhooks that handle migration:
-
v1beta2 → v1beta3: Automatically converts old format to new
Status.ControllerCreated: true→Spec.Type: ProvisionStatus.ControllerCreated: false→Spec.Type: ReferenceserviceInstanceID/serviceInstance→workspacedhcpServer(top-level) →network.provision.dhcpServer- Boolean SNAT (
*bool) → Enum SNAT (true→Enabled,false→Disabled) *bool globalRoutingon TransitGateway → Enum routing (true→Global,false→Local)*bool publicon LoadBalancer → Enum type (true→Public,false→Private)- Annotation-based topology → Explicit
topologyfield *string zone→ plainstring zone*IBMPowerVSResourceReference resourceGroup→ResourceGroupSource resourceGroupvpcSubnets[](flatSubnetstruct with*stringfields) →subnets[]withtype/reference/provisionloadBalancerskeyed map in status →loadBalancerslist in statusvpcSubnetkeyed map in status →vpcSubnetslist in statusvpcSecurityGroupskeyed map in status →vpcSecurityGroupslist in statusimage+imageRef(IBMPowerVSMachine) → unifiedimagewithtype: Referenceortype: Import*string bucket/object/region(IBMPowerVSImage) → plainstringfields- Untyped
storageType/deletePolicystrings → typedPowerVSStorageType/PowerVSImageDeletePolicy - COS instance flat struct →
COSInstanceSourcewithtype/reference/provision
-
v1beta3 → v1beta2: Converts back for compatibility
Spec.Type: Provision→Status.ControllerCreated: trueSpec.Type: Reference→Status.ControllerCreated: falseworkspace→serviceInstancenetwork.provision.dhcpServer→ top-leveldhcpServer- Explicit
topologyfield → Annotation-based configuration - Enum SNAT →
*boolSNAT - Enum routing →
*bool globalRouting - Enum LB type →
*bool public - Unified
image(Reference/Import) →image+imageRefsplit - Typed enums → plain strings for
storageType/deletePolicy
Note: While conversion webhooks provide compatibility, it is recommended to migrate to v1beta3 explicitly for better maintainability.