Контейнер продолжает падать для Pod в миникубе после создания PV и PVC

у меня есть приложение REST, интегрированное с kubernetes, для тестирования запросов REST. Теперь, когда я выполняю запрос POST на стороне клиента, статус автоматически созданного задания остается PENDING на неопределенный срок. То же самое происходит с POD, который также создается автоматически.

Когда я углубился в события на панели инструментов, он подключает том, но не может смонтировать том и выдает эту ошибку:

Unable to mount volumes for pod "ingestion-88dhg_default(4a8dd589-e3d3-4424-bc11-27d51822d85b)": timeout expired waiting for volumes to attach or mount for pod "default"/"ingestion-88dhg". list of unmounted volumes=[cdiworkspace-volume]. list of unattached volumes=[cdiworkspace-volume default-token-qz2nb]

Я определил постоянный том и требование постоянного тома вручную, используя следующие коды, но не подключался ни к каким модулям. Должен ли я это сделать?

PV

{
  "kind": "PersistentVolume",
  "apiVersion": "v1",
  "metadata": {
    "name": "cdiworkspace",
    "selfLink": "/api/v1/persistentvolumes/cdiworkspace",
    "uid": "92252f76-fe51-4225-9b63-4d6228d9e5ea",
    "resourceVersion": "100026",
    "creationTimestamp": "2019-07-10T09:49:04Z",
    "annotations": {
      "pv.kubernetes.io/bound-by-controller": "yes"
    },
    "finalizers": [
      "kubernetes.io/pv-protection"
    ]
  },
  "spec": {
    "capacity": {
      "storage": "10Gi"
    },
    "fc": {
      "targetWWNs": [
        "50060e801049cfd1"
      ],
      "lun": 0
    },
    "accessModes": [
      "ReadWriteOnce"
    ],
    "claimRef": {
      "kind": "PersistentVolumeClaim",
      "namespace": "default",
      "name": "cdiworkspace",
      "uid": "0ce96c77-9e0d-4b1f-88bb-ad8b84072000",
      "apiVersion": "v1",
      "resourceVersion": "98688"
    },
    "persistentVolumeReclaimPolicy": "Retain",
    "storageClassName": "standard",
    "volumeMode": "Block"
  },
  "status": {
    "phase": "Bound"
  }
}

ПВХ

{
  "kind": "PersistentVolumeClaim",
  "apiVersion": "v1",
  "metadata": {
    "name": "cdiworkspace",
    "namespace": "default",
    "selfLink": "/api/v1/namespaces/default/persistentvolumeclaims/cdiworkspace",
    "uid": "0ce96c77-9e0d-4b1f-88bb-ad8b84072000",
    "resourceVersion": "100028",
    "creationTimestamp": "2019-07-10T09:32:16Z",
    "annotations": {
      "pv.kubernetes.io/bind-completed": "yes",
      "pv.kubernetes.io/bound-by-controller": "yes",
      "volume.beta.kubernetes.io/storage-provisioner": "k8s.io/minikube-hostpath"
    },
    "finalizers": [
      "kubernetes.io/pvc-protection"
    ]
  },
  "spec": {
    "accessModes": [
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "10Gi"
      }
    },
    "volumeName": "cdiworkspace",
    "storageClassName": "standard",
    "volumeMode": "Block"
  },
  "status": {
    "phase": "Bound",
    "accessModes": [
      "ReadWriteOnce"
    ],
    "capacity": {
      "storage": "10Gi"
    }
  }
}

Результат journalctl -xe _SYSTEMD_UNIT=kubelet.service

