{"id":444,"date":"2024-10-29T10:16:21","date_gmt":"2024-10-29T10:16:21","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=444"},"modified":"2024-10-29T10:16:21","modified_gmt":"2024-10-29T10:16:21","slug":"run-kubernetes-pod-as-non-root-user","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=444","title":{"rendered":"How To Run Kubernetes Pod as Non-Root User?"},"content":{"rendered":"<p>In this blog, we will look at how to run containers inside a <a href=\"https:\/\/devopscube.com\/kubernetes-pod\/\">Kubernetes pod<\/a> run as a non-root user.<\/p>\n<p>We will look at pod and container-level security contexts to define non-root users.<\/p>\n<h2 id=\"securitycontext-in-kubernetes\">SecurityContext in Kubernetes<\/h2>\n<p>To run pods as non-root users, first, you need to understand <code>SecurityContext<\/code> Kubernetes.<\/p>\n<p>In Kubernetes, the <strong><code>securityContext<\/code><\/strong> configuration feature defines pod or container-level security settings. We will use <strong><code>securityContext<\/code><\/strong> it to run the container with a specific non-root user.<\/p>\n<p>It is one of the simple and efficient ways to improve the security of your containers; it has two types:<\/p>\n<ol>\n<li><strong>Pod-level<\/strong> &#8211; This security context applies to all the containers in the pod.<\/li>\n<li><strong>Container-level <\/strong>&#8211; This security context applies to individual containers.<\/li>\n<\/ol>\n<p><strong>SecurityContext<\/strong> has many security options. We will use the <strong>runAsUser<\/strong> parameter specifically to control the user used by the container.<\/p>\n<h2 id=\"container-image-configuration-for-non-root-user-compatibility\">Container Image Configuration for Non-Root User Compatibility<\/h2>\n<p>Even if you set up a <strong><code>SecurityContext<\/code><\/strong> to enforce non-root user policies, the container image itself must support running as a non-root user.<\/p>\n<p>This means the container image should be configured with the necessary user permissions and should not rely on root privileges to execute processes inside the container.<\/p>\n<p>For example, if you are using a Nginx image, the&nbsp;<strong>Nginx process inside the image<\/strong>&nbsp;should be able to run as a non-root user,&nbsp;<strong>similar to<\/strong>&nbsp;how you would run a Nginx&nbsp;process as a non-root user in Linux.<\/p>\n<p>This is because the nginx process inherently writes to several locations owned by the root user (like <code>\/var\/log\/nginx<\/code> for logs or <code>\/var\/cache\/nginx<\/code> for cache). Therefore, we need to modify the container image to assign specific permissions to a non-root user (e.g., <code>nginxuser<\/code>) to allow modification of these files.<\/p>\n<p>You can configure it while <a href=\"https:\/\/devopscube.com\/build-docker-image\/\">building the Docker image<\/a>. You can refer to <a href=\"https:\/\/devopscube.com\/run-docker-containers-as-non-root-user\/\">building non-root container image<\/a> guide to know more.<\/p>\n<p>Also, if the process you run inside the container doesn\u2019t need access to any files owned by root or root privileges, it won\u2019t be a problem. For example, running a BusyBox container with a simple shell script doesn\u2019t need an image-level non-root configuration unless you are writing to files owned by root.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Important Note: <\/strong><\/b>If the container image isn\u2019t properly configured for non-root execution for processes that need access to files or directories owned by the root user , setting non-root policies in Kubernetes will not be effective, and the pod will throw an error.<\/div>\n<\/div>\n<h2 id=\"container-images-with-non-root-user\">Container Images With Non Root User<\/h2>\n<p>We need to use the following images to understand Pod Non-Root user implementation better.<\/p>\n<p>Two images with non-root user configuration, one is exposed to port 8080 and the other to port 9090 to avoid port conflict.<\/p>\n<p>Use the Dockerfile in this&nbsp;<a href=\"https:\/\/github.com\/techiescamp\/kubernetes-tutorials\/tree\/main\/non-root-user?ref=devopscube.com\" rel=\"noopener\">GitHub repo<\/a>&nbsp;to create both images. Check the&nbsp;<a href=\"https:\/\/devopscube.com\/run-docker-containers-as-non-root-user\/\" rel=\"noreferrer\">running containers as a non-root user<\/a>&nbsp;guide to learn more about creating a Docker image with a&nbsp;non-root user.<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note<\/strong><\/b>: If you just want to learn about the functionality , you can use our images specified on this guide<\/div>\n<\/div>\n<h2 id=\"kubernetes-pod-non-root-user-configurations\">Kubernetes Pod Non-Root User Configurations<\/h2>\n<p>When we say <a href=\"https:\/\/devopscube.com\/kubernetes-pod\/\">Kubernetes pod<\/a>, it can have more than one container. You can apply the <strong><code>securityContext<\/code><\/strong> configuration at the pod and container levels.<\/p>\n<p>To understand it better, we will look at the following use cases that use container images with non-root users:<\/p>\n<ol>\n<li>Running the pod with<strong> pod-level security context<\/strong> in which both container images have non-root users. (Should run without any issues)<\/li>\n<li>Running the pod with a pod-level security context, but in this one container image has a non-root user, and the other container image doesn&#8217;t have a root user. (The one without root user should fail)<\/li>\n<li>Running the pod with a<strong> container-level security context<\/strong> involves running one container as a non-root user and the other as a root user (Both should run without any issues)<\/li>\n<li>Running pod with both pod-level and container-level security context (Container-level security context overrides the pod-level context)<\/li>\n<\/ol>\n<h3 id=\"use-case-1-running-containers-as-a-non-root-user-with-a-pod-with-the-pod-level-security-context\">Use Case 1: Running Containers as a non-root user with a pod with the pod-level security context<\/h3>\n<p>For this use case, we will use a container <strong>image that has non-root user configuration<\/strong> as part of its image.<\/p>\n<p>We will run a pod with <strong>pod-level security context<\/strong> in which <strong>both container images have non-root users.<\/strong><\/p>\n<p>Create a file called <strong><code>pod-level.yaml<\/code><\/strong> and copy the below manifest file content.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Pod\nmetadata:\n  name: testing-pod\nspec:\n  securityContext:\n    runAsUser: 1001\n  containers:\n  - name: first-container\n    image: techiescamp\/nginx-non-root-01:1.0.0\n    ports:\n    - containerPort: 8080\n  - name: second-container\n    image: techiescamp\/nginx-non-root-02:1.0.0\n    ports:\n    - containerPort: 9090<\/code><\/pre>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\"><b><strong style=\"white-space: pre-wrap;\">Note<\/strong><\/b>: You can also set <code spellcheck=\"false\" style=\"white-space: pre-wrap;\">runAsNonRoot: true<\/code> that will set the non-root user from the container image automatically.<\/div>\n<\/div>\n<p>Then, run the following command to apply the manifest file to deploy the pod with pod-level security context.<\/p>\n<pre><code class=\"language-bash\">kubectl apply -f pod-level.yaml<\/code><\/pre>\n<p>Now, how to check if pod is running as root?<\/p>\n<p>Once the pod is up and running, use the  <code>kubectl exec<\/code> command with linux <strong><code>id<\/code><\/strong> command to check if the pod is running as root or non root user.<\/p>\n<pre><code class=\"language-bash\">kubectl exec testing-pod -c first-container -- id\n\nkubectl exec testing-pod -c second-container -- id<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-11.png\" class=\"kg-image\" alt=\"output of running the pod with pod-level security context with both containers have non-root user\" loading=\"lazy\" width=\"615\" height=\"302\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-23-11.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-23-11.png 615w\"><\/figure>\n<p>You can see both containers are running on&nbsp;<strong>UID 1001,<\/strong>&nbsp;which is the UID of non-root users.<\/p>\n<p>Does this mean kubectl exec command logins as non root user?<\/p>\n<p>When you use the <code>kubectl exec<\/code> command to start a session in a container running with a non-root user, you will be logged in as that non-root user.<\/p>\n<p>This means that:<\/p>\n<ol>\n<li>Any commands you run will have the permissions of the non-root user that the container is using.<\/li>\n<li>You will not have root (superuser) privileges inside the container.<\/li>\n<\/ol>\n<h3 id=\"use-case-2-running-the-pod-with-a-pod-level-security-context-with-only-one-container-as-non-root-user\">Use Case 2: Running the pod with a pod-level security context with only one container as non-root user<\/h3>\n<p>In the second use case, we will run a pod with a pod-level security context, but in this, one container has a non-root user, and the other container doesn&#8217;t run as a root user.<\/p>\n<p>In this use case, we expect one of the containers that runs as root to end up in <strong><code>CrashLoopBackoff<\/code><\/strong> because of the pod level non-root user securityContext.<\/p>\n<p>For this use case, use the same <strong>pod-level.yaml<\/strong> used in the above use case.<\/p>\n<p>Just change the image of the <strong>first-contianer<\/strong> to the official Nginx image as given below.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Pod\nmetadata:\n  name: testing-pod\nspec:\n  securityContext:\n    runAsUser: 1001\n  containers:\n  - name: first-container\n    image: nginx:latest\n    ports:\n    - containerPort: 8080\n  - name: second-container\n    image: techiescamp\/nginx-non-root-02:1.0.0\n    ports:\n    - containerPort: 9090<\/code><\/pre>\n<p>We will be using the official <strong>nginx: latest<\/strong> image to test what happens if the container runs with an inactive user.<\/p>\n<p>Apply the manifest file and check the pod&#8217;s status using the following command.<\/p>\n<pre><code class=\"language-bash\">kubectl get po<\/code><\/pre>\n<p>You can see that only one pod is ready, and another pod crashes continuously because the first container doesn&#8217;t have a non-user with UID 1001.<\/p>\n<p>If you want to run the container as a non-root user, you must first create the user during the container image creation.<\/p>\n<p>The second container runs without any issues because it has a non-root user with UID 1001.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-25-12.png\" class=\"kg-image\" alt=\"output of running the pod with a pod-level security context with only one container has non-root user\" loading=\"lazy\" width=\"715\" height=\"239\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-25-12.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-25-12.png 715w\"><\/figure>\n<p>Run the following command to check the pod logs.<\/p>\n<pre><code class=\"language-bash\">kubectl logs testing-pod<\/code><\/pre>\n<p>You can see the following error because the UID we gave is only available for&nbsp;<strong>the second container,<\/strong>&nbsp;not for&nbsp;<strong>the first container<\/strong>.<\/p>\n<pre><code class=\"language-bash\">2024\/10\/09 10:32:06 [emerg] 1#1: mkdir() \"\/var\/cache\/nginx\/client_temp\" failed (13: Permission denied)\nnginx: [emerg] mkdir() \"\/var\/cache\/nginx\/client_temp\" failed (13: Permission denied)<\/code><\/pre>\n<p>Because of the unavailable UID, it doesn&#8217;t have permission to access the directors to run Nginx.<\/p>\n<p>If you check for the UID the containers are using, you will get the following output<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-29-13.png\" class=\"kg-image\" alt=\"output of running the pod with a pod-level security context with only one container has non-root user\" loading=\"lazy\" width=\"879\" height=\"302\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-29-13.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-29-13.png 879w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<h3 id=\"use-case-3-running-the-pod-with-a-container-level-security-context-to-use-different-users-on-containers\">Use Case 3: Running the pod with a container-level security context to use different users on containers<\/h3>\n<p>In the third use case, we will be running the pod with a container-level security context,<\/p>\n<ol>\n<li>run one container as a non-root user<\/li>\n<li>other as a root user.<\/li>\n<\/ol>\n<p>Create a file called <strong>container-level.yaml<\/strong> and copy the manifest file content below.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Pod\nmetadata:\n  name: testing-pod\nspec:\n  containers:\n  - name: first-container\n    image: techiescamp\/nginx-non-root-01:1.0.0\n    ports:\n    - containerPort: 8080\n    securityContext:\n        runAsUser: 1001\n  - name: second-container\n    image: techiescamp\/nginx-non-root-02:1.0.0\n    ports:\n    - containerPort: 9090\n    securityContext:\n        runAsUser: 0<\/code><\/pre>\n<p>In the above manifest file, the security content is given inside each container with a different UID, which tells the containers to run with a non-root user (1001) and a root user (0).<\/p>\n<div class=\"kg-card kg-callout-card kg-callout-card-grey\">\n<div class=\"kg-callout-text\">By default, the UID 0 will be assigned to the root user.<\/div>\n<\/div>\n<p>Run the following command to apply the manifest file to deploy the pod with the pod-level security context.<\/p>\n<pre><code class=\"language-bash\">kubectl apply -f container-level.yaml<\/code><\/pre>\n<p>Once the pod is up and running, use the following command to check in which users the container is running.<\/p>\n<pre><code class=\"language-bash\">kubectl exec testing-pod -c first-container -- id\n\nkubectl exec testing-pod -c second-container -- id<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-32-8.png\" class=\"kg-image\" alt=\"Output of running the pod with a container-level security context to use different users on containers\" loading=\"lazy\" width=\"754\" height=\"334\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-32-8.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-32-8.png 754w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can see the first container is running with the non-root user(1001), and the second container is running with the root user(0).<\/p>\n<h3 id=\"use-case-4-running-pod-with-both-pod-level-and-container-level-security-context\">Use Case 4: Running pod with both pod-level and container-level security context<\/h3>\n<p>In the final use case, we will run the pod with<strong>&nbsp;pod-level and container-level security contexts.<\/strong><\/p>\n<p>We will specify to run as a non-root user in the pod-level security context and define one container to run as a root user using the container-level security context.<\/p>\n<p>Create a file called <strong>pod.yaml<\/strong> and copy the manifest file content below.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Pod\nmetadata:\n  name: testing-pod\nspec:\n  securityContext:\n    runAsUser: 1001\n  containers:\n  - name: first-container\n    image: techiescamp\/nginx-non-root-01:1.0.0\n    ports:\n    - containerPort: 8080\n  - name: second-container\n    image: techiescamp\/nginx-non-root-02:1.0.0\n    ports:\n    - containerPort: 9090\n    securityContext:\n        runAsUser: 0<\/code><\/pre>\n<p>As you can see in the above manifest, the first container is defined to run as a non-root user in the pod-level security context, and the second container is defined to run as a root user using the container-level security context.<\/p>\n<p>Let&#8217;s apply the manifest file and see what happens. Run the following command to apply the manifest file.<\/p>\n<pre><code class=\"language-bash\">kubectl apply -f pod.yaml<\/code><\/pre>\n<p>Once the pod is up and running, use the following command to check in which users the container is running.<\/p>\n<pre><code class=\"language-bash\">kubectl exec testing-pod -c first-container -- id\n\nkubectl exec testing-pod -c second-container -- id<\/code><\/pre>\n<p>You will get the following output.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-60-2.png\" class=\"kg-image\" alt=\"Output of running pod with both pod-level and container-level security context\" loading=\"lazy\" width=\"907\" height=\"316\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-60-2.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-60-2.png 907w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can see the first container is running with the non-root user(1001), and the second container is running with the root user(0).<\/p>\n<p>This means the <strong>container-level security context overrides the pod-level security context.<\/strong><\/p>\n<h2 id=\"faqs\">FAQ&#8217;s<\/h2>\n<h3 id=\"how-to-run-pod-with-non-root-user\">How to run pod with non-root user?<\/h3>\n<p>Using <strong><code>securityContext<\/code><\/strong> parameter and <strong>runAsUser<\/strong> subfield, you can run a pod with non root user. In the <strong>runAsUser<\/strong> parameter you can specify the username or userid.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Running pods as non-root use is one of the best security practice. It minimizes the risks associated with potential vulnerabilities by limiting the privileges of the application inside the container.<\/p>\n<p>So to strengthen the <strong>overall security posture<\/strong> of your Kubernetes environment, you can implement this from the development stages. You can add checks using tools like <a href=\"https:\/\/devopscube.com\/scan-docker-images-using-trivy\/\">Trivy<\/a> in your Docker build pipelines to ensure container images are built with only with non-root users.<\/p>\n<p>You can also prevent pods from deploying that doesnt run as non-root using kubernetes built-in admission controller called <strong>Pod Security Admission<\/strong>.<\/p>\n<p>Also, implementing Kubernetes policy management tools like Kyverno to prevent pods from running as the root user by checking fields like <code>runAsNonRoot<\/code>. It can also validate existing workloads for security misconfigurations.<\/p>\n<p>Now, we would like to know your thoughts?<\/p>\n<p>Are you planning to implement non-root user pods in your environment?<\/p>\n<p>Are you planning to implement policy management tools to ensure compliance?<\/p>\n<p>Let us know the comments.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/run-kubernetes-pod-as-non-root-user\/\" target=\"_blank\" rel=\"noopener noreferrer\">How To Run Kubernetes Pod as Non-Root User? \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/run-kubernetes-pod-as-non-root-user\/<\/p>\n","protected":false},"author":1,"featured_media":445,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-444","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=444"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/444\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/445"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=444"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}