如何在 Kubernetes 上部署 Janus WebRTC 服务器

本文分享如何在 Kubernetes 上部署 Janus WebRTC 服务器。无论您是 Kubernetes 爱好者还是 Janus 专家(或两者都不是),本指南都将逐步指导您完成整个过程。

在 Kubernetes 上部署 Janus 的前提条件

在开始之前,请确保满足以下要求:

Kubernetes 集群

我们将使用MinikubeDocker 驱动程序创建本地 Kubernetes 集群。

  • 该集群将有3 个节点来复制真实环境。
  • 确保我们已经安装了helm。

Envoy Gateway API

我们将使用 Envoy Gateway 进行流量管理,以简化 Janus WebRTC 的路由和负载平衡。

1. 启动具有 3 个节点的 Minikube 集群

这将使用 Docker 驱动程序建立一个有三个节点的本地 Kubernetes 集群:

minikube start --nodes=3 --driver=docker

2. 安装 Envoy Gateway CRD

将 Envoy Gateway CRD 添加到你的 Kubernetes 集群,以启用 Gateway API 将流量路由到正确的 Janus pod

helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.2.4 -n envoy-gateway-system --create-namespace

以上步骤将为您的本地环境做好准备,以便在 Kubernetes 上部署 Janus。完成后,您将拥有一个多节点集群和网关 API,可以执行后续步骤。

行动时间

在我们进入不可避免的 YAML 疯狂之前,让我为您节省一些时间。我已经建立了一个 GitHub repo,里面有您需要的所有 YAML 和配置。所以,如果您是一个经过认证的 Kubernetes 专家,不需要一步一步的指导,可以跳过这步,直接访问 janus-on-kubernetes。

这里不深入介绍 Janus 配置,您可以在 GitHub repo 中找到这些配置。相反,我将重点介绍 Kubernetes 设置,以及我们为简化生成服务和 UDPRoute 而构建的便捷 Python CLI 工具。

什么是Gateway API?

Kubernetes 中的 Gateway API 是管理服务网络的一种更灵活、更可扩展的方式。它建立在 Ingress 的基础上,但为更复杂的用例提供了额外的功能。以下是其核心组件:

Gateway(网关):

网关是网络流量进入群集的入口。它定义流量的路由方式(如监听哪些 IP 或端口)。将其视为负载平衡器或反向代理。

GatewayClass:

GatewayClass 定义了网关的 “类型”,指定了管理网关行为的控制器(如 NGINX、Envoy 等)。它就像是网关的蓝图。

Listeners监听器)

监听器是网关的一部分,定义网关应该监听的协议和端口(例如,端口 80 上的 HTTP)。

HTTPRoute(或其他路由类型)

路由定义特定类型的流量(如 HTTP 或 TCP)应如何流经网关。例如,HTTPRoute 将传入的 HTTP 请求映射到特定的 Kubernetes 服务。

后端(Backend):

后端是流量最终到达的地方–通常是处理实际工作负载的 Kubernetes 服务或其他资源。

与传统的 Ingress 相比,这些组件更易于管理复杂的网络设置,并提供更多的自定义和可扩展性。

现在我们对网关 API 有了清晰的思维导图,让我们从部署和服务配置开始,深入编写 YAML 文件。

部署和服务 Yaml

在这里,我们将创建一个 StatefulSet 部署和一个无头服务。这种设置可确保每个 Janus 实例都能获得一个专用且稳定的 DNS 名称,例如:

janus-0.janus-service.default.svc.cluster.local
janus-1.janus-service.default.svc.cluster.local
janus-2.janus-service.default.svc.cluster.local

通过将BackendTrafficPolicy (BTP)与 StatefulSets 和无头服务结合使用,每个 DNS 都会将流量一致地路由到固定的 Janus 实例。这可确保可靠、稳定且可预测的连接,这对于 Janus 等有状态工作负载至关重要,因为每个实例都需要一个专用的稳定网络身份。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: janus
  namespace: default # 如果不使用命名空间,则省略或更改
spec:
  replicas: 2
  selector:
    matchLabels:
      app: janus
  serviceName: "janus-service" # StatefulSet 网络所需
  template:
    metadata:
      labels:
        app: janus
    spec:
      initContainers:
        - name: init-elevated
          image: busybox:latest
          command: ["sh", "-c"]
          args:
            - |
              chmod -R 777 /recordings/;
          securityContext:
            privileged: true
          volumeMounts:
            - name: janus-recordings
              mountPath: /recordings/
      containers:
        - name: janus
        # 可以构建自己的映像并将其从 https://github.com/flutterjanus/JanusDocker 推送到注册表
          image: shivanshtalwar0/janus-server:latest # for x86_64 => shivanshtalwar0/janus-server:linux-amd64
          resources:
            requests:
              memory: "256Mi" # 容器所需的最小内存
              cpu: "250m" # 容器所需的最小 CPU 
            limits:
              memory: "512Mi" # 容器可以使用的最大内存
              cpu: "500m" # 容器可以使用的最大 CPU 
          volumeMounts:
            - name: janus-config
              mountPath: /opt/janus/etc/janus
            - name: janus-recordings
              mountPath: /recordings

      volumes:
        - name: janus-config
          configMap:
            name: janus-config
        - name: janus-recordings
          hostPath:
            path: /recordings
          emptyDir: {}

  volumeClaimTemplates:
    - metadata:
        name: janus-recordings
      spec:
        accessModes: ["ReadWriteMany"]
        resources:
          requests:
            storage: 100Gi

