# GitHub Enterprise Server에서 GHE.com 실시간 마이그레이션 문제 해결

마이그레이션에 발생할 수 있는 문제에 대한 조언입니다.

마이그레이션에 문제가 발생하는 경우 마이그레이션 상태를 `gh elm migration status --migration-id MIGRATION-ID` 확인하고 오류 정보를 검토합니다.

## 상태 및 권장 작업

| 상태                               | Meaning                                  | 권장 작업                                                         |
| -------------------------------- | ---------------------------------------- | ------------------------------------------------------------- |
| **생성됨**                          | 마이그레이션이 만들어졌지만 아직 시작되지 않았습니다.            |                                                               |
| `gh elm migration start`을 실행합니다. |                                          |                                                               |
| 대기 중 \*\*\*\*                    | 마이그레이션이 시작되기를 기다리고 있습니다.                 | Wait                                                          |
| **내보내기**                         | 원본에서 데이터를 내보내고 있습니다.                     |                                                               |
| `gh elm migration status`로 모니터링  |                                          |                                                               |
| **처리 중**                         | 내보낸 데이터를 대상 위치로 가져오고 있습니다.               |                                                               |
| `gh elm migration status`로 모니터링  |                                          |                                                               |
| **전환 준비**                        | 초기 마이그레이션이 완료되고 마이그레이션이 중단할 준비가 완료되었습니다. | 준비가 되면 실행 `gh elm migration cutover`                          |
| **전환**                           | 원본 리포지토리가 보관되고 나머지 변경 내용이 대상에 적용됩니다.     | 모니터; 상태가 완료됨으로 전환됩니다 **.**                                    |
| **Completed**                    | 마이그레이션이 성공적으로 완료되었습니다.                   | 대상 리포지토리 확인 및 마네킹 회수                                          |
| **실패**                           | 마이그레이션에서 복구할 수 없는 오류가 발생했습니다.            | 오류 조사(아래 참조)                                                  |
| **일시 중지된**                       | 마이그레이션이 일시 중지됨                           | 일시 중지 이유를 확인하고 해결합니다(아래 참조).                                  |
| **종료됨**                          | 마이그레이션이 취소되었습니다.                         | N/A                                                           |
| **성능 저하됨**                       | 대상에 연결할 수 없습니다.                          | GitHub Enterprise Server 어플라이언스와 GHE.com 간의 네트워크 연결 확인(아래 참조) |

## 마이그레이션 상태가 "실패"입니다.

복구할 수 없는 오류가 계속되지 않으면 마이그레이션이 **실패** 상태로 전환됩니다. 이는 가져오지 못하는 개별 리소스와 다릅니다. 마이그레이션에 실패하면 마이그레이션 자체를 진행할 수 없습니다.

조사하려면 `gh elm migration status --migration-id MIGRATION-ID`을 실행하고 응답에서 오류 세부 정보를 검토하십시오. 각 오류에는 형식 `(Correlation ID for Support: UUID)`의 상관 관계 ID가 포함됩니다.
GitHub 지원에 연락하실 경우, 지원 팀이 조사할 수 있도록 이 ID를 제공하세요.

기본 문제를 해결한 후 실패한 마이그레이션을 중단하고 새 마이그레이션 `gh elm migration cancel --migration-id MIGRATION-ID` 을 시작합니다.

## 마이그레이션 상태가 "일시 중지됨"입니다.

문제가 계속되기 전에 개입이 필요한 경우 마이그레이션이 **일시 중지** 됨 상태로 들어갑니다.
`gh elm migration status --migration-id MIGRATION-ID`을 실행하고 일시 중지 이유를 확인합니다.

일반적인 일시 중지 이유:

* **자격 증명 만료**: 만료된 자격 증명 중 personal access tokens (classic) 하나입니다. 필수 범위로 새 토큰을 만든 다음 `gh elm credential update`로 해당 토큰을 업데이트합니다. 그런 다음 마이그레이션을 다시 시작합니다.
* **속도 제한**: 마이그레이션이 API 속도 제한에 도달했습니다. 몇 분 정도 기다린 다음 다시 시작합니다.

기본 문제를 해결한 후 일시 중지된 마이그레이션을 다시 시작하려면 다음을 수행합니다.

```shell
gh elm migration start --migration-id MIGRATION-ID
```

