terraform による Akamai DSA構成管理
始めに
Akamai DSAのproperty設定のコード化に関して概要を解説する
DSAは設定項目が多岐に渡り複雑性が高く、手動での運用コストが非常に高い状態であった
それを解消するために、terraform akamai providerを利用してIaC化を行なった
その設計概要である
ディレクトリ設計
弊社では開発用のdev,動作検証環境のstg、本番環境のproが存在する
そのため以下のようなディレクトリ構成をとった
アプリケーション用のDSAではstg/pro共通のresourceディレクトリを参照し、Dryなコード環境を実現する
■ ディレクトリ構成イメージ
└── app_property_group
└── app_property_1
├── environments
│ ├── pro
│ │ ├── akamai.tf
│ └── stg
│ ├── akamai.tf
└── resources
├── property-snippets
│ └── main.json
├── property.tf
├── variables.tf
└── versions.tf
── dev_property_group
└── dev_property_1
├── environments
│ └── dev
│ ├── akamai.tf
└── resources
├── property-snippets
│ └── main.json
├── property.tf
├── variables.tf
└── versions.tf
ディレクトリ構成概要
name | 用途 |
---|---|
app_property_group | プロパティグループの名前、アプリ名やドメインにする |
app_property_1 | アプリケーション毎のdsa property用ディレクトリ |
environments | 各環境用のtfファイルを格納する,この配下の環境ディレクトリでapplyを行う |
resources | akamai を構成するための設定ファイル群 |
property-snippets | akamaiで指定されるjson形式の設定ファイル群 |
ファイル構成
akamai.tf
- 記述例
プロパティ固有の設定値を全て記述する
module "stg" {
source = "../../resources"
env = "stg"
property_name = "stg-akamai-IaC-test.xxxx.xx.jp"
origin_hostname = "stg-shiina-test.xxxx.xx.jp"
edge_hostname = "stg-akamai-iac-test.xxxx.xx.jp-v1.edgesuite.net"
property_hostname = "stg-akamai-IaC-test.xxxx.xx.jp"
akamai_group_name = "akamai_IaC"
notify_email = "t_shiina@xxxx.xx.jp"
deny_by_ip_enabled = true
}
module "pro" {
source = "../../resources"
env = "pro"
property_name = "akamai-IaC-test.xxxx.xx.jp"
origin_hostname = "shiina-test.xxxx.xx.jp"
edge_hostname = "akamai-iac-test.xxxx.xx.jp-v1.edgesuite.net"
property_hostname = "akamai-IaC-test.xxxx.xx.jp"
group_name = "akamai_IaC_dev"
notify_email = "t_shiina@xxxx.xx.jp"
deny_by_ip_enabled = false
}
property.tf
dsa propertyを構成する要素を全て記述する
data "akamai_property_rules_template" "default"
で可変値を指定して読み込ませる
# acitivation時の連絡先
locals {
email = var.notify_email
rule_format = "v2020-03-04"
is_activate = false
}
# propertyを作成するグループ名
data "akamai_contract" "default" {
group_name = var.akamai_group_name
}
# contract_idを取得
data "akamai_group" "default" {
name = var.akamai_group_name
contract_id = data.akamai_contract.default.id
}
# akamai 形式のjsonファイルをdataとして読み込む
data "akamai_property_rules_template" "default" {
template_file = abspath("../../resources/property-snippets/main.json")
# json に引き渡す可変値を指定
variables {
name = "origin_hostname"
value = var.origin_hostname
type = "string"
}
variables {
name = "cp_code_id"
value = split("_", akamai_cp_code.default.id)[1]
type = "number"
}
variables {
name = "cp_code_name"
value = akamai_cp_code.default.name
type = "string"
}
}
# propertyの作成
resource "akamai_property" "default" {
name = "${var.property_name}_dsa"
group_id = data.akamai_contract.default.group_id
contract_id = data.akamai_contract.default.id
product_id = "prd_Site_Accel"
hostnames {
cname_from = "${var.property_hostname}"
cname_to = akamai_edge_hostname.default.edge_hostname
cname_type = "CUSTOM"
cert_provisioning_type = "CPS_MANAGED"
}
rules = data.akamai_property_rules_template.default.json
}
# edge hostnameも作成する
resource "akamai_edge_hostname" "default" {
product_id = "prd_Site_Accel"
group_id = data.akamai_contract.default.group_id
contract_id = data.akamai_contract.default.id
edge_hostname = "${var.edge_hostname}"
ip_behavior = "IPV4"
}
# CP CODEの作成
resource "akamai_cp_code" "default" {
name = var.property_hostname
contract_id = data.akamai_contract.default.id
group_id = data.akamai_group.default.id
product_id = "prd_Site_Accel"
}
# stating activation
resource "akamai_property_activation" "staging" {
property_id = akamai_property.default.id
contact = [local.email]
version = akamai_property.default.latest_version
note = "Sample activation"
}
# prodution activation
resource "akamai_property_activation" "production" {
property_id = akamai_property.default.id
network = "PRODUCTION"
# PRODUCTIONの適用をフラグを立てて管
version = var.deploy_production_network == true ? akamai_property.default.latest_version : akamai_property.default.production_version
depends_on = [
akamai_property_activation.staging
]
contact = [local.email]
note = var.acitivate_note
}
}
property-snippets以下
各種テンプレートのjsonファイルが用意されており、それをmain.jsonから読み込み指定する
可変値は${env.変数名}
として指定し、property.tfに記述する
- main以外の各種Jsonファイルについて
akamaiのデフォルトファイル構成に倣って下記の様にしている。
name | 用途 |
---|---|
Augment_insights.json | モニタリング用の設定 |
Accelerate_Delivery.json | 配信高速化の設定 |
Offload_origin.json | キャッシュ制御設定 |
Increase_availability.json | 可用性向上のための設定 |
Minimize_payload.json | 圧縮に関する設定等 |
main.json
{
"rules": {
"name": "default",
"behaviors": [
{
"name": "origin",
"options": {
"cacheKeyHostname": "ORIGIN_HOSTNAME",
"compress": true,
"customValidCnValues": [
"{{Origin Hostname}}",
"{{Forward Host Header}}"
],
"enableTrueClientIp": true,
"forwardHostHeader": "ORIGIN_HOSTNAME",
"hostname": "${env.origin_hostname}", # ⬅︎可変値指定をしている
"httpPort": 80,
"httpsPort": 443,
テンプレート呼び出し部抜粋
"children": [
"#include:Augment_insights.json",
"#include:Accelerate_Delivery.json",
"#include:Offload_origin.json",
"#include:Strengthen_security.json",
"#include:Increase_availability.json",
"#include:Minimize_payload.json"
],
コード作成方針
akamai 設定値は多岐にわたりakamai様式のjsonファイル、tfコード相互で連携する必要がある
設定値全てをtfコード化すると管理対象が膨大になり可読性、運用性ともに悪化するため以下の方針を取る
- 設定値は環境毎にユニークなもののみを原則としてakamai.tfに記載し、property.tfは初期値のまま運用する
- 環境差異がある値のみterraform変数としてproperty-snippetsを読み込ませる
- 共通の設定内容はproperty-snippets配下のjsonを直接変更する
運用イメージ
-
dev_property_1
で コードの作成及び動作検証 -
app_property_1
のresourcesに設定ファイルをコピー -
app_property_1
のakamai.tf等を必要に応じて編集 -
app_property_1
のstg
をapply -
app_property_1
で動作検証 -
app_property_1
のpro
を staging network にapply -
app_property_1
の staging networkで動作検証 -
app_property_1
をakamai コントロールパネルから手動でactivate
今後の課題
terraformコード化は完了したもののAkamai API側で散発的にエラーが発生するためCI駆動にはできておらず、手動でのterraform実行運用にとどまっている
CI化に向けて問題解決をしていきたい