While this post will end up with a running Teamspeak server, it is very hard on the resources of the Raspberry Pi and might not be suitable for everyday use.
To deploy a teamspeak server on raspberry pi a few things need to be done:
- (optional) Get a Kubernetes cluster up and running (this is not required, if
you just want to run the
docker
container directly). - Get Teamspeak to run on
ARM
. - Setup an ingress controller to make the Teamspeak server accessible from the outside world (in this case this will be the Nginx Ingress).
Setting up a kubernetes cluster
To setup a kubernetes cluster on Raspberry Pis K3S is very good approach, as the cluster will be more lightweight that simply installing upstream kubernetes.
As a base I recommend using HypriotOS or Ubuntu Server1 as those allow configuring the images using Cloud-Init.
Make sure to follow the instructions to use the the legacy
backend for
iptables
if installing kubernetes
v1.17 or lower: kubeadm instructions.
When installing k3s
to run Teamspeak
Traefik
should not be installed,
as only the 2.x version supports UDP
ingresses - so instead nginx-ingress
will be installed later:
1curl -sfL https://get.k3s.io | sh -s - --no-deploy=traefik
Deploy Teamspeak
Build an ARM image for Teamspeak
Teamspeak does not provide a binary for ARM
.
It is however possible to run it using Qemu - I have already prepared an
ARM
image that will run the Teamspeak server through qemu
that you can
find on my Dockerhub - or if you want to see the source checkout the
repository on Github.
The image is using the same entrypoint.sh
as the official image - so if
you are already using that one you should be able to use it exactly the same
way (if not - feel free to open an issue).
Deploy the image
Now - if you do not want to use kubernetes
, you can simply use the image
using docker
and expose the required Teamspeak
ports as you would with
docker
:
1docker run -p 9987:9987/udp -p 10011:10011 -p 30033:30033 -e TS3SERVER_LICENSE=accept monadt/teamspeak3-server
This way is a lot easier on the resources and will likely run more reliable on a Raspberry PI with < 2 GB of RAM.
Setup nginx-ingress
Get nginx-ingress to run on ARM
Setting up the nginx-ingress
on a cluster running on ARM
needs a few extra
steps when using the official documentation.
The images used in the manifests
are not compatible with armv7
(that is
used when running a cluster on a bunch of Raspberry Pis).
First the mandatory.yaml
has to be updated to use the images for the arm
architecture2:
1wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
2sed -i 's/nginx-ingress-controller:0/nginx-ingress-controller-arm:0/' mandatory.yaml
The resulting mandatory.yaml
file can now be applied to the cluster:
1kubectl apply -f mandatory.yaml
In my local cluster I am using the NodePort
approach, so the service for
that can be applied next:
1kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml
Setup a Teamspeak deployment
With all pieces in place the Teamspeak
container can now be deployed onto
the cluster:
Save the following yaml
into a file (e.g. teamspeak.yaml
).
1---
2apiVersion: v1
3kind: Namespace
4metadata:
5 name: teamspeak
6---
7apiVersion: v1
8kind: PersistentVolumeClaim
9metadata:
10 name: teamspeak-pvc
11 namespace: teamspeak
12spec:
13 accessModes:
14 - ReadWriteOnce
15 storageClassName: local-path
16 resources:
17 requests:
18 storage: 256Mi
19---
20apiVersion: apps/v1
21kind: Deployment
22metadata:
23 name: teamspeak-deployment
24 namespace: teamspeak
25 labels:
26 app: teamspeak
27spec:
28 replicas: 1
29 selector:
30 matchLabels:
31 app: teamspeak
32 template:
33 metadata:
34 namespace: teamspeak
35 labels:
36 app: teamspeak
37 spec:
38 containers:
39 - name: teamspeak-server
40 image: monadt/teamspeak3-server:3.11.0
41 ports:
42 - name: ts
43 containerPort: 9987
44 protocol: UDP
45 resources:
46 env:
47 - name: TS3SERVER_LICENSE
48 value: accept
49 volumeMounts:
50 - mountPath: /var/ts3server/
51 name: teamspeak-data
52 volumes:
53 - name: teamspeak-data
54 persistentVolumeClaim:
55 claimName: teamspeak-pvc
56---
57apiVersion: v1
58kind: Service
59metadata:
60 name: teamspeak-service
61 namespace: teamspeak
62 labels:
63 app: teamspeak
64spec:
65 type: ClusterIP
66 ports:
67 - port: 9987
68 targetPort: ts
69 protocol: UDP
70 name: ts
71 selector:
72 app: teamspeak
73---
74apiVersion: v1
75kind: ConfigMap
76metadata:
77 name: udp-services
78 namespace: ingress-nginx
79data:
80 9987: "teamspeak/teamspeak-service:9987"
Apply this using kubectl
:
1kubectl apply -f teamspeak.yaml
The 9987 udp
port will also need to be added to the ingress
service.
In the ports
section of the service add the following snippet:
1kubectl edit svc ingress-nginx -n ingress-nginx
1- name: teamspeak
2 port: 9987
3 protocol: UDP
4 targetPort: 9987
Forwarding traffic to the ingress
The final step depends a lot on the setup you are deploying the cluster in.
If it is behind your local router, you have to check which port was bound to
the 9987 udp
port and forward this to one of your cluster-nodes:
1kubectl describe svc ingress-nginx -n ingress-nginx
1Name: ingress-nginx
2Namespace: ingress-nginx
3Labels: app.kubernetes.io/name=ingress-nginx
4 app.kubernetes.io/part-of=ingress-nginx
5Annotations: Selector: app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx
6Type: NodePort
7IP: 10.43.33.70
8Port: http 80/TCP
9TargetPort: 80/TCP
10NodePort: http 32224/TCP
11Endpoints:
12Port: https 443/TCP
13TargetPort: 443/TCP
14NodePort: https 31955/TCP
15Endpoints:
16Port: teamspeak 9987/UDP
17TargetPort: 9987/UDP
18NodePort: teamspeak 31222/UDP
19Endpoints:
20Session Affinity: None
21External Traffic Policy: Cluster
22Events: <none>
In this case the port that needs to be forwarded is the 31222
port (the
NodePort
for the 9987 UDP
port).
-
For Ubuntu you will have to edit the file
/boot/firmware/cmdline.txt
and add the optionscgroup_memory=1 cgroup_enable=memory
at the end of the line fork3s
(orcontainers
in general) to work. ↩︎ -
See https://github.com/kubernetes/ingress-nginx/pull/3852 ↩︎