Development/VS Code: Difference between revisions
No edit summary |
H Schumacher (talk | contribs) (Connect to jupyter kernel) |
||
(42 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
= Visual Studio Code = |
= Visual Studio Code = |
||
[[File:vscode.png|frameless|Visual Studio Code, Source: https://code.visualstudio.com/|750px]] |
|||
Visual Studio Code (VS Code) is an open source source-code editor from Microsoft[^1]. It has become one of the most popular IDEs[^2]. |
|||
The functionality of VS Code can easily be extended by installing extensions. These extensions allow for almost arbitrary **language support**, **debugging** or **remote development**. |
|||
You can install VS Code locally on Windows, macOS and Linux. |
|||
Visual Studio Code (VS Code) is an open source source-code editor from Microsoft [1]. It has become one of the most popular IDEs. The functionality of VS Code can easily be extended by installing extensions. These extensions allow for almost arbitrary '''language support''', '''debugging''' or '''remote development'''. You can install VS Code locally on Windows, macOS and Linux. |
|||
<figure markdown> |
|||
{: style="width: 100%; max-width:700px;"} |
|||
<figcaption>Visual Studio Code <br><small>Source: <a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></small></figcaption> |
|||
</figure> |
|||
[1]: https://github.com/Microsoft/vscode<br> |
|||
= VS Code: Remote - SSH = |
|||
[2]: https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-integrated-development-environment |
|||
In order to remotely develop and debug code at KIT's HPC facilities, you can use the **Remote - SSH** extension[^3]. |
|||
The extension allows you to connect your locally installed VS Code with the remote servers. So in contrast to using graphical IDEs within a remote desktop session (RDP, VNC), there are no negative effects like e.g. laggy reactions to your input or blurred display of fonts. |
|||
= VS Code: Remote - SSH = |
|||
== Installation and configuration == |
|||
In order to remotely develop and debug code at HPC facilities, you can use the '''Remote - SSH''' extension [3]. The extension allows you to connect your locally installed VS Code with the remote servers. So in contrast to using graphical IDEs within a remote desktop session (RDP, VNC), there are no negative effects like e.g. laggy reactions to your input or blurred display of fonts. |
|||
{: width=30px align:left style="border: 1px solid black;"} |
|||
In order to install the Remote - SSH extension, just click on the Extensions (Erweiterungen) button in the left side bar and enter "remote ssh" in the search field. Choose **Remote - SSH** from the occurring list and click on **Install**. |
|||
[3]: https://code.visualstudio.com/docs/remote/ssh |
|||
{: width=30px align:left style="border: 1px solid black;"} |
|||
In order to configure remote connections, open the Remote-Explorer extension. On Linux Systems, the file `~/.ssh/config` is automatically evaluated. The targets within this file already appear in the left side bar. |
|||
== Installation and configuration == |
|||
[[File:vscode-extensions-button.png|vscode-extensions-button.png|30px]]<br> |
|||
{: width=350px align:left style="border: 1px solid black;"} |
|||
In order to install the Remote - SSH extension, just click on the Extensions (Erweiterungen) button in the left side bar and enter “remote ssh” in the search field. Choose '''Remote - SSH''' from the occurring list and click on '''Install'''. |
|||
If there are no remote ssh targets defined within this file, you can easily add one by clicking on the + symbol. Make sure that "SSH Targets" is active in the drop down menu of the Remote-Explorer. Enter the connection details `<user>@<server>`. You will be asked, whether the file `~/.ssh/config` should be modified or if another config file should be used or created. |
|||
<br><br> |
|||
[[File:vscode-remoteexplorer-button.png|vscode-remoteexplorer-button.png|30px]]<br> |
|||
In order to configure remote connections, open the Remote-Explorer extension. On Linux Systems, the file <code>~/.ssh/config</code> is automatically evaluated. The targets within this file already appear in the left side bar. |
|||
<br><br> |
|||
[[File:vscode-remoteexplorer-add.png|vscode-remoteexplorer-add.png|350px]]<br> |
|||
If there are no remote ssh targets defined within this file, you can easily add one by clicking on the + symbol. Make sure that “SSH Targets” is active in the drop down menu of the Remote-Explorer. Enter the connection details <code><user>@<server></code>. You will be asked, whether the file <code>~/.ssh/config</code> should be modified or if another config file should be used or created. |
|||
== Connect to login nodes == |
== Connect to login nodes == |
||
[[File:vscode-remoteexplorer-button.png|vscode-remoteexplorer-button.png|30px]]<br> |
|||
In order to connect to a remote SSH target, open the Remote-Explorer. Right-click a target and connect in the current or a new window. TOTP and password can be entered in the corresponding input fields that open. |
In order to connect to a remote SSH target, open the Remote-Explorer. Right-click a target and connect in the current or a new window. TOTP and password can be entered in the corresponding input fields that open. |
||
You are now logged in on the remote server. As usual, you can open a project directory with the standard key binding |
You are now logged in on the remote server. As usual, you can open a project directory with the standard key binding Ctrl+k Ctrl+o. You can now edit and debug code. |
||
'''Attention''': Please remember that you are running and debugging the code on a login node. Do not perform resource-intensive tasks. Furthermore, no GPU resources are available to you. |
|||
!!! attention |
|||
Please remember that you are running and debugging the code on a login node. Do not perform resource-intensive tasks. Furthermore, no GPU resources are available to you. |
|||
Extensions, which are installed locally, are only usable on your local machine and are not automatically installed remotely. However, as soon as you open the Extensions-Explorer during a remote session, VS Code proposes to install the locally installed extensions remotely. |
Extensions, which are installed locally, are only usable on your local machine and are not automatically installed remotely. However, as soon as you open the Extensions-Explorer during a remote session, VS Code proposes to install the locally installed extensions remotely. |
||
Line 40: | Line 40: | ||
== Disconnect from login nodes == |
== Disconnect from login nodes == |
||
[[File:vscode-remoteexplorer-indicator.png|images/vscode-remoteexplorer-indicator.png|200px]]<br> |
|||
If you want to end your remote session, click the green box in the lower left corner. In the input box that opens, select the |
If you want to end your remote session, click the green box in the lower left corner. In the input box that opens, select the “Close Remote Connection” option. If you simply close your VS Code window, some server-side components of VS Code will continue to run remotely. |
||
== Access to compute nodes == |
== Access to compute nodes == |
||
Line 49: | Line 49: | ||
= code-server = |
= code-server = |
||
The application code-server[ |
The application code-server [4] allows to run the server part of VS Code on any machine, it can be accessed in the web browser. This enables, for example, development and debugging on compute nodes.<br> |
||
'''Code-server is available via the Lmod-module <code>devel/code-server</code>''' |
|||
[4]: https://github.com/cdr/code-server |
|||
<figure markdown> |
|||
{: style="width: 100%; max-width:700px;"} |
|||
<figcaption>VS Code in web browser: code-server <br><small>Source: <a href="https://github.com/cdr/code-server">https://github.com/cdr/code-server</a></small></figcaption> |
|||
</figure> |
|||
[[File:code-server.png|code-server.png|VS Code in web browser: code-server, Source: https://github.com/cdr/code-server">https://github.com/cdr/code-server|700px]] |
|||
== Start code-server == |
|||
!!! danger "Security implications" |
|||
Please note that by starting `code-server` you are running a web server that can be accessed by everyone logged in on HoreKa/bwUniCluster. |
|||
=== Start code-server === |
|||
- **If password protection is disabled, anybody can access your account and your data.** |
|||
- Chose a **secure password**! |
|||
- Do **NOT** use `code-server --link`! |
|||
Code-server can be run on either login nodes or compute nodes. In the example shown, an interactive job is started on a GPU partition to run code-server there. |
Code-server can be run on either login nodes or compute nodes. In the example shown, an interactive job is started on a GPU partition to run code-server there. |
||
<syntaxhighlight lang="console">$ salloc -p accelerated --gres=gpu:4 --time=30:00 # Start interactive job with 1 GPU |
|||
```console |
|||
$ module load devel/code-server # Load code-server module</syntaxhighlight> |
|||
$ salloc -p accelerated --gres=gpu:4 --time=30:00 # Start interactive job with 1 GPU |
|||
When code-server is started, it opens a web server listening on a certain port. The user has to '''specify the port'''. It can be chosen freely in the unprivileged range (above 1024). If a port is already assigned, e.g. because several users choose the same port, another port must be chosen. |
|||
$ module load devel/code-server # Load code-server module |
|||
``` |
|||
By starting code-server, you are running a web server that can be accessed by anyone logged in to HoreKa/bwUniCluster. To prevent other people from gaining access to your account and data, this web server is '''password protected'''. If no variable <code>PASSWORD</code> is defined, the password in the default config file <code>~/.config/code-server/config.yaml</code> is used. If you want to define your own password, you can either change it in the config file or export the variable <code>PASSWORD</code>. |
|||
When code-server is started, it opens a web server listening on a certain port. The user has to **specify the port**. It can be chosen freely in the unprivileged range (above 1024). If a port is already assigned, e.g. because several users choose the same port, another port must be chosen. |
|||
<syntaxhighlight lang="console">$ PASSWORD=<mySecret> \ |
|||
By starting code-server, you are running a web server that can be accessed by anyone logged in to HoreKa/bwUniCluster. To prevent other people from gaining access to your account and data, this web server is **password protected**. If no variable `PASSWORD` is defined, the password in the default config file `~/.config/code-server/config.yaml` is used. If you want to define your own password, you can either change it in the config file or export the variable `PASSWORD`. |
|||
code-server \ |
|||
```console |
|||
$ PASSWORD=<mySecret> \ |
|||
code-server } |
|||
--bind-addr 0.0.0.0:8081 \ |
--bind-addr 0.0.0.0:8081 \ |
||
--auth password # Start code-server on port 8081 |
--auth password # Start code-server on port 8081</syntaxhighlight> |
||
``` |
|||
{| style="background:#FFCCCC; width:100%;" |
|||
| '''Security implications''' |
|||
Please note that by starting <code>code-server</code> you are running a web server that can be accessed by everyone logged in on HoreKa/bwUniCluster.<br> |
|||
* '''If password protection is disabled, anybody can access your account and your data.''' |
|||
* Choose a '''secure password'''! |
|||
* Do '''NOT''' use <code>code-server --link</code>! |
|||
|} |
|||
== Connect to code-server == |
== Connect to code-server == |
||
As soon as code-server is running, it can be accessed in the web browser. |
As soon as code-server is running, it can be accessed in the web browser. In order to establish the connection, a SSH tunnel from your local computer to the remote server has to be created via: |
||
In order to establish the connection, a SSH tunnel from your local computer to the remote server has to be created via: |
|||
<syntaxhighlight lang="console">$ ssh -L 8081:<computeNodeID>:8081 <userID>@hk.scc.kit.edu</syntaxhighlight> |
|||
```console |
|||
You need to enter the <code>computeNodeID</code> of the node on which the interactive Slurm job is running. If you have started code server on a login node, just enter <code>localhost</code>. Now you can open http://127.0.0.1:8081 in your web browser. Possibly, you have to allow your browser to open an insecure (non-https) site. The login site looks as follows: |
|||
$ ssh -L 8081:<computeNodeID>:8081 <userID>@hk.scc.kit.edu |
|||
``` |
|||
You need to enter the `computeNodeID` of the node on which the interactive Slurm job is running. If you have started code server on a login node, just enter `localhost`. |
|||
Now you can open [http://127.0.0.1:8081](http://127.0.0.1:8081) in your web browser. Eventually, you have to allow your browser to open an insecure (non-https site). The login site looks as follows: |
|||
[[File:code-server-login.png|Code-server login page.|300px]] |
|||
<figure markdown> |
|||
{: style="width: 300px;"} |
|||
<figcaption>Code-server login page.</figcaption> |
|||
</figure> |
|||
Enter the password from |
Enter the password from <code>~/.config/code-server/config.yaml</code> or from the <code>PASSWORD</code> variable. After clicking the “Submit” button, the familiar VS Code interface will open in your browser. |
||
<figure markdown> |
|||
[[File:code-server-hk.png|Code-server running on GPU node of HoreKa.|700px]] |
|||
<figcaption>Code-server running on GPU node of HoreKa.</figcaption> |
|||
</figure> |
|||
== End code-server session == |
== End code-server session == |
||
If you want to temporarily log out from your code-server session you can open the |
If you want to temporarily log out from your code-server session you can open the “Application Menu” in the left side bar and click on “Log out”. To '''terminate''' the code-server session, you have to cancel it in the interactive Slurm job by pressing ++ctrl+c++. |
||
To **terminate** the code-server session, you have to cancel it in the interactive Slurm job by pressing ++ctrl+c++. |
|||
= Connect to Remote Jupyter Kernel = |
|||
Run jupyter kernel on compute node and connect to it via VSCode. |
|||
== Simple Use Case == |
|||
# Set a password on Helix for jupyterlab: |
|||
#: <syntaxhighlight lang="bash"> |
|||
jupyter notebook --generate-config |
|||
jupyter notebook password |
|||
</syntaxhighlight> |
|||
# Define a batch script |
|||
#: <pre>~/jupyterlab.slurm</pre> |
|||
#: <syntaxhighlight lang="bash"> |
|||
#!/bin/bash |
|||
#SBATCH --partition=cpu-single |
|||
#SBATCH --job-name=jupyterlab |
|||
#SBATCH --time=00:05:00 |
|||
#SBATCH --ntasks=1 |
|||
#SBATCH --cpus-per-task 1 |
|||
##SBATCH --mem-per-cpu=10 |
|||
#SBATCH --mail-user=my_email_address #my_email_address # to use this generic version, add "alias my_email_address=<yourEmailAddress>" to the ~/.bashrc file |
|||
#SBATCH --mail-type=ALL |
|||
module load devel/miniconda |
|||
source $MINICONDA_HOME/etc/profile.d/conda.sh |
|||
PORT=$(( ( RANDOM % 9999 ) + 1024 )) |
|||
jupyter lab --no-browser --ip=0.0.0.0 --port=${PORT} |
|||
HOSTID=$(squeue -h -o "%A %N %j" | grep jupyterlab | awk '{print $2}') |
|||
echo "Connect" |
|||
echo "ssh -N -L ${PORT}:${HOSTID}:${PORT} ${USER}@helix.bwservices.uni-heidelberg.de" |
|||
echo "Job {$SLURM_JOB_ID} running on node {$SLURM_NODEID} on host {$HOSTID}." |
|||
returned_code=$? |
|||
echo "> Script completed with exit code ${returned_code}" |
|||
exit ${returned_code} |
|||
</syntaxhighlight> |
|||
# Run a wrapper script to execute the batch script. You could save it together with other utility scripts in a "bin" directory in your home folder. |
|||
#: <pre>./bin/run_jupyterlab_simple.sh</pre> |
|||
#: <syntaxhighlight lang="bash"> |
|||
#!/bin/bash |
|||
# Define parameters |
|||
jobscript=~/jupyterlab.slurm |
|||
# Run job |
|||
job_id=$(sbatch $jobscript | awk '{print $4}') |
|||
echo "jobid: $job_id" |
|||
# Outfile name |
|||
slurm_out=slurm-${job_id}.out |
|||
# Wait for output file |
|||
while [ ! -f $slurm_out ]; do |
|||
sleep 2; |
|||
done |
|||
# Wait until url is written in output file |
|||
while [ -z ${url} ]; do |
|||
sleep 1; |
|||
url=$(grep -o 'http[^ ]*' $slurm_out | head -n 1); |
|||
done |
|||
# Extract hostID and port from output. |
|||
url_pattern="http://([a-z0-9]{6}):([1-9]{4})/lab" |
|||
if [[ $url =~ $url_pattern ]]; then |
|||
hostID=${BASH_REMATCH[1]} |
|||
port=${BASH_REMATCH[2]} |
|||
echo "To connect with the JupyterLab kernel, please enter the following into your local commandline: " |
|||
echo "ssh -N -L $port:$hostID:$port ${USER}@helix.bwservices.uni-heidelberg.de"; |
|||
fi |
|||
echo "Afterwards, you can either" |
|||
echo "- use the kernel in VSCode or " |
|||
echo "- open JupyterLab with this URL: " |
|||
echo " http://127.0.0.1:${port}/lab " |
|||
echo "Note: It is normal that the ssh command doesn't end after providing the credentials. Ending the command would mean ending the local connection to the kernel." |
|||
#rm $slurm_out |
|||
</syntaxhighlight> |
|||
# Follow the instructions on the commandline to connect to the Jupyter kernel from your local machine. |
|||
== Complex Use Case == |
|||
If you have different use cases for juypterlab, you could use a more flexible wrapper script, for example: |
|||
<pre>./bin/run_jupyterlab.sh</pre> |
|||
<syntaxhighlight lang="bash"> |
|||
#!/bin/bash |
|||
# Starts a jupyter kernel on a node and provides information on how to connect to it locally. |
|||
# If you have only one use case and therefore need only one combination of slurm settings for your jupyter jobs, then you can use the simpler script. |
|||
# This script supports explorative analyses by allowing to overwrite parameters via commandline. |
|||
# Different job configurations can be defined in advance and then used with a given short name (cpu, gpu,...). |
|||
programname=$0 |
|||
function help { |
|||
'''help text''' |
|||
echo "" |
|||
echo "Starts a jupyterlab kernel" |
|||
echo "" |
|||
echo "usage example: $programname --param_set cpu" |
|||
echo "" |
|||
echo " --param_set string name of the parameter set" |
|||
echo " (examples: cpu, gpu)" |
|||
echo " --jobscript string optional, path of batch script" |
|||
echo " (default: ~/jupyterlab.slurm)" |
|||
echo " --slurm_out string optional, name of slurm output file" |
|||
echo " (default: slurm-${job_id}.out)" |
|||
} |
|||
# These parameters are set later in the script. Providing them via commandline, overwrites their values set in the script. |
|||
jobscript=None |
|||
slurm_out=None |
|||
# Process parameters |
|||
while [ $# -gt 0 ]; do |
|||
if [[ $1 == "--help" ]]; then |
|||
help |
|||
exit 0 |
|||
# when given -p as parameter, use its value for the variable param_set |
|||
elif [[ $1 == "-p" ]]; then |
|||
param_set="$2" |
|||
shift |
|||
elif [[ $1 == "--"* ]]; then |
|||
v="${1/--/}" |
|||
declare "$v"="$2" |
|||
shift |
|||
fi |
|||
shift |
|||
done |
|||
function define_param_set(){ |
|||
'''Define parameter sets for sbatch''' |
|||
# Define different sets |
|||
cpu=(--partition=cpu-single --mem=2gb) |
|||
gpu=(--partition=gpu-single --mem=3gb --gres=gpu:1) |
|||
param_set=${1} |
|||
param_set=$param_set[@] |
|||
param_set=("${!param_set}") |
|||
# Add params that are the same for all sets |
|||
param_set+=(--ntasks=1) |
|||
} |
|||
# @param: jobscript, name of the slurm batch script to execute |
|||
if [ "$jobscript" = "None" ]; then |
|||
jobscript=~/jupyterlab.slurm |
|||
fi |
|||
# Translate given param_set value to actual set of parameters |
|||
define_param_set $param_set |
|||
echo "param_set: ${param_set[*]}" |
|||
# Run job |
|||
job_id=$(sbatch ${param_set[@]} $jobscript | awk '{print $4}') |
|||
echo "jobid: $job_id" |
|||
# @param: slurm_out, the filename for the slurm output file |
|||
if [ "$slurm_out" = "None" ]; then |
|||
slurm_out=slurm-${job_id}.out |
|||
fi |
|||
# Wait for output file |
|||
while [ ! -f $slurm_out ]; do |
|||
sleep 1; |
|||
done |
|||
# Wait until url is written in output file |
|||
while [ -z ${url} ]; do |
|||
sleep 1; |
|||
url=$(grep -o 'http[^ ]*' $slurm_out | head -n 1); |
|||
done |
|||
# Extract hostID and port from output. |
|||
url_pattern="http://([a-z0-9]{6}):([1-9]{4})/lab" |
|||
if [[ $url =~ $url_pattern ]]; then |
|||
hostID=${BASH_REMATCH[1]} |
|||
port=${BASH_REMATCH[2]} |
|||
echo "To connect with the JupyterLab kernel, please enter the following into your local commandline: " |
|||
echo "ssh -N -L $port:$hostID:$port ${USER}@helix.bwservices.uni-heidelberg.de"; |
|||
fi |
|||
echo "Afterwards, you can either" |
|||
[^1]: [https://github.com/Microsoft/vscode](https://github.com/Microsoft/vscode) |
|||
echo "- use the kernel in VSCode or " |
|||
[^2]: [https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-integrated-development-environment](https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-integrated-development-environment) |
|||
echo "- open JupyterLab with this URL: " |
|||
[^3]: [https://code.visualstudio.com/docs/remote/ssh](https://code.visualstudio.com/docs/remote/ssh) |
|||
echo " http://127.0.0.1:${port}/lab " |
|||
[^4]: [https://code.visualstudio.com/blogs/2019/10/03/remote-ssh-tips-and-tricks](https://code.visualstudio.com/blogs/2019/10/03/remote-ssh-tips-and-tricks) |
|||
echo "Note: It is normal that the ssh command doesn't end after providing the credentials. Ending the command would mean ending the local connection to the kernel." |
|||
[^5]: [https://github.com/cdr/code-server](https://github.com/cdr/code-server) |
|||
#rm $slurm_out |
|||
</syntaxhighlight> |
Latest revision as of 19:06, 28 February 2025
Visual Studio Code
Visual Studio Code (VS Code) is an open source source-code editor from Microsoft [1]. It has become one of the most popular IDEs. The functionality of VS Code can easily be extended by installing extensions. These extensions allow for almost arbitrary language support, debugging or remote development. You can install VS Code locally on Windows, macOS and Linux.
[1]: https://github.com/Microsoft/vscode
[2]: https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-integrated-development-environment
VS Code: Remote - SSH
In order to remotely develop and debug code at HPC facilities, you can use the Remote - SSH extension [3]. The extension allows you to connect your locally installed VS Code with the remote servers. So in contrast to using graphical IDEs within a remote desktop session (RDP, VNC), there are no negative effects like e.g. laggy reactions to your input or blurred display of fonts.
[3]: https://code.visualstudio.com/docs/remote/ssh
Installation and configuration
In order to install the Remote - SSH extension, just click on the Extensions (Erweiterungen) button in the left side bar and enter “remote ssh” in the search field. Choose Remote - SSH from the occurring list and click on Install.
In order to configure remote connections, open the Remote-Explorer extension. On Linux Systems, the file ~/.ssh/config
is automatically evaluated. The targets within this file already appear in the left side bar.
If there are no remote ssh targets defined within this file, you can easily add one by clicking on the + symbol. Make sure that “SSH Targets” is active in the drop down menu of the Remote-Explorer. Enter the connection details <user>@<server>
. You will be asked, whether the file ~/.ssh/config
should be modified or if another config file should be used or created.
Connect to login nodes
In order to connect to a remote SSH target, open the Remote-Explorer. Right-click a target and connect in the current or a new window. TOTP and password can be entered in the corresponding input fields that open.
You are now logged in on the remote server. As usual, you can open a project directory with the standard key binding Ctrl+k Ctrl+o. You can now edit and debug code.
Attention: Please remember that you are running and debugging the code on a login node. Do not perform resource-intensive tasks. Furthermore, no GPU resources are available to you.
Extensions, which are installed locally, are only usable on your local machine and are not automatically installed remotely. However, as soon as you open the Extensions-Explorer during a remote session, VS Code proposes to install the locally installed extensions remotely.
Disconnect from login nodes
If you want to end your remote session, click the green box in the lower left corner. In the input box that opens, select the “Close Remote Connection” option. If you simply close your VS Code window, some server-side components of VS Code will continue to run remotely.
Access to compute nodes
The workflow described above does not allow debugging on compute nodes that have been requested via an interactive Slurm job, for example. The security settings prevent the login node from being used as a proxy jump host. So there is no way to connect your locally installed VS code to the compute nodes. Debugging GPU codes is therefore also not possible, since this kind of resource is only accessible within Slurm jobs.
code-server
The application code-server [4] allows to run the server part of VS Code on any machine, it can be accessed in the web browser. This enables, for example, development and debugging on compute nodes.
Code-server is available via the Lmod-module devel/code-server
[4]: https://github.com/cdr/code-server
Start code-server
Code-server can be run on either login nodes or compute nodes. In the example shown, an interactive job is started on a GPU partition to run code-server there.
$ salloc -p accelerated --gres=gpu:4 --time=30:00 # Start interactive job with 1 GPU
$ module load devel/code-server # Load code-server module
When code-server is started, it opens a web server listening on a certain port. The user has to specify the port. It can be chosen freely in the unprivileged range (above 1024). If a port is already assigned, e.g. because several users choose the same port, another port must be chosen.
By starting code-server, you are running a web server that can be accessed by anyone logged in to HoreKa/bwUniCluster. To prevent other people from gaining access to your account and data, this web server is password protected. If no variable PASSWORD
is defined, the password in the default config file ~/.config/code-server/config.yaml
is used. If you want to define your own password, you can either change it in the config file or export the variable PASSWORD
.
$ PASSWORD=<mySecret> \
code-server \
--bind-addr 0.0.0.0:8081 \
--auth password # Start code-server on port 8081
Security implications
Please note that by starting
|
Connect to code-server
As soon as code-server is running, it can be accessed in the web browser. In order to establish the connection, a SSH tunnel from your local computer to the remote server has to be created via:
$ ssh -L 8081:<computeNodeID>:8081 <userID>@hk.scc.kit.edu
You need to enter the computeNodeID
of the node on which the interactive Slurm job is running. If you have started code server on a login node, just enter localhost
. Now you can open http://127.0.0.1:8081 in your web browser. Possibly, you have to allow your browser to open an insecure (non-https) site. The login site looks as follows:
Enter the password from ~/.config/code-server/config.yaml
or from the PASSWORD
variable. After clicking the “Submit” button, the familiar VS Code interface will open in your browser.
End code-server session
If you want to temporarily log out from your code-server session you can open the “Application Menu” in the left side bar and click on “Log out”. To terminate the code-server session, you have to cancel it in the interactive Slurm job by pressing ++ctrl+c++.
Connect to Remote Jupyter Kernel
Run jupyter kernel on compute node and connect to it via VSCode.
Simple Use Case
- Set a password on Helix for jupyterlab:
jupyter notebook --generate-config jupyter notebook password
- Define a batch script
~/jupyterlab.slurm
#!/bin/bash #SBATCH --partition=cpu-single #SBATCH --job-name=jupyterlab #SBATCH --time=00:05:00 #SBATCH --ntasks=1 #SBATCH --cpus-per-task 1 ##SBATCH --mem-per-cpu=10 #SBATCH --mail-user=my_email_address #my_email_address # to use this generic version, add "alias my_email_address=<yourEmailAddress>" to the ~/.bashrc file #SBATCH --mail-type=ALL module load devel/miniconda source $MINICONDA_HOME/etc/profile.d/conda.sh PORT=$(( ( RANDOM % 9999 ) + 1024 )) jupyter lab --no-browser --ip=0.0.0.0 --port=${PORT} HOSTID=$(squeue -h -o "%A %N %j" | grep jupyterlab | awk '{print $2}') echo "Connect" echo "ssh -N -L ${PORT}:${HOSTID}:${PORT} ${USER}@helix.bwservices.uni-heidelberg.de" echo "Job {$SLURM_JOB_ID} running on node {$SLURM_NODEID} on host {$HOSTID}." returned_code=$? echo "> Script completed with exit code ${returned_code}" exit ${returned_code}
- Run a wrapper script to execute the batch script. You could save it together with other utility scripts in a "bin" directory in your home folder.
./bin/run_jupyterlab_simple.sh
#!/bin/bash # Define parameters jobscript=~/jupyterlab.slurm # Run job job_id=$(sbatch $jobscript | awk '{print $4}') echo "jobid: $job_id" # Outfile name slurm_out=slurm-${job_id}.out # Wait for output file while [ ! -f $slurm_out ]; do sleep 2; done # Wait until url is written in output file while [ -z ${url} ]; do sleep 1; url=$(grep -o 'http[^ ]*' $slurm_out | head -n 1); done # Extract hostID and port from output. url_pattern="http://([a-z0-9]{6}):([1-9]{4})/lab" if [[ $url =~ $url_pattern ]]; then hostID=${BASH_REMATCH[1]} port=${BASH_REMATCH[2]} echo "To connect with the JupyterLab kernel, please enter the following into your local commandline: " echo "ssh -N -L $port:$hostID:$port ${USER}@helix.bwservices.uni-heidelberg.de"; fi echo "Afterwards, you can either" echo "- use the kernel in VSCode or " echo "- open JupyterLab with this URL: " echo " http://127.0.0.1:${port}/lab " echo "Note: It is normal that the ssh command doesn't end after providing the credentials. Ending the command would mean ending the local connection to the kernel." #rm $slurm_out
- Follow the instructions on the commandline to connect to the Jupyter kernel from your local machine.
Complex Use Case
If you have different use cases for juypterlab, you could use a more flexible wrapper script, for example:
./bin/run_jupyterlab.sh
#!/bin/bash
# Starts a jupyter kernel on a node and provides information on how to connect to it locally.
# If you have only one use case and therefore need only one combination of slurm settings for your jupyter jobs, then you can use the simpler script.
# This script supports explorative analyses by allowing to overwrite parameters via commandline.
# Different job configurations can be defined in advance and then used with a given short name (cpu, gpu,...).
programname=$0
function help {
'''help text'''
echo ""
echo "Starts a jupyterlab kernel"
echo ""
echo "usage example: $programname --param_set cpu"
echo ""
echo " --param_set string name of the parameter set"
echo " (examples: cpu, gpu)"
echo " --jobscript string optional, path of batch script"
echo " (default: ~/jupyterlab.slurm)"
echo " --slurm_out string optional, name of slurm output file"
echo " (default: slurm-${job_id}.out)"
}
# These parameters are set later in the script. Providing them via commandline, overwrites their values set in the script.
jobscript=None
slurm_out=None
# Process parameters
while [ $# -gt 0 ]; do
if [[ $1 == "--help" ]]; then
help
exit 0
# when given -p as parameter, use its value for the variable param_set
elif [[ $1 == "-p" ]]; then
param_set="$2"
shift
elif [[ $1 == "--"* ]]; then
v="${1/--/}"
declare "$v"="$2"
shift
fi
shift
done
function define_param_set(){
'''Define parameter sets for sbatch'''
# Define different sets
cpu=(--partition=cpu-single --mem=2gb)
gpu=(--partition=gpu-single --mem=3gb --gres=gpu:1)
param_set=${1}
param_set=$param_set[@]
param_set=("${!param_set}")
# Add params that are the same for all sets
param_set+=(--ntasks=1)
}
# @param: jobscript, name of the slurm batch script to execute
if [ "$jobscript" = "None" ]; then
jobscript=~/jupyterlab.slurm
fi
# Translate given param_set value to actual set of parameters
define_param_set $param_set
echo "param_set: ${param_set[*]}"
# Run job
job_id=$(sbatch ${param_set[@]} $jobscript | awk '{print $4}')
echo "jobid: $job_id"
# @param: slurm_out, the filename for the slurm output file
if [ "$slurm_out" = "None" ]; then
slurm_out=slurm-${job_id}.out
fi
# Wait for output file
while [ ! -f $slurm_out ]; do
sleep 1;
done
# Wait until url is written in output file
while [ -z ${url} ]; do
sleep 1;
url=$(grep -o 'http[^ ]*' $slurm_out | head -n 1);
done
# Extract hostID and port from output.
url_pattern="http://([a-z0-9]{6}):([1-9]{4})/lab"
if [[ $url =~ $url_pattern ]]; then
hostID=${BASH_REMATCH[1]}
port=${BASH_REMATCH[2]}
echo "To connect with the JupyterLab kernel, please enter the following into your local commandline: "
echo "ssh -N -L $port:$hostID:$port ${USER}@helix.bwservices.uni-heidelberg.de";
fi
echo "Afterwards, you can either"
echo "- use the kernel in VSCode or "
echo "- open JupyterLab with this URL: "
echo " http://127.0.0.1:${port}/lab "
echo "Note: It is normal that the ssh command doesn't end after providing the credentials. Ending the command would mean ending the local connection to the kernel."
#rm $slurm_out