

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# AWS PCS 로그인 노드
<a name="working-with_login-nodes"></a>

대화형 액세스 및 작업 관리를 지원하려면 일반적으로 AWS PCS 클러스터에 하나 이상의 로그인 노드가 필요합니다. 이를 수행하는 방법은 로그인 노드 기능을 위해 구성된 정적 AWS PCS 컴퓨팅 노드 그룹을 사용하는 것입니다. 로그인 노드 역할을 하도록 독립 실행형 EC2 인스턴스를 구성할 수도 있습니다.

**Topics**
+ [AWS PCS 컴퓨팅 노드 그룹을 사용하여 로그인 노드 제공](working-with_login-nodes_compute-node-group-for-login.md)
+ [독립 실행형 인스턴스를 AWS PCS 로그인 노드로 사용](working-with_login-nodes_standalone.md)
+ [독립 실행형 로그인 노드를 AWS PCS의 여러 클러스터에 연결](multi-cluster-login-script.md)

# AWS PCS 컴퓨팅 노드 그룹을 사용하여 로그인 노드 제공
<a name="working-with_login-nodes_compute-node-group-for-login"></a>

 이 주제에서는 제안된 구성 옵션에 대한 개요를 제공하고 AWS PCS 컴퓨팅 노드 그룹을 사용하여 클러스터에 대한 지속적인 대화형 액세스를 제공할 때 고려해야 할 사항을 설명합니다.

## 로그인 노드에 대한 AWS PCS 컴퓨팅 노드 그룹 생성
<a name="working-with_login-nodes_compute-node-group-for-login_create"></a>

 운영상 이는 일반 컴퓨팅 노드 그룹을 생성하는 것과 크게 다르지 않습니다. 그러나 몇 가지 주요 구성 선택 사항이 있습니다.
+  컴퓨팅 노드 그룹에서 하나 이상의 EC2 인스턴스에 대한 정적 조정 구성을 설정합니다.
+  온디맨드 구매 옵션을 선택하여 인스턴스(들)를 회수하지 않도록 합니다.
+  로그인과 같은 컴퓨팅 노드 그룹의 정보 이름을 선택합니다.
+  VPC 외부에서 로그인 노드 인스턴스(들)에 액세스하려면 퍼블릭 서브넷을 사용하는 것이 좋습니다.
+  SSH 액세스를 허용하려는 경우 시작 템플릿에는 SSH 포트를 선택한 IP 주소에 노출하는 보안 그룹이 있어야 합니다.
+  IAM 인스턴스 프로파일에는 최종 사용자에게 부여할 AWS 권한만 있어야 합니다. 세부 정보는 [AWS 병렬 컴퓨팅 서비스를 위한 IAM 인스턴스 프로파일](security-instance-profiles.md) 섹션을 참조하세요.
+  AWS Systems Manager Session Manager가 로그인 인스턴스를 관리하도록 허용하는 것이 좋습니다.
+  인스턴스 AWS 자격 증명에 대한 액세스를 관리 사용자로만 제한하는 것이 좋습니다.
+  로그인 노드(들)가 지속적으로 실행되므로 일반 컴퓨팅 노드 그룹보다 저렴한 인스턴스 유형을 선택합니다.
+  모든 인스턴스에 동일한 소프트웨어가 설치되어 있는지 확인하려면 다른 컴퓨팅 노드 그룹과 동일한(또는 파생) AMI를 사용합니다. AMIs. [AWS PCS용 Amazon Machine Image(AMIs)](working-with_ami.md) 
+  로그인 노드에서 컴퓨팅 인스턴스와 동일한 네트워크 파일 시스템(Amazon EFS, Amazon FSx for Lustre 등) 탑재를 구성합니다. 자세한 내용은 [AWS PCS에서 네트워크 파일 시스템 사용](working-with_file-systems.md) 단원을 참조하십시오.

**로그인 노드에 액세스**  
새 컴퓨팅 노드 그룹이 ACTIVE 상태에 도달하면 생성한 EC2 인스턴스(들)를 찾아 로그인할 수 있습니다. 자세한 내용은 [AWS PCS에서 컴퓨팅 노드 그룹 인스턴스 찾기](working-with_compute-instances.md) 단원을 참조하십시오.

## 로그인 노드에 대한 AWS PCS 컴퓨팅 노드 그룹 업데이트
<a name="working-with_login-nodes_compute-node-group-for-login_update"></a>

 UpdateComputeNodeGroup을 사용하여 로그인 노드 그룹을 업데이트할 수 있습니다. 노드 그룹 업데이트 프로세스의 일부로 실행 중인 인스턴스가 교체됩니다. 이렇게 하면 인스턴스의 활성 사용자 세션 또는 프로세스가 중단됩니다. 실행 중이거나 대기 중인 Slurm 작업은 영향을 받지 않습니다. 자세한 내용은 [AWS PCS 컴퓨팅 노드 그룹 업데이트](working-with_cng_update.md) 단원을 참조하십시오.

 컴퓨팅 노드 그룹에서 사용하는 시작 템플릿을 편집할 수도 있습니다. UpdateComputeNodeGroup을 사용하여 업데이트된 시작 템플릿을 컴퓨팅 노드 그룹에 적용해야 합니다. 컴퓨팅 노드 그룹에서 시작된 새 EC2 인스턴스는 업데이트된 시작 템플릿을 사용합니다. 자세한 내용은 [AWS PCS에서 Amazon EC2 시작 템플릿 사용](working-with_launch-templates.md) 단원을 참조하십시오.

