Skip to content

Commit

Permalink
[FRP]: Create FRP task and demo (#674)
Browse files Browse the repository at this point in the history
* [FRP]: Create FRP task and demo
Create a FRP task and demo for setting up ClusterLink behind a NAT or firewall.

Signed-off-by: Kfir Toledo <[email protected]>
  • Loading branch information
kfirtoledo authored Jul 24, 2024
1 parent 8b29ca0 commit 3b933bd
Show file tree
Hide file tree
Showing 14 changed files with 868 additions and 0 deletions.
61 changes: 61 additions & 0 deletions demos/frp/kind/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# Copyright (c) The ClusterLink Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

################################################################
# Name: FRP demo that connect 3 Kind clusters using FRP:
# Desc: create 3 kind clusters :
# 1) GW, iPerf3 client, FRP client, and FRP server
# 2) GW, iPerf3 server, and FRP client
# 3) GW, iPerf3 client, and FRP client
###############################################################
import os
import sys
import time
projDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__)))))
sys.path.insert(0,f'{projDir}')

from demos.utils.common import printHeader
from demos.utils.kind import Cluster
from demos.iperf3.kind.iperf3_client_start import directTestIperf3,testIperf3Client
from demos.frp.test import frpTest

testOutputFolder = f"{projDir}/bin/tests/frp"

############################### MAIN ##########################
if __name__ == "__main__":
printHeader("\n\nStart Kind Test\n\n")
printHeader("Start pre-setting")

# cl parameters
cl1= Cluster("peer1")
cl2= Cluster("peer2")
cl3= Cluster("peer3")
srcSvc = "iperf3-client"
destSvc = "iperf3-server"
destPort = 5000
iperf3DirectPort = "30001"

# Setup
frpTest(cl1, cl2, cl3, testOutputFolder)
#Testing
printHeader("\n\nStart Iperf3 testing")
cl2.useCluster()
cl2.setKindIp()
directTestIperf3(cl1, srcSvc, cl2.ip, iperf3DirectPort)
time.sleep(5)
testIperf3Client(cl1, srcSvc, destSvc, destPort)
testIperf3Client(cl3, srcSvc, destSvc, destPort)



110 changes: 110 additions & 0 deletions demos/frp/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
# Copyright (c) The ClusterLink Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

################################################################
# Name: FRP demo that connect 3 clusters using FRP:
# Desc: create 3 kind clusters :
# 1) GW, iPerf3 client, FRP client, and FRP server
# 2) GW, iPerf3 server, and FRP client
# 3) GW, iPerf3 client, and FRP client
###############################################################
import os
import sys
import time
import hashlib
projDir = os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__))))

sys.path.insert(0,f'{projDir}')

from demos.utils.common import printHeader, runcmd
from demos.utils.kind import Cluster as KindCluster
from demos.utils.common import printHeader

# Folders
folCl=f"{projDir}/demos/iperf3/testdata/manifests/iperf3-client"
folSv=f"{projDir}/demos/iperf3/testdata/manifests/iperf3-server"
folFrp=f"{projDir}/demos/frp/testdata/manifests/"

# Services
srcSvc = "iperf3-client"
destSvc = "iperf3-server"
destPort = 5000
namespace = "default"
frpNamespace= "frp"

def frpTest(cl1:KindCluster, cl2:KindCluster,cl3:KindCluster, testOutputFolder):
print(f'Working directory {projDir}')
os.chdir(projDir)

# Build docker environment
printHeader("Build docker image")
os.system("make docker-build")
os.system("make install")

# Create Kind clusters environment
cl1.createCluster(runBg=True)
cl3.createCluster(runBg=True)
cl2.createCluster(runBg=False)

# Start Kind clusters environment
cl1.create_fabric(testOutputFolder)
cl1.startCluster(testOutputFolder)
cl2.startCluster(testOutputFolder)
cl3.startCluster(testOutputFolder)

