Сборка и запуск локального образа приложения

DockerBeginner
Практиковаться сейчас

Введение

В предыдущих лабораторных работах по развертыванию использовались образы, которые уже существовали в реестре или кэше кластера. Разработчикам приложений также необходимо понимать рабочий процесс с локальными образами: сборка образа из файлов приложения, предоставление этого образа узлу 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'ы попытаются его запустить.