1
0
Fork 0

/doc/codelabs: add tutorials

master
cheshire 2023-11-03 00:25:45 +01:00
parent a6592b845c
commit 6a33e8f442
6 changed files with 404 additions and 1 deletions

View File

@ -0,0 +1,117 @@
# Building your own Flask web service
In this chapter, we will build our own web service using the Flask framework, dockerize it and register it in the registry.
## Requirements
You will require `docker` in this example. Install it from your standard shell.
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
You can actually create, build and register docker image in completely other environment, and just deploy it to kubernetes in hscloud environment.
It is advised to have done [Run first service](run-first-service.md) chapter.
## Steps
We create a simple Flask application:
```py
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
```
We can check if the application works by running it:
```bash
pip3 install flask
python3 app.py
```
Now we create `Dockerfile` file for our application:
```Dockerfile
# Use an official Python runtime as a base image
FROM python:3.8-slim-buster
# Set the working directory in docker
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --upgrade pip && \
pip install flask gunicorn
# Set environment variables
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
# Expose port 5000 for the Flask app to listen on
EXPOSE 5000
# Define command to run the application using gunicorn
CMD ["gunicorn", "-w", "4", "-b", ":5000", "app:app"]
```
We can test if the application works in Docker:
```bash
docker build -t myflask . # Build the image
docker run -d -p 5000:5000 myflask # Run the container
```
We can check if the application works by opening the browser at `http://localhost:5000`.
## Pushing the image to the registry
First, we need to authenticate to the registry:
```
https://registry.k0.hswaw.net
```
You should get command similar to:
```
docker login -u $hs_username -p *************** https://registry.k0.hswaw.net
```
Now we need to create local server for our docker image:
```bash
docker tag myflask registry.k0.hswaw.net/$hs_username/myflask:latest
docker push registry.k0.hswaw.net/$hs_username/myflask:latest
```
To check if the image is in the registry, you can use:
```bash
curl -X GET https://registry.k0.hswaw.net/v2/$hs_username/myflask/tags/list
```
To remove the image from the registry, you can use:
```bash
docker rmi registry.k0.hswaw.net/$hs_username/myflask:latest
```
## Next step
[Deploying web app](deploying-web-app.md)

View File

@ -0,0 +1,95 @@
# Deploying docker image on hscloud
In this chapter, we will deploy our registered docker image on `hscloud` as a simple HTTP kube service with HTTPS from Let's Encrypt.
## Requirements
Registered image from [Building web app](building-web-app.md):
```
https://registry.k0.hswaw.net/$hs_username/myflask:latest
```
## Steps
We create a `prod.jsonnet` file in location `//personal/$hs_username/myflask/prod.jsonnet`:
```jsonnet
# Remember to replace $hs_username with your SSO username!
local kube = import "../../../kube/kube.libsonnet";
{
local top = self,
local cfg = self.cfg,
cfg:: {
name: 'web-app',
namespace: 'personal-$hs_username',
domain: 'web-app.$hs_username.hscloud.ovh',
image: 'registry.k0.hswaw.net/$hs_username/myflask:latest',
},
ns: kube.Namespace(cfg.namespace),
deployment: top.ns.Contain(kube.Deployment(cfg.name)) {
spec+: {
replicas: 1,
template+: {
spec+: {
containers_: {
default: kube.Container("default") {
image: cfg.image,
ports_: {
http: { containerPort: 5000 },
}
},
},
},
},
},
},
service: top.ns.Contain(kube.Service(cfg.name)) {
target_pod:: top.deployment.spec.template,
},
ingress: top.ns.Contain(kube.Ingress(cfg.name)) {
metadata+: {
annotations+: {
"kubernetes.io/tls-acme": "true",
"cert-manager.io/cluster-issuer": "letsencrypt-prod",
"nginx.ingress.kubernetes.io/proxy-body-size": "0",
},
},
spec+: {
tls: [ { hosts: [ cfg.domain ], secretName: cfg.name + "-tls" } ],
rules: [
{
host: cfg.domain,
http: {
paths: [
{ path: "/", backend: top.service.name_port },
],
},
},
],
},
},
}
```
We can now deploy our application:
```bash
kubecfg update prod.jsonnet
```
The application should be available at `http://web-app.$hs_username.hscloud.ovh`. You will have to wait several seconds for the working HTTPS service.
To remove the application, execute:
```bash
kubecfg delete prod.jsonnet
```

View File

