4.3 Hetzner solution

This commit is contained in:
Łukasz Jędyk 2022-01-05 00:38:14 +01:00
parent 367f7677c4
commit aba3a6f475
7 changed files with 229 additions and 141 deletions

142
.gitignore vendored
View File

@ -1,140 +1,2 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
__pycache__
ssh_key.txt

View File

@ -1,2 +1,18 @@
# 434708-PZC-4.3
## Wymagania
1. Python3
2. pip3
## Instrukcja krok po kroku
1. Instalacja wymaganych pakietów.
```
pip3 install -r requirements.txt
```
2. Utworzyć plik 'ssh_key.txt' i umieścić w nim klucz, który zostanie użyty do dostępu do maszyny.
3. Uruchomienie skryptu tworzącego maszyny oraz load balancer, jako argument podać klucz API Hetzner.
```
python3 deploy.py <api-key>
```
4. Usunięcie utworzonej zasobów (opcjonalne).
```
python3 remove.py <api-key>
```

6
cloud-init Normal file
View File

@ -0,0 +1,6 @@
#cloud-config
runcmd:
- wget https://git.wmi.amu.edu.pl/s470611/DPZC-aws/raw/branch/master/webservice
- chmod +x webservice
- ./webservice

21
constants.py Normal file
View File

@ -0,0 +1,21 @@
SSH_KEY_FNAME = "ssh_key.txt"
CLOUD_INIT_FNAME = "cloud-init"
SSH_KEY_NAME = "434708-4.3"
IP_RANGE = "10.10.10.0/24"
NETWORK_ZONE = "eu-central"
NETWORK_TYPE = "cloud"
VNET_NAME = "434708-4.3-vnet"
SERVER_NAME_1 = "434708-4.3-1"
SERVER_NAME_2 = "434708-4.3-2"
MACHINE_TYPE = "cpx11"
MACHINE_OS = "ubuntu-20.04"
LOAD_BALANCER_NAME = "434708-4.3-lb"
LOAD_BALANCER_ALG = "least_connections"
LB_TYPE = "lb11"
LOCATION = "hel1"

155
deploy.py Normal file
View File