我们使用 service_template.yamlport-ranger.py 来动态创建最终的 service_generated.yaml。这允许我们指定自定义的端口范围,这对 Janus 来说至关重要,因为它需要 UDP 端口来进行媒体遍历,特别是处理 RTP 媒体流流量。

# service_template.yaml
apiVersion: v1
kind: Service
metadata:
  name: janus-service
  namespace: default
spec:
  selector:
    app: janus
  ports:
    - name: janus-http
      protocol: TCP
      port: 8088
      targetPort: 8088
    - name: janus-ws
      protocol: TCP
      port: 8188
      targetPort: 8188
    - name: janus-a-http
      protocol: TCP
      port: 7088
      targetPort: 7088
    - name: janus-a-ws
      protocol: TCP
      port: 7188
      targetPort: 7188
  clusterIP: None

运行下面的命令来创建 service_generated.yaml

python3 port-ranger.py./service_template.yaml janus 10000 11000 UDP./service_generated.yaml

同样,我们将从 udpRoute_template.yaml 中为 UDPRoute 创建一个模板,稍后将派上用场

# udpRoute_template.yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: UDPRoute
metadata:
  name: janus-udp-route
  namespace: default
spec:
  parentRefs:
    - name: envoy-gateway 
      namespace: default
  rules:
    - backendRefs:
        - name: janus-service 
          namespace: default
          port: 10000
          kind: Service
# 注意:由于 Kubernetes 对 UDP 路由的限制,UDP 路由不能超过 16 个
python3 port-ranger.py ./udpRoutes_template.yaml janus 10000 11000 UDP ./udp_routes_generated.yaml --chunk-size 16

现在我们已经完成了生成 YAML 的步骤,可以定义关键的 Gateway 组件了。在这里,我们将概述GatewayGatewayClassHTTPRoute的 YAML 文件。定义这些文件后将完成核心设置。以下是所有三个组件的 YAML 文件:

Gateway.yaml

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: envoy-gateway
spec:
  gatewayClassName: gateway-class
  listeners:
    - name: janus-http-api
      port: 80
      hostname: "*.example.local"
      protocol: HTTP

GatewayClass.yaml

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: gateway-class
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

httpRoute.yaml

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
spec:
  parentRefs: [ {name: envoy-gateway, port: 80, sectionName: janus-http-api } ]
  hostnames: ["*.example.local"]
  rules:
    - matches:
        - path: {type: PathPrefix, value: /rest}
      backendRefs:
        - {group: "", kind: Service, name: janus-service, port: 8088}
    - matches:
        - path: {type: PathPrefix, value: /admin-rest}
      backendRefs:
        - {group: "", kind: Service, name: janus-service, port: 7088}
    - matches:
        - path: {type: PathPrefix, value: /admin-ws}
      backendRefs:
        - {group: "", kind: Service, name: janus-service, port: 7188}                
    - matches:
        - path: {type: PathPrefix, value: /ws}
      backendRefs:
        - {group: "", kind: Service, name: janus-service, port: 8188}        

初始化 Janus 配置

运行以下脚本来初始化 ConfigMap 中的 Janus 配置:

./update_conf.sh

应用 Kubernetes YAML 配置

按照以下顺序应用配置以完成设置:

kubectl apply -f gatewayClass. yaml
 kubectl apply -f gateway. yaml
 kubectl apply -f btp. yaml
 kubectl apply -f httpRoutes. yaml
 kubectl apply -f udp_routes_generated. yaml
 kubectl apply -f deploy. yaml
 kubectl apply -f service_generated. yaml

测试部署

更新本地 DNS

使用以下条目更新/etc/hosts文件:

# /etc/hosts
127.0.0.1 janus-0.example.local
127.0.0.1 janus-1.example.local
127.0.0.1 janus-2.example.local

验证访问权限

一旦一切正确配置,您可以通过以下端点验证 Janus 服务器的可访问性:

REST API

curl http://janus-0.example.local/rest/janus/info

WebSocket

http://janus-0.example.local/ws

Admin WebSocket

http://janus-0.example.local/admin-ws

注意

  • 确保配置中使用的端口范围一致。
  • 对于大规模部署,根据需要调整端口范围和用户计算。

按照这些步骤将确保您在 Kubernetes 上拥有完全部署且功能齐全的 Janus 设置!

小结

在本指南中,我们介绍了在 Kubernetes 上部署 Janus 的过程,从设置配置到测试部署。我们介绍了 StatefulSet、无头服务、网关 API 和端口管理等基本组件,以确保 Janus 的无缝部署。

作者:Shivansh Talwar

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论