Terraformで作るAkamai配信設定とLinode Object Storage

# Terraformで作るAkamai配信設定とLinode Object Storage

Terraformでは複数のプロバイダーを指定して、同一のコード内で管理することができます。
今回は、LinodeのObject Storageに静的コンテンツを配置し、AkamaiのCDNで分散配信する構成をTerraformで作成する例を紹介します。

## Linodeとは

Linodeはシンプル、低価格、使いやすさに定評のあるIaaSのサービスです。
2022年2月にAkamaiが買収を発表しました。（買収完了は本年3月）
https://www.akamai.com/ja/newsroom/press-release/akamai-to-acquire-linode
Linodeは仮想サーバーのみの提供ではなく、S3互換製品であるObject Storageをサービスとして提供しています。
今回はそのObject StorageをオリジンとしたAkamaiの配信設定をTerraformのコードで管理する方法をご紹介します。

## Akamaiの配信設定

今回はAkamaiの配信製品の一つであるDownload Deliveryを利用するTerraformのコードとなっています。
Download Deliveryは大容量のファイルベースのコンテンツ配信に最適化された、高性能のコンテンツ配信ソリューションです。

## Terraformのコードと構成

Terraformのコードはこちらのサンプルを利用します。
https://github.com/isss802/linode-terraform-demo/tree/main/linode-objectstorage-akamai

構成図は以下となります。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/2e451eca-b416-692f-a791-12a8c55f8ef7.png">

## コードの取得

Githubからコードを取得します。

```
$ git clone git@github.com:isss802/linode-terraform-demo.git
$ cd linode-objectstorage-akamai/
```

## Akamai API Keyの設定

AkamaiとLinodeのAPI Keyを取得し、設定をします。
API Key取得の参考サイト
https://www.akamai.com/ja/blog/developers/akamai-api-part1-api-client-edgegrid#000003

~/.edgerc に作成したAPI Keyの登録を行います。

```
$ vim ~/.edgerc

[default]
; Akamai {OPEN} API credentials
client_secret = xxxxxxxxxxxxxxxxxxxxx
host = akab-xxxxxxxxxxxxxxxxxxxxxxxxxx.luna.akamaiapis.net
access_token = akab-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
client_token = akab-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## Linode API Keyの設定

LinodeのAPI Keyを取得し、設定をします。

https://www.linode.com/docs/guides/getting-started-with-the-linode-api/

```
$ export TF_VAR_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

## コードの説明

記載している各コードに関しての説明となります。

```
$ tree ./
./
├── README.md
├── index.html → Linode Object Storageにアップロードするファイル
├── objectstorage.tf → Linode Object Storageの作成、アクセスキーの作成、ファイルアップ
├── property-snippets
│   └── main.json → Download Deliveryの設定ファイル
├── property.tf → Download DeliveryのProperty作成、CPコード作成、Edge Hostnameの作成
├── terraform.tf → プロバイダーの定義
└── variables.tf → 変数の指定
```

## Variablesの指定

Variablesの指定をする際に、ContractIDとGroupNameが必要となります。
ACC(Akamai Control Center)より確認を行い、情報を控えておきます。

グループ名の中にContractIDが含まれている場合が多いです。

<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/8a80f974-7708-d0a9-9185-4afd2d57b811.png">

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/ab8d5729-e3f8-bd9d-0a05-d7fe71421bb9.png">


Contract IDはBillingのページからも確認が可能です。

<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/4688ae8b-2ef9-e020-c106-9c7f12df5727.png">

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/b9f44e66-0546-7ff9-16aa-0d4cf45890c2.png">

variables.tfを編集し、作成する際の値を入力します。

```
$ vim variables.tf

#########################
# Linode
#########################
variable "token" {}

# Linode Object Storageを立ち上げるリージョンを指定

variable "region" {
  default = "us-southeast-1"
}

# Linode Object Storageの名前を記載

variable "label" {
  default = "example"
}

#########################
# Akamai Property
#########################

variable "edgerc_path" {
  type    = string
  default = "~/.edgerc"
}

variable "config_section" {
  type    = string
  default = "default"
}

variable "env" {
  type    = string
  default = "staging"
}

# Group NameとContract ID(先頭にはctr_が必要)を記載する

variable "akamai_group" {
  default = {
    group_name = "example-group"
    contract_id = "ctr_XXXXXXXXXX"
  }
}

# CP Code Nameに任意の名前を設定する

variable "cpcode_name" {
  default = "example"
}

# Akamaiに割り当てるHostnameを指定する

variable "cname" {
  default = "hoge.example.com"
}

# Emailを記載

variable "email" {
  default = "hoge@example.com"
}

# EdgeHostnameを記載する

variable "edge_hostname" {
  default = "hoge-example-com.edgesuite.net"
}
```


