terraformerを使ってコード化対応
手動で管理していたCloudDNSをコード管理したかったので、terraformerを使ってコード化しました。
Installation
brew install terraformer
事前準備
コマンド実行したら以下エラーが出たので、ディレクトリにpluginをinstall
Copy your Terraform provider's plugin(s) to folder ~/.terraform.d/plugins/{darwin,linux}_amd64/, as appropriate.
mkdir -p ~/.terraform.d/plugins/darwin_amd64 cd ~/.terraform.d/plugins/darwin_amd64 wget https://releases.hashicorp.com/terraform-provider-google/2.17.0/terraform-provider-google_2.17.0_darwin_amd64.zip unzip terraform-provider-google_2.17.0_darwin_amd64.zip
Command実行
CloudDNSの以下リソースのコード化を実行
terraformer import google --resources=dns --projects=hogehoge --regions=asia-northeast1 2019/10/23 13:47:53 google importing project hogehoge region asia-northeast1 2019/10/23 13:47:54 google importing... dns ... 2019/10/23 13:48:00 google Connecting.... 2019/10/23 13:48:00 google save dns 2019/10/23 13:48:00 google save tfstate for dns
tfstateファイルとtfファイルが作成されていることを確認
ll generated/google/hogehoge/dns/asia-northeast1/ default.tfstate* dns_managed_zone.tf* dns_record_set.tf* outputs.tf* provider.tf*
GoでTravis-CIを使ってのテストとデプロイ
Goで何か書いた時にCIの設定をまとめてみた。
もっといい方法がありそうなので、ブラッシュアップしていきたい。
golangci-lint
でsyntaxチェックして goreleaser
でdeployの流れ。
.travis.yml
travisの設定は以下の用にする。
branches: ciの設定(ブランチがマスターブランチ以外にプッシュされた場合、CIは実行しないように)
notifications: slackの設定
jobs: lintチェックさせる。 ./bin/golangci-lint
pathに注意
deploy: deployはgoreleaserを使う
language: go branches: only: - master go: - 1.11.x env: - GO111MODULE=on git: depth: 1 before_script: - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.13.2 install: true notifications: slack: secure: hogehoge jobs: include: - stage: lint script: - go get -v -t -d ./... - ./bin/golangci-lint run --config .golangci.yml - stage: test script: go test -v -race -cover ./... - stage: build script: go build deploy: - provider: script skip_cleanup: true script: curl -sL https://git.io/goreleaser | bash on: tags: true
.golangci.yml
golangci configは以下の内容で大体十分。
run: deadline: 5m linters: disable-all: true enable: - gofmt - golint - govet - staticcheck - unused - ineffassign - misspell - gocyclo - deadcode - typecheck
.goreleaser.yml
builds.binary: バイナリ名 release: githubのリポジトリのownerとnameを入れておきます。
before: hooks: - go mod download builds: - binary: hogehoge goos: - darwin - linux goarch: - amd64 changelog: filters: exclude: - .github - Merge pull request - Merge branch archive: format: tar.gz name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" files: - README.md replacements: darwin: Darwin linux: Linux amd64: x86_64 release: github: owner: hogehoge name: hogehoge
Terraformの基本
terraformの基本事項についてaws providerを使用して確認していく。 terraformコマンドで構築する前にクレデンシャル情報を環境変数に渡しておくのを忘れずに。
export AWS_ACCESS_KEY_ID=hogehoge export AWS_SECRET_ACCESS_KEY=hogehoge export AWS_DEFAULT_REGION=hogehoge
コマンド
terraform init
はプロバイダ用のバイナリをダウンロードする。
terraform plan
はdry-run
terraform apply
でplanの内容を実行する
要注意メッセージ
リソースの再作成
# aws_instance.example must be replaced
例えば、awsのproviderでinstanceを作っていたとして、
何かtfファイルを編集したらインスタンスが再作成されてしまったなんてことが起きるので注意。
destroyも要確認。
Terraform の構成要素
- 変数
variableで変数の定義ができる。
variable "example_instance_type" { default = "t3.micro" } resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = var.example_instance_type }
locals
でローカル変数が定義できる。
variableはコマンド実行時に変数を上書きできるがlocalsは上書きできない違いがある。
- output
output
で値を出力することができる
apply時にターミナル上で値が確認できるようになる。
他にはmoduleから値を取得する時に使う。
variable "example_instance_type" { default = "t3.micro" } resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = var.example_instance_type } output "example_instance_id" { value = aws_instance.example.id }
applyすると、実行結果に、作成されたインスタンスの ID が出力される。
Outputs: example_instance_id = i-090d4a8d3ec3fac74
- データソース
データソースを使うと外部データを参照できる。
最新のAmazonLinux2のAMIを以下のように定義して参照してみる、
filter
などを使って検索条件を指定し、most_recent
で最新のAMIを取得している。
data "aws_ami" "recent_amazon_linux_2" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["amzn2-ami-hvm-2.0.????????-x86_64-gp2"] } filter { name = "state" variables = ["abailable"] } } resource "aws_instance" "example" { ami = data.aws_ami.recent_amazon_linux_2.image_id instance_type = "t3.micro" }
- provider
AWS、GCP、Azure、Openstackなど構築する際、そのAPIの違いを吸収するものがプロバイダ。
リージョンの定義をaws mojuleを使ってするとこうなる。
provider "aws" { region = "ap-northeast-1" }
Interpolation Syntax
- 参照
EC2 向けセキュリティグループの定義
80 番ポートを許可すると以下 ※接続元のIPアドレスを制限していないです
resource "aws_security_group" "example_ec2" { name = "example-ec2" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] }
vpc_security_group_ids
からセキュリティグループへの参照を追加し、EC2インスタンスと紐づけます。
vpc_security_group_ids
はリスト形式で渡すため、値を []
で囲んでいます。
TYPE.NAME.ATTRIBUTE
の形式で他のリソースの値を参照できます。
variable "example_instance_type" { default = "t3.micro" } resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = var.example_instance_type vpc_security_group_ids = [aws_security_group.example_ec2.id] user_data = <<EOF #!/bin/bash yum install -y httpd systemctl start httpd.service EOF } output "example_public_dns" { value = aws_instance.example.public_dns }
- 条件分岐
Terraform では、三項演算子が使える。 本番環境と開発環境でインスタンスタイプを切り替えたい時。
variable "env" {} resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = var.env == "prod" ? "m5.large" : "t3.micro" }
env変数をTerrafor 実行時に切り替えると、plan 結果が変わる。
$ terraform plan -var 'env=prod' $ terraform plan -var 'env=dev'
ただ環境を分けたい時はディレクトリで分けたりしてもよいかな。
- 組み込み関数
Terraform には、文字列操作やリスト操作、よくある処理が組み込み関数として提供されている。 外部ファイルを読み込む file 関数を使ってみる。
ユーザデータを user_data.sh
としてスクリプトで外に出す。
main.tf
ファイルと同じディレクトリに置く。
#!/bin/bash yum install -y httpd systemctl start httpd.service
以下でapply すると、user_data.sh
ファイルを読み込んでくれる。
resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = "t3.micro" user_data = file("./user_data.sh") }
- テンプレート
Terraform には、実行時に値を埋め込むテンプレート機能がある。
user_data.sh
を user_data.sh.tpl
とテンプレートファイル化してみる。
インストールパッケージを差し替えられるように、「package」変数を定義する。
#!/bin/sh yum install -y ${package} systemctl start ${package}.service
これを利用するために template_file
データソースを定義する
template
に、テンプレートファイルのパスを指定する
vars 句を記述すると、テンプレートの変数に値を代入できる
data "template_file" "httpd_user_data" { template = file("./user_data.sh.tpl") vars = { package = "httpd" } }
template_file
データソースを参照する
data.template_file.httpd_user_data.rendered
のように記述することで、テンプレートに変数を埋め込んだ結果を取得できる
resource "aws_instance" "example" { ami = "ami-0f9ae750e8274075b" instance_type = "t3.micro" user_data = data.template_file.httpd_user_data.rendered }
tfstateファイル
Terraform が変更した差分を検出して、必要な部分だけ変更できることが確認できた。
この判断をtfstateファイルで行っている。
tfstate ファイルは Terraform が生成するファイルで、現在の状態が記録されている。
Terraform は tfstate ファイルと、HCL で記述されたコードの内容に差分があれば、その差分のみを変更するよう振る舞う。
terraform.tfstate
ファイルは terraform apply
を実行していれば作成される。
中身を見るとJSON文字列に、現在の状態が記述されているのがわかる。
tfstateファイルは terraform apply
を実行したローカルに保存されるが、
これだとチーム開発したときに、他の人にtfstateファイルがないことになってしまい、
全リソース再作成が起きるおそれがあるので、リモートのストレージを、バックエンドとして利用しましょう。AWSならS3などを利用しましょう。
tfstateの格納先が記載されたファイル init.tf
を作り、事前作成したバケットを指定します。
terraform { backend "s3" { bucket = "tfstate-pragmatic-terraform-on-aws" key = "example/terraform.tfstate" region = "ap-northeast-1" } }
リモートのバックエンドとして使用するS3バケットには、バージョニング設定をすることが強く推奨されます。 S3に保存すれば、tfstateファイルから、いつでも以前の状態に戻せるようにもなります。 また、DynamoDB と組み合わせると、ロックも可能
リソースの削除
terraform destroy
でリソース削除できます。実行には注意しましょう。
モジュール
Terraform にもモジュール化の仕組みがあります。
モジュールは別ディレクトリにする必要があるので、まずは modules
ディレクトリを 作成します。
そして、モジュールを定義する main.tf
ファイルを作成します。
利用する側を resources
ディレクトリなどにして、そこに環境ごとにpathを切ってmain.tfを置けば
modules
配下のmoduleを環境毎に再利用することも可能になります。
- モジュールの定義
http_server モジュールを実装します。
Apache をインストール した EC2 インスタンスと、80 番ポートを許可したセキュリティグループを定義してみます。
http_server モジュールのインタフェースは次のとおりです。
- 入力パラメータ instance_type
- EC2 のインスタンスタイプ
- 出力パラメータ public_dns
- EC2 のパブリック DNS
variable "instance_type" {} resource "aws_instance" "default" { ami = "ami-0f9ae750e8274075b" vpc_security_group_ids = [aws_security_group.default.id] instance_type = var.instance_type user_data = <<EOF #!/bin/bash yum install -y httpd systemctl start httpd.service EOF } resource "aws_security_group" "default" { name = "ec2" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } output "public_dns" { value = aws_instance.default.public_dns }
- モジュールの利用
モジュール利用側の main.tf ファイルを以下のように実装します。
利用するモジュールは source
に指定します。
module "dev_server" { source = "./http_server" instance_type = "t3.micro" } output "public_dns" { value = module.dev_server.public_dns }
apply はモジュール利用側のディレクトリで実行します。
ただし、モジュールを使用する場合、もうひと手間必要です。
terraform get
コマンドか terraform init
コマンドを実行して、モジュールを事前に取得しておく必要があります。
terraform init
を実行するスクリプトを作成して、circle ciなどを利用してinitで失敗したらbuildが失敗するようにする運用がいいと思う。
GKE + datadogの監視の仕組みをhelmfileを使っての下準備
GKE + datadogの監視をするのにhelmfileを使ってdatadog-agentを入れるのと、 helmfileをCircle CIで回してパッケージ管理の準備までしてしまおうというもの。
Integrationの有効化
Datadogなので、まずはintegrationの有効化 必要に応じてだけど、代替以下
Docker Google Cloud Platform Google Container Engine Google Compute Engine Google CloudSQL Google Cloud Pubsub Google Cloud Storage kubernates
こちら参考 GCPのIntegrationを有効化するために サービスアカウント が必要なので作成しておく。
監視項目
監視したい内容は以下とする
- Kubernetes 上のアプリ/クラスタコンポーネントの監視
種類 | 監視対象 | 監視項目 | 監視方法 (使うメトリクス項目) |
---|---|---|---|
Work metrics | アプリの Pod (web, api, worker) | unavailable な Pod がいないことを確認 | kubernetes_state.deployment.replicas_unavailable |
Work metrics | アプリの Pod (web, api, worker) | Pod が restart loop に陥っていないことを確認 | "CrashLoopBackOff/n分間にn回以上再起動していないかどうか" |
Work metrics | kube-system namespace の Pods | unavailable な Pod がいないことを確認 | |
Work metrics | Kubernetes worker nodes | 全ての node status が Ready であることを確認 | check: kubernetes_state.node.ready |
Work metrics | Kubernetes worker nodes | 全ての node が schedulable であることを確認 | "metrics: kubernetes_state.node.status/tag: status:schedulable == 0" |
Resources metrics | Kubernetes worker nodes | node のリソースのキャパシティに余裕があることを確認 | "kube_node_status_capacity_cpu_cores/kube_node_status_capacity_memory_bytes" |
- GCEインスタンスの監視
種類 | 監視対象 | 監視項目 | 監視方法 (使うメトリクス項目) |
---|---|---|---|
Resources metrics | Kubernetes worker nodes | Keepalive (Connectivity) 監視 | 従来の VM 運用と同じやり方 |
Resources metrics | Kubernetes worker nodes | CPU Usage | 従来の VM 運用と同じやり方 |
Resources metrics | Kubernetes worker nodes | Memory Usage | 従来の VM 運用と同じやり方 |
Resources metrics | Kubernetes worker nodes | Disk Usage | 従来の VM 運用と同じやり方 |
- Datadog Dashboard に出しておきたい項目
項目 | メトリクス |
---|---|
CPU core 使用率 | kubernetes.cpu.usage.total / kubernetes.cpu.capacity |
Memory 使用率 | kubernetes.memory.usage / kubernetes.memory.capacity |
Disk 使用率 | kubernetes.filesystem.usage_pct |
CPU reqests/limits | kubernetes.cpu.requests / kubernetes.cpu.limits |
Mem reqests/limits | kubernetes.memory.requests / kubernetes.memory.limits |
DatadogのAgentの用意
Monitoring Kubernetes with Datadog How to monitor Google Kubernetes Engine with Datadog
datadogの記事をみるとGKEなどのkubernatesをdatadogでモニタリングするには各ノードにdatadog-agentをdeamonsetで常駐させるのが一般的らしい。 Pod間通信でメトリクスを取ってくるようです。
以下のようなものを用意して、 kubectl create -f datadog-agent.yaml
で当てる感じ。
datadogのkubernatesのintegrationのページにも書いてありまする。
TIPS
- DaemonSetのAPIversionはKubernetesバージョン1.9以降の場合は、
apps/v1
を使用 apps/v1
ではspec.selectorが必要になります。- 他のpodからcustom metricsをDogStatsD経由で送信するため、8125/UDPをHost(ノード)に公開します
- Traceの機能も同様に他のpodから使いたいため8126/TCPをHost(ノード)に開ける。
- API_KEYはSecretから取得。作成コマンドは以下参照。
kubectl create secret generic datadog-secret --from-literal=api_key=*****
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: datadog-agent spec: selector: matchLabels: name: datadog-agent template: metadata: labels: app: datadog-agent name: datadog-agent spec: serviceAccountName: datadog-agent containers: - image: datadog/agent:latest imagePullPolicy: Always name: datadog-agent ports: - containerPort: 8125 # Custom metrics via DogStatsD - uncomment this section to enable custom metrics collection # hostPort: 8125 name: dogstatsdport protocol: UDP - containerPort: 8126 # Trace Collection (APM) - uncomment this section to enable APM # hostPort: 8126 name: traceport protocol: TCP env: - name: DD_API_KEY valueFrom: secretKeyRef: name: datadog-secret key: api-key - name: DD_COLLECT_KUBERNETES_EVENTS value: "true" - name: DD_LEADER_ELECTION value: "true" - name: KUBERNETES value: "true" - name: DD_KUBERNETES_KUBELET_HOST valueFrom: fieldRef: fieldPath: status.hostIP - name: DD_APM_ENABLED value: "true" resources: requests: memory: "256Mi" cpu: "200m" limits: memory: "256Mi" cpu: "200m" volumeMounts: - name: dockersocket mountPath: /var/run/docker.sock - name: procdir mountPath: /host/proc readOnly: true - name: cgroups mountPath: /host/sys/fs/cgroup readOnly: true livenessProbe: exec: command: - ./probe.sh initialDelaySeconds: 15 periodSeconds: 5 volumes: - hostPath: path: /var/run/docker.sock name: dockersocket - hostPath: path: /proc name: procdir - hostPath: path: /sys/fs/cgroup name: cgroups
Kubernetesのintegrationをみると manifestを書いて、それにk8sクラスタに当てる必要がある。 manifest管理をどうするかの問題が発生するが、今回はhelmを使ってインストールをする。
helm + helmfileを用いたdatadog-agentインストール
ますhelmとはK8sのパッケージ管理ツール。
リポジトリに登録された構成情報(Chart)を、 installコマンドに適時引数で設定情報を与え、簡単に自分のクラスタに導入(Release)することができる。
そしてhelmfileはk8sクラスタのhelm releasesを管理してくれるもの。
helmfile.yaml
にデプロイしたいhelm Chartを書いて、 helmfile sync
を実行するとインストールやアップグレードを gemfile
のように冪等に管理してくれるもの。
datadog-agentをクラスタに配置する場合は以下のYAMLを書くだけ。
- datadogのhelm chart
prd.values.yaml
にdatadog-apiキーを入れて読み込ませる
releases: - name: datadog namespace: kube-system chart: stable/datadog version: 1.27.2 values: - ./datadog/prd.values.yaml
Circle CIでhelmインストールする
GKEなので、kubectl,helm,helmfileをインストールして、 gcloudコマンドでログインして、クラスタのクレデンシャルとって、helmを当てていく流れ。
以下はCircle CI側の環境変数に入れておく。
COOGLE_CLOUD_REGION
GCLOUD_SERVICE_KEY
GOOGLE_PROJECT_ID
version: 2 defaults: &defaults working_directory: ~/hogehoge docker: - image: google/cloud-sdk:242.0.0-slim global_env: &global_env GOOGLE_PROJECT_ID: hogehoge COOGLE_CLOUD_REGION: asia-northeast1 K8S_CLUSTER: hogehoge common_steps: install_base_packages: &install_base_packages command: apt-get update && apt-get install wget kubectl install_helm: &install_helm name: install helm command: | # install helm wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.1-linux-amd64.tar.gz tar zxvf helm-v2.13.1-linux-amd64.tar.gz mv ./linux-amd64/helm /usr/local/bin/helm helm init --client-only helm plugin install https://github.com/databus23/helm-diff # install helmfile wget https://github.com/roboll/helmfile/releases/download/v0.54.2/helmfile_linux_amd64 chmod +x ./helmfile_linux_amd64 mv ./helmfile_linux_amd64 /usr/local/bin/helmfile gcloud_login: &gcloud_login name: gcloud login command: | echo ${GCLOUD_SERVICE_KEY} | base64 -d | gcloud auth activate-service-account --key-file=- gcloud --quiet config set project ${GOOGLE_PROJECT_ID} setup_cluster_and_helm: &setup_cluster_and_helm name: setup cluster credential and helm environment command: | gcloud beta container clusters get-credentials ${K8S_CLUSTER} --region ${COOGLE_CLOUD_REGION} --project ${GOOGLE_PROJECT_ID} helm repo update jobs: helmfile-sync-dry-run: <<: *defaults environment: <<: *global_env steps: - checkout - run: *install_base_packages - run: *install_helm - run: *gcloud_login - run: *setup_cluster_and_helm - run: name: helmfile diff command: helmfile --file prd.helmfile.yaml diff - run: name: helmfile sync dry-run command: helmfile --file prd.helmfile.yaml sync --args --dry-run helmfile-sync: <<: *defaults environment: <<: *global_env steps: - checkout - run: *install_base_packages - run: *install_helm - run: *gcloud_login - run: *setup_cluster_and_helm - run: name: helmfile sync command: | helmfile --file prd.helmfile.yaml sync workflows: version: 2 dry-run-and-sync: jobs: - helmfile-sync-dry-run: filters: branches: only: /.*/ - helmfile-sync: requires: - helmfile-sync-dry-run filters: branches: only: master
- サービスアカウントを使用してアクセス承認
gcloud
コマンドライン ツールでアクティブなプロジェクトを設定gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
gcloud
は対話型インターフェースなので、自動化には邪魔なので、プロンプトの無効化を--quiet
でする。--quiet
フラグは先頭の項目の右側に挿入する。
- クラスタの認証情報を取得する
gcloud beta container clusters get-credentials [CLUSTER_NAME] [--internal-ip] [--region=REGION | --zone=ZONE, -z ZONE] [GCLOUD_WIDE_FLAG …]
でクラスタに対して認証を行う。- gcloud beta container clusters get-credentialsとは
- Helm CLI を初期設定
helm init --client-only
ちなみにインターネット環境がない場合は--skip-refresh
- helmクライアント側でキャッシュしているので、最新のリポジトリ内の情報を得るために
helm repo update
を実行して、再取得することでキャッシュをリフレッシュさせる。 helm diff
でreleasesのdiffをとるhelmfile diff
サブコマンドは、マニフェストで定義されているすべてのcharts/releases
にわたってhelm-diffプラグインを実行。helmfile --file prd.helmfile.yaml diff
- 使うには helm-diffパッケージが必要。
helmfile --file prd.helmfile.yaml sync --args --dry-run
- Helmfileは実行中にさまざまなイベントをトリガーとする。 イベントが発生すると、argsを指定してコマンドを実行することで、関連するフックが実行される。
helmfile --file prd.helmfile.yaml sync
- helmfile syncサブコマンドは、helmfileの説明に従ってクラスタの状態を同期する。 デフォルトのhelmfileはhelmfile.yaml。任意のyamlファイルを
--file path/to/your/yaml/file
フラグを指定することで渡すことができる。 - helmfileはマニフェストで宣言されたreleaseごとに
helm upgrade --install
を実行。必要に応じて、secretsを復号化してhelmチャートの値として使用する。 また、指定されたチャートリポジトリを更新し、参照されているローカルチャートの依存関係も更新する。 helm upgrade --install
は releaseが存在するかどうかに応じてインストールまたはアップグレードすることができる。
- helmfile syncサブコマンドは、helmfileの説明に従ってクラスタの状態を同期する。 デフォルトのhelmfileはhelmfile.yaml。任意のyamlファイルを
これで、helmで Datadog agent のインストールができる。また、何かhelmで追加したくなったらhelmfileに書いていくことになる。
気になりンゴ
--dry-run
は実はまだ機能追加されてない?helpに特に出てこない。
--args
でhookさせているけど、helmfileにhookさせるものをかかないとhookされないのかな
releases: - name: myapp chart: mychart # *snip* hooks: - events: ["prepare", "cleanup"] command: "echo" args: ["{{`{{.Environment.Name}}`}}", "{{`{{.Release.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\ "]
Creating multi master cluster with kubeadm(ver1.14以上)
前回kubeadmでマルチマスターのクラスタ構築をしたが、kubeadm1.14で証明書の発行と配布がされるようになったので試してみた。
document
https://kubernetes.io/docs/setup/independent/install-kubeadm/ https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ kubeadmのトラブルシューティング
始める前に
- 以下のいずれかを実行している1台以上のマシンを用意
- Ubuntu 16.04+
- CentOS 7
- マシンごとに2 GB以上のRAM(それ以下にすると、アプリケーション用のスペースが狭まる)
- 2 CPU以上
- クラスタ内のすべてのマシン間の完全なネットワーク接続(パブリックまたはプライベートネットワークは問題なし)
- ノードごとに固有のホスト名、MACアドレス、およびproduct_uuid。
- マシンでは特定のポートを開けとく
- スワップ無効(kubeletを正しく動作させるためにスワップを無効にする。)
今回の構成
ホスト名 | 役割 |
---|---|
dev-proxy01 | ロードバランサー(HAProxy) |
dev-master01 | MasterNode |
dev-master02 | MasterNode |
dev-master03. | MasterNode |
dev-worker01 | WorkerNode |
dev-worker02 | WorkerNode |
dev-worker03 | WorkerNode |
クライアントに必要なもの
cfsslとkubectlをインストールする
HAProxyロードバランサーのインストール
3つのKubernetesマスターノードを配置するので、 トラフィックを分散させるためにそれらの前にHAPRoxyロードバランサーを配置する必要がある。
- LBにするサーバにSSHで接続します。
- OS update
$ sudo yum update -y
- HAProxyをインストール
$ sudo yum install haproxy
- 3つのKubernetesマスターノード間でトラフィックを負荷分散するようにHAProxyを設定。
$ sudo vim /etc/haproxy/haproxy.cfg global ... default ... #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend kubernetes bind 10.64.20.226:6443 option tcplog mode tcp default_backend kubernetes-master-nodes #--------------------------------------------------------------------- # static backend for serving up images, stylesheets and such #--------------------------------------------------------------------- backend static balance roundrobin server static 127.0.0.1:4331 check #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend kubernetes-master-nodes mode tcp balance roundrobin option tcp-check server dev-master01 10.64.20.223:6443 check server dev-master02 10.64.20.225:6443 check server dev-master03 10.64.20.222:6443 check
- HAProxyを再起動。
$ sudo systemctl restart haproxy
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg exclude=kube* EOF # Set SELinux in permissive mode (effectively disabling it) setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes systemctl enable --now kubelet
以下は各kubeノードで実行
sudo visudo
で一般ユーザにroot権限を付与
sudo yum -y install vim
Dockerのインストール
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo $ sudo yum install docker-ce docker-ce-cli containerd.io $ sudo systemctl start docker & sudo systemctl enable docker
kubeadmのインストール
まず事前準備として、全ノードで Docker、CLI 等の関連パッケージのインストールと、 クラスタ内で利用するオーバーレイネットワーク用にカーネルパラメータを変更しておきます。
# 必要な依存パッケージのインストール $ sudo yum -y update # リポジトリの登録と更新 $ sudo su - $ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg exclude=kube* EOF # SELinux disabling it) setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config # Kubernetes 関連パッケージのインストール yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes systemctl enable --now kubelet # オーバーレイネットワーク用にカーネルパラメータを変更 # RHEL / CentOS 7の一部のユーザーは、iptablesがバイパスされているために # トラフィックが誤ってルーティングされるという問題を報告しています。 # あなたのnet.bridge.bridge-nf-call-iptables設定で1に設定されていることを確認する必要がある cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system
kubeadmを使ったHAクラスタの作成
クラスターの初期化とkubeadmでTLS証明書を調査する
マスターノードに1台ログインして以下を実行
- ディレクトリを作成
mkdir /etc/kubernetes/kubeadm
kubeadm-configを作成する。
kubernetesVersion
使用するKubernetesバージョンに設定する必要があります。この例ではstable
を使用。controlPlaneEndpoint
ロードバランサのアドレスまたはDNSとポートを一致させる必要があり。kubeadm、kubelet、kubectl
およびKubernetesのバージョンを一致させることがお勧め。- IPはproxyサーバのIPです。
$ vim /etc/kubernetes/kubeadm/kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration kubernetesVersion: stable # REPLACE with `loadbalancer` IP controlPlaneEndpoint: "10.64.20.226:6443" networking: podSubnet: 10.64.0.0/18
- 指定されたupload-certsと設定でクラスタを初期化します。
# kubeadm init \ --config=/etc/kubernetes/kubeadm/kubeadm-config.yaml \ --experimental-upload-certs
この出力をテキストファイルにコピーし。後で他のコントロールプレーンノードをクラスタに参加させるために必要になるのでメモ。
certificate-key
は kubeadm certs secret の復号化を可能にするのでメモ。
You can now join any number of the control-plane node running the following command on each as root: kubeadm join 10.64.20.226:6443 --token ruf1ng.rcjtrdkczkto9t5d \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 \ --experimental-control-plane --certificate-key d54f93a776345163398ec944fc67021517e96f11e3a59fb3d659ba5ab8f60b17
- 利用するユーザで以下を実行。 kubeconfigコマンドを実行する推奨のkubectlアクセス用。
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
- kube-systemネームスペースのkubeadm-certシークレットを調べる。 etcd、kube-apiserver、およびサービスアカウントの証明書が表示されます。
kubectl get secrets -n kube-system kubeadm-certs -o yaml
ownerReferences: - apiVersion: v1 blockOwnerDeletion: true controller: true kind: Secret name: bootstrap-token-6o49ct uid: c6d15490-55b0-11e9-84b0-fa163e4b8c32
kubeadm
で利用可能なトークンリスト一覧を取得する。6o49ct
が上記のステップの所有者参照であることに注意してください。 これは結合トークンではなく、kubeadm-certsでttlを有効にするプロキシです。 参加するときには、依然としてruf1ng
トークンを使用する必要があります。
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 6o49ct.fxxdtesig28iohi5 1h 2019-04-03T12:35:34+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none> ruf1ng.rcjtrdkczkto9t5d 23h 2019-04-04T10:35:35+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
- CNI-plugin である
calico
を 前のconfigで設定したpodSubnet
にマッチする podのCIDRでインストールする。
kubectl apply -f https://gist.githubusercontent.com/joshrosso/ed1f5ea5a2f47d86f536e9eee3f1a2c2/raw/dfd95b9230fb3f75543706f3a95989964f36b154/calico-3.5.yaml
- NodeのSTATUSが
Ready
であることを確認する。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 16m v1.14.0
kube-system
PodがRunningであることを確認する。
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-node-blstp 1/1 Running 0 13m coredns-fb8b8dccf-7nmlh 1/1 Running 0 16m coredns-fb8b8dccf-jr9nc 1/1 Running 0 16m etcd-dev-master01 1/1 Running 0 15m kube-apiserver-dev-master01 1/1 Running 0 15m kube-controller-manager-dev-master01 1/1 Running 0 15m kube-proxy-sz8cz 1/1 Running 0 16m kube-scheduler-dev-master01 1/1 Running 0 15m
2台目のMaster Nodeを追加する
- メモっておいた以下のコマンドを実行する。
kubeadm join 10.64.20.226:6443 --token ruf1ng.rcjtrdkczkto9t5d \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 \ --experimental-control-plane --certificate-key d54f93a776345163398ec944fc67021517e96f11e3a59fb3d659ba5ab8f60b17
- 上のコマンドが完了したあとは、2台目のMaster Nodeがいることを確認する
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 39m v1.14.0 dev-master02 Ready <none> 15m v1.14.0
- ROLESがnoneだったので、LABELを付与
$ kubectl label node dev-master02 node-role.kubernetes.io/master= node/dev-master02 labeled $ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 41m v1.14.0 dev-master02 Ready master 16m v1.14.0
- Podが作成されていることを確認する
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-node-blstp 1/1 Running 0 38m calico-node-vprt5 1/1 Running 0 17m coredns-fb8b8dccf-7nmlh 1/1 Running 0 41m coredns-fb8b8dccf-jr9nc 1/1 Running 0 41m etcd-dev-master01 1/1 Running 0 41m etcd-dev-master02 1/1 Running 0 17m kube-apiserver-dev-master01 1/1 Running 0 41m kube-apiserver-dev-master02 1/1 Running 0 17m kube-controller-manager-dev-master01 1/1 Running 1 40m kube-controller-manager-dev-master02 1/1 Running 0 17m kube-proxy-bdwgx 1/1 Running 0 17m kube-proxy-sz8cz 1/1 Running 0 41m kube-scheduler-dev-master01 1/1 Running 1 40m kube-scheduler-dev-master02 1/1 Running 0 17m
新しいTokenを使って3台目のMaster Nodeを追加
ここで3番目のMaster Nodeを最後のMasterとして追加するが、 最初に既存のkubeadmトークンをすべて削除する。 新規で構築する場合は不要だが、これは、Kubernetesクラスターが既に実行されているときにマスターを追加する方法です。
- まず、動いているMasterから全てのTokenを表示
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 6o49ct.fxxdtesig28iohi5 1h 2019-04-03T12:35:34+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none> ruf1ng.rcjtrdkczkto9t5d 23h 2019-04-04T10:35:35+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
- 全ての存在するTokenを削除 kubeadm-certsシークレットの有効期限が切れて削除されたため、以前に記録されたjoinコマンドは機能しません。 暗号化キーは無効になり、joinトークンは機能しなくなります。
kubeadm token delete 6o49ct.fxxdtesig28iohi5 kubeadm token delete ruf1ng.rcjtrdkczkto9t5d
削除されたことを確認
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
$ kubeadm token create --ttl 10m --print-join-command kubeadm join 10.64.20.226:6443 --token y5hs8z.nu2my2jhq44b74i5 --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
- kubeadm initのupload-certsフェーズを実行。
$ sudo su - # kubeadm init phase upload-certs --experimental-upload-certs [upload-certs] Storing the certificates in ConfigMap "kubeadm-certs" in the "kube-system" Namespace [upload-certs] Using certificate key: d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d
kubeadm join 10.64.20.226:6443 \ --experimental-control-plane \ --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d \ --token y5hs8z.nu2my2jhq44b74i5 \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
以下は出力の抜粋
This node has joined the cluster and a new control plane instance was created: * Certificate signing request was sent to apiserver and approval was received. * The Kubelet was informed of the new secure connection details. * Control plane (master) label and taint were applied to the new node. * The Kubernetes control plane instances scaled up. * A new etcd member was added to the local/stacked etcd cluster. To start administering your cluster from this node, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Run 'kubectl get nodes' to see this node join the cluster.
上の出力にあるように kubectl
コマンドを実行できるようにする
$ kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port? $ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
Master Nodeとして追加されたことを確認
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 80m v1.14.0 dev-master02 Ready master 56m v1.14.0 dev-master03 Ready master 74s v1.14.0
workerノードのクラスタ組み込み
さきほどの kubeadm join
のコマンドを --experimental-control-plane
をつけないで 実行。
1台ずつpodが組み込まれて完了したことを確認してから実行していくこと。
実行したら error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Unauthorized
とエラーが出た。
# kubeadm join 10.64.20.226:6443 --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d --token y5hs8z.nu2my2jhq44b74i5 --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6 387f00b1612b58be6341b7ea451f0939d0 [preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Unauthorized
この場合はTokenの期限が切れていることが原因
[root@dev-master03 ~]# kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS y5hs8z.nu2my2jhq44b74i5 <invalid> 2019-04-03T11:57:38+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token ym6spi.2e7jfvyaqvtg4wce 1h 2019-04-03T13:49:27+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none>
再度作り直す
[root@dev-master03 ~]# kubeadm token delete y5hs8z.nu2my2jhq44b74i5 bootstrap token with id "y5hs8z" deleted [root@dev-master03 ~]# kubeadm token create --ttl 10m --print-join-command kubeadm join 10.64.20.226:6443 --token 9drkxn.oyse1f63s715af4g --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 [root@dev-master03 ~]# kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 9drkxn.oyse1f63s715af4g 9m 2019-04-03T12:48:20+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token ym6spi.2e7jfvyaqvtg4wce 1h 2019-04-03T13:49:27+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none>
作り直したTokenを使用してjoinされることを確認
kubeadm join 10.64.20.226:6443 \ --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d \ --token 9drkxn.oyse1f63s715af4g \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
出力はこんな感じ
[preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.14" ConfigMap in the kube-system namespace [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Activating the kubelet service [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap... This node has joined the cluster: * Certificate signing request was sent to apiserver and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Nodeとして追加されていることを確認
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 131m v1.14.0 dev-master02 Ready master 106m v1.14.0 dev-master03 Ready master 51m v1.14.0 dev-worker01 Ready <none> 6m53s v1.14.0 dev-worker02 Ready <none> 3m54s v1.14.0 dev-worker03 Ready <none> 3m42s v1.14.0
ROLESがnoneなのでworkerと付与してもいい。 こんな感じで。
$ kubectl label node dev-worker01 node-role.kubernetes.io/worker= node/dev-worker01 labeled $ kubectl label node dev-worker02 node-role.kubernetes.io/worker= node/dev-worker02 labeled $ kubectl label node dev-worker03 node-role.kubernetes.io/worker= node/dev-worker03 labeled $ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 158m v1.14.0 dev-master02 Ready master 134m v1.14.0 dev-master03 Ready master 79m v1.14.0 dev-worker01 Ready worker 34m v1.14.0 dev-worker02 Ready worker 31m v1.14.0 dev-worker03 Ready worker 31m v1.14.0
etcdの冗長化はされないので、するなら別にしないとだめ。 みなさんどうされているか、よければおしえてください。
[hoge@dev-master01 ~]$ kubectl get componentstatus NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":"true"}
Terraform and CORS-Enabled AWS API Gateway and AWS WAF
この記事はAWS WAF と API Gateway endpoint で CORS を有効化について。
以下にsampleを載せてあります。
REST API リソースが API 独自のドメイン以外のドメインからリクエストを受け取る場合、 リソースの選択されたメソッドで Cross-Origin Resource Sharing (CORS) を有効にする必要があるので、
CORS 対応のために、今回は以下のレスポンスヘッダーを付与させます。
- Access-Control-Allow-Origin
API Gateway のREST APIの設定
WAFとAPI Gatewayをつなげるので、 endpoint_configuration
の設定が必要になる。
## API Gateway - Rest API resource "aws_api_gateway_rest_api" "rest_api" { name = "${var.env}-${var.name}-api-gateway" description = "${var.env}-${var.name}-api-gateway" minimum_compression_size = 0 endpoint_configuration { types = ["REGIONAL"] } }
API GatewayのResourcesの設定
TerraformのProviderを参考に作成するだけで大丈夫。
## API Gateway - Resources resource "aws_api_gateway_resource" "resource" { depends_on = ["aws_api_gateway_rest_api.rest_api"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" parent_id = "${aws_api_gateway_rest_api.rest_api.root_resource_id}" path_part = "${var.name}" }
API GatewayのMethodの設定
response_models
や response_parameters
をつける以外は
TerraformのProviderを参考に作成するだけで大丈夫。
CORS対応のために Access-Control-Allow-Origin
をレスポンスヘッダに付与させます。
## API Gateway - Method Setting # post resource "aws_api_gateway_method" "method_post" { depends_on = ["aws_api_gateway_resource.resource"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "POST" authorization = "NONE" api_key_required = false request_parameters = { "method.request.querystring.key" = true } } resource "aws_api_gateway_method_response" "method_response_post_200" { depends_on = ["aws_api_gateway_method.method_post"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_post.http_method}" status_code = "200" response_models = { "application/json" = "Empty" } response_parameters { "method.response.header.Access-Control-Allow-Origin" = true } } resource "aws_api_gateway_method_response" "method_response_post_400" { depends_on = ["aws_api_gateway_method.method_post"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_post.http_method}" status_code = "400" response_models = { "application/json" = "Empty" } response_parameters { "method.response.header.Access-Control-Allow-Origin" = true } }
API GatewayのIntegrationの設定
- ハマりポイント
selection_pattern
が必要aws_api_gateway_integration_response
はaws_api_gateway_method_response
に依存する。
## API Gateway - Integration Setting resource "aws_api_gateway_integration" "integration_post" { depends_on = ["aws_api_gateway_method.method_post"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_post.http_method}" integration_http_method = "POST" type = "HTTP" uri = "${var.url}" } resource "aws_api_gateway_integration_response" "integration_response_post_200" { depends_on = ["aws_api_gateway_method_response.method_response_post_200"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_post.http_method}" status_code = "${aws_api_gateway_method_response.method_response_post_200.status_code}" selection_pattern = "200" response_templates = { "application/json" = "" } response_parameters = { "method.response.header.Access-Control-Allow-Origin" = "'*'" } } resource "aws_api_gateway_integration_response" "integration_response_post_400" { depends_on = ["aws_api_gateway_method_response.method_response_post_400"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_post.http_method}" status_code = "${aws_api_gateway_method_response.method_response_post_400.status_code}" selection_pattern = "4\\d{2}" response_templates = { "application/json" = "" } response_parameters = { "method.response.header.Access-Control-Allow-Origin" = "'*'" } }
API Gateway では、Mock 統合タイプで OPTIONS
メソッドを設定して CORS を有効にし、
前述のレスポンスヘッダーをメソッドのレスポンスヘッダーとして返す。
200 レスポンスで Access-Control-Allow-Origin:'*request-originating server addresses*'
ヘッダーを返すようにすること。
特定の request-originating server addresses
の静的な値を *
に置き換えることもできるけど
広範なサポートを有効にすることはよく考えること。任意のサーバーを指定可能なのでできるならその方がよいので。
今回では *
をつけています。
今回はMock統合タイプでbackendがGoogle Formを例にしている。
Access-Control-Allow-Origin
を設定すれば CORS
は有効化できます。
- ハマりポイント
OPTIONS
メソッドを使用するのを忘れないselection_pattern
が必要aws_api_gateway_integration_response
はaws_api_gateway_method_response
に依存する。
# options resource "aws_api_gateway_method" "method_options" { depends_on = ["aws_api_gateway_resource.resource"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "OPTIONS" authorization = "NONE" api_key_required = false request_parameters = { "method.request.querystring.key" = true } } resource "aws_api_gateway_method_response" "method_response_options_200" { depends_on = ["aws_api_gateway_method.method_options"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_options.http_method}" status_code = "200" response_models = { "application/json" = "Empty" } response_parameters { "method.response.header.Access-Control-Allow-Origin" = true } } resource "aws_api_gateway_method_response" "method_response_options_400" { depends_on = ["aws_api_gateway_method.method_options"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_options.http_method}" status_code = "400" response_models = { "application/json" = "Empty" } response_parameters { "method.response.header.Access-Control-Allow-Origin" = true } } resource "aws_api_gateway_integration" "integration_options" { depends_on = ["aws_api_gateway_method.method_options"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_options.http_method}" integration_http_method = "OPTIONS" type = "MOCK" } resource "aws_api_gateway_integration_response" "integration_response_options_200" { depends_on = ["aws_api_gateway_method_response.method_response_options_200"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_options.http_method}" status_code = "${aws_api_gateway_method_response.method_response_options_200.status_code}" selection_pattern = "200" response_templates = { "application/json" = "" } response_parameters = { "method.response.header.Access-Control-Allow-Origin" = "'*'" } } resource "aws_api_gateway_integration_response" "integration_response_options_400" { depends_on = ["aws_api_gateway_method_response.method_response_options_400"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" resource_id = "${aws_api_gateway_resource.resource.id}" http_method = "${aws_api_gateway_method.method_options.http_method}" status_code = "${aws_api_gateway_method_response.method_response_options_400.status_code}" selection_pattern = "4\\d{2}" response_templates = { "application/json" = "" } response_parameters = { "method.response.header.Access-Control-Allow-Origin" = "'*'" } }
- ハマりポイント
aws_api_gateway_deploymen
とaws_api_gateway_stage
は両方必要ない (stage-nameがconflict する)。こちら参照)
## API Gateway - Deployment resource "aws_api_gateway_deployment" "deployment_200" { depends_on = [ "aws_api_gateway_integration.integration_post", "aws_api_gateway_integration_response.integration_response_post_200", ] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" stage_name = "${var.env}" } resource "aws_api_gateway_method_settings" "method_settings_200" { depends_on = ["aws_api_gateway_deployment.deployment_200"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" stage_name = "${var.env}" method_path = "*/*" settings { metrics_enabled = true logging_level = "INFO" } } resource "aws_api_gateway_deployment" "deployment_400" { depends_on = [ "aws_api_gateway_integration.integration_post", "aws_api_gateway_integration_response.integration_response_post_400", ] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" stage_name = "${var.env}" } resource "aws_api_gateway_method_settings" "method_settings_400" { depends_on = ["aws_api_gateway_deployment.deployment_400"] rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}" stage_name = "${var.env}" method_path = "*/*" settings { metrics_enabled = true logging_level = "INFO" } }
WAFのRuleはIP制限。
同一IPアドレスから5分間に2000(最低値)を超えたリクエストをトリガー。
WAF ResourcesではなくWAF Regional Resoucesを使う必要がある。
- ハマりポイント
metric_name
は英数字のみなので-
などは使わない。こちら参照)
## WAF RULE resource "aws_wafregional_rate_based_rule" "wafrule" { name = "${var.env}-bov-form-protect-dos-rule" metric_name = "${var.env}bovrule" rate_key = "IP" rate_limit = 2000 }
WAF RULEに該当したらBLOCKさせる設定をする。
aws_wafregional_web_acl_association) ではまだ ALB
しか公式サポートしていないようだけど、
WAFとAPI Gatewayの繋ぎこみの設定は web_acl_id
とresource_arn
を書くことで可能。
resource_arn
の書き方は AWSドキュメンテーションなど参照)
もしくはAssociateWebACLのドキュメンテーション)
- ハマりポイント
wafregional_ipset
はALBで使うproviderで今回はIP指定もないので使わない。こちら参照)aws_wafregional_ipset
の変わりにaws_wafregional_rate_based_rule
を使用する
## WAF_ACL rate_based block over 2000 access resource "aws_wafregional_web_acl" "wafacl" { name = "${var.env}-bov-form-protect-dos-acl" metric_name = "${var.env}BovFormAccess" default_action { type = "ALLOW" } rule { action { type = "BLOCK" } priority = 1 rule_id = "${aws_wafregional_rate_based_rule.wafrule.id}" type = "RATE_BASED" } } resource "aws_wafregional_web_acl_association" "wafassosiation" { depends_on = ["aws_wafregional_web_acl.wafacl"] resource_arn = "arn:aws:apigateway:ap-northeast-1::/restapis/${aws_api_gateway_rest_api.rest_api.id}/stages/${var.env}" web_acl_id = "${aws_wafregional_web_acl.wafacl.id}" }
AWS構築[Cloudfront+ELB+WEB+DB+S3]
AWSなれるために2018年ごろに手でポチポチ構築したときのメモ なので今は設定画面とか変わっているものがありそう [Cloudfront+ELB+WEB+DB+S3] 構成。 ほとんどの場合、Terraformで構築すると思うけど、 その前のAWS入門として一応残しておきます。
仕様と構成
サブネット構成
名前タグ | VPC | AZ | IPv4 CIDR ブロック |
---|---|---|---|
subnet-hogehoge-training-ssh | hog | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hogehoge-training-web01 | training | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hogehoge-training-web02 | training | ap-northeast-c | 172.31.hoge.0/24 |
subnet-hogehoge-training-db01 | training | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hogehoge-training-db02 | training | ap-northeast-c | 172.31.hoge.0/24 |
IAMロール
- IAMロール名
- hoge-training
- 権限
- EBSスナップショット
- S3ファイルアップロード権限
S3
サーバ構成
踏み台
- OS
- CentOS7(AWS Marketplaceから)
- インスタンス対応
- t2.micro
- サブネット
- subnet_ssh
- 自動割当パブリックIP
- 有効化
- プライベートIPアドレス
- 172.31.hoge.10
- ディスク
- 初期値を利用
- ボリュームタイプは汎用SSD(GP2)
- タグ
- セキュリティグループ
- キーペア
- 新規作成
- EIP
- 必要
- ホスト名
web
- OS
- CentOS7(AWS Marketplaceから)
- インスタンス対応
- t2.micro
- サブネット
- 自動割当パブリックIP
- 有効化
- プライベートIPアドレス
- ディスク
- 初期値を利用
- ボリュームタイプは汎用SSD(GP2)
- タグ
- セキュリティグループ
- キーペア
- 新規作成
- EIP
- 不要
- ホスト名
- ミドルウェア
ELB(ALB)
- 名前
- hoge-training-elb
- セキュリティグループ
- セキュリティグループ名:hoge-training-elb
- ルーティングの設定
- ターゲットグループ名:hoge-training-elb
- ターゲットの登録
- webサーバ2台を登録
RDS(MySQL)
- サブネットグループの作成
- hoge-training-db
- 開発/テストを洗濯
- DBエンジンのバージョン
- 最新版を選択
- DBインスタンスの選択
- db.t2.micro
- マルチAZ配置
- はい
- DBインスタンス識別子
- hoge-training-db
- マスターユーザの名前
- root
- パスワード
- VPC
- training
- サブネットグループ
- パブリックアクセス可能
- いいえ
- VPCセキュリティグループ
- タグ名: hoge-training-db
- インバウンドルールの編集: webサーバのsubnetからのみ3306のアクセス許可
- データベース名
- hoge_training_db
- バックアップウィンドウ
- 開始時間20:00UTF
- マイナーバージョン自動アップグレード
- いいえ
- メンテナンスウィンドウ
- 開始日時:日曜日の21:00UTF
CloudFront
S3参照
- logoの画像
/image/
配下は300秒キャッシュ(http://hoge-training.<ドメイン>/image/)
- logo以外
/js/
,/css/
配下は600秒キャッシュ(http://hoge-training.<ドメイン>/js/),(http://hoge-training.<ドメイン>/css/)
- それ以外はキャッシュさせない
- 他のパラメータ値は気にしない
Route53
hoge-trainigをサブドメインとして<ドメイン>に登録
流れ
- hoge-training.<ドメイン> にアクセスするとサイト表示閲覧可能にする。
- ELB から 2 台に振り分けられている状態
- index.html を設置
- RDS 作成
- web サーバから mysql コマンドで接続可能
- CloudFront の設定
- プログラムの作成
手順
IAMロールの作成
ロールは永続的な権限(アクセスキー、シークレットアクセスキー)を保持するユーザーとは異なり、 一時的にAWSリソースへアクセス権限を付与する場合に使用します。
- AWSリソースへの権限付与
- EC2上で稼働するアプリに一時的にAWSのリソースへアクセスする権限を与えたい場合
- EC2作成時にロールを付与することで可能
- [AWS]IAMロールをEC2インスタンスに設定(アタッチ)してみたで、既存のインスタンスにもアタッチ可能
- クロスアカウントアクセス
- 複数のAWSアカウント間のリソースを1つのIAMユーザアカウントで操作したい
- IDフェデレーション
- WEB IDフェデレーション
AWSコンソールのIAM→ロール→ロールの作成
EC2インスタンスだけがそのロールを取得することができるポリシーを選択
次のステップ:アクセス権限
をクリック
ポリシーの作成
をクリック
後述の IAMポリシーの付与
に飛びます。
IAMユーザとグループ
今回は使わないがロールではなくユーザとグループを作成してポリシーを付与するのは以下手順
AWSコンソールのIAM→ユーザ→ユーザを追加
IAMユーザにアクセス権限を設定する場合、ユーザーに直接ポリシー付与する方法と、ポリシー付与したグループを作成して、ユーザーをグループに所属させる方法がある。
基本的にはIAMグループに対して、アクセス権限を設定するようにする。
グループの名前も管理者であることが想像できるものにするのがよい。
- ユーザ名
- hoge-training
- AWSアクセスの種類を選択
- アクセスの種類:プログラムによるアクセス、AWSコンソールへのアクセス
- カスタムパスワード:*********
- パスワードのリセットが必要
- ユーザをグループに追加で
グループの作成
をクリック - グループ名
hoge-training
入力してグループの作成
をクリック - ポリシーの付与はのちほど行うので
次のステップ:確認
をクリック ユーザーの作成
をクリック
これでIAMユーザーが作成されました。
作成結果の画面にアクセスキーIDとシークレットアクセスキーが表示されていますので、
忘れずに控えておきましょう。
.csvのダウンロード
をクリックすると、アクセスキー情報が記載されたCSVファイルをダウンロードできます、
後からアクセスキーの作成は可能だが、同じアクセスキーは二度とダウンロードできないので注意。
アクセスキーを不特定多数が閲覧可能な場所には置かないこと。Githubとか...
アクセスキーを入手したら 閉じる
をクリックしてIAMのユーザー画面に戻る。
IAMポリシーの付与
作成したIAMユーザにアクセス権限を設定 アクセス権限はIAMポリシーで管理されます。 ポリシーには管理ポリシーとインラインポリシーの2種類があります。
- 管理ポリシー
- インラインポリシー
- 特定のIAMユーザ、IAMグループ、IAMロールに直接付与されるポリシー
- 基本的には管理ポリシーを使うので、インラインポリシーが付与されることはあまりない。
- 管理ポリシーはそのポリシーを適用している全ユーザ、グループ、ロールに影響があるので、特定のユーザのみに付与したい場合などはインラインポリシーを使う
ポリシーはJSON形式で記述します。
権限を以下のみにしたいので参考記事を参照しつつ設定してください。
- EBSスナップショット
- S3ファイルアップロード権限
参考記事
Review policy
をクリックし、ポリシー名と説明を記入し、 Create policy
をクリック
次にアクセス権限ポリシーをロールにアタッチさせます。
対象のポリシーを選択し、 次のステップ:確認
をクリック
ロール名とロールの説明を入力し、 ロールの作成
をクリック
EC2で対象のインスタンスを選択し、 アクション→インスタンスの設定→IAMロールの割り当て/置換
をクリックし,アタッチしたいポリシーを選択。
サブネットの作成
サブネットは大きなネットワークを複数の小さなネットワークに分割して管理する歳の、管理単位となるネットワーク ELBを作成する予定があるサブネットは余裕を持って、「/24」(256IPアドレス以上)のネットワーク範囲で作成することが推奨 なぜなら、ELB作成時でELBを作成するサブネットに20IPアドレス以上の空きが必要になるため、「/28」(16IPアドレス)で作成したサブネットにはELBを作成することができないため。
AWSコンソールで VPC→サブネット→サブネットの作成
から以下の条件でサブネットを作成する
名前タグ | VPC | AZ | IPv4 CIDR ブロック |
---|---|---|---|
subnet-hoge-training-ssh | training | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hoge-training-web01 | training | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hoge-training-web02 | training | ap-northeast-c | 172.31.hoge.0/24 |
subnet-hoge-training-db01 | training | ap-northeast-b | 172.31.hoge.0/24 |
subnet-hoge-training-db02 | training | ap-northeast-c | 172.31.hoge.0/24 |
踏み台とWEBは- 自動割当パブリックIPを有効化にしたいので、
サブネットのアクション
タブの自動割り当てIP設定の変更
から有効化します。
EC2作成
AWS操作用の公開鍵・秘密鍵の作成
EC2では公開鍵暗号方式でろログインをします。
EC2→キーペア→キーペアの作成
でキーペアを作成します。
作成したキーペアは作成したタイミングでしかダウンロードできないので注意。
- AWSコンソールからEC2を選択
- EC2ダッシュボードからキーペアを選択
- キーペアの作成をクリック
- キーペア名に作成するキーペアの名前を入力
- 作成をクリック
- pem形式のファイルをダウンロードします。
権限は600
にします。
$ chmod 600 hoge.pem
セキュリティグループを作成
セキュリティグループはホワイトリスト方式なので「何を許可するのか」のみ指定可能 また、セキュリティグループはVPCごとの設定になります。
AWSコンソールのEC2→セキュリティグループ→セキュリティグループの作成
からインバウンド(内部への通信)
で以下の条件で作成
- 踏み台
- WEB
- ELB
- DB
EC2作成・起動
AWSコンソールのEC2→インスタンス→インスタンスの作成
から作成していく
- AMIの選択
AWS Marketplace からCentOS7を選択
- インスタンスタイプの選択
t2.micro
- 詳細設定
ネットワークで対象のVPCを選択 サブネットはそれぞれのものを選択 自動割り当てパブリック IPは有効化 ネットワークインターフェイスのプライマリIPで以下のを指定 - ssh - 172.31.hoge.10 - web01 - 172.31.hoge.10 - web02 - 172.31.hoge.10
ストレージの追加
初期値を利用
ボリュームタイプは汎用SSD(GP2)
タグの追加
Name:hoge-training-ssh Name:hoge-training-web01 Name:hoge-training-web02
- セキュリティグループの設定
既存のセキュリティグループを選択
EIP
AWSコンソールのEC2→Elastic IP→新しいアドレスの割り当て
でElasticIPを作成
次にアクション→アドレスの関連付け
で踏み台のインスタンスとプライベートIPを選択を選択し関連付けをおす。
ELBの作成
AWSコンソールのEC2→ロードバランサー→ロードバランサーの作成
をクリック。
ALBのHTTP(S) で作成。
名前:hoge-training-elb リソースはHTTPのみ アベイラビリティーゾーン:VPCと登録するEC2インスタンスを含むAZを選択 タグ:Name,hoge-training-elb
次の手順:セキュリティ設定の構成
を選択
以下のエラーが出るが気にせず、進む。
ロードバランサーのセキュリティを向上させましょう。ロードバランサーは、いずれのセキュアリスナーも使用していません。 ロードバランサーへのトラフィックを保護する必要がある場合は、フロントエンド接続に HTTPS プロトコルをお使いください。 最初のステップに戻り、基本的な設定 セクションでセキュアなリスナーを追加 / 設定することができます。または現在の設定のまま続行することもできます。
ステップ 3: セキュリティグループの設定
では既存のセキュリティグループを選択する
で既に作成したセキュリティグループを選択
ステップ 4: ルーティングの設定
のターゲットグループ
では名前だけ入力
名前:ELBTARGET
ステップ 5: ターゲットの登録
で追加したいEC2インスタンスを選択して、登録済みに追加
をクリック
登録済みに追加
されたら次の手順:確認
を選択
ステップ 6: 確認
で問題なければ作成
ELBの動作確認
webサーバにcentosをインストール
# yum -y install httpd # systemctl list-unit-files -t service |grep httpd httpd.service disabled # systemctl enable httpd.service Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service. # systemctl list-unit-files -t service |grep httpd httpd.service enabled # systemctl start httpd.service
ELBのDNS名をブラウザに入力してindex.html
の中身が表示されることを確認
ターゲットグループのターゲットから両インスタンスがhealthy
になることを確認
Route53の設定
ホストゾーンドメイン
は既にあるものなどを使い、
hoge-trainigをサブドメインとして ドメイン
に登録する。
ホストゾーンはそのドメインのリソースレコードセットの集合です。
Route53→Hosted zones
からドメイン
を選択
Create Record Set
を選択
Name:hoge-training
Type:Aレコード(IPv4)
Value:Alias:Yes
Alias Target:ELBのDNS名
Routing Policy:Simple
のちにAliasをCloudFrontに変更します。
RDS 作成
VPC上にRDSインスタンスを起動する場合、DBサブネットグループを作成する必要があるので まずはサブネットグループを作成します。
RDS→サブネットグループ→DBサブネットグループの作成
を選択
サブネットグループの詳細
名前:hoge-training
説明:middle engineer training ozawa subnet
VPC:trainingのVPCを選択
サブネットの追加でアベイラビリティーゾーン
とサブネット
RDS→インスタンス→DBインスタンスの起動→MySQL
を選択
DB詳細の指定
- 開発/テストを選択
- DBエンジンのバージョン
- 最新のバージョン
- DBインスタンスの選択
- db.t2.micro
- マルチAZ配置
- 別のゾーンにレプリカを作成します
- DBインスタンス識別子
- hoge-training-db
- マスターユーザの名前
- root
- パスワード
[詳細設定]の設定 ネットワーク&セキュリティ
- VPC
- training
- サブネットグループ
- hoge_training
- パブリックアクセシビリティ
- いいえ
- アベイラビリティーゾーン
- 指定なし
- VPCセキュリティグループ
- タグ名: hoge-training-db
データベースの設定
- データベースの名前
- hoge_training_db
- データベースのポート
- 3306
- DBパラメータグループ
- デフォルト
- オプショングループ
- デフォルト
- IAM DB 認証
- 無効化
暗号化
- 無効化(無料利用枠ではデフォルトで無効)
バックアップ
- バックアップの保存期間
- 1日
- バックアップウィンドウ
- 開始時間20:00UTF期間0.5時間
- タグをスナップショットへコピー - チェック
モニタリング
- 拡張モニタリング
- 有効
- モニタリングロール:デフォルト
- 60秒
ログのエクスポート
- 監査ログ
- 有効
- エラーログ
- 無効
- 全般ログ
- 有効
- スロークエリログ
- 有効
メンテナンス
- マイナーバージョン自動アップグレード
- 無効化
- メンテナンスウィンドウ
- 開始日時:日曜日の21:00UTF期間0.5時間
DBインスタンスの作成
で作成完了
webサーバにmysqlクライアントをインスタンス RDSインスタンスからエンドポイントを確認
# yum install mysql -y # mysql -u root -h エンドポイント名 -p
S3
hoge-training.<ドメイン>
でバケットを作成します。
S3→バケットを作成する
で作成します。
{ "Version": "2012-10-17", "Id": "PublicRead", "Statement": [ { "Sid": "ReadAccess", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::hoge-training.<ドメイン/*" } ] }
プロパティの設定およびアクセス許可の設定はデフォルトのまま進めます。
CloudFrontの設定
CloudFrontはAWSのCDNサービスです。 CDNとはコンテンツを配信するために最適化されたネットワークのことです。 分散して配置されたサーバからコンテンツを配布することで効率的にコンテンツを配信する仕組み。
CloudFrontはAWSが世界中に配置したエッジサーバを利用して効率的にコンテンツを配信します。 エッジサーバはCloudFrontのコンテンツの配布ポイントでユーザーのアクセスを最も近くにあるエッジサーバに誘導します。 「xxx.cloudfront.net」というドメインにアクセスすると、最も近いエッジサーバのIPアドレスが返されます。 CloudFrontではコンテンツの配信元のサーバをオリジンサーバと呼びます。 CloudFrontを利用していない場合は、全てのアクセスがオリジンサーバにいくが、 利用するとオリジンサーバに到達する前に、エッジサーバがコンテンツを返す。 そのため、オリジンサーバの負荷を下げることができ負荷分散としても大きな意味があります。 なのでEC2やS3等コンテンツを配信するサーバの前には、なるべくCloudFrontを配置するべき。
エッジロケーションはエッジサーバが存在する地域で、日本では東京と大阪にある。
CloudFront→Create Distribution
をクリック
- コンテンツの配信方法の選択
HTTP[S]で表示するWEBコンテンツの配信なのでWEBを選択します。
- Distributionの設定
OriginSettingでオリジンサーバの設定をします。
今回CloudFrontはS3とALBの前に設置するので、
Origin Domain Name
にS3とALBを選択して入力することになります。
- Origin Domain Name
- Behaviors
- /image/* 300 秒キャッシュ
- Origin Domain Name
- hoge-training-elb-1353485913.ap-northeast-1.elb.amazonaws.com
Behaviors
- /js/* 600 秒キャッシュ
- /css/* 600 秒キャッシュ
- Default (*)
Distributionの設定(Origin Settings)
オリジンサーバの設定をする
設定項目 | 値 | 説明 |
---|---|---|
Origin Domain Name | S3バケットのエンドポイント | オリジンサーバのドメインを入力 |
Origin Path | 値なし | CloudFrontへのリクエストをオリジンサーバの特定のパスにルーティングしたい場合に設定。 |
Origin ID | 任意の名前 | このDistributionを区別するための名前を設定 |
Restrict Bucket Access | No | オリジンがS3の場合のみ有効。S3バケットのコンテンるへのアクセスをCloudFrontからのみに制限する場合はYes。直接エンドポイントにアクセスできるようにするならNo |
Origin Custom Headers | 値なし | リクエストをオリジンサーバに転送する際のヘッダーを指定 |
- Default Cache Behavior Setting
キャッシュの動作の設定をする
設定項目 | 値 | 説明 |
---|---|---|
Path Pattern | Default(*) | キャッシュを有効にするパスのパターンを指定。 |
Viewer Priticol Policy | HTTP and HTTPS | コンテンツにアクセスする際にどのプロトコルを使用するか選択 |
Allowed HTTP Methods | GET,HEAD | エンドユーザーに許可するHTTPメソッドを選択 |
Field-level Encryption Config | 値なし | 特定のデータフィールドにフィードレベル暗号化を適用する場合に指定 |
Cached HTTP Methods | GET,HEAD | CloudFrontでのキャッシュが有効になるHTTPメソッドを選択 |
Cached Based on Selected Request Headers | None | CloudFrontがオリジンサーバに転送するリクエストヘッダーの指定とヘッダー値に基づいてオブジェクトをキャッシュするかの設定を行う。 |
Object Caching | Use Origin Cache Headers | CloudFrontがキャッシュを保持する時間の設定。オリジンサーバで追加したCache-COntorolの時間に応じてキャッシュを保持する場合は、今回の値を設定する。 |
Minimum TTL | 0 | キャッシュの最小保持期間 |
Maximum TTL | 31536000 | キャッシュの最大保持期間 |
Default TTL | 86400 | キャッシュのデフォルトの保持期間 |
Foward Cookied | None | CloudFrontからオリジンサーバに転送するCookieを指定。オリジンがS3のときは無効。 |
Query String Fowarding and Caching | None | クエリ文字列に基づいてキャッシュを行う |
Smooth Streaming | No | Microsoftスムーズストリーミング形式のメディアファイルを配信する場合はYES |
Restrict Viewer Access | No | 署名付きURLを利用するかの選択 |
Compress Objects Automatically | No | ファイルを自動的に圧縮する |
Lambda Function Assopciations | 値なし | トリガーを追加するLambda関数のARNを指定 |
- Distribution Setting
Distributionの詳細を設定
設定項目 | 値 | 説明 |
---|---|---|
Price Class | Use ALL Edge Locations | 価格クラスを選択。 |
AWS WAF Web ACL | None | AWS WAFを使用する場合にウェブACLを選択する・ |
Alternate Domain Names | 値なし | 独自ドメインを利用する場合に設定 |
SSL Certificate | Default CloudFrint Cerificate | DefaultではCloudFrontにデフォルトで用意されている証明書を利用する。 |
Supported HTTP Versions | HTTP/2,HTTP/1.1,HTTP/1.0 | CloudFrontとの通信に使用するHTTPバージョンを指定 |
Default Root Object | index.html | デフォルトのルートオブジェクトを設定 |
Logging | OFF | ログを取得するか設定 |
Bucket for Logs | 値なし | ログを配置するS3のバケットを選択 |
Log Prefix | 値なし | ログファイル名の戦闘につける文字列を指定 |
Cookie Logging | off | ログにCookieも記録するか選択 |
Enable IPv6 | 有効 | IPv6を有効にするか選択 |
Comment | 値なし | 入力は任意。 |
Distribution State | Enabled | Distributionの使用準備が整ったあと、自動的にこのDistributionを有効にするか選択 |
Deployedになったら、Domain Nameに表示されている「****.cloudfront.net」にアクセスすればS3のコンテンツが表示されます。
- Route53との連系
Route53にCLoudFrontのエンドポイントを設定することで、独自ドメインでCloudFrontを利用することができます。 作成したDistributionを選択し、Distribution Settingをクリック。 GeneralタブのEditで編集画面に行き、Alternate Domain Namesに設定したい独自ドメインを入力する。
次にRoute5→Hotsted Zonesから使用する独自ドメインのホストゾーンを選択し、Aliasレコードを追加する。
確認項目
セキュリティ
RDS
- 手動フェイルオーバを行なう
- AZ が切り替わっていることを確認
- サービスが閲覧できることを確認
S3
- web サーバから aws コマンドを利用してS3 のバケットにテストファイルをアップロードする
- S3 のバケットから aws コマンドを利用してテストファイルをダウンロードする
- 踏み台からは S3 操作が不可であることを確認する
EBS
- web サーバから aws コマンドを利用して、EBS スナップショットを取得する
- 踏み台からは EBS スナップショット取得が出来ないことを確認
サイト表示
- yourname-training.<ドメイン> 画面表示が正常であることを確認
- web01, web02 に分散されていることを確認
- web01 を ELB から切り離しても正常に閲覧できることを確認
- image 配下へのアクセス
- S3 へアクセスが行っていることを確認
- js, css 配下へのアクセス ELB を経由していることを確認
- キャッシュ時間に応じてキャッシュされていることを確認
上記以外
- ELB を経由していることを確認
- キャッシュされていないことを確認