Назад | Перейти на главную страницу

Старый модуль не удален после непрерывного обновления

Я столкнулся с проблемой при выполнении скользящего обновления нашего веб-сайта, которое выполняется в контейнере в модуле в нашем кластере, называемом веб-кластером. Кластер состоит из двух контейнеров. У одного модуля есть контейнер, в котором работает наш производственный веб-сайт, а у другого - контейнер, в котором работает промежуточная версия того же сайта. Вот yaml для контроллера репликации для производственного модуля:

apiVersion: v1
kind: ReplicationController
metadata:
  # These labels describe the replication controller
  labels:
    project: "website-prod"
    tier: "front-end"
    name: "website"
  name: "website"
spec:  # specification of the RC's contents
  replicas: 1
  selector:
    # These labels indicate which pods the replication controller manages
    project: "website-prod"
    tier: "front-end"
    name: "website"
  template:
    metadata:
      labels:
        # These labels belong to the pod, and must match the ones immediately above
        # name: "website"
        project: "website-prod"
        tier: "front-end"
        name: "website"
    spec:
      containers:
      - name: "website"
        image: "us.gcr.io/skywatch-app/website"
        ports:
        - name: "http"
          containerPort: 80
        command: ["nginx", "-g", "daemon off;"]
        livenessProbe:
          httpGet:
            path: "/"
            port: 80
          initialDelaySeconds: 60
          timeoutSeconds: 3

Мы внесли изменение, добавив на наш сайт новую страницу. После развертывания в производственном модуле мы получали прерывистые сообщения 404 при тестировании производственного сайта. Мы используем следующие команды для обновления модуля (предполагается, что сейчас работает версия 95.0):

packer build website.json
gcloud docker push us.gcr.io/skywatch-app/website
gcloud container clusters get-credentials website-cluster --zone us-central1-f
kubectl rolling-update website --update-period=20s --image=us.gcr.io/skywatch-app/website:96.0

Вот результат выполнения этих команд:

==> docker: Creating a temporary directory for sharing data...
==> docker: Pulling Docker image: nginx:1.9.7
    docker: 1.9.7: Pulling from library/nginx
    docker: d4bce7fd68df: Already exists
    docker: a3ed95caeb02: Already exists
    docker: a3ed95caeb02: Already exists
    docker: 573113c4751a: Already exists
    docker: 31917632be33: Already exists
    docker: a3ed95caeb02: Already exists
    docker: 1e7c116578c5: Already exists
    docker: 03c02c160fd7: Already exists
    docker: f852bb4464c4: Already exists
    docker: a3ed95caeb02: Already exists
    docker: a3ed95caeb02: Already exists
    docker: a3ed95caeb02: Already exists
    docker: Digest: sha256:3b50ebc3ae6fb29b713a708d4dc5c15f4223bde18ddbf3c8730b228093788a3c
    docker: Status: Image is up to date for nginx:1.9.7
==> docker: Starting docker container...
    docker: Run command: docker run -v /tmp/packer-docker358675979:/packer-files -d -i -t nginx:1.9.7 /bin/bash
    docker: Container ID: 0594bf37edd1311535598971140535166df907b1c19d5f76ddda97c53f884d5b
==> docker: Provisioning with shell script: /tmp/packer-shell010711780
==> docker: Uploading nginx.conf => /etc/nginx/nginx.conf
==> docker: Uploading ../dist/ => /var/www
==> docker: Uploading ../dist => /skywatch/website
==> docker: Uploading /skywatch/ssl/ => /skywatch/ssl
==> docker: Committing the container
    docker: Image ID: sha256:d469880ae311d164da6786ec73afbf9190d2056accedc9d2dc186ef8ca79c4b6
==> docker: Killing the container: 0594bf37edd1311535598971140535166df907b1c19d5f76ddda97c53f884d5b
==> docker: Running post-processor: docker-tag
    docker (docker-tag): Tagging image: sha256:d469880ae311d164da6786ec73afbf9190d2056accedc9d2dc186ef8ca79c4b6
    docker (docker-tag): Repository: us.gcr.io/skywatch-app/website:96.0
