diff --git a/config/_default/config.toml b/config/_default/config.toml index 64610b8..078a8f5 100644 --- a/config/_default/config.toml +++ b/config/_default/config.toml @@ -86,6 +86,8 @@ maxlabnumber = 7 end-of-lab-title = "Cleaning up resources" end-of-lab-text = "You have reached the end of this lab. Please stop your running virtual machines to save resources on the Kubernetes cluster." +exampleWebAppImage = "quay.io/acend/example-web-python:latest" + # Cloud-init - Fedora Cloud #fedoraCloudCDI = "kubevirt/fedora-cloud-container-disk-demo:latest" # fedora cloud 32 fedoraCloudCDI = "quay.io/containerdisks/fedora:40" @@ -98,6 +100,9 @@ cirrosCDI = "quay.io/kubevirt/cirros-container-disk-demo" cirrosContainerDiskDownload = "https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img" alpineContainerDiskDownload = "https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/cloud/nocloud_alpine-3.20.2-x86_64-bios-cloudinit-r0.qcow2" +nodeExporter = "https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz" +nodeExporterVersion = "1.8.2" + dummypwd = "changeme" [params.ui] diff --git a/content/en/docs/superlab/_index.md b/content/en/docs/superlab/_index.md new file mode 100644 index 0000000..425d3d9 --- /dev/null +++ b/content/en/docs/superlab/_index.md @@ -0,0 +1,23 @@ +--- +title: "Super Lab" +weight: 9 +labfoldernumber: "09" +description: > + Deploy a sample application mixing virtual machines and containerized workload. +--- + +In this section we will deploy a Fedora based virtual machine hosting a MariaDB database. We will also deploy a simple +containerized web application which accesses the virtual machine using the default kubernetes pod network. + + +## Lab goals + +* Build your own sample application using concepts like + * VM disk creation using DataVolumes + * Disk preparation using provisioning virtual machines + * Cloud-Init startup scripts + * Instance types and preferences + * Mounting secrets and additional disks + * Exposing ports using services + * Mixing virtual machine workload and virtual machine workload + * Provide metrics for prometheus monitoring diff --git a/content/en/docs/superlab/requirements.md b/content/en/docs/superlab/requirements.md new file mode 100644 index 0000000..d9e3c3c --- /dev/null +++ b/content/en/docs/superlab/requirements.md @@ -0,0 +1,276 @@ +--- +title: "Requirements" +weight: 91 +labfoldernumber: "09" +description: > + Requirements for the demo application. +--- + +For this super lab we do not provide a step-by-step guide for the implementation. The goal is that you implement the required +manifests yourself. However, provide a sample solution in the next chapter. + + +## Basic Information + +The goal of this super lab is to deploy a database and a web application connecting to this database. The database should +be run within a KubeVirt virtual machine. As the web application you will use a provided application. + +The setup should fulfill the following requirements: + +Namespace: + +* Use the same namespace as for your previous labs (``) + +Virtual machine: + +* Operating System: Fedora Cloud 40 + * Recommended image: `{{% param "fedoraCloudCDI" %}}` +* MariaDB database +* Node Exporter + +Web application: + +* Python Example Web Application from acend. + * Image: `{{% param "exampleWebAppImage" %}}` +* The webapp will listen on port `5000` +* The connection to the database can be configured with the environment variable `MYSQL_URI=mysql://user:password@hostname/database-name` + +To reduce the startup time of the database, we recommend to use persistent disk. Pre-provision this generic database vm disk +with the mariadb package and the setup for the node exporter. Use a provisioning virtual machine using cloud-init scripts +to prepare the disk. + +The virtual machine running the mariadb instance should clone the pre-provisioned vm disk. Additionally, this instance +should mount another empty `1Gi` disk for the data folder of the database. Use cloud-init to create and configure the database +users, create the database, start the required services and do the basic virtual machine configuration. For example for the +resource usage you are encouraged to define and use VirtualMachineInstanceType and VirtualMachinePreference. + +You should use a secret to store the database details. All components (database and webapp) should have health-checks. + + +### Required details + +Database users and password + +* database-name: acend_exampledb +* database-user: acend_user +* database-password: mysqlpassword +* database-root-password: mysqlrootpassword + + +## Advanced information + +{{% alert title="Note" color="info" %}} +Here you'll find more useful information and hints for the setup. If you like you can skip this section and start implementing on your own. +{{% /alert %}} + +{{% details title="Show overview graphic" %}} +![Superlab Overview](../superlab-overview.png) +{{% /details %}} + + +### Disk provisioning + +* Use a DataVolume to download the fedora image `{{% param "fedoraCloudCDI" %}}` to a vm disk. + * Use this disk as the disk for the provisioning virtual machine +* Your virtual machine should use the `runStrategy: RerunOnFailure` +* Cloud-Init script should: + * Install `mariadb-server` package + * Create a system user `node_exporter` with a group `node_exporter` and the login shell `/bin/nologin` + * Download node-exporter from `{{% param "nodeExporter" %}}` + * Create a systemd service file to easily start the node exporter. You can find some details [here](https://gist.github.com/jarek-przygodzki/735e15337a3502fea40beba27e193b04). + * Configure the node exporter to run on port `9100`. + * Do some cleanup + * Remove the ssh host files `/etc/ssh/ssh_host_*` + * Remove the `/var/lib/cloud/instances` directory to re-run cloud-init + * Shutdown the virtual machine + +You most likely need a cloud-init script like: +```yaml +#cloud-config-archive +- type: "text/cloud-config" + content: | + packages: + [...] + users: + [...] + write_files: + [...] +- type: "text/x-shellscript" + content: | + #!/bin/sh + # install node_exporter + # [...] + # cleanup + # [...] + shutdown now +``` + +{{% details title="Hint for node exporter" %}} +Installation of node exporter: +```shell +curl -fsSL {{% param "nodeExporter" %}} | \ + sudo tar -zxvf - -C /usr/local/bin --strip-components=1 node_exporter-{{% param "nodeExporterVersion" %}}.linux-amd64/node_exporter && \ + sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter +``` + +Systemd service file `/etc/systemd/system/node_exporter.service`. +```shell +[Unit] +Description=Node Exporter +After=network.target + +[Service] +User=node_exporter +Group=node_exporter +# Fallback when environment file does not exist +Environment=OPTIONS= +EnvironmentFile=-/etc/sysconfig/node_exporter +ExecStart=/usr/local/bin/node_exporter $OPTIONS + +[Install] +WantedBy=multi-user.target +``` +{{% /details %}} + + +### Database virtual machine + +* Use a DataVolume to clone the vm disk and another DataVolume to create an empty disk. + * Use the cloned disk as the root disk for the database virtual machine + * Mount the additional disk on `/var/lib/mysql` +* Your virtual machine should use the `runStrategy: RerunOnFailure` +* Create a secret containing + * The database details + * An init script for your mariadb database +* Cloud-Init script should: + * Set password for fedora user + * Mount secret with mysql details using virtiofs + * Mount additional disk for the database data + * Enable and start the mariadb and node_exporter service + * Load the database init script + * Create a kubernetes Service for the node exporter and mariadb +* The easiest health checks are tcp probes against the mariadb port + +You most likely need a cloud-init script like: +```yaml +#cloud-config +password: +chpasswd: +bootcmd: + [...] +mounts: + [...] +runcmd: + [...] +``` + +Be aware of the runtime order of the cloud-init modules and place the commands accordingly. By default, the mounted disks are accessible by root. You may fix the permissions for the mysql user: + +```shell +sudo chown mysql:mysql /var/lib/mysql +sudo chmod 0751 /var/lib/mysql +``` + +{{% details title="Hint for secret creation and database init script" %}} +Basic `init.sql` script to setup the database: +```sql +ALTER USER 'root'@'localhost' IDENTIFIED BY 'mysqlrootpassword'; +CREATE DATABASE acend_exampledb; +CREATE USER 'acend_user'@'%' identified by 'mysqlpassword'; +GRANT ALL PRIVILEGES ON acend_exampledb.* TO 'acend_user'@'%'; +FLUSH PRIVILEGES; +``` + +Creating a secret containing the values for the database as well as the init script can be done with: +```shell +kubectl create secret generic lab09-mariadb \ + --from-literal=database-name=acend_exampledb \ + --from-literal=database-password=mysqlpassword \ + --from-literal=database-root-password=mysqlrootpassword \ + --from-literal=database-user=acend_user \ + --from-file=init.sql=init.sql +``` +{{% /details %}} + + +### Web application + +* Create a deployment for the web application +* In the deployment you need to set environment variable `MYSQL_URI` + * Use the values (database-user, database-password, database-name) from the secret created above. +* The webapp has a `/health` rest endpoint to be used for health checks +* Create a service targeting port `5000` of the deployed webapp. +* Create an ingress pointing to the service of your webapp + +Your ingress will be similar to: + +```shell +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + [...] +spec: + rules: + - host: webapp-. + http: + paths: + - path: / + pathType: Prefix + backend: + service: + [...] + tls: + - hosts: + - webapp-. +``` + +Make sure you replace the occurrences of + +* `` - your username (eg. `user4`) +* `` - ask the trainer + +with the appropriate values. + + +{{% details title="Configuration Hint" %}} +The configuration of the webapp is done with environment variables. Your config will look similar to this one: +```shell +apiVersion: apps/v1 +kind: Deployment +metadata: + [...] +spec: + [...] + template: + [...] + spec: + containers: + - image: quay.io/acend/example-web-python:latest + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + [...] + env: + - name: MYSQL_DATABASE_NAME + valueFrom: + secretKeyRef: + key: database-name + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_PASSWORD + valueFrom: + secretKeyRef: + key: database-password + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_ROOT_PASSWORD + valueFrom: + secretKeyRef: + key: database-root-password + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_USER + valueFrom: + secretKeyRef: + key: database-user + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_URI + value: mysql://$(MYSQL_DATABASE_USER):$(MYSQL_DATABASE_PASSWORD)@{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb/$(MYSQL_DATABASE_NAME) +``` +{{% /details %}} + diff --git a/content/en/docs/superlab/solution.md b/content/en/docs/superlab/solution.md new file mode 100644 index 0000000..57b3b03 --- /dev/null +++ b/content/en/docs/superlab/solution.md @@ -0,0 +1,383 @@ +--- +title: "Sample Solution" +weight: 92 +labfoldernumber: "09" +description: > + Sample solution for the super lab. +--- + +As we did not provide a step-by-step guide for the super lab, you can find a sample solution for the lab as kubernetes resources. This is a sample solution and your outcome may vary. +The following code blocks contain multiple manifests separated with `---`. You can write them to one file (e.g. `multiple-manifests.yaml`) and apply them all together. + +Make sure all occurrences of + +* `` - your username (eg. `user4`) +* `` - ask the trainer + +are replaced accordingly, before creating the manifests with: + +```shell +kubectl create -f multiple-manifests.yaml +``` + +If you want to inspect the used cloud-init scripts you can decode the base64 string from the secrets in the code blocks below. Copy the base64 string and use the following command: +```shell +echo -n "" | base64 -d +``` + + +## Provision the Fedora MariaDB database disk + +To create a template disk for spinning up MariaDB database instances we used the following kubernetes manifests. + +```yaml +apiVersion: cdi.kubevirt.io/v1beta1 +kind: DataVolume +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-base +spec: + source: + registry: + url: "{{% param "fedoraCloudCDI" %}}" + pvc: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 6Gi +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit-mariadb-provisioner +data: + userdata: I2Nsb3VkLWNvbmZpZy1hcmNoaXZlCi0gdHlwZTogInRleHQvY2xvdWQtY29uZmlnIgogIGNvbnRlbnQ6IHwKICAgIHBhY2thZ2VzOgogICAgICAtIG1hcmlhZGItc2VydmVyCiAgICB1c2VyczoKICAgICAgLSBuYW1lOiBub2RlX2V4cG9ydGVyCiAgICAgICAgZ2Vjb3M6IE5vZGUgRXhwb3J0ZXIgVXNlcgogICAgICAgIHByaW1hcnlfZ3JvdXA6IG5vZGVfZXhwb3J0ZXIKICAgICAgICBncm91cHM6IG5vZGVfZXhwb3J0ZXIKICAgICAgICBzaGVsbDogL2Jpbi9ub2xvZ2luCiAgICAgICAgc3lzdGVtOiB0cnVlCiAgICB3cml0ZV9maWxlczoKICAgICAgLSBjb250ZW50OiB8CiAgICAgICAgICBbVW5pdF0KICAgICAgICAgIERlc2NyaXB0aW9uPU5vZGUgRXhwb3J0ZXIKICAgICAgICAgIEFmdGVyPW5ldHdvcmsudGFyZ2V0CiAgICAgICAgICAKICAgICAgICAgIFtTZXJ2aWNlXQogICAgICAgICAgVXNlcj1ub2RlX2V4cG9ydGVyCiAgICAgICAgICBHcm91cD1ub2RlX2V4cG9ydGVyCiAgICAgICAgICAjIEZhbGxiYWNrIHdoZW4gZW52aXJvbm1lbnQgZmlsZSBkb2VzIG5vdCBleGlzdAogICAgICAgICAgRW52aXJvbm1lbnQ9T1BUSU9OUz0KICAgICAgICAgIEVudmlyb25tZW50RmlsZT0tL2V0Yy9zeXNjb25maWcvbm9kZV9leHBvcnRlcgogICAgICAgICAgRXhlY1N0YXJ0PS91c3IvbG9jYWwvYmluL25vZGVfZXhwb3J0ZXIgJE9QVElPTlMKICAgICAgICAgICAgICAgIAogICAgICAgICAgW0luc3RhbGxdCiAgICAgICAgICBXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldAogICAgICAgIHBhdGg6IC9ldGMvc3lzdGVtZC9zeXN0ZW0vbm9kZV9leHBvcnRlci5zZXJ2aWNlCiAgICAgIC0gY29udGVudDogfAogICAgICAgICAgT1BUSU9OUz0iLS13ZWIubGlzdGVuLWFkZHJlc3M9MC4wLjAuMDo5MTAwIgogICAgICAgIHBhdGg6IC9ldGMvc3lzY29uZmlnL25vZGVfZXhwb3J0ZXIKLSB0eXBlOiAidGV4dC94LXNoZWxsc2NyaXB0IiAgICAKICBjb250ZW50OiB8ICAgIAogICAgIyEvYmluL3NoICAgIAogICAgIyBpbnN0YWxsIG5vZGVfZXhwb3J0ZXIKICAgIGN1cmwgLWZzU0wgaHR0cHM6Ly9naXRodWIuY29tL3Byb21ldGhldXMvbm9kZV9leHBvcnRlci9yZWxlYXNlcy9kb3dubG9hZC92MS44LjIvbm9kZV9leHBvcnRlci0xLjguMi5saW51eC1hbWQ2NC50YXIuZ3ogfCBzdWRvIHRhciAtenh2ZiAtIC1DIC91c3IvbG9jYWwvYmluIC0tc3RyaXAtY29tcG9uZW50cz0xIG5vZGVfZXhwb3J0ZXItMS44LjIubGludXgtYW1kNjQvbm9kZV9leHBvcnRlciAmJiBzdWRvIGNob3duIG5vZGVfZXhwb3J0ZXI6bm9kZV9leHBvcnRlciAvdXNyL2xvY2FsL2Jpbi9ub2RlX2V4cG9ydGVyCiAgICAjIGNsZWFudXAKICAgIHJtIC1yZiAvZXRjL3NzaC9zc2hfaG9zdF8qCiAgICAjIHJlbW92aW5nIGluc3RhbmNlcyBlbnN1cmVzIGNsb3VkIGluaXQgd2lsbCBleGVjdXRlIGFnYWluIGFmdGVyIHJlYm9vdCAgICAKICAgIHJtIC1yZiAvdmFyL2xpYi9jbG91ZC9pbnN0YW5jZXMgICAgCiAgICBzaHV0ZG93biBub3cgCg== +type: Opaque +--- +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-provisioner +spec: + runStrategy: "RerunOnFailure" + template: + metadata: + labels: + kubevirt.io/domain: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-provisioner + spec: + domain: + devices: + disks: + - name: fedora-mariadb + disk: + bus: virtio + - name: cloudinitdisk + disk: + bus: virtio + interfaces: + - name: default + masquerade: {} + resources: + requests: + memory: 2Gi + {{< onlyWhen tolerations >}}tolerations: + - effect: NoSchedule + key: baremetal + operator: Equal + value: "true" + {{< /onlyWhen >}}networks: + - name: default + pod: {} + volumes: + - name: fedora-mariadb + persistentVolumeClaim: + claimName: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-base + - name: cloudinitdisk + cloudInitNoCloud: + secretRef: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit-mariadb-provisioner +``` + + +## Creating the Fedora MariaDB virtual machine + +To create a MariaDB database form the provisioned template disk we used the following kubernetes manifests. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb +spec: + ports: + - port: 3306 + selector: + kubevirt.io/domain: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + clusterIP: None +--- +apiVersion: v1 +kind: Service +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-node-exporter +spec: + ports: + - port: 9100 + protocol: TCP + targetPort: 9100 + selector: + kubevirt.io/domain: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + type: ClusterIP +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit-mariadb +data: + userdata: I2Nsb3VkLWNvbmZpZwpwYXNzd29yZDoga3ViZXZpcnQKY2hwYXNzd2Q6IHsgZXhwaXJlOiBGYWxzZSB9CnRpbWV6b25lOiBFdXJvcGUvWnVyaWNoCmJvb3RjbWQ6CiAgLSBzdWRvIHRlc3QgLXogIiQoc3VkbyBibGtpZCAvZGV2L3ZkYykiICYmIHN1ZG8gbWtmcyAtdCBleHQ0IC1MIGJsb2NrZGlzayAvZGV2L3ZkYyAKICAtIHN1ZG8gbWtkaXIgLXAgL3NlY3JldHMvbWFyaWFkYgogIC0gc3VkbyBtb3VudCAtdCB2aXJ0aW9mcyBtYXJpYWRiIC9zZWNyZXRzL21hcmlhZGIKbW91bnRzOgogIC0gWyIvZGV2L3ZkYyIsICIvdmFyL2xpYi9teXNxbCIsICJleHQ0IiwgImRlZmF1bHRzLG5vZmFpbCIsICIwIiwgIjIiIF0KcnVuY21kOgogICAtIHN1ZG8gY2hvd24gbXlzcWw6bXlzcWwgL3Zhci9saWIvbXlzcWwKICAgLSBzdWRvIGNobW9kIDA3NTEgL3Zhci9saWIvbXlzcWwKICAgLSBzdWRvIHN5c3RlbWN0bCBlbmFibGUgLS1ub3cgbWFyaWFkYgogICAtIHN1ZG8gc3lzdGVtY3RsIGVuYWJsZSAtLW5vdyBub2RlX2V4cG9ydGVyCiAgIC0gc3VkbyBteXNxbCAtdXJvb3QgPCAvc2VjcmV0cy9tYXJpYWRiL2luaXQuc3FsCgo= +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb +data: + database-name: YWNlbmRfZXhhbXBsZWRi + database-password: bXlzcWxwYXNzd29yZA== + database-root-password: bXlzcWxyb290cGFzc3dvcmQ= + database-user: YWNlbmRfdXNlcg== + init.sql: QUxURVIgVVNFUiAncm9vdCdAJ2xvY2FsaG9zdCcgSURFTlRJRklFRCBCWSAnbXlzcWxyb290cGFzc3dvcmQnOwpDUkVBVEUgREFUQUJBU0UgYWNlbmRfZXhhbXBsZWRiOwpDUkVBVEUgVVNFUiAnYWNlbmRfdXNlcidAJyUnIGlkZW50aWZpZWQgYnkgJ215c3FscGFzc3dvcmQnOwpHUkFOVCBBTEwgUFJJVklMRUdFUyBPTiBhY2VuZF9leGFtcGxlZGIuKiBUTyAnYWNlbmRfdXNlcidAJyUnOwpGTFVTSCBQUklWSUxFR0VTOwo= +type: Opaque +--- +apiVersion: cdi.kubevirt.io/v1beta1 +kind: DataVolume +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb +spec: + storage: + accessModes: + - ReadWriteOnce + source: + pvc: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-base + namespace: +--- +apiVersion: cdi.kubevirt.io/v1beta1 +kind: DataVolume +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-data +spec: + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + volumeMode: Filesystem + source: + blank: {} +--- +apiVersion: instancetype.kubevirt.io/v1beta1 +kind: VirtualMachineInstancetype +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-fedora-mariadb + labels: + instancetype.kubevirt.io/class: general.purpose + instancetype.kubevirt.io/cpu: "1" + instancetype.kubevirt.io/icon-pf: pficon-server-group + instancetype.kubevirt.io/memory: 2Gi + instancetype.kubevirt.io/vendor: kubevirt-basics-training + instancetype.kubevirt.io/version: "1" +spec: + cpu: + guest: 1 + memory: + guest: 2Gi +--- +apiVersion: instancetype.kubevirt.io/v1beta1 +kind: VirtualMachinePreference +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-fedora-mariadb + annotations: + iconClass: icon-fedora + openshift.io/display-name: Fedora MariaDB + tags: hidden,kubevirt,fedora,mariadb + labels: + app.kubernetes.io/component: kubevirt + instancetype.kubevirt.io/os-type: linux +spec: + devices: + preferredDiskBus: virtio + preferredInterfaceModel: virtio + requirements: + cpu: + guest: 1 + memory: + guest: 2Gi +--- +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb +spec: + runStrategy: RerunOnFailure + instancetype: + kind: VirtualMachineInstancetype + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-fedora-mariadb + preference: + kind: VirtualMachinePreference + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-fedora-mariadb + template: + metadata: + labels: + kubevirt.io/domain: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + spec: + domain: + devices: + filesystems: + - name: mariadb + virtiofs: {} + disks: + - name: fedora-disk + disk: {} + - name: cloudinitdisk + disk: {} + - name: mariadb-data + disk: {} + interfaces: + - name: default + masquerade: {} + readinessProbe: + initialDelaySeconds: 90 + tcpSocket: + port: 3306 + livenessProbe: + initialDelaySeconds: 90 + tcpSocket: + port: 3306 + networks: + - name: default + pod: {} + {{< onlyWhen tolerations >}}tolerations: + - effect: NoSchedule + key: baremetal + operator: Equal + value: "true" + {{< /onlyWhen >}}volumes: + - name: fedora-disk + persistentVolumeClaim: + claimName: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: cloudinitdisk + cloudInitNoCloud: + secretRef: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-cloudinit-mariadb + - name: mariadb-data + persistentVolumeClaim: + claimName: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb-data + - name: mariadb + secret: + secretName: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb +``` + + +## Creating the web application container + +With the following kubernetes manifests we start a web application pod connecting to our MariaDB database. + +```yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp +spec: + ports: + - port: 5000 + protocol: TCP + targetPort: 5000 + selector: + app: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + type: ClusterIP +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp +spec: + rules: + - host: webapp-. + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + port: + number: 5000 + tls: + - hosts: + - webapp-. +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp +spec: + replicas: 1 + selector: + matchLabels: + app: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 0 + type: RollingUpdate + template: + metadata: + labels: + app: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + spec: + containers: + - image: {{% param "exampleWebAppImage" %}} + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-webapp + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 50m + memory: 128Mi + readinessProbe: + httpGet: + path: /health + port: 5000 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 3 + env: + - name: MYSQL_DATABASE_NAME + valueFrom: + secretKeyRef: + key: database-name + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_PASSWORD + valueFrom: + secretKeyRef: + key: database-password + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_ROOT_PASSWORD + valueFrom: + secretKeyRef: + key: database-root-password + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_DATABASE_USER + valueFrom: + secretKeyRef: + key: database-user + name: {{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb + - name: MYSQL_URI + value: mysql://$(MYSQL_DATABASE_USER):$(MYSQL_DATABASE_PASSWORD)@{{% param "labsubfolderprefix" %}}{{% param "labfoldernumber" %}}-mariadb/$(MYSQL_DATABASE_NAME) +``` diff --git a/content/en/docs/superlab/superlab-overview.drawio b/content/en/docs/superlab/superlab-overview.drawio new file mode 100644 index 0000000..e531236 --- /dev/null +++ b/content/en/docs/superlab/superlab-overview.drawio @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/docs/superlab/superlab-overview.png b/content/en/docs/superlab/superlab-overview.png new file mode 100644 index 0000000..7605515 Binary files /dev/null and b/content/en/docs/superlab/superlab-overview.png differ