Servidor de Python al Cloud amb Emmagatzematge S3 Compartit
🎯 Objectius
- Configurar un servidor Jupyter Notebook a AWS EC2.
- Utilitzar
systemdper gestionar Jupyter com a servei. - Descobrir l’emmagatzematge al núvol amb AWS S3.
- Accedir a S3 des de Jupyter i diferents clients.
- Sincronitzar dades entre EC2 i S3.
- Automatitzar la sincronització amb scripts i Lambda.
🧱 Fase 1: Llançament del Núvol (EC2 + Jupyter com a servei)
1.1 Crear instància EC2
Aneu al AWS Educate Learner Lab i accediu al vostre entorn.
Cerqueu EC2 i creeu una nova instància.
Seleccioneu una AMI Linux i tipus d’instància de baix cost (
t2.micro).Configureu un Security Group:
- Port 22 (SSH) acceptant 0.0.0.0/0.
- Port 8888 (Jupyter) acceptant 0.0.0.0/0.
Llançeu la instància.
1.2 Instal·lar Jupyter Notebook
Connecteu-vos a la instància via SSH.
Actualitzeu els paquets:
sudo yum update -yComproveu que Python3 està instal·lat:
python3 --versionCrearem un entorn virtual per Jupyter al directori
/home/ec2-user/jupyter/env:mkdir -p /home/ec2-user/jupyter python3 -m venv /home/ec2-user/jupyter/env source /home/ec2-user/jupyter/env/bin/activateInstal·leu Jupyter:
pip install jupyterComproveu la instal·lació:
jupyter --versionArranqueu Jupyter:
jupyter-notebook --ip=0.0.0.0 --port=8888 --no-browserAccediu a Jupyter des del navegador amb
http://<IP_PUBLICA>:8888. A la terminal veureu un token d’accés que necessitareu per entrar.
Pregunta de reflexió
- Per què és recomanable executar Jupyter en un entorn virtual separat en lloc d’instal·lar-lo directament al sistema?
🧠 Servei jupyter amb systemd
Ara configurarem Jupyter per executar-lo com un servei de sistema amb systemd, de manera que s’iniciï automàticament a l’arrencada i s’executi en segon pla. La següent taula resumeix els components principals que crearem:
| Component | Lloc | Propòsit |
|---|---|---|
| Usuari de sistema | jupyter (no shell, no home) |
Executar Jupyter de manera segura, únicament per a aquest servei. |
| Configuració Jupyter | /etc/jupyter |
Configuració i credencials de Jupyter. |
| Entorn virtual | /opt/jupyter/env |
Paquets de Python aïllats per Jupyter. |
| Directori de treball | /srv/jupyter |
On es guarden els notebooks i dades. |
| Unitat systemd | /etc/systemd/system/jupyter.service |
Configuració del servei Jupyter per a systemd. |
Crearem un usuari dedicat per a Jupyter:
sudo useradd --system --no-create-home --shell /sbin/nologin jupyter sudo passwd -l jupyterCrearem els directoris necessaris:
sudo mkdir -p /etc/jupyter /opt/jupyter/env /srv/jupyter mkdir /etc/jupyter/runtime /srv/jupyter/notebooks sudo chown -R jupyter:jupyter /srv/jupyter /etc/jupyter /opt/jupyterInstal·larem Jupyter a l’entorn virtual:
sudo python3 -m venv /opt/jupyter/env sudo chown -R jupyter:jupyter /opt/jupyter/env sudo -u jupyter /opt/jupyter/env/bin/pip install --upgrade pip sudo -u jupyter /opt/jupyter/env/bin/pip install jupyterGenereu el fitxer de configuració de Jupyter:
sudo -u jupyter env HOME=/tmp /opt/jupyter/env/bin/jupyter-notebook --generate-config --config-dir=/etc/jupyterEditeu el fitxer de configuració per definir directori i ports:
sudo -u jupyter vi /etc/jupyter/jupyter_notebook_config.pyAfegiu les línies següents:
c.ServerApp.ip = '0.0.0.0' c.ServerApp.port = 8888 c.ServerApp.open_browser = False c.ServerApp.root_dir = '/srv/jupyter' c.ServerApp.notebook_dir = '/srv/jupyter/notebooks' c.serverApp.token = '' c.ServerApp.password = ''Generar una contrasenya per Jupyter:
sudo -u jupyter /opt/jupyter/env/bin/python3 -c "from jupyter_server.auth import passwd; print(passwd())"Copieu la sortida i afegiu-la a
c.ServerApp.passwordal fitxer de configuració.Creeu el fitxer de servei systemd:
sudo vi /etc/systemd/system/jupyter.serviceAfegiu el següent contingut:
[Unit] Description=Jupyter Service After=network.target [Service] Type=simple User=jupyter Group=jupyter WorkingDirectory=/srv/jupyter Environment="XDG_DATA_HOME=/srv/jupyter/.local/share" Environment="JUPYTER_CONFIG_DIR=/etc/jupyter" Environment="PATH=/opt/jupyter/env/bin" Environment="JUPYTER_RUNTIME_DIR=/etc/jupyter/runtime" ExecStart=/opt/jupyter/env/bin/jupyter-notebook --config=/etc/jupyter/jupyter_notebook_config.py Restart=failure RestartSec=10 [Install] WantedBy=multi-user.targetActiveu i inicieu el servei:
sudo systemctl daemon-reload sudo systemctl enable jupyter sudo systemctl start jupyter sudo systemctl status jupyterAccediu a Jupyter des del navegador amb
http://<IP_PUBLICA>:8888i utilitzeu la contrasenya establerta.
Podeu veure els logs de Jupyter amb:
journalctl -u jupyter -fPreguntes de reflexió
- Què passaria si canviem
Type=simpleaType=forking? Quines modificacions hauríem de fer al fitxer de servei? - Quin avantatge té separar l’usuari que executa Jupyter del teu usuari d’administració?
- Quines implicacions té mantenir un servei com Jupyter en execució contínua? (Considereu consum de recursos, seguretat, monitorització.)
💾 Fase 2: Configuració d’emmagatzematge S3
2.1 Creació de buckets S3
Crearem diferents buckets S3 per emmagatzemar els notebooks, les dades, els resultats i també per fer de backup. Per fer-ho, seguirem els passos següents:
Aneu al servei S3 a AWS i creeu els següents buckets (assegureu-vos que els noms siguin únics a nivell global):
amsa-<vostre_nom>-notebooksamsa-<vostre_nom>-dataamsa-<vostre_nom>-resultsamsa-<vostre_nom>-backup
Configurarem que únicament el vostre usuari tingui accés als buckets creats.
A la realitat, hauríeu de crear una política d’accés S3 que permeti només al vostre usuari accedir als buckets. Però ens els learner labs d’AWS Educate, això no és possible. Per tant, en aquest laboratori l’owner del bucket (el vostre usuari d’AWS Educate) serà l’únic que podrà accedir als seu continguts.
- Seleccioneu General purpose.
- ACLs desactivades.
- Activeu tots els controls de bloqueig d’accés públic.
- Desactiveu el versionat.
- Server-side encryption with Amazon S3 managed keys (SSE-S3).
- Seleccioneu Bucket Key activada.
Un cop creats els buckets, anoteu-vos els noms per utilitzar-los més endavant.
Podeu pujar documents de mostra als buckets per exemple des del vostre ordinador local, aneu a la interfície web de S3, seleccioneu el bucket i pengeu fitxers.
2.2 Configuració de l’AWS CLI a l’EC2
Instal·leu l’AWS CLI a l’instància EC2:
sudo yum install awscli -yConfigureu l’AWS CLI amb les vostres credencials d’AWS Educate:
aws configureAneu a la pestaña d’accés al Learner Lab i a la secció AWS Details -> Show AWS CLI -> copieu l’Access Key ID i el Secret Access Key i enganxeu-los a la terminal quan us ho demani. Per a la regió, utilitzeu
us-east-1o la que correspongui al vostre entorn.AWS Access Key ID [None]: <ACCESS_KEY> AWS Secret Access Key [None]: <SECRET_KEY> Default region name [None]: us-east-1 Default output format [None]: NoneComproveu que podeu accedir als buckets creats:
aws s3 lsCopiar fitxers entre l’EC2 i S3:
cd /tmp echo "Això és un fitxer de prova per a S3" > file.txt aws s3 cp file.txt s3://amsa-<vostre_nom>-notebooks/file.txtComproveu que el fitxer s’ha pujat correctament:
aws s3 ls s3://amsa-<vostre_nom>-notebooks/Consulteu la cheat sheet al final del laboratori per veure i provar més ordres de l’AWS CLI relacionades amb S3.
Preguntes de reflexió
- Quins avantatges té utilitzar S3 per emmagatzemar dades en lloc de l’emmagatzematge local de l’EC2?
- Quin és el risc de tenir les credencials d’AWS configurades directament a l’EC2 i com es podria mitigar?
- Cerca informació sobre emmagatzematge basat en blocs (EBS) i emmagatzematge d’objectes (S3). Quines són les diferències principals i en quins casos és millor utilitzar cada tipus?
2.3 Control de versions i sincronització
El servei S3 permet habilitar el control de versions als buckets per mantenir un historial de canvis dels fitxers. Això és útil per recuperar versions anteriors en cas d’errors o pèrdua de dades.
Habiliteu el control de versions al bucket de notebooks:
aws s3api put-bucket-versioning --bucket amsa-<vostre_nom>-notebooks --versioning-configuration Status=EnabledPugeu un fitxer i modifiqueu-lo diverses vegades per veure com es creen diferents versions:
echo "Versió 1" > versioned_file.txt aws s3 cp versioned_file.txt s3://amsa-<vostre_nom>-notebooks/versioned_file.txt echo "Versió 2" > versioned_file.txt aws s3 cp versioned_file.txt s3://amsa-<vostre_nom>-notebooks/versioned_file.txt echo "Versió 3" > versioned_file.txt aws s3 cp versioned_file.txt s3://amsa-<vostre_nom>-notebooks/versioned_file.txtLlisteu les versions del fitxer:
aws s3api list-object-versions --bucket amsa-<vostre_nom>-notebooks --prefix versioned_file.txtRecupereu una versió específica del fitxer:
aws s3api get-object --bucket amsa-<vostre_nom>-notebooks --key versioned_file.txt --version-id <VERSION_ID> restored_versioned_file.txt
Pregunta de reflexió
- Quins problemes pot solucionar el control de versions en un bucket S3? Pensa un exemple pràctic.
- Simula una situació on no pots o no vols utilitzar Git per gestionar els teus notebooks de Jupyter (per exemple, en un entorn cloud compartit). Com podries aprofitar el versionament de buckets S3 per mantenir versions dels teus notebooks i recuperar versions anteriors? Quins avantatges i limitacions tindria aquest enfocament comparat amb Git pel que fa a traçabilitat, col·laboració i eficiència d’emmagatzematge?
⚙️ Fase 3: Prova de S3 des de Jupyter
Inicieu sessió a Jupyter des del navegador.
Creeu un nou notebook de Python3.
Proveu el següent codi per accedir a S3 des de Jupyter
sudo -u jupyter /opt/jupyter/env/bin/pip install boto3 pandas matplotlibimport boto3 import pandas as pd import matplotlib.pyplot as plt from io import StringIO s3_client = boto3.client('s3') bucket_results = "amsa-<vostre_nom>-results" bucket_data = "amsa-<vostre_nom>-data" # Fitxer CSV d'exemple data_csv = """dia,valor 2025-10-21,10 2025-10-22,12 2025-10-23,9 2025-10-24,15 """ with open("dades.csv", "w") as f: f.write(data_csv) s3_client.upload_file("dades.csv", bucket_data, "dades.csv") # Llegir fitxer de S3 obj = s3_client.get_object(Bucket=bucket_data, Key="dades.csv") df = pd.read_csv(StringIO(obj['Body'].read().decode('utf-8'))) print(df) # Crear gràfica plt.figure(figsize=(6,4)) plt.plot(pd.to_datetime(df['dia']), df['valor'], marker='o') plt.title("Valor diari") plt.xlabel("Dia") plt.ylabel("Valor") plt.grid(True) # Guardar i pujar gràfica plt.savefig("grafica_valor.png") s3_client.upload_file("grafica_valor.png", bucket_results, "grafica_valor.png")Quan executeu veureu que jupyter no coneix les credencials d’AWS. Per solucionar-ho, necessiteu copiar les credencials al directori de l’usuari
jupyter.sudo cp -R .aws /srv/jupyter/ sudo chown -R jupyter:jupyter /srv/jupyter/.awsModifiqueu el servei per establir aquest directori:
sudo systemctl stop jupyter echo 'Environment="AWS_SHARED_CREDENTIALS_FILE=/srv/jupyter/.aws/credentials"' | sudo tee -a /etc/systemd/system/jupyter.service sudo systemctl daemon-reload sudo systemctl start jupyterTorneu a executar el notebook. Ara hauria de funcionar correctament i pujar la gràfica a S3.
Descarregueu el fitxer des de S3 i mostreu-lo a Jupyter:
from IPython.display import Image s3_client.download_file(bucket_results, "grafica_valor.png", "descargada_grafica_valor.png") Image(filename="descargada_grafica_valor.png")
🏗️ Fase 4: Sincronització automàtica amb S3
Un dels problemes d’utilitzar 2 serveis diferents com a EC2 i S3 és que les dades poden quedar desincronitzades. Per exemple, si treballem amb notebooks a Jupyter i els guardem localment, aquests canvis no es reflectiran automàticament a S3. Si pujem dades a S3 des d’un altre lloc, aquestes dades no estaran disponibles localment a l’EC2.
Una solució seria abans de treballar a Jupyter sincronitzar les dades des de S3 a l’EC2 i després de treballar, tornar a sincronitzar les dades de l’EC2 a S3. Això es pot fer manualment amb l’AWS CLI, però és millor automatitzar-ho.
#!/bin/bash
# Sincronitzar des de S3 a EC2
aws s3 sync s3://amsa-<vostre_nom>-notebooks /srv/jupyter/notebooks/
# Sincronitzar des de EC2 a S3
aws s3 sync /srv/jupyter/notebooks/ s3://amsa-<vostre_nom>-notebooksUn manera d’automatitzar-ho seria crear un timer de systemd que executi aquest script cada cert temps (per exemple, cada 5 minuts). Així, les dades es mantindrien sincronitzades sense necessitat d’intervenció manual.
Una altra opció seria configurar una Lambda que s’activi quan hi hagi canvis al bucket S3 i sincronitzi aquests canvis a l’EC2. Aquesta opció és més complexa però permet una sincronització més immediata.
Configuració de la funció Lambda
En aquest entorn AWS Educate, Lambda no pot executar ordres directament a l’EC2. En un entorn real, podríem utilitzar AWS Systems Manager (SSM) per enviar ordres a l’EC2 des de Lambda. Però com que no tenim permisos per configurar SSM al Learner Lab, no podem implementar aquest model directament.
import boto3
ec2 = boto3.client('ec2')
ssm = boto3.client('ssm')
def lambda_handler(event, context):
# ID de la instància EC2
instance_id = 'i-0fea0f11ae793a212'
# Comanda a executar a la instància EC2
command = "aws s3 sync s3://amsa-<vostre_nom>-notebooks /srv/jupyter/notebooks/"
# Executa la comanda via AWS Systems Manager
response = ssm.send_command(
InstanceIds=[instance_id],
DocumentName="AWS-RunShellScript",
Parameters={'commands': [command]}
)
return {
'statusCode': 200,
'body': 'Comanda de sincronització enviada correctament.'
}Activitats
- Implementa un timer de systemd que executi un script de sincronització cada 5 minuts.
- Implementa una funció lambda que per cada modificació al bucket S3, creei un fitxer de backup al bucket de backup. Nota: Aquesta lambda si es pot implementar al Learner Lab, utiltizeu el LABROLE per executar el codi que còpia els fitxers al bucket de backup i seleccioneu l’S3 com a trigger. Podeu fer servir python.
🚀 AWS S3 - Cheat Sheet
Copiar un document de EC2 a S3:
aws s3 cp <local-path>/file.txt s3://<bucket-name>/file.txtCopiar un document de S3 a EC2:
aws s3 cp s3://<bucket-name>/file.txt <local-path>/file.txtSincronitzar un directori local amb un bucket de S3:
aws s3 sync <local-directory> s3://<bucket-name>Sincronitzar un bucket de S3 amb un directori local:
aws s3 sync s3://<bucket-name> <local-directory>Crear una carpeta a S3:
aws s3 mb s3://<bucket-name>/folderEliminar un document de S3:
aws s3 rm s3://<bucket-name>/file.txtEliminar documents de S3 de manera recursiva:
aws s3 rm s3://<bucket-name>/ --recursiveLlistar els documents d’un bucket de S3:
aws s3 ls s3://<bucket-name>Llistar els documents d’un bucket de S3 de forma recursiva:
aws s3 ls s3://<bucket-name> --recursive
Activitats extra
- Busca informació sobre con instal·la un servidor similar a Dropbox o Drive utilitzant EC2 i S3. Aquest servidor pot utilitzant el programari Nextcloud o ownCloud. Resumeix els passos principals per fer-ho. No pots utiltizar
dockerper aquesta activitat. A més a més, comparar el cost de tenir aquest servidor amb el cost d’utilitzar serveis com Dropbox o Google Drive per a diferents quantitats d’emmagatzematge (per exemple, 100GB, 1TB, 10TB).
🧹 Finalització i Neteja
Recorda eliminar tots els recursos creats a AWS per evitar càrrecs innecessaris.
Happy SysAdmin! 🕵️♂️