Как исправить «не удалось распаковать изображение в overlayfs снапшоттера: неожиданный тип носителя text/html», когда MicroK8S начинает развертывание?
Я продолжаю идти по разочаровывающему пути изучения Kubernetes (в частности, MicroK8S).
Я создаю образ локально на ноутбуке для разработки следующим образом:
docker build -t k8s-workload .
Это простое веб-приложение PHP, которое сообщает некоторые метаданные запроса. Он успешно строится:
Sending build context to Docker daemon 13.82kB
Step 1/5 : FROM php:8.2-cli-alpine
---> c5f1f9770838
Step 2/5 : WORKDIR /root
---> Using cache
---> 492c997c963b
Step 3/5 : RUN apk update && apk upgrade
---> Using cache
---> f91505d5fe68
Step 4/5 : COPY src /root
---> 02bcc72dfc97
Step 5/5 : CMD ["sh", "/root/bin/start-server.sh"]
---> Running in 6bc3b72365e4
Removing intermediate container 6bc3b72365e4
---> 0c8a405b06af
Successfully built 0c8a405b06af
Successfully tagged k8s-workload:latest
Я создаю из этого архив, чтобы его можно было отправить в мой трехузловой кластер:
docker save k8s-workload > k8s-workload.docker.tar
Затем я отправляю его лидеру кластера (хотя я предполагаю, что его можно отправить любому из них):
scp k8s-workload.docker.tar 192.168.50.251:/home/myuser/
Пока все выглядит хорошо. Теперь я хочу загрузить изображение во все узлы кластера:
root@arran:/home/myuser# microk8s images import < k8s-workload.docker.tar
Pushing OCI images to 192.168.50.251:25000
Pushing OCI images to 192.168.50.135:25000
Pushing OCI images to 192.168.50.74:25000
Увидев, что это удалось, я попытался создать рабочую нагрузку:
root@arran:/home/myuser# microk8s kubectl create deployment k8s-workload --image=k8s-workload
Наконец, давайте получим статус этого модуля:
root@arran:/home/myuser# microk8s kubectl get pods
NAME READY STATUS RESTARTS AGE
k8s-workload-6cdfbb6b59-zvgrl 0/1 ImagePullBackOff 0 35m
Ладно, это выглядит не очень хорошо. Также была ошибка ErrImagePull, но сейчас она, похоже, заменена.
Как я могу отладить, почему изображение не запускается?
Я нашел способ составить список изображений на узле. Я нашел свое недавно созданное изображение на ведущем узле:
root@arran:/home/myuser# microk8s ctr images list | grep workload
docker.io/library/k8s-workload:latest application/vnd.docker.distribution.manifest.v2+json sha256:725b...582b 103.5 MiB linux/amd64
Итак, изображение имеется. Я могу получить некоторые журналы о проблеме, но они не показывают ничего, чего я еще не знаю:
root@arran:/home/myuser# microk8s kubectl logs k8s-workload-1cdfaa6c49-zvgrl
Error from server (BadRequest): container "k8s-workload" in pod "k8s-workload-1cdfaa6c49-zvgrl" is waiting to start: trying and failing to pull image
Что я могу попробовать дальше? Насколько мне известно, ни одному узлу на самом деле не потребуется извлекать изображение, поскольку все они доступны на каждом узле.
Обновление 1
Я не решался добавлять слишком много проблем к одному вопросу, но в целом я думаю, что их стоит добавить, поскольку все они являются препятствиями для получения одного результата: успешного развертывания тривиальной рабочей нагрузки на K8S.
Описывая один модуль в одном развертывании, я заметил следующую ошибку:
В kubelet не настроен IP-адрес ClusterDNS, и он не может создать под, используя политику «ClusterFirst». Возврат к политике «По умолчанию».
Ура! Еще одна вещь, которая не работает из коробки. Я исправил это способом MicroK8S, используя этот ответ . Это не решило проблему, но, по крайней мере, я разбиваю препятствия один за другим.
Обновление 2
Я хотел проверить правильность загруженного неопубликованного изображения, поэтому сделал это с лидером:
root@arran:/home/myuser# docker load < k8s-workload.docker.tar
Это отлично распаковывается:
bb01bd7e32b5: Loading layer [==================================================>] 7.618MB/7.618MB
e759f13eb8bc: Loading layer [==================================================>] 6.015MB/6.015MB
1a72c946ba2b: Loading layer [==================================================>] 12.29kB/12.29kB
9bbacedbd5e4: Loading layer [==================================================>] 6.144kB/6.144kB
53b5e1394bc2: Loading layer [==================================================>] 12.08MB/12.08MB
aff825926dad: Loading layer [==================================================>] 4.096kB/4.096kB
c76bce6229c6: Loading layer [==================================================>] 71.7MB/71.7MB
0503c7346508: Loading layer [==================================================>] 12.8kB/12.8kB
8c2f9e7d94bb: Loading layer [==================================================>] 65.54kB/65.54kB
7e0ad9ed4982: Loading layer [==================================================>] 10.97MB/10.97MB
b99f234d8751: Loading layer [==================================================>] 5.632kB/5.632kB
Loaded image: k8s-workload:latest
Затем я запускаю его на лидере на специальном порту (т.е. это в Docker, а не в K8S):
root@arran:/home/myuser# docker run -p 9000:80 -it k8s-workload
Это отвечает через cURL, как и следовало ожидать от другой машины в локальной сети.
Обновление 3
Мне пришло в голову, что имя изображения в пространстве имен может быть другим - следует ли указыватьdocker.io/library/k8s-workload:latest
скорее, чемk8s-workload
? Я попробовал оба варианта и обнаружил, что получаю один и тот же результат.
Итак, вот последняя ошибка:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m46s default-scheduler Successfully assigned default/k8s-workload-68c899df98-qhmhr to yamazaki
Normal Pulling 3m17s (x4 over 4m45s) kubelet Pulling image "k8s-workload"
Warning Failed 3m15s (x4 over 4m43s) kubelet Failed to pull image "k8s-workload": rpc error: code = NotFound desc = failed to pull and unpack image "docker.io/library/k8s-workload:latest": failed to unpack image on snapshotter overlayfs: unexpected media type text/html for sha256:e823...45c8: not found
Warning Failed 3m15s (x4 over 4m43s) kubelet Error: ErrImagePull
Warning Failed 2m52s (x6 over 4m43s) kubelet Error: ImagePullBackOff
Normal BackOff 2m37s (x7 over 4m43s) kubelet Back-off pulling image "k8s-workload"
Хорошо, теперь у меня есть немного больше деталей. Что на самом деле означает ошибка «не удалось распаковать образ»?
Обновление 4
Полезный ответ ниже предполагает, что мне, возможно, придется установить политику извлечения, чтобы K8S ожидал, что образ будет доступен на каждом узле, и что он не должен пытаться получить их (он не существует нигде удаленно).
Однако, приняв предоставленный совет, я получаю другой код ошибки (CreateContainerError
), основная причина та же:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 64s default-scheduler Successfully assigned default/k8s-workload to yamazaki
Normal Pulled 6s (x7 over 62s) kubelet Container image "k8s-workload" already present on machine
Warning Failed 6s (x7 over 62s) kubelet Error: failed to create containerd container: error unpacking image: unexpected media type text/html for sha256:1f2c...753e1: not found
Обновление 5
На данный момент я сообщил об этом как об ошибке , хотя все равно буду рад ответам здесь.
Обновление 6
На том основании, что упорная настойчивость таинственным образом полезна для души, я попытался удалить изображение с помощьюctr
подкоманда. Это на ведомом узле:
root@yamazaki:/home/myuser# microk8s ctr images rm docker.io/library/k8s-workload:latest
docker.io/library/k8s-workload:latest
Затем, используя ту же подкоманду, я повторно импортировал:
root@yamazaki:/home/myuser# microk8s ctr images import k8s-workload.docker.tar
unpacking docker.io/library/k8s-workload:latest (sha256:725b...582b)...done
Поскольку это работает на уровне узла, а не кластера, я сделал это для каждого из трех узлов.
Затем я использовалrun
команда, поскольку это позволяет установить политику извлечения, и я не хочу путать проблему распаковки с проблемой извлечения сверху. Это снова о лидере кластера:
root@arran:/home/myuser# microk8s kubectl run k8s-workload --image=k8s-workload --image-pull-policy='Never' --port=80
pod/k8s-workload created
Затем я описываю получившийся модуль и получаю знакомую ошибку:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 36s default-scheduler Successfully assigned default/k8s-workload to yamazaki
Normal Pulled 6s (x5 over 35s) kubelet Container image "k8s-workload" already present on machine
Warning Failed 6s (x5 over 35s) kubelet Error: failed to create containerd container: error unpacking image: unexpected media type text/html for sha256:5f76...a3aa: not found
Как это ни парадоксально, это обнадеживает: отправка изображения на каждый узел по отдельности является настоящей проблемой, и поэтому я бы хотел, чтобы импорт изображения на уровне кластера работал. Я подозреваю, что это произойдет, как только я разберусь с проблемой распаковки.
Обновление 7
Да, я кое-что заметил. Как и следовало ожидать, архив изображений на всех узлах имеет одинаковую контрольную сумму. Но при импорте один узел сообщает неправильный тип изображения. Они слегка переформатированы для удобства сравнения:
Узел «Арран»:
Узел «Ямадзаки»:
docker.io/library/k8s-workload:latest
text/html
sha256:5f76...a3aa 218.4 KiB
-
io.cri-containerd.image=managed
Узел «Никка»:
docker.io/library/k8s-workload:latest
application/vnd.docker.distribution.manifest.v2+json
sha256:725b...582b 103.5 MiB
linux/amd64
io.cri-containerd.image=managed
Похоже, что рабочие нагрузки последовательно выбирались для запуска на Yamazaki, и это узел с поврежденным образом. Теперь, чтобы повторно импортировать изображение и привести его в соответствие с остальными...