なになれ

IT系のことを記録していきます

AWSとTerraformでKubernetesを学ぶ本を書いたので1章をまるっと公開します

この記事は、Kubernetes3 Advent Calendar 2020の25日目の投稿です。
最近AWSとTerraformを使ってKubernetesを学ぶ本を書きました。
本記事では、その内容をただ載せるだけの楽をしてしまっています。すみません。ただの宣伝です。
興味を持った方は、明日から販売開始となりますので、下記より購入して頂ければと思います。

techbookfest.org

1章の内容のほかには、ALBとの連携によるサービスの外部公開、オートスケーリングの実現、Argo CDによるデプロイの実装、監視、運用などの内容を盛り込んでいます。

それでは、1章をまるっと公開します。

第1章 セットアップ

本章では、AWSとTerraformを使って、Kubernetes環境を構築します。AWSでは、Amazon EKS(以降、EKS)を使うと、マネージドなKubernetes環境を作成できます。TerraformでEKSのリソースを作るのに、Terraform公式のモジュールレジストリにあるterraform-aws-eks*1を利用します。

Terraformを使うにはAWS CLI*2が必要になります。本書では、すでにAWS CLIをインストールしているものとします。

1.1 Terraform

本節では、Terraformのセットアップを行い、Terraformを使ってAWSのリソースを作成、削除できることを確認します。TerraformをAWSで使うには、Terraform用のIAMユーザーを作成し、アクセスキーを発行します。そのアクセスキーをAWS CLIに設定するとTerraformからAWSを操作できます。

1.1.1 セットアップ

TerraformからAWSのリソースを操作できるように、Terraformのセットアップを行います。

AWSのマネージメントコンソールのIAMからユーザーを作成します(図1.1)。

f:id:hi1280:20201222221747p:plain

図1.1: IAMの画面

User nameを入力します。Programmatic accessをチェックして、Nextをクリックします(図1.2)。

f:id:hi1280:20201222221735p:plain

図1.2: IAMユーザーの設定

Attach existing policies directlyを選択します。AdministratorAccessをチェックし、Nextをクリックします(図1.3)。

f:id:hi1280:20201222221730p:plain

図1.3: IAMポリシーの設定

タグは追加せず、Nextをクリックします。Create userをクリックします(図1.4)。

f:id:hi1280:20201222221744p:plain

図1.4: 確認画面

アクセスキーが表示されます(図1.5)。

f:id:hi1280:20201222221750p:plain

図1.5: アクセスキーの表示

このあとに使用するため、Access key IDとSecret access keyをコピーしておきます。

AdministratorAccessは、AWSにおいて管理者権限となるIAMポリシーです。何でもできてしまう権限のため、アクセスキーの扱いには注意が必要です。

次のコマンドで、AWS CLIの設定を行います。設定を行うには、aws configureを利用します。本書では、すでにAWS CLIをインストール済みとしています。

$ aws configure
AWS Access Key ID [None]: AKIAXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json

AWS Access Key IDとAWS Secret Access Keyにコピーしておいたアクセスキーを入力します。

次のコマンドで、Terraformのインストールを行います。macOSではbrew*3が利用できます。

$ brew install terraform

本書では、Terraformのバージョンv0.13.5を使用しています。

次のとおりに、terraformを実行してUsageの出力が行われれば、正常にインストールされています。

$ terraform
Usage: terraform [-version] [-help] <command> [args]
...

1.1.2 基本操作

TerraformでAWSリソースを作成、削除できるか一連の操作を行います。これ以降の説明では、Terraformを使用してAWSリソースを作成しますので、ここで説明するTerraformの基本操作を理解するようにしてください。

terraform init

Terraformでは、作業用のディレクトリを用意して、初期化を行います。次のようにディレクトリを用意します。

$ mkdir example
$ cd example

exampleディレクトリにmain.tfファイルを用意し、リスト1.1のようにコードを書きます。

リスト1.1: main.tf

provider "aws" {
  region  = "ap-northeast-1"
}

resource "aws_instance" "example" {
  ami           = "ami-0ce107ae7af2e92b5"
  instance_type = "t3.micro"
}

リスト1.1は、EC2インスタンスを作成するTerraformのコードになります。

Terraformのtfファイルが用意できたら、terraform initを実行して、Terraform用の実行ディレクトリとしてexampleディレクトリをセットアップします。

$ terraform init

terraform initによって、AWSを扱うためのProviderというプログラムがダウンロードされて、TerraformでAWSを操作できます。

terraform plan

自身のAWS環境に対して、TerraformがどのようにAWSリソースを作成するのかを確認します。terraform planを実行すると、次のように、どのAWSリソースに変更があるかを把握できます。

$ terraform plan
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

