EasyFaaS网络架构部署方案
EasyFaaS使用基于Linux bridge的容器网络架构。每个funclet组件负责管理容器网络,通过创建bridge网桥和veth pair来实现容器间的网络通信 network.go:25-41 。
网络组件配置
1. 网络管理器初始化
funclet在启动时会初始化网络管理器并创建bridge网桥 funclet.go:115-119 。
2. Bridge网桥配置
网络管理器通过InitNetwork方法创建bridge,并配置IP网段 network.go:47-68 。
3. 容器网络设置
每个容器启动时,系统会为其分配IP地址并设置网络 init.go:100-104 。
单机裸金属部署方案
1. 环境准备
基于快速开始文档,需要准备Linux环境(内核4.0+)和Docker:
2. All-in-One部署方式
EasyFaaS提供了all-in-one部署方式,特别适合单机部署。这种方式将controller、funclet和stubs组件打包在一个镜像中
3. 编译构建
首先编译所有模块:
# 编译全部模块
make
# 打包all-in-one镜像
scripts/build-image.sh -m=one -i=easyfaas -t=dev
4. 裸金属部署配置
创建部署脚本 deploy-bare-metal.sh:
#!/bin/bash
# 设置数据目录
export faasPath=/opt/easyfaas/faas
mkdir -p ${faasPath}/{runtime,runner,data,funcData,invoker/run}
# 启动runner-runtime准备运行时环境
docker run -td \
-e WITHRUNNER=1 \
-e WITHNODEJS10=1 \
-e WITHNODEJS12=1 \
-e WITHPYTHON3=1 \
--name runner-runtime \
-v ${faasPath}/runtime:/var/faas/runtime \
-v ${faasPath}/runner:/var/faas/runner \
registry.baidubce.com/easyfaas-public/runner-runtime:demo1.0
# 等待runtime准备完成
echo "等待runtime准备完成..."
sleep 30
# 启动all-in-one服务
docker run -td \
--privileged \
--name easyfaas \
-p 8080:8080 \
-p 8002:8002 \
-v ${faasPath}/runner:/var/faas/runner \
-v ${faasPath}/runtime:/var/faas/runtime \
-v ${faasPath}/data:/var/faas/runner-data \
-v ${faasPath}/funcData:/var/faas/funcData \
-v ${faasPath}/invoker/run:/var/run/faas \
easyfaas:dev
echo "EasyFaaS部署完成!"
echo "Controller端口: 8080"
echo "Registry端口: 8002"
5. 网络配置优化
对于裸金属部署,需要优化网络配置以避免冲突。基于代码中的网络配置:
创建自定义网络配置:
// pkg/funclet/network/bare_metal_options.go
package network
import "os"
func GetBareMetalNetworkOptions() *NetworkOption {
return &NetworkOption{
BridgeName: "easyfaas-br0",
BridgeIP: "192.168.100.1/24", // 避免与常见网段冲突
MTU: 1500,
}
}
func IsBareMetalEnvironment() bool {
return os.Getenv("EASYFAAS_DEPLOY_MODE") == "bare-metal"
}
6. 服务启动脚本
创建系统服务配置 /etc/systemd/system/easyfaas.service:
[Unit]
Description=EasyFaaS Function Computing Service
After=docker.service
Requires=docker.service
[Service]
Type=forking
Environment=EASYFAAS_DEPLOY_MODE=bare-metal
ExecStart=/opt/easyfaas/deploy-bare-metal.sh
ExecStop=/usr/bin/docker stop easyfaas runner-runtime
ExecStopPost=/usr/bin/docker rm easyfaas runner-runtime
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
7. 功能验证
部署完成后,可以通过以下方式验证:
# 检查服务状态
docker ps
# 测试controller接口
curl http://localhost:8080/health
# 测试registry接口
curl http://localhost:8002/v1/functions
Docker Bridge容器网络部署
基于代码中的docker-compose配置 docker-compose.yaml:21-40 ,以下是三台服务器的配置示例:
服务器1 (Controller节点)
version: '2.0'
services:
easyfaas-controller:
image: easyfaas/controller:latest
network_mode: host
command:
- ./controller
- --port=8080
- --repository-endpoint=http://192.168.1.100:8081
volumes:
- /var/run/faas:/var/run/faas
服务器2 (Funclet节点1)
version: '2.0'
services:
easyfaas-funclet:
image: easyfaas/mini-funclet:latest
network_mode: bridge
privileged: true
command:
- ./funclet
- --container-num=20
- --bridge-name=easyfaas0
- --bridge-cidr=172.18.0.0/16
volumes:
- /var/run/faas:/var/run/faas
服务器3 (Funclet节点2)
version: '2.0'
services:
easyfaas-funclet:
image: easyfaas/mini-funclet:latest
network_mode: bridge
privileged: true
command:
- ./funclet
- --container-num=20
- --bridge-name=easyfaas0
- --bridge-cidr=172.19.0.0/16
volumes:
- /var/run/faas:/var/run/faas
网络隔离配置
系统通过iptables规则实现容器间网络隔离 iptables_linux.go:28-45 ,并支持NAT出站流量 iptables_linux.go:48-71 。
k8s部署方案
1. Kubernetes资源定义文件
ConfigMap配置管理
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: easyfaas-config
namespace: easyfaas-system
data:
controller.yaml: |
port: "8080"
repository-endpoint: "http://easyfaas-registry:8002"
repository-version: "v1"
repository-auth-type: "noauth"
maxprocs: "10"
http-enhanced: "true"
funclet.yaml: |
reserved-memory: "100M"
reserved-cpu: "0.3"
runner-memory: "128M"
container-num: "20"
bridge-name: "easyfaas0"
bridge-ip: "10.244.0.1/16"
Controller部署配置
# controller-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: easyfaas-controller
namespace: easyfaas-system
spec:
replicas: 1
selector:
matchLabels:
app: easyfaas-controller
template:
metadata:
labels:
app: easyfaas-controller
spec:
serviceAccountName: easyfaas-controller
containers:
- name: controller
image: easyfaas/controller:latest
ports:
- containerPort: 8080
env:
- name: CONTROLLER_CONFIG_PATH
value: "/etc/easyfaas/controller.yaml"
volumeMounts:
- name: config
mountPath: /etc/easyfaas
- name: faas-run
mountPath: /var/run/faas
command:
- ./controller
- --config=/etc/easyfaas/controller.yaml
- --logtostderr=true
- -v=2
volumes:
- name: config
configMap:
name: easyfaas-config
- name: faas-run
emptyDir: {}
Funclet DaemonSet配置
# funclet-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: easyfaas-funclet
namespace: easyfaas-system
spec:
selector:
matchLabels:
app: easyfaas-funclet
template:
metadata:
labels:
app: easyfaas-funclet
spec:
serviceAccountName: easyfaas-funclet
hostNetwork: false
hostPID: false
containers:
- name: funclet
image: easyfaas/mini-funclet:latest
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
- SYS_ADMIN
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: KUBERNETES_MODE
value: "true"
volumeMounts:
- name: config
mountPath: /etc/easyfaas
- name: faas-run
mountPath: /var/run/faas
- name: faas-runtime
mountPath: /var/faas/runtime
- name: faas-runner
mountPath: /var/faas/runner
- name: faas-data
mountPath: /var/faas/runner-data
command:
- ./funclet
- --config=/etc/easyfaas/funclet.yaml
- --logtostderr=true
- -v=10
volumes:
- name: config
configMap:
name: easyfaas-config
- name: faas-run
hostPath:
path: /var/run/faas
type: DirectoryOrCreate
- name: faas-runtime
hostPath:
path: /var/faas/runtime
type: DirectoryOrCreate
- name: faas-runner
hostPath:
path: /var/faas/runner
type: DirectoryOrCreate
- name: faas-data
hostPath:
path: /var/faas/runner-data
type: DirectoryOrCreate
2. 服务发现机制
Service资源定义
# services.yaml
apiVersion: v1
kind: Service
metadata:
name: easyfaas-controller
namespace: easyfaas-system
spec:
selector:
app: easyfaas-controller
ports:
- port: 8080
targetPort: 8080
name: http
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
name: easyfaas-registry
namespace: easyfaas-system
spec:
selector:
app: easyfaas-registry
ports:
- port: 8002
targetPort: 8002
name: http
type: ClusterIP
3. 网络策略适配
修改网络管理器以支持Kubernetes
基于现有的网络管理器接口 network.go:25-29 ,我们需要创建一个Kubernetes适配的网络管理器:
// pkg/funclet/network/k8s_network.go
package network
import (
"fmt"
"os"
)
type KubernetesNetworkManager struct {
*ContainerNetwork
kubernetesMode bool
}
func NewKubernetesNetworkManager() NetworkManagerInterface {
return &KubernetesNetworkManager{
ContainerNetwork: &ContainerNetwork{},
kubernetesMode: isKubernetesEnvironment(),
}
}
func isKubernetesEnvironment() bool {
return os.Getenv("KUBERNETES_MODE") == "true" ||
os.Getenv("KUBERNETES_SERVICE_HOST") != ""
}
func (k *KubernetesNetworkManager) InitNetwork(opt *NetworkOption) error {
if k.kubernetesMode {
// 在Kubernetes环境中,跳过自定义bridge创建
// 使用Pod网络
return nil
}
// 回退到原有的bridge网络
return k.ContainerNetwork.InitNetwork(opt)
}
func (k *KubernetesNetworkManager) SetContainerNet(containerPid int) error {
if k.kubernetesMode {
// 在Kubernetes环境中,容器网络由CNI管理
return nil
}
return k.ContainerNetwork.SetContainerNet(containerPid)
}
修改Funclet初始化逻辑
需要修改 funclet.go:97 中的网络管理器创建:
// 在InitFunclet函数中
var networkManager network.NetworkManagerInterface
if os.Getenv("KUBERNETES_MODE") == "true" {
networkManager = network.NewKubernetesNetworkManager()
} else {
networkManager = network.NewNetworkManager()
}
f = &Funclet{
// ... 其他字段
NetworkManager: networkManager,
// ... 其他字段
}
4. 权限和安全配置
RBAC权限配置
# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: easyfaas-controller
namespace: easyfaas-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: easyfaas-funclet
namespace: easyfaas-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: easyfaas-controller
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "daemonsets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: easyfaas-funclet
rules:
- apiGroups: [""]
resources: ["nodes", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: easyfaas-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: easyfaas-controller
subjects:
- kind: ServiceAccount
name: easyfaas-controller
namespace: easyfaas-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: easyfaas-funclet
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: easyfaas-funclet
subjects:
- kind: ServiceAccount
name: easyfaas-funclet
namespace: easyfaas-system
网络策略
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: easyfaas-network-policy
namespace: easyfaas-system
spec:
podSelector:
matchLabels:
app: easyfaas-funclet
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: easyfaas-controller
egress:
- to:
- podSelector:
matchLabels:
app: easyfaas-registry
- to: []
ports:
- protocol: TCP
port: 53
- protocol: UDP
port: 53
完整部署脚本
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: easyfaas-system
#!/bin/bash
# deploy.sh
kubectl apply -f namespace.yaml
kubectl apply -f rbac.yaml
kubectl apply -f configmap.yaml
kubectl apply -f services.yaml
kubectl apply -f controller-deployment.yaml
kubectl apply -f funclet-daemonset.yaml
kubectl apply -f network-policy.yaml