From 788dc15de807a47427caaeaffadedfd0ce986d3a Mon Sep 17 00:00:00 2001 From: Benjamin Affolter <5555767+bliemli@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:01:37 +0200 Subject: [PATCH] Proofread initialize VMs chapter --- .../_index.md | 12 +- .../cloud-init.md | 151 ++++++++++-------- .../ignition.md | 151 ++++++++++-------- .../startup-introduction.md | 23 ++- 4 files changed, 183 insertions(+), 154 deletions(-) diff --git a/content/en/docs/initialize-vms-with-startup-scripts/_index.md b/content/en/docs/initialize-vms-with-startup-scripts/_index.md index 0e8bd52..3ff7487 100644 --- a/content/en/docs/initialize-vms-with-startup-scripts/_index.md +++ b/content/en/docs/initialize-vms-with-startup-scripts/_index.md @@ -3,15 +3,15 @@ title: "Initialize VMs with startup scripts" weight: 4 labfoldernumber: "04" description: > - Initialize and configure Virtual Machines using tools like cloud-init, Ignition or Sysprep. + Initialize and configure virtual machines using tools like cloud-init, Ignition or Sysprep --- -In this Section we will lean how we can initialize and configure VMs. They often start with a generic disk like an ephemeral -Container Disk. How do we customize such VMs for example with adding custom login information? +In this section we will learn how we can initialize and configure VMs at startup. They often start with a generic disk like an ephemeral +container disk. How do we customize such VMs, e.g., with adding custom login information? -## Lab Goals +## Lab goals -* Know the benefit of Startup Scripts -* Know the available methods like cloud-init, Ignition and Sysprep. +* Know the benefit of startup scripts +* Know the available methods like cloud-init, Ignition and Sysprep * Customize your own VM diff --git a/content/en/docs/initialize-vms-with-startup-scripts/cloud-init.md b/content/en/docs/initialize-vms-with-startup-scripts/cloud-init.md index cbd742a..4b42956 100644 --- a/content/en/docs/initialize-vms-with-startup-scripts/cloud-init.md +++ b/content/en/docs/initialize-vms-with-startup-scripts/cloud-init.md @@ -1,12 +1,12 @@ --- -title: "Cloud-Init" +title: "Cloud-init" weight: 42 labfoldernumber: "04" description: > Use cloud-init to initialize your VM --- -In this section we will use cloud-init to initialize a Fedora Cloud[^1] VM. Cloud-init is the defacto standard for providing +In this section we will use cloud-init to initialize a Fedora Cloud[^1] VM. Cloud-init is the de-facto standard for providing startup scripts to VMs. Cloud-init is widely adopted. Some of the known users of cloud-init are: @@ -21,22 +21,22 @@ Cloud-init is widely adopted. Some of the known users of cloud-init are: * openSUSE -## Supported datasources +## Supported data sources -KubeVirt supports the NoCloud and ConfigDrive datasource methods. +KubeVirt supports the `cloudInitNoCloud` and `cloudInitConfigDrive` data source methods. {{% alert title="Note" color="info" %}} -As it is the simplest datasource you should stick to `NoCloud` as the go to datasource. Only if `NoCloud` is not supported -by the cloud-init implementation you should switch to `ConfigDrive`. For example the implementation of coreos-cloudinit was known to -require the ConfigDrive datasource. However, as CoreOS has built Ignition this implementation is superseded but there +As it is the simplest data source you should stick to `cloudInitNoCloud` as the go to data source. Only if `cloudInitNoCloud` is not supported +by the cloud-init implementation you should switch to `cloudInitConfigDrive`. For example the implementation of coreos-cloudinit was known to +require the `cloudInitConfigDrive` data source. However, as CoreOS has built Ignition this implementation is superseded but there may be more implementations. {{% /alert %}} -### NoCloud datasource +### `cloudInitNoCloud` data source -The NoCloud is a flexible datasource to configure an instance locally. It can work without network access but can also -fetch configuration from a remote server. The relevant configuration of a NoCloud datasource in a VM looks like this: +`cloudInitNoCloud` is a flexible data source to configure an instance locally. It can work without network access but can also +fetch configuration from a remote server. The relevant configuration of a `cloudInitNoCloud` data source in a VM looks like this: ```yaml volumes: @@ -46,27 +46,27 @@ volumes: [...] ``` -This volume must be referenced after the vm disk in the `spec.template.spec.domain.devices.disks` section: +This volume must be referenced after the VM disk in the `spec.template.spec.domain.devices.disks` section: + ```yaml - name: cloudinitdisk disk: bus: virtio ``` +Using the `cloudInitNoCloud` attribute gives us the following possibilities to provide our configuration: -Using the `cloudInitNoCloud` attribute give us the following possibilities to provide our configuration: - -* `userData`: inline NoCloud configuration in the user data format. -* `userDataBase64`: NoCloud configuration in the user data format as base64 string. -* `secretRef`: reference to a k8s secret containing NoCloud userdata. -* `networkData`: inline NoCloud networkdata. -* `networkDataBase64`: NoCloud networkdata as base64 string. -* `networkDataSecretRef`: reference to a k8s secret containing NoCloud networkdata. +* `userData`: inline `cloudInitNoCloud` configuration in the user data format +* `userDataBase64`: `cloudInitNoCloud` configuration in the user data format as a base64-encoded string +* `secretRef`: reference to a K8s Secret containing `cloudInitNoCloud` userdata +* `networkData`: inline `cloudInitNoCloud` network data +* `networkDataBase64`: `cloudInitNoCloud` network data as a base64-encoded string +* `networkDataSecretRef`: reference to a K8s Secret containing `cloudInitNoCloud` network data -The most convenient for the lab is to use the NoCloud userdata method. +The most convenient for the lab is to use the `cloudInitNoCloud` user data method. -The user data format recognized the following headers. Depending on the header the content is interpreted and executed -differently. For example if you use the `#!/bin/sh` header the content is treated as an executable shell script. +The user data format recognizes the following headers. Depending on the header, the content is interpreted and executed +differently. For example, if you use the `#!/bin/sh` header the content is treated as an executable shell script. | User data format | Content Header | Expected Content-Type | |----------------------|---------------------------------|---------------------------| @@ -79,9 +79,10 @@ differently. For example if you use the `#!/bin/sh` header the content is treate | Include file | `#include` | text/x-include-url | | Part handler | `#part-handler` | text/part-handler | -If you want to combine multiple items you can do that using #cloud-config-archive. +If you want to combine multiple items, you can do that using #cloud-config-archive. Here is an example how to configure multiple items: + ```yaml volumes: - name: cloudinitdisk @@ -97,17 +98,17 @@ volumes: yum install -y nginx ``` -Check [Cloud-inits Network configuration sources](https://cloudinit.readthedocs.io/en/latest/reference/network-config.html) for more Information about the format -of the network data. Be aware that there is a different format used whenever you use `NoCloud` or `ConfigDrive`. +Check [cloud-init's network configuration sources](https://cloudinit.readthedocs.io/en/latest/reference/network-config.html) for more information about the network data format. +Be aware that there is a different format used whenever you use `cloudInitNoCloud` or `cloudInitConfigDrive`. {{% alert title="Important" color="warning" %}} Make sure you use `secretRef` or `networkDataSecretRef` whenever you provide sensitive data like credentials, certificates and so on. {{% /alert %}} -### ConfigDrive datasource +### `cloudInitConfigDrive` data source -The ConfigDrive datasource works identical to the `NoCloud` datasource. However, the volume type changed from `cloudInitNoCloud` to `cloudInitConfigDrive`: +The `cloudInitConfigDrive` data source works identically to the `cloudInitNoCloud` data source by defining: ```yaml volumes: @@ -117,21 +118,23 @@ volumes: [...] ``` -This volume must be referenced after the vm disk in the `spec.template.spec.domain.devices.disks` section: +The volume must be referenced after the VM disk in the `spec.template.spec.domain.devices.disks` section: + ```yaml - name: cloudinitdisk disk: bus: virtio ``` -When using ConfigDrive the networkdata has to be in the [OpenStack Metadata Service Network](https://specs.openstack.org/openstack/nova-specs/specs/liberty/implemented/metadata-service-network-info.html) format. +When using `cloudInitConfigDrive`, the network data has to be in the [OpenStack Metadata Service Network](https://specs.openstack.org/openstack/nova-specs/specs/liberty/implemented/metadata-service-network-info.html) format. + +## {{% task %}} Creating a cloud-init config Secret -## {{% task %}} Creating a cloud-init config secret +We are now going to create a Fedora Cloud VM and provide a cloud-init userdata configuration to initialize our VM. -We are now going to create a Fedora Cloud VM and provide a cloud-init userdata configuration to initialize our WM. +First, we are going to define our configuration. Create a file called `cloudinit-userdata.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: -First we are going to define our configuration. Create a file `cloudinit-userdata.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: ```yaml #cloud-config password: kubevirt @@ -141,18 +144,20 @@ chpasswd: { expire: False } This will set the password of the default user (`fedora` for Fedora Core) to `kubevirt` and configure the password to never expire. -From this configuration we need to create the secret. You can use the following command to create the secret in the kubernetes cluster. +We need to create the Secret from this configuration. You can use the following command to create it: ```bash kubectl create secret generic {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --from-file=userdata={{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/cloudinit-userdata.yaml --namespace=$USER ``` The output should be: + ``` secret/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit created ``` -You can inspect the secret with: +You can inspect the Secret with: + ```bash kubectl get secret {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit -o yaml --namespace=$USER ``` @@ -168,14 +173,15 @@ metadata: [...] ``` -It would also be possible to create the secret as resource or use a secret management. But for the lab it is more +It would also be possible to create the Secret as a resource or use a secret management solution. But for the lab it is more convenient to create it from the raw configuration using the `kubectl` tool. ## {{% task %}} Creating a VirtualMachine using cloud-init -Create a file `vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}`and start with the -following VM configuration: +Create a file `vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit.yaml` +in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` +and start with the following VM configuration: ```yaml apiVersion: kubevirt.io/v1 @@ -215,11 +221,11 @@ spec: image: {{% param "fedoraCloudCDI" %}} ``` -Extend the VM configuration to include our secret `{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit` we created above. -Use the linked under `Reference` at the end of this lab for further information. +Extend the VM configuration to include our Secret `{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit` we created above. {{% details title="Task Hint: Solution" %}} Your VirtualMachine configuration should look like this: + ```yaml apiVersion: kubevirt.io/v1 kind: VirtualMachine @@ -267,6 +273,7 @@ spec: {{% /details %}} Make sure you create your VM with: + ```bash kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit.yaml --namespace=$USER ``` @@ -274,17 +281,20 @@ kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" % Start the VM and verify whether logging in with the defined user and password works as expected. {{% details title="Solution" %}} -Start the newly created VM, this might take a while(a couple of minutes), due to the lab environment +Start the newly-created VM. This might take a couple of minutes: + ```bash virtctl start {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER ``` -Connect to the console, and login as soon as the prompt shows up + +Connect to the console and log in as soon as the prompt shows up: ```bash virtctl console {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER ``` -You will also see the cloud-init executions in the console log during startup +You will also see the cloud-init execution messages in the console log during startup: + ```bash [...] [ OK ] Started systemd-logind.service - User Login Management. @@ -297,7 +307,7 @@ You will also see the cloud-init executions in the console log during startup ``` {{% alert title="Note" color="info" %}} -Hit the `Enter` key if the login prompt doesn't show automatically. +Hit the `Enter` key if the login prompt doesn't show up automatically. {{% /alert %}} {{% /details %}} @@ -307,12 +317,13 @@ Hit the `Enter` key if the login prompt doesn't show automatically. In the previous section we have created a VM using a cloud-init script. Enhance the startup script with the following functionality: -* Set the Timezone to `Europe/Zurich` -* Install nginx package +* Set the timezone to `Europe/Zurich` +* Install the nginx package * Write a custom nginx.conf to `/etc/nginx/nginx.conf` * Start the nginx service -For the custom nginx configuration you can use the following content: +For the custom nginx configuration, you can use the following content: + ```text user nginx; worker_processes auto; @@ -364,6 +375,7 @@ http { {{% details title="Solution" %}} Your cloud-init configuration (`cloudinit-userdata.yaml`) will look like this: + ```yaml #cloud-config password: kubevirt @@ -426,22 +438,21 @@ runcmd: ``` {{% /details %}} -You need to recreate your secret: +You need to recreate your Secret: ```bash kubectl delete secret {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER kubectl create secret generic {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --from-file=userdata={{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/cloudinit-userdata.yaml --namespace=$USER ``` -Next we need to restart our vm to pick up the changes in the cloud-init configuration. +Next, we need to restart our VM to pick up the changes in the cloud-init configuration: ```bash virtctl restart {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER ``` - {{% alert title="Note" color="info" %}} -It may take some minutes until your server is fully provisioned. While booting you may watch out for the message `Reached target cloud-init.target` in your VMs console. +It may take some minutes until your server is fully provisioned. While booting you may watch out for the message `Reached target cloud-init.target` in your VM's console using: ```bash virtctl console {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER @@ -449,11 +460,11 @@ virtctl console {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %} {{% /alert %}} -## {{% task %}} Testing your webserver on your Virtual Machine +## {{% task %}} Testing your webserver on your virtual machine -We have spawn a Virtual Machine which uses cloud-init and installs a simple nginx webserver. Let us test the webserver: +We have spawned a virtual machine that uses cloud-init and installs a simple nginx webserver. Let us test the webserver: -Create the following kubernetes service (file: `service-cloudinit.yaml` folder: `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}`): +Create the following Kubernetes Service (file: `service-cloudinit.yaml` folder: `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}`): ```yaml apiVersion: v1 @@ -469,18 +480,21 @@ spec: kubevirt.io/domain: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit type: ClusterIP ``` -And create it: + +And create it with: ```bash kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/service-cloudinit.yaml --namespace=$USER ``` +Test your working webserver from your webshell: -Test your working webserver from your webshell. ```bash curl -s {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit.$USER.svc.cluster.local ``` +You should see an output similar to this: + ``` Hello from {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit GMT time: Thursday, 22-Aug-2024 14:13:17 GMT @@ -488,11 +502,11 @@ Local time: Thursday, 22-Aug-2024 16:13:17 CEST ``` -## {{% task %}} (Optional) Expose the Service over an ingress +## {{% task %}} (Optional) Expose the Service -The nginx webserver is now only accessible within our kubernetes cluster. In this optional lab we expose it via ingress to the internet. +The nginx webserver is now only accessible within our Kubernetes cluster. In this optional lab we are going to expose it to the internet. -For that we need to create an ingress resource. Create a file `ingress-cloudinit.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: +For that, we need to create an Ingress resource. Create a file called `ingress-cloudinit.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: ```yaml --- @@ -519,39 +533,38 @@ spec: Make sure all occurrences of -* `` - your Username (eg. `user4`) +* `` - your username (eg. `user4`) * `` - ask the trainer -are replaced accordingly, before you create the ingress by - +are replaced accordingly, before you create the Ingress by executing: ```bash kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/ingress-cloudinit.yaml --namespace=$USER ``` -After that open a new Browser Tab and enter URL: +After that open a new browser tab and enter the URL: `https://{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit-.` -Congratulations, you've successfully exposed nginx, running in a fedora VM, on Kubernetes to the internet. +Congratulations, you've successfully exposed nginx, running in a Fedora VM on Kubernetes, to the internet! ## End of lab {{% alert title="Cleanup resources" color="warning" %}} {{% param "end-of-lab-text" %}} -Stop your running VM with +Stop your running VM with: + ```bash virtctl stop {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit --namespace=$USER ``` {{% /alert %}} -## Reference - -You may find additional Information about cloud-init here: +## References -* [Cloud-Init Module Reference](https://cloudinit.readthedocs.io/en/latest/reference/modules.html#modules) -* [Cloud-Init Examples](https://cloudinit.readthedocs.io/en/latest/reference/examples.html) +You can find additional information about cloud-init here: +* [Cloud-init module reference](https://cloudinit.readthedocs.io/en/latest/reference/modules.html#modules) +* [Cloud-init examples](https://cloudinit.readthedocs.io/en/latest/reference/examples.html) [^1]: [Fedora Cloud](https://fedoraproject.org/cloud/) diff --git a/content/en/docs/initialize-vms-with-startup-scripts/ignition.md b/content/en/docs/initialize-vms-with-startup-scripts/ignition.md index 670cee8..2725e65 100644 --- a/content/en/docs/initialize-vms-with-startup-scripts/ignition.md +++ b/content/en/docs/initialize-vms-with-startup-scripts/ignition.md @@ -6,7 +6,7 @@ description: > Use Ignition to initialize your VM --- -In the previous section we created a VM using a cloud-init configuration secret. This time we will do something similar but with Ignition and Linux Fedora CoreOS. +In the previous section we created a VM using a cloud-init configuration Secret. This time we will do something similar but with Ignition and Linux Fedora CoreOS. Known users of Ignition are: @@ -17,14 +17,14 @@ Known users of Ignition are: * SUSE Linux Enterprise Micro -## Supported datasources +## Supported data sources -To provide Ignition data we have to use the ConfigDrive datasource. +To provide Ignition data we have to use the `cloudInitNoCloud` data source. -### ConfigDrive datasource +### `cloudInitNoCloud` data source -The relevant configuration of a ConfigDrive datasource in a VM looks like this: +The relevant configuration of a `cloudInitNoCloud` data source in a VM looks like this: ```yaml volumes: @@ -39,7 +39,8 @@ volumes: } ``` -Similar to cloud-init, this volume must be referenced after the vm disk in the `spec.template.spec.domain.devices.disks` section: +Similar to cloud-init, this volume must be referenced after the VM disk in the `spec.template.spec.domain.devices.disks` section: + ```yaml - name: ignitiondisk disk: @@ -48,26 +49,25 @@ Similar to cloud-init, this volume must be referenced after the vm disk in the ` Using the `cloudInitConfigDrive` attribute gives us the following possibilities to provide our Ignition configuration: -* `userData`: inline Ignition configuration -* `userDataBase64`: Ignition configuration as base64 string. -* `secretRef`: reference to a k8s secret containing Ignition configuration. +* `userData`: Inline Ignition configuration +* `userDataBase64`: Ignition configuration as a base64-encoded string +* `secretRef`: Reference to a K8s Secret containing Ignition configuration The data format of an Ignition configuration is always JSON. There is a transpiler available to convert a YAML-formatted Butane config to a JSON config if needed. As our config for the Lab is simple enough we directly write the JSON config. -You may find more details about Butane here: [Producing an Ignition Config](https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/#_configuration_process) +You may find more details about Butane [here](https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/#_configuration_process). {{% alert title="Important" color="warning" %}} -Make sure you use `secretRef` whenever you provide sensitive data like credentials, certificates and so on. +Make sure you use `secretRef` whenever you provide sensitive data like credentials, certificates and similar. {{% /alert %}} -## {{% task %}} Creating an Ignition config secret +## {{% task %}} Creating an Ignition config Secret This time we are going to use a Fedora CoreOS VM and provide an Ignition configuration to initialize our VM. -You can find more information and examples in the official documentation under `Reference` at the end of this lab. +First, we define our configuration. Create a file `ignition-data.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: -First we define our configuration. Create a file `ignition-data.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: ```yaml { "ignition": { @@ -84,33 +84,29 @@ First we define our configuration. Create a file `ignition-data.yaml` in the fol } ``` -This will set the password of the default user (`core` for Fedora CoreOS) according to the provided hash. You may wonder what the content +This will set the the default user's password (`core` for Fedora CoreOS) according to the provided hash. You may wonder what the content of `passwordHash` is. Actually it needs to be a hash understandable by the Linux system. There are several approaches to generate a password hash to be used for this lab. Two of them are: -OpenSSL +Using OpenSSL: + ```bash openssl passwd -salt xyz ``` -``` -$1$xyz$I30aA[...] -``` -Pythons Crypt Module +Using Python's crypt module: + ```bash python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))' ``` -``` -$6$vdwmUilVEr7j7j.T$.2wFftwtDSxK[...] -``` Generate a hash for `kubevirt` and add the generated `passwordHash` to the Ignition configuration. -After that don't forget to create the kubernetes secret containing the ignition configuration, similar to the previous lab. +After that don't forget to create the Kubernetes Secret containing the Ignition configuration, similar to the previous lab. {{% details title="Solution" %}} -If you generated the pw hash using the openssl command `openssl passwd -salt xyz kubevirt`, then the `ignition-data.yaml` should look like: +If you generated the password hash using the OpenSSL command `openssl passwd -salt xyz kubevirt`, then the `ignition-data.yaml` should look like: ```yaml @@ -129,8 +125,7 @@ If you generated the pw hash using the openssl command `openssl passwd -salt xyz } ``` - -To create the kubernetes secret run the following command: +To create the Kubernetes Secret, run the following command: ```bash kubectl create secret generic {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --from-file=userdata={{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/ignition-data.yaml --namespace=$USER @@ -141,8 +136,9 @@ kubectl create secret generic {{% param "labsubfolderprefix" %}}{{% param "labfo ## {{% task %}} Creating a VirtualMachine using Ignition -Create a file `vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` and start with the -following VM configuration: +Create a file `vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition.yaml` +in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` +and start with the following VM configuration: ```yaml apiVersion: kubevirt.io/v1 @@ -182,10 +178,11 @@ spec: image: {{% param "fedoraCoreOSCDI" %}} ``` -Similar to the cloud-init section alter the configuration above to include our Ignition config. +Similar to the cloud-init section, alter the configuration above to include our Ignition config. -{{% details title="Task Hint" %}} +{{% details title="Task hint" %}} Your VirtualMachine configuration should look like this: + ```yaml apiVersion: kubevirt.io/v1 kind: VirtualMachine @@ -233,6 +230,7 @@ spec: {{% /details %}} Create your VM with: + ```bash kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/vm_{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition.yaml --namespace=$USER ``` @@ -240,11 +238,13 @@ kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" % Start the VM and verify whether logging in with the defined user and password works as expected. {{% details title="Solution" %}} -Start the newly created VM, this might take a while (a couple of minutes), due to the lab environment +Start the newly created VM. This might take a couple of minutes: + ```bash virtctl start {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --namespace=$USER ``` -Connect to the console and login as soon as the prompt shows up with the defined credentials. + +Connect to the console and log in as soon as the prompt shows up with the defined credentials: ```bash virtctl console {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --namespace=$USER @@ -259,27 +259,30 @@ Hit the `Enter` key if the login prompt doesn't show automatically. ## {{% task %}} Enhance your startup script -With the help of the Documentation and Examples (See Section References below), try to enhance your Ignition configuration to include the following configurations: +With the help of the [referenced documentation and examples](#references), try to enhance your Ignition configuration to include the following configuration: * Create a group `ssh-users` * Add user `core` to the group `docker` and `ssh-users` -* Add a `sshAuthorizedKeys` for the user `core`. See instructions below to generate your ssh key. -* Set the Hostname to `lab05-ignition-` where `` is your username -* Configure the SSH Daemon with: +* Add a `sshAuthorizedKeys` for the user `core` (see instructions below to generate your ssh key) +* Set the hostname to `lab{{% param "labfoldernumber" %}}-ignition-` where `` is your username +* Configure the SSH daemon with: * Disable root login - * Allow only group `ssh-users` to login through ssh. + * Only allow group `ssh-users` to login via ssh Generate your ssh key with the following command: + ```bash ssh-keygen ``` Your ssh key to be used in the `sshAuthorizedKeys` is located in `/home/theia/.ssh/id_rsa.pub`. Get your key with: + ```bash cat /home/theia/.ssh/id_rsa.pub ``` Your output should be similar to: + ``` ssh-rsa AAAAB3NzaC[...] theia@$USER-webshell-554b45d885-b79ks ``` @@ -287,7 +290,8 @@ ssh-rsa AAAAB3NzaC[...] theia@$USER-webshell-554b45d885-b79ks Make sure the key starts with ssh-rsa and copy the key to the `sshAuthorizedKeys` attribute. {{% details title="Task Hint" %}} -Make sure you replace the `` (line 32), the `passwordHash` (line 19) and `sshAuthorizedKeys` (line 21) hashes. Your Ignition configuration will look like this: +Make sure you replace `` (line 32), `passwordHash` (line 19) and `sshAuthorizedKeys` (line 21). Your Ignition configuration will look like this: + ```yaml { "ignition": { @@ -340,14 +344,14 @@ Make sure you replace the `` (line 32), the `passwordHash` (line 19) and ` ``` {{% /details %}} -You need to recreate your secret: +You need to recreate your Secret: ```bash kubectl delete secret {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --namespace=$USER kubectl create secret generic {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --from-file=userdata={{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/ignition-data.yaml --namespace=$USER ``` -Next we need to restart our vm to pick up the changes in the ignition configuration. +Next, we need to restart our VM to pick up the changes in the Ignition configuration. ```bash virtctl restart {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --namespace=$USER @@ -358,10 +362,11 @@ It may take some minutes until your server is fully provisioned. {{% /alert %}} -## {{% task %}} Testing your ssh server on your Virtual Machine +## {{% task %}} Testing your ssh server on your virtual machine -To access our VM from the webshell we need to create a kubernetes service. Create a file +To access our VM from the webshell, we need to create a Kubernetes Service. Create a file called `service-ignition.yaml` in the folder `{{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}` with the following content: + ```yaml apiVersion: v1 kind: Service @@ -377,18 +382,19 @@ spec: type: ClusterIP ``` -And create it: +And create it with: ```bash kubectl apply -f {{% param "labsfoldername" %}}/{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}/service-ignition.yaml --namespace=$USER ``` You may now be able to login with SSH from your webshell to your VM: + ```bash ssh core@{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition.$USER.svc.cluster.local ``` -And hit `yes` to confirm the the authenticity of host. +And hit `yes` to confirm the authenticity of host. ``` Fedora CoreOS 40.20240728.3.0 @@ -403,9 +409,10 @@ Our SSH daemon is configured to only allow logins: * Not from root (`PermitRootLogin no` in `30-disable-rootlogin.conf`) * Only from users which are a member of the `ssh-users` group (`AllowGroups ssh-users` in `30-allow-groups.conf`) -* Using keys and not username/password (`PasswordAuthentication no` in default config). +* Using keys, not passwords (`PasswordAuthentication no` in default config). + +You may verify the presence of the two configuration files with: -You may verify the presence of the two configurations with: ```bash ls /etc/ssh/sshd_config.d/*.conf ``` @@ -415,64 +422,73 @@ Hint: `sudo su - root` Which should list the two files `30-disable-rootlogin` and `30-allow-groups.conf` created in the Ignition config. {{% /alert %}} +Make sure to switch back to the user `core` and verify your assigned groups with: -Verify your assigned groups with, make sure to switch back to the user `core`: ```bash groups ``` + You should see the assigned groups `docker` and `ssh-users`: + ``` core adm wheel sudo systemd-journal docker ssh-users ``` The default hostname would be the VM name `{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition`. Show the configured hostname: + ```bash hostname ``` + We should see our postfix `-` added to our hostname: + ``` {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition- ``` -## {{% task %}} (Optional) Expose ssh as NodePort to the Internet +## {{% task %}} (Optional) Expose ssh as NodePort to the internet -In this optional lab we expose the ssh service as node port to the external world. -Similar to what we did in lab 2.4. +In this optional lab we will expose the ssh service as a node port to the external world, similar to what we did in {{< link "/content/en/docs/getting-started-with-kubevirt/ssh.md" >}}. -* create a NodePort Service -* Find out the Port -* Get the IP Address of one of the Kubernetes Nodes -* ssh to the service. +* Create a NodePort Service +* Find out the port number +* Get the IP address of one of the Kubernetes nodes +* Test it {{% details title="Solution" %}} -Create the NodePort +Create the NodePort Service: + ```bash virtctl expose vmi {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --name={{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition-ssh-np --port=22 --type=NodePort --namespace=$USER ``` -Find out the Port +Find out the port number: + ```bash kubectl get service --namespace=$USER ``` -Get the IP Address of one of the Kubernetes Nodes +Get the IP address of one of the Kubernetes nodes: + ```bash kubectl get nodes --selector=node-role.kubernetes.io/master!=true -o jsonpath={.items[*].status.addresses[?\(@.type==\"ExternalIP\"\)].address} --namespace=$USER ``` + or + ```bash kubectl get nodes -o wide ``` -ssh to the service. +Test it: + ```bash ssh core@ -p ``` - {{% /details %}} @@ -480,18 +496,19 @@ ssh core@ -p {{% alert title="Cleanup resources" color="warning" %}} {{% param "end-of-lab-text" %}} -Stop your running VM with +Stop your running VM with: + ```bash virtctl stop {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-ignition --namespace=$USER ``` -{{% /alert %}} +{{% /alert %}} -## Reference -You may find additional Information about Ignition here: +## References -* [Ignition Documentation](https://coreos.github.io/ignition/) -* [Ignition Examples](https://coreos.github.io/ignition/examples/) -* [Supported Platforms](https://coreos.github.io/ignition/supported-platforms/) +You may find additional information about Ignition here: +* [Ignition documentation](https://coreos.github.io/ignition/) +* [Ignition examples](https://coreos.github.io/ignition/examples/) +* [Supported platforms](https://coreos.github.io/ignition/supported-platforms/) diff --git a/content/en/docs/initialize-vms-with-startup-scripts/startup-introduction.md b/content/en/docs/initialize-vms-with-startup-scripts/startup-introduction.md index 7ae66b1..5db57b3 100644 --- a/content/en/docs/initialize-vms-with-startup-scripts/startup-introduction.md +++ b/content/en/docs/initialize-vms-with-startup-scripts/startup-introduction.md @@ -3,25 +3,25 @@ title: "Introduction" weight: 41 labfoldernumber: "04" description: > - Introduction to VM provisioning with startup scripts. + Introduction to VM provisioning with startup scripts --- -When we create a virtual Machine we often want to configure the virtual Machine to fit in our environment. To achieve this, KubeVirt -supports to assign startup scripts which are executed automatically when the VM initializes. They are typically used to -provide SSH Keys, required configuration to run further configuration with ansible, deploy network configuration and so on. +When we create a virtual machine, we often want to configure the virtual machine to fit in our environment. To achieve this, KubeVirt +supports the assignment of startup scripts which are executed automatically when the VM initializes. They are typically used to +provide SSH keys, required configuration to run further configuration with ansible, deploy network configuration and so on. -The startup script methods are supported. +These startup script methods are supported: -* Cloud-Init[^1] and Ignition[^2] which are targeting Linux and Unix systems -* Sysprep[^3] to initialize Windows based VMs. +* Cloud-init[^1] and Ignition[^2] which are targeting Linux and Unix systems +* Sysprep[^3] to initialize Windows-based VMs -Cloud-Init is the most widely adopted method, and you will find great support on cloud providers such as AWS, GCP and Azure. +Cloud-init is the most-widely adopted method, and you will find great support on cloud providers such as AWS, GCP and Azure. ## Can I run these tools with every disk image? -No, the Disk/System must include the software to run cloud-init, Ignition or Sysprep. This means that you have to use special images/disks. -They are usually called **Cloud Images** and are pre-installed disk images that can be customized using startup scripts. +No, the disk/system must include the software to run cloud-init, Ignition or Sysprep. This means that you have to use special images/disks. +They are usually called **cloud images** and are pre-installed disk images that can be customized using startup scripts. Some variants are: * Fedora Cloud: https://fedoraproject.org/de/cloud/ @@ -30,7 +30,6 @@ Some variants are: Most of them are also directly available on your cloud provider. - -[^1]: [cloud-init](https://cloud-init.io/) +[^1]: [Cloud-init](https://cloud-init.io/) [^2]: [Ignition](https://coreos.github.io/ignition/) [^3]: [Sysprep](https://learn.microsoft.com/de-de/windows-hardware/manufacture/desktop/sysprep--system-preparation--overview?view=windows-11)