OpenBao 트러블슈팅
GitLab v19.1Offering: GitLab Self-Managed
복구 키 작업 및 break-glass 루트 토큰에 대해서는 복구 키 관리를 참조하세요. OpenBao는 GitLab이 Linux 패키지를 사용하는 경우에도 항상 쿠버네티스에서 실행됩니다. 이 예제에서는 Cloud Native 네임스페이스 gitlab을 사용합니다.
-
Status: Beta
복구 키 작업 및 break-glass 루트 토큰에 대해서는 복구 키 관리를 참조하세요. Geo 페일오버에 대해서는 Geo 재해 복구를 참조하세요.
OpenBao 실행 위치#
OpenBao는 GitLab이 Linux 패키지를 사용하는 경우에도 항상 쿠버네티스에서 실행됩니다. 네임스페이스와 배포 이름은 설치 방법에 따라 다릅니다:
| 설치 방법 | 네임스페이스 | Deployment | Pod 컨테이너 |
|---|---|---|---|
| Cloud Native GitLab | gitlab | gitlab-openbao | openbao-server |
| Linux 패키지 | openbao | openbao | openbao-server |
이 예제에서는 Cloud Native 네임스페이스 gitlab을 사용합니다. Linux 패키지
설치의 경우, kubectl 명령에서 gitlab을 openbao로 교체하세요.
OpenBao Pod는 app.kubernetes.io/name=openbao 라벨을 가집니다. 활성 노드에는
openbao-active=true 라벨도 포함됩니다.
OpenBao 로그 찾기#
kubectl logs를 사용하여 OpenBao 로그를 읽습니다. 관련 GitLab Rails 및 Sidekiq 로그는 설치 방법에 따라
별도로 저장됩니다:
| 소스 | Cloud Native GitLab | Linux 패키지 |
|---|---|---|
| OpenBao 서버 | openbao-server 컨테이너에서 kubectl logs | openbao-server 컨테이너에서 kubectl logs |
| GitLab Rails | webservice Pod에서 kubectl logs | /var/log/gitlab/gitlab-rails/production_json.log |
| Sidekiq | sidekiq Pod에서 kubectl logs | /var/log/gitlab/sidekiq/current |
| GitLab Runner | GitLab UI의 CI/CD job 로그 | GitLab UI의 CI/CD job 로그 |
OpenBao는 GitLab에 감사 이벤트를 게시하며, OpenBao Pod 로그에도 기록합니다.
OpenBao Pod 찾기#
OpenBao Pod를 목록으로 보고 어느 노드가 활성 상태인지 확인하려면:
kubectl get pods -n gitlab -l app.kubernetes.io/name=openbao \
--label-columns openbao-active,openbao-sealed
OPENBAO-ACTIVE가 true로 설정된 Pod가 활성 노드입니다. 나머지는 대기 노드입니다.
OpenBao 상태 확인#
OpenBao는 요청을 처리하려면 봉인 해제(unsealed) 상태여야 합니다. Pod에서 bao status를 실행하여 확인하세요:
OPENBAO_POD=$(kubectl get pods -n gitlab -l app.kubernetes.io/name=openbao -o name | head -1)
kubectl exec -n gitlab "$OPENBAO_POD" -c openbao-server -- \
sh -c "BAO_ADDR=http://127.0.0.1:8200 bao status"
출력에서 Sealed가 false여야 합니다. 활성 노드는 HA Mode active를, 대기
노드는 HA Mode standby를 표시합니다:
Seal Type static
Initialized true
Sealed false
Storage Type postgresql
HA Enabled true
HA Mode active
sys/seal-status 엔드포인트는 "sealed":false와 동일한 상태를 보고합니다:
kubectl exec -n gitlab "$OPENBAO_POD" -c openbao-server -- \
sh -c "BAO_ADDR=http://127.0.0.1:8200 bao read sys/seal-status"
`bao` 바이너리가 Pod에 있습니다. Pod 내부에서 엔드포인트 쿼리에는 `bao read`를 사용하세요.
로그에서 봉인 해제에 성공한 노드는 vault is unsealed를 기록합니다. 활성 노드는
acquired lock, enabling active operation을, 대기 노드는 entering standby mode를 기록합니다:
OPENBAO_POD=$(kubectl get pods -n gitlab -l app.kubernetes.io/name=openbao -o name | head -1)
kubectl logs -n gitlab "$OPENBAO_POD" -c openbao-server \
| grep -E "acquired lock, enabling active operation|entering standby mode"
특정 시간대의 오류 찾기#
특정 시간대의 OpenBao 로그를 읽으려면 --since를 사용하세요:
OPENBAO_POD=$(kubectl get pods -n gitlab -l app.kubernetes.io/name=openbao -o name | head -1)
kubectl logs -n gitlab "$OPENBAO_POD" -c openbao-server --since=30m \
| grep -iE "error|warn|failed"
Linux 패키지 설치의 경우, 시간을 기준으로 Rails 및 Sidekiq 로그 파일을 검색하세요. 로그는 JSON 형식으로, 한 줄에 하나의 이벤트가 기록됩니다.
OpenBao는 모든 출력을 표준 오류로 씁니다. 따라서 일부 로그 플랫폼은 모든 줄을 오류로 태깅합니다.
플랫폼의 라벨이 아닌 메시지 본문의 레벨([info], [warn])을 신뢰하세요.
GitLab Rails 로그#
Rails 로그는 UI 및 GraphQL API에서의 시크릿 작업과 OpenBao의 감사 콜백을 다룹니다.
Cloud Native 설치의 경우:
kubectl logs -n gitlab -l app=webservice -c webservice \
| grep -E "Projects::SecretsController|Groups::SecretsController|secrets_manager/audit_logs"
Linux 패키지 설치의 경우:
grep -E "Projects::SecretsController|Groups::SecretsController|secrets_manager/audit_logs" \
/var/log/gitlab/gitlab-rails/production_json.log
GraphQL 작업은 graphql:createProjectSecret 또는 graphql:getGroupSecrets와 같은 caller_id와 함께 나타납니다.
감사 콜백은 /api/v4/internal/secrets_manager/audit_logs 경로로 나타납니다.
Sidekiq 로그#
Secrets Manager 레코드를 프로비저닝, 디프로비저닝, 유지 관리하는 워커는
SecretsManagement:: 네임스페이스 하에서 실행됩니다.
Cloud Native 설치의 경우:
kubectl logs -n gitlab -l app=sidekiq -c sidekiq | grep "SecretsManagement::"
Linux 패키지 설치의 경우:
grep "SecretsManagement::" /var/log/gitlab/sidekiq/current
프로비저닝 문제의 경우, ProvisionProjectSecretsManagerWorker 또는
ProvisionGroupSecretsManagerWorker로 필터링하세요.
GitLab Runner 로그#
CI/CD job이 시크릿 가져오기에 실패하면 GitLab UI의 job 로그에 원인이 나타납니다. job 로그에서 다음 문자열을 검색하세요:
| 문자열 | 의미 |
|---|---|
| Resolving secrets | 러너가 job의 시크릿 확인을 시작했습니다. |
| Using "gitlab_secrets_manager" secret resolver | 러너가 GitLab Secrets Manager 리졸버를 선택했습니다. |
| not initialized or sealed Vault server | OpenBao가 봉인되었거나 초기화되지 않았습니다. |
| api error: status code 403: permission denied | OpenBao가 요청을 거부했습니다. 종종 audience 또는 권한 문제입니다. |
| inline auth JWT is required | 러너가 인증 요청을 만들 수 없었습니다. |
정상 시작 로그#
재시작 후, 활성 노드는 다음 순서로 로그를 기록합니다. 대기 노드는 vault is unsealed에서 멈추고
entering standby mode를 기록합니다. 줄 형식은 설정에 따라 다를 수 있으므로, 접두사가 아닌
메시지 텍스트로 매칭하세요.
| 로그 메시지 | 의미 | 누락 시 |
|---|---|---|
| ==> OpenBao server started! | 프로세스가 시작되고 설정을 읽었습니다. | Pod 시작에 실패했습니다. Pod 이벤트를 확인하세요. |
| vault is unsealed | 자동 봉인 해제에 성공했습니다. | 자동 봉인 해제에 실패했습니다. 봉인 해제 시크릿 또는 KMS를 확인하세요. |
| acquired lock, enabling active operation | 이 노드가 활성화되었습니다. | 활성 노드가 없습니다. 데이터베이스와 HA 잠금을 확인하세요. |
| post-unseal setup complete | 활성 노드의 설정이 완료되었습니다. | 설정이 완료되지 않았습니다. 데이터베이스 연결을 확인하세요. |
오류 메시지#
OpenBao 메시지는 openbao-server 컨테이너에서 옵니다. GitLab 메시지는 Rails 또는
Sidekiq 로그에서 옵니다.
| 컨테이너 | 메시지 | 설명 | 조치 |
|---|---|---|---|
| openbao-server | cipher: message authentication failed | 봉인 키가 저장된 데이터를 복호화할 수 없습니다. | 정적 봉인 해제의 경우, 기본 사이트에서 봉인 해제 시크릿을 복사하세요. KMS 봉인의 경우, KMS 키를 확인하세요. Geo 배포 트러블슈팅을 참조하세요. |
| openbao-server | unknown key ID | 정적 봉인 해제 키 ID가 데이터베이스의 데이터와 일치하지 않습니다. | 기본 사이트에서 봉인 해제 시크릿을 복사하세요. Geo 배포 트러블슈팅을 참조하세요. |
| openbao-server | failed to acquire lock | 대기 노드가 읽기 전용 데이터베이스에서 HA 잠금을 획득할 수 없습니다. | Geo 보조 사이트에서 예상되는 동작입니다. 조치 불필요. |
| openbao-server | cannot execute INSERT in a read-only transaction | 대기 노드가 읽기 복제본에 쓰려고 했습니다. | Geo 보조 사이트에서 예상되는 동작입니다. 그렇지 않은 경우, OpenBao에 데이터베이스 쓰기 권한이 있는지 확인하고 데이터베이스 권한을 점검하세요. |
| openbao-server | post-unseal upgrade seal keys failed: error="no recovery key found" | 복구 키가 저장된 적이 없습니다. | 무해합니다. recovery_key:store를 실행하세요. |
| Rails or Sidekiq | [OpenBao] health check returned unhealthy | OpenBao가 응답했지만 비정상 상태를 보고했습니다. | bao status와 OpenBao 로그를 확인하세요. |
| Rails or Sidekiq | [OpenBao] health check failed | GitLab이 OpenBao에 도달할 수 없었습니다. | 연결을 확인하세요. GitLab이 OpenBao에 연결할 수 없음을 참조하세요. |
| Rails or Sidekiq | Failed to authenticate with OpenBao | OpenBao가 JWT를 거부했습니다. | audience를 확인하세요. JWT 인증 실패를 참조하세요. |
| Rails or Sidekiq | Failed to open TCP connection to |
Sidekiq이 OpenBao URL에 도달할 수 없었습니다. | DNS와 Sidekiq Pod에서 OpenBao URL을 확인하세요. |
| Rails or Sidekiq | SSL_connect ... state=error: wrong version number | https URL이 http를 제공하는 OpenBao 리스너를 가리키고 있습니다. | URL 스킴을 리스너에 맞추세요. GitLab이 OpenBao에 연결할 수 없음을 참조하세요. |
| Rails or Sidekiq | Retrying failed secrets_manager maintenance task | 프로비저닝 또는 디프로비저닝 작업이 재시도 중입니다. | 같은 로그에서 워커 오류를 확인하세요. 재시도는 세 번 후 중단됩니다. |
Secrets Manager가 프로비저닝 상태에서 멈춤#
Secrets Manager를 활성화하면 토글이 로딩 상태로 유지되고 상태가
provisioning으로 표시될 수 있습니다. Secrets Manager에는 failed 상태가 없으므로, 활성화 전에
실패하는 단계가 있으면 레코드가 멈춘 상태로 남게 됩니다. 일반적인 원인은 Sidekiq이 OpenBao에
도달할 수 없는 경우입니다.
진단 방법:
프로비저닝 워커의 Sidekiq 로그를 확인하세요:
kubectl logs -n gitlab -l app=sidekiq -c sidekiq \
| grep -E "ProvisionProjectSecretsManagerWorker|ProvisionGroupSecretsManagerWorker"
Sidekiq Pod 또는 노드에서 Sidekiq이 OpenBao에 도달할 수 있는지 테스트하세요:
curl "https://openbao.example.com/v1/sys/health"
유지 관리 워커는 오래된 작업을 최대 세 번 재시도한 후 중단합니다. 그 이후에는 레코드가
provisioning 상태로 자동 복구 없이 남고, 재시도는 Retrying failed secrets_manager maintenance task를 기록합니다.
연결 문제를 수정한 후, Secrets Manager를 비활성화하고 다시 활성화하여 다시 프로비저닝하세요.
자기 초기화 후 인증 마운트 누락#
여러 OpenBao Pod가 있는 새 설치에서, 자기 초기화 경쟁 조건이 발생하면 OpenBao가
봉인 해제되어 있지만 gitlab_rails_jwt/ 인증 마운트가 없는 상태가 될 수 있습니다. Pod는 정상으로 보이지만
시크릿 작업이 permission denied로 실패합니다. 루트 토큰으로 bao auth list를 실행하여 마운트가 있는지
확인하세요. 경쟁 조건을 방지하려면, 새 설치 시 단일 복제본으로 시작하여 초기화가 완료된 것을 확인한 후
확장하세요.
GitLab이 OpenBao에 연결할 수 없음#
GitLab Rails와 Sidekiq은 HTTP로 OpenBao에 연결합니다. Rails는 internal_url을 사용하고, internal_url이
설정되지 않은 경우 url로 폴백합니다. 설정을 검사하려면
Rails 콘솔에서 다음을 실행하세요:
Gitlab.config.openbao.to_h
일반적인 원인:
-
http를 제공하는 OpenBao 리스너에 대해https://URL을 사용하면wrong version number로 실패합니다.global.openbao.https는 GitLab이 연결하는 스킴을 설정하며, OpenBao 리스너의 TLS를 설정하는 것이 아닙니다. 리스너는 기본적으로 일반 HTTP를 제공합니다. 이에 맞추려면global.openbao.https를 설정하지 않거나,openbao.config.tlsDisable: false로 리스너 TLS를 활성화하고global.openbao.https를true로 설정하세요. -
OIDC 디스커버리와 감사 로깅은 신뢰할 수 없는 TLS 인증서로는 실패합니다. GitLab이 신뢰하는 인증서를 사용하세요.
-
OpenBao 감사 항목이 생성되지 않는 요청은 인증 백엔드에 도달하지 못한 것입니다. Ingress 또는 리버스 프록시를 확인하세요.
Cloud Native 설치의 경우, 올바른 설정은 다음과 같습니다:
global:
openbao:
enabled: true
url: http://gitlab-openbao-active:8200
internal_url: http://gitlab-openbao-active:8200
Linux 패키지 설치의 경우, GitLab은 /etc/gitlab/gitlab.rb의 gitlab_rails['openbao']['url'] 설정을 사용하여
OpenBao에 연결합니다. 번들된 NGINX 리버스 프록시는 oak['components']['openbao'] 설정으로
OpenBao로 라우팅합니다. 자세한 내용은
Linux 패키지 배포용 OpenBao 설치를 참조하세요.
JWT 인증 실패#
GitLab은 JWT로 OpenBao에 인증합니다. JWT의 aud(audience) 클레임은 OpenBao 인증 역할의
bound_audiences 값과 정확히 일치해야 합니다. 후행 슬래시, http와 https 차이, 또는 포트 차이 등
어떠한 차이도 인증 실패를 초래합니다.
OpenBao는 초기화 시 bound_audiences를 OpenBao URL에서 파생하여 저장합니다. 저장된 값은 나중에
URL을 변경해도 변경되지 않습니다. 따라서 URL을 변경하면 인증이 깨집니다. 저장된 bound_audiences가
더 이상 GitLab이 전송하는 aud와 일치하지 않기 때문입니다. 연결 URL과 독립적으로 audience를 설정하려면
global.openbao.jwt_audience를 사용하세요.
GitLab이 전송하는 audience를 찾으려면 Rails 콘솔에서 다음을 실행하세요:
SecretsManagement::ProjectSecretsManager.jwt_audience
이 메서드는 설정된 jwt_audience를 반환하거나, jwt_audience가 설정되지 않은 경우 OpenBao url을 반환합니다.
저장된 값을 검사하려면 루트 토큰으로 인증 역할을 읽고 bound_audiences를 해당 audience와 비교하세요.
이 문제는 권한 있는 접근 없이 수정할 수 없습니다. 루트 토큰은 자기 초기화 후 취소되며,
봉인 해제 키는 대체 수단이 아닙니다. 봉인 해제 시크릿에는 봉인 해제 키만 포함되어 있으며, 루트 토큰은 포함되어 있지 않습니다.
저장된 시크릿을 삭제하지 않고 불일치를 수정하려면 복구 키로 인증을 재설정하세요. 절차는 복구 키로 인증 재설정을 참조하세요.
복구 키가 없으면 OpenBao 데이터를 초기화하세요. 이 작업은 저장된 모든 시크릿을 삭제합니다.
OpenBao Pod가 봉인된 상태#
시작 시 bao status가 Sealed true를 보고하면 자동 봉인 해제에 실패한 것입니다:
-
기본 정적 봉인 해제의 경우, 일반적인 원인은 봉인 해제 시크릿이 없거나 잘못된 것입니다. 시크릿은 Cloud Native 설치의 경우
gitlab-openbao-unseal이고, Linux 패키지 설치의 경우openbao-static-unseal입니다. -
현재 AWS KMS(
awskms)인 KMS 자동 봉인 해제의 경우, 일반적인 원인은 OpenBao가 KMS에 도달할 수 없는 것입니다.
봉인 상태를 확인하려면 OpenBao 상태 확인을 참조하세요.
정적 봉인 해제 키를 이전 키를 사용 가능한 상태로 유지하지 않고 교체하면, OpenBao는 기존 데이터를
복호화할 수 없습니다. 이전 키를 새 키와 함께 추가하고, 모든 Pod가 새 키로 실행된 후에만 제거하세요.
데이터베이스 문제#
OpenBao는 자체 PostgreSQL 데이터베이스가 필요합니다. 전용 데이터베이스 없이 OpenBao를 활성화하면 GitLab 차트가 설치 또는 업그레이드에 실패합니다.
기타 데이터베이스 문제:
-
연결 풀 고갈 또는 높은 지연 시간으로 인해 간헐적인 타임아웃이 발생합니다.
-
Linux 패키지 PostgreSQL 설정에서 잘못된
md5_auth_cidr_addresses,sslMode, 또는 비밀번호 값은 OpenBao Pod를CrashLoopBackOff상태로 만듭니다. 올바른 설정에 대해서는 Linux 패키지 배포용 OpenBao 설치를 참조하세요.
감사 이벤트 누락#
OpenBao는 /api/v4/internal/secrets_manager/audit_logs를 통해 GitLab에 감사 이벤트를 게시합니다. GitLab
차트는 기본적으로 감사 로깅을 활성화합니다. 감사 이벤트가 도착하지 않는 경우:
-
config.audit.http.enabled를false로 설정하면 OpenBao가 이벤트를 게시하지 않습니다. 감사 로깅이 활성화되어 있는지 확인하세요. -
공유 감사 토큰 불일치는 감사 엔드포인트에서
401을 반환합니다. GitLab과 OpenBao가 동일한 감사 토큰을 사용하는지 확인하세요.
Geo 배포 트러블슈팅#
OpenBao는 기본 Geo 사이트에서 활성 노드로, 각 보조 사이트에서 대기 노드로 실행됩니다.
보조 노드는 읽기 전용 PostgreSQL 복제본에 연결하므로, failed to acquire lock 및
cannot execute INSERT in a read-only transaction을 기록합니다. 이 메시지는 예상되는 동작입니다.
보조 노드가 cipher: message authentication failed 또는 unknown key ID를 기록하면, 봉인 키가
기본 사이트의 것과 일치하지 않는 것입니다. 수정 방법은 봉인 메커니즘에 따라 다릅니다:
정적 봉인 해제의 경우, 기본 클러스터에서 보조 클러스터로 gitlab-openbao-unseal 시크릿을 복사한 후
OpenBao Pod를 재시작하세요:
kubectl -n gitlab get secret gitlab-openbao-unseal -o yaml
KMS 봉인의 경우, 두 사이트 모두 동일한 KMS 키를 사용하도록 설정하세요.
페일오버 후 JWT 인증이 실패하면, audience가 더 이상 저장된 bound_audiences와 일치하지 않는 것입니다.
수정 방법은 도메인에 따라 다릅니다:
-
두 사이트 모두 기본 OpenBao URL을 사용하는 경우, 두 사이트 모두에서
jwt_audience를 기본 OpenBao URL로 설정하세요. 보조 사이트에 OpenBao 설치를 참조하세요. -
보조 사이트가 다른 도메인을 사용하는 경우, 이 설정은 지원되지 않습니다. audience를 재설정해도 인증이 복구되지 않습니다. 모든 프로젝트와 그룹 네임스페이스도 재프로비저닝이 필요하기 때문입니다. 승격된 보조 사이트를 가리키도록 DNS를 업데이트하세요. 자세한 내용은 Geo 배포를 참조하세요.
느린 시크릿 작업 진단#
CI/CD job에서 시크릿을 가져오는 속도가 느리거나 시크릿 작업이 타임아웃되는 경우, 다음 쿼리를 사용하여 원인을 찾으세요. 이 쿼리는 OpenBao 메트릭을 스크레이핑하는 Prometheus 또는 Grafana 인스턴스에서 실행하세요. 이러한 메트릭을 노출하려면 OpenBao 메트릭을 참조하세요.
지연 시간이 높은지 확인#
다음 쿼리를 사용하여 밀리초 단위의 평균 요청 지연 시간을 측정하세요. 이 쿼리는 저트래픽 배포를 포함하여 어떤 트래픽 수준에서도 작동합니다:
rate(openbao_core_handle_request_sum[5m])
/
rate(openbao_core_handle_request_count[5m])
정상 부하에서 모든 요청 유형에 걸친 평균 지연 시간은 일반적으로 3~7ms입니다. 평균 지연 시간이 지속적으로 20ms를 초과하면 조사하세요.
OpenBao가 요청을 활발히 처리하는 경우, 다음 쿼리를 사용하여 P99 지연 시간을 확인하세요:
openbao_core_handle_request{quantile="0.99"}
정상 P99는 10ms 미만입니다. 이 쿼리는 요약 윈도우에 최근 관측값이 없으므로 OpenBao가 유휴 상태일 때
NaN을 반환합니다. 그 경우에는 비율 기반 쿼리를 사용하세요.
잠재적 문제 파악#
| 잠재적 문제 | 확인 항목 | 쿼리 | 임계값 | 조치 |
|---|---|---|---|---|
| CPU 제한이 너무 낮음 | CFS 스로틀 비율 | CPU 스로틀링 쿼리 | > 25% | CPU 제한 증가 |
| 수요가 CPU 용량을 초과 | CPU 사용률 | CPU 사용률 쿼리 | 요청의 > 50% | 사이징 테이블의 다음 행으로 확장 |
| 요청 급증 | 진행 중인 요청 | openbao_core_in_flight_requests | 5를 지속적으로 초과 | 일시적 현상. 재발 여부 모니터링. |
| PostgreSQL 병목 | 평균 PostgreSQL 읽기 지연 시간 | rate(openbao_postgres_get_sum[5m]) / rate(openbao_postgres_get_count[5m]) | > 5ms | PostgreSQL 리소스 및 연결 풀 확인 |
| 메모리 부족 | 메모리 사용률 | 메모리 사용률 쿼리 | 메모리 요청에 근접 | 네임스페이스 공식을 사용하여 메모리 증가 |
PostgreSQL 지연 시간이 높은 경우, 연결 풀이 포화 상태인지 확인하세요. 모든 연결이 사용 중이면 추가 요청이 대기열에 쌓이고 지연 시간이 증가합니다. 연결 풀 설정에 대해서는 데이터베이스 리소스를 참조하세요.