У меня есть приложение 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 для проекта, 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, с другой стороны, выдает ошибку CrashLoopBackOff, поскольку файл inputpoint.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
И ПВХ:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: api-pvc
namespace: hse-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Отредактировано сообщение, чтобы добавить развертывание и pvc. Я думаю, ты в деле. Я удалил крепление громкости, и оно, похоже, заработало. Когда я возвращаю его обратно и запускаю его, ls -la возвращает всего 0.
В настройке Kubernetes вы создаете PersistentVolumeClaim, а затем монтируете его поверх /usr/src/app/api
в своей спецификации Pod. Созданный 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. вообще старайтесь избегать.
По большей части это правильный ответ. Однако, скажем, по какой-либо причине вам нужно создать PersistenVolumeClaim для вашего контейнера, вместо удаления монтирования вы можете создать подпапку внутри основного каталога, например /usr/src/app/api/data, что я и сделал в мое дело.
Но я отмечу это как ответ, поскольку он определил фактическую причину проблемы.
Из вопроса не очевидно, что в контейнере есть постоянный каталог данных. Часто это не лучшая практика; в контексте Kubernetes это не позволит вам масштабировать развертывание, например, до replicas: 2
. Если вы сможете хранить все данные в связанной реляционной базе данных, контейнер будет проще масштабировать и управлять им.
Правда, это на мне. Как бы вы посоветовали обращаться с данными, которые традиционно не хранятся в базе данных, такими как документы и изображения? Я бы предпочел не хранить их в виде больших двоичных объектов в своих таблицах и предпочел бы, чтобы они хранились в папках и на них ссылались URL-адреса.
Как выглядит ваше развертывание Kubernetes? Блок
volumes:
в файле Compose выглядит так, как будто он может заменить весь код в изображении чем-то другим, а это означает, что вы на самом деле не запускаете свой образ в более простой для отладки среде Docker. Если такой инструмент, как Kompose, пытается воспроизвести это монтирование привязки, код не будет нигде в кластере и может заменить код изображения пустым содержимым.