Cloud-Init is a project that standardizes methods for injecting data into cloud VMs on launch. Data typically includes metadata and userdata
Metadata is dynamically generated by the cloud provider and contains information about the unique instance.
Userdata is VM configuration data supplied by the user that executes when the VM instance starts.
It is common for cloud IaaS users to associate userdata with a VM instance in order to execute a short script that software provisions on startup.
The Cloud Init project supports multiple ways of supplying metadata and userdata to a VM. These methods are called data sources.
http://cloudinit.readthedocs.io/en/latest/topics/datasources.html
KubeVirt supports the different data source standards by taking the userdata and metadata associated with a VM and formatting that data in a way that adheres to the specific datasource standard in use.
http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html
The NoCloud data source involves generating an iso with userdata and metadata in it, and attaching that iso the the VM instance. The fedora-atomic project supports this datasource for their VM images.
To associated userdata with a VM instance using the NoCloud data source, all users have to do is base64 encode userdata information into the VM definition.
Example
metadata:
name: testvm-nocloud
apiVersion: kubevirt.io/v1alpha1
kind: VirtualMachine
spec:
domain:
devices:
disks:
- type: RegistryDisk:v1alpha
source:
name: kubevirt/cirros-registry-disk-demo:devel
target:
dev: vda
- type: file
target:
dev: vdb
cloudinit:
nocloud:
userDataBase64: I2Nsb3VkLWNvbmZpZwpwYXNzd29yZDogYXRvbWljCnNzaF9wd2F1dGg6IFRydWUKY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9Cg==
interfaces:
- source:
network: default
type: network
memory:
unit: MB
value: 64
os:
type:
os: hvm
type: qemu
Instead of placing the userdata directly into the VM definition, another option is to reference the userdata in a k8s secret object.
To use this method, the user must create an Opaque type kubernetes secret with a key named 'userdata' containing a value representing the base64 encoded userdata. The name of the kubernetes secret is then referenced in the CloudInit object on the VM spec.
Example: Create a k8s secret with UserData. Reference the secret in the NoCloud disk definition.
First create the secret.
apiVersion: v1
kind: Secret
metadata:
name: my-vm-secret
type: Opaque
data:
userdata: I2Nsb3VkLWNvbmZpZwpwYXNzd29yZDogYXRvbWljCnNzaF9wd2F1dGg6IFRydWUKY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9Cg==
Then reference the secret in the userDataSecretRef field.
metadata:
name: testvm-nocloud
apiVersion: kubevirt.io/v1alpha1
kind: VirtualMachine
spec:
domain:
devices:
disks:
- type: RegistryDisk:v1alpha
source:
name: kubevirt/cirros-registry-disk-demo:devel
target:
dev: vda
- type: file
target:
dev: vdb
cloudinit:
nocloud:
userDataSecretRef: my-vm-userdata
interfaces:
- source:
network: default
type: network
memory:
unit: MB
value: 64
os:
type:
os: hvm
type: qemu
Multiple VMs can reference the same k8s secret object containing userdata.
Internally, kubevirt passes the cloud-init spec to the config-disk package. That package generates the iso files associated with the nocloud datasource.
When the VM starts, virt-handler injects the NoCloud iso as a file based disk that the VM consumes.
From there the NoCloud datasource process internal to the VM detects the attached disk and processes the userdata and metadata stored on the disk.
The VM definition structures and cloud-init package have been structured in a way that should allow for additional disk based data sources to be added in the future with ease.
Example: User facing details related to another data source.
cloudInit:
SomeOtherProviderData:
userDataBase64: I2Nsb3VkLWNvbmZpZwpwYXNzd29yZDogYXRvbWljCnNzaF9wd2F1dGg6IFRydWUKY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9Cg==
Whatever1: somethingelse
Whatever2: otherstuff
The cloud-init package would then get a new data source called 'SomeOtherSource'. Everything related to the 'NoCloud' source is isolated by switch statements already. The 'SomeOtherSource' implementation details would just need to be added in whatever way makes sense for that data source.
Not all cloud init data sources involve injecting a disk into the VM. Another common method for injecting cloud init data is to use a metadata server. With a metadata server, the VM launches and makes a request for the cloud init data on a well known IP address backed by the metadata server. The metadata server responds with the userdata and metadata associated with that VM.
For KubeVirt to support metadata servers, this will require integrating the metadata server into the VM launch flow. KubeVirt will have to know how to register VM specific information with the metadata server so that server can provide it to the VM upon request.