## Terraformの実行

Terraformを実行し、各環境へリソースの作成を行います。
尚、今回のサンプルではAkamaiへのステージング環境に設定を適用するため4分ほど実行にかかります。
コーヒーでも作って待ちます。

```
$ terraform init
$ terraform apply

akamai_property_activation.dd: Still creating... [3m40s elapsed]
akamai_property_activation.dd: Creation complete after 3m44s [id=:STAGING]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
```

作成完了したらAkamaiのACCからPropertyが作成されていることを確認します。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/e01e0267-e663-e125-9708-6b2f89276e6f.png">

設定ではS3互換ストレージであるLinode Object Storageが設定されています。

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/c6d27b84-eb0a-15f0-a597-8a4ae4c03828.png">

また、Edge Hostnameが利用可能になるまで15分程度かかります。
作ったコーヒーでも飲んで待ちます。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/b35c2d4b-0d29-5e86-b41c-3f7d067cc329.png">

## 接続確認

Edge Hostnameの作成が完了したら、ステージング環境へのアクセス確認を行います。
Akamaiのステージング環境にアクセスするにはSpoofing（スプーフィング）を行います。
詳しくはこちらのサイトを参考にしてください。
https://community.akamai.com/customers/s/article/Stagingrxdxn?language=en_US

```
$ dig xxxxxxxxxx.edgesuite-staging.net +short
axxx.dscd.akamai-staging.net.
xx.xx.xx.xx #IPをコピーする
xx.xx.xx.xx

$ sudo vim /etc/hosts
xx.xx.xx.xx hoge.example.com #IPとドメインをHostsに記載する
```
Webブラウザからhoge.example.comにアクセスし、ページが表示されるか確認する。

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/4823c3c3-7c51-db6f-ce4b-30105c14e4ca.png">

## 運用のTips_1

Akamaiの配信設定をTerraformで管理する場合、jsonファイルの管理が必要です。

```
$ tree ./
./
├── property-snippets
│   └── main.json → Download Deliveryの設定ファイル
```

このjsonファイルの可読性が低く、またどのような設定を記載すればいいかが悩ましいところです。

このjsonファイルはData Sourcesのakamai_property_rulesにより管理をしやすくすることができます。
jsonファイルをテンプレート化したい場合に、指定の箇所を変数化することができ、他の環境にも流用しやすくなります。

https://registry.terraform.io/providers/akamai/akamai/latest/docs/data-sources/property_rules

```
$ view property.tf

data "akamai_property_rules_template" "rules" {
  template_file = abspath("${path.module}/property-snippets/main.json")
# 変数を指定可能、この場合はLinodeのObject Storageを指定している
  variables {
    name = "hostname"
    value = "${linode_object_storage_bucket.mybucket.label}.${linode_object_storage_bucket.mybucket.cluster}.linodeobjects.com"
    type = "string"
  }
```

main.json内に `"${env.hostname}"` として記載している。

```
$ view property-snippets/main.json

 34         "behaviors": [
 35                 {
 36                   "name": "origin",
 37                   "options": {
 38                    "cacheKeyHostname": "REQUEST_HOST_HEADER",
 39                    "compress": true,
 40                    "enableTrueClientIp": true,
 41                    "forwardHostHeader": "ORIGIN_HOSTNAME",
 42                    "hostname": "${env.hostname}",
 43                    "httpPort": 80,
```

## 運用Tips_2

Akamai Propertyに新規設定を1つ追加したい場合、このmain.jsonの追記が必要となります。
しかし、このjsonをどのように記載したら差分がでないようになるか悩ましいところです。
ACCからProperty Managerを操作し、追加したい設定を入れた後に View JSONから参照が可能となります。
また、ダウンロードも行えるので、作成したい、もしくは追加したいjsonがどのような記載か確認し、Terraformへ反映する運用を行うことでコード化の手間を簡略化してみましょう。

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49877/265d4f34-fc63-023b-a303-d45b2d6425ce.png">


## まとめ

Terraformで作るAkamai配信設定とLinode Object Storage、いかがでしょうか。
Akamaiは様々なリソースがTerraformに対応しているため、Infrastructure as Code（IaC）の対応を迅速に進めていくことができます。

## 関連記事

アカマイ・テクノロジーズ合同会社のQiitaではLinode関連など開発者向けの記事を記載しております。

https://qiita.com/organizations/Akamai

https://qiita.com/isss802/items/3bbc3cc208982c96f9e1

https://qiita.com/isss802/items/895bd604fdf67c0fc55c