4.3. Ignition

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.

Known users of Ignition are:

  • Fedora CoreOS
  • Red Hat Enterprise Linux CoreOS
  • Flatcar
  • openSUSE MicroOS
  • SUSE Linux Enterprise Micro

Supported data sources

To provide Ignition data we have to use the cloudInitNoCloud data source.

cloudInitNoCloud data source

The relevant configuration of a cloudInitNoCloud data source in a VM looks like this:

volumes:
  - name: ignitiondisk
    cloudInitNoCloud:
      userData: |
        {
          "ignition": {
            "version": "3.2.0"
          },
          [...]
        }        

Similar to cloud-init, this volume must be referenced after the VM disk in the spec.template.spec.domain.devices.disks section:

- name: ignitiondisk
  disk:
    bus: virtio

Using the cloudInitConfigDrive attribute gives us the following possibilities to provide our 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 .

Task 4.3.1: 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.

First, we define our configuration. Create a file ignition-data.yaml in the folder labs/lab04 with the following content:

{
  "ignition": {
    "version": "3.4.0"
  },
  "passwd": {
    "users": [
      {
        "name": "core",
        "passwordHash": "[...]"
      }
    ]
  }
}

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:

Using OpenSSL:

openssl passwd -salt xyz <PASSWORD>

Using Python’s crypt module:

python -c 'import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))'

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.

Solution

If you generated the password hash using the OpenSSL command openssl passwd -salt xyz kubevirt, then the ignition-data.yaml should look like:

{
  "ignition": {
    "version": "3.4.0"
  },
  "passwd": {
    "users": [
      {
        "name": "core",
        "passwordHash": "$1$xyz$I30aASnHH5bA2yVRoRlsI1"
      }
    ]
  }
}

To create the Kubernetes Secret, run the following command:

kubectl create secret generic lab04-ignition --from-file=userdata=labs/lab04/ignition-data.yaml --namespace lab-<username>

Task 4.3.2: Creating a VirtualMachine using Ignition

Create a file vm_lab04-ignition.yaml in the folder labs/lab04 and start with the following VM configuration:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: lab04-ignition
spec:
  runStrategy: Halted
  template:
    metadata:
      labels:
        kubevirt.io/domain: lab04-ignition
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            masquerade: {}
        resources:
          requests:
            memory: 2Gi
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/fedora/fedora-coreos-kubevirt:stable

Similar to the cloud-init section, alter the configuration above to include our Ignition config.

Task hint

Your VirtualMachine configuration should look like this:

apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: lab04-ignition
spec:
  runStrategy: Halted
  template:
    metadata:
      labels:
        kubevirt.io/domain: lab04-ignition
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
            - name: ignitiondisk
              disk:
                bus: virtio
          interfaces:
            - name: default
              masquerade: {}
        resources:
          requests:
            memory: 2Gi
      networks:
        - name: default
          pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/fedora/fedora-coreos-kubevirt:stable
        - name: ignitiondisk
          cloudInitConfigDrive:
            secretRef:
              name: lab04-ignition

Create your VM with:

kubectl apply -f labs/lab04/vm_lab04-ignition.yaml --namespace lab-<username>

Start the VM and verify whether logging in with the defined user and password works as expected.

Solution

Start the newly created VM. This might take a couple of minutes:

virtctl start lab04-ignition --namespace lab-<username>

Connect to the console and log in as soon as the prompt shows up with the defined credentials:

virtctl console lab04-ignition --namespace lab-<username>

Task 4.3.3: Enhance your startup script

With the help of the referenced documentation and examples , 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 lab04-ignition-<username>
  • Configure the SSH daemon with:
    • Disable root login
    • Only allow group ssh-users to login via ssh

Generate your ssh key with the following command:

ssh-keygen

Your ssh key to be used in the sshAuthorizedKeys is located in /home/theia/.ssh/id_rsa.pub. Get your key with:

cat /home/theia/.ssh/id_rsa.pub

