veilnet-conflux)This guide walks you through setting up an RKE2 Kubernetes cluster using VeilNet for networking across multiple nodes.
Important: Certain configuration values must be identical across all server nodes in your cluster. These include: cluster-cidr, cluster-dns, cluster-domain, service-cidr, and cni. Make sure to use the same values on all nodes to prevent cluster join failures.
First, prepare the VeilNet Conflux binary and register the node:
chmod +x ./veilnet-conflux
Register the node with VeilNet:
sudo ./veilnet-conflux register \
-t <YOUR_VEILNET_TOKEN> \
--cidr <YOUR_CIDR> \
--tag <YOUR_TAG> \
-p
Replace the placeholders:
<YOUR_VEILNET_TOKEN>: Your VeilNet registration token<YOUR_CIDR>: The CIDR block for this node (e.g., 10.128.0.1/16)<YOUR_TAG>: A tag to identify this node (e.g., master-node-1)Check the VeilNet service logs:
journalctl -u veilnet -f
Update the system:
sudo apt update
sudo apt upgrade -y
Create the RKE2 config directory:
sudo mkdir -p /etc/rancher/rke2
Create the RKE2 configuration file. Replace <YOUR_NODE_IP> with the VeilNet IP address assigned to this node:
sudo tee /etc/rancher/rke2/config.yaml > /dev/null <<EOF
node-ip: <YOUR_NODE_IP>
node-external-ip: <YOUR_NODE_IP>
tls-san:
- <YOUR_NODE_IP>
cni: canal
EOF
Note: RKE2 uses canal as the default CNI (which includes Flannel). By setting node-ip to your VeilNet IP address, the CNI will automatically use the VeilNet interface for pod networking.
Replace the placeholders:
<YOUR_NODE_IP>: The VeilNet IP address of this node (e.g., 10.128.0.1)Install RKE2:
curl -sfL https://get.rke2.io | sudo sh -
Enable and start the RKE2 service:
sudo systemctl enable rke2-server.service
sudo systemctl start rke2-server.service
Wait for the service to start and check its status:
sudo systemctl status rke2-server.service
Get the node token for joining additional nodes:
sudo cat /var/lib/rancher/rke2/server/node-token
Set up kubectl:
mkdir -p ~/.kube
sudo cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
export KUBECONFIG=~/.kube/config
Add the kubectl path to your PATH:
export PATH=$PATH:/var/lib/rancher/rke2/bin
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc
After RKE2 starts, verify that the CNI (Canal/Flannel) is using the VeilNet interface. The CNI should automatically bind to the interface specified by node-ip. Check the Canal pods:
kubectl get pods -n kube-system -l app=flannel
kubectl get pods -n kube-system -l k8s-app=canal
If needed, you can patch the Canal daemonset to explicitly use the VeilNet interface by editing the Flannel daemonset:
kubectl patch daemonset kube-flannel-ds -n kube-system --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--iface=veilnet"}]'
Note: RKE2 manages the CNI configuration automatically. By setting node-ip to your VeilNet IP, the CNI should use that interface. The manual patch above is only needed if the CNI doesn't automatically detect the correct interface.
To join additional server nodes to form a HA cluster, first register each node with VeilNet (as in Step 1), then create the RKE2 config directory:
sudo mkdir -p /etc/rancher/rke2
Create the RKE2 configuration file. Replace the placeholders with your values:
sudo tee /etc/rancher/rke2/config.yaml > /dev/null <<EOF
server: https://<CONTROL_NODE_IP>:9345
token: <NODE_TOKEN>
node-ip: <NEW_NODE_IP>
node-external-ip: <NEW_NODE_IP>
tls-san:
- <NEW_NODE_IP>
cni: canal
EOF
Important: The cni, cluster-cidr, service-cidr, cluster-dns, and cluster-domain values must match the control node configuration. If you customized these on the control node, use the same values here.
Replace the placeholders:
<NODE_TOKEN>: The token from the control node<CONTROL_NODE_IP>: The VeilNet IP of the control node (e.g., 10.128.0.1)<NEW_NODE_IP>: The VeilNet IP of the new server node (e.g., 10.128.0.2)Install RKE2:
curl -sfL https://get.rke2.io | sudo sh -
Enable and start the RKE2 server service:
sudo systemctl enable rke2-server.service
sudo systemctl start rke2-server.service
To join worker nodes to the cluster, first register each node with VeilNet (as in Step 1), then create the RKE2 config directory:
sudo mkdir -p /etc/rancher/rke2
Create the RKE2 configuration file for the worker node:
sudo tee /etc/rancher/rke2/config.yaml > /dev/null <<EOF
server: https://<CONTROL_NODE_IP>:9345
token: <NODE_TOKEN>
node-ip: <WORKER_NODE_IP>
node-external-ip: <WORKER_NODE_IP>
cni: canal
EOF
Important: The cni, cluster-cidr, service-cidr, cluster-dns, and cluster-domain values must match the control node configuration. If you customized these on the control node, use the same values here.
Replace the placeholders:
<NODE_TOKEN>: The token from the control node<CONTROL_NODE_IP>: The VeilNet IP of the control node (e.g., 10.128.0.1)<WORKER_NODE_IP>: The VeilNet IP of the worker node (e.g., 10.128.0.3)Install RKE2:
curl -sfL https://get.rke2.io | sudo sh -
Enable and start the RKE2 agent service:
sudo systemctl enable rke2-agent.service
sudo systemctl start rke2-agent.service
Verify your cluster is running correctly:
kubectl get nodes
kubectl get pods --all-namespaces
Check that Canal/Flannel is using the VeilNet interface:
kubectl get pods -n kube-system -l app=flannel
kubectl get pods -n kube-system -l k8s-app=canal
kubectl logs -n kube-system -l app=flannel | grep -i veilnet
To update VeilNet on a node, download the new binary and follow these steps:
chmod +x ./veilnet-conflux
sudo ./veilnet-conflux remove
sudo ./veilnet-conflux install
sudo reboot
After rebooting, the node will reconnect to the VeilNet network with the updated binary, as well as the RKE2 cluster.
To update RKE2 on a node:
sudo systemctl stop rke2-server.service
# or for worker nodes:
sudo systemctl stop rke2-agent.service
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=<VERSION> sudo sh -
sudo systemctl start rke2-server.service
# or for worker nodes:
sudo systemctl start rke2-agent.service
To achieve direct service mesh connectivity (similar to Docker's network namespace sharing where containers share the network namespace with veilnet-conflux), you can deploy veilnet-conflux as a sidecar container in your Kubernetes pods. This allows your application containers to share the network namespace with veilnet-conflux, giving them direct access to the VeilNet TUN device and enabling direct communication between services using VeilNet IP addresses.
Here's an example manifest that deploys an application with veilnet-conflux as a sidecar:
apiVersion: v1
kind: Secret
metadata:
name: veilnet-conflux-secret
namespace: default
type: Opaque
stringData:
VEILNET_REGISTRATION_TOKEN: <YOUR_REGISTRATION_TOKEN>
VEILNET_GUARDIAN: <YOUR_GUARDIAN_URL>
VEILNET_PORTAL: "true"
VEILNET_CONFLUX_TAG: <YOUR_CONFLUX_TAG>
VEILNET_CONFLUX_CIDR: <VEILNET_CIDR>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
# VeilNet Conflux sidecar - must be first container
- name: veilnet-conflux
image: veilnet/conflux:beta
imagePullPolicy: Always
securityContext:
capabilities:
add:
- NET_ADMIN
volumeMounts:
- name: dev-net-tun
mountPath: /dev/net/tun
envFrom:
- secretRef:
name: veilnet-conflux-secret
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
# Your application container
- name: app
image: your-app:latest
ports:
- containerPort: 8080
name: http
# Application shares network namespace with veilnet-conflux
# Access other services via VeilNet IP addresses
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: dev-net-tun
hostPath:
path: /dev/net/tun
type: CharDevice
# All containers in the pod share the same network namespace
# This is the default behavior in Kubernetes
---
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: default
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
network_mode: "container:veilnet-conflux".veilnet-conflux container runs as a sidecar alongside your application container in the same pod./dev/net/tun and NET_ADMIN capability to create the VeilNet interface.envFrom.Once deployed, your application can:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-with-db
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: web-app-with-db
template:
metadata:
labels:
app: web-app-with-db
spec:
containers:
# VeilNet Conflux sidecar
- name: veilnet-conflux
image: veilnet/conflux:beta
imagePullPolicy: Always
securityContext:
capabilities:
add:
- NET_ADMIN
volumeMounts:
- name: dev-net-tun
mountPath: /dev/net/tun
envFrom:
- secretRef:
name: veilnet-conflux-secret
# Web application
- name: web-app
image: nginx:latest
ports:
- containerPort: 80
# Database (shares network namespace)
- name: database
image: postgres:15-alpine
env:
- name: POSTGRES_DB
value: mydb
- name: POSTGRES_USER
value: user
- name: POSTGRES_PASSWORD
value: password
ports:
- containerPort: 5432
volumes:
- name: dev-net-tun
hostPath:
path: /dev/net/tun
type: CharDevice
In this example, all three containers (veilnet-conflux, web-app, and database) share the same network namespace, allowing them to communicate via localhost while also having access to the VeilNet network.
No, you do not need to configure a sub-router. VeilNet handles all the networking automatically, including routing between nodes across different regions.
No, you do not need to configure firewall rules or CNI VXLAN settings. VeilNet manages the network layer, and the Canal CNI (which includes Flannel) will use the VeilNet interface automatically when node-ip is set to your VeilNet IP address.
Yes, RKE2 supports multiple CNI options: canal (default, includes Flannel), calico, cilium, or none. To use Cilium or Calico, set cni: cilium or cni: calico in your RKE2 config file. You'll need to configure the CNI to use the VeilNet interface by ensuring node-ip is set to your VeilNet IP address. Some CNIs may require additional configuration to bind to the veilnet interface.
We do not recommend using Longhorn for distributed storage unless all nodes are in the same local network. Longhorn has strict latency requirements that may not be met when nodes are distributed across different regions or have higher network latency. For multi-region deployments, consider using other storage solutions that are designed for higher latency environments.
Yes, you can still use VeilNet for your cluster even if all nodes are on the same local network. VeilNet provides additional security by encrypting all traffic between nodes and can help isolate your cluster traffic from other network traffic on the same physical network.
RKE2 is Rancher's enterprise-grade Kubernetes distribution that follows upstream Kubernetes more closely, while K3s is a lightweight distribution. RKE2 uses systemd for service management and has stricter security defaults. Both work well with VeilNet, but RKE2 may be preferred for production environments requiring full Kubernetes compliance.