Kubernetes
OpenVPN
VPN
Kubernetes Pod
Container Networking

OpenVPN Client in Kubernetes Pod

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Running an OpenVPN client inside a Kubernetes pod is a workable pattern when an application must reach a private network through a VPN tunnel. The usual design is a sidecar container that establishes the tunnel while the application container in the same pod uses the shared pod network namespace.

Why the Sidecar Pattern Works

Containers in the same pod share one network namespace. That means if the OpenVPN sidecar adds routes or changes default routing, the application container can use those routes without running OpenVPN itself.

This makes the sidecar model attractive when:

  • only one workload needs the VPN
  • the tunnel should be isolated to one pod
  • the application should remain unchanged

A dedicated pod that runs only the VPN client is also possible, but the sidecar pattern is often the most direct fit.

Store VPN Material in a Secret

The .ovpn file, certificates, keys, and credentials should normally be stored in a Kubernetes Secret, not a ConfigMap.

bash
1kubectl create secret generic openvpn-client \
2  --from-file=client.ovpn \
3  --from-file=ca.crt \
4  --from-file=client.crt \
5  --from-file=client.key

That lets the pod mount the VPN material securely as files.

Example Sidecar Pod

Here is a minimal pod example with an OpenVPN sidecar and an application container:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: app-with-vpn
5spec:
6  containers:
7    - name: openvpn
8      image: dperson/openvpn-client
9      securityContext:
10        capabilities:
11          add:
12            - NET_ADMIN
13      volumeMounts:
14        - name: vpn-config
15          mountPath: /vpn
16        - name: tun-device
17          mountPath: /dev/net/tun
18    - name: app
19      image: curlimages/curl
20      command: ["sleep", "infinity"]
21  volumes:
22    - name: vpn-config
23      secret:
24        secretName: openvpn-client
25    - name: tun-device
26      hostPath:
27        path: /dev/net/tun
28        type: CharDevice

The image and command may vary, but the important ingredients are the OpenVPN configuration, the NET_ADMIN capability, and access to the TUN device.

Readiness and Routing Checks

A VPN container being alive is not the same as the VPN tunnel being ready. After startup, verify the tunnel from inside the pod before letting the application depend on it.

Typical checks include:

bash
ip route
ip addr

And from the application container:

bash
curl http://internal-service.example.local

In production, readiness should usually depend on the tunnel being established, not just on the OpenVPN process running.

Security and Cluster Policy Constraints

This pattern is operationally useful, but it is not lightweight. Many clusters restrict:

  • 'NET_ADMIN'
  • 'hostPath mounts'
  • access to /dev/net/tun
  • privileged or near-privileged networking changes

That means the YAML may be valid and still be rejected by admission policies or Pod Security restrictions. If the cluster forbids this design, the fix is often architectural rather than syntactic.

Think About DNS and Egress Behavior

A VPN tunnel changes more than raw connectivity. It can affect DNS, default routes, and outbound policy. If the application uses cluster DNS, private DNS through the tunnel, or both, you need to know which resolver path the pod is actually using after the tunnel comes up.

This is why OpenVPN sidecars should be treated as part of the pod's networking design, not as a magic extra container.

Common Pitfalls

Starting an OpenVPN container without the TUN device or required capabilities causes the container to run without a working tunnel.

Putting certificates or sensitive .ovpn material in a ConfigMap instead of a Secret weakens configuration hygiene.

Letting the application start normal traffic before the tunnel is ready leads to intermittent or misleading connectivity failures.

Ignoring cluster security policy can waste time when the real reason the pod fails is that NET_ADMIN or hostPath is forbidden.

Treating DNS and routing as unchanged after the VPN starts often produces difficult-to-debug reachability issues.

Summary

  • An OpenVPN client can run inside a Kubernetes pod, often as a sidecar next to the application.
  • Put VPN configuration and keys in a Secret.
  • The OpenVPN container usually needs NET_ADMIN and access to /dev/net/tun.
  • Containers in the same pod share a network namespace, which is what makes the sidecar approach useful.
  • Readiness, routing, DNS, and cluster security policy are the main operational challenges.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.