UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

ansibleでECSのタスク定義を更新し、安全に機密情報を管理する

nazoです。

ansibleにはクラウド操作モジュールがいくつか用意されており、特定のインスタンスの操作とは別に、クラウドインフラの構成管理も行うことができます。

今回はそれを利用して、ECSのタスク定義とサービスの更新をansible経由で行いたいと思います。ansibleは2.5以上のバージョンが必須になります。執筆時点ではベータなので、 pip install ansible==2.5.0b2 でインストールしてください。

ansibleを使うメリット

ECSのタスク更新を行うツールは、 ECS CLI が最もメジャーかと思いますが、ansibleを使うことにより、 ansible-vault と組み合わせて機密情報をそのまま保存することができます。

ECSを Twelve-Factor App に則って設計すると、タスク定義の環境変数にパスワードなどの機密情報を入れることになります。そのため、タスク定義を更新するツール自体が機密情報を管理できる必要があり、ansibleはそのための組み合わせに最適と言えます。

タスク定義を登録する

ECSのタスク定義を登録する場合は以下のように記述します。

- name: Create test-app task definition
  ecs_taskdefinition:
    family: "test-app"
    state: present
    force_create: True
    containers:
      - name: test-app
        cpu: 512
        essential: true
        image: "{{ test_app_repository }}:{{ test_app_tag }}"
        memory: 512
        portMappings:
          - containerPort: 80
            hostPort: 80
            protocol: tcp
        entryPoint:
          - "bundle"
          - "exec"
          - "puma"
          - "-e"
          - "production"
          - "-C"
          - "config/puma.rb"
        workingDirectory: "/test_app"
        environment:
          - name: DATABASE_USERNAME
            value: "{{ test_app_database_username }}"
          - name: DATABASE_PASSWORD
            value: "{{ test_app_database_password }}"
        logConfiguration:
          logDriver: awslogs
          options:
            "awslogs-group": "test-app"
            "awslogs-region": "ap-northeast-1"
  register: test_app_task_output

containers以下は、boto3の指定方法 と同じになりますので、そちらを参考にするのが良いです。

force_create: True オプションを付けると、ansible-playbookを実行する度に必ず新しいリビジョンのタスク定義を作るようになります。ちなみに この機能は私が作ったのですが 、いろいろあって2.5まで延期されていました。なのでこのタイミングでの紹介となりました。

なお、 force_create: True オプションがない場合、タスク定義がある場合には更新されず、 revision: [リビジョン番号] オプションがある場合、その番号を作るべき状態でないと作ることができません。タスク定義はリビジョンを連番で作るのが基本なので、このオプションが必要でした。

サービスを更新する

タスク定義を作ったら、単発実行タスクでない限りは対応するサービスの更新が必要です。ansibleでは以下のように行います。

- name: Create test-app service
  ecs_service:
    state: present
    name: "test-service"
    cluster: "test-cluster"
    task_definition: "{{ test_app_task_output.taskdefinition.family }}:{{ test_app_task_output.taskdefinition.revision }}"
    role: "test_ecs_role"
    load_balancers:
      -
        targetGroupArn: "{{ test_service_arn }}"
        containerName: "test-app"
        containerPort: 80
    desired_count: 1
    placement_strategy:
      - type: spread
        field: attribute:ecs.availability-zone
      - type: spread
        field: instanceId
    deployment_configuration:
      minimum_healthy_percent: 50
      maximum_percent: 200

まとめ

ansibleからECSのタスク定義を更新することによって、パスワードなどの機密情報を安全に管理しつつ適用する方法について紹介しました。

なお、構成管理にterraformなどのansible以外のツールを併用する場合、「ECSのサービスがないと設定できないもの」がそちらにある場合に多少の矛盾が発生します。具体的にはオートスケールの設定などです。ここは目を瞑るか、そのあたりを全てansibleに寄せるか、の選択が必要になります。私はそこは諦めて、あくまでタスク定義とサービスの更新のみにansibleを使用しています。