## 로그인 노드에 대한 AWS PCS 컴퓨팅 노드 그룹 삭제
<a name="working-with_login-nodes_compute-node-group-for-login_delete"></a>

 AWS PCS에서 **컴퓨팅 노드 그룹 삭제 메커니즘을 사용하여 로그인 노드 그룹을** 업데이트할 수 있습니다. 실행 중인 인스턴스는 노드 그룹 삭제의 일부로 종료됩니다. 이렇게 하면 인스턴스의 활성 사용자 세션 또는 프로세스가 중단됩니다. 실행 중이거나 대기 중인 Slurm 작업은 영향을 받지 않습니다. 자세한 내용은 [AWS PCS에서 컴퓨팅 노드 그룹 삭제](working-with_cng_delete.md) 단원을 참조하십시오.

# 독립 실행형 인스턴스를 AWS PCS 로그인 노드로 사용
<a name="working-with_login-nodes_standalone"></a>

 AWS PCS 클러스터의 Slurm 스케줄러와 상호 작용하도록 독립 EC2 인스턴스를 설정할 수 있습니다. 이는 AWS PCS 클러스터에서 작동하지만 AWS PCS 관리 외부에서 작동하는 로그인 노드, 워크스테이션 또는 전용 워크플로 관리 호스트를 생성하는 데 유용합니다. 이렇게 하려면 각 독립 실행형 인스턴스가 다음을 수행해야 합니다.

1. 호환되는 Slurm 소프트웨어 버전이 설치되어 있어야 합니다.

1.  AWS PCS 클러스터의 Slurmctld 엔드포인트에 연결할 수 있어야 합니다.