## 마이그레이션 상태가 "저하됨"입니다.

**성능 저하** 상태는 어플라이언스에서 GitHub Enterprise Server 마이그레이션 서비스가 대상 엔터프라이즈에 연결할 수 없음을 의미합니다. 마이그레이션은 원본 쪽에서 계속되지만 대상 상태를 알 수 없습니다.

장치 GitHub Enterprise Server와 GHE.com의 서브도메인 간의 네트워크 연결을 확인한 후 `gh elm migration status --migration-id MIGRATION-ID`를 다시 실행합니다. 상태 응답에는 연결 문제가 발생한 기간을 평가하는 데 도움이 될 수 있는 대상과의 마지막으로 성공한 연락처에 대한 타임스탬프가 포함됩니다.

## "내보내기"에서 마이그레이션이 중단됨

마이그레이션이 30분 이상 진행률 변경 없이 **내보내기** 상태로 유지되면 내보내기가 중단될 수 있습니다.

1. 리소스 수가 변경되고 있는지 여부를 실행하고 `gh elm migration status --migration-id MIGRATION-ID` 확인합니다.

2. 개수가 정적이면 대상에 대한 어플라이언스의 네트워크 연결을 확인합니다.

3. GitHub Enterprise Server 어플라이언스에서 내보내기 로그를 검토하세요(SSH 관리자 액세스 필요):

   ```shell copy
   journalctl -t elm-exporter-backfiller --since "1 hour ago" | tail -50
   journalctl -t elm-exporter-sender --since "1 hour ago" | tail -50
   ```

4. 내보내기 작업이 중단된 경우 자동으로 복구되어야 합니다. 그렇지 않은 경우 GitHub 지원에 연락하세요.

## Git 동기화가 완료되지 않음

연장된 기간 후에 초기 Git 푸시가 완료되지 않은 것으로 표시되면 `gh elm migration status` Git 동기화기 로그를 확인합니다.

```shell copy
journalctl -t elm-exporter-git-syncer --since "2 hours ago"
```

살펴볼 항목:

* **`connection refused`**: GitHub Enterprise Server 어플라이언스와 대상 간의 네트워크 문제입니다. 방화벽 규칙과 DNS 해석을 점검하세요.
* \*\*`authentication failed`\*\*personal access token (classic): 필요한 범위가 부족하거나 만료되었을 수 있습니다.
* **`remote: error`**: 대상에서 푸시를 거부할 수 있습니다. 오류 세부 정보를 문의 GitHub 지원 하세요.

## 일부 리소스를 가져오지 못했습니다.

개별 리소스를 가져오지 못하면 전체 마이그레이션이 실패할 수 있습니다. 의 출력 `gh elm migration status --migration-id MIGRATION-ID`에서 실패한 리소스 수를 볼 수 있습니다.

실패한 리소스는 모든 자동 재시도를 모두 소진한 후에만 표시되므로 표시되는 모든 오류는 개입 없이는 확인할 수 없는 것으로 확인됩니다. 상태 응답에서 오류 세부 정보를 검토합니다. 백필 또는 라이브 업데이트에서 실패한 각 리소스가 표시됩니다 `"state": "failed"`.

실패한 리소스의 수와 유형이 허용 가능한 경우 전환을 진행할 수 있습니다. 그렇지 않은 경우 마이그레이션을 중단하고 기본 문제를 해결한 다음 새 마이그레이션을 시작합니다.

## 컷오버에 실패했으며 원본 리포지토리를 사용할 수 없습니다.

