TerraformでAkamai配信設定を作ってみる

お久しぶりです、インフラのいわなちゃんさん(@xcir)です。

弊社は複数のCDNを利用していますが、Akamaiを主に利用しており多数の配信設定(プロパティ)を運用しています。
これまでは新規プロパティはAkamai Control Center(ACC/旧LUNA)で作成していましたが、
今回多数のプロパティを作る必要があり既存も含めてTerraformで運用を行えるようにしたので共有します。

既存プロパティをterrafromでapplyするまで

まずは運用は考えずに既存のプロパティのexport/編集/terraform apply/Activateという一連の動作を試してみましょう。

akamai/shellを実行する

Akamaiを外部ツールから叩く際にはAPIクレデンシャルが必要なのでこちらを参考に発行して~/.edgercに配置してください。
次にAkamaiの操作環境をどう作るかですが、公式のdocker-image(akamai/shell)を使うのが楽です。

akamai/shellはakamai-cliやterraformなどが含まれており、例えばpurgeもACCを使わずにできるので何かと便利です。

起動時の指定として先ほど配置した.edgercを/root/.edgercにマウントする必要があります。

プロパティのexportを行う

akamai-cliterraform export-propertyを利用してexportします。
そのまま実行するとカレントディレクトリにexportされるので--tfworkpathで出力先を指定しています。

これでexportできました。

最小構成だとおそらくこのようなファイル構成となっており、behaviorなどの設定は./property-snippets/main.jsonにあります。

Compressible objectsとEnable H2/H3が子ルール


また子ルールがあると同一階層に別名のjsonがありますが、その場合でも基点はmain.jsonでそこからincludeされています。

Terraformでapplyまで行う

exportされた直後はinitもされてない状態なのでapplyできません。
そのため同じフォルダにあるimport.shを実行しterraformの実行環境を整えます。

後はmain.jsonを修正してterraform plan ~ applyを実行することで設定をAkamai側に反映できます。
ただこれはActivateはされておらず、ACCで設定の保存をした状態と同じです。

設定のactivateを行う

設定のactivateを行うにはakamai-cliのpm activate-versionを利用します。(pm activateではありません)
もちろんACC上で行うことも可能です。

今回はstagingを対象としたいので-n stagingを指定していますが、productionを指定すれば本番のactivateも可能です。

運用にどう乗せるか

以上で一連の流れですがそう難しくなく既存プロパティのexportができます。
新規作成についても普通に作ればいいので行けそうです。
と最初考えてたのですが、実運用に乗せるためには難しい問題があり頭を悩ませることとなりました。

Akamai特有のterraform運用の難しさ

CDNに限らずですが今はどのサービスでもWeb上から設定を変更できます。
ところがterraform利用時はCIツールと連携させてterraform側に寄せてしまうことが一般的です。
これはWeb側で変更するとterraform側の設定と差分が発生(drift)するからです。
ではAkamaiもterraformに寄せられるかというと実運用上ではほぼ不可能です。

設定項目と変更が多い

プロパティは条件文に相当するCriteriaと、HTTP/3を有効にするなどの様々な機能を設定するBehaviorなどを設定していきますが
現時点でCriteriaが39、Behaviorが214あります。
もちろん良く使う設定は限られていますし、契約によって使えないのも多数ありますがこれを覚えて行うのは無理です。
また割と頻繁にバージョンアップが行われ、behaviorの数もですがオプション項目が増えます。
ACCで設定をActivateする前に新旧バージョン比較を行うのが一般的ですが、変更していない設定でも差分が出ることがあります。
これはバージョンアップが行われたことが原因です。

変更がないのにバージョンアップで差分がでたbehavior

増えた項目にはデフォルト値がある(はず)ので知らなくても問題がないといえばないのですが、
必ず使うだろうOriginの設定項目の多さを見てもわかる通り人力で書くのは厳しく、ACC上で設定を作ってexportするかJSON表示の内容をコピペするのが現実的です。

JSONを表示でterraformでも利用できるjsonを見ることができる

なおバージョンを固定することも可能ですが、新機能も使えなくなります。

プロパティ作成時にもルールフォーマットのバージョン指定できるが頻繁にバージョンが上がっていることがわかる

