# 관리형 클러스터

Managed Clusters에 대해 알아보고 맞춤형 백엔드 솔루션으로 빠르게 시작하세요.

## ✔️ 소개

Managed Clusters는 자체 관리형 게임 서비스와 게임 백엔드의 호스팅을 쉽고 빠르게 만들어줍니다. 서비스 이미지를 준비하면 저희가 고가용성이고 탄력적인 클라우드 환경을 제공하여 이를 실행합니다:

* 플레이어 인증,
* 데이터 저장 - 계정, 진행 상황, 인벤토리, 보상 등
* 소셜 서비스 - 채팅, 클랜, 순위표, 토너먼트 등
* 맞춤 매치메이킹 - 사용 [#advanced-matchmaker](#advanced-matchmaker "mention"), [#nakama-by-heroic-labs](#nakama-by-heroic-labs "mention"), ...
* 서버리스 컴퓨팅 - 관리형 [함수형 서비스](https://github.com/openfaas/faas) (대안: cloudscript, lambda), ...

프라이빗 클러스터는 귀하의 서비스에 **전용 컴퓨팅을 제공하여 플레이어에게 24/7 서비스할 수 있도록 합니다**.

{% hint style="info" %}
저희 클러스터 머신은 2.4 - 3.2 GHz 클럭 속도의 AMD/Intel CPU를 사용합니다. 부하 테스트 조정 및 서버에 충분한 리소스가 있는지 확인하려면 [커뮤니티 디스코드](https://discord.gg/MmJf8fWjnt) 로 연락해 주세요.
{% endhint %}

## 🛠️ 개발자 도구

개선할 부분을 발견하시면 저희 [커뮤니티 디스코드](https://discord.gg/NgCnkHbsGp).

에 알려 주세요. 원활한 경험이 되시길 바랍니다. 🚀

### Docker

서버의 신뢰성을 높이기 위해 저희는 [Docker](https://www.docker.com/) - 가상화 소프트웨어를 사용하여 운영체제 수준까지 모든 서버 코드 종속성이 서버가 어디서 어떻게 시작되든 항상 정확히 동일하도록 보장합니다.

### Kubernetes (K8s)

[Kubernetes](https://kubernetes.io/docs/concepts/overview/)는 K8s로도 알려져 있으며 컨테이너화된 애플리케이션(Docker 이미지)의 배포, 확장 및 관리를 자동화하는 오픈 소스 시스템입니다. 애플리케이션을 구성하는 컨테이너를 논리적 단위로 그룹화하여 관리 및 검색을 쉽게 합니다.

Edgegap Managed Clusters는 관리 목적으로 Kubernetes API를 제공합니다.

### K8s Lens

100만 명 이상의 사용자와 함께, [K8s Lens](https://k8slens.dev/) 는 전 세계에서 가장 인기 있는 Kubernetes IDE입니다. 클러스터에 연결하고 탐색하며 인사이트를 얻고 필요할 때 조치를 취하세요. Lens는 워크로드와 리소스의 모든 정보를 항상 적절한 컨텍스트로 실시간 제공해 줍니다.

Edgegap Cluster Kubernetes API는 Lens 또는 다른 Kubernetes IDE를 통해 사용할 수 있습니다.

### Helm 패키지 관리자

[Helm](https://helm.sh/) 은 Kubernetes용으로 빌드된 소프트웨어를 찾고 공유하며 사용하는 가장 좋은 방법입니다. Helm은 Kubernetes 애플리케이션을 관리하는 데 도움을 줍니다 - Helm 차트는 가장 복잡한 Kubernetes 애플리케이션도 정의, 설치 및 업그레이드할 수 있도록 해줍니다. 차트는 만들기, 버전 관리, 공유 및 게시가 쉬우므로 Helm을 사용하고 복사-붙여넣기를 그만두세요.

[Helm CLI 설치](https://helm.sh/docs/intro/install/) 는 개발자가 클러스터 패키지를 관리할 수 있는 간단한 인터페이스를 제공합니다.

## 🚀 시작하기

☑️ [무료 Edgegap 계정에 가입](https://app.edgegap.com/auth/register) 하고 종량제 요금제로 업그레이드하여 Clusters를 활성화하세요.

☑️ 이동: [Managed Clusters](https://app.edgegap.com/cluster-management/clusters/list) 페이지로.

☑️ 클릭: **클러스터 생성** 먼저 클릭한 다음 다음을 입력하세요:

* **레이블** 나중에 클러스터를 쉽게 찾을 수 있도록
* **클러스터 크기 -** 참조 [#introduction](#introduction "mention").

{% hint style="danger" %}
**개발 및 운영 환경을 위해 별도의 클러스터를 생성할 것을 강력히 권장합니다.**
{% endhint %}

☑️ 예상 비용을 검토하고 **클러스터 생성** 를 클릭하여 새 클러스터를 시작하세요.

☑️ 클러스터가 준비되면, **Kubeconfig를 클릭하여 구성 및 자격증명을 다운로드하세요** 새 클러스터에 연결하고 관리하기 위해.

☑️ [kubeconfig 파일을 이동하세요](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) 다음 위치로 `kubectl` 이 찾을 수 있도록.

☑️ Lens 사용자: [kubeconfig 파일을 가져오세요](https://docs.k8slens.dev/getting-started/add-cluster/#specify-kubeconfig-files).

☑️ 다음 명령으로 클러스터 연결을 테스트하세요: `kubectl get nodes` :

```bash
kubectl get nodes
NAME                            STATUS   ROLES    AGE    VERSION
lke334087-533013-294dcfe70000   Ready    <none>   10m   v1.31.0
lke334087-533013-4e69edc10000   Ready    <none>   10m   v1.31.0
lke334087-533013-50bf39880000   Ready    <none>   10m   v1.31.0
```

🙌 축하합니다! Managed Cluster 설정을 완료했습니다. 이제 서비스를 설치할 수 있습니다.

## 📦 Heroic Labs의 Nakama

{% hint style="info" %}
Edgegap을 다음과 통합하세요: [Nakama 플러그인](https://github.com/edgegap/nakama-edgegap) + [Unity 플러그인](https://github.com/edgegap/edgegap-server-nakama-plugin-unity)! [다른 플랫폼/기능에 대해서는 연락해 주세요.](https://discord.gg/NgCnkHbsGp)
{% endhint %}

자체 호스팅을 위해 다음 단계를 따르세요: [Nakama 게임 백엔드](https://heroiclabs.com/docs/nakama/getting-started/) 을(를) Managed Clusters에 호스팅하려면:

☑️ 생성: **DNS 레코드 타입 A** 를 DNS 제공자에 생성하세요(예:  [Cloudflare](https://developers.cloudflare.com/dns/get-started/)). 이후 URL을 기록해 두세요. 귀하의 **DNS 레코드용 외부 IP** 는 Lens의 Services / `ingress-nginx-controller` .

에서 확인할 수 있습니다. [☑️ DNS 설정이 올바른지 확인하려면 조회를 수행하세요](https://dnschecker.org/ns-lookup.php).

DNSchecker `☑️ 다음 이름으로 파일을 생성하세요:` values.yaml

<pre class="language-yaml"><code class="lang-yaml">내용(자신의 값 사용):

isProductionEnvironment: true
# Nakama 서버의 외부 호스트명 - 이전 단계의 DNS 레코드 <a data-footnote-ref href="#user-content-fn-1">externalHostName:</a>

이전 단계의 DNS 레코드
  nakama:
  # 배포할 Nakama 버전.
  # 사용 가능한 버전은 https://hub.docker.com/r/heroiclabs/nakama/tags 를 참조하세요.
  version: 3.26.0
  # Nakama 콘솔의 사용자 이름과 비밀번호 <a data-footnote-ref href="#user-content-fn-2">username:</a>
  관리자 사용자 이름을 직접 선택하세요 <a data-footnote-ref href="#user-content-fn-3">password:</a>
</code></pre>

{% hint style="danger" %}
**관리자용으로 안전한 비밀번호를 선택하세요** 위의 \<VALUES>를 파일 내의 본인 값으로 교체하세요.
{% endhint %}

☑️ Nakama helm 차트 배포:

```bash
helm upgrade --install \
  --namespace nakama --create-namespace -f <FILE_PATH>/values.yaml \
  --version 1.0.0 <RELEASE_NAME> oci://registry-1.docker.io/edgegap/heroiclabs-nakama
```

☑️ Lens: Workloads / Deployments 섹션에서 설치를 확인하세요, `nakama` 가 실행 중이어야 합니다.

✅ **Nakama 콘솔에 연결하세요** URL 및 자격증명은 `☑️ 다음 이름으로 파일을 생성하세요:` 파일에서 확인하세요.

🙌 축하합니다! 자체 호스팅 Nakama 게임 백엔드 설정을 완료했습니다!

### 서비스 업데이트

Managed Cluster에서 호스팅 중인 서비스를 업데이트하려면 다음 단계를 따르세요:

☑️ 귀하의 `value.yaml` 파일을 새 파일로 업데이트하세요.

☑️ 다음 명령으로 helm 차트를 업데이트하세요:

```bash
helm upgrade --reuse-values \
  --namespace nakama -f <FILE_PATH>/values.yaml \
  --version 1.0.0 <RELEASE_NAME> oci://registry-1.docker.io/edgegap/heroiclabs-nakama
```

☑️ 업데이트된 파드를 종료하여 변경 사항을 다시 로드하세요. 그러면 파드가 자동으로 재시작된 후 새 helm 차트가 사용됩니다.

🙌 축하합니다! Nakama Cluster 업데이트를 완료했습니다!

## 👷 고급 매치메이커

다음 단계를 따라 [OpenMatch](https://open-match.dev/site/) 을(를) Managed Cluster에 호스팅하세요.

☑️ DNS 제공자에 DNS 레코드 타입 A를 생성하세요(예:  [Cloudflare](https://developers.cloudflare.com/dns/get-started/)). 이후 URL을 기록해 두세요. 귀하의 **DNS 레코드용 외부 IP** 는 Lens의 Services / `ingress-nginx-controller` .

에서 확인할 수 있습니다. [☑️ DNS 설정이 올바른지 확인하려면 조회를 수행하세요](https://dnschecker.org/ns-lookup.php).

DNSchecker `☑️ 다음 이름으로 파일을 생성하세요:` values.yaml

```yaml
isProductionEnvironment: false

director:
  credential:
    registry: <YOUR_DIRECTOR_REGISTRY>
    username: <YOUR_DIRECTOR_REGISTRY_USERNAME>
    password: <YOUR_DIRECTOR_REGISTRY_PASSWORD>
  image: <DIRECTOR_IMAGE>
  env: {
    "KEY": "VALUE"
  }

mmf:
  credential:
    registry: <MATCHMAKER_FUNCTION_REGISTRY>
    username: <MATCHMAKER_FUNCTION_REGISTRY_USERNAME>
    password: <MATCHMAKER_FUNCTION_REGISTRY_PASSWORD>
  image: <MATCHMAKER_FUNCTION_IMAGE>
  env: {
    "KEY": "VALUE"
  }

frontend:
  credential:
    registry: <FRONTEND_REGISTRY>
    username: <FRONTEND_REGISTRY_USERNAME>
    password: <FRONTEND_REGISTRY_PASSWORD>
  externalHostName: <YOUR_CLOUDFLARE_HOST_NAME> # 예: exemple.test.com
  image: <FRONTEND_IMAGE>
  env: {
    "KEY": "VALUE"
  }

# 모든 서브차트에서 볼 수 있는 글로벌 구성
global:
  kubernetes:
    resources:
      requests:
        memory: 100Mi
        cpu: 100m
      limits:
        memory: 100Mi
        cpu: 100m
```

{% hint style="danger" %}
**관리자용으로 안전한 비밀번호를 선택하세요** 위의 \<VALUES>를 파일 내의 본인 값으로 교체하세요.
{% endhint %}

☑️ 추가: **Edgegap 레포지토리** 를 레포지토리 목록에 추가하세요:

```bash
helm repo add edgegap-public https://registry.edgegap.com/chartrepo/edgegap-public
```

☑️ 고급 매치메이커 helm 차트 배포:

```bash
helm upgrade --install \
  --namespace matchmaker --create-namespace -f <FILE_PATH>/values.yaml \
  --version 1.0.1 <RELEASE_NAME> edgegap-public/open-match-edgegap
```

🙌 축하합니다! 고급 매치메이커 설정을 완료했습니다!

### 서비스 업데이트

Managed Cluster에서 호스팅 중인 서비스를 업데이트하려면 다음 단계를 따르세요:

☑️ 귀하의 `value.yaml` 파일을 새 파일로 업데이트하세요.

☑️ 다음 명령으로 helm 차트를 업데이트하세요:

```bash
helm upgrade --reuse-values \
  --namespace matchmaker -f <FILE_PATH>/values.yaml \
  --version 1.0.1 <RELEASE_NAME> edgegap-public/open-match-edgegap
```

☑️ 업데이트된 파드(director, mmf, frontend)를 종료하여 변경 사항을 다시 로드하세요. 그러면 파드가 자동으로 재시작된 후 새 helm 차트가 사용됩니다.

🙌 축하합니다! 고급 매치메이커 업데이트를 완료했습니다!

### 지속적 배포

배포 파이프라인에 다음 셸 스크립트를 추가하여 서비스 업데이트를 자동화하세요:

```bash
#!/bin/bash

RELEASE_NAME="<RELEASE_NAME>"
NAMESPACE="matchmaker"  # 네임스페이스를 변경했다면 여기를 수정하세요.

helm upgrade --reuse-values -f <FILE_PATH>/value.yaml --namespace $NAMESPACE --version 1.0.1 $RELEASE_NAME edgegap-public/open-match-edgegap

echo "redis-tools 설치 중"
apt-get update
apt-get install -y redis-tools

DIRECTOR_DEPLOYMENT_NAME="$RELEASE_NAME-director"
MMF_DEPLOYMENT_NAME="$RELEASE_NAME-mmf"
CUSTOM_FRONTEND_DEPLOYMENT_NAME="$RELEASE_NAME-custom-frontend"
REDIS_HOST="$RELEASE_NAME-redis-master"

declare -A replicas

# 각 배포(director, mmf, custom-frontend)에 대해 파드를 중지합니다
for deployment in $DIRECTOR_DEPLOYMENT_NAME $MMF_DEPLOYMENT_NAME $CUSTOM_FRONTEND_DEPLOYMENT_NAME
do
  echo "배포의 파드 중지: $deployment"
  replicas[$deployment]=$(kubectl get deployment $deployment -o=jsonpath='{.spec.replicas}' --namespace $NAMESPACE)
  kubectl scale deployment/$deployment --replicas=0 --namespace $NAMESPACE
done

# 파드가 종료될 때까지 기다립니다
for deployment in $DIRECTOR_DEPLOYMENT_NAME $MMF_DEPLOYMENT_NAME $CUSTOM_FRONTEND_DEPLOYMENT_NAME
do

  echo "파드 종료 대기 중: $deployment"
  kubectl wait --for=delete pod -l app=$deployment --timeout=60s --namespace $NAMESPACE

  # 대기 명령이 성공했는지 확인합니다. 실패하면 스크립트를 종료합니다
  if [ $? -ne 0 ]; then
    echo "파드 종료 대기 실패: $deployment"
    exit 1
  fi
done

# Redis 데이터베이스 정리
echo "Redis 데이터베이스 정리 중"
redis-cli -h $REDIS_HOST flushall

# 각 배포(director, mmf, custom-frontend)에 대해 파드를 원래 수로 다시 조정합니다
for deployment in $DIRECTOR_DEPLOYMENT_NAME $MMF_DEPLOYMENT_NAME $CUSTOM_FRONTEND_DEPLOYMENT_NAME
do
  echo "배포의 파드 수를 ${replicas[$deployment]}로 재조정 중: $deployment"
  kubectl scale deployment/$deployment --replicas=${replicas[$deployment]} --namespace $NAMESPACE
done
```

### Letsencrypt 인증서 검증 (C#)

일부 클라이언트에서는 권장되는 Letsencrypt 인증서 검증이 다음 오류로 실패할 수 있습니다:

```bash
Curl error 60: Cert verify failed. Certificate has expired. UnityTls error code: 7
```

{% hint style="success" %}
운영체제를 업데이트하면 오래된 루트 인증 기관 문제를 해결할 수 있습니다.
{% endhint %}

최후의 수단으로, 게임 클라이언트는 커스텀 인증서 처리기 함수를 구현할 수 있습니다:

````csharp
```csharp
public class CustomCertificateHandler : CertificateHandler
{
  private readonly string EXPECTED_CERT = "-----BEGIN CERTIFICATE-----<key>-----END CERTIFICATE-----\r\n";
  protected override bool ValidateCertificate(byte[] certificateData)
  {
    X509Certificate2 certificate = new X509Certificate2(certificateData);
    X509Certificate2 expectedCert = new X509Certificate2(Encoding.ASCII.GetBytes(EXPECTED_CERT));

    using (SHA256 sha256 = SHA256.Create())
    {
      Debug.Log("certificate.Thumbprint: " + certificate.Thumbprint);
      Debug.Log("expectedCert.Thumbprint: " + expectedCert.Thumbprint);

      return certificate.Thumbprint == expectedCert.Thumbprint;
    }
  }
}
```
````

사용법:

```csharp
UnityWebRequest request = UnityWebRequest.Get(...);
request.certificateHandler = new BypassCertificateHandler();
request.SendWebRequest();
request.certificateHandler.Dispose();
```

저장소에 `EXPECTED_CERT` 값을 보관하고 런타임에 불러오는 것을 권장합니다. 이렇게 하면 게임 클라이언트 업데이트 없이 갱신할 수 있습니다.

## 🟢 운영 및 관측성

### 클러스터 등급 변경

출시 준비와 출시 후 최적화를 통해 출시 당일 플레이어가 차단되지 않도록 준비하세요.

{% hint style="warning" %}
&#x20;클러스터 크기 변경은 클러스터를 중지해야 합니다. 무중단 업데이트에 대해서는 [blue/green 배포](https://circleci.com/blog/canary-vs-blue-green-downtime/) 를 참조하세요.
{% endhint %}

### 지원 및 향후 업데이트

**귀하의 성공이 저희의 최우선 과제입니다.** 맞춤 요청을 보내거나, 필수 기능이 누락되었음을 요청하거나, 의견을 표현하고 싶으시면, [커뮤니티 디스코드로 연락해 주세요](https://discord.gg/MmJf8fWjnt).

[^1]: \<DNS\_A\_RECORD\_URL>

[^2]: \<USERNAME>

[^3]: \<PASSWORD>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/docs.edgegap.com-ko/learn/advanced-features/managed-clusters.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