terraform planの出力結果にある「+」マークはリソースを作成することを表しています。「resource "aws_instance"」とあるので、EC2インスタンスを作成する計画だと分かります。

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      ...
    }

terraform apply

実行計画が確認できたら、次に、Terraformを使ってAWSリソースを作成します。terraform applyを実行すると、あらためてplanの結果が表示され、実行するか確認が行われます。

$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.example will be created
  + resource "aws_instance" "example" {
      ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

terraform applyの実行結果の最後に「Enter a value:」と出力され、「yes」を入力すると、EC2インスタンスが作成されます。

  Enter a value: yes

aws_instance.example: Creating...

最後に次のように出力されれば成功です。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

実際にEC2インスタンスが作成されているかをAWSマネージメントコンソールで確認します。AWSマネージメントコンソールからEC2の画面を表示すると、作成したインスタンスを確認できます(図1.6)。

f:id:hi1280:20201222221741p:plain

図1.6: EC2インスタンス作成確認

terraform destroy

Terraformを使って、作成したリソースを削除して、元の状態に戻します。そのためには、terraform destroyを実行します。

$ terraform destroy
aws_instance.example: Refreshing state... [id=i-048b8ae615444c5f5]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_instance.example will be destroyed
  - resource "aws_instance" "example" {
      ...
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

terraform destroyの出力結果にある「-」マークはリソースの削除を表しています。applyコマンドと同様に実行していいか確認されますので、yesと入力して、削除を実行します。

AWSマネージメントコンソールを確認すると、EC2インスタンスがTerminatedになっていて、削除されていることが分かります(図1.7)。

f:id:hi1280:20201222221738p:plain

図1.7: EC2インスタンス削除確認

ここまでがTerraformのセットアップと基本操作です。

【コラム】Terraformの学び方

本書では、AWSリソースを作るためだけにTerraformを使用していますが、実はTerraformの世界は奥が深いです。たとえば、モジュール機能を使って汎用的にTerraformリソースを定義できます。また、既存のAWSリソースをTerraformで管理できるように、インポートする機能があります。

このように、Terraformには、リソースを作る以外に学ぶと便利な機能があります。本書では言及しませんが、本格的にTerraformを学びたい場合には、『実践Terraform AWSにおけるシステム設計とベストプラクティス』*4をオススメします。

1.2 Amazon EKS

本節では、Terraformを使用して、EKSおよびEKSに必要なAWSリソースを作成します。EKSのリソースを作るのにterraform-aws-eks*1を利用します。そのほかVPCなどのネットワーク関連のAWSリソースを作成します。

まずは、次のように作業用ディレクトリを用意します。

$ mkdir terraform-aws-eks-example
$ cd terraform-aws-eks-example

作業用ディレクトリ内に各種tfファイルを用意します。TerraformからAWSを利用できるように、リスト1.2のように定義します。

リスト1.2: main.tf

locals {
  cluster_name    = "eks-example"
  cluster_version = "1.18"
}

provider "aws" {
  region = "ap-northeast-1"
}

regionでAWSリージョンを指定します。localsは、tfファイル内で使用可能な変数を定義できます。ここでは、EKSクラスタの名前やバージョンを保持しています。

EKS用のVPC作成は、リスト1.3のようにvpc.tfを用意します。

リスト1.3: vpc.tf

data "aws_availability_zones" "available" {}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.64.0"

  name           = "vpc-example"
  cidr           = "10.0.0.0/16"
  azs            = data.aws_availability_zones.available.names
  public_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]

  public_subnet_tags = {
    "kubernetes.io/cluster/${local.cluster_name}" = "shared"
    "kubernetes.io/role/elb"                      = "1"
  }

}

terraform-aws-modules/vpc/awsを使うとVPC、Subnetを簡潔な記述で作成できます。CIDRは10.0.0.0/16を使用します。自身の環境でCIDRが既存のVPCと被っている場合には変更が必要です。public_subnetsでSubnetを作成します。SubnetのIPアドレス数によって、Kubernetesクラスタで起動可能なPod数が制限されます。ここでは、サブネットマスクを24にしていますが、実際にはクラスタの規模に応じて調整が必要です。Podについては、第2章で説明します。EKSの決まりとして、利用するsubnetのタグに特別な指定が必要です。*5

EKSの作成は、リスト1.4のようにeks.tfを用意します。

リスト1.4: eks.tf

module "eks" {
  source          = "terraform-aws-modules/eks/aws"
  version         = "13.2.1"
  cluster_name    = local.cluster_name
  cluster_version = local.cluster_version
  subnets         = module.vpc.public_subnets

  vpc_id = module.vpc.vpc_id

