Merge pull request #1 from lcsnetworks/tactical-k8s

Add Kubernetes manifests for TRMM
This commit is contained in:
Dan 2022-01-03 08:58:32 -08:00 committed by GitHub
commit b5f906830b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 803 additions and 0 deletions

21
kubernetes/README.md Normal file
View File

@ -0,0 +1,21 @@
# TacticalRMM Kubernetes manifests
**Author:** [Joel DeTeves](https://github.com/joeldeteves)
**Desription:** TacticalRMM Kubernetes manifests tested & working on Digital Ocean managed Kubernetes (DOKS).
**Disclaimer:** _These manifests rely on an experimental developer images and as such are NOT SUPPORTED, at least until the required changes are merged into the main image. I have done my best to make them as secure as possible them however I am NOT responsible for anything that happens to you or your data as a result of using these files. Please do your due dilligence security-wise and open a Github issue if you wish to report a problem. USE AT YOUR OWN RISK. By using these files you agree that you are the sole entity responsible for any damages that may arise as a result._
# Pre-requisites
- A working Kubernetes cluster
- Kubernetes [NFS provisioner](https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner) or another storage provisioner that supports ```ReadWriteMany```
- [cert-manager](https://github.com/jetstack/cert-manager) or a Lets Encrypt cert issuer of your choice. Alternatively, you can mount your own certs as secret volumes into the pods
# Deploying the files
1. ```kubectl apply -f namespace.yaml```
2. ```kubectl apply -f .```
3. ```kubectl apply -f deployment/ -R```
# Questions / Concerns
Please open an issue in Github or you can also check in the [Tactical RMM Discord Channel](https://discord.gg/upGTkWp).
**Note: I am not affiliated with TRMM or AmidaWare; I am a community contributor. Please direct TRMM-related issues to the appropriate channels.**

15
kubernetes/certs.yaml Normal file
View File

@ -0,0 +1,15 @@
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: rmm-mydomain-com
namespace: tacticalrmm
spec:
secretName: rmm-mydomain-com-tls
commonName: rmm.mydomain.com
dnsNames:
- rmm.mydomain.com
- api.rmm.mydomain.com
- mesh.rmm.mydomain.com
issuerRef:
name: letsencrypt
kind: ClusterIssuer

View File

@ -0,0 +1,66 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-backend
name: tactical-backend
spec:
replicas: 1
selector:
matchLabels:
service: tactical-backend
strategy:
type: Recreate
template:
metadata:
labels:
network/api-db: "true"
network/redis: "true"
network/proxy: "true"
service: tactical-backend
spec:
containers:
- name: trmm-backend
image: tacticalrmm/tactical:0.10.5-dev
args:
- tactical-backend
resources: {}
env:
- name: CERT_PUB_PATH
value: /etc/ssl/certs/custom/tls.crt
- name: CERT_PRIV_PATH
value: /etc/ssl/certs/custom/tls.key
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
- mountPath: /etc/ssl/certs/custom
name: tactical-certs
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
- name: tactical-certs
secret:
secretName: rmm-mydomain-com-tls
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-backend
name: tactical-backend
spec:
ports:
- name: "http"
port: 80
targetPort: 80
- name: "https"
port: 443
targetPort: 443
selector:
service: tactical-backend

View File

@ -0,0 +1,81 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-celery
name: tactical-celery
spec:
replicas: 1
selector:
matchLabels:
service: tactical-celery
strategy:
type: Recreate
template:
metadata:
labels:
network/api-db: "true"
network/redis: "true"
service: tactical-celery
spec:
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: trmm-celery
image: tacticalrmm/tactical:0.10.5-dev
args:
- tactical-celery
resources: {}
env:
- name: CERT_PUB_PATH
value: /etc/ssl/certs/custom/tls.crt
- name: CERT_PRIV_PATH
value: /etc/ssl/certs/custom/tls.key
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-celerybeat
name: tactical-celerybeat
spec:
replicas: 1
selector:
matchLabels:
service: tactical-celerybeat
strategy:
type: Recreate
template:
metadata:
labels:
network/api-db: "true"
network/redis: "true"
service: tactical-celerybeat
spec:
containers:
- name: trmm-celerybeat
image: tacticalrmm/tactical:latest
args:
- tactical-celerybeat
resources: {}
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data

View File

@ -0,0 +1,46 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-frontend
name: tactical-frontend
spec:
replicas: 1
selector:
matchLabels:
service: tactical-frontend
strategy: {}
template:
metadata:
labels:
service: tactical-frontend
spec:
containers:
- name: trmm-frontend
image: tacticalrmm/tactical-frontend:latest
resources: {}
env:
- name: API_HOST
value: api.rmm.mydomain.com
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-frontend
name: tactical-frontend
spec:
ports:
- name: "http"
port: 80
targetPort: 80
- name: "https"
port: 443
targetPort: 443
selector:
service: tactical-frontend

View File

@ -0,0 +1,64 @@
apiVersion: v1
kind: Pod
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
network/api-db: "true"
network/proxy: "true"
service: tactical-init
name: tactical-init
spec:
containers:
- args:
- tactical-init
image: tacticalrmm/tactical:0.10.5-dev
name: trmm-init
env:
- name: API_HOST
value: api.rmm.mydomain.com
- name: APP_HOST
value: rmm.mydomain.com
- name: MESH_HOST
value: mesh.rmm.mydomain.com
- name: MESH_WS_URL
value: ws://tactical-meshcentral:443
- name: MESH_USER
value: meshuser
- name: POSTGRES_HOST
value: 10.137.88.210
- name: POSTGRES_PASS
valueFrom:
secretKeyRef:
name: tactical-secrets
key: postgres-password
- name: POSTGRES_USER
value: tacticalrmm
- name: POSTGRES_DB
value: tacticalrmm
- name: TRMM_PASS
valueFrom:
secretKeyRef:
name: tactical-secrets
key: trmm-password
- name: TRMM_USER
value: tacticalrmm
- name: CERT_PUB_PATH
value: /etc/ssl/certs/custom/tls.crt
- name: CERT_PRIV_PATH
value: /etc/ssl/certs/custom/tls.key
resources: {}
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
- mountPath: /etc/ssl/certs/custom
name: tactical-certs
restartPolicy: OnFailure
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
- name: tactical-certs
secret:
secretName: rmm-mydomain-com-tls
status: {}

View File

@ -0,0 +1,81 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-meshcentral
name: tactical-meshcentral
spec:
replicas: 1
selector:
matchLabels:
service: tactical-meshcentral
strategy:
type: Recreate
template:
metadata:
labels:
network/mesh-db: "true"
network/proxy: "true"
service: tactical-meshcentral
spec:
containers:
- name: trmm-meshcentral
image: tacticalrmm/tactical-meshcentral:0.10.5-dev
resources: {}
env:
- name: MESH_HOST
value: mesh.rmm.mydomain.com
- name: MESH_USER
value: meshuser
- name: MESH_PASS
valueFrom:
secretKeyRef:
name: tactical-secrets
key: mesh-password
- name: MESH_PERSISTENT_CONFIG
value: "0"
- name: MONGODB_USER
value: mongodbuser
- name: MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: tactical-secrets
key: mongodb-password
- name: NGINX_HOST_IP # Point to NGINX service
value: tactical-nlb
- name: WS_MASK_OVERRIDE # Enable for Traefik compatibility
value: "0"
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
- mountPath: /home/node/app/meshcentral-data
name: mesh-data
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
- name: mesh-data
persistentVolumeClaim:
claimName: mesh-data
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-meshcentral
name: tactical-meshcentral
spec:
ports:
- name: "http"
port: 80
targetPort: 80
- name: "https"
port: 443
targetPort: 443
selector:
service: tactical-meshcentral

View File

@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-mongodb
name: tactical-mongodb
spec:
replicas: 1
selector:
matchLabels:
service: tactical-mongodb
strategy:
type: Recreate
template:
metadata:
labels:
network/mesh-db: "true"
service: tactical-mongodb
spec:
securityContext:
runAsUser: 2000
fsGroup: 2000
containers:
- name: trmm-mongodb
image: mongo:4.4
resources: {}
env:
- name: MONGO_INITDB_DATABASE
value: meshcentral
- name: MONGO_INITDB_ROOT_USERNAME
value: mongodbuser
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: tactical-secrets
key: mongodb-password
volumeMounts:
- mountPath: /data/db
name: mongo-data
restartPolicy: Always
volumes:
- name: mongo-data
persistentVolumeClaim:
claimName: mongo-data
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-mongodb
name: tactical-mongodb
spec:
ports:
- name: "27017"
port: 27017
targetPort: 27017
selector:
service: tactical-mongodb

View File

@ -0,0 +1,56 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-redis
name: tactical-redis
spec:
replicas: 1
selector:
matchLabels:
service: tactical-redis
strategy:
type: Recreate
template:
metadata:
labels:
network/redis: "true"
service: tactical-redis
spec:
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: trmm-redis
image: redis:6.0-alpine
args:
- redis-server
- --appendonly
- "yes"
resources: {}
volumeMounts:
- mountPath: /data
name: redis-data
restartPolicy: Always
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-data
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-redis
name: tactical-redis
spec:
ports:
- name: "6379"
port: 6379
targetPort: 6379
selector:
service: tactical-redis

View File

@ -0,0 +1,16 @@
# CAUTION: THIS FILE IS FOR DEMONSTRATION PURPOSES ONLY
# DO NOT UPLOAD SECRETS TO YOUR GIT REPOSITORY !!!!
# Secrets must be encoded using base64 (ensure there is no newline at the end of the file):
# echo -n 'mysupersecretpassword' | base64 -w0
apiVersion: v1
kind: Secret
metadata:
name: tactical-secrets
namespace: tacticalrmm
data:
# Default password: changeme
trmm-password: Y2hhbmdlbWU=
mesh-password: Y2hhbmdlbWU=
mongodb-password: Y2hhbmdlbWU=
postgres-password: Y2hhbmdlbWU=

View File

@ -0,0 +1,76 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-nlb
name: tactical-web
spec:
replicas: 1
selector:
matchLabels:
service: tactical-nlb
strategy:
type: Recreate
template:
metadata:
labels:
network/proxy: "true"
service: tactical-nlb
spec:
containers:
- name: nginx
image: tacticalrmm/tactical-nginx:0.10.5-dev
resources: {}
env:
- name: API_HOST
value: api.rmm.mydomain.com
- name: APP_HOST
value: rmm.mydomain.com
- name: MESH_HOST
value: mesh.rmm.mydomain.com
- name: NGINX_RESOLVER
value: kube-dns.kube-system.svc.cluster.local
- name: BACKEND_SERVICE
value: tactical-backend.tacticalrmm.svc.cluster.local
- name: FRONTEND_SERVICE
value: tactical-frontend.tacticalrmm.svc.cluster.local
- name: MESH_SERVICE
value: tactical-meshcentral.tacticalrmm.svc.cluster.local
- name: WEBSOCKETS_SERVICE
value: tactical-websockets.tacticalrmm.svc.cluster.local
- name: CERT_PUB_PATH
value: /etc/ssl/certs/custom/tls.crt
- name: CERT_PRIV_PATH
value: /etc/ssl/certs/custom/tls.key
ports:
- containerPort: 80
- containerPort: 443
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
- mountPath: /etc/ssl/certs/custom
name: tactical-certs
- name: trmm-nats
image: tacticalrmm/tactical-nats:latest
resources: {}
env:
- name: API_HOST
value: api.rmm.mydomain.com
ports:
- containerPort: 4222
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
- mountPath: /etc/ssl/certs/custom
name: tactical-certs
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
- name: tactical-certs
secret:
secretName: rmm-mydomain-com-tls
status: {}

View File

@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-websockets
name: tactical-websockets
spec:
replicas: 1
selector:
matchLabels:
service: tactical-websockets
strategy:
type: Recreate
template:
metadata:
labels:
network/api-db: "true"
network/redis: "true"
network/proxy: "true"
service: tactical-websockets
spec:
securityContext:
runAsUser: 1000
fsGroup: 1000
containers:
- name: trmm-websockets
image: tacticalrmm/tactical:latest
args:
- tactical-websockets
resources: {}
volumeMounts:
- mountPath: /opt/tactical
name: tactical-data
restartPolicy: Always
volumes:
- name: tactical-data
persistentVolumeClaim:
claimName: tactical-data
---
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-websockets
name: tactical-websockets
spec:
ports:
- name: "http"
port: 80
targetPort: 80
- name: "https"
port: 443
targetPort: 443
- name: "8383"
port: 8383
targetPort: 8383
selector:
service: tactical-websockets

View File

@ -0,0 +1,7 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: tacticalrmm
labels:
app: tacticalrmm

View File

@ -0,0 +1,61 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: proxy
spec:
ingress:
- {}
podSelector:
matchLabels:
network/proxy: "true"
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-db
namespace: tacticalrmm
spec:
ingress:
- from:
- podSelector:
matchLabels:
network/api-db: "true"
- podSelector:
matchLabels:
network/proxy: "true"
podSelector:
matchLabels:
network/api-db: "true"
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mesh-db
namespace: tacticalrmm
spec:
ingress:
- from:
- podSelector:
matchLabels:
network/mesh-db: "true"
- podSelector:
matchLabels:
network/proxy: "true"
podSelector:
matchLabels:
network/mesh-db: "true"
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: redis
namespace: tacticalrmm
spec:
ingress:
- from:
- podSelector:
matchLabels:
network/redis: "true"
podSelector:
matchLabels:
network/redis: "true"

20
kubernetes/nlb.yaml Normal file
View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-nlb
name: tactical-nlb
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: "http"
port: 80
- name: "https"
port: 443
- name: "nats"
port: 4222
selector:
service: tactical-nlb

69
kubernetes/pvc.yaml Normal file
View File

@ -0,0 +1,69 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: tactical-data
namespace: tacticalrmm
labels:
app: tacticalrmm
service: tactical-data
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client
resources:
requests:
storage: 200Mi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mesh-data
namespace: tacticalrmm
labels:
app: tacticalrmm
service: mesh-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-data
namespace: tacticalrmm
labels:
app: tacticalrmm
service: mongo-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
status: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data
namespace: tacticalrmm
labels:
app: tacticalrmm
service: redis-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
status: {}