<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.cs.vt.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Carnold</id>
	<title>Computer Science Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.cs.vt.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Carnold"/>
	<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php/Special:Contributions/Carnold"/>
	<updated>2026-04-14T15:00:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4943</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4943"/>
		<updated>2025-10-28T13:02:55Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-secret.png]]&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-config.png]]&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
[[File:launch-mariadb-upgrade.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-storage.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-mount.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-health.png]]&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
Version updates to your manual deployment will have to be made manually.  If you use the &#039;&#039;&#039;lts&#039;&#039;&#039; tag &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; then anytime the pod is restarted then the newest version of the long term support image is pulled and ran.  If you a specific a version number tag, then you will need to manually change the version number to update.&lt;br /&gt;
&lt;br /&gt;
== Accessing ==&lt;br /&gt;
* By design, access to your database workload is limited to the internal network between your other workloads&lt;br /&gt;
* You can access the database through the command prompt on the running database pod&lt;br /&gt;
* You can create another workload with a database client installed&lt;br /&gt;
* You can use a web based database client and create an ingress to access it from external hosts.  See: [[HowTo:CS_Launch#Launch_an_App_Using_a_Public_Image]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4942</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4942"/>
		<updated>2025-10-14T14:55:06Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Ansible Script ==&lt;br /&gt;
The techstaff have provided an ansible script to install and setup your central storage allocation at: https://version.cs.vt.edu/techstaff/ansible/-/tree/main/roles/csCentralStorage&lt;br /&gt;
&lt;br /&gt;
You can also install manually following the instructions below.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4940</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4940"/>
		<updated>2025-10-02T17:50:21Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-secret.png]]&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-config.png]]&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
[[File:launch-mariadb-upgrade.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-storage.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-mount.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-health.png]]&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
Version updates to your manual deployment will have to be made manually.  If you use the &#039;&#039;&#039;lts&#039;&#039;&#039; tag &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; then anytime the pod is restarted then the newest version of the long term support image is pulled and ran.  If you a specific a version number tag, then you will need to manually change the version number to update.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4939</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4939"/>
		<updated>2025-10-02T17:47:58Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Launching a Database Using Helm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Creating a Secret ==&lt;br /&gt;
Kubernetes uses secrets to store sensitive information, such as passwords, in a secure manner.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-pass&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATE:&#039;&#039;&#039;  These instructions used to show how to deploy an App using the Bitnami helm charts.  Bitnami is now a paid product, so I have updated these instructions to use the groundhog2k helm charts which are currently community based.  See our separate wiki page on Bitnami to see the old instructions and tips on migrating existing Bitnami deployments: [[CS Launch Bitnami]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alternative&#039;&#039;&#039; You can also choose to deploy a database manually using an official docker image, see [[CS_Launch_MariaDB]]&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Groundhog2k.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;groundhog2k&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;mariadb&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
settings:&lt;br /&gt;
  # bug in chart requires this for now:&lt;br /&gt;
  allowEmptyRootPassword: true&lt;br /&gt;
  rootPassword:&lt;br /&gt;
    value: &#039;ChangeMe&#039;&lt;br /&gt;
storage:&lt;br /&gt;
  requestedSize: 1Gi&lt;br /&gt;
  keepPvc: true&lt;br /&gt;
userDatabase:&lt;br /&gt;
  name: &lt;br /&gt;
    value: &#039;test-db&#039;&lt;br /&gt;
  user: &lt;br /&gt;
    value: &#039;test&#039;&lt;br /&gt;
  password: &lt;br /&gt;
    value: &#039;Insecure&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-config.png&amp;diff=4938</id>
		<title>File:Launch-mariadb-config.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-config.png&amp;diff=4938"/>
		<updated>2025-10-02T17:46:03Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-secret.png&amp;diff=4937</id>
		<title>File:Launch-mariadb-secret.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-secret.png&amp;diff=4937"/>
		<updated>2025-10-02T17:45:47Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4936</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4936"/>
		<updated>2025-10-02T17:45:02Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-secret.png]]&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[File:launch-mariadb-config.png]]&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
[[File:launch-mariadb-upgrade.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-storage.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-mount.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-health.png]]&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4935</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4935"/>
		<updated>2025-10-02T17:40:22Z</updated>

		<summary type="html">&lt;p&gt;Carnold: Protected &amp;quot;CS Launch MariaDB&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
[[File:launch-mariadb-upgrade.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-storage.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-mount.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-health.png]]&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-health.png&amp;diff=4934</id>
		<title>File:Launch-mariadb-health.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-health.png&amp;diff=4934"/>
		<updated>2025-10-02T17:40:09Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-mount.png&amp;diff=4933</id>
		<title>File:Launch-mariadb-mount.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-mount.png&amp;diff=4933"/>
		<updated>2025-10-02T17:39:55Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-storage.png&amp;diff=4932</id>
		<title>File:Launch-mariadb-storage.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-storage.png&amp;diff=4932"/>
		<updated>2025-10-02T17:39:38Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-upgrade.png&amp;diff=4931</id>
		<title>File:Launch-mariadb-upgrade.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-upgrade.png&amp;diff=4931"/>
		<updated>2025-10-02T17:39:25Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4930</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4930"/>
		<updated>2025-10-02T17:39:06Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
[[File:launch-mariadb-upgrade.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-storage.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-mount.png]]&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:launch-mariadb-health.png]]&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-deployment.png&amp;diff=4929</id>
		<title>File:Launch-mariadb-deployment.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=File:Launch-mariadb-deployment.png&amp;diff=4929"/>
		<updated>2025-10-02T17:35:53Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4928</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4928"/>
		<updated>2025-10-02T17:35:25Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
[[File:launch-mariadb-deployment.png]]&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4927</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4927"/>
		<updated>2025-10-02T17:33:43Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt; or use a specific version that you want&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4926</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4926"/>
		<updated>2025-10-02T17:31:50Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Health Check&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exits with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Readiness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;30 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Liveness Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;120 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &#039;&#039;&#039;Command run inside the container exists with status 0&#039;&#039;&#039; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list under &#039;&#039;&#039;Startup Check&#039;&#039;&#039;&lt;br /&gt;
* Change &#039;&#039;&#039;Initial Delay&#039;&#039;&#039; to &amp;lt;code&amp;gt;10 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Timeout&#039;&#039;&#039; to &amp;lt;code&amp;gt;5 Sec.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Command to run&#039;&#039;&#039; with &amp;lt;code&amp;gt;bash -c &#039;healthcheck.sh --connect --innodb_initialized&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Failure Threshold&#039;&#039;&#039; to &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt;&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4925</id>
		<title>CS Launch MariaDB</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_MariaDB&amp;diff=4925"/>
		<updated>2025-10-02T17:23:28Z</updated>

		<summary type="html">&lt;p&gt;Carnold: Created page with &amp;quot;== Introduction == Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library  == Create Project and Namespace == You will need a project and namespace on CS Launch to deploy your database.  See HowTo:CS_Launch for instructions on doing this.  == Create Persistence Storage == Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.  * Navi...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Instructions for deploying a simple MariaDB database service on CS Launch using Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
&lt;br /&gt;
== Create Project and Namespace ==&lt;br /&gt;
You will need a project and namespace on CS Launch to deploy your database.  See [[HowTo:CS_Launch]] for instructions on doing this.&lt;br /&gt;
&lt;br /&gt;
== Create Persistence Storage ==&lt;br /&gt;
Your database will need a Persistent Volume Claim to store the data so that it is not lost between restarts.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;PersistentVolumeClaims&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with a namespace unique name, example: &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change &#039;&#039;&#039;Request Storage&#039;&#039;&#039; to the size of your storage requirements, example: &amp;lt;code&amp;gt;1 GiB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Passwords Secret ==&lt;br /&gt;
A secret is a secure way to store your deployments password information.&lt;br /&gt;
&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;MARIADB_ROOT_PASSWORD&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the root password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in additional &#039;&#039;&#039;Keys&#039;&#039;&#039;:&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_DATABASE&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test-db&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_USER&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;MARIADB_PASSWORD&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;Insecure&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create Custom Configurations ==&lt;br /&gt;
You can use a ConfigMap to storage custom configuration options.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with namespace unique name, example: &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my.cnf&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with your custom configuration options:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[mariadb]&lt;br /&gt;
### Put custom mariadb configurations here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Create the Deployment ==&lt;br /&gt;
Now you have all the components created, you can create the deployment itself.  We will create it as a &amp;quot;Deployment&amp;quot; to make it easier.  You can create as a StatefulSet to get a consistent pod name, but it is more work set up initially.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Deployments&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Workloads&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with the hostname you want other workloads to access the service by, example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Container Image&#039;&#039;&#039; with the version of mariadb docker image you want, example: &amp;lt;code&amp;gt;mariadb:lts&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Port or Service&#039;&#039;&#039; button&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Cluster IP&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Service Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in service &#039;&#039;&#039;Name&#039;&#039;&#039; with a port name example: &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Private Container Port&#039;&#039;&#039; with the database port: &amp;lt;code&amp;gt;3306&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click on &#039;&#039;&#039;Add Variable&#039;&#039;&#039; under &#039;&#039;&#039;Environment Variables&#039;&#039;&#039;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;Secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Type&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-secret&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Secret&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Scaling and Upgrade Policy&#039;&#039;&#039; under the &#039;&#039;&#039;Deployment&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;Recreate: kill ALL pods, then start new pods&#039;&#039;&#039; checkbox&lt;br /&gt;
** This tells the cluster to remove pods before restarting because multiple pods can not mount the PVC&lt;br /&gt;
* Click on the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;Pod&#039;&#039;&#039; tab&lt;br /&gt;
* Select &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-config&amp;lt;/code&amp;gt; under the &#039;&#039;&#039;ConfigMap&#039;&#039;&#039; drop down list&lt;br /&gt;
* Select &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; from the &#039;&#039;&#039;Add Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Change &#039;&#039;&#039;VolumeName&#039;&#039;&#039; to &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;mariadb-pvc&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Persistent Volume Claim&#039;&#039;&#039; drop down list&lt;br /&gt;
* Click on &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Click on &#039;&#039;&#039;Storage&#039;&#039;&#039; under the &#039;&#039;&#039;container-0&#039;&#039;&#039; tab&lt;br /&gt;
* Select &amp;lt;code&amp;gt;configuration&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/etc/mysql/conf.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Select &amp;lt;code&amp;gt;data&amp;lt;/code&amp;gt; from the &#039;&#039;&#039;Select Volume&#039;&#039;&#039; drop down list&lt;br /&gt;
* Fill in &#039;&#039;&#039;Mount Point&#039;&#039;&#039; with &amp;lt;code&amp;gt;/var/lib/mysql&amp;lt;/code&amp;gt;&lt;br /&gt;
* Finally, click on the &#039;&#039;&#039;Create&#039;&#039;&#039; button to start your deployment&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4924</id>
		<title>CS Launch Bitnami</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4924"/>
		<updated>2025-10-02T16:27:38Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
