Kubernetes: дебаг Init containers при запуске SQL-миграций

Автор: | 15/10/2020

Имеется приложение в Kubernetes.

Деплоится из Helm-чарта.

При очередном деплое – новые поды не стартуют, а сам деплой падает со стандартной ошибкой “Upgrade “CHARTNAME” failed: timed out waiting for the condition“:

wait.go:225: [debug] Deployment is not ready: eks-dev-1-community-api-ns/community-api. 0 out of 3 expected pods are ready
upgrade.go:367: [debug] warning: Upgrade “community-api” failed: timed out waiting for the condition
upgrade.go:385: [debug] Upgrade failed and atomic is set, rolling back to last successful release

Проблема возникает на этапе запуска InitContainer для выполнения SQL-миграций. Сами миграции запускаются не лучшим образом, но – как есть.

Собственно ниже – подебажим запуск таких контейнеров, и зафиксим ошибку.

InitContainer – Init:1/2

Проверяем статус подов:

[simterm]

$ kk -n eks-dev-1-community-api-ns get pod
NAME                             READY   STATUS     RESTARTS   AGE
community-api-778dfdcd5b-7ckxj   0/1     Init:1/2   0          46m
community-api-778dfdcd5b-dppth   0/1     Init:1/2   0          46m
community-api-778dfdcd5b-wh4wh   1/1     Running    0          8

[/simterm]

Статус пода “Init:1/2” – один из двух Init-конейнеров в поде не отработал.

Проверяем state пода:

[simterm]

$ kk -n eks-dev-1-community-api-ns get pod community-api-778dfdcd5b-7ckxj -o yaml
...
  containerStatuses:
  - image: projectname/community-api:16.b2cbe959
    imageID: ""
    lastState: {}
    name: community-api
    ready: false
    restartCount: 0
    state:
      waiting:
        reason: PodInitializing
...

[/simterm]

PodInitializing – под ждёт Init-контейнер.

В деплойменте проверим, какие Init-контейнеры должны запуститься:

...
  initContainers:
  - name: git-clone
    image: projectname/git-cloner
...
    command: ['sh', '-c', '/opt/git/git.sh']
...
  - name: init-migration
    image: fufuhu/sql-migrate:latest
    command: ['sh', '-c', 'while [ ! -d /git/db/migrations ]; do sleep 2; done && sleep 2; /bin/sql-migrate up -config=/config/config.yaml -env=main']
...

Проверяем события:

[simterm]

$ kk -n eks-dev-1-community-api-ns get events
...
51m         Normal    Created                  pod/community-api-778dfdcd5b-7ckxj          Created container git-clone
51m         Normal    Started                  pod/community-api-778dfdcd5b-7ckxj          Started container git-clone
...
51m         Normal    Created                  pod/community-api-778dfdcd5b-7ckxj          Created container init-migration
51m         Normal    Started                  pod/community-api-778dfdcd5b-7ckxj          Started container init-migration
...

[/simterm]

Хорошо – контейнеры создавались и запускались.

Kubernetes Pod: .status.initContainerStatuses

С помощью --template '{{.status.initContainerStatuses}}' проверим статусы Init-контейнеров в поде:

[simterm]