1. Slurm Auth 및 Cred Kiosk Daemon(`sackd`)이 AWS PCS 클러스터의 엔드포인트 및 보안 암호로 올바르게 구성되도록 합니다. 자세한 내용은 Slurm 설명서의 [sackd](https://slurm.schedmd.com/sackd.html)를 참조하세요.

 이 자습서는 AWS PCS 클러스터에 연결하는 독립 인스턴스를 구성하는 데 도움이 됩니다.

**Contents**
+ [1단계 - 대상 AWS PCS 클러스터의 주소 및 보안 암호 검색](working-with_login-nodes_standalone_get-addr.md)
+ [2단계 - EC2 인스턴스 시작](working-with_login-nodes_standalone_launch.md)
+ [3단계 - 인스턴스에 Slurm 설치](working-with_login-nodes_standalone_install-slurm.md)
+ [4단계 - 클러스터 보안 암호 검색 및 저장](working-with_login-nodes_standalone_get-secret.md)
+ [5단계 - AWS PCS 클러스터에 대한 연결 구성](working-with_login-nodes_standalone_configure-connection.md)
+ [6단계 - (선택 사항) 연결 테스트](working-with_login-nodes_standalone_test.md)

# 1단계 - 대상 AWS PCS 클러스터의 주소 및 보안 암호 검색
<a name="working-with_login-nodes_standalone_get-addr"></a>

다음 명령과 AWS CLI 함께를 사용하여 대상 AWS PCS 클러스터에 대한 세부 정보를 검색합니다. 명령을 실행하기 전에 다음과 같은 바꾸기를 합니다.
+ *region-code*를 대상 클러스터가 실행 AWS 리전 중인 로 바꿉니다.
+ *cluster-ident*를 대상 클러스터의 이름 또는 식별자로 바꿉니다.

```
aws pcs get-cluster --region region-code --cluster-identifier cluster-ident
```

명령은이 예제와 유사한 출력을 반환합니다.

```
{
    "cluster": {
        "name": "get-started",
        "id": "pcs_123456abcd",
        "arn": "arn:aws:pcs:us-east-1:111122223333:cluster/pcs_123456abcd",
        "status": "ACTIVE",
        "createdAt": "2024-12-17T21:03:52+00:00",
        "modifiedAt": "2024-12-17T21:03:52+00:00",
        "scheduler": {
            "type": "SLURM",
            "version": "25.05"
        },
        "size": "SMALL",
        "slurmConfiguration": {
            "authKey": {
                "secretArn": "arn:aws:secretsmanager:us-east-1:111122223333:secret:pcs!slurm-secret-pcs_123456abcd-a12ABC",
                "secretVersion": "ef232370-d3e7-434c-9a87-ec35c1987f75"
            }
        },
        "networking": {
            "subnetIds": [
                "subnet-0123456789abcdef0"
            ],
            "securityGroupIds": [
                "sg-0123456789abcdef0"
            ]
        },
        "endpoints": [
            {
                "type": "SLURMCTLD",
                "privateIpAddress": "10.3.149.220",
                "port": "6817"
            }
        ]
    }
}
```

이 샘플에서 클러스터 Slurm 컨트롤러 엔드포인트의 IP 주소는 `10.3.149.220` 이고 포트에서 실행 중입니다`6817`. `secretArn`는 이후 단계에서 클러스터 보안 암호를 검색하는 데 사용됩니다. IP 주소와 포트는 이후 단계에서 `sackd` 서비스를 구성하는 데 사용됩니다.

# 2단계 - EC2 인스턴스 시작
<a name="working-with_login-nodes_standalone_launch"></a>

**EC2 인스턴스 시작**

1. [Amazon EC2 콘솔](https://console.aws.amazon.com/ec2)을 엽니다.

1. 탐색 창에서 **Instances**(인스턴스)를 선택한 다음에 **Launch Instances**(인스턴스 시작)를 선택하여 새 인스턴스 시작 마법사를 엽니다.

1. (선택 사항) **이름 및 태그** 섹션에서와 같은 인스턴스의 이름을 제공합니다`PCS-LoginNode`. 이름은 인스턴스에 리소스 태그(`Name=PCS-LoginNode`)로 할당됩니다.

1. **애플리케이션 및 OS 이미지** 섹션에서 AWS PCS에서 지원하는 운영 체제 중 하나의 AMI를 선택합니다. 자세한 내용은 [지원되는 운영 체제](working-with_ami_installers.md#working-with_ami_installers_os) 단원을 참조하십시오.

1. **인스턴스 유형** 섹션에서 지원되는 인스턴스 유형을 선택합니다. 자세한 내용은 [지원되는 인스턴스 유형](working-with_ami_installers.md#working-wth_ami_installers_instance-types) 단원을 참조하십시오.

1. **키 페어** 섹션에서 인스턴스에 사용할 SSH 키 페어를 선택합니다.

1. **네트워크 설정** 섹션에서:

   1. **편집**을 선택합니다.

     1.  AWS PCS 클러스터의 VPC를 선택합니다.

     1. **방화벽(보안 그룹)**에서 **기존 보안 그룹 선택**을 선택합니다.

        1. 인스턴스와 대상 AWS PCS 클러스터의 Slurm 컨트롤러 간의 트래픽을 허용하는 보안 그룹을 선택합니다. 자세한 내용은 [보안 그룹 요구 사항 및 고려 사항](working-with_networking_sg.md#working-with_networking_sg-requirements) 단원을 참조하십시오.

        1. (선택 사항) 인스턴스에 대한 인바운드 SSH 액세스를 허용하는 보안 그룹을 선택합니다.

1. **스토리지** 섹션에서 필요에 따라 스토리지 볼륨을 구성합니다. 애플리케이션과 라이브러리를 설치하여 사용 사례를 활성화할 수 있도록 충분한 공간을 구성해야 합니다.

1.  **고급**에서 클러스터 보안 암호에 대한 액세스를 허용하는 IAM 역할을 선택합니다. 자세한 내용은 [Slurm 클러스터 보안 암호 가져오기](working-with_clusters_secrets_get.md) 단원을 참조하십시오.

1.  **요약** 창에서 **인스턴스 시작**을 선택합니다.

# 3단계 - 인스턴스에 Slurm 설치
<a name="working-with_login-nodes_standalone_install-slurm"></a>

인스턴스가 시작되고 활성화되면 원하는 메커니즘을 사용하여 인스턴스에 연결합니다. 에서 제공하는 Slurm 설치 관리자 AWS 를 사용하여 인스턴스에 Slurm을 설치합니다. 자세한 내용은 [Slurm 설치 관리자](working-with_ami_installers.md#working-with_ami_installers_slurm) 단원을 참조하십시오.

Slurm 설치 관리자를 다운로드하고 압축을 푼 다음 `installer.sh` 스크립트를 사용하여 Slurm을 설치합니다. 자세한 내용은 [3단계 - Slurm 설치](working-with_ami_custom_install-slurm.md) 단원을 참조하십시오.

# 4단계 - 클러스터 보안 암호 검색 및 저장
<a name="working-with_login-nodes_standalone_get-secret"></a>

이 지침에는가 필요합니다 AWS CLI. 자세한 내용은 [버전 2 사용 설명서의의 최신 버전 설치 또는 업데이트를 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) *AWS Command Line Interface 참조하세요*.

다음 명령을 사용하여 클러스터 보안 암호를 저장합니다.
+ Slurm에 대한 구성 디렉터리를 생성합니다.

  ```
  sudo mkdir -p /etc/slurm
  ```
+ 클러스터 보안 암호를 검색, 디코딩 및 저장합니다. 이 명령을 실행하기 전에 *region-code*를 대상 클러스터가 실행 중인 리전으로 바꾸고 *secret-arn*을 [1단계](working-with_login-nodes_standalone_get-addr.md)에서 `secretArn` 검색된 값으로 바꿉니다.

  ```
  aws secretsmanager get-secret-value \
   --region region-code \
   --secret-id 'secret-arn' \
   --version-stage AWSCURRENT \
   --query 'SecretString' \
   --output text | base64 -d | sudo tee /etc/slurm/slurm.key
  ```
**주의**  
다중 사용자 환경에서는 인스턴스에 액세스할 수 있는 모든 사용자가 인스턴스 메타데이터 서비스(IMDS)에 액세스할 수 있는 경우 클러스터 보안 암호를 가져올 수 있습니다. 이렇게 하면 다른 사용자를 가장할 수 있습니다. IMDS에 대한 액세스를 루트 또는 관리 사용자로만 제한하는 것이 좋습니다. 또는 인스턴스 프로파일에 의존하지 않는 다른 메커니즘을 사용하여 보안 암호를 가져오고 구성하는 것이 좋습니다.
+ Slurm 키 파일에 대한 소유권 및 권한을 설정합니다.

  ```
  sudo chmod 0600 /etc/slurm/slurm.key
  sudo chown slurm:slurm /etc/slurm/slurm.key
  ```
**참고**  
Slurm 키는 `sackd` 서비스가 실행되는 사용자 및 그룹이 소유해야 합니다.

# 5단계 - AWS PCS 클러스터에 대한 연결 구성
<a name="working-with_login-nodes_standalone_configure-connection"></a>

 AWS PCS 클러스터에 대한 연결을 설정하려면 다음 단계에 따라 `sackd`를 시스템 서비스로 시작합니다.

**참고**  
 Slurm 25.05 이상을 사용하는 경우 스크립트를 사용하여 로그인 노드를 설정하여 대신 여러 클러스터에 연결할 수 있습니다. 자세한 내용은 [독립 실행형 로그인 노드를 AWS PCS의 여러 클러스터에 연결](multi-cluster-login-script.md) 단원을 참조하십시오.

1. 다음 명령을 사용하여 `sackd` 서비스에 대한 환경 파일을 설정합니다. 명령을 실행하기 전에 *ip-address* 및 *port*를 [1단계](working-with_login-nodes_standalone_get-addr.md)의 엔드포인트에서 검색된 값으로 바꿉니다.

   ```
   sudo echo "SACKD_OPTIONS='--conf-server=ip-address:port'" > /etc/sysconfig/sackd
   ```

1. `sackd` 프로세스 관리를 위한 `systemd` 서비스 파일을 생성합니다.

   ```
   sudo cat << EOF > /etc/systemd/system/sackd.service
   [Unit]
   Description=Slurm auth and cred kiosk daemon
   After=network-online.target remote-fs.target
   Wants=network-online.target
   ConditionPathExists=/etc/sysconfig/sackd
   
   [Service]
   Type=notify
   EnvironmentFile=/etc/sysconfig/sackd
   User=slurm
   Group=slurm
   RuntimeDirectory=slurm
   RuntimeDirectoryMode=0755
   ExecStart=/opt/aws/pcs/scheduler/slurm-25.05/sbin/sackd --systemd \$SACKD_OPTIONS
   ExecReload=/bin/kill -HUP \$MAINPID
   KillMode=process
   LimitNOFILE=131072
   LimitMEMLOCK=infinity
   LimitSTACK=infinity
   
   [Install]
   WantedBy=multi-user.target
   EOF
   ```

1. `sackd` 서비스 파일의 소유권을 설정합니다.

   ```
   sudo chown root:root /etc/systemd/system/sackd.service && \
       sudo chmod 0644 /etc/systemd/system/sackd.service
   ```

1. `sackd` 서비스를 활성화합니다.

   ```
   sudo systemctl daemon-reload && sudo systemctl enable sackd
   ```

1. `sackd` 서비스를 시작합니다.

   ```
   sudo systemctl start sackd
   ```

# 6단계 - (선택 사항) 연결 테스트
<a name="working-with_login-nodes_standalone_test"></a>

`sackd` 서비스가 실행 중인지 확인합니다. 샘플 출력은 다음과 같습니다. 오류가 있는 경우 일반적으로 여기에 표시됩니다.

```
[root@ip-10-3-27-112 ~]# systemctl status sackd
[x] sackd.service - Slurm auth and cred kiosk daemon
   Loaded: loaded (/etc/systemd/system/sackd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2024-12-17 16:34:55 UTC; 8s ago
 Main PID: 9985 (sackd)
   CGroup: /system.slice/sackd.service
           └─9985 /opt/aws/pcs/scheduler/slurm-25.05/sbin/sackd --systemd --conf-server=10.3.149.220:6817

Dec 17 16:34:55 ip-10-3-27-112.ec2.internal systemd[1]: Starting Slurm auth and cred kiosk daemon...
Dec 17 16:34:55 ip-10-3-27-112.ec2.internal systemd[1]: Started Slurm auth and cred kiosk daemon.
Dec 17 16:34:55 ip-10-3-27-112.ec2.internal sackd[9985]: sackd: running
```

`sinfo` 및와 같은 Slurm 클라이언트 명령을 사용하여 클러스터에 대한 연결이 작동하는지 확인합니다`squeue`. 다음은의 출력 예제입니다`sinfo`.

```
[root@ip-10-3-27-112 ~]# /opt/aws/pcs/scheduler/slurm-25.05/bin/sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
all up infinite 4 idle~ compute-[1-4]
```

작업을 제출할 수도 있어야 합니다. 예를 들어이 예제와 유사한 명령은 클러스터의 노드 1개에서 대화형 작업을 시작합니다.

```
/opt/aws/pcs/scheduler/slurm-25.05/bin/srun --nodes=1 -p all --pty bash -i
```

# 독립 실행형 로그인 노드를 AWS PCS의 여러 클러스터에 연결
<a name="multi-cluster-login-script"></a>

`pcs-multi-cluster-login-configure.sh` 스크립트는 단일 독립 실행형 로그인 노드에서 여러 Slurm `sackd` 데몬을 구성하는 자동화된 방법을 제공합니다. 이를 통해 로그인 노드가 여러 클러스터와 통신할 수 있습니다. 스크립트는 다음 작업을 자동화합니다.
+  AWS PCS API 작업을 사용하여 클러스터 정보 가져오기
+ base64로 인코딩된 Slurm 인증 키에 대한 프롬프트
+ 클러스터 인증 키를 사용하여 Slurm JWKS 파일을 생성합니다.
+ 클러스터 엔드포인트 및 포트로 `sackd` 서비스를 구성합니다.
+ 클러스터별 데몬에 대한 `systemd` 서비스 파일을 생성합니다`sackd`.
+ 클러스터 환경 설정을 위한 활성화 스크립트를 생성합니다.
+ `sackd` 서비스를 활성화하고 시작합니다.

**참고**  
이 스크립트에는 Slurm 버전 25.05 이상이 필요합니다.

Slurm은 인스턴스에 이미 설치되어 있어야 합니다(수동 프로세스의 [3단계](working-with_login-nodes_standalone_install-slurm.md)에 해당). 인스턴스는 대상 클러스터의 엔드포인트에 도달할 수 있어야 합니다. 스크립트는 수동 구성 프로세스에서 [4단계](working-with_login-nodes_standalone_get-secret.md)와 [5단계](working-with_login-nodes_standalone_configure-connection.md)의 동일한 작업을 수행합니다. 클러스터 정보를 자동으로 가져오고, `sackd` 서비스를 구성하고, 필요한 `systemd` 서비스 파일을 생성하고, 사용자가 클러스터 상호 작용을 위해 셸 환경을 구성하는 데 사용할 수 있는 활성화 스크립트를 생성합니다.

**Topics**
+ [AWS PCS 다중 클러스터 로그인 노드 구성 스크립트의 사전 조건](multi-cluster-login-script-prerequisites.md)
+ [AWS PCS 다중 클러스터 로그인 노드 구성 스크립트 코드](multi-cluster-login-script-code.md)
+ [AWS PCS 다중 클러스터 로그인 노드 구성 스크립트 사용](multi-cluster-login-script-usage.md)

# AWS PCS 다중 클러스터 로그인 노드 구성 스크립트의 사전 조건
<a name="multi-cluster-login-script-prerequisites"></a>

## 시스템 요구 사항
<a name="system-requirements"></a>
+ 가 `systemd` 지원되는 Linux OS
+ 시스템 구성에 대한 루트 권한

## 필수 명령 및 패키지
<a name="required-commands"></a>
+ `bash` – 쉘 인터프리터(버전 4.0 이상)
+ `curl` - AWS IMDS v2 메타데이터 검색의 경우
+ `jq` - AWS API 응답을 구문 분석하기 위한 JSON 프로세서
+ `aws` – AWS CLI v2 - AWS PCS API 작업 실행 및 Secrets Manager 액세스
+ `systemctl` - `systemd` 서비스 관리
+ `find` - 파일 시스템 검색 유틸리티
+ `grep` - 텍스트 패턴 일치
+ `sed` - 텍스트 조작을 위한 스트림 편집기
+ `sort` - 텍스트 정렬 유틸리티
+ `tail` - 파일의 마지막 줄을 표시합니다.
+ `mkdir` - 디렉터리 생성
+ `chmod` - 파일 권한 변경
+ `chown` - 파일 소유권 변경
+ `ldconfig` - 동적 링커 구성

## AWS 요구 사항
<a name="aws-requirements"></a>
+ Slurm 버전 25.05 이상을 실행하는 AWS PCS 클러스터
+ AWS 구성된 자격 증명(IAM 역할, 자격 증명 파일 또는 환경 변수를 통해)
+ 다음에 대한 권한:
  + `pcs:GetCluster`
  + `secretsmanager:GetSecretValue` (대체 보안 암호를 사용하는 경우)

## 시스템 사용자 및 그룹
<a name="system-users-groups"></a>
+ `slurm` 사용자와 그룹이 시스템에 있어야 합니다.

## Slurm 설치
<a name="slurm-installation"></a>
+ Slurm은 AWS PCS Slurm 설치 관리자 패키지와 동일한 위치에 설치해야 합니다.

  ```
  /opt/aws/pcs/scheduler/slurm-version
  ```

# AWS PCS 다중 클러스터 로그인 노드 구성 스크립트 코드
<a name="multi-cluster-login-script-code"></a>

다음 소스 코드를 다음 이름의 파일에 저장합니다.

```
pcs-multi-cluster-login-configure.sh
```

## 스크립트 소스 코드
<a name="multi-cluster-login-script-code-content"></a>

```
#!/bin/bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

# AWS PCS Multi-Cluster Standalone Login Node Configuration Script
# 
# This script configures AWS Parallel Computing Service (PCS) multi-cluster stand alone login nodes
# by setting up the Slurm authentication and credential kiosk daemon (sackd)
# for connecting to remote PCS clusters.
#
# Prerequisites:
# - AWS CLI configured with appropriate permissions
# - Slurm version 25.05 or later
# - Root privileges for system configuration
# - Network connectivity to AWS PCS endpoints


set -eo pipefail

# Function to display usage
usage() {
    echo "Usage: $0 --cluster-identifier <cluster-identifier> [--endpoint-url <endpoint-url>]"
    echo "       $0 -h|--help"
}

# Function to display help
help() {
    echo "AWS PCS Multi-Cluster Standalone Login Node Configuration Script"
    echo "==============================================="
    echo
    echo "This script configures multi-cluster standalone login node for AWS Parallel Computing Service (PCS)"
    echo "by setting up the Slurm authentication and credential kiosk daemon (sackd)."
    echo
    usage
    echo
    echo "Options:"
    echo "  --cluster-identifier <id>    AWS PCS cluster identifier (required)"
    echo "  --endpoint-url <url>         Custom PCS endpoint URL (optional)"
    echo "  -h, --help                   Show this help message"
    echo
    echo "Examples:"
    echo "  $0 --cluster-identifier my-pcs-cluster"
    echo
    echo "Note: This script requires root privileges and Slurm version 25.05 or later."
}

# Function to retrieve authentication key
get_auth_key() {
    if [ "$ALTERNATE_SECRET_RETRIEVAL" = "true" ]; then
        echo "Retrieving authentication key from AWS Secrets Manager..." >&2
        local auth_key_arn=$(echo "$CLUSTER_INFO" | jq -r '.cluster.slurmConfiguration.authKey.secretArn')
        local auth_key_version=$(echo "$CLUSTER_INFO" | jq -r '.cluster.slurmConfiguration.authKey.secretVersion')
        
        if [ "$auth_key_arn" = "null" ] || [ "$auth_key_version" = "null" ]; then
            echo "Error: Auth key information not found in cluster configuration" >&2
            exit 1
        fi
        
        if ! aws secretsmanager get-secret-value --secret-id "$auth_key_arn" --version-id "$auth_key_version" --query SecretString --output text --region "$REGION" 2>/dev/null; then
            echo "Error: Failed to retrieve auth key from Secrets Manager" >&2
            exit 1
        fi
    else
        echo "Please enter the base64-encoded Slurm authentication key:" >&2
        echo -n "Base64 of the Slurm secret key: " >&2
        local key
        read -rs key
        echo >&2
        echo "$key"
    fi
}

# Function to get next available SACKD port
get_next_sackd_port() {
    local exclude_file="$1"
    local port=6918
    local used_ports=()
    
    # Get all currently used SACKD ports into an array
    while IFS= read -r line; do
        used_ports+=("$line")
    done < <(find /etc/sysconfig -name "sackd-pcs-*" ! -path "$exclude_file" \
             -exec grep SACKD_PORT= '{}' ';' 2>/dev/null | \
             sed 's/.*SACKD_PORT=//' | sort -n)
    
    # Loop through used ports to find first available port
    for used_port in "${used_ports[@]}"; do
        if [ "$port" -lt "$used_port" ]; then
            break
        elif [ "$port" -eq "$used_port" ]; then
            ((port++))
        fi
    done
    
    echo "$port"
}

# Function to configure cluster
configure_cluster() {
    mkdir -p /etc/slurm
    SLURM_JWKS_FILE="/etc/slurm/slurm-${CLUSTER_NAME}.jwks"
    echo '{"keys":[{"alg":"HS256","kty":"oct","kid":"key-'"${CLUSTER_ID}"'","k":"'"${BASE64_SLURM_KEY}"'"}]}' | jq -c '.' > "${SLURM_JWKS_FILE}"
    
    chmod 0600 "$SLURM_JWKS_FILE"
    chown slurm:slurm "$SLURM_JWKS_FILE"
    
    SLURM_INSTALL_PATH="/opt/aws/pcs/scheduler/slurm-${SLURM_VERSION}"
    
    SACKD_RUNTIME_DIRECTORY="/run/slurm-${CLUSTER_NAME}"
    mkdir -p "${SACKD_RUNTIME_DIRECTORY}"
    chown slurm:slurm "${SACKD_RUNTIME_DIRECTORY}"
    
    mkdir -p /etc/sysconfig
    SACKD_SERVICE_NAME="sackd-pcs-${CLUSTER_NAME}"
    SACKD_SERVICE_ENV="/etc/sysconfig/${SACKD_SERVICE_NAME}"
    SACKD_PORT=$(get_next_sackd_port "$SACKD_SERVICE_ENV")
    cat > "${SACKD_SERVICE_ENV}" << EOF
SACKD_OPTIONS='--conf-server=$ENDPOINTS'
SLURM_SACK_JWKS='$SLURM_JWKS_FILE'
RUNTIME_DIRECTORY='$SACKD_RUNTIME_DIRECTORY'
SACKD_PORT=$SACKD_PORT
EOF
    
    SACKD_SERVICE_PATH="/etc/systemd/system/${SACKD_SERVICE_NAME}.service"
    
    cat << EOF > "$SACKD_SERVICE_PATH"
[Unit]
Description=Slurm auth and cred kiosk daemon
After=network-online.target remote-fs.target
Wants=network-online.target
ConditionPathExists=${SACKD_SERVICE_ENV}

[Service]
Type=notify
EnvironmentFile=${SACKD_SERVICE_ENV}
User=slurm
Group=slurm
RuntimeDirectory=slurm-${CLUSTER_NAME}
RuntimeDirectoryMode=0755
ExecStart=${SLURM_INSTALL_PATH}/sbin/sackd --systemd \$SACKD_OPTIONS
ExecReload=/bin/kill -HUP \$MAINPID
KillMode=process
LimitNOFILE=131072
LimitMEMLOCK=infinity
LimitSTACK=infinity

[Install]
WantedBy=multi-user.target
EOF
    
    chown root:root "$SACKD_SERVICE_PATH"
    chmod 0644 "$SACKD_SERVICE_PATH"
    systemctl daemon-reload && systemctl enable "$SACKD_SERVICE_NAME"
    systemctl restart "$SACKD_SERVICE_NAME"
    
    ACTIVATE_SCRIPT="activate-pcs-${CLUSTER_NAME}"
    cat > "$ACTIVATE_SCRIPT" << EOF
# Activate script for Slurm cluster ${CLUSTER_NAME}

# Add Slurm paths
export PATH="${SLURM_INSTALL_PATH}/bin:\$PATH"
export MANPATH="${SLURM_INSTALL_PATH}/share/man:\$MANPATH"
export LD_LIBRARY_PATH="${SLURM_INSTALL_PATH}/lib:\$LD_LIBRARY_PATH"
ldconfig

# Set Slurm configuration
export SLURM_CONF="/run/slurm-${CLUSTER_NAME}/conf/slurm.conf"
export PCS_CLUSTER_NAME="${CLUSTER_NAME}"
export PCS_CLUSTER_IDENTIFIER="${CLUSTER_IDENTIFIER}"
export PCS_CLUSTER_ID="${CLUSTER_ID}"

echo "Activated PCS cluster environment: ${CLUSTER_NAME}"

# Deactivate function
function deactivate-pcs-${CLUSTER_NAME}() {
    export PATH="\$(echo "\$PATH" | sed -e "s|${SLURM_INSTALL_PATH}/bin:||g" -e "s|:${SLURM_INSTALL_PATH}/bin||g" -e "s|^${SLURM_INSTALL_PATH}/bin\$||")"
    export MANPATH="\$(echo "\$MANPATH" | sed -e "s|${SLURM_INSTALL_PATH}/share/man:||g" -e "s|:${SLURM_INSTALL_PATH}/share/man||g" -e "s|^${SLURM_INSTALL_PATH}/share/man\$||")"
    export LD_LIBRARY_PATH="\$(echo "\$LD_LIBRARY_PATH" | sed -e "s|${SLURM_INSTALL_PATH}/lib:||g" -e "s|:${SLURM_INSTALL_PATH}/lib||g" -e "s|^${SLURM_INSTALL_PATH}/lib\$||")"
    unset SLURM_CONF
    unset PCS_CLUSTER_NAME
    unset PCS_CLUSTER_IDENTIFIER
    unset PCS_CLUSTER_ID
    unset -f deactivate-pcs-${CLUSTER_NAME}
    ldconfig
    echo "Deactivated PCS cluster environment: ${CLUSTER_NAME}"
}

export -f deactivate-pcs-${CLUSTER_NAME}

EOF
}

# Main function
main() {
    # Parse arguments
    CLUSTER_IDENTIFIER=""
    PCS_ENDPOINT_URL=""
    
    while [ "$1" != "" ]; do
        case $1 in
            --cluster-identifier)
                shift
                CLUSTER_IDENTIFIER="$1"
                ;;
            --endpoint-url)
                shift
                PCS_ENDPOINT_URL="--endpoint-url $1"
                ;;
            -h|--help)
                help
                exit 0
                ;;
            *)
                echo "Invalid argument: $1" >&2
                usage >&2
                exit 1
                ;;
        esac
        shift
    done
    
    # Validate required arguments
    if [ -z "$CLUSTER_IDENTIFIER" ]; then
        echo "Error: --cluster-identifier is required" >&2
        usage >&2
        exit 1
    fi
    
    # Validate running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root" >&2
        exit 1
    fi
    
    # Validate required commands are available
    for cmd in aws jq curl; do
        if ! command -v "$cmd" &> /dev/null; then
            echo "Error: Required command '$cmd' not found" >&2
            exit 1
        fi
    done
    
    # Get the region name from IMDS v2 with error handling (try IPv6 first, fallback to IPv4)
    echo "Retrieving AWS region from instance metadata..."
    # Try IPv6 IMDS endpoint first (fd00:ec2::254) with fast timeout (1s connect, 2s total)
    # If IPv6 fails, fallback to IPv4 IMDS endpoint (169.254.169.254)
    IMDS_ENDPOINT="http://[fd00:ec2::254]"
    if ! TOKEN=$(curl -s -X PUT "${IMDS_ENDPOINT}/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" --connect-timeout 1 --max-time 2 2>/dev/null); then
        IMDS_ENDPOINT="http://169.254.169.254"
        if ! TOKEN=$(curl -s -X PUT "${IMDS_ENDPOINT}/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" --max-time 5); then
            echo "Error: Failed to retrieve IMDS token. Ensure this script is running on an EC2 instance." >&2
            exit 1
        fi
    fi
    
    if ! REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" "${IMDS_ENDPOINT}/latest/dynamic/instance-identity/document" --max-time 5 | jq -r '.region'); then
        echo "Error: Failed to retrieve AWS region from instance metadata" >&2
        exit 1
    fi
    
    echo "Detected AWS region: $REGION"
    
    # Retrieve cluster information from AWS PCS
    echo "Retrieving cluster information for: $CLUSTER_IDENTIFIER"
    # shellcheck disable=SC2086
    if ! CLUSTER_INFO=$(aws pcs get-cluster --region "$REGION" --cluster-identifier "$CLUSTER_IDENTIFIER" $PCS_ENDPOINT_URL 2>/dev/null); then
        echo "Error: Failed to retrieve cluster information. Check cluster identifier and AWS permissions." >&2
        exit 1
    fi
    
    CLUSTER_ID=$(echo "$CLUSTER_INFO" | jq -r '.cluster.id')
    CLUSTER_NAME="$(echo "$CLUSTER_INFO" | jq -r '.cluster.name')"
    SLURM_VERSION=$(echo "$CLUSTER_INFO" | jq -r '.cluster.scheduler.version')
    SLURM_VERSION=${SLURM_VERSION#Slurm_}
    
    # Check if Slurm version is >= 25.05
    # shellcheck disable=SC2072
    if [[ "$SLURM_VERSION" < "25.05" ]]; then
        echo "Error: This script requires Slurm version 25.05 or later. Found version: $SLURM_VERSION" >&2
        exit 1
    fi
    
    ENDPOINTS=$(echo "$CLUSTER_INFO" | jq -r '.cluster.endpoints[] | select(.type == "SLURMCTLD") | (if .privateIpAddress != "" then .privateIpAddress else "[" + .ipv6Address + "]" end) + ":" + .port' | tr '\n' ',' | sed 's/,$//')
    
    # Get BASE64_SLURM_KEY
    BASE64_SLURM_KEY=$(get_auth_key)
    
    if [ -z "$BASE64_SLURM_KEY" ]; then
        echo "Error: base64 Slurm key cannot be empty" >&2
        exit 1
    fi
    
    configure_cluster
    
    # Final configuration summary
    echo "========================================"
    echo "Configuration completed successfully!"
    echo "========================================"
    echo "Cluster Name: $CLUSTER_NAME"
    echo "Cluster ID: $CLUSTER_ID"
    echo "Slurm Version: $SLURM_VERSION"
    echo "Service Name: $SACKD_SERVICE_NAME"
    echo "SACKD Port: $SACKD_PORT"
    echo
    echo "To activate this cluster environment, run:"
    echo "  source ./$ACTIVATE_SCRIPT"
    echo
    echo "To deactivate this cluster environment, run:"
    echo "  deactivate-pcs-${CLUSTER_NAME}"
    echo
    echo "To check service status:"
    echo "  systemctl status $SACKD_SERVICE_NAME"
    echo
    echo "To view service logs:"
    echo "  journalctl -u $SACKD_SERVICE_NAME -f"
}

# Exit if being sourced for testing
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && return

# Execute main function
main "$@"
```

# AWS PCS 다중 클러스터 로그인 노드 구성 스크립트 사용
<a name="multi-cluster-login-script-usage"></a>

## 스크립트 실행
<a name="running-script"></a>

**구성 스크립트를 실행하려면**

1. [스크립트의 내용을](multi-cluster-login-script-code.md#multi-cluster-login-script-code-content) 다음과 같은 파일에 저장합니다.

   ```
   pcs-multi-cluster-login-configure.sh
   ```

1. 실행 가능하도록 설정합니다.

   ```
   chmod +x pcs-multi-cluster-login-configure.sh
   ```

1. 스크립트를 실행합니다.

   ```
   ./pcs-multi-cluster-login-configure.sh --cluster-identifier cluster-name
   ```

## 클러스터 상호 작용 환경
<a name="activation-script-usage"></a>

구성에 성공하면 스크립트는 현재 디렉터리에 클러스터별 활성화 스크립트를 생성합니다. 스크립트의 이름은 입니다`activate-pcs-cluster-name`. 활성화 스크립트는 대상 클러스터와 상호 작용하는 데 필요한 환경 변수 및 경로를 구성합니다.

**클러스터 환경을 활성화하려면**
+ `source` 명령을 사용하여 활성화 스크립트 실행

  ```
  source ./activate-pcs-cluster-name
  ```  
**Example**  

  ```
  # Activate cluster environment for cluster 'my-cluster'
  source ./activate-pcs-my-cluster
  
  # Now you can use Slurm commands
  sinfo
  squeue
  sbatch my-job.sh
  ```

**활성화 스크립트가 수행하는 작업**
+ 클러스터의 구성을 가리키도록 `SLURM_CONF` 환경 변수를 설정합니다.
+ 클러스터의 Slurm 바이너리`PATH`를 포함하도록를 업데이트합니다.
+ 기타 필요한 Slurm 환경 변수(`MANPATH`, `LD_LIBRARY_PATH`)를 구성합니다.
+  AWS PCS 클러스터 식별 변수를 설정합니다.
+ 대상 AWS PCS 클러스터와의 원활한 상호 작용을 활성화합니다.

**클러스터 환경을 비활성화하려면**
+ 비활성화 명령을 실행합니다.

  ```
  deactivate-pcs-cluster-name
  ```  
**Example**  

  ```
  # After activating a cluster
  source ./activate-pcs-my-cluster
  
  # Work with the cluster
  sinfo
  
  # Deactivate when done
  deactivate-pcs-my-cluster
  ```

**비활성화 명령이 수행하는 작업**
+ 원래 `PATH` 환경 변수를 복원합니다.
+ 클러스터별 Slurm 환경 변수를 설정 해제합니다.
+ 쉘 환경을 사전 활성화 상태로 되돌립니다.

**참고**  
활성화는 세션별로 다르며 클러스터와 상호 작용하려는 쉘 세션에서 소싱되어야 합니다.