diff --git a/README.md b/README.md index 098bad75..becb2dbf 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This projects provides a highly opinionated way to develop Odoo modules. It feat * **Odoo Scripts**: Develope scripts to patch Odoo code. * **Odoo Revisions**: Snapshot the Odoo source at a specific date. See [revisions](./revisions.md) for details. * **Odoo Image**: Build and publish a custom Odoo Docker image. See [README](./build/README.md) for details. -* **Kubernetes**: Deploy Odoo and Postgres to a Kubernetes cluster. +* **Kubernetes**: Deploy Odoo and Postgres to a minikube cluster. * **Develop Modules**: Scaffold a new module, develop new Odoo features locally and [much more](./task.md). * **Credentials**: Setup credentials to log into Odoo. * **Import Data**: Import Odoo records from CSV. @@ -34,6 +34,8 @@ The Odoo development environment has the following requirements: You can also use [Nix](https://nixos.org/) to setup the development requirements. +To test Kubernetes deployments for Odoo install [minikube](https://minikube.sigs.k8s.io/docs/) and [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl). + ## Usage The usage section is a set of workflows. See `task help` or [task](./task.md) for details about the project commands. @@ -216,7 +218,7 @@ task stop task drop-db ``` -### Define Postgres image version +#### Define Postgres image version Define the Postgres image in your `.env` file: @@ -224,7 +226,7 @@ Define the Postgres image in your `.env` file: POSTGRES_IMAGE=postgres:12-alpine ``` -### Build Odoo image +#### Build Odoo image To build the Docker image setup these `.env` vars: @@ -251,7 +253,7 @@ Publish the Odoo image. task publish ``` -### Mail catcher +#### Mail catcher Start mail server. @@ -265,6 +267,28 @@ Setup mail server config for Odoo. task setup-mail ``` +### Kubernetes + +Run a local Kubernets cluster with minikube. + +#### Start minikube + +Ensure you have `minikube` installed. + +```bash +task start-minikube +``` + +#### Deploy Odoo to minikube + +Ensure you have `kubectl` installed and can access the cluster. + +The following command applies the Odoo and Postgres manifests and initializes the Odoo database. + +```bash +task init-minikube +``` + ## Troubleshooting ### Remove tracked submodule folders diff --git a/k8s/odoo-cm.yaml b/k8s/odoo-cm.yaml new file mode 100644 index 00000000..0818c27f --- /dev/null +++ b/k8s/odoo-cm.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: odoo-config + labels: + app: odoo +data: + HOST: postgres + USER: odoo + PASSWORD: odoo diff --git a/k8s/odoo-svc.yaml b/k8s/odoo-svc.yaml new file mode 100644 index 00000000..9a192832 --- /dev/null +++ b/k8s/odoo-svc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: odoo +spec: + type: NodePort + selector: + app: odoo + ports: + - protocol: TCP + port: 8069 + targetPort: 8069 + nodePort: 31945 \ No newline at end of file diff --git a/k8s/odoo17-deploy.yaml b/k8s/odoo17-deploy.yaml new file mode 100644 index 00000000..ad7451c5 --- /dev/null +++ b/k8s/odoo17-deploy.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: odoo + labels: + app: odoo +spec: + replicas: 1 + selector: + matchLabels: + app: odoo + template: + metadata: + labels: + app: odoo + spec: + containers: + - name: odoo + image: odoo:16 + ports: + - containerPort: 8069 + envFrom: + - configMapRef: + name: odoo-config \ No newline at end of file diff --git a/k8s/postgres-cm.yaml b/k8s/postgres-cm.yaml new file mode 100644 index 00000000..34174b40 --- /dev/null +++ b/k8s/postgres-cm.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-config + labels: + app: postgres +data: + POSTGRES_DB: odoo + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoo \ No newline at end of file diff --git a/k8s/postgres-deploy.yaml b/k8s/postgres-deploy.yaml new file mode 100644 index 00000000..3f0c9263 --- /dev/null +++ b/k8s/postgres-deploy.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres # Sets Deployment name +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:16 # Sets Image + ports: + - containerPort: 5432 # Exposes container port + envFrom: + - configMapRef: + name: postgres-config + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgredb + volumes: + - name: postgredb + persistentVolumeClaim: + claimName: postgresql-data-claim \ No newline at end of file diff --git a/k8s/postgres-pvc.yaml b/k8s/postgres-pvc.yaml new file mode 100644 index 00000000..383d7a0d --- /dev/null +++ b/k8s/postgres-pvc.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: PersistentVolumeClaim # Create PVC +metadata: + name: postgresql-data-claim # Sets name of PV +spec: + storageClassName: manual + accessModes: + - ReadWriteMany # Sets read and write access + resources: + requests: + storage: 10Gi # Sets volume size +--- +apiVersion: v1 +kind: PersistentVolume # Create a PV +metadata: + name: postgresql-data # Sets PV's name + labels: + type: local # Sets PV's type to local +spec: + storageClassName: manual + capacity: + storage: 10Gi # Sets PV Volume + accessModes: + - ReadWriteMany + hostPath: + path: "/data/volume" # Sets the volume's path \ No newline at end of file diff --git a/k8s/postgres-svc.yaml b/k8s/postgres-svc.yaml new file mode 100644 index 00000000..edcca54d --- /dev/null +++ b/k8s/postgres-svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres # Sets service name + labels: + app: postgres # Labels and Selectors +spec: + type: NodePort # Sets service type + ports: + - port: 5432 # Sets port to run the postgres application + selector: + app: postgres \ No newline at end of file diff --git a/k8s/postgres.yml b/k8s/postgres.yml deleted file mode 100644 index 4ab7b580..00000000 --- a/k8s/postgres.yml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: postgres-pv-claim -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres - labels: - app: postgres -spec: - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: postgres:latest - env: - - name: POSTGRES_DB - value: odoo - - name: POSTGRES_USER - value: odoo - - name: POSTGRES_PASSWORD - value: odoo - ports: - - containerPort: 5432 - volumeMounts: - - mountPath: /var/lib/postgresql/data - name: postgres-storage - volumes: - - name: postgres-storage - persistentVolumeClaim: - claimName: postgres-pv-claim diff --git a/task b/task index 8f502d75..e90c6071 100755 --- a/task +++ b/task @@ -46,6 +46,7 @@ function help-table() { printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "import-csv" "[db][path]" "Import data from csv. Filename must match PostgreSQL table name." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "info" "" "Show values of project env vars." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "init-db" "[db]" "Initialize the Odoo database. Default is branch name." + printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "init-minikube" "" "Deploy the Odoo K8s manifets." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "init-nextcloud-env" "[env]" "Create env file for Nextcloud instance." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "init-odoo-env" "[env]" "Create env file for Odoo Instance." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "init-venv" "" "Initialize python virtual env." @@ -81,6 +82,7 @@ function help-table() { printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "set-admin" "[db]" "Sets the password for the first user in database. Default is branch name." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "source" "" "Source the Python virtual env." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "start" "[name][db]" "Start docker container. Options: none, db, admin, odoo, native, mail." + printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "start-minikube" "" "Start minikube Kubernetes cluster." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "start-psql" "[db]" "Start PSQL shell in Docker container. Default is branch name." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "start-shell" "[db]" "Start Odoo shell from source folder. Default is branch name." printf "| %-${cmd_width}s | %-${opt_width}s | %-${desc_width}s |\n" "stop" "[name]" "Stop docker containers." @@ -449,6 +451,11 @@ function start() { fi } +function start-minikube() { + echo "Start minikube." + minikube start +} + function deploy() { if [[ "$1" =~ "db" ]]; then kubectl apply -f k3s/postgres.yml @@ -532,6 +539,26 @@ function start-psql() { docker exec -it db psql "postgres://odoo:odoo@localhost:5432/$DATABASE" } +function init-minikube() { + echo "Deploy Postgres:" + kubectl apply -f k8s/postgres-cm.yaml + kubectl apply -f k8s/postgres-pvc.yaml + kubectl apply -f k8s/postgres-deploy.yaml + kubectl apply -f k8s/postgres-svc.yaml + + echo "Deploy Odoo:" + kubectl apply -f k8s/odoo-cm.yaml + kubectl apply -f k8s/odoo17-deploy.yaml + kubectl apply -f k8s/odoo-svc.yaml + + echo "Init Odoo database:" + ODOO_POD=$(kubectl get pods -o=name --all-namespaces | grep odoo) + kubectl exec "$ODOO_POD" -- env + kubectl exec "$ODOO_POD" -- /bin/bash -c "odoo -d odoo -i web --db_host \$HOST -r\$USER -w\$PASSWORD --stop-after-init --no-http" + + echo "Access Odoo with: $(minikube service odoo --url)" +} + function init-db() { DATABASE="$1" if [ -z "$DATABASE" ]; then @@ -1571,6 +1598,9 @@ case "$1" in init-db) init-db "$2" ;; + init-minikube) + init-minikube + ;; init-nextcloud-env) init-nextcloud-env "$2" ;; @@ -1677,6 +1707,9 @@ case "$1" in source) activate-venv ;; + start-minikube) + start-minikube + ;; start-psql) start-psql "$2" ;;