mirror of
https://gerrit.hackerspace.pl/hscloud
synced 2024-10-18 02:37:45 +00:00
docs: update CRLF to more based LF to remove hsdocs bad render
Change-Id: I8ccb44a6e659f8d280849f780700b322de7bdc12 Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1824 Reviewed-by: radex <radex@hackerspace.pl>
This commit is contained in:
parent
c370e44c23
commit
dccfc0d3f4
3 changed files with 326 additions and 318 deletions
|
@ -1,125 +1,125 @@
|
||||||
# Building your own Flask web service
|
# 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.
|
In this chapter, we will build our own web service using the Flask framework, dockerize it and register it in the registry.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
You will require `docker` in this example. You can find installation instructions [here](https://docs.docker.com/engine/install/). For example, on Ubuntu you can install it with:
|
You will require `docker` in this example. You can find installation instructions [here](https://docs.docker.com/engine/install/). For example, on Ubuntu you can install it with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
sudo sh get-docker.sh
|
sudo sh get-docker.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
To create, build and register docker image you don't need a compiled hscloud environment, howerver you will need it to deploy the image to kubernetes.
|
To create, build and register docker image you don't need a compiled hscloud environment, howerver you will need it to deploy the image to kubernetes.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
We create a simple Flask application:
|
We create a simple Flask application:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
# app.py
|
# app.py
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
|
||||||
def hello_world():
|
def hello_world():
|
||||||
return 'Hello, World!'
|
return 'Hello, World!'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run()
|
app.run()
|
||||||
```
|
```
|
||||||
|
|
||||||
We can check if the application works by running it. First we start the virtual environment and install Flask:
|
We can check if the application works by running it. First we start the virtual environment and install Flask:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# for Linux and macOS environments
|
# for Linux and macOS environments
|
||||||
python3 -m venv .venv
|
python3 -m venv .venv
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# for Windows environments
|
# for Windows environments
|
||||||
py -m venv .venv
|
py -m venv .venv
|
||||||
.venv\bin\Activate.bat
|
.venv\bin\Activate.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
After that:
|
After that:
|
||||||
```bash
|
```bash
|
||||||
pip3 install flask
|
pip3 install flask
|
||||||
python3 app.py
|
python3 app.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we create `Dockerfile` file for our application:
|
Now we create `Dockerfile` file for our application:
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
# Use an official Python runtime as a base image
|
# Use an official Python runtime as a base image
|
||||||
FROM python:3.12.0-bullseye
|
FROM python:3.12.0-bullseye
|
||||||
|
|
||||||
# Set the working directory in docker
|
# Set the working directory in docker
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy the current directory contents into the container at /app
|
# Copy the current directory contents into the container at /app
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|
||||||
# Install any needed packages specified in requirements.txt
|
# Install any needed packages specified in requirements.txt
|
||||||
RUN pip install --upgrade pip && \
|
RUN pip install --upgrade pip && \
|
||||||
pip install flask gunicorn
|
pip install flask gunicorn
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV FLASK_APP=app.py
|
ENV FLASK_APP=app.py
|
||||||
ENV FLASK_RUN_HOST=0.0.0.0
|
ENV FLASK_RUN_HOST=0.0.0.0
|
||||||
|
|
||||||
# Expose port 5000 for the Flask app to listen on
|
# Expose port 5000 for the Flask app to listen on
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|
||||||
# Define command to run the application using gunicorn
|
# Define command to run the application using gunicorn
|
||||||
CMD ["gunicorn", "-w", "4", "-b", ":5000", "app:app"]
|
CMD ["gunicorn", "-w", "4", "-b", ":5000", "app:app"]
|
||||||
```
|
```
|
||||||
|
|
||||||
We can test if the application works in Docker:
|
We can test if the application works in Docker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t myflask:2137 . # Build the image
|
docker build -t myflask:2137 . # Build the image
|
||||||
docker run -p 5000:5000 myflask:2137 # Run the container
|
docker run -p 5000:5000 myflask:2137 # Run the container
|
||||||
```
|
```
|
||||||
|
|
||||||
We can check if the application works by opening the browser at `http://localhost:5000`.
|
We can check if the application works by opening the browser at `http://localhost:5000`.
|
||||||
|
|
||||||
## Pushing the image to the registry
|
## Pushing the image to the registry
|
||||||
|
|
||||||
First, we need to authenticate to the registry. That will require visiting the link in a web browser:
|
First, we need to authenticate to the registry. That will require visiting the link in a web browser:
|
||||||
|
|
||||||
```
|
```
|
||||||
https://registry.k0.hswaw.net
|
https://registry.k0.hswaw.net
|
||||||
```
|
```
|
||||||
|
|
||||||
You should get command similar to:
|
You should get command similar to:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker login -u $hs_username -p *************** https://registry.k0.hswaw.net
|
docker login -u $hs_username -p *************** https://registry.k0.hswaw.net
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it in your environment.
|
Run it in your environment.
|
||||||
|
|
||||||
Now we need to create local server for our docker image:
|
Now we need to create local server for our docker image:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# create local server for our docker image. Replace $hs_username with your sso username
|
# create local server for our docker image. Replace $hs_username with your sso username
|
||||||
docker tag myflask:2137 registry.k0.hswaw.net/$hs_username/myflask:2137
|
docker tag myflask:2137 registry.k0.hswaw.net/$hs_username/myflask:2137
|
||||||
docker push registry.k0.hswaw.net/$hs_username/myflask:2137
|
docker push registry.k0.hswaw.net/$hs_username/myflask:2137
|
||||||
```
|
```
|
||||||
|
|
||||||
To remove the image from the registry, you can use:
|
To remove the image from the registry, you can use:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# remove image from registry. Replace $hs_username with your sso username
|
# remove image from registry. Replace $hs_username with your sso username
|
||||||
docker rmi registry.k0.hswaw.net/$hs_username/myflask:2137
|
docker rmi registry.k0.hswaw.net/$hs_username/myflask:2137
|
||||||
```
|
```
|
||||||
|
|
||||||
## Next step
|
## Next step
|
||||||
|
|
||||||
[Deploying Flask web app](deploying-flask-web-app.md)
|
[Deploying Flask web app](deploying-flask-web-app.md)
|
|
@ -1,119 +1,119 @@
|
||||||
# Deploying docker image on hscloud
|
# 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.
|
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
|
## Requirements
|
||||||
|
|
||||||
Registered image from [Building web app](building-web-app.md). Also, built `hscloud` environment from [Building an environment](prepare-environment.md) section.
|
Registered image from [Building web app](building-web-app.md). Also, built `hscloud` environment from [Building an environment](prepare-environment.md) section.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
We create a `prod.jsonnet` file in location `//personal/$hs_username/myflask/prod.jsonnet`.
|
We create a `prod.jsonnet` file in location `//personal/$hs_username/myflask/prod.jsonnet`.
|
||||||
The format of `jsonnet` is very similar to `json`, but allows the use of variables, functions, and the import of other files.
|
The format of `jsonnet` is very similar to `json`, but allows the use of variables, functions, and the import of other files.
|
||||||
For further reference on `jsonnet` see [jsonnet.org](https://jsonnet.org/learning/tutorial.html).
|
For further reference on `jsonnet` see [jsonnet.org](https://jsonnet.org/learning/tutorial.html).
|
||||||
|
|
||||||
|
|
||||||
```jsonnet
|
```jsonnet
|
||||||
# Remember to replace $hs_username with your SSO username!
|
# Remember to replace $hs_username with your SSO username!
|
||||||
|
|
||||||
# The import is done from the `kube.libsonnet` file in the `kube` folder in the `hscloud` folder.
|
# The import is done from the `kube.libsonnet` file in the `kube` folder in the `hscloud` folder.
|
||||||
local kube = import "../../../kube/kube.libsonnet";
|
local kube = import "../../../kube/kube.libsonnet";
|
||||||
|
|
||||||
{
|
{
|
||||||
local top = self,
|
local top = self,
|
||||||
local cfg = self.cfg,
|
local cfg = self.cfg,
|
||||||
|
|
||||||
cfg:: {
|
cfg:: {
|
||||||
name: 'web-app',
|
name: 'web-app',
|
||||||
# The hscloud configuration only allows the namespace in `personal-$hs_username` format.
|
# The hscloud configuration only allows the namespace in `personal-$hs_username` format.
|
||||||
namespace: 'personal-$hs_username',
|
namespace: 'personal-$hs_username',
|
||||||
# The hscloud configuration only allows the domain in `*.$hs_username.hscloud.ovh` format.
|
# The hscloud configuration only allows the domain in `*.$hs_username.hscloud.ovh` format.
|
||||||
domain: 'web-app.$hs_username.hscloud.ovh',
|
domain: 'web-app.$hs_username.hscloud.ovh',
|
||||||
image: 'registry.k0.hswaw.net/$hs_username/myflask:2137',
|
image: 'registry.k0.hswaw.net/$hs_username/myflask:2137',
|
||||||
},
|
},
|
||||||
|
|
||||||
ns: kube.Namespace(cfg.namespace),
|
ns: kube.Namespace(cfg.namespace),
|
||||||
|
|
||||||
deployment: top.ns.Contain(kube.Deployment(cfg.name)) {
|
deployment: top.ns.Contain(kube.Deployment(cfg.name)) {
|
||||||
spec+: {
|
spec+: {
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
template+: {
|
template+: {
|
||||||
spec+: {
|
spec+: {
|
||||||
containers_: {
|
containers_: {
|
||||||
default: kube.Container("default") {
|
default: kube.Container("default") {
|
||||||
image: cfg.image,
|
image: cfg.image,
|
||||||
ports_: {
|
ports_: {
|
||||||
http: { containerPort: 5000 },
|
http: { containerPort: 5000 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
service: top.ns.Contain(kube.Service(cfg.name)) {
|
service: top.ns.Contain(kube.Service(cfg.name)) {
|
||||||
target_pod:: top.deployment.spec.template,
|
target_pod:: top.deployment.spec.template,
|
||||||
},
|
},
|
||||||
|
|
||||||
ingress: top.ns.Contain(kube.Ingress(cfg.name)) {
|
ingress: top.ns.Contain(kube.Ingress(cfg.name)) {
|
||||||
metadata+: {
|
metadata+: {
|
||||||
annotations+: {
|
annotations+: {
|
||||||
"kubernetes.io/tls-acme": "true",
|
"kubernetes.io/tls-acme": "true",
|
||||||
"cert-manager.io/cluster-issuer": "letsencrypt-prod",
|
"cert-manager.io/cluster-issuer": "letsencrypt-prod",
|
||||||
"nginx.ingress.kubernetes.io/proxy-body-size": "0",
|
"nginx.ingress.kubernetes.io/proxy-body-size": "0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
spec+: {
|
spec+: {
|
||||||
tls: [ { hosts: [ cfg.domain ], secretName: cfg.name + "-tls" } ],
|
tls: [ { hosts: [ cfg.domain ], secretName: cfg.name + "-tls" } ],
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
host: cfg.domain,
|
host: cfg.domain,
|
||||||
http: {
|
http: {
|
||||||
paths: [
|
paths: [
|
||||||
{ path: "/", backend: top.service.name_port },
|
{ path: "/", backend: top.service.name_port },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We log into the cluster:
|
We log into the cluster:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hs_username=$USER # if your username is the same as your SSO username
|
hs_username=$USER # if your username is the same as your SSO username
|
||||||
prodaccess -username $hs_username
|
prodaccess -username $hs_username
|
||||||
```
|
```
|
||||||
|
|
||||||
We can now deploy our application:
|
We can now deploy our application:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubecfg update prod.jsonnet
|
kubecfg update prod.jsonnet
|
||||||
```
|
```
|
||||||
|
|
||||||
The application should be available at `http://web-app.$hs_username.hscloud.ovh`. You will have to wait a few minutes for a working HTTPS service.
|
The application should be available at `http://web-app.$hs_username.hscloud.ovh`. You will have to wait a few minutes for a working HTTPS service.
|
||||||
|
|
||||||
You can also list the pods:
|
You can also list the pods:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List pods in the namespace. Replace $hs_username with your SSO username!
|
# List pods in the namespace. Replace $hs_username with your SSO username!
|
||||||
kubectl get pods --namespace personal-$hs_username
|
kubectl get pods --namespace personal-$hs_username
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see something like this:
|
You should see something like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
NAME READY STATUS RESTARTS AGE
|
NAME READY STATUS RESTARTS AGE
|
||||||
...
|
...
|
||||||
web-app-569996b8d8-lfl68 1/1 Running 0 18m
|
web-app-569996b8d8-lfl68 1/1 Running 0 18m
|
||||||
```
|
```
|
||||||
|
|
||||||
To remove the application, execute following command, taking your pod name from the previous command, in this case `web-app-569996b8d8-lfl68`:
|
To remove the application, execute following command, taking your pod name from the previous command, in this case `web-app-569996b8d8-lfl68`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Delete the pod. Replace $hs_username with your SSO username!
|
# Delete the pod. Replace $hs_username with your SSO username!
|
||||||
kubectl delete pod web-app-569996b8d8-lfl68 --namespace personal-$hs_username
|
kubectl delete pod web-app-569996b8d8-lfl68 --namespace personal-$hs_username
|
||||||
```
|
```
|
|
@ -1,77 +1,85 @@
|
||||||
# Building an environment
|
# Building an environment
|
||||||
|
|
||||||
In this chapter, I will describe how to build an environment in which we will build hscloud services.
|
In this chapter, I will describe how to build an environment in which we will build hscloud services.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
You need `git` and `curl`. On Ubuntu you can install them with:
|
You need `git` and `curl`. On Ubuntu you can install them with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install git curl
|
sudo apt install git curl
|
||||||
```
|
```
|
||||||
|
|
||||||
Clone the repository with the source code of the cloud services:
|
Clone the repository with the source code of the cloud services:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone "https://gerrit.hackerspace.pl/hscloud"
|
git clone "https://gerrit.hackerspace.pl/hscloud"
|
||||||
cd hscloud
|
cd hscloud
|
||||||
```
|
```
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
We can configure the environment using nix-shell. To do this, we install `nix`:
|
We can configure the environment using nix-shell. To do this, we install `nix`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sh <(curl -L https://nixos.org/nix/install) --daemon
|
sh <(curl -L https://nixos.org/nix/install) --daemon
|
||||||
```
|
```
|
||||||
|
|
||||||
And we start it (from inside the `hscloud` folder):
|
And we start it (from inside the `hscloud` folder):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix-shell
|
nix-shell
|
||||||
```
|
```
|
||||||
|
|
||||||
We now use the `bazel` tool to build and run the necessary services, including `prodaccess` and `kubecfg`:
|
(alternatively, you can skip whole `nix shell` config and just install dependencies):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bazel build //tools:install
|
sudo apt-get -y install default-jre default-jdk python3-dev build-essential clang wget libpq-dev zip git
|
||||||
bazel run //tools:install
|
wget https://github.com/bazelbuild/bazelisk/releases/download/v1.18.0/bazelisk-linux-amd64 -O /usr/bin/bazel
|
||||||
```
|
chmod +x /usr/bin/bazel
|
||||||
|
```
|
||||||
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:
|
We now use the `bazel` tool to build and run the necessary services, including `prodaccess` and `kubecfg`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hs_username=$USER # if your username is the same as your SSO username
|
bazel build //tools:install
|
||||||
prodaccess -username $hs_username
|
bazel run //tools:install
|
||||||
```
|
```
|
||||||
|
|
||||||
If you do not have access to the cluster, contact someone within [Matrix #infra channel](https://matrix.to/#/#infra:hackerspace.pl).
|
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:
|
||||||
To check if we have access to the cluster, we can run the command:
|
|
||||||
|
```bash
|
||||||
```bash
|
hs_username=$USER # if your username is the same as your SSO username
|
||||||
# shows the Kubernetes version
|
prodaccess -username $hs_username
|
||||||
kubectl version
|
```
|
||||||
|
|
||||||
# shows the statistics of the cluster
|
If you do not have access to the cluster, contact someone within [Matrix #infra channel](https://matrix.to/#/#infra:hackerspace.pl).
|
||||||
kubectl top nodes
|
|
||||||
```
|
To check if we have access to the cluster, we can run the command:
|
||||||
|
|
||||||
We can also call the public Docker image (again, in place of `$hs_username`, insert the username in SSO hackerspace):
|
```bash
|
||||||
|
# shows the Kubernetes version
|
||||||
```bash
|
kubectl version
|
||||||
# to create an instance of (sub) alpine
|
|
||||||
kubectl -n personal-$hs_username run --image=alpine:latest -it foo
|
# shows the statistics of the cluster
|
||||||
```
|
kubectl top nodes
|
||||||
|
```
|
||||||
If you want to delete the instance, run:
|
|
||||||
|
We can also call the public Docker image (again, in place of `$hs_username`, insert the username in SSO hackerspace):
|
||||||
```bash
|
|
||||||
# to delete an instance (sub) of alpine
|
```bash
|
||||||
kubectl -n personal-$hs_username delete pod foo
|
# to create an instance of (sub) alpine
|
||||||
```
|
kubectl -n personal-$hs_username run --image=alpine:latest -it foo
|
||||||
|
```
|
||||||
## Next step
|
|
||||||
|
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: [Building Flask web app](building-flask-web-app.md)
|
Next step: [Building Flask web app](building-flask-web-app.md)
|
Loading…
Reference in a new issue