Jul 01 09:47:26 rehan-B85M-HD3 kubelet[22759]: E0701 09:47:26.979098   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:47:40 rehan-B85M-HD3 kubelet[22759]: E0701 09:47:40.979722   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:47:55 rehan-B85M-HD3 kubelet[22759]: E0701 09:47:55.978806   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:48:08 rehan-B85M-HD3 kubelet[22759]: E0701 09:48:08.979375   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:48:23 rehan-B85M-HD3 kubelet[22759]: E0701 09:48:23.979463   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:48:37 rehan-B85M-HD3 kubelet[22759]: E0701 09:48:37.979005   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:48:48 rehan-B85M-HD3 kubelet[22759]: E0701 09:48:48.977686   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:49:02 rehan-B85M-HD3 kubelet[22759]: E0701 09:49:02.979125   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:49:17 rehan-B85M-HD3 kubelet[22759]: E0701 09:49:17.979408   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:49:28 rehan-B85M-HD3 kubelet[22759]: E0701 09:49:28.977499   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:49:41 rehan-B85M-HD3 kubelet[22759]: E0701 09:49:41.977771   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:49:53 rehan-B85M-HD3 kubelet[22759]: E0701 09:49:53.978605   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:50:05 rehan-B85M-HD3 kubelet[22759]: E0701 09:50:05.980251   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:50:16 rehan-B85M-HD3 kubelet[22759]: E0701 09:50:16.979292   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:50:31 rehan-B85M-HD3 kubelet[22759]: E0701 09:50:31.978346   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:50:42 rehan-B85M-HD3 kubelet[22759]: E0701 09:50:42.979302   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:50:55 rehan-B85M-HD3 kubelet[22759]: E0701 09:50:55.978043   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:51:08 rehan-B85M-HD3 kubelet[22759]: E0701 09:51:08.977540   22759 pod_workers.go:190] Error syncing pod 6577b694-f18d-4d7b-9a75-82dc17c908ca ("myplanet-d976447c6-dsfx9_default(6577b694-f18d-4d7
Jul 01 09:51:24 rehan-B85M-HD3 kubelet[22759]: E0701 09:51:24.190929   22759 remote_image.go:113] PullImage "friendly/myplanet:0.0.1-SNAPSHOT" from image service failed: rpc error: code = Unknown desc = E
Jul 01 09:51:24 rehan-B85M-HD3 kubelet[22759]: E0701 09:51:24.190971   22759 kuberuntime_image.go:51] Pull image "friendly/myplanet:0.0.1-SNAPSHOT" failed: rpc error: code = Unknown desc = Error response 
Jul 01 09:51:24 rehan-B85M-HD3 kubelet[22759]: E0701 09:51:24.191024   22759 kuberuntime_manager.go:775] container start failed: ErrImagePull: rpc error: code = Unknown desc = Error response from daemon:

Развертывание Yaml

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: back
spec:
  replicas: 1
  selector:
    matchLabels:
      app: back
  template:
    metadata:
      labels:
        app: back
    spec:
      containers:
      - name: back
        image: back:latest
        ports:
        - containerPort: 8081
          protocol: TCP
        volumeMounts:
        - mountPath: /data
          name: back
      volumes:
      - name: back
        hostPath:
          # directory location on host
          path: /back
          # this field is optional
          type: Directory

Файл Docker

FROM python:3.7-stretch

COPY . /code

WORKDIR /code

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

RUN pip install -r requirements.txt

ENTRYPOINT ["python", "ingestion.py"]

pyython-файл1

import os
import shutil
import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(name)s - %(message)s')
logger = logging.getLogger("ingestion")

import requests

import datahub

scihub_username = os.environ["scihub_username"]
scihub_password = os.environ["scihub_password"]
result_url = "http://" + os.environ["CDINRW_BASE_URL"] + "/jobs/" + os.environ["CDINRW_JOB_ID"] + "/results"

logger.info("Searching the Copernicus Open Access Hub")
scenes = datahub.search(username=scihub_username,
                        password=scihub_password,
                        producttype=os.getenv("producttype"),
                        platformname=os.getenv("platformname"),
                        days_back=os.getenv("days_back", 2),
                        footprint=os.getenv("footprint"),
                        max_cloud_cover_percentage=os.getenv("max_cloud_cover_percentage"),
                        start_date = os.getenv("start_date"),
                        end_date = os.getenv("end_date"))

logger.info("Found {} relevant scenes".format(len(scenes)))

job_results = []
for scene in scenes:
    # do not donwload a scene that has already been ingested
    if os.path.exists(os.path.join("/out_data", scene["title"]+".SAFE")):
        logger.info("The scene {} already exists in /out_data and will not be downloaded again.".format(scene["title"]))
        filename = scene["title"]+".SAFE"
    else:
        logger.info("Starting the download of scene {}".format(scene["title"]))
        filename = datahub.download(scene, "/tmp", scihub_username, scihub_password, unpack=True)
        logger.info("The download was successful.")
        shutil.move(filename, "/out_data")
    result_message = {"description": "test",
                      "type": "Raster",
                      "format": "SAFE",
                      "filename": os.path.basename(filename)}
    job_results.append(result_message)

res = requests.put(result_url, json=job_results, timeout=60)
res.raise_for_status()

**файл Python 2 **

import logging
import os
import urllib.parse
import zipfile

import requests

