{"id":3540,"date":"2026-05-20T06:05:23","date_gmt":"2026-05-20T06:05:23","guid":{"rendered":"https:\/\/aiopsschool.com\/blog\/?p=3540"},"modified":"2026-05-20T06:11:39","modified_gmt":"2026-05-20T06:11:39","slug":"mage-ai-on-kubernetes-eks-using-helm","status":"publish","type":"post","link":"https:\/\/aiopsschool.com\/blog\/mage-ai-on-kubernetes-eks-using-helm\/","title":{"rendered":"Mage AI on Kubernetes\/EKS using Helm"},"content":{"rendered":"\n<p> Here is the consolidated <strong>Mage AI deployment process on Kubernetes\/EKS using Helm<\/strong>, including the exact volume issue you hit and the working fix.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Mage AI on Kubernetes\/EKS using Helm<\/h1>\n\n\n\n<p>Mage provides an official Helm chart through the <code>mageai<\/code> Helm repository. The official Helm docs show the basic flow: add the repo, update it, search the chart, and install <code>mageai\/mageai<\/code>. They also document using <code>extraVolumes<\/code> and <code>extraVolumeMounts<\/code> for project storage, especially with PVC-backed storage on cloud Kubernetes. (<a href=\"https:\/\/docs.mage.ai\/production\/deploying-to-cloud\/using-helm?utm_source=chatgpt.com\">docs.mage.ai<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. Add Mage AI Helm repository<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo add mageai https:\/\/mage-ai.github.io\/helm-charts\nhelm repo update\n<\/code><\/pre>\n\n\n\n<p>Check available charts:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm search repo mageai\n<\/code><\/pre>\n\n\n\n<p>Example output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                  CHART VERSION   APP VERSION   DESCRIPTION\nmageai\/mageai         0.2.14          0.9.79        A Helm chart for Mage AI\nmageai\/mageai-ingress 0.0.1                         A Helm chart for deploying ingress for Mage AI\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. Create a dedicated namespace<\/h2>\n\n\n\n<p>Avoid installing directly into <code>default<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create namespace mageai-dev\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Important issue with default install<\/h2>\n\n\n\n<p>If you run this directly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm install mageai-dev mageai\/mageai -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>the pod may fail with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CreateContainerError\n<\/code><\/pre>\n\n\n\n<p>In your case, the exact error was:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>failed to mkdir \"\/path\/to\/mage_project\": mkdir \/path: read-only file system\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Why this happened<\/h3>\n\n\n\n<p>The chart was trying to use a placeholder\/project path:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/path\/to\/mage_project\n<\/code><\/pre>\n\n\n\n<p>That path is not valid for your EKS setup. Kubernetes tried to create it, but the filesystem was read-only from the container runtime perspective.<\/p>\n\n\n\n<p>So the image was fine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Successfully pulled image \"mageai\/mageai:0.9.79\"\n<\/code><\/pre>\n\n\n\n<p>The problem was <strong>volume\/project path configuration<\/strong>, not image pull, not Helm repo, and not EKS networking.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. Working test install using <code>emptyDir<\/code><\/h2>\n\n\n\n<p>For testing, create this values file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; mageai-dev-values.yaml &lt;&lt;'EOF'\nservice:\n  type: ClusterIP\n\nconfig:\n  USER_CODE_PATH: \/home\/src\/default_repo\n\nextraVolumeMounts:\n  - name: mage-fs\n    mountPath: \/home\/src\n\nextraVolumes:\n  - name: mage-fs\n    emptyDir: {}\nEOF\n<\/code><\/pre>\n\n\n\n<p>Install fresh:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm install mageai-dev mageai\/mageai -n mageai-dev \\\n  -f mageai-dev-values.yaml\n<\/code><\/pre>\n\n\n\n<p>Or if release already exists:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm upgrade mageai-dev mageai\/mageai -n mageai-dev \\\n  -f mageai-dev-values.yaml\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. Verify deployment<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                      READY   STATUS    RESTARTS   AGE\nmageai-xxxxxxxxxx-xxxxx   1\/1     Running   0          1m\n<\/code><\/pre>\n\n\n\n<p>Check service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get svc -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)\nmageai   ClusterIP   172.20.xxx.xxx   &lt;none&gt;        6789\/TCP\n<\/code><\/pre>\n\n\n\n<p>This means Mage AI is <strong>internal-only<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. Access Mage AI from your laptop<\/h2>\n\n\n\n<p>Run this from your laptop terminal:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl port-forward svc\/mageai 6789:6789 -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Keep that terminal open.<\/p>\n\n\n\n<p>Then open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:6789\n<\/code><\/pre>\n\n\n\n<p>If port <code>6789<\/code> is already used on your laptop:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl port-forward svc\/mageai 6790:6789 -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Then open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:6790\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Complete clean install flow<\/h1>\n\n\n\n<p>Use this if starting from zero:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm repo add mageai https:\/\/mage-ai.github.io\/helm-charts\nhelm repo update\n\nkubectl create namespace mageai-dev\n\ncat &gt; mageai-dev-values.yaml &lt;&lt;'EOF'\nservice:\n  type: ClusterIP\n\nconfig:\n  USER_CODE_PATH: \/home\/src\/default_repo\n\nextraVolumeMounts:\n  - name: mage-fs\n    mountPath: \/home\/src\n\nextraVolumes:\n  - name: mage-fs\n    emptyDir: {}\nEOF\n\nhelm install mageai-dev mageai\/mageai -n mageai-dev \\\n  -f mageai-dev-values.yaml\n\nkubectl get pods -n mageai-dev\nkubectl get svc -n mageai-dev\n\nkubectl port-forward svc\/mageai 6789:6789 -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Open:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http:&#47;&#47;localhost:6789\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Cleanup commands<\/h1>\n\n\n\n<p>Remove old failed\/default install:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall my-mageai -n default\n<\/code><\/pre>\n\n\n\n<p>Remove current dev install:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall mageai-dev -n mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Delete namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete namespace mageai-dev\n<\/code><\/pre>\n\n\n\n<p>Check all Mage resources:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm list -A | grep mage\nkubectl get all -A | grep mage\nkubectl get svc -A | grep mage\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Production storage note<\/h1>\n\n\n\n<p>The working fix used:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>emptyDir: {}\n<\/code><\/pre>\n\n\n\n<p>That is fine for testing, but not production.<\/p>\n\n\n\n<p><code>emptyDir<\/code> is temporary pod storage. If the pod is deleted or rescheduled, Mage project files can disappear.<\/p>\n\n\n\n<p>For production on EKS, use persistent storage such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AWS EFS \u2192 Kubernetes StorageClass \u2192 PVC \u2192 \/home\/src\n<\/code><\/pre>\n\n\n\n<p>Mage\u2019s Helm docs show the production-style pattern of mounting project storage to <code>\/home\/src<\/code> using <code>extraVolumeMounts<\/code> and <code>extraVolumes<\/code>, with a PVC such as an EFS-backed ReadWriteMany volume. (<a href=\"https:\/\/docs.mage.ai\/production\/deploying-to-cloud\/using-helm?utm_source=chatgpt.com\">docs.mage.ai<\/a>)<\/p>\n\n\n\n<p>Production-style values example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>service:\n  type: ClusterIP\n\nconfig:\n  USER_CODE_PATH: \/home\/src\/default_repo\n\nextraVolumeMounts:\n  - name: mage-fs\n    mountPath: \/home\/src\n\nextraVolumes:\n  - name: mage-fs\n    persistentVolumeClaim:\n      claimName: mageai-efs-pvc\n<\/code><\/pre>\n\n\n\n<p>Then deploy:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm upgrade --install mageai-dev mageai\/mageai -n mageai-dev \\\n  -f mageai-prod-values.yaml\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final architecture from your working setup<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>Laptop Browser\n    \u2193\nhttp:&#47;&#47;localhost:6789\n    \u2193\nkubectl port-forward\n    \u2193\nKubernetes Service: mageai\nType: ClusterIP\nPort: 6789\n    \u2193\nMage AI Pod\nContainer Port: 6789\n    \u2193\nMounted project path:\n\/home\/src\/default_repo\n<\/code><\/pre>\n\n\n\n<p>Your current successful setup is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Mage AI app       \u2705 Running\nService type      \u2705 ClusterIP \/ internal-only\nAccess method     \u2705 kubectl port-forward\nPort              \u2705 6789\nStorage           \u26a0\ufe0f emptyDir \/ testing only\nVolume issue      \u2705 Fixed\n<\/code><\/pre>\n\n\n\n<p>Yes. Run these cleanup commands.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Stop port-forward<\/h2>\n\n\n\n<p>In the terminal where port-forward is running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Ctrl + C\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">2. Check existing Mage Helm releases<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>helm list -A | grep mage\n<\/code><\/pre>\n\n\n\n<p>You may see:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>my-mageai     default\nmageai-dev    mageai-dev\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. Uninstall Mage releases<\/h2>\n\n\n\n<p>Remove old install from <code>default<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall my-mageai -n default\n<\/code><\/pre>\n\n\n\n<p>Remove fresh dev install:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall mageai-dev -n mageai-dev\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. Delete Mage namespace<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete namespace mageai-dev\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. Verify cleanup<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>helm list -A | grep mage\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get all -A | grep mage\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get svc -A | grep mage\n<\/code><\/pre>\n\n\n\n<p>Expected: no output.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Confirm AWS LoadBalancer is removed<\/h2>\n\n\n\n<p>Because earlier installs created AWS LoadBalancers, check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get svc -A | grep LoadBalancer\n<\/code><\/pre>\n\n\n\n<p>If no Mage service appears, Kubernetes has requested AWS to delete the ELB.<\/p>\n\n\n\n<p>You can also check from AWS CLI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws elbv2 describe-load-balancers --region ap-northeast-1 \\\n  --query \"LoadBalancers&#91;?contains(LoadBalancerName, 'mage')].&#91;LoadBalancerName,DNSName,State.Code]\" \\\n  --output table\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Full cleanup block<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>helm uninstall my-mageai -n default\nhelm uninstall mageai-dev -n mageai-dev\n\nkubectl delete namespace mageai-dev\n\nhelm list -A | grep mage\nkubectl get all -A | grep mage\nkubectl get svc -A | grep mage\nkubectl get svc -A | grep LoadBalancer\n<\/code><\/pre>\n\n\n\n<p>If <code>helm uninstall my-mageai -n default<\/code> says release not found, that is fine \u2014 it was already removed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here is the consolidated Mage AI deployment process on Kubernetes\/EKS using Helm, including the exact volume issue you hit and [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3540","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=3540"}],"version-history":[{"count":2,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3540\/revisions"}],"predecessor-version":[{"id":3542,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/3540\/revisions\/3542"}],"wp:attachment":[{"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=3540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=3540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aiopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=3540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}