簡単そうとなめてかかると罠にはまりがちなAWS CodeDeployについて、いくつか覚書。

 

単純化しているが以下のサンプルを元にする。

appspec.yml

version: 0.0
os: linux
files:
- source: /opt/script                #ディレクトリ自体を配布
    destination: /opt/script
  - source: /opt/conf/server.conf    #特定のファイルを配布
    destination: /opt/conf
file_exists_behavior: OVERWRITE      #既存ファイルの上書き指定
permissions:
  - object: /opt/script              #/opt/script配下のディレクトリすべて指定したパーミッションになる
    pattern: "**"
    owner: root
    group: root
    mode: 755
    type:
      - directory
  - object: /opt/script
    pattern: "*.sh"
    owner: root
    group: root
    mode: 755
    type:
      - file
  - object: /opt/conf                #/opt/script配下のshファイルはすべて指定したパーミッションになる
    pattern: "**"
    owner: root
    group: root
    mode: 755
    type:
      - directory
  - object: /opt/conf                #/opt/conf内のserver.confに対するパーミッションを指定
    pattern: "server.conf"
    owner: root
    group: root
    mode: 644
    type:
      - file
hooks:
  AfterInstall:
    - location: ./deploy_task        #hookスクリプトファイルを相対パスで指定
      timeout: 300

 

1.filesセクションの記述

appspec.ymlのfilesセクションがわかっているようでわかっていなかった。ひとつのappspec.ymlに複数のパターンがあると気をつけていても間違える。

files
source: ディレクトリ配布の場合はディレクトリ名を、個別ファイルの場合はファイル名を指定。
destination: ディレクトリ名を指定。

destinationではファイル名は指定しない。(これ重要)

 

2. CodeDeployの上書きオプション

OSに最初から入っている既存のファイルやリビジョンに加える前から存在しているファイルを配布したい場合、デフォルトだと以下のエラーにより失敗する。

 

The deployment failed because a specified file already exists at this location

 

CodeDeployエージェント 1.3.2以降のバージョンであれば、appspec.ymlのfilesセクションにfile_exists_behaviorオプションを指定すれば期待値になる。

files:
  - source: /opt/script
    destination: /opt/script
  - source: /opt/conf/server.conf
    destination: /opt/conf
file_exists_behavior: OVERWRITE    #既存リソースに対する動作を上書きとして指定

 

file_exists_behaviorに指定可能な値は DISALLOW|OVERWRITE|RETAIN のどれか。詳細は以下参考。

参考
AppSpecの「files」セクション

 

3. デプロイ後のファイルタイムスタンプ問題

現状の仕様により、CodePipelineでソースアクションとしてCodeCommitをソースにした場合、ファイルのタイムスタンプを取得できないという問題がある。何もしないとデプロイ後のタイムスタンプが1979年12月29日になってしまう。これを是正するため、以下のhookスクリプトによりデプロイ時点の時刻をタイムスタンプとしてセットする。

ミドルウェアの設定ファイルを配布する場合は、この後プロセス再起動の処理を書くこともできる。

deploy_task

#!/bin/bash

touch /opt/script/*
touch /opt/conf/*

 

4. AMIから復旧させたインスタンスのリビジョン

過去のインスタンスで実行した既存のデプロイは、teriminate後にAMIから復旧させたインスタンスでもリビジョン対象として認識される。このためfile_exists_behaviorがなくてもデプロイは可能である。(しかしその後の変更時にエラーを回避したければ、つけておく方が安心)

 

5. リビジョン対象資材削除時の対応

検索したが意外に情報がない。ほぼ皆無だ。以下、仕方ないので自分で検証して判明した結果より。

(1) ディレクトリ内の資材一部の削除 リポジトリ内の対象資材をGit上から削除する。コミット/pushするとデプロイ時にその資材は削除された状態になる。サンプルymlの例で言うと、/opt/script内に複数のスクリプトがあるとして、その中の一つを削除したければGit上でdeleteし、appspec.ymlは変更なしでよい。

(2) filesセクションで特定のファイルを削除する appspec.ymlのfilesセクションから対象のsource/destination行を削除する。permissionセクションからも削除。サンプルymlからserver.confを削除する場合、以下2行を削除する。

  - source: /opt/conf/server.conf
    destination: /opt/conf

 

さらに以下も削除。

  - object: /opt/conf
    pattern: "server.conf"
    owner: root
    group: root
    mode: 644
    type:
      - file

 

ただし、これを実行すると「対象のファイルだけリビジョン対象外としてディレクトリは残す」ことができない。(ディレクトリの階層の状況にもよる)デプロイで期待値にならない部分は手動で対応するしかなさそうである。

 

 

Travel Travel Travel


関連がありそうな記事