# Create iPerf3 micro-services
cl1.loadService(srcSvc, "taoyou/iperf3-alpine",f"{folCl}/iperf3-client.yaml" )
cl2.loadService(destSvc, "taoyou/iperf3-alpine",f"{folSv}/iperf3.yaml" )
cl3.loadService(srcSvc, "taoyou/iperf3-alpine",f"{folCl}/iperf3-client.yaml" )
os.environ['FRP_SERVER_IP'] = cl1.ip
os.environ['FRP_SECRET_KEY'] = hashlib.sha256(str(time.time_ns()).encode()).hexdigest()[:10]
# Use envsubst to replace the placeholder and apply the ConfigMap
cl1.useCluster()
runcmd(f"kubectl apply -f {folFrp}/frp-ns.yaml")
runcmd(f"kubectl apply -f {folFrp}/server/frps-configmap.yaml")
cl1.loadService("frps", "snowdreamtech/frps",f"{folFrp}/server/frps.yaml", frpNamespace)

# Create peers
printHeader("Create peers")
cl1.useCluster()
runcmd(f"envsubst < {folFrp}/client/peer1/frpc-configmap.yaml| kubectl apply -f -")
cl1.loadService("frpc", "snowdreamtech/frpc",f"{folFrp}/client/frpc.yaml",frpNamespace )
runcmd(f"kubectl apply -f {folFrp}/client/peer1/peer.yaml")
cl2.useCluster()
runcmd(f"kubectl apply -f {folFrp}/frp-ns.yaml")
runcmd(f"envsubst < {folFrp}/client/peer2/frpc-configmap.yaml| kubectl apply -f -")
cl2.loadService("frpc", "snowdreamtech/frpc",f"{folFrp}/client/frpc.yaml",frpNamespace )
runcmd(f"kubectl apply -f {folFrp}/client/frpc.yaml")
runcmd(f"kubectl apply -f {folFrp}/client/peer2/peer.yaml")
cl3.useCluster()
runcmd(f"kubectl apply -f {folFrp}/frp-ns.yaml")
runcmd(f"envsubst < {folFrp}/client/peer3/frpc-configmap.yaml| kubectl apply -f -")
cl3.loadService("frpc", "snowdreamtech/frpc",f"{folFrp}/client/frpc.yaml" ,frpNamespace)
runcmd(f"kubectl apply -f {folFrp}/client/peer3/peer.yaml")
# Create exports
cl2.exports.create(destSvc, namespace, destPort)

# Import destination service
printHeader(f"\n\nStart Importing {destSvc} service to {cl1.name}")
cl1.imports.create(destSvc,namespace,destPort,cl2.name,destSvc,namespace)
cl3.imports.create(destSvc,namespace,destPort,cl2.name,destSvc,namespace)

# Add policy
printHeader("Applying policies")
cl1.policies.create(name="allow-all",namespace=namespace, action="allow", from_attribute=[{"workloadSelector": {}}],to_attribute=[{"workloadSelector": {}}])
cl2.policies.create(name="allow-all",namespace=namespace, action="allow", from_attribute=[{"workloadSelector": {}}],to_attribute=[{"workloadSelector": {}}])
cl3.policies.create(name="allow-all",namespace=namespace, action="allow", from_attribute=[{"workloadSelector": {}}],to_attribute=[{"workloadSelector": {}}])



27 changes: 27 additions & 0 deletions demos/frp/testdata/manifests/client/frpc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: frpc
namespace: frp
spec:
replicas: 1
selector:
matchLabels:
app: frpc
template:
metadata:
labels:
app: frpc
spec:
# hostNetwork: true
containers:
- name: frpc
image: snowdreamtech/frpc
imagePullPolicy: IfNotPresent
volumeMounts:
- name: frpc-config-volume
mountPath: /etc/frp
volumes:
- name: frpc-config-volume
configMap:
name: frpc-config
33 changes: 33 additions & 0 deletions demos/frp/testdata/manifests/client/peer1/frpc-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: frpc-config
namespace: frp
data:
frpc.toml: |
# Set server address
serverAddr = "${FRP_SERVER_IP}"
serverPort = 30444
[[proxies]]
name = "clusterlink-peer1"
type = "stcp"
localIP = "clusterlink.clusterlink-system.svc.cluster.local"
localPort = 443
secretKey = "${FRP_SECRET_KEY}"
[[visitors]]
name = "clusterlink-peer1-to-peer2-visitor"
type = "stcp"
serverName = "clusterlink-peer2"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6002
[[visitors]]
name = "clusterlink-peer1-to-peer3-visitor"
type = "stcp"
serverName = "clusterlink-peer3"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6003
47 changes: 47 additions & 0 deletions demos/frp/testdata/manifests/client/peer1/peer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
name: peer2
namespace: clusterlink-system
spec:
gateways:
- host: frp-peer2-clusterlink.frp.svc.cluster.local
port: 6002

