使用 SecurityContext readOnlyRootFilesystem 时的 Kubernetes 137 退出代码
Kubernetes 137 exit code when using SecurityContext readOnlyRootFilesystem
我正在尝试在具有只读文件系统的容器中托管网络应用程序。每当我尝试通过容器的 SecurityContext
将根文件系统配置为只读时,我都会收到以下错误:
Ports: 80/TCP, 443/TCP
Host Ports: 0/TCP, 0/TCP
State: Terminated
Reason: Error
Exit Code: 137
Started: Thu, 23 Sep 2021 18:13:08 +0300
Finished: Thu, 23 Sep 2021 18:13:08 +0300
Ready: False
我尝试使用 AppArmor 配置文件实现相同的效果,如下所示:
profile parser-profile flags=(attach_disconnected) {
#include <abstractions/base>
...
deny /** wl,
...
不幸的是,结果是一样的。
我假设正在发生的事情是容器无法为 Web 应用程序保存文件并且失败了。
在我的场景中,我将是 运行 不受信任的代码,我必须确保不允许用户访问文件系统。
关于我做错了什么以及如何实现只读文件系统有什么想法吗?
我正在使用 AKS,下面是我的部署配置:
apiVersion: v1
kind: Service
metadata:
name: parser-service
spec:
selector:
app: parser
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
- port: 443
targetPort: 443
protocol: TCP
name: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: parser-deployment
spec:
replicas: 5
selector:
matchLabels:
app: parser
template:
metadata:
labels:
app: parser
annotations:
container.apparmor.security.beta.kubernetes.io/parser: localhost/parser-profile
spec:
containers:
- name: parser
image: parser.azurecr.io/parser:latest
ports:
- containerPort: 80
- containerPort: 443
resources:
limits:
cpu: "1.20"
securityContext:
readOnlyRootFilesystem: true
编辑:我还尝试创建集群级别的 PSP,但也没有用。
我设法重现了您的问题并实现了只读文件系统,只有一个目录例外。
首先,值得注意的是您在部署中同时使用了两种解决方案——AppArmor 配置文件和 SecurityContext。由于 AppArmor 似乎要复杂得多并且需要为每个节点完成配置我决定只使用 SecurityContext 因为它工作正常。
我收到你在评论中提到的这个错误:
Failed to create CoreCLR, HRESULT: 0x80004005
这个错误并没有说明什么,但经过一些测试后我发现它只发生在你是 运行 文件系统是只读的 pod - 应用程序试图保存文件但不能这样做.
该应用程序在 /tmp
目录中创建了一些文件,因此解决方案是使用 Kubernetes Volumes so it will be read write. In my example I used emptyDir 挂载 /tmp
但您可以使用任何其他您想要的卷,只要它支持写入给它。部署配置(可以看到我加了volumeMounts
和volumes
以及最下面):
apiVersion: v1
kind: Service
metadata:
name: parser-service
spec:
selector:
app: parser
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
- port: 443
targetPort: 443
protocol: TCP
name: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: parser-deployment
spec:
replicas: 5
selector:
matchLabels:
app: parser
template:
metadata:
labels:
app: parser
spec:
containers:
- name: parser
image: parser.azurecr.io/parser:latest
ports:
- containerPort: 80
- containerPort: 443
resources:
limits:
cpu: "1.20"
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /tmp
name: temp
volumes:
- name: temp
emptyDir: {}
执行到 pod 后,我可以看到 pod 文件系统被挂载为只读:
# ls
app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
# touch file
touch: cannot touch 'file': Read-only file system
# mount
overlay on / type overlay (ro,...)
通过 运行 kubectl describe pod {pod-name}
我可以看到 /tmp
目录被挂载为读写并且它正在使用 temp
卷:
Mounts:
/tmp from temp (rw)
请记住,如果您正在使用其他目录(例如保存文件),您还需要以与 /tmp
.
相同的方式挂载它们
我正在尝试在具有只读文件系统的容器中托管网络应用程序。每当我尝试通过容器的 SecurityContext
将根文件系统配置为只读时,我都会收到以下错误:
Ports: 80/TCP, 443/TCP
Host Ports: 0/TCP, 0/TCP
State: Terminated
Reason: Error
Exit Code: 137
Started: Thu, 23 Sep 2021 18:13:08 +0300
Finished: Thu, 23 Sep 2021 18:13:08 +0300
Ready: False
我尝试使用 AppArmor 配置文件实现相同的效果,如下所示:
profile parser-profile flags=(attach_disconnected) {
#include <abstractions/base>
...
deny /** wl,
...
不幸的是,结果是一样的。
我假设正在发生的事情是容器无法为 Web 应用程序保存文件并且失败了。
在我的场景中,我将是 运行 不受信任的代码,我必须确保不允许用户访问文件系统。
关于我做错了什么以及如何实现只读文件系统有什么想法吗?
我正在使用 AKS,下面是我的部署配置:
apiVersion: v1
kind: Service
metadata:
name: parser-service
spec:
selector:
app: parser
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
- port: 443
targetPort: 443
protocol: TCP
name: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: parser-deployment
spec:
replicas: 5
selector:
matchLabels:
app: parser
template:
metadata:
labels:
app: parser
annotations:
container.apparmor.security.beta.kubernetes.io/parser: localhost/parser-profile
spec:
containers:
- name: parser
image: parser.azurecr.io/parser:latest
ports:
- containerPort: 80
- containerPort: 443
resources:
limits:
cpu: "1.20"
securityContext:
readOnlyRootFilesystem: true
编辑:我还尝试创建集群级别的 PSP,但也没有用。
我设法重现了您的问题并实现了只读文件系统,只有一个目录例外。
首先,值得注意的是您在部署中同时使用了两种解决方案——AppArmor 配置文件和 SecurityContext。由于 AppArmor 似乎要复杂得多并且需要为每个节点完成配置我决定只使用 SecurityContext 因为它工作正常。
我收到你在评论中提到的这个错误:
Failed to create CoreCLR, HRESULT: 0x80004005
这个错误并没有说明什么,但经过一些测试后我发现它只发生在你是 运行 文件系统是只读的 pod - 应用程序试图保存文件但不能这样做.
该应用程序在 /tmp
目录中创建了一些文件,因此解决方案是使用 Kubernetes Volumes so it will be read write. In my example I used emptyDir 挂载 /tmp
但您可以使用任何其他您想要的卷,只要它支持写入给它。部署配置(可以看到我加了volumeMounts
和volumes
以及最下面):
apiVersion: v1
kind: Service
metadata:
name: parser-service
spec:
selector:
app: parser
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
- port: 443
targetPort: 443
protocol: TCP
name: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: parser-deployment
spec:
replicas: 5
selector:
matchLabels:
app: parser
template:
metadata:
labels:
app: parser
spec:
containers:
- name: parser
image: parser.azurecr.io/parser:latest
ports:
- containerPort: 80
- containerPort: 443
resources:
limits:
cpu: "1.20"
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- mountPath: /tmp
name: temp
volumes:
- name: temp
emptyDir: {}
执行到 pod 后,我可以看到 pod 文件系统被挂载为只读:
# ls
app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
# touch file
touch: cannot touch 'file': Read-only file system
# mount
overlay on / type overlay (ro,...)
通过 运行 kubectl describe pod {pod-name}
我可以看到 /tmp
目录被挂载为读写并且它正在使用 temp
卷:
Mounts:
/tmp from temp (rw)
请记住,如果您正在使用其他目录(例如保存文件),您还需要以与 /tmp
.