すべての機能をTerraformで制御できない

Akamaiでログを取得するにはDataStream2(DS2)を利用します。( Log Delivery Servicesは終息方向)
DS2側にはログを出力するプロパティ名を、プロパティ側にログの送信先としてDS2名を設定する必要があるのですが少し厄介で先にプロパティをActivateしないとDS2に追加できません。
  1. プロパティを作成してActivateする(Staging/ProductionのどちらでもOK)
  2. DS2側にプロパティを追加してActivate
  3. プロパティにDS2のbehaviorを追加してActivate
このように複雑な手順が必要なものがあったり、他にもterraformで作れないリソースをbehaviorから参照するものがあったりと全てterraform管理下に置くのは無理でしょう。
ということでACCの利用が必須なので、terraformを便利に使いつつどのように整合性をとっていくかを考える必要があります。

ACCとterraformのどちらも使う

両方使う場合はdriftをどう扱うかが問題です。
今回実現したいのはAkamaiのプロパティの作成や更新をterraformで運用したいというものでした。
特に複数のプロバイダを使うこともないので最悪毎回exportしても問題ないと発想を変えました。
要は設定のマスタはAkamaiなのでそことの同期を確実に行い、terraform側ではstateを持たないという方針でフローを作成しました。
これらのフローを実現するためにいくつかのスクリプトを作成しましたのでまずスクリプトを紹介します。

akamai-tf-tools

https://github.com/xcir/akamai-tf-tools

akamai-docker.sh

akamai/shellの起動スクリプトです。
以下の機能があります
  • 現在のパスを/workdir/mountにマウント
  • 抜ける際にプロパティの格納先(/props)とワークディレクトリ(/work)を実行ユーザでchown
実行ユーザーで動かそうといろいろ試したのですが、akamai/shell内でrootでないと一部コマンドが動かなくなることからやむを得ずこのようにしています。
.edgercは$HOME/.edgercを基本としていますが、$AKHOMEを設定すると他のパスを使うことが可能です。

get_property.sh [property name] [property ver(option)]

akamai/shell内でのみ実行可能です。
指定したプロパティを取得します。
保存先はprops/ctr_[contractID]/[property name]となります

get_all_property.py

akamai/shell内でのみ実行可能です。
アクセス可能なすべてのプロパティを取得するため実行には時間がかかります。
保存先はprops/ctr_[contractID]/[property name]となります

maintenance.py

akamai/shell内でのみ実行可能です。
プロパティの取得・更新・削除といったメンテナンスを行います。
運用はこのコマンドを使うだけで事足りるはずです。
オプションは
  • -f tfstateがあるパスを削除する
  • -x 実行が必要なコマンドをサジェストするだけでなく実行する
となっており、基本的には常に-f -xを同時に指定して動かします。
なお更新についてはプロパティバージョンを見ています。
そのためこのようなケースには対応できません。
  1. maintenance.pyでアクティベートを行っていない設定を取得(プロパティV2)
  2. ACC上で設定編集(V2)
  3. 再度maintenance.pyを実行するが同一バージョン(V2)のため更新が反映されない
この場合は該当プロパティのディレクトリを削除すれば再取得します。
編集前にterraform planを実行して差分がでたら消すと覚えておけばいいです。
また、初回実行時は内部でget_all_property.pyを実行するため時間がかかります。

使ってみる

ひとまずツールを使って全プロパティを取得してみましょう。

これだけです。
exportしたプロパティはすべてprops/以下にあります。
ACCで変更しようがterraformで変更しようがmaintenance.pyで綺麗な状態になるのでdriftを意識しなくても良くなります。
なおテストツールもあるのですが、それは別記事で紹介します。

プロパティの新規作成

  1. テンプレートをworkディレクトリにコピーして編集
  2. terraform init~apply
  3. activate(stg)
  4. DS2設定
    1. DS2に新規作成したプロパティを追加
    2. プロパティにDS2設定を追加
    3. terraform apply
  5. 再activate(stg)
  6. そのほか必要なリソースの作成
    1. createRPT.py
    2. createLDS.py
  7. maintenance.py -f -x
  8. テスト
  9. git add ~ push
  10. activate(prod)