# constructing URLs for querying the data hub
_BASE_URL = "https://scihub.copernicus.eu/dhus/"
SITE = {}
SITE["SEARCH"] = _BASE_URL + "search?format=xml&sortedby=beginposition&order=desc&rows=100&start={offset}&q="
_PRODUCT_URL = _BASE_URL + "odata/v1/Products('{uuid}')/"
SITE["CHECKSUM"] = _PRODUCT_URL + "Checksum/Value/$value"
SITE["SAFEZIP"] = _PRODUCT_URL + "$value"

logger = logging.getLogger(__name__)

def _build_search_url(producttype=None, platformname=None, days_back=2, footprint=None, max_cloud_cover_percentage=None, start_date=None, end_date=None):
    search_terms = []
    if producttype:
        search_terms.append("producttype:{}".format(producttype))
    if platformname:
        search_terms.append("platformname:{}".format(platformname))
    if start_date and end_date:
        search_terms.append(
            "beginPosition:[{}+TO+{}]".format(start_date, end_date))
    elif days_back:
        search_terms.append(
            "beginPosition:[NOW-{}DAYS+TO+NOW]".format(days_back))
    if footprint:
        search_terms.append("footprint:%22Intersects({})%22".format(
            footprint.replace(" ", "+")))
    if max_cloud_cover_percentage:
        search_terms.append("cloudcoverpercentage:[0+TO+{}]".format(max_cloud_cover_percentage))
    url = SITE["SEARCH"] + "+AND+".join(search_terms)
    return url


def _unpack(zip_file, directory, remove_after=False):
    with zipfile.ZipFile(zip_file) as zf:
        # This assumes that the zipfile only contains the .SAFE directory at root level
        safe_path = zf.namelist()[0]
        zf.extractall(path=directory)
    if remove_after:
        os.remove(zip_file)
    return os.path.normpath(os.path.join(directory, safe_path))


def search(username, password, producttype=None, platformname=None ,days_back=2, footprint=None, max_cloud_cover_percentage=None, start_date=None, end_date=None):
    """ Search the Copernicus SciHub

    Parameters
    ----------
    username : str
      user name for the Copernicus SciHub
    password : str
      password for the Copernicus SciHub
    producttype : str, optional
      product type to filter for in the query (see https://scihub.copernicus.eu/userguide/FullTextSearch#Search_Keywords for allowed values)
    platformname : str, optional 
      plattform name to filter for in the query (see https://scihub.copernicus.eu/userguide/FullTextSearch#Search_Keywords for allowed values)
    days_back : int, optional
      number of days before today that will be searched. Default are the last 2 days. If start and end date are set the days_back parameter is ignored
    footprint : str, optional
      well-known-text representation of the footprint
    max_cloud_cover_percentage: str, optional
      percentage of cloud cover per scene. Can only be used in combination with Sentinel-2 imagery. 
      (see https://scihub.copernicus.eu/userguide/FullTextSearch#Search_Keywords for allowed values)
    start_date: str, optional
        start point of the search extent has to be used in combination with end_date
    end_date: str, optional
        end_point of the search extent has to be used in combination with start_date

    Returns
    -------
    list
      a list of scenes that match the search parameters
    """

    import xml.etree.cElementTree as ET
    scenes = []
    search_url = _build_search_url(producttype, platformname, days_back, footprint, max_cloud_cover_percentage, start_date, end_date)
    logger.info("Search URL: {}".format(search_url))
    offset = 0
    rowsBreak = 5000
    name_space = {"atom": "http://www.w3.org/2005/Atom",
                  "opensearch": "http://a9.com/-/spec/opensearch/1.1/"}
    while offset < rowsBreak:  # Next pagination page:
        response = requests.get(search_url.format(offset=offset), auth=(username, password))
        root = ET.fromstring(response.content)
        if offset == 0:
            rowsBreak = int(
                root.find("opensearch:totalResults", name_space).text)
        for e in root.iterfind("atom:entry", name_space):
            uuid = e.find("atom:id", name_space).text
            title = e.find("atom:title", name_space).text
            begin_position = e.find(
                "atom:date[@name='beginposition']", name_space).text
            end_position = e.find(
                "atom:date[@name='endposition']", name_space).text
            footprint = e.find("atom:str[@name='footprint']", name_space).text
            scenes.append({
                "id": uuid,
                "title": title,
                "begin_position": begin_position,
                "end_position": end_position,
                "footprint": footprint})
        # Ultimate DHuS pagination page size limit (rows per page).
        offset += 100
    return scenes


