Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ecspresso exec

ecspresso exec

FUJIWARA Shunichiro

April 23, 2021
Tweet

More Decks by FUJIWARA Shunichiro

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  6. 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
    特定のタスクを選択後、停⽌

    View Slide

  7. 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が出ます)

    View Slide

  8. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. 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.
    つれない

    View Slide

  13. 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
    とりつく島がない

    View Slide

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

    View Slide

  15. 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とか)は無視

    View Slide

  16. 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)
    =ユーザ⼊⼒割り込みシグナル
    を無視)

    View Slide

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

    View Slide

  18. 実習
    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))
    }

    View Slide

  19. $ 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

    View Slide

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

    View Slide