Build 'docker' finished.
==> Builds finished. The artifacts of successful builds are:
--> docker: Imported Docker image: sha256:d469880ae311d164da6786ec73afbf9190d2056accedc9d2dc186ef8ca79c4b6
--> docker: Imported Docker image: us.gcr.io/skywatch-app/website:96.0
[2016-05-16 15:09:39,598, INFO] The push refers to a repository [us.gcr.io/skywatch-app/website]
e75005ca29bf: Preparing
5f70bf18a086: Preparing
5f70bf18a086: Preparing
5f70bf18a086: Preparing
0b3fbb980e2d: Preparing
40f240c1cbdb: Preparing
673cf6d9dedb: Preparing
5f70bf18a086: Preparing
ebfc3a74f160: Preparing
031458dc7254: Preparing
5f70bf18a086: Preparing
5f70bf18a086: Preparing
12e469267d21: Preparing
ebfc3a74f160: Waiting
031458dc7254: Waiting
12e469267d21: Waiting
5f70bf18a086: Layer already exists
673cf6d9dedb: Layer already exists
40f240c1cbdb: Layer already exists
0b3fbb980e2d: Layer already exists
ebfc3a74f160: Layer already exists
031458dc7254: Layer already exists
12e469267d21: Layer already exists
e75005ca29bf: Pushed
96.0: digest: sha256:ff865acd292409f3b5bf3c14494a6016a45d5ea831e5260304007a2b83e21189 size: 7328
[2016-05-16 15:09:40,483, INFO] Fetching cluster endpoint and auth data.
kubeconfig entry generated for website-cluster.
[2016-05-16 15:10:18,823, INFO] Created website-8c10af72294bdfc4d2d6a0e680e84f09
Scaling up website-8c10af72294bdfc4d2d6a0e680e84f09 from 0 to 1, scaling down website from 1 to 0 (keep 1 pods available, don't exceed 2 pods)
Scaling website-8c10af72294bdfc4d2d6a0e680e84f09 up to 1
Scaling website down to 0
Update succeeded. Deleting old controller: website
Renaming website-8c10af72294bdfc4d2d6a0e680e84f09 to website
replicationcontroller "website" rolling updated

Все это выглядит хорошо, но после завершения мы получали случайные ошибки 404 на новой странице. Когда я запустил kubectl get pods, я обнаружил, что у меня работает три модуля вместо ожидаемых двух:

NAME                                                     READY     STATUS    RESTARTS   AGE
website-8c10af72294bdfc4d2d6a0e680e84f09-iwfjo           1/1       Running   0          1d
website-keys9                                            1/1       Running   0          1d
website-staging-34caf57c958848415375d54214d98b8a-yo4sp   1/1       Running   0          3d

Используя kubectl describe pod команда я определил, что капсула website-8c10af72294bdfc4d2d6a0e680e84f09-iwfjo работает новая версия (96.0), а под website-keys9работает старая версия (95.0). Мы получаем ошибки 404, потому что входящий запрос будет случайным образом доставлен на старую версию веб-сайта. Когда я вручную удаляю модуль со старой версией, ошибки 404 исчезают.

Кто-нибудь знает, при каких обстоятельствах непрерывное обновление не удалит модуль, на котором запущена старая версия веб-сайта? Есть ли что-то, что мне нужно изменить в yaml или командах, чтобы гарантировать, что удаление модуля, на котором запущена старая версия, всегда происходит?

Цените любую помощь или совет по этому поводу.

Это Ошибка Kubernetes # 27721. Но даже если бы это было не так, у вас все равно будет момент, когда ваш пользовательский трафик будет доставлен как в старые, так и в новые модули. Это нормально для большинства приложений, но в вашем случае нежелательно, поскольку приводит к неожиданным ошибкам 404. Я предлагаю вам создать новый модуль с набором меток, который отличается от старого, например, поместив версию изображения в метку. Затем вы можете обновить службу, чтобы выбрать новую метку - это быстро (не атомарно, а быстро) переключит весь трафик со старой серверной части службы на новую.

Но, наверное, проще перейти на использование развертываний.