@ -0,0 +1,155 @@
import sys
from constants import *
from hcloud import Client
from hcloud.locations.domain import Location
from hcloud.networks.domain import NetworkSubnet
from hcloud.images.domain import Image
from hcloud.server_types.domain import ServerType
from hcloud.load_balancer_types.domain import LoadBalancerType
from hcloud.load_balancers.domain import LoadBalancerAlgorithm
from hcloud.load_balancers.domain import LoadBalancerService
from hcloud.load_balancers.domain import LoadBalancerServiceHttp
from hcloud.load_balancers.domain import LoadBalancerHealthCheck
from hcloud.load_balancers.domain import LoadBalancerHealtCheckHttp
from hcloud.load_balancers.domain import LoadBalancerTarget
with open(SSH_KEY_FNAME, "r") as file:
ssh_key_text = file.read()
with open(CLOUD_INIT_FNAME, "r") as file:
cloud_init = file.read()
if len(sys.argv) < 2:
raise ValueError("API key must be provided as an argument!")
client = Client(
token=str(sys.argv[1])
)
# ssh key
if client.ssh_keys.get_by_name(SSH_KEY_NAME):
ssh_key = client.ssh_keys.get_by_name(SSH_KEY_NAME)
else:
ssh_key = client.ssh_keys.create(name=SSH_KEY_NAME, public_key=ssh_key_text)
print(f"Klucz {ssh_key.data_model.name} został utworzony.")
# network
if client.networks.get_by_name(VNET_NAME):
vnet = client.networks.get_by_name(VNET_NAME)
else:
vnet = client.networks.create(
name=VNET_NAME,
ip_range=IP_RANGE,
subnets=[
NetworkSubnet(ip_range=IP_RANGE, network_zone=NETWORK_ZONE, type=NETWORK_TYPE)
]
)
print(f"Utworzono sieć wirtualną: {vnet.data_model.name} ({vnet.data_model.ip_range})")
# webservice_1
if(client.servers.get_by_name(SERVER_NAME_1)):
webservice_1 = client.servers.get_by_name(SERVER_NAME_1)
else:
webservice_1_response = client.servers.create(
name=SERVER_NAME_1,
server_type=ServerType(MACHINE_TYPE),
image=Image(name=MACHINE_OS),
ssh_keys=[ssh_key],
networks=[vnet],
location=Location(LOCATION),
user_data=cloud_init
)
webservice_1_response.action.wait_until_finished()
webservice_1 = webservice_1_response.server
print(f"Utworzono webservice 1: {webservice_1.data_model.name} ({webservice_1.data_model.public_net.ipv4.ip})")
# webservice_2
if(client.servers.get_by_name(SERVER_NAME_2)):
webservice_2 = client.servers.get_by_name(SERVER_NAME_2)
else:
webservice_2_response = client.servers.create(
name=SERVER_NAME_2,
server_type=ServerType(MACHINE_TYPE),
image=Image(name=MACHINE_OS),
ssh_keys=[ssh_key],
networks=[vnet],
location=Location(LOCATION),
user_data=cloud_init
)
webservice_2_response.action.wait_until_finished()
webservice_2 = webservice_2_response.server
print(f"Utworzono webservice 2: {webservice_2.data_model.name} ({webservice_2.data_model.public_net.ipv4.ip})")
# load balance service health check http
lb_health_check_http = LoadBalancerHealtCheckHttp(
path="/factors/10",
status_codes=["2??", "3??"],
tls=False,
)
# load balance service health check
lb_health_check = LoadBalancerHealthCheck(
protocol="http",
port="8080",
interval=10,
timeout=6,
retries=3,
http=lb_health_check_http
)
# load balance http
lb_service_http = LoadBalancerServiceHttp(
cookie_name="HCLBSTICKY",
cookie_lifetime="300",
certificates=[],
redirect_http=False,
sticky_sessions=False,
)
# load balancer service
lb_service = LoadBalancerService(
protocol="http",
listen_port="8080",
destination_port="8080",
proxyprotocol=False,
health_check=lb_health_check,
http=lb_service_http
)
# webservice_1 target
webservice_1_target = LoadBalancerTarget(
type="server",
server=webservice_1,
use_private_ip=True
)
# webservice_2 target
webservice_2_target = LoadBalancerTarget(
type="server",
server=webservice_2,
use_private_ip=True
)
# load balancer
if(client.load_balancers.get_by_name(LOAD_BALANCER_NAME)):
load_balancer = client.load_balancers.get_by_name(LOAD_BALANCER_NAME)
else:
load_balancer_response = client.load_balancers.create(
name=LOAD_BALANCER_NAME,
load_balancer_type=LoadBalancerType(name=LB_TYPE),
location=Location(LOCATION),
algorithm=LoadBalancerAlgorithm(LOAD_BALANCER_ALG),
services=[lb_service],
targets=[webservice_1_target, webservice_2_target],
public_interface=True,
network=vnet
)
load_balancer_response.action.wait_until_finished()
load_balancer = client.load_balancers.get_by_name(LOAD_BALANCER_NAME)
print(f"Utworzono load balancer: {load_balancer.data_model.name} ({load_balancer.data_model.public_net.ipv4.ip}:8080)")

27
remove.py Normal file
View File

@ -0,0 +1,27 @@
import sys
from constants import *
from hcloud import Client
if len(sys.argv) < 2:
raise ValueError("API key must be provided as an argument!")
client = Client(
token=str(sys.argv[1])
)
ssh_key = client.ssh_keys.get_by_name(SSH_KEY_NAME)
vnet = client.networks.get_by_name(VNET_NAME)
webservice_1 = client.servers.get_by_name(SERVER_NAME_1)
webservice_2 = client.servers.get_by_name(SERVER_NAME_2)
load_balancer = client.load_balancers.get_by_name(LOAD_BALANCER_NAME)
if load_balancer:
load_balancer.delete()
if webservice_1:
webservice_1.delete()
if webservice_2:
webservice_2.delete()
if vnet:
vnet.delete()
if ssh_key:
ssh_key.delete()

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
hcloud==1.16.0