feat: deploy FarmOS Precision Agriculture Architecture on highest-storage node

This commit is contained in:
fchinembiri 2026-05-21 18:55:06 +02:00
parent ea69e01760
commit 6435130215
7 changed files with 484 additions and 0 deletions

20
k8s/argocd-farm.yaml Normal file
View File

@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: farm-platform
namespace: argocd
spec:
project: default
source:
repoURL: http://gitea.geocrop.svc.cluster.local:3000/fchinembiri/geocrop-platform..git
targetRevision: HEAD
path: k8s/farm
destination:
server: https://kubernetes.default.svc
namespace: farm
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@ -0,0 +1,24 @@
apiVersion: v1
kind: Namespace
metadata:
name: farm
---
apiVersion: v1
kind: Secret
metadata:
name: farm-db-credentials
namespace: farm
type: Opaque
data:
# Base64 encoded: farmos
POSTGRES_USER: ZmFybW9z
# Base64 encoded: f4rm0s_db_p4ssw0rd
POSTGRES_PASSWORD: ZjRybTBzX2RiX3A0c3N3MHJk
# Base64 encoded: farmos
POSTGRES_DB: ZmFybW9z
# Base64 encoded: timescale
TIMESCALE_USER: dGltZXNjYWxl
# Base64 encoded: t1m3sc4l3_db_p4ssw0rd
TIMESCALE_PASSWORD: dDFtM3NjNGwzX2RiX3A0c3N3MHJk
# Base64 encoded: sensors
TIMESCALE_DB: c2Vuc29ycw==

54
k8s/farm/02-storage.yaml Normal file
View File

@ -0,0 +1,54 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: farmos-sites-pvc
namespace: farm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgis-data-pvc
namespace: farm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: timescaledb-data-pvc
namespace: farm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nodered-data-pvc
namespace: farm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: grafana-data-pvc
namespace: farm
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi

141
k8s/farm/03-databases.yaml Normal file
View File

@ -0,0 +1,141 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgis
namespace: farm
spec:
serviceName: "postgis"
replicas: 1
selector:
matchLabels:
app: postgis
template:
metadata:
labels:
app: postgis
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vmi3045103.contaboserver.net
containers:
- name: postgis
image: postgis/postgis:14-3.3
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_DB
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: postgis-data-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgis
namespace: farm
spec:
ports:
- port: 5432
selector:
app: postgis
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: timescaledb
namespace: farm
spec:
serviceName: "timescaledb"
replicas: 1
selector:
matchLabels:
app: timescaledb
template:
metadata:
labels:
app: timescaledb
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vmi3045103.contaboserver.net
containers:
- name: timescaledb
image: timescale/timescaledb:latest-pg14
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: TIMESCALE_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: TIMESCALE_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: TIMESCALE_DB
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: timescaledb-data-pvc
---
apiVersion: v1
kind: Service
metadata:
name: timescaledb
namespace: farm
spec:
ports:
- port: 5432
selector:
app: timescaledb

185
k8s/farm/04-apps.yaml Normal file
View File

@ -0,0 +1,185 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: farmos
namespace: farm
spec:
replicas: 1
selector:
matchLabels:
app: farmos
template:
metadata:
labels:
app: farmos
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vmi3045103.contaboserver.net
containers:
- name: farmos
image: farmos/farmos:3.x
env:
- name: FARMOS_DB_TYPE
value: "pgsql"
- name: FARMOS_DB_HOST
value: "postgis"
- name: FARMOS_DB_PORT
value: "5432"
- name: FARMOS_DB_NAME
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_DB
- name: FARMOS_DB_USER
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_USER
- name: FARMOS_DB_PASS
valueFrom:
secretKeyRef:
name: farm-db-credentials
key: POSTGRES_PASSWORD
resources:
requests:
memory: "512Mi"
cpu: "200m"
limits:
memory: "1Gi"
volumeMounts:
- name: sites
mountPath: /opt/drupal/web/sites
volumes:
- name: sites
persistentVolumeClaim:
claimName: farmos-sites-pvc
---
apiVersion: v1
kind: Service
metadata:
name: farmos
namespace: farm
spec:
ports:
- port: 80
targetPort: 80
selector:
app: farmos
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodered
namespace: farm
spec:
replicas: 1
selector:
matchLabels:
app: nodered
template:
metadata:
labels:
app: nodered
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vmi3045103.contaboserver.net
containers:
- name: nodered
image: nodered/node-red:latest
ports:
- containerPort: 1880
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: nodered-data-pvc
---
apiVersion: v1
kind: Service
metadata:
name: nodered
namespace: farm
spec:
ports:
- port: 1880
selector:
app: nodered
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: farm
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vmi3045103.contaboserver.net
containers:
- name: grafana
image: grafana/grafana:latest
env:
- name: GF_SECURITY_ALLOW_EMBEDDING
value: "true"
ports:
- containerPort: 3000
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
volumeMounts:
- name: data
mountPath: /var/lib/grafana
volumes:
- name: data
persistentVolumeClaim:
claimName: grafana-data-pvc
---
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: farm
spec:
ports:
- port: 3000
selector:
app: grafana

51
k8s/farm/05-ingress.yaml Normal file
View File

@ -0,0 +1,51 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: farm-ingress
namespace: farm
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
spec:
ingressClassName: nginx
tls:
- hosts:
- farm.techarvest.co.zw
secretName: farmos-tls
- hosts:
- nodered.farm.techarvest.co.zw
secretName: nodered-tls
- hosts:
- grafana.farm.techarvest.co.zw
secretName: grafana-tls
rules:
- host: farm.techarvest.co.zw
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: farmos
port:
number: 80
- host: nodered.farm.techarvest.co.zw
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nodered
port:
number: 1880
- host: grafana.farm.techarvest.co.zw
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000

View File

@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- 01-namespace-secrets.yaml
- 02-storage.yaml
- 03-databases.yaml
- 04-apps.yaml
- 05-ingress.yaml