원본 리포지토리가 보관된 후 전환에 실패하면 ELM 서비스가 해당 리포지토리의 보관 해제를 시도합니다. 이 작업이 실패하면 리포지토리 관리자가 리포지토리의 보관을 해제할 수 있습니다.
[리포지토리 보관](/ko/enterprise-server@3.19/repositories/archiving-a-github-repository/archiving-repositories#unarchiving-a-repository)을(를) 참조하세요.

리포지토리의 모든 문제 및 끌어오기 요청이 Elasticsearch에서 다시 인덱싱되므로 리포지토리를 보관하지 않으면 인스턴스에 추가 부하가 발생합니다.

원본 리포지토리의 보관이 해제된 후에는 `gh elm migration cutover --migration-id MIGRATION-ID`을 사용해 컷오버를 다시 시도하거나, `gh elm migration cancel --migration-id MIGRATION-ID`로 마이그레이션을 중단한 다음 준비가 되면 새 마이그레이션을 시작할 수 있습니다.

## 강제 푸시로 인해 마이그레이션을 다시 시작해야 합니다.

마이그레이션이 진행되는 동안 누군가가 원본 리포지토리의 기본 분기로 강제 푸시하는 경우 원본과 대상 간의 Git 동기화가 중단됩니다. 강제 푸시는 증분적으로 조정할 수 없는 방식으로 커밋 기록을 다시 작성합니다.

이 경우, 마이그레이션을 `gh elm migration cancel --migration-id MIGRATION-ID` 중단하고 새 마이그레이션을 시작합니다. 다시 시작하기 전에 마이그레이션이 활성 상태일 때 기본 분기로 강제 푸시가 금지된다는 것을 팀에게 알리십시오.

## 마이그레이션 액세스 토큰이 거부되었습니다.

인증 오류로 마이그레이션이 실패하는 경우 다음을 확인합니다.

* 원본 및 대상 토큰은 모두 다음과 같습니다 personal access tokens (classic).
  Fine-grained personal access tokens 는 지원되지 않습니다.
* 대상 조직에서 SAML Single Sign-On을 적용하는 경우 토큰에 SSO에 대한 권한이 부여되어야 합니다.
* 두 토큰 모두 [Enterprise Live Migrations를 사용하여 리포지토리 마이그레이션](/ko/enterprise-server@3.19/migrations/elm/migrate-your-repository#4-configure-the-live-migration-secrets)에 지정된 범위를 갖습니다.

최근에 토큰을 회전한 경우 마이그레이션에서 새 자격 증명을 자동으로 선택합니다. 마이그레이션 서비스를 실행 `ghe-config-apply` 하거나 다시 시작할 필요가 없습니다.

## GitHub CLI 액세스 토큰이 거부되었습니다.

Enterprise Live Migrations 는 두 개의 자격 증명 집합을 사용합니다. 이 섹션은 2단계에서 만들고 로컬로 저장한 **연산자 토큰** 에 `gh elm configure`적용됩니다.

연산자는 각 엔드포인트에 대해 다음을 personal access token (classic) 사용해야 합니다.

* **원본 연산자 토큰**은 GitHub Enterprise Server에서 생성해야 합니다.
* **대상 연산자 토큰**은 에 GHE.com만들어야 합니다.
* 두 토큰 모두 [Enterprise Live Migrations를 사용하여 리포지토리 마이그레이션](/ko/enterprise-server@3.19/migrations/elm/migrate-your-repository#2-create-the-tokens-used-by-the-operator-who-will-perform-the-migration)에 지정된 범위를 갖습니다.
* 토큰 소유자는 해당 엔터프라이즈의 관리자여야 합니다. 범위를 선택하면 사용자에게 관리 액세스 권한이 부여되지 않습니다.
* Fine-grained personal access tokens 는 지원되지 않습니다.

### 일반적인 응답

| 응답                                                                                                                                   | Meaning                                                                               | 해결 방법                                                                                                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401 Bad credentials`                                                                                                                | 엔드포인트에서 토큰을 인증할 수 없습니다. 권한 부여 범위는 아직 평가되지 않았습니다.                                      | 토큰이 만료되거나 해지되지 않았는지, 토큰이 완전히 복사되었는지, 원본 및 대상 토큰이 교환되지 않았는지 확인합니다. 사용 중인 호스트에서 각 토큰이 만들어졌는지 확인합니다.                                                                               |
| `403 Forbidden`                                                                                                                      | 토큰이 인증되었지만 해당 사용자 또는 범위는 작업에 권한을 부여하지 않습니다.                                           |                                                                                                                                                                                 |
| `admin:enterprise`와 함께 personal access token (classic)를 사용합니다. 토큰 소유자가 엔터프라이즈의 관리자인지 확인합니다. SAML SSO가 적용되는 경우 SSO에 대한 토큰에 권한을 부여합니다. |                                                                                       |                                                                                                                                                                                 |
| `Resource not accessible by personal access token`                                                                                   | 토큰 유형 또는 사용 권한은 지원되지 않습니다. 이는 일반적으로 fine-grained personal access token에서 발생합니다.       |                                                                                                                                                                                 |
| personal access token (classic)이 있는 `admin:enterprise`로 바꿉니다.                                                                        |                                                                                       |                                                                                                                                                                                 |
| `404 Not Found`                                                                                                                      | 요청이 잘못된 API URL을 사용하거나 Enterprise Live Migrations 대상 엔터프라이즈에 대해 사용하도록 설정되지 않을 수 있습니다. | 의 경우 GHE.com후행 슬래시 없이 테넌트 API URL(예: `https://api.SUBDOMAIN.ghe.com`)을 사용합니다. 원본 API URL도 확인합니다. 두 URL이 모두 올바르면 GitHub 지원에 문의하여 Enterprise Live Migrations이(가) 활성화되어 있는지 확인하세요. |

### 토큰의 유효성을 독립적으로 검사합니다.

각 토큰을 `/user`와 함께 사용하기 전에 Enterprise Live Migrations 엔드포인트에 대해 테스트하세요. 이러한 명령은 응답 헤더를 인쇄하지만 응답 본문을 삭제합니다.

원본(GitHub Enterprise Server) 토큰의 경우:

```shell
curl --silent --show-error --output /dev/null --dump-header - \
  --header "Authorization: Bearer $SOURCE_OPERATOR_TOKEN" \
  "$SOURCE_API_URL/user"
```

대상 토큰의 경우:

```shell
curl --silent --show-error --output /dev/null --dump-header - \
  --header "Authorization: Bearer $TARGET_OPERATOR_TOKEN" \
  "$TARGET_API_URL/user"
```

각 요청은 `200 OK`를 반환해야 합니다.
`X-OAuth-Scopes` 응답 헤더에는 `admin:enterprise`이 포함되어야 합니다.

`200 OK`이 Enterprise Live Migrations을 반환하지만 `401 Bad credentials` 명령이 `/user`을 반환하는 경우, CLI에 다른 토큰 또는 URL이 저장되어 있을 수 있습니다. 다시 실행하고 `gh elm configure` 각 토큰을 해당 엔드포인트와 신중하게 연결합니다.

운영자 토큰은 Enterprise Live Migrations CLI에 의해 로컬에 저장됩니다. 연산자 토큰을 회전한 후 다시 실행 `gh elm configure` 하거나 적절한 명령줄 옵션을 사용하여 대체 자격 증명을 제공합니다.

이는 4단계에서 구성된 마이그레이션 서비스 토큰과 다릅니다. 업데이트된 마이그레이션 서비스 자격 증명은 자동으로 반영되며 `ghe-config-apply` 또는 마이그레이션 서비스 재시작이 필요하지 않습니다.

로그, 스크린샷, 지원 번들 또는 지원 요청에 액세스 토큰을 포함하지 마세요. 문제가 계속되면 HTTP 상태, 엔드포인트 호스트 이름, 마이그레이션 ID, 표준 시간대가 포함된 타임스탬프, 그리고 상관관계 ID를 토큰은 제외하고 GitHub 지원에 제공하세요.

## 원본 GHES URL이 거부되었습니다.

Enterprise Live Migrations 에서는 GitHub Enterprise Server URL이 HTTPS를 사용해야 합니다. URL이 HTTP로 구성된 경우 마이그레이션은 실행 전 유효성 검사에 실패합니다.

## 지원을 위한 로그 수집

GitHub 지원에 문의할 때 가장 유용한 자료는 다음과 같습니다:

1. **지원 번들** (권장): `ghe-support-bundle -u` 어플라이언스에서 GitHub Enterprise Server을 실행합니다. 그러면 모든 Enterprise Live Migrations 로그가 자동으로 캡처됩니다.
2. **마이그레이션 상태 출력**: `gh elm migration status --migration-id MIGRATION-ID`
3. **마이그레이션 ID** 및 대략적인 오류 시간(표준 시간대 포함)
4. **모든 상관 ID**(오류 메시지에서)

지원 번들을 사용할 수 없는 경우 로그를 수동으로 수집할 수 있습니다.

```shell copy
journalctl -t elm-exporter-migration-manager --since "24 hours ago" > migration-manager.log
journalctl -t elm-exporter-backfiller --since "24 hours ago" > backfiller.log
journalctl -t elm-exporter-sender --since "24 hours ago" > sender.log
journalctl -t elm-exporter-git-syncer --since "24 hours ago" > git-syncer.log
```