diff --git a/helm-deployment.sh b/helm-deployment.sh new file mode 100644 index 000000000..f1632a439 --- /dev/null +++ b/helm-deployment.sh @@ -0,0 +1,23 @@ +set -e + +NAMESPACE="k8s-namespace" +CHART_DIR="./k8s-deployment" + +echo "Checking Kubernetes connection..." +kubectl cluster-info > /dev/null + +echo "Creating namespace if not exists..." +kubectl get namespace $NAMESPACE >/dev/null 2>&1 || \ +kubectl create namespace $NAMESPACE + +echo "Installing Helm chart..." +helm upgrade --install $NAMESPACE $CHART_DIR \ + --namespace $NAMESPACE \ + -f $CHART_DIR/values.yaml \ + -f $CHART_DIR/secrets.yaml + +echo "Deployment status:" +kubectl get pods -n $NAMESPACE +kubectl get svc -n $NAMESPACE + +echo "CMF deployed successfully." diff --git a/kubernetes/.helmignore b/kubernetes/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/kubernetes/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/kubernetes/Chart.yaml b/kubernetes/Chart.yaml new file mode 100644 index 000000000..0ab4c92de --- /dev/null +++ b/kubernetes/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: cmf-deployment +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/kubernetes/INSTALLATION.md b/kubernetes/INSTALLATION.md new file mode 100644 index 000000000..e075c3ed1 --- /dev/null +++ b/kubernetes/INSTALLATION.md @@ -0,0 +1,400 @@ +# CMF Kubernetes Deployment Installation Guide + +This guide provides step-by-step instructions to deploy the Common Metadata Framework (CMF) on Kubernetes using Helm. + +## Table of Contents +- [Prerequisites](#prerequisites) +- [Architecture Overview](#architecture-overview) +- [Building Docker Images](#building-docker-images) +- [Configuration](#configuration) +- [Deployment Steps](#deployment-steps) +- [Verification](#verification) +- [Accessing Services](#accessing-services) +- [Uninstallation](#uninstallation) + +--- + +## Prerequisites + +Before starting the installation, ensure you have: + +1. **Kubernetes Cluster** (v1.19+) + - Minikube, kind, or a cloud-based cluster (EKS, GKE, AKS) + - Verify: `kubectl cluster-info` + +2. **Helm** (v3.0+) + - Install from: https://helm.sh/docs/intro/install/ + - Verify: `helm version` + +3. **Docker** or **Podman** (for building images) + - Verify: `docker version` or `podman version` + +4. **kubectl** configured to access your cluster + - Verify: `kubectl get nodes` + +5. **Storage provisioner** (for persistent volumes) + - For Minikube: enabled by default + - For cloud providers: ensure default storage class exists + - Verify: `kubectl get storageclass` + +--- + +## Architecture Overview + +The CMF deployment consists of the following components: + +- **CMF Server**: Backend API server for metadata management +- **UI**: React-based web interface +- **PostgreSQL**: Metadata database +- **Neo4j**: Graph database for metadata relationships +- **Nginx**: Reverse proxy and load balancer +- **TensorBoard** (optional): ML experiment visualization + +--- + +## Building Docker Images + +### 1. Build CMF Server Image + +```bash +# Navigate to the repository root +cd /home/user_name/testing/deployment_k8s + +# Build the CMF server image +docker build -f server/Dockerfile -t cmf-server:latest . + +# Tag for your registry (replace with your registry URL) +docker tag cmf-server:latest /cmf-server:latest + +# Push to registry +docker push /cmf-server:latest +``` + +**Alternative for Minikube:** +```bash +# Use Minikube's Docker daemon to avoid pushing to external registry +eval $(minikube docker-env) +docker build -f server/Dockerfile -t cmf-server:latest . +``` + +### 2. Build UI Image + +```bash +# Build the UI image +docker build -f ui/Dockerfile -t cmf-ui:latest ./ui + +# Tag for your registry +docker tag cmf-ui:latest /cmf-ui:latest + +# Push to registry +docker push /cmf-ui:latest +``` + +**Alternative for Minikube:** +```bash +eval $(minikube docker-env) +docker build -f ui/Dockerfile -t cmf-ui:latest ./ui +``` + +### 3. Third-Party Images + +The following images are pulled from public registries automatically: +- **Neo4j**: `neo4j:latest` +- **PostgreSQL**: `postgres:13` +- **Nginx**: `nginx:alpine` +- **TensorBoard**: `tensorflow/tensorflow:latest` + +--- + +## Configuration + +### 1. Update values.yaml + +Edit `k8s-deployment/values.yaml` to configure your deployment: + +```bash +vi k8s-deployment/values.yaml +``` + +**Key configurations to update:** + +```yaml +# Update the CMF server image repository +cmf_service: + image: + repository: "/cmf-server" # Replace with your image name + tag: latest + +# Update storage class if needed (leave empty for static PV binding) +storage: + storageClassName: "" # or "standard", "gp2", etc. + +# Configure service types based on your cluster +service: + type: NodePort # or LoadBalancer, ClusterIP + +# Neo4j authentication +neo4j_service: + neo4jAuth: "neo4j/test1234" # Change password for production + +# Database configuration +common_env: + POSTGRES_HOST: "postgres" + POSTGRES_DB: "mlmd" + POSTGRES_PORT: "5432" +``` + +### 2. Configure Secrets + +Edit `k8s-deployment/secrets.yaml` with your database credentials: + +```bash +vi k8s-deployment/secrets.yaml +``` + +**Update the following:** + +```yaml +secrets: + POSTGRES_USER: "myuser" # Change for production + POSTGRES_PASSWORD: "mypassword" # Use a strong password +``` + +**Note:** For production, use Kubernetes secrets management or external secret stores (e.g., HashiCorp Vault, AWS Secrets Manager). + +### 3. Storage Configuration + +**For Static Persistent Volumes:** + +If using pre-created PVs, ensure they exist before deployment: + +```bash +kubectl get pv +``` + +Set `storage.storageClassName: ""` in `values.yaml`. + +**For Dynamic Provisioning:** + +Set the appropriate storage class: + +```yaml +storage: + storageClassName: "standard" # or your cluster's storage class +``` + +Verify available storage classes: +```bash +kubectl get storageclass +``` + +--- + +## Deployment Steps + +### 1. Create Namespace + +```bash +export NAMESPACE="k8s-namespace" +kubectl create namespace $NAMESPACE +``` + +### 2. Deploy Using Helm Script + +Use the provided deployment script: + +```bash +chmod +x helm-deployment.sh +./helm-deployment.sh +``` + +**Manual Deployment (Alternative):** + +```bash +helm upgrade --install cmf-deployment ./k8s-deployment \ + --namespace $NAMESPACE \ + -f ./k8s-deployment/values.yaml \ + -f ./k8s-deployment/secrets.yaml \ + --create-namespace +``` + +### 3. Monitor Deployment + +Watch pods being created: + +```bash +kubectl get pods -n $NAMESPACE -w +``` + +Wait for all pods to reach `Running` state: + +```bash +kubectl get pods -n $NAMESPACE +``` + +Expected output: +``` +NAME READY STATUS RESTARTS AGE +cmf-server-xxx 1/1 Running 0 2m +neo4j-xxx 1/1 Running 0 2m +nginx-xxx 1/1 Running 0 2m +postgres-xxx 1/1 Running 0 2m +ui-xxx 1/1 Running 0 2m +``` + +--- + +## Verification + +### 1. Check All Resources + +```bash +# Check pods +kubectl get pods -n $NAMESPACE + +# Check services +kubectl get svc -n $NAMESPACE + +# Check persistent volume claims +kubectl get pvc -n $NAMESPACE + +# Check persistent volumes +kubectl get pv +``` + +### 2. View Logs + +```bash +# CMF Server logs +kubectl logs -n $NAMESPACE -l app=cmf-server --tail=50 + +# UI logs +kubectl logs -n $NAMESPACE -l app=ui --tail=50 + +# PostgreSQL logs +kubectl logs -n $NAMESPACE -l app=postgres --tail=50 + +# Neo4j logs +kubectl logs -n $NAMESPACE -l app=neo4j --tail=50 +``` + +### 3. Check Pod Status + +```bash +# Describe a pod for detailed information +kubectl describe pod -n $NAMESPACE +``` + +--- + +## Accessing Services + +### 1. Get Service URLs + +```bash +kubectl get svc -n $NAMESPACE +``` + +### 2. Access via NodePort (default) + +For **Minikube**: + +```bash +# Get Minikube IP +minikube ip + +# Get service NodePort +kubectl get svc -n $NAMESPACE nginx -o jsonpath='{.spec.ports[0].nodePort}' + +# Access UI +minikube service nginx -n $NAMESPACE +``` + +For **Regular Cluster**: + +```bash +# Get any node IP +kubectl get nodes -o wide + +# Access using: http://: +``` + +### 3. Access Neo4j Browser + +```bash +# Get Neo4j NodePort +kubectl get svc -n $NAMESPACE neo4j -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}' + +# Access: http://: +# Login with credentials from values.yaml (default: neo4j/test1234) +``` + +### 4. Port Forwarding (Alternative) + +For local development/testing: + +```bash +# Forward CMF server +kubectl port-forward -n $NAMESPACE svc/cmf-server 8080:8080 + +# Forward UI +kubectl port-forward -n $NAMESPACE svc/nginx 3000:80 + +# Forward Neo4j +kubectl port-forward -n $NAMESPACE svc/neo4j 7474:7474 7687:7687 + +# Forward PostgreSQL +kubectl port-forward -n $NAMESPACE svc/postgres 5432:5432 +``` + +Access services at: +- UI: http://localhost:3000 +- CMF API: http://localhost:8080 +- Neo4j Browser: http://localhost:7474 +- PostgreSQL: localhost:5432 + +--- + +## Uninstallation + +### Remove Helm Release + +```bash +helm uninstall cmf-deployment -n $NAMESPACE +``` + +### Delete Namespace + +```bash +kubectl delete namespace $NAMESPACE +``` + +### Delete Persistent Volumes (Optional) + +**Warning:** This will delete all data permanently. + +```bash +# List PVs +kubectl get pv + +# Delete specific PV +kubectl delete pv +``` + +### Clean Up Minikube Docker Images (If applicable) + +```bash +eval $(minikube docker-env) +docker rmi cmf-server:latest cmf-ui:latest +``` + +--- + +## Additional Resources + +- [Kubernetes Documentation](https://kubernetes.io/docs/) +- [Helm Documentation](https://helm.sh/docs/) +- [CMF Documentation](https://hewlettpackard.github.io/cmf/) +- [Neo4j Kubernetes Guide](https://neo4j.com/docs/operations-manual/current/kubernetes/) + +--- diff --git a/kubernetes/neo4j/neo4j-pv.yaml b/kubernetes/neo4j/neo4j-pv.yaml deleted file mode 100644 index c9937d96d..000000000 --- a/kubernetes/neo4j/neo4j-pv.yaml +++ /dev/null @@ -1,51 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv-neo4j-data -spec: - capacity: - storage: 10Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/neo4j/data - ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv-neo4j-logs -spec: - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/neo4j/logs - ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv-neo4j-import -spec: - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/neo4j/import - ---- -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv-neo4j-plugins -spec: - capacity: - storage: 5Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/neo4j/plugins - diff --git a/kubernetes/neo4j/neo4j-pvc.yaml b/kubernetes/neo4j/neo4j-pvc.yaml deleted file mode 100644 index 47d070bf7..000000000 --- a/kubernetes/neo4j/neo4j-pvc.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc-neo4j-data -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi # Should match the size of the corresponding PV - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc-neo4j-logs -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi # Should match the size of the corresponding PV - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc-neo4j-import -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi # Should match the size of the corresponding PV - ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc-neo4j-plugins -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi # Should match the size of the corresponding PV - diff --git a/kubernetes/postgres/postgres-deployment.yaml b/kubernetes/postgres/postgres-deployment.yaml deleted file mode 100644 index ca2208dfa..000000000 --- a/kubernetes/postgres/postgres-deployment.yaml +++ /dev/null @@ -1,73 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres-deployment -spec: - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: postgres:13 - ports: - - containerPort: 5432 - env: - - name: POSTGRES_USER - value: "myuser" - - name: POSTGRES_PASSWORD - value: "mypassword" - - name: POSTGRES_DB - value: "mlmd" - volumeMounts: - - mountPath: /var/lib/postgresql/data - name: postgres-data - livenessProbe: - exec: - command: - - pg_isready - - -p - - "5432" - - -d - - mlmd - - -U - - myuser - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 5 - readinessProbe: - exec: - command: - - pg_isready - - -p - - "5432" - - -d - - mlmd - - -U - - myuser - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 5 - volumes: - - name: postgres-data - persistentVolumeClaim: - claimName: pvc-postgres-data ---- -apiVersion: v1 -kind: Service -metadata: - name: postgres -spec: - type: ClusterIP - ports: - - port: 5432 - targetPort: 5432 - selector: - app: postgres diff --git a/kubernetes/postgres/postgres-pv.yaml b/kubernetes/postgres/postgres-pv.yaml deleted file mode 100644 index 9302528a8..000000000 --- a/kubernetes/postgres/postgres-pv.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: pv-postgres-data -spec: - capacity: - storage: 50Gi - accessModes: - - ReadWriteOnce - hostPath: - path: /mnt/cmf/data/postgres_data diff --git a/kubernetes/postgres/postgres-pvc.yaml b/kubernetes/postgres/postgres-pvc.yaml deleted file mode 100644 index c6b4b123b..000000000 --- a/kubernetes/postgres/postgres-pvc.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc-postgres-data -spec: - storageClassName: "" - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 50Gi - volumeName: pv-postgres-data diff --git a/kubernetes/secrets.yaml b/kubernetes/secrets.yaml new file mode 100644 index 000000000..16e628a73 --- /dev/null +++ b/kubernetes/secrets.yaml @@ -0,0 +1,3 @@ +secrets: + POSTGRES_USER: "myuser" + POSTGRES_PASSWORD: "mypassword" \ No newline at end of file diff --git a/kubernetes/templates/NOTES.txt b/kubernetes/templates/NOTES.txt new file mode 100644 index 000000000..657e37054 --- /dev/null +++ b/kubernetes/templates/NOTES.txt @@ -0,0 +1,35 @@ +1. Get the application URL by running these commands: +{{- if .Values.httpRoute.enabled }} +{{- if .Values.httpRoute.hostnames }} + export APP_HOSTNAME={{ .Values.httpRoute.hostnames | first }} +{{- else }} + export APP_HOSTNAME=$(kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o jsonpath="{.spec.listeners[0].hostname}") + {{- end }} +{{- if and .Values.httpRoute.rules (first .Values.httpRoute.rules).matches (first (first .Values.httpRoute.rules).matches).path.value }} + echo "Visit http://$APP_HOSTNAME{{ (first (first .Values.httpRoute.rules).matches).path.value }} to use your application" + + NOTE: Your HTTPRoute depends on the listener configuration of your gateway and your HTTPRoute rules. + The rules can be set for path, method, header and query parameters. + You can check the gateway configuration with 'kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o yaml' +{{- end }} +{{- else if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "cmf-deployment.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "cmf-deployment.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "cmf-deployment.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "cmf-deployment.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/kubernetes/templates/_helpers.tpl b/kubernetes/templates/_helpers.tpl new file mode 100644 index 000000000..ee0137703 --- /dev/null +++ b/kubernetes/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cmf-deployment.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cmf-deployment.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cmf-deployment.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "cmf-deployment.labels" -}} +helm.sh/chart: {{ include "cmf-deployment.chart" . }} +{{ include "cmf-deployment.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "cmf-deployment.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cmf-deployment.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cmf-deployment.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "cmf-deployment.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/kubernetes/templates/hpa.yaml b/kubernetes/templates/hpa.yaml new file mode 100644 index 000000000..6ff7c51e2 --- /dev/null +++ b/kubernetes/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "cmf-deployment.fullname" . }} + labels: + {{- include "cmf-deployment.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "cmf-deployment.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/kubernetes/templates/httproute.yaml b/kubernetes/templates/httproute.yaml new file mode 100644 index 000000000..d37f44c68 --- /dev/null +++ b/kubernetes/templates/httproute.yaml @@ -0,0 +1,38 @@ +{{- if .Values.httpRoute.enabled -}} +{{- $fullName := include "cmf-deployment.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $fullName }} + labels: + {{- include "cmf-deployment.labels" . | nindent 4 }} + {{- with .Values.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- with .Values.httpRoute.parentRefs }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range .Values.httpRoute.rules }} + {{- with .matches }} + - matches: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .filters }} + filters: + {{- toYaml . | nindent 8 }} + {{- end }} + backendRefs: + - name: {{ $fullName }} + port: {{ $svcPort }} + weight: 1 + {{- end }} +{{- end }} diff --git a/kubernetes/templates/ingress.yaml b/kubernetes/templates/ingress.yaml new file mode 100644 index 000000000..382579bbb --- /dev/null +++ b/kubernetes/templates/ingress.yaml @@ -0,0 +1,43 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "cmf-deployment.fullname" . }} + labels: + {{- include "cmf-deployment.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "cmf-deployment.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/kubernetes/templates/neo4j/neo4j-pv.yaml b/kubernetes/templates/neo4j/neo4j-pv.yaml new file mode 100644 index 000000000..c0f7e94c1 --- /dev/null +++ b/kubernetes/templates/neo4j/neo4j-pv.yaml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv-neo4j-data + labels: + type: neo4j-data +spec: + capacity: + storage: {{ .Values.neo4j_service.pvc.data.storage }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.storageClassName | quote }} + hostPath: + path: /mnt/neo4j/data + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv-neo4j-logs + labels: + type: neo4j-logs +spec: + capacity: + storage: {{ .Values.neo4j_service.pvc.logs.storage }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.storageClassName | quote }} + hostPath: + path: /mnt/neo4j/logs + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv-neo4j-import + labels: + type: neo4j-import +spec: + capacity: + storage: {{ .Values.neo4j_service.pvc.import.storage }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.storageClassName | quote }} + hostPath: + path: /mnt/neo4j/import + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv-neo4j-plugins + labels: + type: neo4j-plugins +spec: + capacity: + storage: {{ .Values.neo4j_service.pvc.plugins.storage }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.storageClassName | quote }} + hostPath: + path: /mnt/neo4j/plugins + type: DirectoryOrCreate diff --git a/kubernetes/templates/neo4j/neo4j-pvc.yaml b/kubernetes/templates/neo4j/neo4j-pvc.yaml new file mode 100644 index 000000000..fbc33e0b9 --- /dev/null +++ b/kubernetes/templates/neo4j/neo4j-pvc.yaml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-neo4j-data +spec: + storageClassName: {{ .Values.storage.storageClassName | quote }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.neo4j_service.pvc.data.storage }} # Should match the size of the corresponding PV + selector: + matchLabels: + type: neo4j-data + volumeName: pv-neo4j-data + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-neo4j-logs +spec: + storageClassName: {{ .Values.storage.storageClassName | quote }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.neo4j_service.pvc.logs.storage }} # Should match the size of the corresponding PV + selector: + matchLabels: + type: neo4j-logs + volumeName: pv-neo4j-logs + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-neo4j-import +spec: + storageClassName: {{ .Values.storage.storageClassName | quote }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.neo4j_service.pvc.import.storage }} # Should match the size of the corresponding PV + selector: + matchLabels: + type: neo4j-import + volumeName: pv-neo4j-import + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-neo4j-plugins +spec: + storageClassName: {{ .Values.storage.storageClassName | quote }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.neo4j_service.pvc.plugins.storage }} # Should match the size of the corresponding PV + selector: + matchLabels: + type: neo4j-plugins + volumeName: pv-neo4j-plugins \ No newline at end of file diff --git a/kubernetes/neo4j/neo4j.yaml b/kubernetes/templates/neo4j/neo4j.yaml similarity index 63% rename from kubernetes/neo4j/neo4j.yaml rename to kubernetes/templates/neo4j/neo4j.yaml index dabf2fd19..c1ae76a9d 100644 --- a/kubernetes/neo4j/neo4j.yaml +++ b/kubernetes/templates/neo4j/neo4j.yaml @@ -3,7 +3,7 @@ kind: Deployment metadata: name: neo4j spec: - replicas: 1 + replicas: {{ .Values.replicaCount }} selector: matchLabels: app: neo4j @@ -13,11 +13,11 @@ spec: app: neo4j spec: containers: - - name: neo4 - image: neo4j:latest + - name: neo4j + image: "{{ .Values.neo4j_service.image.repository }}:{{ .Values.neo4j_service.image.tag }}" ports: - - containerPort: 7474 - - containerPort: 7687 + - containerPort: {{ .Values.neo4j_service.service.port }} + - containerPort: {{ .Values.neo4j_service.service.boltPort }} volumeMounts: - name: data-volume mountPath: /data @@ -29,11 +29,11 @@ spec: mountPath: /plugins env: - name: NEO4J_AUTH - value: "neo4j/test1234" + value: {{ .Values.neo4j_service.neo4jAuth }} - name: NEO4J_dbms_connector_http_listen__address - value: "0.0.0.0:7474" + value: "0.0.0.0:{{ .Values.neo4j_service.service.port }}" - name: NEO4J_dbms_connector_bolt_listen__address - value: "0.0.0.0:7687" + value: "0.0.0.0:{{ .Values.neo4j_service.service.boltPort }}" - name: NEO4J_server_config_strict__validation_enabled value: "false" volumes: @@ -57,11 +57,11 @@ metadata: spec: type: NodePort ports: - - port: 7474 - targetPort: 7474 + - port: {{ .Values.neo4j_service.service.port }} + targetPort: {{ .Values.neo4j_service.service.port }} name: http - - port: 7687 - targetPort: 7687 + - port: {{ .Values.neo4j_service.service.boltPort }} + targetPort: {{ .Values.neo4j_service.service.boltPort }} name: bolt selector: app: neo4j diff --git a/kubernetes/nginx/nginx-configmap.yaml b/kubernetes/templates/nginx/nginx-configmap.yaml similarity index 100% rename from kubernetes/nginx/nginx-configmap.yaml rename to kubernetes/templates/nginx/nginx-configmap.yaml diff --git a/kubernetes/nginx/nginx-deployment.yaml b/kubernetes/templates/nginx/nginx-deployment.yaml similarity index 56% rename from kubernetes/nginx/nginx-deployment.yaml rename to kubernetes/templates/nginx/nginx-deployment.yaml index 447321108..4afcf7f27 100644 --- a/kubernetes/nginx/nginx-deployment.yaml +++ b/kubernetes/templates/nginx/nginx-deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: app: nginx spec: - replicas: 1 + replicas: {{ .Values.replicaCount }} selector: matchLabels: app: nginx @@ -15,11 +15,11 @@ spec: app: nginx spec: containers: - - name: nginx - image: nginx:alpine - imagePullPolicy: IfNotPresent + - name: {{ .Values.nginx_service.image.repository }} + image: "{{ .Values.nginx_service.image.repository }}:{{ .Values.nginx_service.image.tag }}" + imagePullPolicy: {{ .Values.pullPolicy }} ports: - - containerPort: 80 + - containerPort: {{ .Values.nginx_service.service.port }} - containerPort: 443 volumeMounts: - name: nginx-config @@ -38,12 +38,12 @@ metadata: labels: app: nginx spec: - type: NodePort # 👈 Makes it accessible from your host + type: NodePort # Makes it accessible from your host ports: - name: http - port: 80 - targetPort: 80 - nodePort: 30080 # 👈 consistent access point: http://$(minikube ip):30080 + port: {{ .Values.nginx_service.service.port }} + targetPort: {{ .Values.nginx_service.service.port }} + nodePort: 30080 # consistent access point: http://$(minikube ip):30080 - name: https port: 443 targetPort: 443 diff --git a/kubernetes/templates/postgres/postgres-deployment.yaml b/kubernetes/templates/postgres/postgres-deployment.yaml new file mode 100644 index 000000000..34842a5a3 --- /dev/null +++ b/kubernetes/templates/postgres/postgres-deployment.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-deployment +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: "{{ .Values.postgres_service.image.repository }}:{{ .Values.postgres_service.image.tag }}" + ports: + - containerPort: {{ .Values.postgres_service.service.port }} + env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-secret + key: POSTGRES_PASSWORD + - name: POSTGRES_DB + value: "{{ .Values.common_env.POSTGRES_DB }}" + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-data + livenessProbe: + exec: + command: + - /bin/sh + - -c + - 'pg_isready -p {{ .Values.postgres_service.service.port }} -d {{ .Values.common_env.POSTGRES_DB }} -U "$POSTGRES_USER"' + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + readinessProbe: + exec: + command: + - /bin/sh + - -c + - 'pg_isready -p {{ .Values.postgres_service.service.port }} -d {{ .Values.common_env.POSTGRES_DB }} -U "$POSTGRES_USER"' + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: pvc-postgres-data +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + type: {{ .Values.postgres_service.service.type }} + ports: + - port: {{ .Values.postgres_service.service.port }} + targetPort: {{ .Values.postgres_service.service.port }} + selector: + app: postgres diff --git a/kubernetes/templates/postgres/postgres-pv.yaml b/kubernetes/templates/postgres/postgres-pv.yaml new file mode 100644 index 000000000..1b63a271e --- /dev/null +++ b/kubernetes/templates/postgres/postgres-pv.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv-postgres-data + labels: + type: postgres-data +spec: + capacity: + storage: {{ .Values.postgres_service.pvc.data.storage }} + accessModes: + - ReadWriteOnce + storageClassName: {{ .Values.storage.storageClassName | quote }} + hostPath: + path: /mnt/cmf/data/postgres_data + type: DirectoryOrCreate diff --git a/kubernetes/templates/postgres/postgres-pvc.yaml b/kubernetes/templates/postgres/postgres-pvc.yaml new file mode 100644 index 000000000..972623bce --- /dev/null +++ b/kubernetes/templates/postgres/postgres-pvc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-postgres-data +spec: + storageClassName: {{ .Values.storage.storageClassName | quote }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.postgres_service.pvc.data.storage }} + selector: + matchLabels: + type: postgres-data + volumeName: pv-postgres-data diff --git a/kubernetes/templates/secret.yaml b/kubernetes/templates/secret.yaml new file mode 100644 index 000000000..3ade4ac49 --- /dev/null +++ b/kubernetes/templates/secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-secret +type: Opaque +data: + POSTGRES_USER: {{ .Values.secrets.POSTGRES_USER | b64enc | quote }} + POSTGRES_PASSWORD: {{ .Values.secrets.POSTGRES_PASSWORD | b64enc | quote }} \ No newline at end of file diff --git a/kubernetes/server/cmf-deployment.yaml b/kubernetes/templates/server/cmf-deployment.yaml similarity index 60% rename from kubernetes/server/cmf-deployment.yaml rename to kubernetes/templates/server/cmf-deployment.yaml index 7efb42f27..dc6f00c36 100644 --- a/kubernetes/server/cmf-deployment.yaml +++ b/kubernetes/templates/server/cmf-deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: app: cmf-server spec: - replicas: 1 + replicas: {{ .Values.replicaCount }} selector: matchLabels: app: cmf-server @@ -16,27 +16,29 @@ spec: spec: containers: - name: cmf-server - image: cmf-server:latest - imagePullPolicy: IfNotPresent # important for Minikube local builds + image: "{{ .Values.cmf_service.image.repository }}:{{ .Values.cmf_service.image.tag }}" + imagePullPolicy: {{ .Values.pullPolicy }} # important for Minikube local builds ports: - - containerPort: 8080 + - containerPort: {{ .Values.cmf_service.service.port }} env: - - name: POSTGRES_HOST - value: "postgres" # Kubernetes Service for Postgres - - name: POSTGRES_USER - value: "myuser" - - name: POSTGRES_PASSWORD - value: "mypassword" - - name: POSTGRES_DB - value: "mlmd" - - name: POSTGRES_PORT - value: "5432" - - name: REACT_APP_CMF_API_URL - value: "http://nginx" # for internal reference, safe to keep + {{- range $key, $value := .Values.common_env }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-secret + key: POSTGRES_USER + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-secret + key: POSTGRES_PASSWORD readinessProbe: httpGet: path: / - port: 8080 + port: {{ .Values.cmf_service.service.port }} initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 @@ -44,7 +46,7 @@ spec: livenessProbe: httpGet: path: / - port: 8080 + port: {{ .Values.cmf_service.service.port }} initialDelaySeconds: 30 periodSeconds: 20 timeoutSeconds: 5 @@ -80,14 +82,14 @@ spec: apiVersion: v1 kind: Service metadata: - name: server # 👈 matches your nginx.conf (proxy_pass http://server:8080/) + name: server # matches your nginx.conf (proxy_pass http://server:8080/) labels: app: cmf-server spec: - type: ClusterIP + type: {{ .Values.cmf_service.service.type }} selector: app: cmf-server ports: - name: http - port: 8080 - targetPort: 8080 + port: {{ .Values.cmf_service.service.port }} + targetPort: {{ .Values.cmf_service.service.port }} diff --git a/kubernetes/server/cmfserver-pv.yaml b/kubernetes/templates/server/cmfserver-pv.yaml similarity index 53% rename from kubernetes/server/cmfserver-pv.yaml rename to kubernetes/templates/server/cmfserver-pv.yaml index 11a3d205e..17db85b18 100644 --- a/kubernetes/server/cmfserver-pv.yaml +++ b/kubernetes/templates/server/cmfserver-pv.yaml @@ -2,63 +2,83 @@ apiVersion: v1 kind: PersistentVolume metadata: name: pv-server-data + labels: + type: server-data spec: capacity: - storage: 40Gi + storage: {{ .Values.cmf_service.pvc.data.storage }} accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.storage.storageClassName | quote }} hostPath: path: /mnt/cmf/data + type: DirectoryOrCreate --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-server-data-env + labels: + type: server-data-env spec: capacity: - storage: 5Gi + storage: {{ .Values.cmf_service.pvc.env.storage }} accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.storage.storageClassName | quote }} hostPath: path: /mnt/cmf/data/env + type: DirectoryOrCreate --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-server-data-static + labels: + type: server-data-static spec: capacity: - storage: 20Gi + storage: {{ .Values.cmf_service.pvc.static.storage }} accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.storage.storageClassName | quote }} hostPath: path: /mnt/cmf/data/static + type: DirectoryOrCreate --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-server-data-labels + labels: + type: server-data-labels spec: capacity: - storage: 5Gi + storage: {{ .Values.cmf_service.pvc.labels.storage }} accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.storage.storageClassName | quote }} hostPath: path: /mnt/cmf/data/labels + type: DirectoryOrCreate --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-tensorboard-logs + labels: + type: tensorboard-logs spec: capacity: - storage: 20Gi + storage: {{ .Values.tensorboard_service.pvc.logs.storage }} accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain + storageClassName: {{ .Values.storage.storageClassName | quote }} hostPath: path: /mnt/cmf/data/tensorboard-logs + type: DirectoryOrCreate \ No newline at end of file diff --git a/kubernetes/server/cmfserver-pvc.yaml b/kubernetes/templates/server/cmfserver-pvc.yaml similarity index 50% rename from kubernetes/server/cmfserver-pvc.yaml rename to kubernetes/templates/server/cmfserver-pvc.yaml index 647df1b7a..7c69ce918 100644 --- a/kubernetes/server/cmfserver-pvc.yaml +++ b/kubernetes/templates/server/cmfserver-pvc.yaml @@ -3,12 +3,15 @@ kind: PersistentVolumeClaim metadata: name: pvc-server-data spec: - storageClassName: "" + storageClassName: {{ .Values.storage.storageClassName | quote }} accessModes: - ReadWriteOnce resources: requests: - storage: 40Gi + storage: {{ .Values.cmf_service.pvc.data.storage }} + selector: + matchLabels: + type: server-data volumeName: pv-server-data --- apiVersion: v1 @@ -16,12 +19,15 @@ kind: PersistentVolumeClaim metadata: name: pvc-server-data-env spec: - storageClassName: "" + storageClassName: {{ .Values.storage.storageClassName | quote }} accessModes: - ReadWriteOnce resources: requests: - storage: 5Gi + storage: {{ .Values.cmf_service.pvc.env.storage }} + selector: + matchLabels: + type: server-data-env volumeName: pv-server-data-env --- apiVersion: v1 @@ -29,12 +35,15 @@ kind: PersistentVolumeClaim metadata: name: pvc-server-data-static spec: - storageClassName: "" + storageClassName: {{ .Values.storage.storageClassName | quote }} accessModes: - ReadWriteOnce resources: requests: - storage: 20Gi + storage: {{ .Values.cmf_service.pvc.static.storage }} + selector: + matchLabels: + type: server-data-static volumeName: pv-server-data-static --- apiVersion: v1 @@ -42,12 +51,15 @@ kind: PersistentVolumeClaim metadata: name: pvc-server-data-labels spec: - storageClassName: "" + storageClassName: {{ .Values.storage.storageClassName | quote }} accessModes: - ReadWriteOnce resources: requests: - storage: 5Gi + storage: {{ .Values.cmf_service.pvc.labels.storage }} + selector: + matchLabels: + type: server-data-labels volumeName: pv-server-data-labels --- apiVersion: v1 @@ -55,10 +67,13 @@ kind: PersistentVolumeClaim metadata: name: pvc-tensorboard-logs spec: - storageClassName: "" + storageClassName: {{ .Values.storage.storageClassName | quote }} accessModes: - ReadWriteOnce resources: requests: - storage: 20Gi + storage: {{ .Values.tensorboard_service.pvc.logs.storage }} + selector: + matchLabels: + type: tensorboard-logs volumeName: pv-tensorboard-logs diff --git a/kubernetes/server/tensorboard.yaml b/kubernetes/templates/server/tensorboard.yaml similarity index 67% rename from kubernetes/server/tensorboard.yaml rename to kubernetes/templates/server/tensorboard.yaml index 02caa10ed..3de97cc79 100644 --- a/kubernetes/server/tensorboard.yaml +++ b/kubernetes/templates/server/tensorboard.yaml @@ -5,7 +5,7 @@ metadata: labels: app: tensorboard spec: - replicas: 1 + replicas: {{ .Values.replicaCount }} selector: matchLabels: app: tensorboard @@ -16,20 +16,20 @@ spec: spec: containers: - name: tensorboard - image: tensorflow/tensorflow:latest - imagePullPolicy: IfNotPresent + image: "{{ .Values.tensorboard_service.image.repository }}:{{ .Values.tensorboard_service.image.tag }}" + imagePullPolicy: {{ .Values.pullPolicy }} command: ["/bin/bash", "-c"] args: - tensorboard --logdir /logs --host 0.0.0.0 --path_prefix=/tensorboard ports: - - containerPort: 6006 + - containerPort: {{ .Values.tensorboard_service.service.port }} volumeMounts: - name: tensorboard-logs mountPath: /logs readinessProbe: httpGet: path: /tensorboard - port: 6006 + port: {{ .Values.tensorboard_service.service.port }} initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 @@ -37,7 +37,7 @@ spec: livenessProbe: httpGet: path: /tensorboard - port: 6006 + port: {{ .Values.tensorboard_service.service.port }} initialDelaySeconds: 30 periodSeconds: 20 timeoutSeconds: 5 @@ -54,10 +54,10 @@ metadata: labels: app: tensorboard spec: - type: ClusterIP + type: {{ .Values.tensorboard_service.service.type }} selector: app: tensorboard ports: - name: http - port: 6006 - targetPort: 6006 + port: {{ .Values.tensorboard_service.service.port }} + targetPort: {{ .Values.tensorboard_service.service.port }} diff --git a/kubernetes/templates/serviceaccount.yaml b/kubernetes/templates/serviceaccount.yaml new file mode 100644 index 000000000..61e2d2ecd --- /dev/null +++ b/kubernetes/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "cmf-deployment.serviceAccountName" . }} + labels: + {{- include "cmf-deployment.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/kubernetes/templates/ui/ui-deployment.yaml b/kubernetes/templates/ui/ui-deployment.yaml new file mode 100644 index 000000000..ed34c3673 --- /dev/null +++ b/kubernetes/templates/ui/ui-deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ui-deployment + labels: + app: ui +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: ui + template: + metadata: + labels: + app: ui + spec: + containers: + - name: ui + image: "{{ .Values.ui_service.image.repository }}:{{ .Values.ui_service.image.tag }}" + imagePullPolicy: {{ .Values.pullPolicy }} # important for Minikube local builds + ports: + - containerPort: {{ .Values.ui_service.service.port }} + env: + - name: REACT_APP_CMF_API_URL + value: http://x.x.x.x:30080 # same cluster DNS; backend reachable via Nginx + readinessProbe: + httpGet: + path: / + port: {{ .Values.ui_service.service.port }} + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + livenessProbe: # added for better health management + httpGet: + path: / + port: {{ .Values.ui_service.service.port }} + initialDelaySeconds: 20 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 5 +--- +apiVersion: v1 +kind: Service +metadata: + name: ui # matches proxy_pass http://ui:3000/; + labels: + app: ui +spec: + type: {{ .Values.ui_service.service.type }} # internal-only (access via Nginx) + ports: + - name: http + port: {{ .Values.ui_service.service.port }} + targetPort: {{ .Values.ui_service.service.port }} + selector: + app: ui diff --git a/kubernetes/ui/ui-deployment.yaml b/kubernetes/ui/ui-deployment.yaml deleted file mode 100644 index c2af008bb..000000000 --- a/kubernetes/ui/ui-deployment.yaml +++ /dev/null @@ -1,56 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: ui-deployment - labels: - app: ui -spec: - replicas: 1 - selector: - matchLabels: - app: ui - template: - metadata: - labels: - app: ui - spec: - containers: - - name: ui - image: ui:latest - imagePullPolicy: IfNotPresent # ✅ important for Minikube local builds - ports: - - containerPort: 3000 - env: - - name: REACT_APP_CMF_API_URL - value: http://x.x.x.x:30080 # ✅ same cluster DNS; backend reachable via Nginx - readinessProbe: - httpGet: - path: / - port: 3000 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 5 - livenessProbe: # ✅ added for better health management - httpGet: - path: / - port: 3000 - initialDelaySeconds: 20 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 5 ---- -apiVersion: v1 -kind: Service -metadata: - name: ui # ✅ matches proxy_pass http://ui:3000/; - labels: - app: ui -spec: - type: ClusterIP # ✅ internal-only (access via Nginx) - ports: - - name: http - port: 3000 - targetPort: 3000 - selector: - app: ui diff --git a/kubernetes/values.yaml b/kubernetes/values.yaml new file mode 100644 index 000000000..5e04e6e2d --- /dev/null +++ b/kubernetes/values.yaml @@ -0,0 +1,259 @@ +# Default values for cmf-deployment. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +replicaCount: 1 + +common_env: + POSTGRES_HOST: "postgres" # Kubernetes Service for Postgres + POSTGRES_DB: "mlmd" + POSTGRES_PORT: "5432" + REACT_APP_CMF_API_URL: "http://nginx" # for internal reference, safe to keep + +service: + type: NodePort + +# This sets the pull policy for images. +pullPolicy: IfNotPresent + +# Storage configuration +storage: + # Leave empty for static PV binding, or specify a storageClass for dynamic provisioning + # Examples: "standard", "gp2", "fast", "nfs-client", etc. + storageClassName: "" + +neo4j_service: + image: + repository: neo4j + tag: latest + + neo4jAuth: "neo4j/test1234" + + service: + type: NodePort + port: 7474 + boltPort: 7687 + + useExistingPvc: true + + pvc: + data: + storage: 5Gi + logs: + storage: 5Gi + import: + storage: 5Gi + plugins: + storage: 5Gi + +cmf_service: + image: + repository: "image_name" # replace with actual image name + tag: latest + + service: + type: ClusterIP + port: 8080 + + useExistingPvc: true + + pvc: + data: + storage: 40Gi + env: + storage: 5Gi + static: + storage: 20Gi + labels: + storage: 5Gi + +postgres_service: + image: + repository: postgres + tag: 13 + + service: + type: ClusterIP + port: 5432 + + useExistingPvc: true + + pvc: + data: + storage: 50Gi + +nginx_service: + image: + repository: nginx + tag: alpine + + service: + type: NodePort + port: 80 + +tensorboard_service: + image: + repository: tensorflow/tensorflow + tag: latest + + service: + type: ClusterIP + port: 6006 + + pvc: + logs: + storage: 10Gi + +ui_service: + image: + repository: "image_name" # replace with actual image name + tag: latest + + service: + type: ClusterIP + port: 3000 + + + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# -- Expose the service via gateway-api HTTPRoute +# Requires Gateway API resources and suitable controller installed within the cluster +# (see: https://gateway-api.sigs.k8s.io/guides/) +httpRoute: + # HTTPRoute enabled. + enabled: false + # HTTPRoute annotations. + annotations: {} + # Which Gateways this Route is attached to. + parentRefs: + - name: gateway + sectionName: http + # namespace: default + # Hostnames matching HTTP header. + hostnames: + - chart-example.local + # List of rules and filters applied. + rules: + - matches: + - path: + type: PathPrefix + value: /headers + # filters: + # - type: RequestHeaderModifier + # requestHeaderModifier: + # set: + # - name: My-Overwrite-Header + # value: this-is-the-only-value + # remove: + # - User-Agent + # - matches: + # - path: + # type: PathPrefix + # value: /echo + # headers: + # - name: version + # value: v2 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http + +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {}