FEATURE: improve documentation for VPN-only use case
This commit is contained in:
parent
63987713dd
commit
5a45c1f85b
@ -130,6 +130,9 @@ sudo wg setconf wg0 peer.ini
|
|||||||
|
|
||||||
[See the VPN docs for more details](./docs/vpn.md).
|
[See the VPN docs for more details](./docs/vpn.md).
|
||||||
|
|
||||||
|
In case you want to only run Kilo as VPN server, [see the VPN-only walkthrough](./docs/vpn-only.md)
|
||||||
|
for details.
|
||||||
|
|
||||||
## Multi-cluster Services
|
## Multi-cluster Services
|
||||||
|
|
||||||
A logical application of Kilo's VPN is to connect two different Kubernetes clusters.
|
A logical application of Kilo's VPN is to connect two different Kubernetes clusters.
|
||||||
|
125
docs/vpn-only.md
Normal file
125
docs/vpn-only.md
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Kilo as VPN Server to connect into the cluster
|
||||||
|
|
||||||
|
Use Case: Connect into the Kubernetes Cluster via WireGuard VPN, so that a WireGuard client has direct
|
||||||
|
access to Pods and Services.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Ensure Wireguard is installed on the host system
|
||||||
|
- UDP port 51820 must be externally reachable to the cluster
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
- For this case, it is enough to deploy a single instance of Kilo into the cluster. Kilo should be
|
||||||
|
**pinned** to a single Node, because the WireGuard private key is host-specific.
|
||||||
|
- CNI has to be disabled, because you are keeping the existing CNI plugin.
|
||||||
|
- You can use in-cluster Kubernetes configuration, and do not need to mount the host Kubernetes config.
|
||||||
|
(The latter is only needed to extract in the CNI case to detect the outside-visible Hostname for
|
||||||
|
each node).
|
||||||
|
- We only tested this with Flannel or Flannel+Calico (=Canal) so far.
|
||||||
|
|
||||||
|
You can still access all Kubernetes Services and Pods, no matter where they run, in this configuration.
|
||||||
|
|
||||||
|
The full configuration can be found at [manifests/kilo-vpn-only-example.yaml](../manifests/kilo-vpn-only-example.yaml).
|
||||||
|
|
||||||
|
**Make sure to adjust the `nodeSelector` in the `DaemonSet`**.
|
||||||
|
|
||||||
|
## Registering a new VPN client
|
||||||
|
|
||||||
|
1. Create a new WireGuard keypair on the VPN Client. Remember the public key.
|
||||||
|
|
||||||
|
2. For the client, create a Kubernetes `peer` resource:
|
||||||
|
|
||||||
|
- pick a new, unique, IP address for the client from the `10.5.0.*` IP range.
|
||||||
|
Based on this IP, we can lateron decide what the client can access.
|
||||||
|
|
||||||
|
- add the public key from the VPN client (see step 1) to the `peer` resource.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: kilo.squat.ai/v1alpha1
|
||||||
|
kind: Peer
|
||||||
|
metadata:
|
||||||
|
name: squat
|
||||||
|
spec:
|
||||||
|
allowedIPs:
|
||||||
|
# desired IP address of the client's interface.
|
||||||
|
- 10.5.0.1/32
|
||||||
|
# Public Key of the client
|
||||||
|
publicKey: A......................................=
|
||||||
|
persistentKeepalive: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Configure your local VPN client in the following way:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
PrivateKey = (already filled)
|
||||||
|
# IP address of VPN client; from the "peer" kubernetes resource as configured above
|
||||||
|
Address = 10.5.0.1/32
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
# from within the "kilo" Pod, run "wg" - that outputs the persistent, public key for
|
||||||
|
# the server
|
||||||
|
PublicKey = B......................................=
|
||||||
|
|
||||||
|
# Add the Pod and Service networks, e.g. if 10.42.* is the Pod Network; and 10.43.*
|
||||||
|
# is the Service network:
|
||||||
|
AllowedIPs = 10.42.0.0/16, 10.43.0.0/16
|
||||||
|
|
||||||
|
# public IP address of the Kilo node + Wireguard/Kilo UDP Port
|
||||||
|
Endpoint = 138.201.76.122:51820
|
||||||
|
|
||||||
|
# the server is always reachable, so we do not need PersistentKeepalive in
|
||||||
|
# this direction.
|
||||||
|
PersistentKeepalive = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optional: Using Calico / Canal to restrict the NetworkPolicy in the Cluster
|
||||||
|
|
||||||
|
If you are running Calico + Flannel (=Canal), you can use `HostEndpoint` combined
|
||||||
|
with a `GlobalNetworkPolicy` to restrict what each VPN client can access in the cluster:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: crd.projectcalico.org/v1
|
||||||
|
kind: HostEndpoint
|
||||||
|
metadata:
|
||||||
|
name: wireguard-kilo
|
||||||
|
labels:
|
||||||
|
interface: wireguard-kilo
|
||||||
|
spec:
|
||||||
|
node: THE_KILO_NODE_HERE
|
||||||
|
expectedIPs:
|
||||||
|
# in the "kilo" container, we run "ip address show kilo0",
|
||||||
|
# and this is the IP of the "inner" side of the wireguard interface.
|
||||||
|
# thus, we need to match on this IP here.
|
||||||
|
- 10.4.0.1
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: crd.projectcalico.org/v1
|
||||||
|
kind: GlobalNetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: wireguard-kilo
|
||||||
|
spec:
|
||||||
|
selector: interface == 'wireguard-kilo'
|
||||||
|
# we want to apply the policy as it enters our cluster (exits the wireguard
|
||||||
|
# interface). On the application pods, we could not apply it anymore, because
|
||||||
|
# the IP address gets rewritten to the Flannel interface IP.
|
||||||
|
applyOnForward: true
|
||||||
|
types:
|
||||||
|
- Ingress
|
||||||
|
ingress:
|
||||||
|
- action: Allow
|
||||||
|
source:
|
||||||
|
nets:
|
||||||
|
- 10.5.0.1/32 # a certain VPN client ...
|
||||||
|
destination:
|
||||||
|
# ... can access a certain app
|
||||||
|
namespaceSelector: network-policy-namespace == "cattle-prometheus"
|
||||||
|
selector: app == "grafana"
|
||||||
|
|
||||||
|
# anything which is not whitelisted explicitly is forbidden
|
||||||
|
- action: Deny
|
||||||
|
```
|
22
docs/vpn.md
22
docs/vpn.md
@ -60,6 +60,9 @@ for ip in $(kgctl showconf peer $PEER | grep AllowedIPs | cut -f 3- -d ' ' | tr
|
|||||||
done
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When using the official Mac OS WireGuard client, the routes from `AllowedIPs` will be automatically
|
||||||
|
routed to the VPN tunnel. You do not need to manually register routes there.
|
||||||
|
|
||||||
Once the routes are in place, the connection to the cluster can be tested.
|
Once the routes are in place, the connection to the cluster can be tested.
|
||||||
For example, try connecting to the API server:
|
For example, try connecting to the API server:
|
||||||
|
|
||||||
@ -105,3 +108,22 @@ EOF
|
|||||||
```
|
```
|
||||||
|
|
||||||
[See the multi-cluster services docs for more details on connecting clusters to external services](./multi-cluster-services.md).
|
[See the multi-cluster services docs for more details on connecting clusters to external services](./multi-cluster-services.md).
|
||||||
|
|
||||||
|
## Accessing Service IPs via the VPN
|
||||||
|
|
||||||
|
Service IPs are usually assigned to a separate IP address range compared to the Pod IPs. Kilo will only
|
||||||
|
output the Pod IP range in the WireGuard Client configuration when running `kgctl showconf peer`. This is
|
||||||
|
because Service IPs can be sent to any Kubernetes node, and then routing happens internally towards
|
||||||
|
the pods.
|
||||||
|
|
||||||
|
To access service IPs via the VPN client, simply add them in your WireGuard client configuration
|
||||||
|
to the `AllowedIPs` list, f.e. like `10.43.0.0/15` (if your services are allocated from the `10.43` IP
|
||||||
|
range).
|
||||||
|
|
||||||
|
## Using Kilo only as VPN server
|
||||||
|
|
||||||
|
You can also use Kilo only for accessing your cluster pods and services via VPN client; and not as
|
||||||
|
CNI Plugin.
|
||||||
|
|
||||||
|
This is documented [in the docs for vpn-only](./vpn-only.md), because this is easier to configure
|
||||||
|
and deploy.
|
100
manifests/kilo-vpn-only-example.yaml
Normal file
100
manifests/kilo-vpn-only-example.yaml
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: kilo
|
||||||
|
namespace: kilo
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: kilo
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- kilo.squat.ai
|
||||||
|
resources:
|
||||||
|
- peers
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- apiextensions.k8s.io
|
||||||
|
resources:
|
||||||
|
- customresourcedefinitions
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kilo
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kilo
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kilo
|
||||||
|
namespace: kilo
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: kilo
|
||||||
|
namespace: kilo
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kilo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: kilo
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kilo
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
# !!! Decide where you want to run your Kilo ingress.
|
||||||
|
kubernetes.io/hostname: TODO-ADD-YOUR-HOST-HERE
|
||||||
|
serviceAccountName: kilo
|
||||||
|
# we need to be part of the host network; otherwise, we cannot configure wireguard.
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: kilo
|
||||||
|
image: squat/kilo
|
||||||
|
args:
|
||||||
|
- --hostname=$(NODE_NAME)
|
||||||
|
# we only want to use Kilo as VPN; and not as CNI interface.
|
||||||
|
- --cni=false
|
||||||
|
- --encapsulate=never
|
||||||
|
# we want to work together with Flannel.
|
||||||
|
- --compatibility=flannel
|
||||||
|
- --local=false
|
||||||
|
env:
|
||||||
|
- name: NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
# we need to be root to configure wireguard
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: kilo-dir
|
||||||
|
mountPath: /var/lib/kilo
|
||||||
|
tolerations:
|
||||||
|
- effect: NoSchedule
|
||||||
|
operator: Exists
|
||||||
|
- effect: NoExecute
|
||||||
|
operator: Exists
|
||||||
|
volumes:
|
||||||
|
- name: kilo-dir
|
||||||
|
hostPath:
|
||||||
|
path: /var/lib/kilo
|
Loading…
Reference in New Issue
Block a user