Введение
В предыдущих лабораторных работах по развертыванию использовались образы, которые уже существовали в реестре или кэше кластера. Разработчикам приложений также необходимо понимать рабочий процесс с локальными образами: сборка образа из файлов приложения, предоставление этого образа узлу Kubernetes и настройка Deployment для его использования.
В этой лабораторной работе вы соберете небольшой образ веб-приложения локально с помощью Minikube, развернете его с параметром imagePullPolicy: Never, а затем пересоберете приложение с новым тегом образа для выполнения последовательного обновления (rolling update). Это отражает типичную задачу в стиле CKAD: связать артефакт приложения с рабочей нагрузкой Kubernetes, которая его запускает.
Подготовка рабочего пространства для локального образа
На этом этапе вы подготовите чистый namespace и убедитесь, что путь для сборки образа доступен.
Начните работу в директории /home/labex/project. В этой папке вы создадите файлы приложения, файлы для сборки образа и манифесты Kubernetes.
mkdir -p /home/labex/project
cd /home/labex/project
Проверьте доступность API-сервера Kubernetes. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и повторите команду.
kubectl get nodes --request-timeout=5s
Ожидаемый вывод:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Дождитесь, пока Pod сетевого плагина кластера перейдет в состояние Ready. Приложение будет тестироваться через Service, поэтому сетевая инфраструктура должна быть исправна.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Ожидаемый вывод:
pod/calico-node-... condition met
Создайте namespace с именем ckad-prep-local-image и установите его в качестве текущего:
kubectl create namespace ckad-prep-local-image
kubectl config set-context --current --namespace=ckad-prep-local-image
Проверьте namespace и ознакомьтесь с командой сборки образа в Minikube. Команда minikube image build собирает образ непосредственно для профиля Minikube, поэтому Pod'ы могут использовать его без отправки в реестр.
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
minikube image build --help | sed -n '1,4p'
Ожидаемый вывод:
ckad-prep-local-image
Build a container image...
Сборка первого локального образа
На этом этапе вы создадите небольшое веб-приложение и соберете его как local-message-app:v1.
Образ будет использовать httpd из BusyBox для отдачи одного статического файла. Содержимое файла — это отображаемая версия приложения, чтобы позже вы могли подтвердить, какой тег образа запущен в Kubernetes.
Создайте директорию приложения и первую веб-страницу:
mkdir -p local-message-app/www
cat > local-message-app/www/index.html <<'EOF'
local-image-v1
EOF
Создайте Dockerfile. Инструкция COPY помещает ваш локальный файл www/index.html в образ, а CMD запускает веб-сервер BusyBox на порту 8080 при запуске контейнера из этого образа.
cat > local-message-app/Dockerfile <<'EOF'
FROM busybox:1.36
COPY www/index.html /www/index.html
EXPOSE 8080
CMD ["httpd", "-f", "-p", "8080", "-h", "/www"]
EOF
Соберите образ для активного профиля Minikube. Опция -t присваивает образу локальный тег, а последний аргумент — это путь к контексту сборки.
minikube image build --profile labex-v135 -t local-message-app:v1 ./local-message-app
Ожидаемый вывод:
naming to docker.io/library/local-message-app:v1 done
Выведите список образов, известных Minikube, и найдите ваш новый тег:
minikube image ls --profile labex-v135 | grep local-message-app
Ожидаемый вывод:
docker.io/library/local-message-app:v1
Развертывание локального образа
На этом этапе вы запустите локальный образ в Kubernetes.
Поскольку local-message-app:v1 не отправлен в удаленный реестр, Deployment использует imagePullPolicy: Never. Это указывает kubelet использовать образ, который уже существует на узле, вместо попытки загрузить его из сети.
Создайте local-image-app.yaml:
cat > local-image-app.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-message-app
spec:
replicas: 2
selector:
matchLabels:
app: local-message-app
template:
metadata:
labels:
app: local-message-app
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: local-message-app:v1
imagePullPolicy: Never
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: local-message-app
spec:
selector:
app: local-message-app
ports:
- port: 80
targetPort: 8080
EOF
Примените манифест и дождитесь развертывания:
kubectl apply -f local-image-app.yaml
kubectl rollout status deployment/local-message-app --timeout=120s
Ожидаемый вывод:
deployment.apps/local-message-app created
service/local-message-app created
deployment "local-message-app" successfully rolled out
Создайте клиентский Pod и протестируйте Service:
kubectl run image-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/image-client --timeout=120s
kubectl exec image-client -- wget -qO- http://local-message-app
Ожидаемый вывод:
local-image-v1
Пересборка и обновление локального образа
На этом этапе вы пересоберете приложение с новым тегом образа и обновите Deployment до этого тега.
Изменение файла на диске не меняет уже запущенный образ. Вы должны собрать новый тег образа и обновить Deployment, чтобы Kubernetes запустил новые Pod'ы с этим тегом. Это делает смену версии наглядной и позволяет избежать зависимости от изменяемого содержимого локальных образов.
Замените содержимое веб-страницы на версию два:
cat > local-message-app/www/index.html <<'EOF'
local-image-v2
EOF
Соберите второй тег образа:
minikube image build --profile labex-v135 -t local-message-app:v2 ./local-message-app
Ожидаемый вывод:
naming to docker.io/library/local-message-app:v2 done
Обновите образ в Deployment и дождитесь завершения обновления:
kubectl set image deployment/local-message-app web=local-message-app:v2
kubectl rollout status deployment/local-message-app --timeout=120s
Ожидаемый вывод:
deployment.apps/local-message-app image updated
deployment "local-message-app" successfully rolled out
Подтвердите тег образа и ответ приложения:
kubectl get deployment local-message-app -o jsonpath='{.spec.template.spec.containers[0].image}'; echo
kubectl exec image-client -- wget -qO- http://local-message-app
Ожидаемый вывод:
local-message-app:v2
local-image-v2
Резюме
Вы собрали образ небольшого приложения для профиля Minikube, развернули его с параметром imagePullPolicy: Never, протестировали через Service в Kubernetes, а затем пересобрали приложение с новым тегом образа и выполнили обновление Deployment. Ключевой момент рабочего процесса заключается в том, чтобы сделать образ доступным на узле до того, как Pod'ы попытаются его запустить.



