Slide 1

Slide 1 text

ecspresso exec 2021.04.23 aws ecs execute-command --task ${value} ⾯⽩法⼈カヤック 藤原俊⼀郎 @fujiwara

Slide 2

Slide 2 text

@fujiwara github.com/kayac/ecspresso Amazon ECS デプロイツール github.com/fujiwara/lambroll AWS Lambda デプロイツール

Slide 3

Slide 3 text

ecspresso のご紹介 github.com/kayac/ecspresso Amazon ECS デプロイツール Simple / Minimal (最近は機能が増えてきた…) ECS サービスとタスク定義の管理に特化 Terraform / CloudFormation と連携可能 ecspresso handbook zenn.dev/fujiwara/books/ecspresso-handbook

Slide 4

Slide 4 text

ecspresso の設計思想 サービスとタスクだけを扱う アプリケーションはデプロイのラ イフサイクルが他のリソースとは 違う (⾼頻度) ライフサイクルが違うものをひと つのツールで全て管理すると、お 互いに事故りがち ECSのデプロイに特化する

Slide 5

Slide 5 text

ecspresso のコマンド (v1.5) 設定⽣成 → init appspec サービス関係 → create delete status デプロイ → deploy scale refresh rollback wait タスク起動、タスク定義登録 → run register 検証 → diff verify render タスクの状態を⾒る → tasks (New!) execute-command!!! → exec (New!)

Slide 6

Slide 6 text

ecspresso tasks ecspresso で管理しているサービス/タスク定義によって実⾏されているタスクを表⽰ $ ecspresso --config config.yaml tasks | ID | TASKDEFINITION | INSTANCE | LASTSTATUS | DESIREDSTATUS | CREATEDAT | GROUP | TYPE | +----------------------------------+--------------------+----------+------------+---------------+---------------------------+-----------------------+---------+ | 31aba18f436e415f819670e8936fb09f | ecspresso-test:276 | | RUNNING | RUNNING | 2021-04-22T22:46:51+09:00 | service:nginx-local | FARGATE | | 581833da4ade4ad9aafa0bbadcf9b636 | ecspresso-test:276 | | RUNNING | RUNNING | 2021-04-22T22:46:51+09:00 | service:nginx-local | FARGATE | | f218b20ec86d4be2bf77a28c76dfe306 | ecspresso-test:277 | | PENDING | RUNNING | 2021-04-22T22:49:36+09:00 | family:ecspresso-test | FARGATE | | 8a4124cac40e431095a46d36210189be | ecspresso-test:276 | | STOPPED | STOPPED | 2021-04-20T23:05:29+09:00 | service:nginx-local | FARGATE | | d0a37d791e924d5d8bbfdaeeb58ae882 | ecspresso-test:276 | | STOPPED | STOPPED | 2021-04-20T22:57:35+09:00 | service:nginx-local | FARGATE | --find 特定のタスクを選択後、詳細をJSONで表⽰ --stop 特定のタスクを選択後、停⽌

Slide 7

Slide 7 text

ecspresso exec (本題) Demo asciinema.org/a/405167 # config.yaml filter_command: peco 対象のタスク、タスク内のコンテナの絞り込みに外部コマンドを指定可能 fzf github.com/junegunn/fzf peco github.com/peco/peco percol github.com/mooz/percol など、複数⾏から1⾏を選択できるコマンドならなんでもOK (指定がなければID/コンテナ名を⼊⼒するpromptが出ます)

Slide 8

Slide 8 text

ecspresso exec = aws ecs exeucte-command aws ecs execute-command と同様、引数での指定も可能 aws ecs execute-command \ --cluster default --task ${task_id} \ --container ${container_name} \ --command sh --interactive ⇅ ecspresso exec --config config.yaml \ --id ${task_id} \ --container ${container_name} \ --command sh

Slide 9

Slide 9 text

ecspresso exec で何を実⾏するかはあなた次第! shell が取れたら何でもできる 完

Slide 10

Slide 10 text

ecspresso exec で何を実⾏するかはあなた次第! shell が取れたら何でもできる ………では物⾜りないのでもうちょっと

Slide 11

Slide 11 text

実装の話をします aws ecs execute-command colipot svc exec ecspresso exec いずれも session-manager-plugin (コマンド) が必要 session-manager-plugin is なに?

Slide 12

Slide 12 text

session-manager-plugin インストール⽅法はすぐ⾒つかるんですが docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager- working-with-install-plugin.html 使い⽅のドキュメントが⾒つからない(あったら教えてください) 単体で実⾏してみる $ session-manager-plugin The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. つれない