def download(scene, directory, username, password, unpack=True):
    """ Download a Sentinel scene based on its uuid

    Parameters
    ----------
    scene : dict
        the scene to be downloaded
    path : str
        the path where the file will be downloaded to
    username : str
        username for the Copernicus SciHub
    password : str
        password for the Copernicus SciHub
    unpack: boolean, optional
        flag that defines whether the downloaded product should be unpacked after download. defaults to true

    Raises
    ------
    ValueError
        if the size of the downloaded file does not match the Content-Length header
    ValueError
        if the checksum of the downloaded file does not match the checksum provided by the Copernicus SciHub

    Returns
    -------
    str
        path to the downloaded file
    """

    import hashlib
    md5hash = hashlib.md5()
    md5sum = requests.get(SITE["CHECKSUM"].format(
        uuid=scene["id"]), auth=(username, password)).text

    download_path = os.path.join(directory, scene["title"] + ".zip")
    # overwrite if path already exists
    if os.path.exists(download_path):
        os.remove(download_path)
    url = SITE["SAFEZIP"].format(uuid=scene["id"])
    rsp = requests.get(url, auth=(username, password), stream=True)
    cl = rsp.headers.get("Content-Length")
    size = int(cl) if cl else -1
    # Actually fetch now:
    with open(download_path, "wb") as f:  # Do not read as a whole into memory:
        written = 0
        for block in rsp.iter_content(8192):
            f.write(block)
            written += len(block)
            md5hash.update(block)
    written = os.path.getsize(download_path)
    if size > -1 and written != size:
        raise ValueError("{}: size mismatch, {} bytes written but expected {} bytes to write!".format(
            download_path, written, size))
    elif md5sum:
        calculated = md5hash.hexdigest()
        expected = md5sum.lower()
        if calculated != expected:
            raise ValueError("{}: MD5 mismatch, calculated {} but expected {}!".format(
                download_path, calculated, expected))
    if unpack:
        return _unpack(download_path, directory, remove_after=False)
    else:
        return download_path

Как я могу правильно и автоматически установить том на модуль? Я не хочу создавать модули вручную для каждой службы REST и назначать им тома


person rehan    schedule 10.07.2019    source источник
comment
Несколько дополнительных вопросов: Не могли бы вы проверить и опубликовать результат journalctl -xe _SYSTEMD_UNIT=kubelet.service? Есть ли что-нибудь, связанное с проблемами с монтированием томов? Еще одна вещь ... Не могли бы вы также показать свое определение Deployment/Pod, где объявлено ваше монтирование тома?   -  person mario    schedule 17.07.2019
comment
@mario, я добавил ответ из приведенного выше утверждения на вопрос. Однако изображение, которое отображается в ошибке, не из докера minikube. это из докера моей системы, но интересно то, что у меня уже есть запущенное развертывание из образа в докере minikube, которое работает нормально. это не правильно настраивает среду докера?   -  person rehan    schedule 19.07.2019
comment
@mario также я добавил файл Deployment.yaml для сломанного модуля, если это то, что вы имели в виду под определением модуля, однако я нигде явно не монтирую том?   -  person rehan    schedule 19.07.2019
comment
Что касается логов, я не вижу там ничего, связанного с проблемами с монтированием томов, поэтому пока не обращайте на них внимания, проверьте действия, описанные в моем ответе.   -  person mario    schedule 19.07.2019


Ответы (2)


я снова просмотрел журналы модуля и понял, что параметры, необходимые для python file1, не были предоставлены и вызывали сбой контейнера. я протестировал его, предоставив все недостающие параметры, указанные в журналах, и указав их в deployment.yaml для модуля, который теперь выглядел так:

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: back
spec:
  replicas: 1
  selector:
    matchLabels:
      app: back
  template:
    metadata:
      creationTimestamp: 
      labels:
        app: back
    spec:
      containers:
      - name: back
        image: back:latest
        imagePullPolicy: Never
        env:
        - name: scihub_username
          value: test
        - name: scihub_password
          value: test
        - name: CDINRW_BASE_URL
          value: 10.1.40.11:8081/swagger-ui.html
        - name: CDINRW_JOB_ID
          value: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        ports:
        - containerPort: 8081
          protocol: TCP
        volumeMounts:
        - mountPath: /data
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          # directory location on host
          path: /back
          # this field is optional
          type: Directory