$ kk-n eks-dev-1-community-api-ns get pod community-api-778dfdcd5b-7ckxj --template '{{.status.initContainerStatuses}}'                           
[map[image:*** lastState:map[] name:git-clone ready:true restartCount:0 [...] exitCode:0 finishedAt:2020-09-30T08:15:07Z reason:Completed]] 
map[imageID:*** lastState:map[] name:init-migration ready:false restartCount:0 state:map[running[...]]

[/simterm]

Тут два контейнера – git-clone, который свою задачу “выполнил” (reason:Completed), и второй контейнер – init-migration, который в статусе running.

Смотрим их логи.

Если просто попробовать посмотреть логи пода – то kubectl сообщит, что:

[simterm]

$ kk logs -f community-api-778dfdcd5b-7ckxj
Error from server (BadRequest): container "community-api" in pod "community-api-778dfdcd5b-7ckxj" is waiting to start: PodInitializing

[/simterm]

Поэтому – указываем контейнер явно. Первым запускается git-clone, указываем его через -c git-clone:

[simterm]

$ kk -n eks-dev-1-community-api-ns logs community-api-778dfdcd5b-7ckxj -c git-clone
Setting up SSH settings...
Setting up SSH private key...
....
Warning: Permanently added 'github.com,140.82.114.3' (RSA) to the list of known hosts.
ERROR: Repository not found.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
Purging private key...

[/simterm]

Собственно – всё понятно: git-clone попытался склонировать репозиторий, не смог, но завершил работу с кодом 0 (name:git-clone ready:true restartCount:0 [...] exitCode:0 в выводе .status.initContainerStatuses), после чего запустился контенер для запуска миграций баз данных, но он отработать не может, так как файлов миграции нет – и он висит.

Проверяем скрипт Гита, который указан в деплойменте – command: ['sh', '-c', '/opt/git/git.sh']и используется в нашем контейнере git-clone для клонирования репозитория:

[simterm]

$ docker run -ti projectname/git-cloner cat /opt/git/git.sh
...
Status: Downloaded newer image for projectname/git-cloner:latest
#!/bin/sh

echo "Setting up SSH settings..."
echo "ssh -o StrictHostKeyChecking=no -i private \$@;" > ./sshOverride.sh
chmod 700 ./sshOverride.sh;

echo "Setting up SSH private key..."
echo -e "$SSH_PRIVATE_KEY" > private
chmod 600 private
echo "Setting up GIT settings..."
export GIT_SSH=./sshOverride.sh

echo "Cloning repository..."
git clone -b $GIT_BRANCH $REPOSITORY_URL /git

echo "Purging private key..."
rm -f private

[/simterm]

А ошибка у нас выглядела:

ERROR: Repository not found. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.

Пробуем склонировать репозиторий со своим ключём:

[simterm]

$ GIT_SSH_COMMAND='ssh -i ~/.ssh/setevoy_main_priv_openssh -o IdentitiesOnly=yes' git clone [email protected]:projectname-dev/backend-services.git -b feature/WLIOS-7335-community-api
Cloning into 'backend-services'...
...
Resolving deltas: 100% (2624/2624), done.

[/simterm]

Всё работает, репозиторий и бранч есть.

Проверяем секрет – есть ли сам ключ id_rsa в Kubernetes Secrets:

...
        env:
        - name: SSH_PRIVATE_KEY
          valueFrom:
            secretKeyRef:
              name: git-ssh-key
              key: id_rsa
...

[simterm]

$ kk -n eks-dev-1-community-api-ns get secret git-ssh-key -o yaml
apiVersion: v1
data:
  id_rsa: LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYj...
...

[/simterm]

Да, есть, вроде всё ОК.

Попробуем с ним скачать – получаем сам ключ из содержимого поля id_rsa, сохраняем его в файл key.rsa:

[simterm]

$ echo LS0***S0= | base64 -d > key.rsa
$ chmod 600 key.rsa

[/simterm]

И пробуем применить его:

[simterm]

$ GIT_SSH_COMMAND='ssh -i key.rsa -o IdentitiesOnly=yes' git clone [email protected]:projectname-dev/backend-services.git -b feature/WLIOS-7335-community-api
Cloning into 'backend-services'...
Load key "key.rsa": invalid format
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

[/simterm]

Проблема ясна – Deploy Key в Github репозитории не подходит.

Обновляем его в секретах, передеплоиваем, проверяем:

[simterm]

$ kk -n eks-dev-1-community-api-ns logs community-api-7d8967d448-mvw8m -c git-clone
Setting up SSH settings...
Setting up SSH private key...
Setting up GIT settings...
Cloning repository...
Cloning into '/git'...
Warning: Permanently added 'github.com,140.82.114.3' (RSA) to the list of known hosts.
Purging private key...

[/simterm]

И поды запустились:

[simterm]

$ kk -n eks-dev-1-community-api-ns get pod
NAME                            READY   STATUS    RESTARTS   AGE
community-api-84675f55dd-5jn5z   1/1     Running   0          58m
community-api-84675f55dd-qvjfw   1/1     Running   0          58m

[/simterm]

Готово.