[Kubernetes] 테라폼을 통한 Cluster 구성 자동화

안녕하세요? 정리하는 개발자 워니즈입니다. 지금까지 Kubernetes의 기본적인 개념에 대해서 알아봤는데요. 이번시간에는 쿠버네티스의 클러스를 테라폼을 통해서 구성하는 방법에 대해서 알아보도록 하겠습니다.

지난 글들은 아래를 참고 해주시면 됩니다.

위의 그림에 보시는것처럼 크게 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 ConfigurationAutosciling 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 ConfigurationAutosciling 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를 손쉽게 구성해주니, 편리성이 증대되었습니다. 더불어, 코드를 통해서 인프라를 관리하다보니 변경이력에 대한 내용을 확인할 수 있고, 주변 동료와도 협업이 잘될 것 같습니다.

다음 시간에는 필자가 구성하는 내용에 대한 소개와 볼륨 마운트에 대해서 정리해보도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다