Это начало загрузку данных и решило проблему на данный момент, однако я не хочу, чтобы это работало, поскольку я хочу, чтобы оно запускалось через REST API, который предоставляет все параметры, а также запускает и останавливает этот контейнер. Я создам для этого отдельный вопрос и свяжу его ниже, чтобы кто-нибудь мог подписаться.

person rehan    schedule 31.07.2019

Я определил постоянный том и требование постоянного тома вручную, используя следующие коды, но не подключался ни к каким модулям. Должен ли я это сделать?

Значит, вы до сих пор никак не упоминали об этом в своем Pod определении, верно? По крайней мере, я не вижу его нигде в вашем Deployment. Если да, то ответ: да, вы должны сделать это, чтобы поды в вашем кластере могли его использовать.

Начнем с самого начала. По сути, весь процесс настройки Pod (применяется также к шаблону Pod в определении развертывания) для использования PersistentVolume для хранения состоит из 3 шагов [источник]:

  1. Администратор кластера создает PersistentVolume, поддерживаемый физическим хранилищем. Администратор не связывает том ни с одним подом.

  2. Пользователь кластера создает PersistentVolumeClaim, который автоматически привязывается к подходящему PersistentVolume.

  3. Пользователь создает Pod (это также может быть Deployment, в котором вы определяете определенную спецификацию шаблона пода), который использует PersistentVolumeClaim в качестве хранилища.

Нет смысла подробно описывать здесь все вышеперечисленные шаги, так как это уже сделано очень хорошо здесь.

Проверить доступность PV/PVC можно с помощью следующих команд:

kubectl get pv volume-name на этом этапе статус вашего тома должен отображаться как Bound

то же самое с kubectl get pvc task-pv-claim (в вашем случае kubectl get pvc cdiworkspace, однако я бы рекомендовал использовать другое имя, например, cdiworkspace-claim для PersistentVolumeClaim, чтобы его можно было легко отличить от самого PersistentVolume) - эта команда также должна показывать статус Bound

Обратите внимание, что в файле конфигурации Pod указано только PersistentVolumeClaim, но не указано само PersistentVolume. С точки зрения Pod претензия — это том. Вот хорошее описание, которое ясно отмечает разницу между этими двумя объектами[источник] :

PersistentVolume (PV) — это часть хранилища в кластере, которая была предоставлена ​​администратором или динамически предоставлена ​​с использованием классов хранения. Это ресурс в кластере, точно так же, как узел является ресурсом кластера. PV — это плагины тома, такие как Volumes, но их жизненный цикл не зависит от любого отдельного модуля, который использует PV. Этот объект API собирает сведения о реализации хранилища, будь то NFS, iSCSI или система хранения, специфичная для облачного провайдера.

PersistentVolumeClaim (PVC) — это запрос пользователя на хранение. Он похож на стручок. Поды потребляют ресурсы узлов, а PVC — ресурсы PV. Поды могут запрашивать определенные уровни ресурсов (ЦП и памяти). Утверждения могут запрашивать определенный размер и режимы доступа (например, могут быть смонтированы один раз для чтения/записи или много раз только для чтения).

Ниже приведен пример спецификации в определении Pod / Deployment, который относится к существующему PersistentVolumeClaim:

spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

Что касается вашего вопроса:

Как я могу правильно и автоматически установить том на модуль? я не хочу создавать модули вручную для каждой службы REST и назначать им тома

Вам не нужно создавать их вручную. Вы можете указать PersistentVolumeClaim, который они используют в спецификации шаблона пода, в вашем определении Deployment.

Документационные ресурсы:

Подробное пошаговое описание того, как настроить Pod для использования PersistentVolumeClaim в качестве хранилища, вы можете найти здесь.

Подробнее о концепции постоянных томов в Kubernetes можно узнать в этой статье. .

Если вы хотите поделиться некоторыми данными, доступными на вашем хосте minikube, с каждым Pod в вашем кластере, существует гораздо более простой подход, чем PersistentVolume. Он называется hostPath. Подробное описание вы можете найти здесь, а ниже пример, который может быть полезен в вашем конкретном случае:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          # directory location on host
          path: /directory/with/python/files
          # this field is optional
          type: Directory

Примеры, которые вы разместили, на самом деле в формате json, а не в формате yaml. Вы сможете легко преобразовать их в требуемый формат на этой странице. Вы должны поместить свои файлы в /directory/with/python/files на хосте minikube, и они будут доступны в каталоге /data в каждом поде, созданном вашим развертыванием.