Your output should be similar to:

ssh-rsa AAAAB3NzaC[...] theia@<username>-webshell-554b45d885-b79ks

Make sure the key starts with ssh-rsa and copy the key to the sshAuthorizedKeys attribute.

Task hint

Make sure you replace passwordHash (line 19) and sshAuthorizedKeys (line 21). Your Ignition configuration will look like this:

{
  "ignition": {
    "config": {},
    "version": "3.4.0"
  },
  "passwd": {
    "groups": [
      {
        "name": "ssh-users"
      }
    ],
    "users": [
      {
        "name": "core",
        "groups": [
          "docker",
          "ssh-users"
        ],
        "passwordHash": "[...]",
        "sshAuthorizedKeys": [
          "ssh-rsa AAAAB3NzaC[...] theia@<username>-webshell-554b45d885-b79ks"
        ]
      }
    ]
  },
  "storage": {
    "files": [
      {
        "path": "/etc/hostname",
        "mode": 420,
        "overwrite": true,
        "contents": { "source": "data:,lab04-ignition-<username>" }
      },
      {
        "path": "/etc/ssh/sshd_config.d/30-disable-rootlogin.conf",
        "mode": 644,
        "overwrite": true,
        "contents": { "source": "data:,PermitRootLogin%20no" }
      },
      {
        "path": "/etc/ssh/sshd_config.d/30-allow-groups.conf",
        "mode": 644,
        "overwrite": true,
        "contents": { "source": "data:,AllowGroups%20ssh-users" }
      }
    ]
  }
}

You need to recreate your Secret:

kubectl delete secret lab04-ignition --namespace lab-<username>
kubectl create secret generic lab04-ignition --from-file=userdata=labs/lab04/ignition-data.yaml --namespace lab-<username>

Next, we need to restart our VM to pick up the changes in the Ignition configuration.

virtctl restart lab04-ignition --namespace lab-<username>

Task 4.3.4: 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 called service-ignition.yaml in the folder labs/lab04 with the following content:

apiVersion: v1
kind: Service
metadata:
  name: lab04-ignition
spec:
  ports:
  - port: 22
    protocol: TCP
    targetPort: 22
  selector:
    kubevirt.io/domain: lab04-ignition
  type: ClusterIP

And create it with:

kubectl apply -f  labs/lab04/service-ignition.yaml --namespace lab-<username>

You may now be able to login with SSH from your webshell to your VM:

ssh core@lab04-ignition.lab-<username>.svc.cluster.local

And hit yes to confirm the authenticity of host.

Fedora CoreOS 43.20251028.3.0
Tracker: https://github.com/coreos/fedora-coreos-tracker
Discuss: https://discussion.fedoraproject.org/tag/coreos

Last login: Fri Aug 23 12:21:09 2024

Make sure to switch back to the user core and verify your assigned groups with:

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 lab04-ignition. Show the configured hostname:

hostname

We should see our postfix -<username> added to our hostname:

lab04-ignition-<username>

Task 4.3.5: (Optional) Expose ssh as NodePort to the internet

In this optional lab we will expose the ssh service as a node port to the external world, similar to what we did in .

  • Create a NodePort Service
  • Find out the port number
  • Get the IP address of one of the Kubernetes nodes
  • Test it
Solution

Create the NodePort Service:

virtctl expose vmi lab04-ignition --name=lab04-ignition-ssh-np --port=22 --type=NodePort --namespace lab-<username>

Find out the port number:

kubectl get service --namespace lab-<username>

Get the IP address of one of the Kubernetes nodes:

kubectl get nodes --selector=node-role.kubernetes.io/master!=true -o jsonpath={.items[*].status.addresses[?\(@.type==\"ExternalIP\"\)].address} --namespace lab-<username>

or

kubectl get nodes -o wide

Test it:

ssh core@<node-ip> -p <port>

End of lab

References

You may find additional information about Ignition here: