mirror of
https://github.com/opf/openproject-deploy.git
synced 2026-02-14 16:59:51 +00:00
kubernetes setup (#24)
This commit is contained in:
13
kubernetes/01-backend-networkpolicy.yaml
Executable file
13
kubernetes/01-backend-networkpolicy.yaml
Executable file
@@ -0,0 +1,13 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: backend
|
||||
spec:
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
openproject.network/backend: "true"
|
||||
podSelector:
|
||||
matchLabels:
|
||||
openproject.network/backend: "true"
|
||||
13
kubernetes/01-frontend-networkpolicy.yaml
Executable file
13
kubernetes/01-frontend-networkpolicy.yaml
Executable file
@@ -0,0 +1,13 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: frontend
|
||||
spec:
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
openproject.network/frontend: "true"
|
||||
podSelector:
|
||||
matchLabels:
|
||||
openproject.network/frontend: "true"
|
||||
14
kubernetes/01-opdata-persistentvolumeclaim.yaml
Executable file
14
kubernetes/01-opdata-persistentvolumeclaim.yaml
Executable file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
openproject.service: opdata
|
||||
name: opdata
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
status: {}
|
||||
14
kubernetes/01-pgdata-persistentvolumeclaim.yaml
Executable file
14
kubernetes/01-pgdata-persistentvolumeclaim.yaml
Executable file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
openproject.service: pgdata
|
||||
name: pgdata
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
status: {}
|
||||
24
kubernetes/02-cache-deployment.yaml
Executable file
24
kubernetes/02-cache-deployment.yaml
Executable file
@@ -0,0 +1,24 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: cache
|
||||
name: cache
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: cache
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.service: cache
|
||||
spec:
|
||||
containers:
|
||||
- image: memcached
|
||||
name: cache
|
||||
resources: {}
|
||||
restartPolicy: Always
|
||||
status: {}
|
||||
41
kubernetes/02-db-deployment.yaml
Executable file
41
kubernetes/02-db-deployment.yaml
Executable file
@@ -0,0 +1,41 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: db
|
||||
name: db
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: db
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.service: db
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
- name: POSTGRES_DB
|
||||
value: openproject
|
||||
- name: POSTGRES_PASSWORD
|
||||
value: p4ssw0rd
|
||||
image: postgres:13
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
name: psql
|
||||
name: db
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/postgresql/data
|
||||
name: pgdata
|
||||
restartPolicy: Always
|
||||
terminationGracePeriodSeconds: 3
|
||||
volumes:
|
||||
- name: pgdata
|
||||
persistentVolumeClaim:
|
||||
claimName: pgdata
|
||||
status: {}
|
||||
15
kubernetes/03-cache-service.yaml
Executable file
15
kubernetes/03-cache-service.yaml
Executable file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: cache
|
||||
labels:
|
||||
openproject.service: cache
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
openproject.service: cache
|
||||
ports:
|
||||
- name: cache
|
||||
protocol: TCP
|
||||
port: 11211
|
||||
targetPort: 11211
|
||||
15
kubernetes/03-db-service.yaml
Executable file
15
kubernetes/03-db-service.yaml
Executable file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: db
|
||||
labels:
|
||||
openproject.service: db
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
openproject.service: db
|
||||
ports:
|
||||
- name: db
|
||||
protocol: TCP
|
||||
port: 5432
|
||||
targetPort: 5432
|
||||
37
kubernetes/04-seeder-pod.yaml
Executable file
37
kubernetes/04-seeder-pod.yaml
Executable file
@@ -0,0 +1,37 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.service: seeder
|
||||
name: seeder
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- ./docker/prod/seeder
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: postgres://postgres:p4ssw0rd@$(DB_SERVICE_HOST):$(DB_SERVICE_PORT)/openproject?pool=20&encoding=unicode&reconnect=true
|
||||
- name: IMAP_ENABLED
|
||||
value: "false"
|
||||
- name: OPENPROJECT_CACHE__MEMCACHE__SERVER
|
||||
value: $(CACHE_SERVICE_HOST):$(CACHE_SERVICE_PORT)
|
||||
- name: OPENPROJECT_RAILS__RELATIVE__URL__ROOT
|
||||
- name: RAILS_CACHE_STORE
|
||||
value: memcache
|
||||
- name: RAILS_MAX_THREADS
|
||||
value: "16"
|
||||
- name: RAILS_MIN_THREADS
|
||||
value: "4"
|
||||
image: openproject/community:12
|
||||
name: seeder
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/openproject/assets
|
||||
name: opdata
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: opdata
|
||||
persistentVolumeClaim:
|
||||
claimName: opdata
|
||||
status: {}
|
||||
48
kubernetes/05-cron-deployment.yaml
Executable file
48
kubernetes/05-cron-deployment.yaml
Executable file
@@ -0,0 +1,48 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: cron
|
||||
name: cron
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: cron
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.service: cron
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- ./docker/prod/cron
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: postgres://postgres:p4ssw0rd@db/openproject?pool=20&encoding=unicode&reconnect=true
|
||||
- name: IMAP_ENABLED
|
||||
value: "false"
|
||||
- name: OPENPROJECT_CACHE__MEMCACHE__SERVER
|
||||
value: cache:11211
|
||||
- name: OPENPROJECT_RAILS__RELATIVE__URL__ROOT
|
||||
- name: RAILS_CACHE_STORE
|
||||
value: memcache
|
||||
- name: RAILS_MAX_THREADS
|
||||
value: "16"
|
||||
- name: RAILS_MIN_THREADS
|
||||
value: "4"
|
||||
image: openproject/community:12
|
||||
name: cron
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/openproject/assets
|
||||
name: opdata
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: opdata
|
||||
persistentVolumeClaim:
|
||||
claimName: opdata
|
||||
status: {}
|
||||
62
kubernetes/05-web-deployment.yaml
Executable file
62
kubernetes/05-web-deployment.yaml
Executable file
@@ -0,0 +1,62 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: web
|
||||
name: web
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: web
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.network/frontend: "true"
|
||||
openproject.service: web
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- ./docker/prod/web
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: postgres://postgres:p4ssw0rd@$(DB_SERVICE_HOST):$(DB_SERVICE_PORT)/openproject?pool=20&encoding=unicode&reconnect=true
|
||||
- name: IMAP_ENABLED
|
||||
value: "false"
|
||||
- name: OPENPROJECT_CACHE__MEMCACHE__SERVER
|
||||
value: $(CACHE_SERVICE_HOST):$(CACHE_SERVICE_PORT)
|
||||
- name: OPENPROJECT_RAILS__RELATIVE__URL__ROOT
|
||||
- name: RAILS_CACHE_STORE
|
||||
value: memcache
|
||||
- name: RAILS_MAX_THREADS
|
||||
value: "16"
|
||||
- name: RAILS_MIN_THREADS
|
||||
value: "4"
|
||||
image: openproject/community:12
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- curl
|
||||
- -f
|
||||
- http://localhost:8080/health_checks/default
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
name: web
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/openproject/assets
|
||||
name: opdata
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: opdata
|
||||
persistentVolumeClaim:
|
||||
claimName: opdata
|
||||
status: {}
|
||||
48
kubernetes/05-worker-deployment.yaml
Executable file
48
kubernetes/05-worker-deployment.yaml
Executable file
@@ -0,0 +1,48 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: worker
|
||||
name: worker
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: worker
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/backend: "true"
|
||||
openproject.service: worker
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- ./docker/prod/worker
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
value: postgres://postgres:p4ssw0rd@$(DB_SERVICE_HOST):$(DB_SERVICE_PORT)/openproject?pool=20&encoding=unicode&reconnect=true
|
||||
- name: IMAP_ENABLED
|
||||
value: "false"
|
||||
- name: OPENPROJECT_CACHE__MEMCACHE__SERVER
|
||||
value: $(CACHE_SERVICE_HOST):$(CACHE_SERVICE_PORT)
|
||||
- name: OPENPROJECT_RAILS__RELATIVE__URL__ROOT
|
||||
- name: RAILS_CACHE_STORE
|
||||
value: memcache
|
||||
- name: RAILS_MAX_THREADS
|
||||
value: "16"
|
||||
- name: RAILS_MIN_THREADS
|
||||
value: "4"
|
||||
image: openproject/community:12
|
||||
name: worker
|
||||
resources: {}
|
||||
volumeMounts:
|
||||
- mountPath: /var/openproject/assets
|
||||
name: opdata
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: opdata
|
||||
persistentVolumeClaim:
|
||||
claimName: opdata
|
||||
status: {}
|
||||
15
kubernetes/06-web-service.yaml
Executable file
15
kubernetes/06-web-service.yaml
Executable file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web
|
||||
labels:
|
||||
openproject.service: web
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
openproject.service: web
|
||||
ports:
|
||||
- name: web
|
||||
protocol: TCP
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
32
kubernetes/07-proxy-deployment.yaml
Executable file
32
kubernetes/07-proxy-deployment.yaml
Executable file
@@ -0,0 +1,32 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: proxy
|
||||
name: proxy
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
openproject.service: proxy
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
openproject.network/frontend: "true"
|
||||
openproject.service: proxy
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- ./docker/prod/proxy
|
||||
env:
|
||||
- name: APP_HOST
|
||||
value: $(WEB_SERVICE_HOST)
|
||||
- name: OPENPROJECT_RAILS__RELATIVE__URL__ROOT
|
||||
image: openproject/community:12
|
||||
name: proxy
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources: {}
|
||||
restartPolicy: Always
|
||||
status: {}
|
||||
14
kubernetes/08-proxy-service.yaml
Executable file
14
kubernetes/08-proxy-service.yaml
Executable file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
openproject.service: proxy
|
||||
name: proxy
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
openproject.service: proxy
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
17
kubernetes/09-proxy-ingress.yaml
Executable file
17
kubernetes/09-proxy-ingress.yaml
Executable file
@@ -0,0 +1,17 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: proxy-ingress
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: k8s.openproject-dev.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: proxy
|
||||
port:
|
||||
number: 80
|
||||
65
kubernetes/README.md
Normal file
65
kubernetes/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# OpenProject installation using Kubernetes
|
||||
|
||||
This is an example setup of OpenProject on Kubernetes.
|
||||
|
||||
## Install
|
||||
|
||||
Clone this repository:
|
||||
|
||||
```
|
||||
git clone https://github.com/opf/openproject-deploy --depth=1 --branch=stable/12 openproject
|
||||
```
|
||||
|
||||
Go to the compose folder:
|
||||
|
||||
```
|
||||
cd openproject/kubernetes
|
||||
```
|
||||
|
||||
Adjust the host name for the ingress in [09-proxy-ingress.yaml](./09-proxy-ingress.yaml).
|
||||
The default value `k8s.openproject-dev.com` simply points to `127.0.0.1`.
|
||||
You will have to insert the actual host name here and set up the DNS so that it points to the cluster IP.
|
||||
|
||||
Next, apply the definitions:
|
||||
|
||||
```
|
||||
kubectl apply -f .
|
||||
```
|
||||
|
||||
## Ingress
|
||||
|
||||
For the ingress to work you will need to enable an ingress addon in your cluster.
|
||||
|
||||
If you already have a load balancer you want to use to expose the service,
|
||||
simply delete [09-proxy-ingress.yaml](./09-proxy-ingress.yaml) and integrate
|
||||
the [proxy service](./08-proxy-service.yaml) in your existing ingress or load balancer.
|
||||
|
||||
## SSL Termination
|
||||
|
||||
This setup does not include SSL termination.
|
||||
The ingress simply listens on port 80 and serves HTTP requests.
|
||||
|
||||
You will have to set up HTTPS yourself.
|
||||
You can find more information on this in the [kubernetes docs](https://kubernetes.github.io/ingress-nginx/user-guide/tls/).
|
||||
|
||||
## Scaling
|
||||
|
||||
You can adjust the `replica` specs in the [web](./05-web-deployment.yaml) and [worker](./05-worker-deployment.yaml) deployments
|
||||
to scale up the respective processes.
|
||||
|
||||
## TROUBLESHOOTING
|
||||
|
||||
### The **db** deployment fails due to the data directory not being empty
|
||||
|
||||
This can happen if your cluster creates the `opdata` PVC (persistent volume claims) with an ext4 file system
|
||||
which will automatically have a `lost+found` folder.
|
||||
|
||||
To fix the issue you can add the following to the [db-deployment](./02-db-deployment.yaml)'s env next to
|
||||
`POSTGRES_USER` and `POSTGRES_PASSWORD`:
|
||||
|
||||
```
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
```
|
||||
|
||||
This makes the postgres container use a subfolder of the mount path (`/var/lib/postgresql/data`) as the data directory.
|
||||
Reference in New Issue
Block a user