プロパティを新規に作成する際には後ほど触れるテンプレートをベースに作っていきます。
手順が煩雑なのは先に触れたactivateしないと設定追加ができないDS2があるためで、それを除くとほぼ流れ作業です。
また今回公開しているスクリプトではないですが、createRPT/LDSはレポーティンググループとLog Delivery Services(LDS)の作成を行うスクリプトです。
恐らく運用をする際には各社でそれぞれ必要な設定があると思いますので、apiやcliを駆使してできるスクリプトを作っておくと便利です。

プロパティの更新

  1. maintenance.py -f -x
    1. 上記で変更があった場合は一度git add ~ commit
  2. import.sh
  3. terraform plan
    1. ここで差分が出る場合は同一バージョンで変更があったケースなので該当プロパティフォルダを削除
    2. maintenance.py -f -x
    3. import.sh
  4. 設定編集
  5. terraform plan ~ apply
  6. activate(stg)
  7. テスト
  8. maintenance.py -f -x
  9. git add ~ push
  10. activate(prod)
maintnance.pyを実行することでACC上で編集していてもexportできるのでdriftを気にせず編集が可能です。

新規プロパティ用テンプレート

今回サンプルとして提供しているテンプレートは公式を改造したものです。
流石に社内のテンプレートをそのまま出せないのでだいぶ機能は削っていますが一通りのことと拡張のしやすさはあると思いますので是非改造して使ってみてください。
まずサンプルを使う前に最低限編集が必要な部分がありますのでそれを紹介した上でどのように使うかを説明します。

akamai.auto.tfvars


コントラクトIDとグループIDの指定が必要です。

akama-cliでpm lgを実行すると現在の一覧が見れます。

テンプレートを利用して新規にプロパティを作成する

テンプレートをworkディレクトリにコピーしてmodules.tfを編集します

コメントの通りなのでそこまで悩むことはないと思いますが、cdn.example.netのプロパティを作るとしたらこんな形でしょうか
なお、プロダクトはDownloadDeliveryにしていますが、環境に合わせて変更してください。

ひとまずこれでプロパティを作成します。

これで作成できたのでひとまずACC上で確認してみましょう

無事設定ができていることが確認できます。
そのままactivateしてもいいのですが、ルールを追加します。
akamai-property/property-snippets/main.jsonを修正してrules/Enable_H2_H3.jsonを追加します。

再度terraformで適用します。
なおterraformのプラグインがないというエラーが出た場合は再度initしてapplyすればいけます。

さきほどからEnable H2/H3が増えています。
この後はmaintenance.py -f -xを実行すればprops以下に今作成した設定がexportされます。

テンプレートのカスタム

先ほど機能を削ったと書きましたが、削ったのはEnable_H2_H3.jsonのような子ルールです。
他にもPOSTキャッシュやDS2つなぎこみなどの様々なルールがありますが、ここは各々で増やしていけばよいでしょう。

増やし方も簡単です。適当なプロパティでルールを作成してJSONを表示するだけです。

Enable_H2_H3.jsonとApplyした後のJSONを表示の結果は同じ

これをrules以下に配置した上で#include:rules/template.jsonとするだけです。

またここで作成したルールはもちろん既存の設定にも適用できます。
exportしたプロパティはprops以下にあるので

props/ctr_[contractID]/[propertyname]/property-snippets/

に利用したいルールjsonをコピーして同じように#includeすれば利用できます。

またすべての設定をテンプレートで実現する必要はなく、他で使いづらいものやテンプレート化しづらいものはACC上で編集してしまえばよいです。
その辺の割り切りが重要です。

最後に

単純にAkamaiのプロパティをexportして編集してterraformでapplyするだけなら簡単なのですが、
いざ実際の運用に乗せようと考えるとACCをどう扱うかという問題にぶち当たります。
今回紹介したフローではterraformで操作した後は消すことでACC/terraformのどちらでも操作ができるようにして解決しました。
このフローはまだ途上で改善が必要なポイントもあるのですがひとまず最初のステップとしては有用だとおもいますので試してもらえれば幸いです。
またテストについては次の記事で紹介します。