Initial commit of the k8-mini-app project with backend, frontend, worker, and RabbitMQ integration. Added Dockerfiles, Kubernetes manifests, and necessary configurations for deployment.
This commit is contained in:
parent
4d4868dd06
commit
fe9c240033
5
backend/Dockerfile
Normal file
5
backend/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN npm install
|
||||||
|
CMD ["node", "index.js"]
|
||||||
145
backend/index.js
Normal file
145
backend/index.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const amqp = require('amqplib');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Variabili globali
|
||||||
|
let channel = null;
|
||||||
|
let connection = null;
|
||||||
|
|
||||||
|
// Funzione per connettersi a RabbitMQ
|
||||||
|
async function connectRabbitMQ() {
|
||||||
|
try {
|
||||||
|
console.log('Tentativo di connessione a RabbitMQ...');
|
||||||
|
connection = await amqp.connect('amqp://rabbitmq');
|
||||||
|
console.log('Connessione a RabbitMQ stabilita');
|
||||||
|
|
||||||
|
// Gestione della chiusura della connessione
|
||||||
|
connection.on('close', () => {
|
||||||
|
console.warn('Connessione a RabbitMQ chiusa, tentativo di riconnessione tra 5 secondi...');
|
||||||
|
setTimeout(connectRabbitMQ, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gestione errori
|
||||||
|
connection.on('error', (err) => {
|
||||||
|
console.error('Errore nella connessione a RabbitMQ:', err);
|
||||||
|
if (!connection.closed) connection.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Crea canale
|
||||||
|
channel = await connection.createChannel();
|
||||||
|
console.log('Canale creato');
|
||||||
|
|
||||||
|
// NUOVO: Tenta di cancellare tutti i consumatori esistenti
|
||||||
|
try {
|
||||||
|
await channel.cancel('');
|
||||||
|
console.log('Tentativo di cancellazione consumatori esistenti');
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Nessun consumatore da cancellare o errore:', err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configura la coda con durabilità (nome modificato)
|
||||||
|
await channel.assertQueue('messages_v2', {
|
||||||
|
durable: true, // La coda sopravvive al riavvio del broker
|
||||||
|
autoDelete: false // La coda non viene eliminata quando non ha più consumatori
|
||||||
|
});
|
||||||
|
console.log('Coda "messages_v2" verificata/creata');
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nella connessione a RabbitMQ:', error);
|
||||||
|
setTimeout(connectRabbitMQ, 5000);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inizializza il server dopo la connessione a RabbitMQ
|
||||||
|
async function startServer() {
|
||||||
|
try {
|
||||||
|
await connectRabbitMQ();
|
||||||
|
|
||||||
|
// Endpoint per inviare messaggi alla coda
|
||||||
|
app.post('/api/enqueue', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const msg = JSON.stringify(req.body);
|
||||||
|
console.log('Invio messaggio alla coda:', msg);
|
||||||
|
|
||||||
|
// Invia il messaggio con persistenza (nome coda modificato)
|
||||||
|
channel.sendToQueue('messages_v2', Buffer.from(msg), {
|
||||||
|
persistent: true // Il messaggio è persistente
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Messaggio inviato con successo');
|
||||||
|
res.json({ status: 'success', message: 'Messaggio inviato alla coda', data: req.body });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nell\'invio del messaggio:', error);
|
||||||
|
res.status(500).json({ status: 'error', message: 'Errore nell\'invio del messaggio' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Endpoint per recuperare messaggi dalla coda
|
||||||
|
app.get('/api/messages', async (req, res) => {
|
||||||
|
try {
|
||||||
|
console.log('Tentativo di recupero messaggio con GET...');
|
||||||
|
|
||||||
|
// Usa il metodo get invece di consume (nome coda modificato)
|
||||||
|
const msg = await channel.get('messages_v2', { noAck: false });
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
console.log('Messaggio trovato:', msg.content.toString());
|
||||||
|
// Conferma esplicita che il messaggio è stato ricevuto
|
||||||
|
channel.ack(msg);
|
||||||
|
const content = JSON.parse(msg.content.toString());
|
||||||
|
res.json({ status: 'success', message: content });
|
||||||
|
} else {
|
||||||
|
console.log('Nessun messaggio trovato nella coda con GET');
|
||||||
|
res.json({ status: 'empty', message: 'Nessun messaggio nella coda' });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nel recupero del messaggio:', error);
|
||||||
|
res.status(500).json({ status: 'error', message: `Errore nel recupero: ${error.message}` });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Endpoint di debug per verificare lo stato della coda
|
||||||
|
app.get('/api/queue-info', async (req, res) => {
|
||||||
|
try {
|
||||||
|
// Nome coda modificato
|
||||||
|
const queueInfo = await channel.assertQueue('messages_v2', { passive: true });
|
||||||
|
console.log('Informazioni coda:', queueInfo);
|
||||||
|
res.json({
|
||||||
|
status: 'success',
|
||||||
|
queue: 'messages_v2',
|
||||||
|
messageCount: queueInfo.messageCount,
|
||||||
|
consumerCount: queueInfo.consumerCount,
|
||||||
|
properties: queueInfo
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nel recupero info coda:', error);
|
||||||
|
res.status(500).json({ status: 'error', message: 'Errore nel recupero info coda' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Avvia il server
|
||||||
|
app.listen(3000, () => console.log('Backend in ascolto sulla porta 3000'));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nell\'avvio del server:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avvia il server
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
// Gestione della chiusura pulita
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
try {
|
||||||
|
if (channel) await channel.close();
|
||||||
|
if (connection) await connection.close();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nella chiusura della connessione:', error);
|
||||||
|
} finally {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
9
backend/package.json
Normal file
9
backend/package.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"amqplib": "^0.10.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
43
ci-build.sh
Executable file
43
ci-build.sh
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script per buildare e pushare le immagini al registry locale
|
||||||
|
|
||||||
|
# Variabili
|
||||||
|
REGISTRY="localhost:5000"
|
||||||
|
TAG=$(date +%Y%m%d-%H%M%S) # Usa timestamp come tag
|
||||||
|
|
||||||
|
# Verifica che il registry locale sia in esecuzione
|
||||||
|
if ! curl -s http://localhost:5000/v2/ > /dev/null; then
|
||||||
|
echo "❌ Registry localhost:5000 non raggiungibile. Avvialo con: docker run -d -p 5000:5000 registry:2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build e push delle immagini
|
||||||
|
echo "🔨 Building backend image..."
|
||||||
|
docker build -t $REGISTRY/backend:$TAG ./backend
|
||||||
|
docker push $REGISTRY/backend:$TAG
|
||||||
|
|
||||||
|
echo "🔨 Building frontend image..."
|
||||||
|
docker build -t $REGISTRY/frontend:$TAG ./frontend
|
||||||
|
docker push $REGISTRY/frontend:$TAG
|
||||||
|
|
||||||
|
echo "🔨 Building worker image..."
|
||||||
|
docker build -t $REGISTRY/worker:$TAG ./worker
|
||||||
|
docker push $REGISTRY/worker:$TAG
|
||||||
|
|
||||||
|
# Aggiorna i file YAML di Kubernetes
|
||||||
|
echo "📝 Updating Kubernetes manifests..."
|
||||||
|
sed -i "s|localhost:5000/backend:latest|$REGISTRY/backend:$TAG|g" k8s/backend.yaml
|
||||||
|
sed -i "s|localhost:5000/frontend:latest|$REGISTRY/frontend:$TAG|g" k8s/frontend.yaml
|
||||||
|
sed -i "s|localhost:5000/worker:latest|$REGISTRY/worker:$TAG|g" k8s/worker.yaml
|
||||||
|
|
||||||
|
# Commit e push a Gitea se necessario
|
||||||
|
if [ "$1" == "--push" ]; then
|
||||||
|
echo "🚀 Pushing changes to Gitea..."
|
||||||
|
git add k8s/
|
||||||
|
git commit -m "Update images to tag $TAG"
|
||||||
|
git push
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Build completato. Immagini taggate come: $TAG"
|
||||||
|
echo "📋 Per applicare le modifiche manualmente: kubectl apply -f k8s/"
|
||||||
|
echo "🔄 Per sincronizzare con Argo CD: argocd app sync k8-mini-app"
|
||||||
26
docker-compose.yml
Normal file
26
docker-compose.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq:3-management
|
||||||
|
ports:
|
||||||
|
- "15672:15672"
|
||||||
|
- "5672:5672"
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: ./backend
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
depends_on:
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build: ./frontend
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
worker:
|
||||||
|
build: ./worker
|
||||||
|
depends_on:
|
||||||
|
- rabbitmq
|
||||||
5
frontend/Dockerfile
Normal file
5
frontend/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Dockerfile - Frontend
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY ./index.html /usr/share/nginx/html/index.html
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
105
frontend/index.html
Normal file
105
frontend/index.html
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Frontend</title>
|
||||||
|
<style>
|
||||||
|
#messageDisplay {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
min-height: 50px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Mini Frontend</h1>
|
||||||
|
<button onclick="sendMessage()">Invia Messaggio</button>
|
||||||
|
<button onclick="retrieveMessage()">Recupera Messaggio</button>
|
||||||
|
<button onclick="checkQueueInfo()">Verifica Stato Coda</button>
|
||||||
|
|
||||||
|
<div id="messageDisplay">
|
||||||
|
<p>I messaggi recuperati appariranno qui...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
async function sendMessage() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/enqueue', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ message: 'Hello from frontend!' })
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
alert('Messaggio inviato alla coda!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nell\'invio del messaggio:', error);
|
||||||
|
alert('Errore nell\'invio del messaggio!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retrieveMessage() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/messages');
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
const displayDiv = document.getElementById('messageDisplay');
|
||||||
|
|
||||||
|
if (data.status === 'success') {
|
||||||
|
displayDiv.innerHTML = `
|
||||||
|
<h3>Messaggio recuperato:</h3>
|
||||||
|
<pre>${JSON.stringify(data.message, null, 2)}</pre>
|
||||||
|
`;
|
||||||
|
} else if (data.status === 'empty') {
|
||||||
|
displayDiv.innerHTML = `<p>Nessun messaggio disponibile nella coda.</p>`;
|
||||||
|
} else {
|
||||||
|
displayDiv.innerHTML = `<p>Errore: ${data.message}</p>`;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nel recupero del messaggio:', error);
|
||||||
|
document.getElementById('messageDisplay').innerHTML =
|
||||||
|
`<p>Errore nella connessione al backend: ${error.message}</p>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkQueueInfo() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/queue-info');
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
const displayDiv = document.getElementById('messageDisplay');
|
||||||
|
|
||||||
|
if (data.status === 'success') {
|
||||||
|
displayDiv.innerHTML = `
|
||||||
|
<h3>Informazioni Coda:</h3>
|
||||||
|
<p>Nome: ${data.queue}</p>
|
||||||
|
<p>Messaggi in coda: ${data.messageCount}</p>
|
||||||
|
<p>Consumatori attivi: ${data.consumerCount}</p>
|
||||||
|
<pre>Proprietà complete: ${JSON.stringify(data.properties, null, 2)}</pre>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
displayDiv.innerHTML = `<p>Errore: ${data.message}</p>`;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore nel recupero info coda:', error);
|
||||||
|
document.getElementById('messageDisplay').innerHTML =
|
||||||
|
`<p>Errore nella connessione al backend: ${error.message}</p>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
21
k8s/argocd/application.yaml
Normal file
21
k8s/argocd/application.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: k8-mini-app
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://git.algios.dev/francescoalbano/k8-mini-app.git
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: k8s
|
||||||
|
# Se Gitea richiede autenticazione, aggiungi:
|
||||||
|
# username: git
|
||||||
|
# password: <vuoto, verrà usato un segreto>
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: default
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
34
k8s/backend.yaml
Normal file
34
k8s/backend.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: backend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: backend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: backend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: backend
|
||||||
|
image: localhost:5000/backend:20250523-010002
|
||||||
|
ports:
|
||||||
|
- containerPort: 3000
|
||||||
|
tolerations:
|
||||||
|
- key: "node.kubernetes.io/disk-pressure"
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: backend
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: backend
|
||||||
|
ports:
|
||||||
|
- port: 3000
|
||||||
|
targetPort: 3000
|
||||||
38
k8s/frontend.yaml
Normal file
38
k8s/frontend.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: frontend
|
||||||
|
image: localhost:5000/frontend:20250523-010002
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
tolerations:
|
||||||
|
- key: "node.kubernetes.io/disk-pressure"
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
tolerations:
|
||||||
|
- key: "node.kubernetes.io/disk-pressure"
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: frontend
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
40
k8s/ingress.yaml
Normal file
40
k8s/ingress.yaml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: app-ingress
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: local.test
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /api
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
- http: # Regola senza host per accesso via IP
|
||||||
|
paths:
|
||||||
|
- path: /api
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: backend
|
||||||
|
port:
|
||||||
|
number: 3000
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
37
k8s/rabbitmq.yaml
Normal file
37
k8s/rabbitmq.yaml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: rabbitmq
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: rabbitmq
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: rabbitmq
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: rabbitmq
|
||||||
|
image: rabbitmq:3-management
|
||||||
|
ports:
|
||||||
|
- containerPort: 5672
|
||||||
|
- containerPort: 15672
|
||||||
|
tolerations:
|
||||||
|
- key: "node.kubernetes.io/disk-pressure"
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: rabbitmq
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 5672
|
||||||
|
name: amqp
|
||||||
|
- port: 15672
|
||||||
|
name: management
|
||||||
|
selector:
|
||||||
|
app: rabbitmq
|
||||||
21
k8s/worker.yaml
Normal file
21
k8s/worker.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: worker
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: worker
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: worker
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: worker
|
||||||
|
image: localhost:5000/worker:20250523-010340
|
||||||
|
tolerations:
|
||||||
|
- key: "node.kubernetes.io/disk-pressure"
|
||||||
|
operator: "Exists"
|
||||||
|
effect: "NoSchedule"
|
||||||
5
worker/Dockerfile
Normal file
5
worker/Dockerfile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN npm install
|
||||||
|
CMD ["node", "worker.js"]
|
||||||
8
worker/package.json
Normal file
8
worker/package.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "worker",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "worker.js",
|
||||||
|
"dependencies": {
|
||||||
|
"amqplib": "^0.10.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
worker/worker.js
Normal file
14
worker/worker.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const amqp = require('amqplib');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const conn = await amqp.connect('amqp://rabbitmq');
|
||||||
|
const ch = await conn.createChannel();
|
||||||
|
await ch.assertQueue('messages');
|
||||||
|
console.log('Worker started, waiting for messages...');
|
||||||
|
ch.consume('messages', (msg) => {
|
||||||
|
if (msg !== null) {
|
||||||
|
console.log('Received:', msg.content.toString());
|
||||||
|
ch.ack(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
Loading…
x
Reference in New Issue
Block a user