I have an image, which is a simple web server running on port 80. When I run it locally, I get:
The app is listening at http://localhost:80
and everything is fine.
However, when I deploy the following to K8s, it crashes constantly.
Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: apps
labels:
app: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: myimage:dev
imagePullPolicy: Always
ports:
- containerPort: 80
Logs of one of the pods:
node:events:371
throw er; // Unhandled 'error' event
^
Error: listen EACCES: permission denied 0.0.0.0:80
at Server.setupListenHandle [as _listen2] (node:net:1298:21)
at listenInCluster (node:net:1363:12)
at Server.listen (node:net:1450:7)
at Function.listen (/app/node_modules/express/lib/application.js:618:24)
at Object.<anonymous> (/app/index.js:17:5)
at Module._compile (node:internal/modules/cjs/loader:1095:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1124:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:816:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
Emitted 'error' event on Server instance at:
at emitErrorNT (node:net:1342:8)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'EACCES',
errno: -13,
syscall: 'listen',
address: '0.0.0.0',
port: 80
}
Why my image is able to run successfully on my local machine, and it fails on the Kubernetes?
Non-root users (non privileged) can't open a listening socket on ports below 1024.
You can find the solution here:
Remember, we do NOT want to run your applications as the root user, but there is a hitch: your safe user does not have permission to use the default HTTP port (80). You goal is to be able to publish a website that visitors can use by navigating to an easy to use URL like http://example.com.
Unfortunately, unless you sign on as root, you’ll normally have to use a URL like http://example.com:3000 - notice the port number.
A lot of people get stuck here, but the solution is easy. There a few options but this is the one I like. Type the following commands:
sudo apt-get install libcap2-bin
sudo setcap cap_net_bind_service=+ep /usr/local/bin/node
You can also see this similar question.