RPC — Remote Procedure Call

Couche OSI : L5 — Session
Port : variable selon l’implémentation (gRPC : 443/80, portmapper : 111)

RPC (Remote Procedure Call) est un mécanisme qui permet à un programme d’appeler une fonction sur une machine distante comme si elle était locale. L’appel réseau est abstrait — le développeur écrit du code comme pour un appel de fonction classique.


Principe

Sans RPC (appel local) :
  resultat = calculer(42)     ← appel direct en mémoire

Avec RPC (appel distant) :
  resultat = calculer(42)     ← même syntaxe, mais...
                              ← sérialise l'argument (42)
                              ← envoie sur le réseau
                              ← serveur exécute calculer(42)
                              ← sérialise le résultat
                              ← renvoie sur le réseau
                              ← désérialise → resultat

Le code client ne “voit” pas le réseau — la complexité est dans le stub (code généré automatiquement).


Évolution des standards RPC

GénérationTechnologieSérialisationTransportUsage
AncienneONC RPC (Sun RPC)XDR (binaire)UDP/TCPNFS, NIS (Linux/Unix)
SOAPXML-RPC / SOAPXMLHTTPServices web enterprise (legacy)
RESTREST (pas du RPC strict)JSONHTTPAPIs web modernes
ModernegRPC (Google)ProtobufHTTP/2Microservices, Kubernetes
ModerneJSON-RPCJSONHTTP/WebSocketAPIs légères, blockchain

gRPC — la référence moderne

gRPC est l’implémentation RPC de Google, utilisée massivement dans les microservices et Kubernetes.

// Définition du service (.proto)
syntax = "proto3";
 
service Calculatrice {
  rpc Additionner (Operandes) returns (Resultat);
  rpc StreamResultats (Operandes) returns (stream Resultat);  // streaming
}
 
message Operandes {
  int32 a = 1;
  int32 b = 2;
}
 
message Resultat {
  int32 valeur = 1;
}
# Code client généré automatiquement (Python)
import grpc
import calculatrice_pb2_grpc, calculatrice_pb2
 
channel = grpc.secure_channel('api.monentreprise.fr:443', grpc.ssl_channel_credentials())
stub = calculatrice_pb2_grpc.CalculatriceStub(channel)
 
response = stub.Additionner(calculatrice_pb2.Operandes(a=3, b=5))
print(response.valeur)  # → 8

Avantages de gRPC :

  • Schéma strict (.proto) → contrat entre client et serveur
  • Protobuf → 3-10x plus compact que JSON
  • HTTP/2 → multiplexage, streaming bidirectionnel
  • Génération de code multilangage (Python, Go, Java, Rust…)
  • Intégré à Kubernetes (etcd ↔ kube-apiserver utilisent gRPC)

4 types d’appels gRPC

1. Unaire (classique)
   Client ──► Requête ──► Serveur
   Client ◄── Réponse ◄── Serveur

2. Server Streaming
   Client ──► Requête ──► Serveur
   Client ◄── Réponse 1 ◄──
   Client ◄── Réponse 2 ◄──   [le serveur streame]
   Client ◄── Réponse N ◄──

3. Client Streaming
   Client ──► Requête 1 ──► Serveur
   Client ──► Requête 2 ──►        [le client streame]
   Client ──► Requête N ──►
   Client ◄── Réponse unique ◄──

4. Bidirectionnel
   Client ◄══════════════════► Serveur  [les deux streament simultanément]

Sécurité gRPC — TLS et mTLS

gRPC utilise TLS par défaut pour chiffrer les communications. En environnement interne (microservices, Kubernetes), on configure généralement mTLS pour une authentification mutuelle.

# gRPC avec mTLS côté client (Python)
import grpc
 
# Charger les certificats
with open('ca.crt', 'rb') as f: ca_cert = f.read()
with open('client.crt', 'rb') as f: client_cert = f.read()
with open('client.key', 'rb') as f: client_key = f.read()
 
credentials = grpc.ssl_channel_credentials(
    root_certificates=ca_cert,
    private_key=client_key,
    certificate_chain=client_cert,
)
 
# Canal sécurisé par mTLS
channel = grpc.secure_channel('api.monentreprise.fr:443', credentials)
# gRPC avec mTLS côté serveur (Python)
server_credentials = grpc.ssl_server_credentials(
    private_key_certificate_chain_pairs=[(server_key, server_cert)],
    root_certificates=ca_cert,
    require_client_auth=True,   # ← force le mTLS
)
server.add_secure_port('[::]:443', server_credentials)

Pour le détail du handshake mTLS : TLS et SSL


gRPC dans Kubernetes

gRPC est le protocole de communication interne de Kubernetes entre tous les composants du control plane.

kube-apiserver ── gRPC + mTLS ──► etcd           (stockage clé-valeur)
kubelet        ── gRPC + mTLS ──► kube-apiserver  (status des pods)
kubelet        ── gRPC        ──► container runtime (via CRI)
container runtime ── gRPC     ──► containerd/CRI-O
# Inspecter les services gRPC d'etcd
grpcurl -cacert /etc/kubernetes/pki/etcd/ca.crt \
        -cert /etc/kubernetes/pki/apiserver-etcd-client.crt \
        -key  /etc/kubernetes/pki/apiserver-etcd-client.key \
        localhost:2379 list
 
# Lire une clé dans etcd via gRPC
grpcurl -cacert /etc/kubernetes/pki/etcd/ca.crt \
        -cert /etc/kubernetes/pki/apiserver-etcd-client.crt \
        -key  /etc/kubernetes/pki/apiserver-etcd-client.key \
        -d '{"key": "L3BvZHM="}' \
        localhost:2379 etcdserverpb.KV/Range
 
# Vérifier les endpoints CRI (container runtime interface)
crictl --runtime-endpoint unix:///run/containerd/containerd.sock info

Composants concernés : etcd, kubelet, container runtime

API Kubernetes et gRPC

L’API Kubernetes (kube-apiserver) expose deux interfaces :

  • REST/HTTP → pour kubectl, les opérateurs, les outils externes
  • gRPC/Protobuf → pour les communications internes haute performance
# kubectl peut utiliser le format protobuf (plus rapide que JSON)
kubectl get pods -o json     # ← JSON par défaut (lisible)
# En interne kubectl peut négocier application/vnd.kubernetes.protobuf

En relation avec