업그레이드 도중 여러 파드가 0/1 Running 상태로 멈추고 로그에 401 Unauthorized 가 반복된다. 이전 릴리스 파드와 새 파드가 같이 떠 있다.
새 파드가 Ready 가 되지 못하면 쿠버네티스는 기존 파드를 내리지 않는다. 따라서 구·신 파드가 함께 보이는 것 자체는 정상이고, 문제는 새 파드가 왜 Ready 가 되지 않는지다.
여기서 나오는 401 은 대부분 사용자 로그인 실패가 아니라 파드 간 내부 인증 호출 실패다.
PostgreSQL -> sas-logon-app(UAA) -> identities / configuration / authorization -> 나머지 서비스
앞단이 죽어 있으면 뒤에 매달린 서비스는 전부 401 을 내며 Ready 에 실패한다. 그래서 401 이 난 파드부터 만지면 안 되고 앞단부터 살려야 한다.
kubectl -n <namespace> get pods | egrep 'postgres|logon|identit|config|author|consul'
kubectl -n <namespace> get pods | egrep '0/1|0/2|1/2|CrashLoop|Error|Pending'
업그레이드 중 오퍼레이터가 리소스를 만드는 순서가 엇갈리면서 TLS 시크릿 마운트에 실패하는 사례가 있다.
MountVolume.SetUp failed for volume "..." : secret "sas-crunchy-platform-postgres-tls-secret" not found
확인할 것은 세 가지다.
kubectl -n <namespace> describe pod <postgres-pod>
kubectl -n <namespace> get secret | egrep 'crunchy|postgres'
kubectl -n <namespace> get pod <postgres-pod> -o yaml | grep -B5 -A5 secretName
kubectl -n <namespace> get secret <secret> -o jsonpath='{.metadata.creationTimestamp}{"\n"}'
kubectl -n <namespace> get pod <postgres-pod> -o jsonpath='{.metadata.creationTimestamp}{"\n"}'
kubectl -n <namespace> delete pod <postgres-pod>
PostgreSQL 이 실제로 새 버전으로 올라갔는지도 확인한다.
kubectl -n <namespace> exec -it <postgres-pod> -- psql -U postgres -t -c "show server_version;"
kubectl -n <namespace> get pod <postgres-pod> -o jsonpath='{.spec.containers[*].image}{"\n"}'
kubectl -n <namespace> get postgrescluster
거의 모든 서비스가 logon 을 바라보므로 logon 이 살아나기 전에는 나머지를 건드리지 않는다.
kubectl -n <namespace> logs <logon-pod> --all-containers --previous --tail=500
kubectl -n <namespace> logs <logon-pod> --all-containers --tail=500 \
| egrep -i 'exception|caused by|error|liquibase|lock|postgres|jdbc|ssl|x509|secret|config'
kubectl -n <namespace> describe deploy sas-logon-app
tail 을 짧게 주면 원인 줄을 놓친다. Caused by: 바로 아래가 핵심이다.
Waiting for PostgreSQL advisory lock
advisory lock 은 여러 logon 인스턴스가 동시에 DB 스키마 마이그레이션을 하지 않도록 거는 분산 잠금이다. 한 파드가 마이그레이션을 수행하고 나머지는 대기한다. 마이그레이션 중에 logon 파드를 반복해서 지우면 안 된다. 잠금이 계속 반복되거나 스키마가 깨질 수 있다.
정상 흐름이면 잠금 획득 후 마이그레이션 성공 메시지가 이어진다. 그 뒤에 이런 메시지로 끝난다면 마이그레이션이 아니라 그다음 초기화 단계가 실패한 것이다.
Exception encountered during context initialization - cancelling refresh attempt
이것은 애플리케이션 시작 중 실패하면 나오는 일반적인 종료 메시지라서 그 자체로는 원인을 알려 주지 않는다. --previous 로그의 스택 트레이스를 봐야 한다.
업그레이드로 ConfigMap 이름과 내용이 바뀌면, 옛 ReplicaSet 에 매달린 파드는 없어진 ConfigMap 을 찾다가 실패한다.
configmap "..." not found
이것은 정리해야 할 파드이지 고칠 파드가 아니다. 새 파드가 최소 하나라도 정상으로 뜰 수 있는 상태인지 먼저 확인한 뒤 옛 파드를 지운다.
kubectl -n <namespace> get rs | grep <app>
kubectl -n <namespace> delete pod <old-pod>
kubectl -n <namespace> scale rs <old-rs> --replicas=0
새 ReplicaSet 이 정상일 때만 옛 ReplicaSet 을 0 으로 내린다.
앞단이 정상이 되면 멈춰 있던 파드는 자동으로 회복되기도 하고, 실패 상태를 그대로 물고 있기도 한다. 남은 것만 골라 다시 만든다.
kubectl -n <namespace> get pods | egrep '0/1|0/2|1/2|CrashLoop|Error' | awk '{print $1}' \
| xargs -r kubectl -n <namespace> delete pod
핵심 인프라 파드 상태를 확인하기 전에는 일괄 삭제하지 않는다.
권장 순서는 인프라(PostgreSQL, Consul, Redis, RabbitMQ) → 인증·구성(logon, identities, authorization, configuration) → 나머지 서비스다.
업그레이드로 CAS 가 재기동되면 기존 세션은 사라진다. SAS 9.4 쪽에서 예전 세션 참조를 그대로 쓰면 다음 오류가 난다.
ERROR: Could not find the specified session.
세션을 새로 열고 라이브러리를 다시 매핑한다.
cas mysession;
cas _all_ list;
caslib _all_ list sessref=mysession;
libname mycas cas sessref=mysession caslib=casuser;
proc casutil sessref=mysession;
list files incaslib="casuser";
quit;
세션 범위로 만들었던 CASLIB 은 세션과 함께 사라진다. 여러 세션에서 계속 쓰려면 전역 CASLIB 으로 만들어야 한다.
세션을 여는 것 자체가 실패하고 "활성화된 CAS 연결이 없다" 로 끝난다면 SAS 코드 문제가 아니라 Viya 쪽 문제다. CAS 파드와 logon 파드 상태, CAS 서비스의 엔드포인트를 확인한다.
kubectl -n <namespace> get pods | egrep 'logon|cas'
kubectl -n <namespace> get svc,endpoints | grep cas