  node_groups = {
    ng-1 = {
      desired_capacity = 2
      max_capacity     = 2
      min_capacity     = 2
      instance_type    = "t3.small"
    }
  }

  write_kubeconfig = false
}

data "aws_eks_cluster" "cluster" {
  name = module.eks.cluster_id
}

data "aws_eks_cluster_auth" "cluster" {
  name = module.eks.cluster_id
}

terraform-aws-modules/eks/awsを使うとEKSを作成できます。ここでは、Clusterのバージョンにlocalsの変数を使って1.18を指定します。node_groupsを指定して、EKSのマネージドノードグループを作成します。

terraform-aws-eksではマネージドノードグループではないノードグループの作成もサポートしています。その場合は、worker_groupsフィールドを指定してノードグループを作成できます。詳細はterraform-aws-eksのドキュメントを確認してみてください。*1

Terraformの実行中にKubernetes環境へのアクセスが必要になります。リスト1.5のように、kubernetes.tfを用意して、TerraformがKubernetes環境にアクセスできるようにします。

リスト1.5: kubernetes.tf

provider "kubernetes" {
  load_config_file       = "false"
  host                   = data.aws_eks_cluster.cluster.endpoint
  token                  = data.aws_eks_cluster_auth.cluster.token
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
}

リスト1.5のコードは、筆者が試した限りでは、terraform applyでエラーにならないために必要でした。なぜこれが必要なのか筆者もよく分かっていないのですが、おまじないと思って書きましょう。

利用するTerraformのバージョンに制限をかけるため、リスト1.6のようにversions.tfを用意します。

リスト1.6: versions.tf

terraform {
  required_version = ">= 0.12"
}

Terraformのバージョンを0.12以上で使用するように指定します。

ここまでできたら、EKSに関係するAWSリソースを作成する準備は完了です。

次は、これまでのtfファイルを利用して、実際にAWSリソースを作成します。まずは、次のとおりにterraform initを実行して、作業ディレクトリのセットアップを行いましょう。

$ terraform init

続いて、terraform applyでEKSを作成します。

$ terraform apply
module.eks.data.aws_iam_policy_document.cluster_assume_role_policy: Refreshing state...
module.eks.data.aws_partition.current: Refreshing state...
module.eks.data.aws_iam_policy_document.cluster_elb_sl_role_creation[0]: Refreshing state...
...
  Enter a value: yes

module.eks.aws_iam_policy.cluster_elb_sl_role_creation[0]: Creating...
module.vpc.aws_vpc.this[0]: Creating...
...
Apply complete! Resources: 33 added, 0 changed, 0 destroyed.

EKSの作成完了までには、10分ほどかかります。エラーがなく、applyが完了すればEKSリソースが作られています。

1.3 Kubernetes

本節では、EKSで作成したKubernetes環境の動作確認のために、Kubernetesリソースの取得ができるかを確認します。前節まででEKSのセットアップは完了していますが、EKSで作成したKubernetes環境に接続するための操作が必要です。

次のコマンドで、Kubernetesを操作するためのCLIツールであるkubectlをインストールします。

$ brew install kubectl

Kubernetesに接続するために必要なkubeconfigを次のコマンドのとおりに作成します。

$ aws eks --region ap-northeast-1 update-kubeconfig --name eks-example

aws eks update-kubeconfigコマンドの--nameオプションには、EKSのクラスタ名を指定します。

kubectlはkubeconfigの設定を参照してKubernetes環境にアクセスします。ここまでの操作でKubernetes環境へのアクセスが可能です。

最後に、EKSで作成したKubernetes環境にアクセスできるかを確認するために、次のとおりにkubectl get podsを実行してみます。

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
kube-system   aws-node-5cckx             1/1     Running   0          9m37s
kube-system   aws-node-9rqqx             1/1     Running   0          9m37s
kube-system   coredns-86f7d88d77-ch98t   1/1     Running   0          23m
kube-system   coredns-86f7d88d77-gh9xm   1/1     Running   0          23m
kube-system   kube-proxy-6x6fz           1/1     Running   0          9m37s
kube-system   kube-proxy-shfjv           1/1     Running   0          9m37s

kubectl get podsの出力には、STATUS、AGEといった項目があります。STATUSがRunningになっていれば、正常にPodが起動しています。また、AGEはPodの起動時間を表します。

ここまででAWSとTerraformを使って、シンプルなKubernetes環境を構築できました。注意ですが、このまま環境を構築したままにしておくと、EKSでは1時間あたり、0.10USDの料金が発生します。また、別でEC2インスタンスの料金などもかかります。不要な場合、適宜terraform destroyで削除しましょう。


いかがでしたでしょうか?ここまでが1章の内容になります。
改めて、本書の内容に興味を持った方は、下記より購入をよろしくお願いします。

techbookfest.org