Ниже ваше развертывание в формате yaml с каталогом /directory/with/python/files на вашем хосте, смонтированным в /data с использованием hostPath:

---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: back
  namespace: default
  selfLink: "/apis/extensions/v1beta1/namespaces/default/deployments/back"
  uid: 9f21717c-2c04-459f-b47a-95fd8e11728d
  resourceVersion: '298987'
  generation: 1
  creationTimestamp: '2019-07-16T13:16:15Z'
  labels:
    run: back
  annotations:
    deployment.kubernetes.io/revision: '1'
spec:
  replicas: 1
  selector:
    matchLabels:
      run: back
  template:
    metadata:
      creationTimestamp: 
      labels:
        run: back
    spec:
      containers:
      - name: back
        image: back:latest
        ports:
        - containerPort: 8080
          protocol: TCP
        volumeMounts:
        - mountPath: /data
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          # directory location on host
          path: /directory/with/python/files
          # this field is optional
          type: Directory
        resources: {}
        terminationMessagePath: "/dev/termination-log"
        terminationMessagePolicy: File
        imagePullPolicy: Never
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      schedulerName: default-scheduler
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600
status:
  observedGeneration: 1
  replicas: 1
  updatedReplicas: 1
  unavailableReplicas: 1
  conditions:
  - type: Progressing
    status: 'True'
    lastUpdateTime: '2019-07-16T13:16:34Z'
    lastTransitionTime: '2019-07-16T13:16:15Z'
    reason: NewReplicaSetAvailable
    message: ReplicaSet "back-7fd9995747" has successfully progressed.
  - type: Available
    status: 'False'
    lastUpdateTime: '2019-07-19T08:32:49Z'
    lastTransitionTime: '2019-07-19T08:32:49Z'
    reason: MinimumReplicasUnavailable
    message: Deployment does not have minimum availability.
person mario    schedule 19.07.2019
comment
мне также нужно определить секреты, потому что в настоящее время в моем модуле под volumeMounts, когда я создаю модуль, используя приведенный выше ответ, он использует секреты по умолчанию и какой том является task-pv-storage в примере создания модуля. не могли бы вы определить это. это нигде не определено - person rehan; 26.07.2019
comment
также я не думаю, что это связано с конфигурациями PV/PVC, потому что один из моих контейнеров без каких-либо файлов Python работает нормально, но остальные, которым требуется файл Docker для запуска файла Python, выдают ошибку back-off restarting failed container. я прикрепил файл докера и его вспомогательный файл для дальнейшего просмотра - person rehan; 26.07.2019
comment
Если ваши поды используют какой-то определенный секрет, вы должны указать его в определении развертывания. Подробнее об использовании секретов можно прочитать kubernetes.io/docs/concepts/configuration/. secret/#using-secrets Что касается другой ошибки, похоже, она не имеет ничего общего с предыдущей, которую вы упомянули. И как вы предоставляете эти файлы модулям? Доступны ли они через смонтированный том? - person mario; 26.07.2019
comment
поэтому я монтирую свой локальный репозиторий, где хранятся файлы, затем подключаюсь к minikube по ssh и создаю образ докера в minikube, а затем выхожу. затем я развертываю и создаю модуль через это: sudo kubectl run back --image=back:latest --port=8080 --image-pull-policy Never . Когда я создаю образ в миникубе, я думаю, у них должны быть все эти файлы. как мне указать путь монтирования для тома, созданного в миникубе? - person rehan; 26.07.2019
comment
Есть что-нибудь интересное в логах контейнеров? Попробуйте docker logs container-name или kubectl logs pod-name Значит, он использует не PersistentVolumeClaim, а какую-то папку хоста? Взгляните также на этот kubernetes.io/docs/setup/learning -среда/миникубе/ - person mario; 26.07.2019
comment
для обеих команд вывод no such container:back &pods:back not found. Хотя и изображение, и модуль доступны в миникубе. - person rehan; 26.07.2019
comment
как мне определить «путь монтирования» в volume mount при создании модуля в ответе выше. Пример в документах работает нормально. я создал каталог /mnt/data и встроил в него свой образ, но это привело к той же ошибке. Как правильно объявить путь и что там должно быть? - person rehan; 26.07.2019
comment
@rehan, пожалуйста, посмотрите мое последнее редактирование моего ответа, я думаю, это может быть на самом деле лучшее решение для вас, чем использование PersistentVolume, особенно если вы используете простую установку minikube с одним узлом. - person mario; 26.07.2019