[AWS] ECS 筆記

Jan. 26, 2023, 4:43 p.m.
雲端運算

簡介

Amazon的ECS是一項完全托管的Conatiner服務,可以做到對Container的部署、管理、擴展。使得開發人員能放更多重心在應用程式的開發,而非環境的維護。

還有一個類似的服務是AWS的[[EKS]],他是一個完全托管的Kubernetes服務。(Kubernetes被廣泛使用於容器化應用程序的部署和管理)

如果本身已經有在使用Kubernets管理Container,同時希望對系統有更多的自訂性的話,可以考慮使用EKS。而ECS的學習難度曲線比Kubernetes低,適合期望能整合其他AWS資源的專案。

Launch Type

ECS提供了幾種不同的底層啟動方式(Launch Type),分別是EC2、Fargate、On-premises。

EC2 Launch Type

用EC2啟動的話,是將Conatiner跑在EC2的實體上。需要先備好一些EC2實體,然後在這些實體上運行Container,並且需要自行管理這些EC2。這些EC2還要另外執行一個稱為ECS Agent的程式,讓EC2得以根ECS的服務溝通。這種方式提供了更大的靈活性和控制,適合有高度自定義需求的情境。

Fargate Launch Type

用Fargate啟動的Container則是一種類似Serverless的方式。只需要定義好Task後告訴ECS要運行多少Container在Cluster裡面即可,而不用擔心EC2實體的管理問題。Fargate會自動處理所有低層細節,我們只需關注在應用程式的開發即可。如果要使用Load Balancer,則所使用的Target Group必須是IP Type!

On-premises

從外部的Instance(Server或VM)做啟動的動作。

系統設置

Tasks的設置

首先來定義Task。(這邊假設Image已經丟到ECR上面)
Task是定義了Docker Image怎麼跑的一種Template樣板。有點Docker Compose的味道在裡面。除了在這個地方指定Image的名稱,以及他的URI要去哪裡下載外,一些重要的設定像是:
- Container裡頭的應用程式的Port Mapping
- 如果有使用S3上面的.env檔案的話,需要指定S3的路徑
- 是否需要Mount外部的Volume

Task Settings

Data Volume

實務上Volumes會使用EFS的服務。把EFS載到每個ECS Task上面,就能讓跑在任何AZ上面的Task共享相同的資料。另外如果底層是跑Fargate,volume是掛載EFS的話,應用程式就等同於是個無伺服器的應用。

Clusters設置

再來需要建立的是ECS的叢集(Clusters)。這裡主要是希望你能確認好底層的啟動型態是Fargate還是EC2,同時Instances的Auto Scaling Group設定也會在這個階段做確認。(注意是ASG不是Load Balancer)

Cluster_Settings

Services

再來需要建立Services,這個地方定義了要怎麼跑一開始要設定的Task們。

Service_settings

可選擇的定義負載平衡器

我們也可以在定義Services的時候,同時定義要不要使用負載平衡器(ALB或NLB)
一個需要注意的地方是,如果Container今天部署的速度比較慢的話,Load Balancer這邊設定的Health Check有可能會檢查失敗,導致服務一直收掉啟動不了。(系統以為Container們壞了)。
另外一個蠻蠢的,但如果沒注意就會發生錯誤的點是,Health Check URI最後的/,也要根據後端伺服器做對應的設定。舉例來說:
- /health-check
- /health-check/
是完全不一樣的東西,寫錯會導致過不了。

IAM Roles for ECS

我們需要幫Task們給定兩個特殊的IAM Role,分別是Task Role以及Task Execution Role

Task Role

這個Role是要給執行Task的實體們使用的,位於這些Instance底下的Container裡面的應用程式如果會去呼叫其他AWS資源的話,就要給他們能夠assume其他Role的權限。

可以參考Role裡面的Trust relationships設定:

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
  • 這個設定允許EC2去assume特定的Role,讓EC2有權限做跟該Role一樣的事情

Task Execution Role

這個Role是要給ECS ContainerFarget Agent使用的。他賦予的權限主要用在管理Task的生命週期和執行環境,而不是用在Task裡面的Container身上。
比方說,啟動在Farget上面的Task需要從ECR把Image拉下來,從SSM拿出敏感的資料,把Container的Log送到CloudWatch…等等。

如果有使用s3上面的.env檔案

在定義Task的時後,有提到可能會使用到s3上面的.env檔案。這個時候,就需要放兩個權限到ECSTaskExecutionRole上面

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{ENV_FILE_PATH_S3}}"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:GetBucketLocation",
            "Resource": "arn:aws:s3:::{ENV_BUCKET_S3}"
        }
    ]
}
  • 注意Bucket的Resource不要後面多了一條/,不然又會變成Objects
  • 假設今天S3上的Bucket名稱換掉了,那除了ExecutionRole內的Bucket名稱要換掉之外,Task定義的S3 Bucket名稱也要記得換掉

如果服務部署在Private Subnet

如果應用程式的架構是讓Task跑在Private Subnet裡面的話,會訪問不了AWS Global等級的服務,例如S3, ECR…。錯誤範例如下:

ResourceInitializationError: 
unable to pull secrets or registry auth: execution resource retrieval failed: 
unable to retrieve ecr registry auth: service call has been retried 3 time(s): 
RequestError: send request failed caused by: 
Post "https://api.ecr.ap-northeast-1.amazonaws.com/": dial tcp 52.119.220.175:443: i/o timeout

但我們可以透過設定下面的VPC Endpoint讓我們的subnet能夠訪問到這些服務。
- com.amazonaws.region.ecr.dkr
- com.amazonaws.region.ecr.api
- S3 Gateway Endpoints
- com.amazonaws.region.logs
詳細的設置可參考AWS官方的文件

Tags:

AWS