Wireguard
Run a Pod with WireGuard Interface
This guide explains how to securely attach a WireGuard interface to a Pod using a Kubernetes Secret for key management.
Why Use WireGuard?
WireGuard creates encrypted tunnels between the Pod and a node outside the Kubernetes cluster, enabling secure communication across networks (e.g., cross-cluster connectivity, bypassing NAT, or encrypting traffic).
Step 1: Create a Secret for WireGuard Private Key
Create the file config.json
with the following content:
{
"address": "1.2.3.4/32",
"privateKey": "AAev16ZVYhmCQliIYKXMje1zObRp6TmET0KiUx7MJXc=",
"peers": [
{
"endpoint": "5.6.7.8:51820",
"publicKey": "+gXCSfkib2xFMeebKXIYBVZxV/Vh2mbi1dJeHCCjQmg=",
"allowedIPs": [
"9.10.11.12/24"
],
"persistentKeepalive": "25s"
}
]
}
Replace all three IP adresses and both keys with real content.
Current limitations
- Even if the endpoint supports multiple client addresses, current implementation in Kubernetes supports only a single address.
- The name of the file must be strictly
config.json
. - The
address
andallowedIPs
must not be from the same network. E.g.,"address": "10.1.2.3/32"
and"allowedIPs": ["10.1.2.0/24"]
will not work.
Create the secret:
kubectl create secret generic wireguard-config --from-file ./config.json
Step 2: Create a Pod with WireGuard Interface
Deploy a Pod with the WireGuard interface, it will be net1
(attached via the k8s.v1.cni.cncf.io/networks
annotation).
apiVersion: v1
kind: Pod
metadata:
name: wireguard-pod
annotations:
k8s.v1.cni.cncf.io/networks: default/wgnet # Attach WireGuard interface `net1`
wgcni.schu.io/configsecret: wireguard-config # references the created secret
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: main
image: your-application-image
command:
- as-needed
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
Verification
-
Check if
net1
interface exists (requiresip
command in the Pod):kubectl exec wireguard-pod -n [namespace] -- ip a show net1
Expect output showing the WireGuard interface with an IP.
-
Test connectivity (requires
ping
command in the Pod):kubectl exec wireguard-pod -n [namespace] -- ping <PEER_IP>
Replace
<PEER_IP>
with the peer’s WireGuard IP from theconfig.json
.
Caveats
The WG CNI currently supports assigning only a single IP address, which means it can configure either an IPv4 or an IPv6 address—but not both simultaneously. This poses a limitation when targeting dual-stack endpoints such as:
$ host kubas-pub.cloud.trusted.e-infra.cz
kubas-pub.cloud.trusted.e-infra.cz has address 10.16.48.119
kubas-pub.cloud.trusted.e-infra.cz has IPv6 address 2001:718:801:42bf:8:4:0:1
In such scenarios, a Pod using WireGuard may experience intermittent connectivity. This happens because DNS resolution may return either an IPv4 or IPv6 address, and only one of these will work in the WireGuard configuration. As a result, the connection may alternate between working and timing out, depending on which address family is used.
Recommendation
To avoid this issue, we recommend configuring the Pod for single-stack networking. Choose either IPv4 or IPv6 and consistently use that stack throughout:
- Set both the
address
andallowedIPs
fields to match the chosen IP family in the WireGUard configuration. - Ensure that the connection to the remote WireGuard peer uses the same stack.
- Align the stack used for communication with the address family specified in the WireGuard configuration.
Example: IPv6-Only Reverse Proxy with NGINX
Below is an example configuration for NGINX where the reverse proxy connects to an IPv6 address directly, bypassing DNS resolution. The Host
header is explicitly set to ensure proper virtual host routing:
location / {
proxy_pass https://[2001:718:801:42bf:8:4:0:1];
proxy_buffering off;
proxy_set_header Host vllm.cloud.trusted.e-infra.cz;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Multiple Pods
By design, a single WireGuard configuration cannot be used simultaneously across multiple Pods or devices. Each Pod requires a unique WireGuard configuration that must not be shared or reused elsewhere.
This limitation arises because WireGuard effectively establishes a Layer 2-like network among peers. If multiple clients use the same IP address within this network, it leads to IP address collisions, resulting in unstable behavior.
Symptom
A common symptom of this issue is connectivity flapping in regular intervals—typically every 10 seconds. For example, the connection may be stable for 10 seconds, then drop for the next 10 seconds, repeating in a loop.
Last updated on