01문제 정의 - 흩어지는 ECS 운영
이 절에서는 ecs9s가 어떤 불편을 풀려는 도구인지 다룹니다. 출발점은 ECS를 운영할 때 화면을 계속 오가야 하는 일상입니다.
서비스 배포 상태는 ECS 콘솔에서 봅니다. 컨테이너 로그는 CloudWatch Logs에, 이미지 태그는 ECR에, 알람은 CloudWatch 알람 페이지에 있습니다.
배포가 이상하면 aws ecs describe-services를 칩니다. 컨테이너에 들어가려면 aws ecs execute-command의 긴 인자를 다시 조립합니다. 하나의 장애를 진단하는 동안 브라우저 탭과 터미널 사이를 여러 번 오가게 됩니다.
Kubernetes 진영은 이 문제를 k9s로 풀었습니다. k9s는 리소스 목록, 드릴다운, 로그, 셸 접속을 키보드만으로 처리하는 터미널 UI이고, EKS 운영자의 기본 도구가 되었습니다.
ecs9s는 이 경험을 ECS로 가져오는 프로젝트입니다. README는 k9s(Kubernetes), e1s(ECS), tui-aws(AWS)에서 영감을 받았다고 밝히고 있습니다.
기존 도구와의 차별점은 두 가지입니다. 첫째는 조회에 그치지 않는 ECS 특화 운영 액션입니다. 강제 재배포(설정 변경 없이 태스크를 새로 띄우는 배포), ECS Exec(실행 중인 컨테이너에 셸로 접속하는 ECS 기능) 활성화, 태스크 중지, 태스크 정의 등록 해제가 각 페이지의 단축키에 연결되어 있습니다.
다만 모든 액션이 연결된 것은 아닙니다. desired count(서비스가 유지할 태스크 개수) 조정, 이전 태스크 정의로의 롤백, SSM 포트포워딩(원격 컨테이너의 포트를 내 로컬 포트로 이어 주는 접속)은 internal/action/에 래퍼 모듈로 준비되어 있으나 아직 단축키에는 배선되지 않았습니다.
둘째는 ECS 주변 서비스의 통합 뷰입니다. ECR 이미지, ELB 타겟그룹, IAM 역할, Secrets Manager, 비용 추정까지 21개 뷰가 하나의 탭 구조 안에 들어 있습니다. 덕분에 진단에 필요한 문맥 전환이 터미널 안에서 끝납니다.
README는 21개 뷰, Go 1.24+, 3개 테마를 서술합니다. 이 문서는 해당 수치를 코드에서 다시 세어 확인했습니다.
뷰 수는 internal/ui/messages.go의 PageType 상수 21개, internal/ui/pages/의 페이지 파일 21개와 일치했습니다. Go 버전은 go.mod의 go 1.24.2 선언과 일치했습니다. README와 코드가 어긋나는 수치는 발견되지 않았습니다.
02동작 원리 - TUI 아키텍처
이 절에서는 ecs9s가 안에서 어떻게 움직이는지 봅니다. 프로그램이 시작되는 과정, 코드가 나뉘는 계층, 화면 사이를 오가는 방식 순서로 살펴봅니다.
ecs9s는 Go 단일 바이너리입니다. TUI 프레임워크는 Bubbletea(Elm 아키텍처 기반 Go TUI 라이브러리)이고, 스타일은 Lipgloss, AWS 연동은 AWS SDK for Go v2를 씁니다.
시작 시 받는 플래그는 몇 개일까요? main.go가 파싱하는 것은 --profile, --region, --theme, --version 네 개입니다. 이어서 ~/.ecs9s/config.yaml을 읽고 AWS 세션을 만든 뒤 tea.NewProgram을 시작합니다.
같은 값이 양쪽에 있으면 어느 쪽이 이길까요? CLI 플래그가 설정 파일 값보다 우선합니다.
2.1 계층 구조
코드는 internal/ 아래에서 표현 계층, 데이터 계층, 액션 계층으로 나뉩니다. 표현 계층의 루트는 internal/app/app.go의 App 모델입니다. App 모델은 21개 페이지와 8개 재사용 컴포넌트(table, tabs, commandbar, statusbar, help, confirm, logviewer, sparkline)를 합성하고 메시지를 라우팅합니다.
아래 표에서는 각 계층이 어떤 패키지로 이루어지고 무엇을 담는지 보면 됩니다.
| 계층 | 패키지 | 내용 |
|---|---|---|
| 표현 | app, ui/pages, ui/components, ui/styles, theme | 루트 모델과 라우팅, 21개 페이지 모델, 8개 위젯, Lipgloss 스타일, 3개 테마 프리셋(dark, light, blue) |
| 데이터 | aws | SDK v2 클라이언트 래퍼 10개 파일 - ecs, cloudwatch, ecr, elb, ec2, iam, autoscaling, ssm, secrets, session |
| 액션 | action | 변경 작업 래퍼 6개 모듈 - exec, portforward, scale, deploy, rollback, taskdef (현재 호출되는 것은 exec뿐) |
| 설정 | config | ~/.ecs9s/config.yaml 로더 (profile, region, theme) |
2.2 뷰와 내비게이션 모델
모든 뷰의 정체성은 internal/ui/messages.go의 PageType 열거형 하나로 정의됩니다. 각 PageType은 탭 이름(String())과 명령 모드 문자열(Command())을 함께 갖습니다. 그래서 뷰를 하나 추가하면 탭과 : 명령이 같은 자리에서 함께 늘어납니다.
드릴다운 위치는 NavContext 구조체에 담겨 페이지 사이를 이동합니다.
const (
PageCluster PageType = iota
PageService
PageTask
PageContainer
PageTaskDef
// ... Logs, ECR, ELB, ASG, VPC, IAM, Metrics, EC2,
// ... Events, Stopped, ResMap, Cost, SSM, Secrets, Deploy,
PageAlarms // 총 21개
)
// NavContext holds the drill-down context as the user navigates deeper.
type NavContext struct {
ClusterARN string
ClusterName string
ServiceName string
ServiceARN string
TaskARN string
TaskID string
}
내비게이션은 두 방식이 공존하는 하이브리드입니다. Tab, [, ]로 탭을 순회할 수도 있고, k9s처럼 :service, :ecr, :cost를 입력해 바로 이동하는 명령 모드도 있습니다.
탭을 전환해도 드릴다운 컨텍스트는 유지됩니다. 그래서 Service에서 특정 서비스로 들어간 뒤 Events나 Metrics 탭으로 옮기면 같은 서비스 범위의 데이터가 나옵니다.
2.3 비동기 AWS API 연동
AWS 호출은 UI 스레드를 막지 않습니다. 각 페이지의 Update()는 API 호출을 tea.Cmd 클로저로 반환합니다. Bubbletea 런타임이 이를 고루틴(Go의 경량 스레드)에서 실행한 뒤, 결과를 clusterLoadedMsg 같은 타입 메시지로 돌려줍니다.
에러는 ui.ErrorMsg로 승격되어 상태 바에 표시됩니다. 데이터 흐름은 한 방향입니다: 사용자 입력 → App.Update() → Page.Update() → tea.Cmd(AWS API) → 로드 완료 메시지 → Page.View().
저장소 컨벤션은 테이블에서 선택 행을 읽을 때 Cursor() 인덱스가 아니라 SelectedRow()의 행 데이터를 쓰도록 강제합니다. 커서 인덱스를 원본 배열 인덱스로 쓰면, / 필터나 정렬이 적용된 순간 다른 리소스에 액션이 날아가기 때문입니다. 파괴적 액션이 있는 도구에서는 중요한 설계 결정입니다.
03핵심 메커니즘 딥다이브
이 절에서는 ecs9s의 핵심 동작 세 가지를 코드로 확인합니다. 화면 사이를 오가는 방법, 컨테이너 셸을 열기 전의 검증, 그리고 운영 액션이 실제로 어디까지 연결되어 있는지입니다.
3.1 드릴다운과 브레드크럼
탐색의 기본 축은 Cluster → Service → Task → Container 계층입니다. Enter를 누르면 선택 행의 ARN과 이름이 NavContext에 누적되면서 한 단계 내려갑니다. Esc나 Backspace는 navStack에 쌓인 이전 상태를 복원해 되돌아갑니다.
NavContext를 바꾸는 경로는 드릴다운 하나뿐입니다. 덕분에 "지금 어느 클러스터의 어느 서비스를 보고 있는가"라는 브레드크럼(현재 위치를 경로처럼 보여주는 표시)이 항상 상태 바에 일관되게 남습니다.
페이지는 두 부류로 나뉩니다. ECR, ELB, VPC, IAM 같은 글로벌 페이지는 컨텍스트 없이 리전 전체를 보여주고, 상태 바의 클러스터 표시를 숨깁니다.
Service, Task, Events, Metrics 같은 컨텍스트 페이지는 드릴다운 범위로 데이터를 좁힙니다. 명령 모드로 어느 페이지에 점프해도 이 구분이 유지됩니다.
3.2 ECS Exec 셸의 3단계 사전 검증
ECS Exec는 실패 지점이 많은 기능입니다. 로컬 플러그인 누락, 서비스의 enableExecuteCommand 미설정, 에이전트 미기동 중 하나만 걸려도 셸이 열리지 않습니다. 그런데 AWS CLI의 에러 메시지만으로는 원인을 찾기 어렵습니다.
ecs9s는 검증을 몇 단계 거칠까요? Container 뷰에서 x를 누르는 순간, 셸 실행 전에 3단계 검증을 차례로 통과시킵니다.
- 로컬 도구 검증입니다. exec.LookPath로 AWS CLI와 session-manager-plugin이 PATH에 있는지 확인합니다. 없으면 설치 문서 URL을 포함한 에러를 상태 바에 띄웁니다.
- 태스크 상태 검증입니다. DescribeTasks로 태스크의 enableExecuteCommand 플래그와 ExecuteCommandAgent 관리 에이전트가 RUNNING인지 확인합니다. 실패 사유는 원인별로 다른 문장으로 안내됩니다.
- TUI 중단과 복원입니다. 검증을 통과하면 tea.ExecProcess가 터미널 제어권을 aws ecs execute-command --interactive 서브프로세스에 넘깁니다. 셸이 종료되면 TUI 상태를 그대로 복원합니다.
for _, ctr := range task.Containers {
for _, ma := range ctr.ManagedAgents {
if ma.Name == ecstypes.ManagedAgentNameExecuteCommandAgent {
result.InitStatus = aws.ToString(ma.LastStatus)
result.AgentRunning = result.InitStatus == "RUNNING"
}
}
}
if !result.TaskExecEnable {
result.Details = "enableExecuteCommand is not set on this task. ..."
} else if !result.AgentRunning {
result.Details = "ExecuteCommand agent status: ... may need to be restarted ..."
}
Service 뷰에서 e로 ECS Exec를 활성화하면 서비스에 enableExecuteCommand가 설정되고, 강제 재배포가 함께 트리거됩니다. 기존 태스크에는 에이전트가 없습니다. 그래서 ExecuteCommandAgent를 실은 새 태스크가 뜬 뒤에야 접속이 가능합니다.
또한 Task Role에 ssmmessages:CreateControlChannel 등 4개 채널 권한이 있어야 합니다. 이 대기와 권한이 ECS Exec에서 가장 흔한 혼선 지점입니다.
3.3 운영 액션 - 배포, 스케일, 롤백, 포트포워딩
변경 작업 래퍼는 internal/action/에 6개 모듈(exec, portforward, scale, deploy, rollback, taskdef)로 준비되어 있습니다. 그런데 현재 배선된 액션은 이 모듈 대신 internal/aws의 클라이언트 메서드를 페이지가 직접 호출합니다. action 모듈 중 실제로 호출되는 것은 ECS Exec 경로의 exec.go뿐입니다.
확인 다이얼로그는 어떨까요? confirm 컴포넌트는 구현되어 있으나 현재 어떤 액션에도 연결되어 있지 않습니다. 그래서 강제 재배포, 태스크 중지, 태스크 정의 등록 해제는 확인 다이얼로그 없이 즉시 실행되고, 사전 검증이 있는 것은 ECS Exec(x) 경로뿐입니다.
아래 표에서는 어떤 페이지의 어떤 키가 실제로 어떤 코드를 호출하는지 보면 됩니다.
| 페이지 | 키 | 동작 | 실제 호출 경로 |
|---|---|---|---|
| Service | f | 강제 재배포 | internal/aws/ecs.go의 ForceNewDeployment (UpdateService) |
| Service | e | ECS Exec 활성화 | internal/aws/ecs.go의 EnableExecOnService (enableExecuteCommand 설정 + 재배포) |
| Task | Ctrl+d | 태스크 중지 | internal/aws/ecs.go의 StopTask |
| Container | x | ECS Exec 셸 | action/exec.go + CheckExecEnabled 검증 + tea.ExecProcess |
| TaskDef | Ctrl+d | 태스크 정의 등록 해제 | internal/aws/ecs.go의 DeregisterTaskDefinition |
Service 뷰의 S(desired count 조정)와 b(이전 태스크 정의로 롤백), Container 뷰의 Ctrl+f(포트포워딩)는 도움말 오버레이에는 표기되어 있으나 키 핸들러가 배선되지 않았습니다.
대응하는 action/scale.go, action/rollback.go, action/portforward.go 모듈은 존재하지만 어디에서도 호출되지 않습니다. 따라서 현재 버전에서 이 세 키는 동작하지 않습니다.
미배선 상태이긴 하지만 롤백 래퍼는 추측하지 않도록 설계되어 있습니다. action/rollback.go의 RollbackService는 먼저 DescribeServices로 PRIMARY 배포의 태스크 정의를 특정합니다. 그다음 배포 목록에서 그와 다른 태스크 정의를 가진 최근 배포를 롤백 대상으로 고릅니다.
그런 배포가 없을 때만 리비전 번호를 하나 내린 후보를 만듭니다. 이때도 DescribeTaskDefinition으로 그 리비전이 실제로 존재하는지 확인한 뒤에야 UpdateService를 호출합니다. 검증에 실패하면 변경 없이 에러로 끝납니다.
포트포워딩 래퍼는 SSM의 AWS-StartPortForwardingSession 문서를 사용합니다. 타겟 식별자는 ecs:{cluster-name}_{task-id}_{runtime-id} 형식입니다. 여기에는 ARN이 아니라 짧은 이름이 들어가야 해서, 코드가 ARN에서 이름과 ID를 추출하는 헬퍼를 따로 둡니다.
이 형식을 손으로 조립하다 틀리는 것이 CLI 사용 시 흔한 실수이므로 래퍼의 가치는 분명합니다. 다만 이 래퍼를 호출하는 키 핸들러와 포트 입력 UI가 아직 배선되지 않아, 현재 버전에서는 사용할 수 없습니다.
현재 상태: confirm 컴포넌트는 구현되어 있으나 어떤 액션에도 연결되어 있지 않아, 강제 재배포/태스크 중지/태스크 정의 등록 해제는 확인 없이 즉시 실행됩니다. 사전 검증을 거치는 것은 ECS Exec(x) 경로뿐입니다.
0421개 리소스 뷰 개관
이 절에서는 21개 뷰를 한눈에 정리합니다. 어떤 화면이 있고, 명령 모드에서 무엇을 입력해 이동하는지 봅니다.
뷰는 어떻게 나뉠까요? ECS 핵심 5개, 운영 서비스 8개, 관리 8개입니다. 아래 커맨드 문자열은 PageType.Command() 배열에서 그대로 옮긴 값이고, 명령 모드에서 : 뒤에 입력하는 단어와 정확히 일치합니다.
아래 표에서는 각 뷰가 보여주는 내용과 이동 커맨드를 보면 됩니다.
| 분류 | 뷰 | 커맨드 | 보여주는 것 |
|---|---|---|---|
| ECS 핵심 | Cluster | :cluster | 클러스터 목록, 드릴다운 시작점 |
| Service | :service | 서비스와 배포 상태, 강제 재배포와 ECS Exec 활성화의 진입점 | |
| Task | :task | 실행 중 태스크, 태스크 중지 | |
| Container | :container | 태스크 내 컨테이너, ECS Exec 셸 진입점 | |
| TaskDef | :taskdef | 태스크 정의 리비전, 등록 해제 | |
| 운영 서비스 | Logs | :log | CloudWatch Logs 로그 뷰어 |
| ECR | :ecr | 레포지토리와 이미지 | |
| ELB | :elb | 로드밸런서, 타겟그룹 | |
| ASG | :asg | Auto Scaling 타겟과 정책 | |
| VPC | :vpc | VPC, 서브넷, 보안 그룹 | |
| IAM | :iam | 역할과 정책 | |
| Metrics | :metrics | CPU / Memory 스파크라인 | |
| EC2 | :ec2 | EC2 인스턴스 | |
| 관리 | Events | :events | 서비스 이벤트 |
| Stopped | :stopped | 중지된 태스크와 중지 사유(StoppedReason) | |
| ResMap | :resmap | 서비스 중심 리소스 맵(배포, 타겟그룹, 태스크 연결) | |
| Cost | :cost | 태스크 정의 실측 값 기반 Fargate 비용 추정 | |
| SSM | :ssm | Parameter Store (SecureString은 복호화 없이 마스킹) | |
| Secrets | :secrets | Secrets Manager 목록 | |
| Deploy | :deploy | 배포 이력 | |
| Alarms | :alarms | CloudWatch 알람 |
Cost 뷰는 이름으로 추측하지 않습니다. DescribeTaskDefinition이 반환한 실제 vCPU와 메모리 값으로 시간당/일간/월간 비용을 계산합니다.
SSM 뷰는 WithDecryption: false로 호출해 SecureString(암호화되어 저장되는 비밀 값 형식) 값이 메모리에 올라오지 않게 합니다. 화면에는 ****로 마스킹합니다. 조회 도구가 비밀 값을 다루는 방식으로는 보수적인 선택입니다.
05실제 운영 흐름
이 절에서는 설치부터 실제 장애 진단까지의 흐름을 따라갑니다. 명령 몇 줄로 시작할 수 있는지부터 봅니다.
5.1 설치와 실행
배포 형태는 go build가 만드는 단일 바이너리입니다. 저장소를 클론해 빌드하고 PATH에 옮기면 끝입니다.
git clone https://github.com/whchoi98/ecs9s.git
cd ecs9s
go build -o ecs9s . # Go 1.24.2 이상
sudo mv ecs9s /usr/local/bin/
ecs9s --profile myprofile --region ap-northeast-2 --theme dark
반복 사용하는 값은 ~/.ecs9s/config.yaml에 저장합니다. 같은 키를 CLI 플래그로 주면 플래그가 이깁니다.
aws:
profile: default
region: ap-northeast-2
theme: dark # dark | light | blue
5.2 배포 장애 진단 시나리오
"배포 후 5xx가 늘었다"는 상황을 가정합니다. 먼저 :service로 이동해 running/desired 불일치를 확인합니다. Enter로 태스크에 내려가 :stopped에서 중지 사유를 읽습니다.
다음은 로그입니다. :log로 컨테이너 로그를 보고, 더 파야 하면 Container까지 내려가 x로 셸을 엽니다.
원인이 새 이미지라면 롤백이 필요합니다. 그런데 도움말에 표기된 b 키는 아직 배선되지 않았습니다. 그래서 현재 버전에서는 aws ecs update-service로 이전 태스크 정의를 지정해 되돌려야 합니다.
롤백을 제외하면 이 루프에서 브라우저를 열 일이 없습니다. 아래 표에서는 모든 뷰에서 공통으로 쓰는 이동 키를 보면 됩니다.
| 키 | 동작 |
|---|---|
| Tab / [ / ] | 탭 전환 (드릴다운 컨텍스트 유지) |
| : + 커맨드 | 명령 모드로 뷰 직접 이동 |
| Enter / Esc | 드릴다운 / 뒤로 가기 |
| /, s, R | 필터, 정렬, 새로고침 |
| ?, q | 도움말 오버레이, 종료 |
06한계
이 절에서는 코드에서 확인되는 한계를 정리합니다. 도입 전에 알아 두면 좋은 제약들입니다.
프로젝트는 README 배지 기준 v0.1.0(git 태그/릴리스 미발행, 바이너리 버전 문자열은 dev)입니다. CHANGELOG도 아직 [Unreleased] 상태입니다. 따라서 아래 항목은 현재 시점의 스냅샷입니다.
- 미배선 액션 - 도움말에 표기된 S(스케일), b(롤백), Ctrl+f(포트포워딩)는 키 핸들러가 배선되지 않아 동작하지 않습니다. action/의 scale, rollback, portforward 모듈은 존재하지만 호출되지 않습니다. confirm 컴포넌트 역시 어떤 액션에도 연결되어 있지 않습니다. 그래서 강제 재배포, 태스크 중지, 태스크 정의 등록 해제가 확인 다이얼로그 없이 즉시 실행됩니다.
- 외부 의존 - ECS Exec 셸은 SDK로 직접 구현되지 않고 aws CLI 서브프로세스를 실행합니다. 미배선 상태인 포트포워딩 래퍼도 같은 방식입니다. 로컬에 AWS CLI와 session-manager-plugin이 없으면 동작하지 않으며, 사전 검증이 이를 에러로 알려줍니다.
- 세션 고정 - 프로파일과 리전은 main.go에서 세션을 만들 때 한 번 결정됩니다. 명령 모드의 21개 커맨드는 모두 뷰 전환용이고, 실행 중 프로파일이나 리전을 바꾸는 커맨드는 없습니다. 멀티 리전 운영이라면 프로세스를 리전별로 띄워야 합니다.
- 비용 추정의 범위 - Cost 뷰의 단가는 어떤 값일까요? us-east-1 온디맨드 Fargate 값 (vCPU $0.04048/시간, 메모리 $0.004445/GB-시간)이 코드에 고정되어 있습니다. 다른 리전이나 Savings Plans가 적용된 환경에서는 추정치가 실제 청구액과 다릅니다.
- 롤백 후보의 한계 - 미배선 상태인 롤백 래퍼(action/rollback.go) 기준의 제약입니다. 다른 태스크 정의를 가진 배포가 없으면 리비전 번호를 하나 내린 후보를 시도합니다. 그 리비전이 이미 등록 해제되었다면 존재 검증에 걸려 롤백이 에러로 끝납니다. 안전하지만, 이 경우 수동으로 대상 리비전을 골라야 합니다.
- 설치 경로 - 별도의 릴리스 바이너리 배포가 없습니다. 소스 빌드가 유일한 설치 방법이므로 Go 툴체인이 필요합니다.
07결론
이 절에서는 분석을 정리하고, 이 도구를 지금 써 볼 만한지 판단합니다.
ecs9s는 k9s가 Kubernetes 운영자에게 준 "터미널 안에서 끝나는 루프"를 ECS에 맞게 다시 만든 도구입니다. 같은 계열의 e1s와 비교했을 때 이 프로젝트가 힘을 준 곳은 ECS의 실제 운영 동선입니다.
강제 재배포, ECS Exec 활성화, 태스크 중지, 태스크 정의 등록 해제가 단축키로 연결되어 있습니다. 스케일, 롤백, 포트포워딩은 래퍼 모듈만 준비된 미배선 상태입니다. 그리고 ECR부터 비용 추정까지 주변 서비스를 포함한 21개 뷰가 하나의 내비게이션 모델 안에 들어 있습니다.
구현 관점에서 눈여겨볼 부분은 실패를 앞당기는 설계입니다. ECS Exec의 3단계 사전 검증, 미배선 롤백 래퍼의 대상 존재 확인, SelectedRow 기반 행 선택, SecureString 비복호화가 그 예입니다. 이 결정들은 "조회는 편하게, 변경은 보수적으로"라는 방향을 지향합니다.
다만 confirm 다이얼로그가 아직 어떤 액션에도 연결되어 있지 않습니다. 그래서 변경 액션의 안전장치는 현재 ECS Exec 사전 검증에 한정됩니다. ECS를 콘솔과 CLI로 오가며 운영하고 있다면, 단일 바이너리 하나로 시도해 볼 비용이 충분히 낮은 도구입니다.
한 문장으로 요약하면, ecs9s는 ECS의 조회와 핵심 조치를 터미널 한 화면에 모은 도구이고, 일부 액션(스케일, 롤백, 포트포워딩)과 확인 다이얼로그가 아직 연결되지 않은 v0.1.0 초기 단계입니다.
--참고 자료
핵심 출처
- ecs9s - GitHub 저장소 - WooHyung Choi, 소스와 README(배지 기준 v0.1.0), docs/architecture.md (2026-08-09 접속 확인) https://github.com/whchoi98/ecs9s
공식 문서
- Monitor containers with ECS Exec - Amazon ECS Developer Guide (2026-08-09 접속 확인) https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html
관련 프로젝트
- k9s - Kubernetes CLI To Manage Your Clusters In Style (2026-08-09 접속 확인) https://github.com/derailed/k9s
- e1s - Easily Manage AWS ECS Resources in Terminal (2026-08-09 접속 확인) https://github.com/keidarcy/e1s