We used to support an encourage users to use the Bitnami helm charts for installing CS Launch Apps.  However, they have moved to a paid service so it is no longer feasible for us to use them.  Currently, we suggest to use either:&lt;br /&gt;
* Manual deployment of Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
** Example deployment: [[CS Launch MariaDB]]&lt;br /&gt;
* Groundhog2k helm charts (based on the Docker official images): https://github.com/groundhog2k/helm-charts&lt;br /&gt;
** Example deployment: [[HowTo:CS_Launch#Launching_a_Database_Using_Helm]]&lt;br /&gt;
&lt;br /&gt;
== Migration Strategies ==&lt;br /&gt;
If you have an existing Bitnami deployment that you need to keep active, then here are some strategies to keep your deployment working.&lt;br /&gt;
&lt;br /&gt;
=== Legacy Bitnami ===&lt;br /&gt;
The Bitnami crew are moving their images to a legacy repository.  Support for this is likely to be short term, and updates are unlikely.&lt;br /&gt;
* You should be able to immediately switch your &amp;lt;code&amp;gt;bitnami...&amp;lt;/code&amp;gt; images definitions to &amp;lt;code&amp;gt;bitnamilegacy...&amp;lt;/code&amp;gt; to continue working&lt;br /&gt;
&lt;br /&gt;
=== Full Replacement ===&lt;br /&gt;
Probably the best solution is to completely replace your Bitnami deployment to either a manual deployment of the Official Docker image or groundhog2k chart deployment.  This would involve the following steps:&lt;br /&gt;
* Backup all current data and configurations&lt;br /&gt;
* Delete Bitnami deployment&lt;br /&gt;
* Deploy new instance using an currently supported method&lt;br /&gt;
* Import the backup data&lt;br /&gt;
&lt;br /&gt;
=== In-Place Replacement ===&lt;br /&gt;
This method may require more work and intimate knowledge of how the deployment works.  The idea is to replace the existing Bitnami docker image with an official docker image that is maintained.  Some things to consider when trying this method:&lt;br /&gt;
* Make sure to make a backup of all data and configurations before attempting&lt;br /&gt;
* You will likely have to re-map existing configurations and secrets&lt;br /&gt;
* Data mounts might be different between the two images&lt;br /&gt;
* Make sure the application version is close to the same&lt;br /&gt;
* Future updates will have to be done manually instead of through the helm chart&lt;br /&gt;
&lt;br /&gt;
== Detailed Migration ==&lt;br /&gt;
We might provide more details instructions for popular deployments such as MariaDB, if needed.&lt;br /&gt;
&lt;br /&gt;
== Instructions Archive ==&lt;br /&gt;
Here is a copy of the old instructions using Bitnami for archive purposes.  These instructions will no longer be supported.&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: &#039;test-db&#039;&lt;br /&gt;
  username: &#039;test&#039;&lt;br /&gt;
  password: &#039;Insecure&#039;&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: &#039;1Gi&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4923</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4923"/>
		<updated>2025-10-02T14:45:04Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Launching a Database Using Helm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Creating a Secret ==&lt;br /&gt;
Kubernetes uses secrets to store sensitive information, such as passwords, in a secure manner.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-pass&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATE:&#039;&#039;&#039;  These instructions used to show how to deploy an App using the Bitnami helm charts.  Bitnami is now a paid product, so I have updated these instructions to use the groundhog2k helm charts which are currently community based.  See our separate wiki page on Bitnami to see the old instructions and tips on migrating existing Bitnami deployments: [[CS Launch Bitnami]]&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Groundhog2k.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;groundhog2k&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;mariadb&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
settings:&lt;br /&gt;
  # bug in chart requires this for now:&lt;br /&gt;
  allowEmptyRootPassword: true&lt;br /&gt;
  rootPassword:&lt;br /&gt;
    value: &#039;ChangeMe&#039;&lt;br /&gt;
storage:&lt;br /&gt;
  requestedSize: 1Gi&lt;br /&gt;
  keepPvc: true&lt;br /&gt;
userDatabase:&lt;br /&gt;
  name: &lt;br /&gt;
    value: &#039;test-db&#039;&lt;br /&gt;
  user: &lt;br /&gt;
    value: &#039;test&#039;&lt;br /&gt;
  password: &lt;br /&gt;
    value: &#039;Insecure&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4922</id>
		<title>CS Launch Bitnami</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4922"/>
		<updated>2025-10-02T14:17:56Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
We used to support an encourage users to use the Bitnami helm charts for installing CS Launch Apps.  However, they have moved to a paid service so it is no longer feasible for us to use them.  Currently, we suggest to use either:&lt;br /&gt;
* Manual deployment of Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
* Groundhog2k helm charts (based on the Docker official images): https://github.com/groundhog2k/helm-charts&lt;br /&gt;
&lt;br /&gt;
== Migration Strategies ==&lt;br /&gt;
If you have an existing Bitnami deployment that you need to keep active, then here are some strategies to keep your deployment working.&lt;br /&gt;
&lt;br /&gt;
=== Legacy Bitnami ===&lt;br /&gt;
The Bitnami crew are moving their images to a legacy repository.  Support for this is likely to be short term, and updates are unlikely.&lt;br /&gt;
* You should be able to immediately switch your &amp;lt;code&amp;gt;bitnami...&amp;lt;/code&amp;gt; images definitions to &amp;lt;code&amp;gt;bitnamilegacy...&amp;lt;/code&amp;gt; to continue working&lt;br /&gt;
&lt;br /&gt;
=== Full Replacement ===&lt;br /&gt;
Probably the best solution is to completely replace your Bitnami deployment to either a manual deployment of the Official Docker image or groundhog2k chart deployment.  This would involve the following steps:&lt;br /&gt;
* Backup all current data and configurations&lt;br /&gt;
* Delete Bitnami deployment&lt;br /&gt;
* Deploy new instance using an currently supported method&lt;br /&gt;
* Import the backup data&lt;br /&gt;
&lt;br /&gt;
=== In-Place Replacement ===&lt;br /&gt;
This method may require more work and intimate knowledge of how the deployment works.  The idea is to replace the existing Bitnami docker image with an official docker image that is maintained.  Some things to consider when trying this method:&lt;br /&gt;
* Make sure to make a backup of all data and configurations before attempting&lt;br /&gt;
* You will likely have to re-map existing configurations and secrets&lt;br /&gt;
* Data mounts might be different between the two images&lt;br /&gt;
* Make sure the application version is close to the same&lt;br /&gt;
* Future updates will have to be done manually instead of through the helm chart&lt;br /&gt;
&lt;br /&gt;
== Detailed Migration ==&lt;br /&gt;
We might provide more details instructions for popular deployments such as MariaDB, if needed.&lt;br /&gt;
&lt;br /&gt;
== Instructions Archive ==&lt;br /&gt;
Here is a copy of the old instructions using Bitnami for archive purposes.  These instructions will no longer be supported.&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: &#039;test-db&#039;&lt;br /&gt;
  username: &#039;test&#039;&lt;br /&gt;
  password: &#039;Insecure&#039;&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: &#039;1Gi&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4921</id>
		<title>CS Launch Bitnami</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4921"/>
		<updated>2025-10-02T14:09:39Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
We used to support an encourage users to use the Bitnami helm charts for installing CS Launch Apps.  However, they have moved to a paid service so it is no longer feasible for us to use them.  Currently, we suggest to use either:&lt;br /&gt;
* Manual deployment of Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
* Groundhog2k helm charts (based on the Docker official images): https://github.com/groundhog2k/helm-charts&lt;br /&gt;
&lt;br /&gt;
== Migration Strategies ==&lt;br /&gt;
If you have an existing Bitnami deployment that you need to keep active, then here are some strategies to keep your deployment working.&lt;br /&gt;
&lt;br /&gt;
=== Legacy Bitnami ===&lt;br /&gt;
The Bitnami crew are moving their images to a legacy repository.  Support for this is likely to be short term, and updates are unlikely.&lt;br /&gt;
* You should be able to immediately switch your &amp;lt;code&amp;gt;bitnami...&amp;lt;/code&amp;gt; images definitions to &amp;lt;code&amp;gt;bitnamilegacy...&amp;lt;/code&amp;gt; to continue working&lt;br /&gt;
&lt;br /&gt;
=== Full Replacement ===&lt;br /&gt;
Probably the best solution is to completely replace your Bitnami deployment to either a manual deployment of the Official Docker image or groundhog2k chart deployment.  This would involve the following steps:&lt;br /&gt;
* Backup all current data and configurations&lt;br /&gt;
* Delete Bitnami deployment&lt;br /&gt;
* Deploy new instance using an currently supported method&lt;br /&gt;
* Import the backup data&lt;br /&gt;
&lt;br /&gt;
=== In-Place Replacement ===&lt;br /&gt;
This method may require more work and intimate knowledge of how the deployment works.  The idea is to replace the existing Bitnami docker image with an official docker image that is maintained.  Some things to consider when trying this method:&lt;br /&gt;
* Make sure to make a backup of all data and configurations before attempting&lt;br /&gt;
* You will likely have to re-map existing configurations and secrets&lt;br /&gt;
* Data mounts might be different between the two images&lt;br /&gt;
&lt;br /&gt;
== Detailed Migration ==&lt;br /&gt;
We might provide more details instructions for popular deployments such as MariaDB, if needed.&lt;br /&gt;
&lt;br /&gt;
== Instructions Archive ==&lt;br /&gt;
Here is a copy of the old instructions using Bitnami for archive purposes.  These instructions will no longer be supported.&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: &#039;test-db&#039;&lt;br /&gt;
  username: &#039;test&#039;&lt;br /&gt;
  password: &#039;Insecure&#039;&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: &#039;1Gi&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4920</id>
		<title>CS Launch Bitnami</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Bitnami&amp;diff=4920"/>
		<updated>2025-10-02T13:54:59Z</updated>

		<summary type="html">&lt;p&gt;Carnold: Created page with &amp;quot;== Introduction == We used to support an encourage users to use the Bitnami helm charts for installing CS Launch Apps.  However, they have moved to a paid service so it is no longer feasible for us to use them.  Currently, we suggest to use either: * Manual deployment of Docker official images: https://hub.docker.com/u/library * Groundhog2k helm charts: https://github.com/groundhog2k/helm-charts  == Instructions Archive == Here is a copy of the old instructions using Bit...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
We used to support an encourage users to use the Bitnami helm charts for installing CS Launch Apps.  However, they have moved to a paid service so it is no longer feasible for us to use them.  Currently, we suggest to use either:&lt;br /&gt;
* Manual deployment of Docker official images: https://hub.docker.com/u/library&lt;br /&gt;
* Groundhog2k helm charts: https://github.com/groundhog2k/helm-charts&lt;br /&gt;
&lt;br /&gt;
== Instructions Archive ==&lt;br /&gt;
Here is a copy of the old instructions using Bitnami for archive purposes.  These instructions will no longer be supported.&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: &#039;test-db&#039;&lt;br /&gt;
  username: &#039;test&#039;&lt;br /&gt;
  password: &#039;Insecure&#039;&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: &#039;1Gi&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4919</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4919"/>
		<updated>2025-10-02T13:47:53Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Creating a Secret ==&lt;br /&gt;
Kubernetes uses secrets to store sensitive information, such as passwords, in a secure manner.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-secret&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;my-pass&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATE:&#039;&#039;&#039;  These instructions used to show how to deploy an App using the Bitnami helm charts.  Bitnami is now a paid product, so I have updated these instructions to use the groundhog2k helm charts which are currently community based.  See our separate wiki page on Bitnami to see the old instructions and tips on migrating existing Bitnami deployments: [[CS Launch Bitnami]]&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Groundhog2k.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;groundhog2k&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;mariadb&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
settings:&lt;br /&gt;
  # bug in chart requires this for now:&lt;br /&gt;
  allowEmptyRootPassword: true&lt;br /&gt;
storage:&lt;br /&gt;
  requestedSize: 1Gi&lt;br /&gt;
  keepPvc: true&lt;br /&gt;
userDatabase:&lt;br /&gt;
  name: &lt;br /&gt;
    value: &#039;test-db&#039;&lt;br /&gt;
  user: &lt;br /&gt;
    value: &#039;test&#039;&lt;br /&gt;
  password: &lt;br /&gt;
    value: &#039;Insecure&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4918</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4918"/>
		<updated>2025-10-02T13:19:13Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating a Secret ==&lt;br /&gt;
Kubernetes uses secrets to store sensitive information, such as passwords, in a secure manner.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Storage&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Opaque&#039;&#039; tile&#039;&#039;&#039; as this type of secret is suited for storing passwords&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Key&#039;&#039;&#039; with &amp;lt;code&amp;gt;rootpass&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fill in &#039;&#039;&#039;Value&#039;&#039;&#039; with what you want to use as the password, for example: &amp;lt;code&amp;gt;ChangeMe&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATE:&#039;&#039;&#039;  These instructions used to show how to deploy an App using the Bitnami helm charts.  Bitnami is now a paid product, so I have updated these instructions to use the groundhog2k helm charts which are currently community based.  See our separate wiki page on Bitnami to see the old instructions and tips on migrating existing Bitnami deployments: [[CS Launch Bitnami]]&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Groundhog2k.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;groundhog2k&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;mariadb&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
settings:&lt;br /&gt;
  existingSecret: mariadb&lt;br /&gt;
  rootPassword:&lt;br /&gt;
    secretKey: rootpass&lt;br /&gt;
storage:&lt;br /&gt;
  requestedSize: 1Gi&lt;br /&gt;
  keepPvc: true&lt;br /&gt;
userDatabase:&lt;br /&gt;
  name: &lt;br /&gt;
    value: &#039;test-db&#039;&lt;br /&gt;
  user: &lt;br /&gt;
    value: &#039;test&#039;&lt;br /&gt;
  password: &lt;br /&gt;
    value: &#039;Insecure&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4917</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4917"/>
		<updated>2025-10-02T13:13:09Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Launching a Database Using Helm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATE:&#039;&#039;&#039;  These instructions used to show how to deploy an App using the Bitnami helm charts.  Bitnami is now a paid product, so I have updated these instructions to use the groundhog2k helm charts which are currently community based.  See our separate wiki page on Bitnami to see the old instructions and tips on migrating existing Bitnami deployments: [[CS Launch Bitnami]]&lt;br /&gt;
&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Groundhog2k.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;groundhog2k&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;mariadb&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
settings:&lt;br /&gt;
  existingSecret: mariadb&lt;br /&gt;
  rootPassword:&lt;br /&gt;
    secretKey: root-pass&lt;br /&gt;
storage:&lt;br /&gt;
  requestedSize: 1Gi&lt;br /&gt;
  keepPvc: true&lt;br /&gt;
userDatabase:&lt;br /&gt;
  name: &lt;br /&gt;
    value: &#039;test-db&#039;&lt;br /&gt;
  user: &lt;br /&gt;
    value: &#039;test&#039;&lt;br /&gt;
  password: &lt;br /&gt;
    value: &#039;Insecure&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4916</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4916"/>
		<updated>2025-09-17T13:42:37Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Launching a Database Using Helm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt; or a unique hostname you want to give your database&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: &#039;test-db&#039;&lt;br /&gt;
  username: &#039;test&#039;&lt;br /&gt;
  password: &#039;Insecure&#039;&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: &#039;1Gi&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4909</id>
		<title>Spam Controls</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4909"/>
		<updated>2025-06-16T11:50:46Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== How To Use Computer Science Spam Controls ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction ===&lt;br /&gt;
Computer Science uses a spam fighting mail gateway to control spam emails.&lt;br /&gt;
&lt;br /&gt;
=== How it Works ===&lt;br /&gt;
The mail gateway analyses each incoming email and gives the message a spam score.  If the score is extremely high, then the message will be quarantined, which means it is held on the mail gateway to be reviewed by the receiver.  Moderately scored messages will get flagged by adding [***JUNK***] to the subject of the message and delivered.  Once a day or week, the system will send an email with a summary of all quarantined spams.  The email will include a web link to a site where you can review the quarantined spams and modify your personal whitelist and blacklist.  The site is IP restricted to VT campus/VPN.&lt;br /&gt;
&lt;br /&gt;
=== Whitelist ===&lt;br /&gt;
The system supports a personal whitelist and site-wide whitelist.  A personal whitelisted address will deliver to you even if the message scores high.  You can modify your personal whitelist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your whitelist or have a suggestion for a site-wide whitelist entry.&lt;br /&gt;
&lt;br /&gt;
=== Blacklist ===&lt;br /&gt;
The system supports personal blacklist and site-wide blacklist.  A personal blacklisted address will always try to be quarantined.  You can modify your personal blacklist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your blacklist or have a suggestion for a site-wide blacklist entry.&lt;br /&gt;
&lt;br /&gt;
=== Aliases and Mailing Lists ===&lt;br /&gt;
Each individual @cs.vt.edu email address is considered unique by the spam system and will have its own whitelist and blacklist.  For example, if johndoe@cs.vt.edu has an alias john@cs.vt.edu then both addresses will have a unique set of whitelists and blacklists.  The same applies to mailing lists.&lt;br /&gt;
* To modify the whitelist or blacklist of an alias or mailing list address, you will need to use the unique login link sent in the daily spam report to that specific address&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
The default action for CS email is filter junk flagged messages into a folder called &#039;&#039;&#039;caughtspam&#039;&#039;&#039;  You can turn off this filtering through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
* The new CS spam controls does not support an email interface, so the old spam reporting emails will no longer function: spam@cs.vt.edu, notspam@cs.vt.edu, etc.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4908</id>
		<title>Spam Controls</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4908"/>
		<updated>2025-06-09T15:25:47Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== How To Use Computer Science Spam Controls ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction ===&lt;br /&gt;
Computer Science uses a spam fighting mail gateway to control spam emails.&lt;br /&gt;
&lt;br /&gt;
=== How it Works ===&lt;br /&gt;
The mail gateway analyses each incoming email and gives the message a spam score.  If the score is extremely high, then the message will be quarantined, which means it is held on the mail gateway to be reviewed by the receiver.  Moderately scored messages will get flagged by adding [***JUNK***] to the subject of the message and delivered.  Once a day or week, the system will send an email with a summary of all quarantined spams.  The email will include a web link to a site where you can review the quarantined spams and modify your personal whitelist and blacklist.  The site is IP restricted to VT campus/VPN.&lt;br /&gt;
&lt;br /&gt;
=== Whitelist ===&lt;br /&gt;
The system supports a personal whitelist and site-wide whitelist.  A personal whitelisted address will deliver to you even if the message scores high.  You can modify your personal whitelist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your whitelist or have a suggestion for a site-wide whitelist entry.&lt;br /&gt;
&lt;br /&gt;
=== Blacklist ===&lt;br /&gt;
The system supports personal blacklist and site-wide blacklist.  A personal blacklisted address will always try to be quarantined.  You can modify your personal blacklist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your blacklist or have a suggestion for a site-wide blacklist entry.&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
The default action for CS email is filter junk flagged messages into a folder called &#039;&#039;&#039;caughtspam&#039;&#039;&#039;  You can turn off this filtering through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
* The new CS spam controls does not support an email interface, so the old spam reporting emails will no longer function: spam@cs.vt.edu, notspam@cs.vt.edu, etc.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4907</id>
		<title>Spam Controls</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Spam_Controls&amp;diff=4907"/>
		<updated>2025-06-09T15:25:34Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== How To Use Computer Science Spam Controls ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction ===&lt;br /&gt;
Computer Science uses a spam fighting mail gateway to control spam emails.&lt;br /&gt;
&lt;br /&gt;
=== How it Works ===&lt;br /&gt;
The mail gateway analyses each incoming email and gives the message a spam score.  If the score is extremely high, then the message will be quarantined, which means it is held on the mail gateway to be reviewed by the receiver.  Moderately scored messages will get flagged by adding [***JUNK***] to the subject of the message and delivered.  Once a day or week, the system will send an email with a summary of all quarantined spams.  The email will include a web link to a site where you can review the quarantined spams and modify your personal whitelist and blacklist.  The site is IP restricted to VT campus/VPN.&lt;br /&gt;
&lt;br /&gt;
=== Whitelist ===&lt;br /&gt;
The system supports a personal whitelist and site-wide whitelist.  A personal whitelisted address will deliver to you even if the message scores high.  You can modify your personal whitelist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your whitelist or have a suggestion for a site-wide whitelist entry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Blacklist ===&lt;br /&gt;
The system supports personal blacklist and site-wide blacklist.  A personal blacklisted address will always try to be quarantined.  You can modify your personal blacklist two ways:&lt;br /&gt;
* Through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
* Using the link from the spam system daily spam report message&lt;br /&gt;
&lt;br /&gt;
[[Contact Techstaff]] if have trouble editing your blacklist or have a suggestion for a site-wide blacklist entry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
The default action for CS email is filter junk flagged messages into a folder called &#039;&#039;&#039;caughtspam&#039;&#039;&#039;  You can turn off this filtering through the CS Intranet email controls: https://admin.cs.vt.edu/my-email/&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
* The new CS spam controls does not support an email interface, so the old spam reporting emails will no longer function: spam@cs.vt.edu, notspam@cs.vt.edu, etc.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4906</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4906"/>
		<updated>2025-05-08T16:25:00Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Launching a Database Using Helm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: test-db&lt;br /&gt;
  username: test&lt;br /&gt;
  password: Insecure&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: 1Gi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4905</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4905"/>
		<updated>2025-05-08T14:18:14Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch (formerly CS cloud) website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* We need to add the helm chart repository:&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Repositories&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Index URL&#039;&#039;&#039; with &amp;lt;code&amp;gt;https://charts.bitnami.com/bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: test-db&lt;br /&gt;
  username: test&lt;br /&gt;
  password: Insecure&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: 1Gi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4904</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4904"/>
		<updated>2025-04-18T12:42:51Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Video Demo ==&lt;br /&gt;
Link to a CS Launch demo created by Computer Science TA Wyatt Sweat: https://www.youtube.com/watch?v=BNmQfneAEzc&amp;amp;ab_channel=WyattSweat&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* We need to add the helm chart repository:&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Repositories&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Index URL&#039;&#039;&#039; with &amp;lt;code&amp;gt;https://charts.bitnami.com/bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: test-db&lt;br /&gt;
  username: test&lt;br /&gt;
  password: Insecure&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: 1Gi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;testdb.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Example 2: &amp;lt;code&amp;gt;chatbot.discovery.cs.vt.edu&amp;lt;/code&amp;gt;  The Discovery cluster on CS Launch allows you to map any *.discovery.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Grant_Proposal&amp;diff=4892</id>
		<title>Grant Proposal</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Grant_Proposal&amp;diff=4892"/>
		<updated>2025-01-09T19:05:26Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
This page has been created as a quick reference which gathers all the available resources in a single location for the purposes of writing Grant Proposals. If you see an outdated resource or a missing resource please contact techstaff@cs.vt.edu.&lt;br /&gt;
&lt;br /&gt;
= Resources Available in the Department =&lt;br /&gt;
== RLogin ==&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 32 Compute 5 GPU&lt;br /&gt;
*** Cores: 32 Intel&lt;br /&gt;
*** RAM: 384GB&lt;br /&gt;
*** Storage: 1TB&lt;br /&gt;
** Network: 10Gbit interconnect&lt;br /&gt;
&lt;br /&gt;
== CSRVM ==&lt;br /&gt;
To facilitate wide ranging research activities, some of the major services provided by the department include a Computer Science Research Virtual Machine cluster (CSRVM) which has the flexibility to create multi-core large scale VM&#039;s in a matter of minutes.  &lt;br /&gt;
&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 9&lt;br /&gt;
*** Cores: At least 64&lt;br /&gt;
*** Ram: 512GB&lt;br /&gt;
** Network: 10Gbit low latency SFP+ interconnect&lt;br /&gt;
** Storage: 143 terabytes of redundant CEPH disk storage.&lt;br /&gt;
&lt;br /&gt;
== CSRGPU ==&lt;br /&gt;
This GPU Virtual Machine cluster is dedicated to GPU computation research.  This is an excellent resource for prototyping small scale models in a virtual GPU environment before scaling up to larger hardware.&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 15&lt;br /&gt;
*** Cores: At least 40&lt;br /&gt;
*** Ram: At least 192GB&lt;br /&gt;
** GPUs: Multiple NVidia P40, T4, A2 GPUs&lt;br /&gt;
** Network: 10Gbit interconnect&lt;br /&gt;
** Storage: 174 TB of dedicated CEPH storage&lt;br /&gt;
&lt;br /&gt;
== Systems Cluster ==&lt;br /&gt;
In addition, Computer Science has a ten (10) node homogeneous cluster, dedicated to systems research.  &lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 10 (Homogeneous)&lt;br /&gt;
*** Cores: 48 (Intel)&lt;br /&gt;
*** RAM: 256GB&lt;br /&gt;
** Network: 10Gbit interconnect&lt;br /&gt;
** Storage: 73TB&lt;br /&gt;
&lt;br /&gt;
== Kubernetes Clusters ==&lt;br /&gt;
=== Discovery ===&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 24 (Compute)&lt;br /&gt;
*** Cores: 1100&lt;br /&gt;
*** RAM: 3.2TB&lt;br /&gt;
** Storage: 34TB&lt;br /&gt;
=== Endeavour ===&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 12 (Compute)&lt;br /&gt;
*** Cores: 728&lt;br /&gt;
*** GPU&#039;s: 12&lt;br /&gt;
*** RAM: 5.2TB&lt;br /&gt;
** Storage: 42TB&lt;br /&gt;
&lt;br /&gt;
== Shared Storage System ==&lt;br /&gt;
An on-premise robust shared storage system is available for departmental use.&lt;br /&gt;
* Hardware and software redundant storage&lt;br /&gt;
* Encrypted at rest&lt;br /&gt;
* Encryption in transit is available&lt;br /&gt;
* Can be mounted on multiple machines at the same time&lt;br /&gt;
* Available for use on kubernetes clusters&lt;br /&gt;
* Currently 180TB raw storage available&lt;br /&gt;
&lt;br /&gt;
== CBB: Mnemosyne ==&lt;br /&gt;
High memory computation system, dedicated to computational bioinformatics research.&lt;br /&gt;
* Hardware:&lt;br /&gt;
** Nodes: 1&lt;br /&gt;
*** Cores: 64 (Intel)&lt;br /&gt;
*** RAM: 7686GB&lt;br /&gt;
** Network: 10Gbit interconnected to Storage&lt;br /&gt;
** Storage: 30TB&lt;br /&gt;
&lt;br /&gt;
== Secure Server Room &amp;amp; Graduate Area ==&lt;br /&gt;
The Computer Science department has a secure, modern, climate-controlled server room.  The room is equipped with numerous sensors, controls, and backup systems to ensure all servers are continuously operating at peak performance.  In addition, there is a separate secure, climate-controlled workspace for graduate students to work directly with servers and equipment, if appropriate.&lt;br /&gt;
&lt;br /&gt;
= Resources Available from the University = &lt;br /&gt;
[https://arc.vt.edu/ Advanced Research Computing - ARC]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Ingress&amp;diff=4889</id>
		<title>CS Launch Ingress</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Ingress&amp;diff=4889"/>
		<updated>2024-12-03T12:35:34Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Adding an Annotation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This is guide a supplement to the [[HowTo:CS Launch]] guide.  It goes into more detail about CS Launch Ingress support.&lt;br /&gt;
&lt;br /&gt;
== Annotations ==&lt;br /&gt;
You can modify the behavior of your ingress using kubernetes annotations on your ingress resource.  A common example is to restrict access to certain IP ranges.  A full list of annotations and their descriptions can be found at: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md&lt;br /&gt;
&lt;br /&gt;
=== Adding an Annotation ===&lt;br /&gt;
You apply annotations by modifying the ingress resource object.    &lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Kebab&#039;&#039; menu&#039;&#039;&#039; for the ingress you want to edit, and select &#039;&#039;&#039;Edit Config&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Labels &amp;amp; Annotations&#039;&#039;&#039;&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Annotation&#039;&#039;&#039;&#039;&#039; button.&lt;br /&gt;
* &#039;&#039;&#039;Fill in&#039;&#039;&#039; the &#039;&#039;&#039;Key&#039;&#039;&#039; and &#039;&#039;&#039;Value&#039;&#039;&#039; fields.&lt;br /&gt;
* Alternatively, you can modify your YAML specification directly, example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apiVersion: networking.k8s.io/v1&lt;br /&gt;
kind: Ingress&lt;br /&gt;
metadata:&lt;br /&gt;
  annotations:&lt;br /&gt;
    nginx.ingress.kubernetes.io/rewrite-target: /$2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Common Annotations ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range&amp;lt;/code&amp;gt;&lt;br /&gt;
** Restricts ingress access to a specific set of IP ranges&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#whitelist-source-range&lt;br /&gt;
** To allow access from anywhere, set value to &amp;lt;code&amp;gt;0.0.0.0/0,::/0&amp;lt;/code&amp;gt;&lt;br /&gt;
** Example restricts to VT campus and VPN addresses: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range: 128.173.0.0/16,198.82.0.0/16,172.16.0.0/12,45.3.120.0/21,2001:468:c80::/48,2607:b400::/40&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/rewrite-target&amp;lt;/code&amp;gt;&lt;br /&gt;
** Modifies the URL path before sending upstream.  For example, to remove a leading path.&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#rewrite&lt;br /&gt;
** Example removes all path from request -- container sees the request to root path: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/rewrite-target: /&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/proxy-read-timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
** Increase timeout for proxy actions, defaults to 30 seconds&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#custom-timeouts&lt;br /&gt;
** Example increase timeout to 60 seconds: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/proxy-read-timeout: 60&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discovery Ingress ===&lt;br /&gt;
* By default ingresses on the &#039;&#039;Discovery&#039;&#039; cluster are IP limited to VT campus and VT VPN.  You can use &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range&amp;lt;/code&amp;gt; (see above) to restrict or expand this IP range.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=CS_Launch_Ingress&amp;diff=4888</id>
		<title>CS Launch Ingress</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=CS_Launch_Ingress&amp;diff=4888"/>
		<updated>2024-12-03T12:33:38Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Annotations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This is guide a supplement to the [[HowTo:CS Launch]] guide.  It goes into more detail about CS Launch Ingress support.&lt;br /&gt;
&lt;br /&gt;
== Annotations ==&lt;br /&gt;
You can modify the behavior of your ingress using kubernetes annotations on your ingress resource.  A common example is to restrict access to certain IP ranges.  A full list of annotations and their descriptions can be found at: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md&lt;br /&gt;
&lt;br /&gt;
=== Adding an Annotation ===&lt;br /&gt;
You apply annotations by modifying the ingress resource object.    &lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Kebab&#039;&#039; menu&#039;&#039;&#039; for the ingress you want to edit, and select &#039;&#039;&#039;Edit Config&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Labels &amp;amp; Annotations&#039;&#039;&#039;&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Annotation&#039;&#039;&#039;&#039;&#039; button.&lt;br /&gt;
* &#039;&#039;&#039;Fill in&#039;&#039;&#039; the &#039;&#039;&#039;Key&#039;&#039;&#039; and &#039;&#039;&#039;Value&#039;&#039;&#039; fields.&lt;br /&gt;
* Alternatively, you can modify your YAML specification directly, example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apiVersion: networking.k8s.io/v1&lt;br /&gt;
kind: Ingress&lt;br /&gt;
metadata:&lt;br /&gt;
    nginx.ingress.kubernetes.io/rewrite-target: /$2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Common Annotations ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range&amp;lt;/code&amp;gt;&lt;br /&gt;
** Restricts ingress access to a specific set of IP ranges&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#whitelist-source-range&lt;br /&gt;
** To allow access from anywhere, set value to &amp;lt;code&amp;gt;0.0.0.0/0,::/0&amp;lt;/code&amp;gt;&lt;br /&gt;
** Example restricts to VT campus and VPN addresses: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range: 128.173.0.0/16,198.82.0.0/16,172.16.0.0/12,45.3.120.0/21,2001:468:c80::/48,2607:b400::/40&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/rewrite-target&amp;lt;/code&amp;gt;&lt;br /&gt;
** Modifies the URL path before sending upstream.  For example, to remove a leading path.&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#rewrite&lt;br /&gt;
** Example removes all path from request -- container sees the request to root path: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/rewrite-target: /&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/proxy-read-timeout&amp;lt;/code&amp;gt;&lt;br /&gt;
** Increase timeout for proxy actions, defaults to 30 seconds&lt;br /&gt;
** https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#custom-timeouts&lt;br /&gt;
** Example increase timeout to 60 seconds: &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/proxy-read-timeout: 60&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Discovery Ingress ===&lt;br /&gt;
* By default ingresses on the &#039;&#039;Discovery&#039;&#039; cluster are IP limited to VT campus and VT VPN.  You can use &amp;lt;code&amp;gt;nginx.ingress.kubernetes.io/whitelist-source-range&amp;lt;/code&amp;gt; (see above) to restrict or expand this IP range.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Main_Page&amp;diff=4887</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Main_Page&amp;diff=4887"/>
		<updated>2024-12-03T12:31:14Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* List of Additional Resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the Computer Science Wiki! ==&lt;br /&gt;
&lt;br /&gt;
This wiki is used by techstaff to share documentation and common HowTos.  It can also be used by anyone in the department to share information.&lt;br /&gt;
&lt;br /&gt;
Use the links &amp;quot;Documentation&amp;quot; and &amp;quot;HowTos&amp;quot; in the main menu access the techstaff content.&lt;br /&gt;
&lt;br /&gt;
==Commonly Requested Information==&lt;br /&gt;
*[[Conference_Rooms|Using a Conference Room]]&lt;br /&gt;
*[[Network_Printers|Connect to a Network Printer]]&lt;br /&gt;
*[[User_Account_Policy|Create a CS User account]]&lt;br /&gt;
*[[Internet_Access|Get Connected to the Network]] (See this for IOT and VR Devices as well)&lt;br /&gt;
*[[Poster_Printing|Request for Poster Printing]]&lt;br /&gt;
*[[Email|Configure your Email]]&lt;br /&gt;
*[[Class_Information|Information for Specific Classes]]&lt;br /&gt;
*[[Grant_Proposal|Grant Proposal]]&lt;br /&gt;
*[[Google_Migration|Google Migration]]&lt;br /&gt;
*[[Lab_Leads_Program_Summary|Lab Leads Program Summary]]&lt;br /&gt;
&lt;br /&gt;
==Security Recommendations==&lt;br /&gt;
Techstaff has worked on a comprehensive guide for security which can be found here:&lt;br /&gt;
&lt;br /&gt;
 [[CS Security Guide]]. &lt;br /&gt;
&lt;br /&gt;
Below we have a quick overview of some of these topics. &lt;br /&gt;
&lt;br /&gt;
===Quick Overview===&lt;br /&gt;
&lt;br /&gt;
* Patching&lt;br /&gt;
** Maintaining a up-to-date patched OS is one of the best ways to prevent malicious attacks.&lt;br /&gt;
&lt;br /&gt;
*Firewalls&lt;br /&gt;
** To Restrict access to the VT main campus IP&#039;s use these:&lt;br /&gt;
*** IP: 172.16.0.0 Subnet: 255.240.0.0&lt;br /&gt;
*** IP: 128.173.0.0 Subnet: 255.255.0.0&lt;br /&gt;
*** IP: 198.82.0.0 Subnet: 255.255.0.0&lt;br /&gt;
*** IP: 45.3.120.0 Subnet: 255.255.248.0 (This is an additional block of IP&#039;s added for VPN users on March 17th, 2020)&lt;br /&gt;
&lt;br /&gt;
* Password Security&lt;br /&gt;
** [[Passwords]]&lt;br /&gt;
&lt;br /&gt;
==List of Additional Resources==&lt;br /&gt;
*[[HowTo:CS_Launch|Using CS Launch]]&lt;br /&gt;
*[[Doc::Faculty Resources|Faculty Resources]]&lt;br /&gt;
&lt;br /&gt;
==Other Information==&lt;br /&gt;
*Managing Inventory&lt;br /&gt;
*System Administration &amp;amp; Security&lt;br /&gt;
*Obtaining Software&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4886</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4886"/>
		<updated>2024-11-11T17:52:13Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Ansible Script ==&lt;br /&gt;
The techstaff have provided an ansible script to install and setup your central storage allocation at: https://version.cs.vt.edu/techstaff/ansible/-/tree/main/roles/csCentralStorage&lt;br /&gt;
&lt;br /&gt;
You can also install manually following the instructions below.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Doc::Secure&amp;diff=4885</id>
		<title>Doc::Secure</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Doc::Secure&amp;diff=4885"/>
		<updated>2024-11-11T13:59:31Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The department offers a security and vulnerability monitoring service.  It is primarily aimed at Linux based machines, but also supports Windows and Mac.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service is based on Wazuh (https://wazuh.com/).  It runs a lightweight agent on the endpoint that automatically scans the machine for vulnerabilities, and reports any alerts to our central service. Here are some examples of the type of things wazuh scans for:&lt;br /&gt;
* Malware detection&lt;br /&gt;
* Known software vulnerabilties&lt;br /&gt;
* File Integrity - changes to known system files&lt;br /&gt;
* Logs for active threats&lt;br /&gt;
&lt;br /&gt;
== Install ==&lt;br /&gt;
Installing the CS secure service is easy, and usually a set and forget operation.&lt;br /&gt;
&lt;br /&gt;
=== RPM based Linux ===&lt;br /&gt;
Run the following commands, requires sudo access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -o wazuh-agent-4.9.2-1.x86_64.rpm https://packages.wazuh.com/4.x/yum/wazuh-agent-4.9.2-1.x86_64.rpm&lt;br /&gt;
sudo WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=$&#039;secure&#039; rpm -ihv wazuh-agent-4.9.2-1.x86_64.rpm&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl enable --now wazuh-agent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other DEB based Linux ===&lt;br /&gt;
Run the following commands, request sudo access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.2-1_amd64.deb&lt;br /&gt;
sudo WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=$&#039;secure&#039; dpkg -i ./wazuh-agent_4.9.2-1_amd64.deb&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl enable --now wazuh-agent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
Run the following powershell commands, run as administrator:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.9.2-1.msi -OutFile $env:tmp\wazuh-agent; msiexec.exe /i $env:tmp\wazuh-agent /q WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039; &lt;br /&gt;
NET START WazuhSvc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Silicon based Mac ===&lt;br /&gt;
Run the following in a terminal shell, requires administrator access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -so wazuh-agent.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-4.9.2-1.arm64.pkg &amp;amp;&amp;amp; echo &amp;quot;WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; &amp;amp;&amp;amp; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039;&amp;quot; &amp;gt; /tmp/wazuh_envs &amp;amp;&amp;amp; sudo installer -pkg ./wazuh-agent.pkg -target /&lt;br /&gt;
sudo /Library/Ossec/bin/wazuh-control start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel based Mac ===&lt;br /&gt;
Run the following in a terminal shell, requires administrator access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -so wazuh-agent.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-4.9.2-1.intel64.pkg &amp;amp;&amp;amp; echo &amp;quot;WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; &amp;amp;&amp;amp; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039;&amp;quot; &amp;gt; /tmp/wazuh_envs &amp;amp;&amp;amp; sudo installer -pkg ./wazuh-agent.pkg -target /&lt;br /&gt;
sudo /Library/Ossec/bin/wazuh-control start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Alerts ===&lt;br /&gt;
Alerts will be monitored by Techstaff.  If you want to get emailed directly when alerts happen, [[Contact Techstaff]].&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Doc::Secure&amp;diff=4884</id>
		<title>Doc::Secure</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Doc::Secure&amp;diff=4884"/>
		<updated>2024-11-11T13:57:17Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The department offers a security and vulnerability monitoring service.  It is primarily aimed at Linux based machines, but also supports Windows and Mac.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service is based on Wazuh (https://wazuh.com/).  It runs a lightweight agent on the endpoint that automatically scans the machine for vulnerabilities, and reports any alerts to our central service. Here are some examples of the type of things wazuh scans for:&lt;br /&gt;
* Malware detection&lt;br /&gt;
* Known software vulnerabilties&lt;br /&gt;
* File Integrity - changes to known system files&lt;br /&gt;
* Logs for active threats&lt;br /&gt;
&lt;br /&gt;
== Install ==&lt;br /&gt;
Installing the CS secure service is easy, and usually a set and forget operation.&lt;br /&gt;
&lt;br /&gt;
=== RPM based Linux ===&lt;br /&gt;
Run the following commands, requires sudo access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -o wazuh-agent-4.9.2-1.x86_64.rpm https://packages.wazuh.com/4.x/yum/wazuh-agent-4.9.2-1.x86_64.rpm&lt;br /&gt;
sudo WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=$&#039;secure&#039; rpm -ihv wazuh-agent-4.9.2-1.x86_64.rpm&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl enable --now wazuh-agent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other DEB based Linux ===&lt;br /&gt;
Run the following commands, request sudo access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.2-1_amd64.deb&lt;br /&gt;
sudo WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=$&#039;secure&#039; dpkg -i ./wazuh-agent_4.9.2-1_amd64.deb&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl enable --now wazuh-agent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
Run the following powershell commands, run as administrator:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.9.0-1.msi -OutFile ${env.tmp}\wazuh-agent; msiexec.exe /i ${env.tmp}\wazuh-agent /q WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039;&lt;br /&gt;
NET START WazuhSvc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Silicon based Mac ===&lt;br /&gt;
Run the following in a terminal shell, requires administrator access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -so wazuh-agent.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-4.9.0-1.arm64.pkg &amp;amp;&amp;amp; echo &amp;quot;WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; &amp;amp;&amp;amp; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039;\n&amp;quot; &amp;gt; /tmp/wazuh_envs &amp;amp;&amp;amp; sudo installer -pkg ./wazuh-agent.pkg -target /&lt;br /&gt;
sudo /Library/Ossec/bin/wazuh-control start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel based Mac ===&lt;br /&gt;
Run the following in a terminal shell, requires administrator access:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -so wazuh-agent.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-4.9.0-1.intel64.pkg &amp;amp;&amp;amp; echo &amp;quot;WAZUH_MANAGER=&#039;secure.cs.vt.edu&#039; &amp;amp;&amp;amp; WAZUH_REGISTRATION_PASSWORD=&#039;secure&#039;\n&amp;quot; &amp;gt; /tmp/wazuh_envs &amp;amp;&amp;amp; sudo installer -pkg ./wazuh-agent.pkg -target /&lt;br /&gt;
sudo /Library/Ossec/bin/wazuh-control start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Note:&#039;&#039;&#039; If you have specific wazuh group that you want to join, you can add &amp;lt;code&amp;gt;WAZUH_AGENT_GROUP=&#039;&amp;lt;groupname&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Alerts ===&lt;br /&gt;
Alerts will be monitored by Techstaff.  If you want to get emailed directly when alerts happen, [[Contact Techstaff]].&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=Howto::VScode&amp;diff=4882</id>
		<title>Howto::VScode</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=Howto::VScode&amp;diff=4882"/>
		<updated>2024-11-01T11:32:57Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Visual Studio Code (vscode) is an increasing popular way of developing software on rlogin.cs.vt.edu.  With the appropriate plugin, it will allow you directly edit your files on rlogin.cs.vt.edu and make it easy to get a terminal to run and test your code.  These instructions are geared toward the Windows version of vscode, but should be easily adaptable to other operation systems.  These instruction also assume that you already have the latest version of vscode installed locally.&lt;br /&gt;
&lt;br /&gt;
== Plugin installation and configuration ==&lt;br /&gt;
* Make sure you also have an SSH client: https://code.visualstudio.com/docs/remote/troubleshooting#_installing-a-supported-ssh-client&lt;br /&gt;
* Click on the &amp;quot;Gear&amp;quot; icon and select &amp;quot;Extensions&amp;quot; OR push &amp;lt;ctr&amp;gt;-&amp;lt;shift&amp;gt;-x&lt;br /&gt;
* Search for &amp;quot;Remote - SSH&amp;quot;&lt;br /&gt;
* Click the &amp;quot;Install&amp;quot; button&lt;br /&gt;
* This should give you a small green button (bottom left) with &amp;quot;&amp;gt;&amp;lt;&amp;quot; icon&lt;br /&gt;
* Click on the green button and select &amp;quot;Connect to host...&amp;quot;&lt;br /&gt;
* Select &amp;quot;+ Add New SSH Host...&amp;quot;&lt;br /&gt;
* Type in &amp;quot;&amp;lt;username&amp;gt;@rlogin.cs.vt.edu -A&amp;quot; change &amp;lt;username&amp;gt; to your CS username.  Your username should be all lowercase.&lt;br /&gt;
* It should give you a dialog saying the host was added and a button to &amp;quot;Connect&amp;quot;&lt;br /&gt;
* When you first connect it will ask you what platform the host is, select &amp;quot;Linux&amp;quot;&lt;br /&gt;
* It will also likely ask for your password unless you already have a SSH key set up&lt;br /&gt;
* Once connected, the green button should update with &amp;quot;SSH: rlogin.cs.vt.edu&amp;quot; letting you know you are connected remotely&lt;br /&gt;
&lt;br /&gt;
== Set up SSH key authentication ==&lt;br /&gt;
* Setting up a public/private key will save you from having to enter your password so many times while using vscode&lt;br /&gt;
* While inside VS Code, hit &amp;lt;ctrl&amp;gt;-o to open a file, open the &#039;&#039;&#039;local&#039;&#039;&#039; file: &amp;quot;c:\Users\&amp;lt;username&amp;gt;\.ssh\id_rsa.pub&amp;quot;  If this file does not exist, then you can run &amp;quot;ssh-keygen&amp;quot; from the command to generate the file&lt;br /&gt;
* Copy the whole contents of this file&lt;br /&gt;
* Use VS code to edit the &#039;&#039;&#039;remote&#039;&#039;&#039; file: ~/.ssh/authorized_keys (if this is your first time, then you might have to create it as a new text file)&lt;br /&gt;
** Alternately, you can use the command line to SSH into rlogin.cs.vt.edu and edit the file directly using the command `nano ~/.ssh/authorized_keys`&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
* It is common to run into issues with vscode and remote SSH&lt;br /&gt;
* The first step to identifying the problem is to determine if the problem is with VS Code and it&#039;s server component or an SSH connectivity problem&lt;br /&gt;
** You can do this by opening a command prompt and run the command &amp;lt;code&amp;gt;ssh &amp;lt;username&amp;gt;@rlogin.cs.vt.edu&amp;lt;/code&amp;gt; replace &amp;lt;username&amp;gt; with your CS username&lt;br /&gt;
** If you can successfully connect this way, then the problem is likely a configuration issue with VS Code&lt;br /&gt;
** If this does not work, then the problem is likely SSH.&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting VS Code ===&lt;br /&gt;
* First try resetting the remote side by issuing the VS code command (ctrl-shift-p): &amp;quot;Remote-SSH: Kill VS Code Server on Host...&amp;quot;&lt;br /&gt;
* Make sure you are running the latest version of &amp;quot;Remote -SSH&amp;quot; extension (ctrl-shift-x) and that it is reloaded&lt;br /&gt;
* Check the extension settings by hitting (ctrl-shift-x) and click on the &amp;quot;gear&amp;quot; icon under &amp;quot;Remote - SSH&amp;quot; and select &amp;quot;Extension Settings&amp;quot;&lt;br /&gt;
* Make sure your account is not over disk quota.  SSH into rlogin outside of VS Code and try the following commands:&lt;br /&gt;
** &amp;lt;code&amp;gt;touch ~/test&amp;lt;/code&amp;gt; - This command will attempt to write the file ~/test  It will give an error if you are over your quota.&lt;br /&gt;
** &amp;lt;code&amp;gt;du -sh ~&amp;lt;/code&amp;gt; - This command will give you your total disk usage.&lt;br /&gt;
** &amp;lt;code&amp;gt;du -shx ~/*&amp;lt;/code&amp;gt; - This command will breakdown your disk usage for each directory and file in your home directory.  Note: this will not include top level &amp;quot;.&amp;quot; hidden files.  This will help you track down files that are taking up your disk space.&lt;br /&gt;
* Common settings:&lt;br /&gt;
** Make sure that &amp;quot;Remote Platform&amp;quot; is set to linux for rlogin.cs.vt.edu&lt;br /&gt;
** Make sure that &amp;quot;Config File&amp;quot; is set to a valid value, this is generally left blank&lt;br /&gt;
** Make sure that &amp;quot;Path&amp;quot; is set to a valid value, this is generally left blank which means it will use the Windows SSH client&lt;br /&gt;
* Lastly, you can try using SSH to connect rlogin.cs.vt.edu and manually remove the VS Code server directory by running the command &amp;lt;code&amp;gt;rm -rf ~/.vscode-server&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you still are unable to connect VS Code to rlogin.cs.vt.edu, then [[Contact Techstaff]] Sometimes a VS Code server component will get stuck and need to be killed&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting SSH ===&lt;br /&gt;
* If you get an error such as &amp;quot;&#039;&#039;not recognized as an internal or external command...&#039;&#039;&amp;quot; then make sure you have the Windows SSH client installed&lt;br /&gt;
* If you get an error such as &amp;quot;&#039;&#039;Permission denied, please try again&#039;&#039;&amp;quot; then make sure you are using your CS username and that it is all lowercase.  You can test your CS password online at https://admin.cs.vt.edu and reset the password at https://admin.cs.vt.edu/reset/&lt;br /&gt;
* If SSH seems to accept your password but hangs for a while and then times out, then you there might be an issue with your bash init scripts (.bashrc and .bash_profile).  Try connecting again and hit &amp;lt;ctrl&amp;gt;-c while it hangs to break the loop.  This should let you in so that you can fix your bash init scripts.&lt;br /&gt;
* If you still are unable to SSH into rlogin.cs.vt.edu, then [[Contact Techstaff]]&lt;br /&gt;
* Windows Specific error: Bad Owner or Permissions on SSH Config&lt;br /&gt;
** See: https://www.virtualizationhowto.com/2022/02/bad-owner-or-permissions-on-ssh-config-windows-10&lt;br /&gt;
&lt;br /&gt;
=== Other problems ===&lt;br /&gt;
* If you have modified your .bashrc file on rlogin, this could potentially cause an issue with VS Code being able to connect.  If your .bashrc file produces any kind of output or error messages then SSH will be unable to tunnel binary files which is used by VS Code.  &lt;br /&gt;
** Be careful about sourcing your .bash_profile inside .bashrc, as it can unknowingly create output.&lt;br /&gt;
** The system default .bashrc file can be found on rlogin at &amp;lt;code&amp;gt;/etc/skel/.bashrc&amp;lt;/code&amp;gt;&lt;br /&gt;
* Rarely, you might be put onto an rlogin node that is not working correctly.  To resolve this, wait at least 5 minutes before reconnecting and the load balancer will put you onto a new node.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4881</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4881"/>
		<updated>2024-10-30T19:02:38Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* We need to add the helm chart repository:&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Repositories&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Index URL&#039;&#039;&#039; with &amp;lt;code&amp;gt;https://charts.bitnami.com/bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: test-db&lt;br /&gt;
  username: test&lt;br /&gt;
  password: Insecure&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: 1Gi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
== Notes on Storage ==&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
== Advanced ==&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4880</id>
		<title>HowTo:CS Launch</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Launch&amp;diff=4880"/>
		<updated>2024-10-30T19:02:19Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This is a quick start guide for using the CS Launch website and kubernetes resources.  It will walk you through setting up a basic website with database support.  There is a separate guide that describes how to do all these steps using a command line terminal at [[HowTo:CS Launch Terminal]]&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
The https://launch.cs.vt.edu site manages multiple clusters.  Here is a list of clusters available for use by Computer Science members:&lt;br /&gt;
* &#039;&#039;Endeavour&#039;&#039;&lt;br /&gt;
** This cluster is meant for long term teaching projects, and specialty projects that require GPU resources.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty and Staff.&lt;br /&gt;
** Projects can be shared with any CS member, including students. &lt;br /&gt;
** Ingress: *.endeavour.cs.vt.edu&lt;br /&gt;
* &#039;&#039;Discovery&#039;&#039;&lt;br /&gt;
** This cluster is meant for general teaching projects.&lt;br /&gt;
** Creation of projects on this cluster is limited to CS Faculty, Staff, graduate students, and CS majors.&lt;br /&gt;
** Projects can be shared with any VT member with a CS account, including non-CS students.&lt;br /&gt;
** Ingress: *.discovery.cs.vt.edu&lt;br /&gt;
** Ingresses on this cluster are limited to campus and VPN IPs by default, but can be opened further using annotations.  See: [[CS Launch Ingress]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Project ==&lt;br /&gt;
Access to CS Launch is made through projects.  A project is a collection of kubernetes namespaces and resources.  You can have access to multiple projects.  Projects can be shared with other CS members.&lt;br /&gt;
&lt;br /&gt;
* Go to CS Launch website: &#039;&#039;&#039;https://launch.cs.vt.edu&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click the login button&#039;&#039;&#039; to use your CS username and password to log in&lt;br /&gt;
* The main screen will show a list of kubernetes clusters you have access to, if the list is blank then you don&#039;t have access to any clusters&lt;br /&gt;
* &#039;&#039;&#039;Click on the cluster name&#039;&#039;&#039; where you want to create the new project&lt;br /&gt;
* This is your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* From the menu on the left &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Project&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name for your project  Example: &amp;lt;code&amp;gt;test-project&amp;lt;/code&amp;gt;&lt;br /&gt;
* You add additional project members now or later after the project is created&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Project_create.png]]&lt;br /&gt;
&lt;br /&gt;
== Create a New Namespace ==&lt;br /&gt;
Kubernetes uses namespaces to separate resources.  The CS Launch resources groups namespaces into projects for access control.  A project can contain multiple namespaces.  At least one namespace is required before resources can be created in a project.  To access a namespace you must be a member of the project the namespace is associated with.  A namespace can only be associated with a single project.&lt;br /&gt;
* Navigate to the list of projects&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Projects/Namespaces&#039;&#039;&#039;&#039;&#039; from the cluster dashboard&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create Namespace&#039;&#039; button&#039;&#039;&#039; that is associated with the project you want to assign the namespace to&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a cluster unique name.  Example: &amp;lt;code&amp;gt;test-namespace&amp;lt;/code&amp;gt; The namespace name can be the same as the project name as long as it follows the naming rules and is not already in use.  Kubernetes namespace names must following DNS name rules: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
[[Image:Create_namespace.png]]&lt;br /&gt;
&lt;br /&gt;
== Launching a Database Using Helm==&lt;br /&gt;
Kubernetes supports Helm charts to automate deployment of software.  There are existing Helm charts for many popular software projects, such as databases.  Using a Helm chart can make setting up and updating complex software much easier.  This guide will walk you through deploying MariaDB using a Helm chart from Bitnami.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Apps&#039;&#039;&#039;&#039;&#039; from the menu on the left&lt;br /&gt;
* We need to add the helm chart repository:&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Repositories&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Name&#039;&#039;&#039; with &amp;lt;code&amp;gt;bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** Fill in &#039;&#039;&#039;Index URL&#039;&#039;&#039; with &amp;lt;code&amp;gt;https://charts.bitnami.com/bitnami&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Charts&#039;&#039;&#039;&#039;&#039; underneath &#039;&#039;Apps&#039;&#039;&lt;br /&gt;
* We need to find the MariaDB chart&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select &#039;&#039;Bitnami&#039;&#039; &#039;&#039;&#039;in the first drop down list&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Database&#039;&#039; &#039;&#039;&#039;from the catagories drop down list&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;MariaDB&#039;&#039; tile&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Select the namespace from the drop down list&#039;&#039;&#039; where you want the database deployed to&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Next&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* You will be presented with a long list of options and their default values in yaml format&lt;br /&gt;
* For our example, &#039;&#039;&#039;change the following options&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
auth:&lt;br /&gt;
  database: test-db&lt;br /&gt;
  username: test&lt;br /&gt;
  password: Insecure&lt;br /&gt;
primary:&lt;br /&gt;
  persistence:&lt;br /&gt;
    size: 1Gi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Install&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will take a minute or two for the deployment to complete.  The site will give you a window to watch the progress, and report any errors that might occur.&lt;br /&gt;
* You should now have a running database, but no real way to access it yet&lt;br /&gt;
* Other pods in the same namespace will be able to connect to this database using the hostname &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Launch an App Using a Public Image ==&lt;br /&gt;
Next we will launch a web app called &#039;&#039;Adminer&#039;&#039; that will allow us to interact with our running database, and assign it a URL.&lt;br /&gt;
* Navigate to your &#039;&#039;&#039;Cluster Dashboard&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039; as this type of deployment is best suited for our &#039;&#039;Adminer&#039;&#039; web app.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;  The name must following DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Container Image&#039;&#039;&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;adminer:latest&amp;lt;/code&amp;gt;  This is a path to a docker image, and it resolves to the latest image from the &#039;&#039;adminer&#039;&#039; project on https://docker.io.&lt;br /&gt;
* We need to tell kubernetes how this deployment will interact with the network by giving it a cluster IP.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; under the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;tcp8080&amp;lt;/code&amp;gt; under &#039;&#039;Networking&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in &#039;&#039;Private Container Port&#039;&#039;&#039;&#039;&#039; with &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt;.  TCP port 8080 is the port that the &#039;&#039;Adminer&#039;&#039; web app listens to.&lt;br /&gt;
* Many public docker images use environment variables to effect how the deployment runs.  &#039;&#039;Adminer&#039;&#039; has several environment variables you can set.  For our example, we will set some default values for convenience.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Add Variable&#039;&#039;&#039;&#039;&#039; under &#039;&#039;Environment Variables&#039;&#039;.&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Variable Name&#039;&#039; with the value &amp;lt;code&amp;gt;ADMINER_DEFAULT_SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
*** &#039;&#039;&#039;Fill in &#039;&#039;Value&#039;&#039; with the value &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* The rest of the options can be left on their default settings.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* The web app will start running, but we won&#039;t have a way to access it until we map a URL to the container, this is called an ingress in kubernetes.&lt;br /&gt;
&lt;br /&gt;
== Create Ingress to a Workload ==&lt;br /&gt;
Creating an ingress in kubernetes allows you to map an external URL to your running container so it can be accessed from anywhere on the Internet.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;testdb.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-adminer&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;8080&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
* For our example, you should be able to go to the URL and login using the password set earlier in the database deployment.  Server name is &amp;lt;code&amp;gt;mariadb&amp;lt;/code&amp;gt;&lt;br /&gt;
* See &#039;&#039;&#039;[[CS Launch Ingress]]&#039;&#039;&#039; for additional information about CS Launch Ingresses&lt;br /&gt;
&lt;br /&gt;
== Create a Custom Web Application ==&lt;br /&gt;
You can do more than just launch pre-built docker images on CS Launch.  You can create your own custom docker images allowing you to host just about any kind of app on kubernetes.  This will walk you through an example of that process.&lt;br /&gt;
* &#039;&#039;&#039;Build your custom docker image&#039;&#039;&#039;  Refer to [[HowTo:Docker]] for an example of building and hosting your own custom docker image.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; If your docker image is not public, then you will need to &#039;&#039;&#039;import an access token&#039;&#039;&#039; to be able to download and use your custom docker image.&lt;br /&gt;
** Refer to [[HowTo:Docker#Use_a_Token_to_Access_Registry]] to &#039;&#039;&#039;create an access token&#039;&#039;&#039; for your registry.&lt;br /&gt;
** &#039;&#039;&#039;Copy the contents of your access token&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on &#039;&#039;Secrets&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
** Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Select the &#039;&#039;Registry&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;test-regstry&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Registry Domain Name&#039;&#039;&#039;&#039;&#039; field with the hostname of your Docker registry.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Username&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;Name&#039;&#039; from when you created your access token.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Fill in the &#039;&#039;Password&#039;&#039; field&#039;&#039;&#039; with the &#039;&#039;contents of your access token&#039;&#039;  Example: &amp;lt;code&amp;gt;glpat-FqgNwpWtZJT-sfapguRv&amp;lt;/code&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create a ConfigMap ===&lt;br /&gt;
Kubernetes has a special storage option called a &#039;&#039;ConfigMap&#039;&#039;.  ConfigMaps can be used to create custom config files that can be directly mounted into the Docker image to localize your deployment.  For example, use a ConfigMap to create a database configuration file instead of embedding that config inside of the docker image itself.  For this example, we will create a &#039;&#039;config.php&#039;&#039; ConfigMap file and mount it under the /var/www/html/dbconfig directory inside the running container.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;ConfigMaps&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Binary Data&#039;&#039;&#039;&#039;&#039; on the left.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Key&#039;&#039; field&#039;&#039;&#039; with the value &amp;lt;code&amp;gt;config.php&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;File in the &#039;&#039;Value&#039;&#039; field&#039;&#039;&#039; with contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
declare(strict_types=1);&lt;br /&gt;
&lt;br /&gt;
define(&amp;quot;HOST&amp;quot;, &amp;quot;mariadb&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_NAME&amp;quot;, &amp;quot;test-db&amp;quot;);&lt;br /&gt;
define(&amp;quot;DB_USER&amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
define(&amp;quot;PASS&amp;quot;, &amp;quot;Insecure&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
$host = HOST;&lt;br /&gt;
$db_name = DB_NAME;&lt;br /&gt;
&lt;br /&gt;
$dsn = &amp;quot;mysql:host=$host;dbname=$db_name&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
	$db = new PDO ($dsn, DB_USER, PASS);&lt;br /&gt;
	$db-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);&lt;br /&gt;
} catch (PDOException $e) {&lt;br /&gt;
	throw new PDOException($e-&amp;gt;getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create Database Tables ===&lt;br /&gt;
Most dynamic web apps will require a database to be created before use.  For our example, you need to import a SQL dump to create tables and data.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your Adminer Ingress URL&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Log in using your database credentials&#039;&#039;&#039;&lt;br /&gt;
* Download the database dump from https://raw.githubusercontent.com/AaravRajSIngh/Chatbot/main/database.sql&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Import&#039;&#039; button&#039;&#039;&#039; to the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Browse...&#039;&#039; button&#039;&#039;&#039; and &#039;&#039;&#039;locate the downloaded sql dump&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Execute&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Launch a Custom Application using a ConfigMap ===&lt;br /&gt;
We are ready to launch the custom built web app.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Workloads&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Deployment&#039;&#039; tile&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the database&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Pod&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039; menu&#039;&#039;&#039; under the &#039;&#039;Pod&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Volume Name&#039;&#039; field&#039;&#039;&#039; with a pod unique name.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ConfigMap&#039;&#039; from the &#039;&#039;Add Volume&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select your custom ConfigMap from the &#039;&#039;ConfigMap&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-config&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;container-0&#039;&#039; tab&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; with a project unique name.  The name must following DNS naming rules.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Container Image&#039;&#039; field&#039;&#039;&#039; with your personal Docker image URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add Port or Service&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;ClusterIP&#039;&#039; from the &#039;&#039;Service Type&#039;&#039; drop down list&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Name&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;http&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in the &#039;&#039;Private Container Port&#039;&#039; field&#039;&#039;&#039; under &#039;&#039;Networking&#039;&#039; with the value: &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Storage&#039;&#039;&#039;&#039;&#039; under the &#039;&#039;container-0&#039;&#039; tab.&lt;br /&gt;
* &#039;&#039;&#039;Select your pod volume from the &#039;&#039;Select Volume&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Mount Point&#039;&#039;&#039;&#039;&#039; with the value: &amp;lt;code&amp;gt;/var/www/html/dbconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Create an Ingress to a Custom Application ===&lt;br /&gt;
We need to create another ingress to access this new web application.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your &#039;&#039;Cluster Dashboard&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Service Discovery&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Ingresses&#039;&#039;&#039;&#039;&#039; from the sub-menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Make sure to &#039;&#039;&#039;select the same namespace as the web app&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Name&#039;&#039;&#039;&#039;&#039; with a project unique name.  Example: &amp;lt;code&amp;gt;chatbot-ingress&amp;lt;/code&amp;gt;  The name must follow DNS naming rules.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Request Host&#039;&#039;&#039;&#039;&#039; with the hostname of the URL you want to map to.  Example: &amp;lt;code&amp;gt;chatbot.endeavour.cs.vt.edu&amp;lt;/code&amp;gt;  The Endeavour cluster on CS Launch allows you to map any *.endeavour.cs.vt.edu hostname to your ingress.  Additionally, a TLS certificate is used to automatically encrypt your ingress traffic.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Path&#039;&#039;&#039;&#039;&#039; with &#039;&#039;Prefix&#039;&#039; value of &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;  Using &#039;&#039;/&#039;&#039; will map the top level path, and all sub-paths of the URL to this deployment.  You can create multiple sub-paths to the same hostname to different deployments allowing you to flesh out a URL running as multiple containers.  Example: mapping /api/* to a deployment that runs the backend of your website.&lt;br /&gt;
* &#039;&#039;&#039;Select your application deployment from the &#039;&#039;Target Service&#039;&#039; drop down list&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Select &amp;lt;code&amp;gt;80&amp;lt;/code&amp;gt; from the &#039;&#039;Port&#039;&#039; drop down list&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* Once created you should have a working URL to your web application, and a link on the &#039;&#039;Ingresses&#039;&#039; tabs.&lt;br /&gt;
&lt;br /&gt;
=== Notes on Storage ===&lt;br /&gt;
* Persistent volumes (PVs) can be used for storage on your workloads&lt;br /&gt;
* PVs can be created on demand using the default storage class&lt;br /&gt;
* The default storage class PVs can only be mounted on a single pod at a time&lt;br /&gt;
* If you need larger storage (&amp;gt; 1TB) or read/write from multiple pods, then consider using the CS central storage service: [[HowTo:CS_Stash]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced ===&lt;br /&gt;
* Using GPU enabled containers on &#039;&#039;Endeavour&#039;&#039; cluster see [[HowTo:CS_Launch_GPU]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo&amp;diff=4879</id>
		<title>HowTo</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo&amp;diff=4879"/>
		<updated>2024-10-28T12:11:19Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[Howto::Firewall|Protecting a service using a firewall]]&lt;br /&gt;
&lt;br /&gt;
*[[Network_Printers|Connect to Shared Printer]]&lt;br /&gt;
&lt;br /&gt;
*[[CS_Backups|Setting up a back-up to our central backup system]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::CSThunderbird|Configuring thunderbird to use CS email]]&lt;br /&gt;
&lt;br /&gt;
*[[Spam Controls|How to use CS spam controls]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::PersonalSite|How to create your personal website]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::WebWritableDir|Make a directory writable by webscripts for interactive websites]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::SSLRedirect|Redirect a webpage to SSL/HTTPS encrypted on CS Hosting]]&lt;br /&gt;
&lt;br /&gt;
*[[HowTo:CS_Stash|Use CS Central Storage Service]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::MountHome|Mount your CS home directory on your PC]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::Docker Registry|Use CS Docker Image Registry]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::Export Git|Copy repo between git.cs.vt.edu and version.cs.vt.edu]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::Resize LVM|How to resize your VM disk to use full space]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::VScode|How to connect VSCode to rlogin.cs.vt.edu]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::High Risk|How to make your machine high risk compliant]]&lt;br /&gt;
&lt;br /&gt;
*[[Howto::Access rlogin service|How to access rlogin/glogin service]]&lt;br /&gt;
&lt;br /&gt;
*[[HowTo:CS_Launch|Using the CS Launch Service (kubernetes cluster)]]&lt;br /&gt;
&lt;br /&gt;
*[[HowTo:Docker 172 Fix|Fix your docker install to coexist on VT (172) network]]&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4878</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4878"/>
		<updated>2024-10-28T12:10:03Z</updated>

		<summary type="html">&lt;p&gt;Carnold: Protected &amp;quot;HowTo:CS Stash&amp;quot; ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is very limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Ansible Script ==&lt;br /&gt;
The techstaff have provided an ansible script to install and setup your central storage allocation at: https://version.cs.vt.edu/techstaff/ansible/-/tree/main/roles/csCentralStorage&lt;br /&gt;
&lt;br /&gt;
You can also install manually following the instructions below.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4877</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4877"/>
		<updated>2024-10-28T12:09:56Z</updated>

		<summary type="html">&lt;p&gt;Carnold: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is very limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Ansible Script ==&lt;br /&gt;
The techstaff have provided an ansible script to install and setup your central storage allocation at: https://version.cs.vt.edu/techstaff/ansible/-/tree/main/roles/csCentralStorage&lt;br /&gt;
&lt;br /&gt;
You can also install manually following the instructions below.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4876</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4876"/>
		<updated>2024-10-25T13:00:56Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Mounting Your Allocation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is very limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4875</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4875"/>
		<updated>2024-10-25T12:51:04Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Mounting Your Allocation on CS Launch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is very limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,wsync,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your [[HowTo:CS_Launch|CS Launch]] project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4874</id>
		<title>HowTo:CS Stash</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:CS_Stash&amp;diff=4874"/>
		<updated>2024-10-25T12:50:05Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Mounting Your Allocation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
CS Stash is a shared departmental storage system designed for sharing files to Linux based servers and workstations.  The service is based on Ceph, and more specifically CephFS: https://docs.ceph.com/en/reef/cephfs/  The goal of the service is to provide fault tolerant, secure, high-speed file sharing to Linux machines in the department.  This project is currently in it&#039;s pilot state, so space is very limited right now.&lt;br /&gt;
&lt;br /&gt;
== How it Works ==&lt;br /&gt;
The service uses CephFS to share files primarily to Linux based hosts.  It works like an NFS share in that it allows multiple hosts to mount R/W at the same time.  File permissions also work similar to NFS or a locally mounted file system on the host.&lt;br /&gt;
&lt;br /&gt;
== Creating an Allocation ==&lt;br /&gt;
All allocations are created by Techstaff.  [[Contact Techstaff]] to make your request for storage space.&lt;br /&gt;
&lt;br /&gt;
== Installing Ceph Client ==&lt;br /&gt;
To mount your allocation, you will need to install the ceph client, if it is not already installed.  You will need root level access to install ceph.  See: https://docs.ceph.com/en/latest/install/ for more details and the latest information on installing ceph.  Here are some brief instructions, using the &amp;lt;code&amp;gt;cephadm&amp;lt;/code&amp;gt; tool that should work on any supported Linux system (Redhat, Rocky, CentOS, Ubuntu, Debian, Alma, Etc.).&lt;br /&gt;
&lt;br /&gt;
* Download the cephadm tool&lt;br /&gt;
** &amp;lt;code&amp;gt;curl --silent --remote-name --location https://download.ceph.com/rpm-reef/el9/noarch/cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make the tool executable&lt;br /&gt;
** &amp;lt;code&amp;gt;chmod +x cephadm&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the &#039;&#039;reef&#039;&#039; ceph repo (&#039;&#039;&#039;Note:&#039;&#039;&#039; Older OSs might have to go down the &#039;&#039;quincy&#039;&#039; release, for example Rocky Linux 8)&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm add-repo --release reef&amp;lt;/code&amp;gt;&lt;br /&gt;
* Install the ceph client&lt;br /&gt;
** &amp;lt;code&amp;gt;sudo ./cephadm install ceph-common&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation ==&lt;br /&gt;
When your allocation is created, you will be given the following information needed to mount your filesystem:&lt;br /&gt;
* &amp;lt;username&amp;gt;&lt;br /&gt;
* &amp;lt;secret_key&amp;gt;&lt;br /&gt;
* &amp;lt;path&amp;gt;&lt;br /&gt;
You need to save the contents of the &amp;lt;secret_key&amp;gt; into a file, and secure the file.  For example, in the file &amp;lt;code&amp;gt;/etc/.&amp;lt;username&amp;gt;.secret&amp;lt;/code&amp;gt; with chmod mode 0600.&lt;br /&gt;
&lt;br /&gt;
You can have the filesystem automatically mounted on boot by adding an entry to your &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt; file, substitute your information as needed.  You can optionally mount a sub-path of your top level path.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;username&amp;gt;@.cephfs=&amp;lt;path&amp;gt;[/&amp;lt;sub-path] &amp;lt;mount_location&amp;gt; ceph mon_addr=stash.cs.vt.edu:3300,secretfile=&amp;lt;path_to_secret_file&amp;gt;,_netdev,noatime,wsync,rbytes,ms_mode=secure 0 0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can mount the storage immediately, run &amp;lt;code&amp;gt;sudo mount &amp;lt;mount_location&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* You may get notices about files in your /etc/ceph directory, but they can be ignored.&lt;br /&gt;
&lt;br /&gt;
== Mounting Your Allocation on CS Launch ==&lt;br /&gt;
[[Contact Techstaff]] to have your storage allocation added to your CS Launch project.  This has the advantage of being R/W from multiple containers on CS Launch versus the built-in CS Launch storage.&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
* Your &amp;lt;secret_key&amp;gt; should be kept secret, anyone with access to the &amp;lt;username&amp;gt; and &amp;lt;secret_key&amp;gt; can mount, and have full access to your filesystem&lt;br /&gt;
* The CephFS mount works like a locally mounted POSIX filesystem with ACLs enabled.  You can change file ownership and permissions like you would a local filesystem.&lt;br /&gt;
* All data is stored encrypted at rest&lt;br /&gt;
* If you use the &amp;quot;ms_mode=secure&amp;quot; mount option, then the data will also be encrypted on wire.  This is the recommended option.&lt;br /&gt;
&lt;br /&gt;
== Resizing ==&lt;br /&gt;
Your storage allocation can be resized quickly and easily without the need to unmount and remount the share.  A resize will be need to done by [[Contact Techstaff|Techstaff]]&lt;br /&gt;
&lt;br /&gt;
== Quotas ==&lt;br /&gt;
CephFS supports quotas.  You can set a specific quota on any individual directory that effects that directory and any sub-directories.  For full details, see: https://docs.ceph.com/en/latest/cephfs/quota/&lt;br /&gt;
Here is a quick example of setting a 1GB quota on a directory of your mount:&lt;br /&gt;
* &amp;lt;code&amp;gt;setfattr -n ceph.quota.max_bytes -v $(numfmt --from=iec 1G) /mnt/ceph/test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command uses the value as bytes.  The &#039;&#039;numfmt&#039;&#039; command is just a convenient way to convert larger values into bytes.&lt;br /&gt;
&lt;br /&gt;
== Performance ==&lt;br /&gt;
My benchmarks test show that performance from a 1Gbit network connection is about equivalent to a single local spindle drive.  Performance from a 10Gbit network connection is much greater than a single local spindle drive.   &lt;br /&gt;
&lt;br /&gt;
== Backups ==&lt;br /&gt;
Techstaff currently does not do any automatic backups of the data on the CS Stash service.  &lt;br /&gt;
* The service is fault tolerant to hardware failures&lt;br /&gt;
* CephFS offers snapshot support that can help mitigate data loss due to accidental deletion.  See: https://docs.ceph.com/en/reef/dev/cephfs-snapshots/ for more details.&lt;br /&gt;
* Here is a brief example of creating a snapshot of a subdirectory in your allocation:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@localhost:/# cd /mnt/ceph/test&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 1&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cd .snap&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# mkdir my_snapshot&lt;br /&gt;
user@localhost:/mnt/ceph/test/.snap# cd ..&lt;br /&gt;
user@localhost:/mnt/ceph/test# echo &amp;quot;Version 2&amp;quot; &amp;gt; version.txt&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat version.txt&lt;br /&gt;
Version 2&lt;br /&gt;
user@localhost:/mnt/ceph/test# cat .snap/my_snapshot/version.txt&lt;br /&gt;
Version 1&lt;br /&gt;
user@localhost:/mnt/ceph/test#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Here is a very simple bash script that would keep a one week rolling list of snaphots for a directory&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
DIR=/mnt/ceph/test&lt;br /&gt;
NAME=$(date +%A)&lt;br /&gt;
&lt;br /&gt;
rmdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
mkdir &amp;quot;$DIR/.snap/$NAME&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If off-site backup is a priority, then an outside solution will need to be implemented&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
* I used the program &#039;&#039;&#039;fio&#039;&#039;&#039; to benchmark&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
*** This creates a 4 GB file. It performs 4 KB reads and writes using a 75%/25% split in the file, with 64 operations running at a time.&lt;br /&gt;
** &#039;&#039;large_io&#039;&#039; Options: &amp;lt;code&amp;gt;fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=1M --iodepth=8 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/ceph/testfile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* Results from running on a local spindle disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 618 IOPs, 2.5 MB/s&lt;br /&gt;
*** Write: 204 IOPs, 819 KB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 94 IOPs, 94.7 MB/s&lt;br /&gt;
*** Write: 32 IOPs, 32.6 MB/s&lt;br /&gt;
* Results from running on a local SSD disk with xfs filesystem&lt;br /&gt;
** &#039;&#039;small io&#039;&#039; results:&lt;br /&gt;
*** Read: 32.8k IOPs, 128 MB/s&lt;br /&gt;
*** Write: 11k IOPs, 42.9 MB/s&lt;br /&gt;
** &#039;&#039;large io&#039;&#039; results:&lt;br /&gt;
*** Read: 142 IOPs, 142 MB/s&lt;br /&gt;
*** Write: 49 IOPs, 49.0 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039; on reference: SSD drive outperforms a spindle drive on small IO operations.  Actual read and write speeds are similar.&lt;br /&gt;
&lt;br /&gt;
=== From 1 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1912 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 639 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 31.5 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1929 IOPs, 7.7 MB/s&lt;br /&gt;
** Write: 644 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 91 IOPs, 91.5 MB/s&lt;br /&gt;
** Write: 31 IOPs, 33.1 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: Faster than a local spindle drive for small IO operations and almost identical performance to a local spindle drive for large IO and is network speed limited.  Encryption on wire seemed to make very little difference in performance.&lt;br /&gt;
&lt;br /&gt;
=== From 10 gigabit networking connection ===&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 1958 IOPs, 7.8 MB/s&lt;br /&gt;
** Write: 654 IOPs, 2.6 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;no encryption on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 358 IOPs, 376 MB/s &lt;br /&gt;
** Write: 123 IOPs, 130 MB/s&lt;br /&gt;
* &#039;&#039;small io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 2168 IOPs, 8.7 MB/s&lt;br /&gt;
** Write: 724 IOPs, 2.9 MB/s&lt;br /&gt;
* &#039;&#039;large io&#039;&#039; results &#039;&#039;&#039;encrypted on wire&#039;&#039;&#039;:&lt;br /&gt;
** Read: 321 IOPs, 337 MB/s&lt;br /&gt;
** Write: 110 IOPs, 111 MB/s&lt;br /&gt;
* &#039;&#039;&#039;Conclusion&#039;&#039;&#039;: No real change in performance for small IO operations from 1gig connection, but huge gain in large IO operations.  Encrypted was actually faster for small IO operations, not sure why it could be that it is forcing the use of v2 protocol instead of v1.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
	<entry>
		<id>http://wiki.cs.vt.edu/index.php?title=HowTo:Docker&amp;diff=4873</id>
		<title>HowTo:Docker</title>
		<link rel="alternate" type="text/html" href="http://wiki.cs.vt.edu/index.php?title=HowTo:Docker&amp;diff=4873"/>
		<updated>2024-10-23T11:37:26Z</updated>

		<summary type="html">&lt;p&gt;Carnold: /* Use a Token to Access Registry */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This guide will walk you through creating a git repository which gives you a docker registry to host docker images, build a docker image, and push the image up to the registry.  The image will be based on the official PHP docker image https://hub.docker.com/_/php , and a copy of &#039;&#039;Chatbot for College Students&#039;&#039; app installed https://github.com/AaravRajSIngh/Chatbot   You will need access to workstation that has Docker installed.  You can SSH to rlogin.cs.vt.edu and build docker images there.  This example compliments the CS Launch walkthrough at [[HowTo:CS Launch]] which will walk you through hosting this docker image using Computer Science kubernetes cluster. &lt;br /&gt;
&lt;br /&gt;
== Create Repository ==&lt;br /&gt;
Computer offers two Gitlab instances: https://git.cs.vt.edu and https://version.cs.vt.edu  git.cs.vt.edu is geared toward academic use, and version.cs.vt.edu is for departmental or research use.  We will use git.cs.vt.edu for this example.&lt;br /&gt;
* &#039;&#039;&#039;Log into https://git.cs.vt.edu&#039;&#039;&#039; using your CS username and password.&lt;br /&gt;
* &#039;&#039;&#039;Click on &#039;&#039;Projects&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;New Project&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create blank project&#039;&#039; tile&#039;&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Project name&#039;&#039; field&#039;&#039;&#039; with a unique name for your docker image project.  Example: &amp;lt;code&amp;gt;chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Project URL&#039;&#039; fields&#039;&#039;&#039; with your own sub path and project slug.&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;Visibility Level&#039;&#039;&#039;&#039;&#039;  If your project is &#039;&#039;public&#039;&#039; then anyone on the Internet will be able to download and use your docker image given the correct URL.  If your project is &#039;&#039;Private&#039;&#039; or &#039;&#039;Internal&#039;&#039; then to use your docker image you need to create and use a deployment token which will be discussed further in this walk through.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create project&#039;&#039; button&#039;&#039;&#039;.&lt;br /&gt;
* A docker image registry is automatically created with your git repository.&lt;br /&gt;
* &#039;&#039;&#039;Check your docker registry&#039;&#039;&#039;:&lt;br /&gt;
** &#039;&#039;&#039;Select &#039;&#039;Deploy-&amp;gt;Container Registry&#039;&#039; from the menu on the left&lt;br /&gt;
** &#039;&#039;&#039;Take note&#039;&#039;&#039; of the example docker commands it gives, this contains your &#039;&#039;&#039;Docker registry URL&#039;&#039;&#039;.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* Adding files to this git repository is optional, however you might find it a useful place to store versioned copies of your Docker image creation files.&lt;br /&gt;
&lt;br /&gt;
== Create Docker Image ==&lt;br /&gt;
* &#039;&#039;&#039;SSH to rlogin.cs.vt.edu&#039;&#039;&#039; See [[Howto::Access_rlogin_service]]  Alternatively, you can use any workstation that has Docker installed.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; Clone your git repository.&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;git clone https://git.cs.vt.edu/carnold/chatbot.git&amp;lt;/code&amp;gt;&lt;br /&gt;
** Change into the directory &amp;lt;code&amp;gt;cd chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Use a text editor to create a new file called &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;nano Dockerfile&amp;lt;/code&amp;gt;&lt;br /&gt;
** Contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Start from Apache based PHP image&lt;br /&gt;
FROM php:apache&lt;br /&gt;
&lt;br /&gt;
# Make sure git command is installed&lt;br /&gt;
RUN apt-get update &amp;amp;&amp;amp; \&lt;br /&gt;
    apt-get install vim git -y&lt;br /&gt;
&lt;br /&gt;
# Install additional PHP modules&lt;br /&gt;
RUN docker-php-ext-install mysqli pdo pdo_mysql&lt;br /&gt;
&lt;br /&gt;
# Download chatbot app&lt;br /&gt;
RUN cd /var/www/html &amp;amp;&amp;amp; \&lt;br /&gt;
    git clone https://github.com/AaravRajSIngh/Chatbot.git . &amp;amp;&amp;amp; \&lt;br /&gt;
    chmod 600 .git &amp;amp;&amp;amp; \&lt;br /&gt;
    cp -f homepage.php index.php&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Build the docker image and give it a tag for easy identification.&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;docker build . -t test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* If successful, your image will be built and store locally but is not yet accessible from your registry.&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; You can run your docker image locally to make sure it works&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;docker run -it test-chatbot /bin/bash&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Optional:&#039;&#039;&#039; Commit and push your Dockerfile up to the git repository.&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;git add --all&amp;lt;/code&amp;gt;&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;git commit -m init&amp;lt;/code&amp;gt;&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;git push origin main&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Push Docker Image to Registry ==&lt;br /&gt;
At this point you should have a built and working docker image that is stored locally.  You will need to push the image up to your docker registry to be able to access it from other hosts or clusters.&lt;br /&gt;
* &#039;&#039;&#039;Log into your docker registry using the docker command&#039;&#039;&#039;  You need to give the docker command the hostname of the registry.  If you are using https://git.cs.vt.edu then the hostname is &amp;lt;code&amp;gt;container.cs.vt.edu&amp;lt;/code&amp;gt;  If you are using https://version.cs.vt.edu then the hostname is &amp;lt;code&amp;gt;docker.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;docker login container.cs.vt.edu&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Tag your docker image&#039;&#039;&#039; with your &#039;&#039;Docker Registry URL&#039;&#039; from earlier.&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;docker tag test-chatbot container.cs.vt.edu/carnold/chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Push the image&#039;&#039;&#039; to your &#039;&#039;Docker Registry URL&#039;&#039;&lt;br /&gt;
** Example: &amp;lt;code&amp;gt;docker push container.cs.vt.edu/carnold/chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
** You can use &#039;&#039;tags&#039;&#039; to store multiple versions of your docker image by adding a &amp;lt;code&amp;gt;:&amp;lt;tag&amp;gt;&amp;lt;/code&amp;gt; to the end of your Docker Registry URL.  Example: &amp;lt;code&amp;gt;container.cs.vt.edu/carnold/chatbot:latest&amp;lt;/code&amp;gt;&lt;br /&gt;
* If successful, your docker image should be uploaded and ready to deploy.&lt;br /&gt;
&lt;br /&gt;
== Use a Token to Access Registry ==&lt;br /&gt;
If your git repository that hosts your Docker Registry is set to &#039;&#039;Internal&#039;&#039; or &#039;&#039;Private&#039;&#039; visibility, then you will need to create and use a deployment token to download the images.&lt;br /&gt;
* &#039;&#039;&#039;Navigate to your git repository website&#039;&#039;&#039; such as https://git.cs.vt.edu/carnold/chatbot&lt;br /&gt;
* &#039;&#039;&#039;Select &#039;&#039;Settings -&amp;gt; Access Tokens&#039;&#039;&#039;&#039;&#039; from the menu on the left.&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Add new token&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Fill in &#039;&#039;Token name&#039;&#039;&#039;&#039;&#039; with a unique name for your access token.  &#039;&#039;&#039;Take note of the name&#039;&#039;&#039; that you give this token, as it will be used as the username in kubernetes.  Example: &amp;lt;code&amp;gt;test-chatbot&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Check the box for &#039;&#039;read_registry&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Click on the &#039;&#039;Create project access token&#039;&#039; button&#039;&#039;&#039;&lt;br /&gt;
* It will display the contents of your access token, &#039;&#039;&#039;make a copy of the content&#039;&#039;&#039; as you will need to paste it into a secret resource in the kubernetes cluster.&lt;br /&gt;
* Refer to [[HowTo:CS_Launch#Create_a_Custom_Web_Application]] on how to import this token into kubernetes for hosting your docker images.&lt;/div&gt;</summary>
		<author><name>Carnold</name></author>
	</entry>
</feed>