@ -0,0 +1,84 @@
# Building an environment
In this chapter, I will describe how to build an environment in which we will build hscloud services.
## Requirements
You need `git` and `curl`. On Ubuntu you can install them with:
```bash
sudo apt install git curl
```
Clone the repository with the source code of the cloud services:
```bash
git clone "https://gerrit.hackerspace.pl/hscloud"
cd hscloud
```
If you want to commit anything on gerrit, we have to do additional steps ([source](https://gerrit.hackerspace.pl/admin/repos/hscloud,general)):
```bash
mkdir -p .git/hooks/
curl -Lo .git/hooks/commit-msg https://gerrit.hackerspace.pl/tools/hooks/commit-msg
chmod +x .git/hooks/commit-msg
```
## Steps
We can configure the environment using niix-shell. To do this, we install `nix`:
```bash
sh <(curl -L https://nixos.org/nix/install) --daemon
```
And we start it (from inside the `hscloud` folder):
```bash
nix-shell
```
We now use the `bazel` tool to build and run the necessary services, including `prodaccess` and `kubectl`:
```bash
bazel build //tools:install
bazel run //tools:install
```
Now we can request to grant us access to the hscloud cluster through the [prodaccess](https://pkg.go.dev/code.hackerspace.pl/hscloud/cluster/prodaccess#section-readme) tool. In place of `$hs_username` insert the username in SSO hackerspace:
```bash
hs_username=$USER # if your username is the same as your SSO username
prodaccess -username $hs_username
```
If you do not have access to the cluster, contact [@q3k](q3k:hackerspace.pl) or [@inf](informatic:hackerspace.pl) within [Matrix](https://matrix.hackerspace.pl/).
To check if we have access to the cluster, we can run the command:
```bash
# shows the Kubernetes version
kubectl version
# shows the statistics of the cluster
kubectl top nodes
```
We can also call the public Docker image (again, in place of `$hs_username`, insert the username in SSO hackerspace):
```bash
# to create an instance of (sub) alpine
kubectl -n personal-$hs_username run --image=alpine:latest -it foo
```
If you want to delete the instance, run:
```bash
# to delete an instance (sub) of alpine
kubectl -n personal-$hs_username delete pod foo
```
## Next step
Next step: [Run first service](run-first-service.md)

View File

@ -0,0 +1,103 @@
# Running a public service in hscloud
In this chapter, I will show you how to run an existing service that will be publicly available on the Internet.
## Requirements
Done steps from [**Prepare environment**](prepare-environment.md) chapter.
## Creating a copy of ldapweb
We start in the `hscloud` folder, with the `nix-shell` environment enabled. If you don't have your namespace in the `//personal` folder yet, we create it:
```bash
mkdir personal/$hs_username
```
We copy the configuration of the `ldapweb` service into the workspace:
```bash
cp -r hswaw/ldapweb/ personal/$hs_username/
cd personal/$hs_username/ldapweb/
```
## Modifying the service
The configuration of `ldapweb` is contained in the `prod.jsonnet` file. The format of `jsonnet` is very similar to `json`, but allows the use of variables, functions, and the import of other files.
We are interested in the initial part of the file:
```jsonnet
local kube = import "../../kube/kube.libsonnet"
{
local top = self,
local cfg = self.cfg,
cfg:: {
name: 'ldapweb',
namespace: 'ldapweb',
domain: 'profile.hackerspace.pl',
image: 'registry.k0.hswaw.net/radex/ldap-web:1695486391',
},
...
}
```
The import is done from the `kube.libsonnet` file in the `kube` folder in the `hscloud` folder. In order for the import to proceed correctly in this case, we need to go back one more folder: `../../../kube/kube.libsonnet`.
The `hscloud` configuration only allows the namespace in `personal-$hs_username` format. In addition, we need to change the domain to `*.$hs_username.hscloud.ovh`. Finally, we change the service name to `test`.
Finally, the above fragment of the `prod.jsonnet` file should look like this:
```jsonnet
# remember to replace $hs_username with your username!
local kube = import "../../../kube/kube.libsonnet";
{
local top = self,
local cfg = self.cfg,
cfg:: {
name: 'test',
namespace: 'personal-$hs_username',
domain: 'test.$hs_username.hscloud.ovh',
image: 'registry.k0.hswaw.net/radex/ldap-web:1695486391',
},
...
}
```
We log into the cluster:
```bash
hs_username=$USER # if your username is the same as your SSO username
prodaccess -username $hs_username
```
We invoke the command to apply the changes:
```bash
kubecfg update prod.jsonnet
```
Our service should be at `https://test.$hs_username.hscloud.ovh/`. During the first couple of minutes we will get a message about an invalid certificate, because the Let's Encrypt service has not yet managed to generate a certificate for our domain.
To remove the service, call:
```bash
kubecfg delete prod.jsonnet
```
or
```bash
kubectl delete service test -n personal-$hs_username
```
## Next step
[Building web app](building-web-app.md)

View File

@ -189,5 +189,5 @@ Further steps
- If you need a **Git refresher** - we highly recommend the [Git Visual Reference](https://marklodato.github.io/visual-git-guide/index-en.html)
- [Bazel & Go basics](bazel-go.md) will (TODO) guide you through building some code using Bazel, and then writing a tiny bit of Go code of your own.
- **TODO** will guide you through accessing our production Kubernetes cluster and running some code on it.
- [Prepare environment with nix](prepare-environment.md) will guide you through accessing our production Kubernetes cluster and running some code on it.

View File

@ -11,6 +11,10 @@ Getting started
- [**Checking out hscloud**](getting-started/checking-out.md) - how to get a copy of hscloud, how to navigate around it, and what's what. This is nearly **mandatory** for anyone who wishes to interact with hscloud.
- [**Your First Change**](getting-started/your-first-change.md) - how to use Gerrit and git to send your first change to hscloud, and an intro to personal directories. Using Gerrit can be somewhat confusing even (or especially) if you're used to Gitflow or GitHub.
- [**Bazel & Go basics**](getting-started/bazel-go.md) - will (TODO) guide you through building some code using Bazel, and then writing a tiny bit of Go code of your own.
- [**Preparing kubernetes environment**](getting-started/prepare-environment.md) - how to build environment using `nix` and `bazel`, to be able to run first kubernetes pod.
- [**Creating test pod**](getting-started/run-first-service.md) - how to deploy first service from available image.
- [**Building web app**](getting-started/building-web-app.md) - how to prepare our first Flask app and register it on hscloud k8s registry.
- [**Deploying web app**](getting-started/deploying-web-app.md) - how to deploy our registed web app.
See also
--------