我有一个 Flask + Postgres 应用程序,使用 docker-compose 进行容器化。
services:
database:
image: postgres:latest
container_name: hse-database
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=hse-app-db
expose:
- "5432"
ports:
- "5432:5432"
restart: always
api:
build: ./hse_api
container_name: hse_api
ports:
- "5000:5000"
env_file: ./hse_api/.env
volumes:
- ./hse_api:/usr/src/app/api
depends_on:
- database
restart: always
我有一个入口点文件,旨在使用在我的 manage.py 文件中创建的函数来为数据库播种,并且到目前为止,仅使用 Docker 时似乎工作正常。
当我还为该项目启动 Kubernetes pod 时,postgres 似乎启动良好,如下所示:
NAME READY STATUS RESTARTS AGE
pod/hse-api-5c7f656b8c-d59v8 0/1 CrashLoopBackOff 12 (56s ago) 37m
pod/postgres-7d4b444649-nnc9n 1/1 Running 0 37m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hse-api ClusterIP 10.103.119.87 <none> 5000/TCP 37m
service/hse-database ClusterIP 10.108.4.231 <none> 5432/TCP 37m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/hse-api 0/1 1 0 37m
deployment.apps/postgres 1/1 1 1 37m
NAME DESIRED CURRENT READY AGE
replicaset.apps/hse-api-5c7f656b8c 1 1 0 37m
replicaset.apps/postgres-7d4b444649 1 1 1 37m
另一方面,Api pod 会抛出 CrashLoopBackOff 错误,因为找不到 entrypoint.sh。
Port: 5000/TCP
Host Port: 0/TCP
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: ContainerCannotRun
Message: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/usr/src/app/api/entrypoint.sh": stat /usr/src/app/api/entrypoint.sh: no such file or directory: unknown
但是,当我尝试从 docker-hub 映像运行容器时:
docker run -it --rm imranoshpro/hse-api:v0.2.1 /bin/sh
看起来成功定位到文件,但是这次错误是找不到数据库服务器。
入口点文件无法获取可能是什么原因?
部署yaml如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hse-api
namespace: hse-app
spec:
replicas: 1
selector:
matchLabels:
app: hse-api
template:
metadata:
labels:
app: hse-api
spec:
containers:
- name: hse-api
image: imranoshpro/hse-api:v0.2.1
imagePullPolicy: Always
ports:
- containerPort: 5000
envFrom:
- secretRef:
name: hse-api-secrets
volumeMounts:
- name: api-volume
mountPath: /usr/src/app/api
volumes:
- name: api-volume
persistentVolumeClaim:
claimName: api-pvc
imagePullSecrets:
- name: docker-hub-secret
和PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: api-pvc
namespace: hse-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
在 Kubernetes 设置中,您将创建一个 PersistentVolumeClaim,然后将其安装在 Pod 规范中的
/usr/src/app/api
上。 创建的 PersistentVolume 一开始是空的,直到有明确的写入内容为止,因此这具有隐藏图像中所有代码的效果。
您应该删除整个 PersistentVolumeClaim,以及将其安装到容器中的部分
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: api-pvc # <-- delete this entire object
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hse-api
spec:
template:
spec:
containers:
- name: hse-api
volumeMounts: # <-- delete this entire section
- name: api-volume
mountPath: /usr/src/app/api
volumes: # <-- delete this entire section
- name: api-volume
persistentVolumeClaim:
claimName: api-pvc
同样,在 Compose 文件中,您应该删除
volumes:
容器的
api
块
services:
api:
volumes: # <-- delete this entire section
- ./hse_api:/usr/src/app/api
在普通 Docker 或 Compose 中,这会将映像中的代码替换为主机系统上的代码。 Kubernetes 作为一个通常是远程的集群环境,无法看到您的主机系统。 此外,由于您要用其他内容替换映像的代码,因此在这个 Compose 设置中,您永远不会真正运行映像中的内容,因此您很容易遇到 Docker 设置的“在我的机器上运行”之类的问题一般情况下尽量避免。