参考文献: Terraform Up & Running (Yevgeniy Brikman著)
cd
mkdir -p ~/20231121
cd 20231121
-- 1. k8sモジュール作成
mkdir -p ~/20231121/modules/services/k8s-app
cat <<-'EOF' > ~/20231121/modules/services/k8s-app/variables.tf
variable "name" {
description ="name"
type = string
}
variable "image" {
description = "image"
type = string
}
variable "container_port" {
description = "container_port"
type = number
}
variable "replicas" {
description = "replicas"
type = number
}
variable "environment_variables" {
description = "environment_variables"
type = map(string)
default = {}
}
EOF
cat <<-'EOF' > ~/20231121/modules/services/k8s-app/main.tf
terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.0"
}
}
}
locals {
pod_labels = {
app = var.name
}
}
resource "kubernetes_deployment" "app" {
metadata {
name = var.name
}
spec {
replicas = var.replicas
template{
metadata {
labels = local.pod_labels
}
spec {
container {
name = var.name
image = var.image
port {
container_port = var.container_port
}
dynamic "env" {
for_each = var.environment_variables
content {
name = env.key
value = env.value
}
}
}
}
}
selector {
match_labels = local.pod_labels
}
}
}
resource "kubernetes_service" "app" {
metadata {
name = var.name
}
spec {
type = "LoadBalancer"
port {
port = 80
target_port = var.container_port
protocol = "TCP"
}
selector = local.pod_labels
}
}
EOF
cat <<-'EOF' > ~/20231121/modules/services/k8s-app/outputs.tf
locals {
status = kubernetes_service.app.status
}
output "service_endpoint" {
value = try(
"http://${local.status[0]["load_balancer"][0]["ingress"][0]["hostname"]}",
"(error parsing hostnmame from status)"
)
description = "service_endpoint"
}
EOF
-- 2. EKSモジュール作成
mkdir -p ~/20231121/modules/services/eks-cluster
cat <<-'EOF' > ~/20231121/modules/services/eks-cluster/variables.tf
variable "name" {
description = "name"
type = string
}
variable "min_size" {
description = "min_size"
type = number
}
variable "max_size" {
description = "max_size"
type = number
}
variable "desired_size" {
description = "desired_size"
type = number
}
variable "instance_types" {
description = "instance_types"
type = list(string)
}
EOF
cat <<-'EOF' > ~/20231121/modules/services/eks-cluster/main.tf
terraform {
required_version = "= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "= 4.17.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_iam_role" "cluster" {
name = "${var.name}-cluster-role"
assume_role_policy = data.aws_iam_policy_document.cluster_assume_role.json
}
data "aws_iam_policy_document" "cluster_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["eks.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy_attachment" "AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.cluster.name
}
data "aws_vpc" "default" {
default = true
}
data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
resource "aws_eks_cluster" "cluster" {
name = var.name
role_arn = aws_iam_role.cluster.arn
version = "1.28"
vpc_config {
subnet_ids = data.aws_subnets.default.ids
}
depends_on = [
aws_iam_role_policy_attachment.AmazonEKSClusterPolicy
]
}
resource "aws_iam_role" "node_group" {
name = "${var.name}-node-group"
assume_role_policy = data.aws_iam_policy_document.node_assume_role.json
}
data "aws_iam_policy_document" "node_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy_attachment" "AmazonEKSWorkerNodePolicy" {
policy_arn ="arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.node_group.name
}
resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly" {
policy_arn ="arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.node_group.name
}
resource "aws_iam_role_policy_attachment" "AmazonEKS_CNI_Policy" {
policy_arn ="arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.node_group.name
}
resource "aws_eks_node_group" "nodes" {
cluster_name = aws_eks_cluster.cluster.name
node_group_name = var.name
node_role_arn = aws_iam_role.node_group.arn
subnet_ids = data.aws_subnets.default.ids
instance_types = var.instance_types
scaling_config {
min_size = var.min_size
max_size = var.max_size
desired_size = var.desired_size
}
depends_on = [
aws_iam_role_policy_attachment.AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.AmazonEC2ContainerRegistryReadOnly,
aws_iam_role_policy_attachment.AmazonEKS_CNI_Policy,
]
}
EOF
cat <<-'EOF' > ~/20231121/modules/services/eks-cluster/outputs.tf
output "cluster_name" {
value = aws_eks_cluster.cluster.name
description = "cluster_name"
}
output "cluster_arn" {
value = aws_eks_cluster.cluster.arn
description = "cluster_arn"
}
output "cluster_endpoint" {
value = aws_eks_cluster.cluster.endpoint
description = "cluster_endpoint"
}
output "cluster_certificate_authority" {
value = aws_eks_cluster.cluster.certificate_authority
description = "cluster_certificate_authority"
}
EOF
-- 3. メインモジュール作成
mkdir -p ~/20231121/examples/kubernetes-eks
cat <<-'EOF' > ~/20231121/examples/kubernetes-eks/main.tf
provider "aws" {
region = "ap-northeast-1"
}
module "eks_cluster" {
source = "../../modules/services/eks-cluster"
name = "example-eks-clsuter"
min_size = 1
max_size = 2
desired_size = 1
instance_types = ["t3.small"]
}
provider "kubernetes" {
host = module.eks_cluster.cluster_endpoint
cluster_ca_certificate = base64decode(
module.eks_cluster.cluster_certificate_authority[0].data
)
token = data.aws_eks_cluster_auth.cluster.token
}
data "aws_eks_cluster_auth" "cluster" {
name = module.eks_cluster.cluster_name
}
module "simple_webapp" {
source = "../../modules/services/k8s-app"
name = "simple-webapp"
image = "training/webapp"
replicas = 2
container_port = 5000
environment_variables = {
PROVIDER = "Terraform"
}
depends_on = [module.eks_cluster]
}
EOF
cat <<-'EOF' > ~/20231121/examples/kubernetes-eks/variables.tf
output "service_endpoint" {
value = module.simple_webapp.service_endpoint
description = "service_endpoint"
}
EOF
-- 4. 動作確認
cd ~/20231121/examples/kubernetes-eks
terraform init
terraform fmt
terraform -version
terraform plan
terraform apply -auto-approve
aws eks update-kubeconfig --region ap-northeast-1 --name example-eks-clsuter
kubectl get nodes
kubectl get deployments
kubectl get pods
kubectl get services
terraform destroy -auto-approve