---
apiVersion: v1
kind: Service
metadata:
name: frp-peer2-clusterlink
namespace: frp
spec:
type: ClusterIP
selector:
app: frpc
ports:
- port: 6002
targetPort: 6002
---
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
name: peer3
namespace: clusterlink-system
spec:
gateways:
- host: frp-peer3-clusterlink.frp.svc.cluster.local
port: 6003

---
apiVersion: v1
kind: Service
metadata:
name: frp-peer3-clusterlink
namespace: frp
spec:
type: ClusterIP
selector:
app: frpc
ports:
- port: 6003
targetPort: 6003
33 changes: 33 additions & 0 deletions demos/frp/testdata/manifests/client/peer2/frpc-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: frpc-config
namespace: frp
data:
frpc.toml: |
# Set server address
serverAddr = "${FRP_SERVER_IP}"
serverPort = 30444
[[proxies]]
name = "clusterlink-peer2"
type = "stcp"
localIP = "clusterlink.clusterlink-system.svc.cluster.local"
localPort = 443
secretKey = "${FRP_SECRET_KEY}"
[[visitors]]
name = "clusterlink-peer2-to-peer1-visitor"
type = "stcp"
serverName = "clusterlink-peer1"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6001
[[visitors]]
name = "clusterlink-peer2-to-peer3-visitor"
type = "stcp"
serverName = "clusterlink-peer3"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6003
45 changes: 45 additions & 0 deletions demos/frp/testdata/manifests/client/peer2/peer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
name: peer1
namespace: clusterlink-system
spec:
gateways:
- host: frp-peer1-clusterlink.frp.svc.cluster.local
port: 6001
---
apiVersion: v1
kind: Service
metadata:
name: frp-peer1-clusterlink
namespace: frp
spec:
type: ClusterIP
selector:
app: frpc
ports:
- port: 6001
targetPort: 6001
---
apiVersion: clusterlink.net/v1alpha1
kind: Peer
metadata:
name: peer3
namespace: clusterlink-system
spec:
gateways:
- host: frp-peer3-clusterlink.frp.svc.cluster.local
port: 6003
---
apiVersion: v1
kind: Service
metadata:
name: frp-peer3-clusterlink
namespace: frp
spec:
type: ClusterIP
selector:
app: frpc
ports:
- port: 6003
targetPort: 6003
33 changes: 33 additions & 0 deletions demos/frp/testdata/manifests/client/peer3/frpc-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: frpc-config
namespace: frp
data:
frpc.toml: |
# Set server address
serverAddr = "${FRP_SERVER_IP}"
serverPort = 30444
[[proxies]]
name = "clusterlink-peer3"
type = "stcp"
localIP = "clusterlink.clusterlink-system.svc.cluster.local"
localPort = 443
secretKey = "${FRP_SECRET_KEY}"
[[visitors]]
name = "clusterlink-peer3-to-peer1-visitor"
type = "stcp"
serverName = "clusterlink-peer1"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6001
[[visitors]]
name = "clusterlink-peer3-to-peer2-visitor"
type = "stcp"
serverName = "clusterlink-peer2"
secretKey = "${FRP_SECRET_KEY}"
bindAddr = "::"
bindPort = 6002
Loading

0 comments on commit 3b933bd

Please sign in to comment.