Réseau
Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.
Le réseau d'une App est fermé par défaut : un service n'accepte que les connexions sur ses
ports déclarés, venant des autres services de la même App (et d'Internet s'il est exposé),
et ne sort nulle part sauf vers les services de votre tenant. Deux champs ouvrent des portes :
allowFrom (une autre App de votre tenant entre) et egress: [internet] (le service sort).
Prérequis
- Une App en cours d'écriture (Depuis docker compose).
Étapes
1. Ouvrir ce qui doit l'être
apiVersion: deploy.stackngo.io/v1alpha1
kind: App
metadata:
name: shop
spec:
services:
api:
image: registry.gitlab.com/acme/shop-api:1.4.2
ports: ["8080"]
ingress: { port: 8080 }
egress: [internet] # appelle un prestataire de paiement
dependsOn: [db]
db:
image: postgres:17
user: "999"
ports: ["5432"]
allowFrom: [reporting] # l'App « reporting » du tenant peut lire la base
volumes:
- { path: /var/lib/postgresql/data, size: 10Gi }
En ligne de commande : sng app create … --egress-internet --allow-from reporting,
sng app patch shop --service api --egress-internet=false.
2. Appliquer et tester
sng apply shop.yml
sng app logs shop --service api --since 5m
Depuis api, db:5432 répond ; https://api.paiement.example aussi. Depuis db, une
requête vers Internet est bloquée.
Vérification
Un petit job de sonde dit ce qui passe :
apiVersion: deploy.stackngo.io/v1alpha1
kind: App
metadata:
name: netcheck
spec:
services:
closed:
kind: job
image: curlimages/curl:8.11.1
user: "100"
size: xxxs
command: ["sh", "-c", "for u in https://example.com http://169.254.169.254/; do if curl -s -m 5 -o /dev/null $u; then echo \"OK $u\"; else echo \"BLOCKED $u\"; fi; done"]
open:
kind: job
image: curlimages/curl:8.11.1
user: "100"
size: xxxs
egress: [internet]
command: ["sh", "-c", "for u in https://example.com http://169.254.169.254/; do if curl -s -m 5 -o /dev/null $u; then echo \"OK $u\"; else echo \"BLOCKED $u\"; fi; done"]
sng apply netcheck.yml
sng app logs netcheck
[netcheck-closed-3f9a1c2e-x7k2q] BLOCKED https://example.com
[netcheck-closed-3f9a1c2e-x7k2q] BLOCKED http://169.254.169.254/
[netcheck-open-8b1d7e40-p9s4m] OK https://example.com
[netcheck-open-8b1d7e40-p9s4m] BLOCKED http://169.254.169.254/
Qui peut joindre quoi
Entrée vers un service
| Depuis | Vers | Autorisé ? |
|---|---|---|
| un autre service de la même App | un port déclaré dans ports | oui |
| un autre service de la même App | un port non déclaré | non |
| une autre App de votre tenant | un port déclaré | oui si l'App est dans allowFrom |
| Internet (en HTTPS) | le port de ingress seulement | oui si ingress |
| un autre tenant | quoi que ce soit | jamais |
| n'importe qui | un service sans ports | non : il n'accepte rien |
Les règles sont en place avant que le service ne démarre : il n'y a pas de fenêtre où un service serait ouvert.
Sortie d'un service
| Vers | Autorisé ? |
|---|---|
| les services de votre tenant (toutes Apps) | oui, mais le service cible doit accepter (voir ci-dessus) |
| le DNS de la plateforme | oui |
| Internet | seulement avec egress: [internet] |
les adresses privées (autres tenants, réseaux privés, 169.254.169.254) | jamais, même avec egress: [internet] |
egress n'accepte que la valeur internet ; il n'y a pas d'ouverture par adresse ou par port.
Nommer les services entre eux
Un service db de l'App shop qui déclare ports: ["5432"] est joignable par les autres
services de l'App en db:5432, exactement comme en compose. Avec la forme "5433:5432",
c'est db:5433 qui est exposé, vers le port 5432 du conteneur.
Depuis une autre App du tenant (autorisée par allowFrom), utilisez le même nom : db:5432.
Évitez de donner le même nom de service à deux Apps d'un tenant : le second est refusé
(NameConflict), car un nom de service est unique dans tout le tenant.
allowFrom
- Liste de noms d'Apps de votre tenant (10 au plus), pas de services.
- Ouvre tous les
portsdu service aux services de ces Apps. Pas de granularité par port. - Exige au moins un port déclaré, sinon le manifeste est invalide (
allowFrom : le service n'a aucun port à ouvrir). sng app patch shop --service db --allow-from ''retire toutes les autorisations.
dependsOn et réseau
dependsOn ordonne la création des services ; il n'ouvre aucune porte. Un service peut
dépendre d'un autre sans pouvoir le joindre (si celui-ci n'a pas de ports), et réciproquement.
Pour qu'api attende db et lui parle : dependsOn: [db] sur api, ports: ["5432"] sur db.
Si ça ne marche pas
| Ce que vous voyez | Cause | Correction |
|---|---|---|
connection refused ou délai dépassé vers db:5432 | Le port n'est pas dans les ports de db, ou l'appelant est dans une autre App absente de allowFrom | Déclarer le port, ou ajouter l'App à allowFrom |
| Un appel vers une API externe expire | Le service n'a pas egress: [internet] | L'ajouter, puis sng apply |
NameConflict sur un service | Une autre App du tenant a un service du même nom | Renommer l'un des deux services |
Manifeste refusé : allowFrom : le service n'a aucun port à ouvrir | allowFrom sur un service sans ports | Déclarer au moins un port |
Pour aller plus loin
- Ces règles s'appliquent à chaque service et ne peuvent pas être désactivées.
- Vos conteneurs ne reçoivent aucune variable décrivant les autres services : passez les
adresses par
env(DB_HOST: db). - La résolution des noms publics est toujours permise : aucune ouverture supplémentaire n'est
nécessaire pour résoudre un nom avant de le joindre avec
egress: [internet].