[Kubernetes] 테라폼을 통한 Cluster 구성 자동화
안녕하세요? 정리하는 개발자 워니즈입니다. 지금까지 Kubernetes의 기본적인 개념에 대해서 알아봤는데요. 이번시간에는 쿠버네티스의 클러스를 테라폼
을 통해서 구성하는 방법에 대해서 알아보도록 하겠습니다.
지난 글들은 아래를 참고 해주시면 됩니다.
- 쿠버네티스 1편 : 설치 가이드
- 쿠버네티스 2편 : pod
- 쿠버네티스 3편 : service
- 쿠버네티스 4편 : deployment
- 쿠버네티스 5편 : pod 설정
- 쿠버네티스 6편 : 배포 전략
- 쿠버네티스 7편 : volume
- 쿠버네티스 8편 : daemonset
- 쿠버네티스 9편 : 테라폼을 통한 클러스터 구성
- 쿠버네티스 10편 : eks에서 volume 사용하기
- 쿠버네티스 11편 : helm
- 쿠버네티스 12편 : helm chart template
- 쿠버네티스 13편 : helm deploy
- 쿠버네티스 14편 : fluentd를 통한 log수집
- 쿠버네티스 15편 : chartmuseum
- 쿠버네티스 16편 : 배포툴(ArgoCD 설치방법/사용법)
- 쿠버네티스 17편 : 배포툴(ArgoCD 구성/알람)
- 쿠버네티스 18편 : 쿠버네티스 Autoscailing
- 쿠버네티스 19편 : 쿠버네티스 로깅 아키텍처
위의 그림에 보시는것처럼 크게 3 가지
로 구분이 되어있습니다.
- Kubernetes-server (Cli 를 수행하는 서버)
- EKS 클러스터
- EKS worker-nodes
cli를 수행하는 서버는 EKS 를 통한 제어의 업무를 담당합니다.
EKS 클러스터를 생성한 뒤, worker-nodes를 생성하여 Cluster join을 수행합니다.
테라폼을 통해 인프라를 구성해 두면, 추후에 문제가 발생하거나 다른 쪽에 동일한 작업을 해야될 때, 몇가지 customizing만 해주면, 위의 내용을 손쉽게 구성 할 수 있습니다. 그렇기때문에 더더욱 IaC(Infra as a Code)가 중요해지고 있습니다. 인프라 자체를 코드로 관리하면서, 변경이력에 대한 수행도 해주기때문에 관리적인 측면에서 매우 좋습니다.
1. 테라폼 소스 clone
테라폼을 수행하기 위해서는 테라폼이 설치 되어있는 OS에서 수행을 해야됩니다. 필자 같은 경우는 bastion
호스트에서 진행을 했습니다.
테라폼 소스를 다운받기 위해서 git clone 을 수행합니다 .
# git clone https://github.com/wonizz/eks-terraform.git
본인이 원하는 특정한 경로에서 위의 명령어를 수행하면 2개의 폴더가 보입니다.
- kubernetes-server : cli에 대한 EC2 생성 내용입니다.
- cluster : eks 클러스터 + worker nodes에 대한 내용입니다.
클론이 완료되었다면, 다음 명령을 통해서 terraform에 필요한 모듈들을 다운받습니다.
# terraform init
테라폼에서 사용하는 모듈을 통해서 오토스케일링
그룹이라던지, ec2 configuration
등에 대한 내용을 수정할 수 있습니다.
2. Kubernetes-server 생성
먼저 cli를 수행하는 쿠버네티스 서버를 생성해보도록 하겠습니다. 이번 포스팅은 테라폼에 대한 내용보단, eks 를 구성하는 내용에 입각해서 작성을 하고 있기때문에, 기본적으로 테라폼 사용법은 어느정도 안다는 가정하에 작성을 하였습니다.
위의 그림에서 보시면, (1) 에 해당하는 내용인데, 먼저 소스를 보도록 하겠습니다.
resource "aws_security_group" "kubernetes-server-instance-sg" {
name = "kubernetes-server-instance-sg"
description = "kubectl_instance_sg"
vpc_id = "vpc-c8d80ba1" => 커스터마이징
ingress {
from_port = 22
to_port = 22
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"]
}
tags = {
Name = "kubectl_server-SG"
}
}
resource "aws_instance" "kubernetes-server" {
instance_type = "t2.micro" => 커스터마이징
ami = "ami-091e0e1906e653417" => 커스터마이징
key_name = "KP_DEV_AP_TEST" => 커스터마이징
subnet_id = "subnet-045fb8733552fbee1" => 커스터마이징
vpc_security_group_ids = ["${aws_security_group.kubernetes-server-instance-sg.id}"]
root_block_device {
volume_type = "gp2"
volume_size = "50"
delete_on_termination = "true"
}
tags = {
Name = "eks-cli"
}
}
resource "aws_eip" "ip" {
instance = "${aws_instance.kubernetes-server.id}"
vpc = true
tags = {
Name = "server_eip"
}
}
위에서 보면, 다음의 3가지 리소스에 대해서 생성을 하고 있습니다.
- security-group
- instance
- eip
간단하게 보면, 보안그룹 생성 + 인스턴스 생성 + EIP를 생성하고, 인스턴스에 해당 보안그룹 적용, EIP mapping을 수행하는 내용입니다.
위의 내용에서 보듯이 커스터마이징 영역은 추후에 variables.tf로 빼두어, configure 할 생각입니다.
# terrafom plan
위의 명령어를 통해서 테라폼 수행여부에 대한 내용을 확인 할 수 있습니다.
3개의 리소스가 생성이 되고, 된 결과는 모두 console창에서 확인이 가능합니다.
그럼 여기서 provider셋팅은 어디서 했을까요?
provider 같은 경우, provider.tf 파일로 두어, 셋팅이 가능하지만, aws configure 를 통해서 iam 역할 및 권한을 부여하여 생성을 수행 할 수 있습니다. 필자 같은 경우는 bastion host에 이미 셋팅이 되어있기 때문에 따로 설명은 안드렸습니다.
그리고 위의 소스를 plan 혹은 apply를 하게 되면 어느쪽 region에서 수행할지 input 값을 받습니다.
2. EKS 클러스 생성
eks 클러스터를 생성하는 소스에 대해서 알아보도록 하겠습니다.
여기서는 크게 3가지 구성으로 나뉘어집니다.
- IAM role 생성
- security group 생성
- eks cluster 생성
#IAM Role
resource "aws_iam_role" "cluster-role" {
name = "cluster-iam-role"
assume_role_policy = < 커스터마이징
}
depends_on = [
"aws_iam_role_policy_attachment.eks-cluster-AmazonEKSClusterPolicy",
"aws_iam_role_policy_attachment.eks-cluster-AmazonEKSServicePolicy",
]
}
위의 내용에서 IAM role을 생성하고, 셋팅하는 부분이 있습니다. 이부분은 cluster의 role을 매핑하기 위함인데, 클러스터에 대한 정책, EKS 서비스에 대한 정책들을 셋팅합니다.
방화벽 같은 경우는 다음 2가지 경우에 대해서 셋팅을 합니다.
- kubernetes API통신을 위한 443 오픈 (클러스터가 외부의 API요청하기 위함)
- worker-nodes내의 pod으로부터 통신을 위한 443 오픈(worker-nodes 에서 클러스터로 요청)
추가로 클러스터 같은 경우는 생성을 한뒤, role 매핑과 정책 매핑을 하고 있습니다.
3. 워커 노드 생성
워커 노드 같은경우는 오토 스케일링 그룹
을 통해서 인스턴스를 생성하게끔 되어있습니다. 그래서 오토스케일링에 대한 Launch Configuration
과 Autosciling Group
을 지정해줍니다.
locals {
worker-node-userdata = < 커스터마이징
USERDATA
}
#Launch Configuration
resource "aws_launch_configuration" "worker" {
iam_instance_profile = "${aws_iam_instance_profile.worker-node.name}"
image_id = "${data.aws_ami.eks-worker.id}"
instance_type = "t2.micro" => 커스터마이징
name_prefix = "worker-node" => 커스터마이징
security_groups = ["${aws_security_group.worker-node-sg.id}"]
user_data_base64 = "${base64encode(local.worker-node-userdata)}"
key_name = "P6_DEV_AP_AEM" => 커스터마이징
associate_public_ip_address = "true"
lifecycle {
create_before_destroy = true
}
}
#Autoscalling Group
resource "aws_autoscaling_group" "worker" {
desired_capacity = 2
launch_configuration = "${aws_launch_configuration.worker.id}"
max_size = 3
min_size = 2
name = "worker-nodes"
vpc_zone_identifier = ["subnet-09158d63ef844c783", "subnet-017bde34c2265144d", "subnet-0ee44c4bea2dbb0d6"]
tag {
key = "Name"
value = "worker-nodes" => 커스터마이징
propagate_at_launch = true
}
tag {
key = "kubernetes.io/cluster/eksclustertest"
value = "owned"
propagate_at_launch = true
}
}
우선 위에 userdata에서 ‘eksclustertest’ 는 반드시 (2)에서 생성한 클러스터 네임을 기입해야됩니다. 클러스터에 내용을 워커가 인식하게끔 하기 위함입니다.
Launch Configuration
과 Autosciling Group
두가지 내용은 보면 쉽게 이해가 될 것입니다.
어떠한 ami를 사용하여 어떤타입의 인스턴스를 생성할 것인지 그리고 이런 config를 통해서 자동 조정은 어떤식으로 할것인지에 대한 내용입니다. 필자 같은 경우는 테스트를 위해서 2대의 오토스케일링그룹을 지정했습니다.
# terraform plan
역시 테라폼 플랜을 통해서 어떠한 리소스들이 생성이 되는지 확인합니다
# terraform apply
최종적으로 apply를 통해서 인스턴스를 생성합니다.
4. 클러스터 구성
위의 리소스들을 생성했다고, 클러스터까지 구성된것은 아닙니다. 실제로 worker-nodes를 클러스터로 join을 시켜주는 작업이 필요합니다.
필자 같은 경우, cli 인스턴스를 k8s ami를 기반으로 생성하였기 때문에 기본적으로 kubectl 명령어는 설치가 되어있습니다.
1. aws-iam-authenticator 설치
iam 기반으로 명령줄을 통해 master에서 작업 요청이 되기떄문에 해당 작업이 필요합니다.
curl -o aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.13.7/2019-06-11/bin/linux/amd64/aws-iam-authenticator
chmod +x ./aws-iam-authenticator
mkdir -p $HOME/bin && cp ./aws-iam-authenticator $HOME/bin/aws-iam-authenticator && export PATH=$HOME/bin:$PATH
echo ‘export PATH=$HOME/bin:$PATH’ >> ~/.bashrc
2. 아마존 EKS 를 위한 kubectl 설정
아마존에서 생성한 EKS 클러스터에서 api를 호출하기 위하여 cli 인스턴스에 configuration작업을 합니다.
aws eks --region region update-kubeconfig -- name cluster_name
테스트
kubectl get svc
결과
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 443/TCP 1m
3. 워커노드 조인
curl -o aws-auth-cm.yaml https://amazon-eks.s3-us-west-2.amazonaws.com/cloudformation/2019-02-11/aws-auth-cm.yaml
aws-auth-cm.yaml 파일을 열고, role에 대한 셋팅 부분을 테라폼을 통해 생성하였던 롤로 지정을 한 뒤 저장합니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: => 변경
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
적용
kubectl apply -f aws-auth-cm.yaml
테스트
kubectl get nodes — watch
4. 기본 앱 배포
이제 클러스링까지 완전히 된 EKS에 앱을 한가지 배포해봅니다.
앱 배포(nginx)
kubectl create deployment nginx --image=nginx
서비스 배포
kubectl create service nodeport nginx --tcp=80:80
서비스의 노드 포트를 통해서 접속합니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
nginx NodePort 10.102.166.47 80:30784/TCP
kubernetes ClusterIP 10.100.0.1 443/TCP
테스트
http://:30784
5. 마치며..
이번시간에는 테라폼을 통해서 클러스터링을 자동 구성하는 내용을 살펴봤습니다. IaC개념을 도입함과 동시에 EKS를 손쉽게 구성해주니, 편리성이 증대되었습니다. 더불어, 코드를 통해서 인프라를 관리하다보니 변경이력에 대한 내용을 확인할 수 있고, 주변 동료와도 협업이 잘될 것 같습니다.
다음 시간에는 필자가 구성하는 내용에 대한 소개와 볼륨 마운트에 대해서 정리해보도록 하겠습니다.