Slide 13

Slide 13 text

session-manager-plugin help とかないかな $ session-manager-plugin help Unknown operation help. Use session-manager-plugin --version to check the version. $ session-manager-plugin --help Unknown operation --help. Use session-manager-plugin --version to check the version. $ session-manager-plugin --version 1.2.54.0 とりつく島がない

Slide 14

Slide 14 text

session-manager-plugin は OSS ではない 呼び出しかたのドキュメントも⾒つからない でもこれを使わないと execute-command は実装できない(はず) 使っている側の OSS (aws-cli, copilot-cli) を⾒ればいいじゃない

Slide 15

Slide 15 text

aws-cli (v2) の場合 awscli/customizations/ecs/executecommand.py にあります class ExecuteCommandCaller(CLIOperationCaller): def invoke(self, service_name, operation_name, parameters, parsed_globals): try: client = # ... response = client.execute_command(**parameters) # ... with ignore_user_entered_signals(): check_call(["session-manager-plugin", json.dumps(response['session']), region_name, "StartSession", # ... ) (要約) ExecuteCommand APIのレスポンスのsessionをJSONにしたもの、リージョ ン、"StartSession"を引数にして session-manager-plugin を呼ぶ。ユーザ割り込みシグ ナル(Ctrl-Cとか)は無視

Slide 16

Slide 16 text

copilot-cli の場合 internal/pkg/exec/ssm_plugin.go あたりにあります const ( ssmPluginBinaryName = "session-manager-plugin" startSessionAction = "StartSession" ) func (s SSMPluginCommand) StartSession(ssmSess *ecs.Session) error { response, err := json.Marshal(ssmSess) if err != nil { return fmt.Errorf("marshal session response: %w", err) } if err := s.runner.InteractiveRun(ssmPluginBinaryName, []string{string(response), aws.StringValue(s.sess.Config.Region), startSessionAction}); err != nil { return fmt.Errorf("start session: %w", err) } (要約) ExecuteCommand APIのレスポンスのSessionをJSONにしたもの、リージョ ン、"StartSession"を引数にして session-manager-plugin を呼ぶ。 ( InteractiveRun の中で signal.Ignore(os.Interrupt) =ユーザ⼊⼒割り込みシグナル を無視)

Slide 17

Slide 17 text

session-manager-plugin で exec する⽅法まとめ . ECS ExecuteCommand API を叩く . レスポンスの Session を JSON ⽂字列にしたもの、リージョン名、"StartSession" を引 数にして session-manager-plugin をコマンドとして呼ぶ (引数はaws-cliを読むとまだあるようだけど最低限これでOK) . SIGINT は無視する 無視しないと Ctrl-C が exec 先に伝わらないで⼿元のコマンドが終了してしまう

Slide 18

Slide 18 text

実習 ExecuteCommandを叩いてレスポンスのSessionをJSONで表⽰するコマンドを作る func main() { svc := ecs.New(session.Must(session.NewSession())) res, _ := svc.ExecuteCommand(&ecs.ExecuteCommandInput{ Cluster: aws.String(os.Args[1]), Task: aws.String(os.Args[2]), Container: aws.String(os.Args[3]), Command: aws.String(os.Args[4]), Interactive: aws.Bool(true), }) sess, _ := json.Marshal(res.Session) fmt.Println(string(sess)) }

Slide 19

Slide 19 text

$ go run exec.go default 581833da4ade4ad9aafa0bbadcf9b636 nginx sh | jq . { "SessionId":"ecs-execute-command-03e7af5c716f7b340", "StreamUrl":"wss://ssmmessages.ap-northeast-1.amazonaws.com/v1/data-channel/ ecs-execute-command-03e7af5c716f7b340?role=publish_subscribe", "TokenValue":"AAEAAcNzLXhpq...." } そのJSONで session-manager-plugin を呼ぶと… $ session-manager-plugin '{...}' ap-northeast-1 StartSession Starting session with SessionId: ecs-execute-command-03e7af5c716f7b340 # nginx -v nginx version: nginx/1.19.10

Slide 20

Slide 20 text

まとめ ecspresso exec で快適な ECS Exec 環境を実装しました # config.yaml cluster: クラスタ名 service: サービス名 filter_command: peco この config.yaml を ecspresso --config に指定するだけで、ecspresso 管理下でない ECS サ ービスも簡単 exec できるのでぜひお試しを session-manager-plugin の使い⽅を公式のOSS実装から探りました