Kubernetes 03 – Kubernetes Cluster on AWS with kops

지난 글 Kubernetes 02 – ReplicaSet에 이어 kops를 사용해서 AWS 환경에서 Kubernetes (이하 K8s) Cluster를 구성해보자.

kops/kops_create_cluster 문서에 kops의 사용법이 쉽게 설명되어 있지만, 사내 망등의 Internal Network 위에 private topology를 사용해서 K8s Cluster를 구성하는 과정을 단계별로 설명해보고자 한다.

kops

kops는 K8s Cluster를 쉽게 생성, 관리할 수 있게 도와주는 오픈소스 프로젝트다.

kops의 README 페이지에 따르면 We like to think of it as kubectl for clusters. 라고 프로젝트를 설명하고 있다.
프러덕션 레벨의 K8s Cluster를 간단한 CLI 명령을 통해 생성, 관리, 업그레이드, 삭제할 수 있도록 지원한다.
이 밖에도 K8s Cluster의 Master Node의 HA 구성 등 다양한 옵션을 간단한 명령으로 손쉽게 설정할 수 있다는 장점을 가지고 있다.

kops는 2019년 4월 현재 설치 대상으로 AWS를 공식지원하고, GCE는 beta, VMware vSphere는 alpha 버전으로 지원하며 Digital Ocean 등으로 대상 플랫폼을 확장해 가고 있다.

발음은 케이옵스 라고 발음하는 분도 있고, 나는 콥스 라고 부르고 있다.

kops 이외에도 kubeadm, kubespray, kube-aws, kubicorn , Kubernetes the hard way 등 K8s Cluster를 셋업하는 다양한 방법이 있지만, kops를 사용하기로 결정한 이유는 kops는 terraform을 통해 프로비저닝 할 수 있기 때문이다. terraform을 처음 써본 뒤로 가능하면 AWS 인프라는 Terraform을 통해서 생성/관리하려고 하고 있다.

라고 이 글을 쓰기 시작할 때는 생각했으나 kops로 몇 번 클러스터를 만들고 관리해보니 terraform을 거치지 않고 s3의 kops state를 그대로 사용하는 것이 편했다.

K8s 클러스터 생성 후 kops 명령을 통하지 않고 terraform 코드만으로 리소스를 변경할 경우, 이후 kops 명령을 통해 리소스 변경이 필요할 때 리소스 상태의 싱크가 맞지 않거나 kops state에 저장된 상태로 덮어써지는 문제 등이 있어 현재는 kops로 생성한 클러스터의 리소스는 terraform을 통하지 않고 kops만으로 관리하고 있다.

다음 프로젝트처럼 kops 기반으로 특정 형태를 유지하면서 여러개의 K8s 클러스터를 프로비저닝해야하는 경우에는 terraform과 함께 사용하는 것이 좀 더 유용할 것 같다.

이밖에도 kops는 K8s Node를 AWS Auto Scaling Group으로 관리해서 Scaling Policy를 적용하기 쉽고 Cluster의 변경, 업그레이드가 상대적으로 편하며, AWS provider를 사용한 AWS 리소스 (예를들면 ELB) 제어도 kubeadm을 사용했을 때 보다 좀 더 무탈(?) 하게 잘 실행되어서 만족감이 높았다.

AWS위에서 K8s클러스터를 구성할 때 kops만큼 검색 키워드에 많이 걸리는 kubeadm은 클라우드 리소스의 인프라스트럭처가 이미 구성되있는 상태 (혹은 인프라스트럭처의 직접적인 권한이 없는 상태에서 클러스터를 구축해야하는 경우) 에서 K8s cluster를 구축하기에 용이한 것 같다.


먼저 K8s Cluster를 생성할 AWS 에 kops를 사용할 준비가 필요하다.

VPC 생성

kops는 K8s Cluster를 위한 AWS VPC를 kops 커맨드를 통해 새로 만드는 방법과, 기존에 운영하던 AWS VPC 위에 K8s Cluster를 생성하는 방법을 모두 지원한다.

신규 VPC를 생성하는 방법은 이미 kops 문서에 잘 설명되어 있어 이 글에서는 기존에 운영하던 dev VPC가 이미 있는 상태에서 그 위에 Cluster를 구성한다는 가정으로 진행해 보려고 한다. AWS NAT Gateway에서 NAT instance로 전환하기에서 작성했던 Terraform Module cheap_vpc를 사용해서 dev VPC를 생성했다.

예제에서는 AWS 도쿄리전을 사용한다. 파일을 그대로 다운받아 실행하는 경우 도쿄리전에 리소스가 생성됨에 주의! 서울리전에 리소스를 생성할 경우 provider.tf 파일에서 ap-northeast-1을 ap-northeast-2로 수정하면 된다.

$ git clone git@github.com:asbubam/2dal-infrastructure.git
$ cd 2dal-infrastructure/terraform/common/vpc
  • 2dal-infrastructure/terraform/common/vpc/dev_vpc.tf
# dev_vpc.tf
module "vpc" {
  source = "github.com/asbubam/2dal-infrastructure/terraform/modules/cheap_vpc"

  name = "dev"
  cidr = "172.16.0.0/16"

  azs              = ["ap-northeast-1a", "ap-northeast-1c"]
  public_subnets   = ["172.16.1.0/24", "172.16.2.0/24"]
  private_subnets  = ["172.16.101.0/24", "172.16.102.0/24"]
  database_subnets = ["172.16.201.0/24", "172.16.202.0/24"]

  bastion_ami                 = "${data.aws_ami.amazon_linux_nat.id}"
  bastion_availability_zone   = "${module.vpc.azs[0]}"
  bastion_subnet_id           = "${module.vpc.public_subnets_ids[0]}"
  bastion_ingress_cidr_blocks = ["0.0.0.0/0"] # 예제에서는 0.0.0.0/0 으로 열었지만 가급적이면 bastion도 사내망에서만 접근할 수 있도록 제한한다.
  bastion_keypair_name        = "2dal-dev" # bastion에 할당할 key pair 이름

  tags = {
    "TerraformManaged" = "true"
  }
}
  • terraform init, plan, apply
$ terraform init
...
Terraform has been successfully initialized!

# terraform plan으로 생성될 리소스 확인
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.aws_ami.amazon_linux_nat: Refreshing state...

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

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:

  + module.vpc.aws_db_subnet_group.database
  + module.vpc.aws_default_network_acl.dev_default
  + module.vpc.aws_default_security_group.dev_default
  + module.vpc.aws_eip.bastion
  + module.vpc.aws_instance.bastion
  + module.vpc.aws_internet_gateway.this
  + module.vpc.aws_route_table.private[0]
  + module.vpc.aws_route_table.private[1]
  + module.vpc.aws_route_table.public
  + module.vpc.aws_route_table_association.database[0]
  + module.vpc.aws_route_table_association.database[1]
  + module.vpc.aws_route_table_association.public[0]
  + module.vpc.aws_route_table_association.public[1]
  + module.vpc.aws_security_group.bastion
  + module.vpc.aws_security_group.ssh_from_bastion
  + module.vpc.aws_subnet.database[0]
  + module.vpc.aws_subnet.database[1]
  + module.vpc.aws_subnet.private[0]
  + module.vpc.aws_subnet.private[1]
  + module.vpc.aws_subnet.public[0]
  + module.vpc.aws_subnet.public[1]
  + module.vpc.aws_vpc.this

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

# terraform apply로 리소스 생성
$ terraform apply
...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
...
Apply complete! Resources: 24 added, 0 changed, 0 destroyed.

terraform을 사용해서 dev VPC와 private/db private/public Subnet, Route Table, Internet Gateway, Bastion 및 NAT 겸용 EC2 instance를 생성 했다.

AWS Cloud Provider의 Kubernetes tag의 이해

AWS에 K8s Cluster를 셋업하면 K8s의 AWS Cloud Provider를 통해서 Ingress Controller등의 K8s 리소스를 생성할 때 리소스가 사용할 Subnet 등을 자동으로 찾아 배치하게 되는데, 이때 KubernetesCluster tag의 값이 해당 K8s Cluster의 이름과 동일한 AWS 리소스를 찾아 사용하게 된다.

ref: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/aws/aws_under_the_hood.md#tagging

이 부분은 AWS EKS를 사용할 때도 동일하게 적용되는 룰로, 처음에 AWS 위에 K8s Cluster를 구성했을 때 몰라서 고생했던 부분이다.

이에 추가해서 kubernetes.io/cluster/{Cluster Name} tag를 입력하는데 AWS 리소스를 한개의 Cluster가 독점해서 사용할 때는 owned를 여러개의 Cluster가 공유해서 사용할 때는 shared를 값으로 입력한다. ref: https://github.com/kubernetes/kubernetes/blob/master/pkg/cloudprovider/providers/aws/tags.go#L43-L52

K8s Cluster 이름을 2dal.k8s.local으로 사용할 예정이다.

kops 1.6.2 버전부터 .k8s.local 로 끝나는 Cluster 이름을 사용할 경우 Cluster를 위한 별도의 외부 도메인 등록없이 Cluster를 생성할 수 있다. kops는 local gossip state를 사용해서 Cluster 내부의 변경사항을 각 Node로 전파/관리한다. ref: kops/gossip.md at master · kubernetes/kops · GitHub

K8s 클러스터에서 생성하는 AWS 리소스(ex ALB) 가 알맞은 subnet 대역의 IP를 사용하게 하기 위해서 VPC Subnet 에는 다음과 같은 tag가 정의되어야 한다.

kops를 사용해서 셋업할 경우 이 태그는 kops에 의해 자동으로 Subnet에 설정된다.

Public Subnets:

"kubernetes.io/cluster/<cluster-name>" = "shared"  # 여러 cluster가 서브넷을 공유
"kubernetes.io/role/elb"               = "1"       # public ELB는 서브넷을 사용
"SubnetType"                           = "Utility" # public리소스는 서브넷을 사용

Private Subnets:

"kubernetes.io/cluster/<cluster-name>" = "shared"  # 여러 Cluster가 서브넷을 공유
"kubernetes.io/role/internal-elb"      = "1"       # internal ELB는 서브넷을 사용
"SubnetType"                           = "Private" # private리소스는 서브넷을 사용

ref: kops/run_in_existing_vpc.md at master · kubernetes/kops · GitHub

VPC에는 EnableDNSHostnames=true 옵션이 활성화 되야한다. (VPC 생성 시 별도 설정을 하지 않았다면 enabled 되어있다.)

ref: kops/run_in_existing_vpc.md at master · kubernetes/kops · GitHub

Note also the Kubernetes VPCs (currently) require EnableDNSHostnames=true. kops will detect the required change, but refuse to make it automatically because it is a shared VPC. Please review the implications and make the change to the VPC manually.

kops가 사용할 IAM 생성

kops로 K8s Cluster를 구축하기 위해서는 다음의 IAM Policy가 필요하다. 이 글에서는 기존에 생성한 VPC를 사용함으로 AmazonVPCFullAccess policy를 제외한 나머지 4개의 policy가 필요하다.

* AmazonEC2FullAccess
* IAMFullAccess
* AmazonS3FullAccess
* AmazonVPCFullAccess
* AmazonRoute53FullAccess

기존, Terraform에서 사용하던 IAM Role을 그대로 사용해도 되지만 이후 관리를 위해서 kops가 사용할 IAM Role을 별도로 생성해서 관리하는 편이 좋겠다.

나는 kops 라는 IAM Role 을 만들고 4개의 policy를 부여했다.

IAM Role, Policy도 terraform으로 관리하면 좋겠지만, terraform에 익숙해지기 전에는 IAM은 수동으로 관리하는 것이 좋다고 생각한다. IAM Policy 와 IAM User, Group등을 연결하는 policy attachment 등을 (현재의 IAM 상태를 기반으로 정의하지 않고) 잘못 정의할 경우 기존에 사용중이던 IAM role에서 권한이 빠지는 등 문제가 발생할 수 있기 때문이다.

bastion instance에 kops role 부여

kops IAM Role을 bastion instance에 부여하고, bastion에서 kops명령을 수행한다.

  • 2dal-infrastructure/terraform/common/vpc/dev_vpc.tf
module "vpc" {
  source = "github.com/asbubam/2dal-infrastructure/terraform/modules/cheap_vpc"

  name = "dev"
  cidr = "172.16.0.0/16"

  azs              = ["ap-northeast-1a", "ap-northeast-1c"]
  public_subnets   = ["172.16.1.0/24", "172.16.2.0/24"]
  private_subnets  = ["172.16.101.0/24", "172.16.102.0/24"]
  database_subnets = ["172.16.201.0/24", "172.16.202.0/24"]

  bastion_ami                 = "${data.aws_ami.amazon_linux_nat.id}"
  bastion_availability_zone   = "${module.vpc.azs[0]}"
  bastion_subnet_id           = "${module.vpc.public_subnets_ids[0]}"
  bastion_ingress_cidr_blocks = ["0.0.0.0/0"]
  bastion_keypair_name        = "2dal-dev"
  bastion_instance_profile    = "kops" # 이 라인을 추가한다.

  tags = {
    "TerraformManaged"  = "true"
  }
}
  • terraform apply
$ terraform apply

kops 데이터를 저장할 S3 bucket생성

terraform에서 terraform state를 통해 리소스의 상태를 관리하듯이 kops는 kops state 파일을 사용해서 K8s Cluster의 상태를 관리한다. kops state를 저장할 s3 bucket을 생성한다.

  • 2dal-infrastructure/terraform/common/s3/provider.tf
provider "aws" {
  region = "ap-northeast-1"
}
  • 2dal-infrastructure/terraform/common/s3/kops-state-local-k8s-2dal.tf
resource "aws_s3_bucket" "kops-state-local-k8s-2dal" {
  bucket = "kops-state-local-k8s-2dal"
  acl    = "private"

  versioning {
    enabled = true
  }
}
  • terraform init, plan, apply
$ terraform init
$ terraform plan
$ terraform apply

kops 설치

  • bastion instance에 접속
$ ssh -i {bastion 생성 시 등록한 keypair pem 파일} ec2-user@{bastion ip}
  • 환경변수를 쉽게 설정하기 위해 direnv를 설치
$ wget https://github.com/direnv/direnv/releases/download/v2.18.2/direnv.linux-amd64
$ chmod +x direnv.linux-amd64
$ sudo mv direnv.linux-amd64 /usr/local/bin/direnv
$ vi ~/.bashrc
export EDITOR=/usr/bin/vim
eval "$(direnv hook bash)"
$ source ~/.bashrc
$ direnv version
2.18.2
  • kops binary를 다운받아 설치
$ curl -Lo kops https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
$ chmod +x kops
$ sudo mv kops /usr/local/bin/
$ kops version
Version 1.11.1 (git-0f2aa8d30)
  • K8s node 접속용 ssh key 생성 bastion에서 K8s Master, Node에 접속할 때 사용할 ssh key를 생성한다. kops create 시에 별도로 public key path를 입력하지 않으면 default로 ~/.ssh/id_rsa.pub 파일을 사용해서 Master, Node EC2 instance를 생성한다.
$ ssh-keygen

K8s Cluster 생성

오래 기다렸다. 이제 kops create 명령으로 K8s Cluster를 생성해보자!

  • 작업 디렉터리 생성 및 환경변수 설정 이 값들은 kops 명령 실행 시 파라미터로 전달할 수 있지만 지정된 값을 계속 사용하게 되기 때문에 direnv를 사용해서 ~/kops 디렉터리에 접근 시 자동으로 설정할 수 있도록 한다.
$ mkdir kops
$ cd kops
$ direnv edit .
export KOPS_STATE_STORE=s3://kops-state-local-k8s-2dal
export KOPS_CLUSTER_NAME=2dal.k8s.local
export KUBECONFIG=~/.kube/2dal.k8s.local
:wq # 저장
  • kops create
kops create cluster \
  --zones=ap-northeast-1a,ap-northeast-1c \        # Node가 사용할 AZ
  --master-zones=ap-northeast-1a,ap-northeast-1c \ # master가 사용할 AZ
  --node-count=2 \ # Node instance count
  --node-size=t2.small \ # Node instance type - 연습용으로는 t2.small, medium 정도가 적당하다.                 
  --node-volume-size=20 \ # Node instance EBS size
  --node-security-groups=sg-090e1a638b1910292,sg-0a322c2385e859d4a \ # Node에 설정할 Security Group 나는 dev-default 와 dev-ssh-from-bastion 의 SG id를 입력했다.
  --master-count=3 \ # Master instance count 1, 3, 5..  
  --master-size=t2.small \ # Master instance type - t2.medium 이상은 되야 덜 답답했다.
  --master-volume-size=20 \ # Master intance EBS size
  --master-security-groups=sg-090e1a638b1910292,sg-0a322c2385e859d4a\ # Master에 설정할 Security Group 나는 dev-default 와 dev-ssh-from-bastion 의 SG id를 입력했다.
  --topology=private \ # 클러스터를 public, private 어떻게 오픈할 것인가?
  --api-loadbalancer-type=internal \ # K8s api-server의 LB는 public, internal 중 어떤 것으로 할 것인가?
  --admin-access=172.16.0.0/16 \ # K8s api-server에 access를 허용할 ip 대역, 우선 VPC 대역 전체를 허용했다. 필요에 따라 수정한다.
  --vpc=vpc-007605415dedcb611 \ # dev VPC
  --network-cidr=172.16.0.0/16 \ # dev VPC의 CIDR
  --subnets=subnet-06da6f4bfca8b579b,subnet-0b4f2f38e17055fba \ # private subnet - 위에서 설명한 AWS cloud provider가 인식하기 위한 태그를 kops가 붙여준다.
  --utility-subnets=subnet-038e0115b3816692b,subnet-08f020f81a02421b4 \ # public subnet 
  --image='ami-0dbe2acf413e40198' \ # 도쿄 리전의 core os AMI ID
  --networking=calico \ # calico, weave 등 overlay network driver를 선택할 수 있다.  
  --cloud-labels "Owner=asbubam,Blog=blog.2dal.com" # 생성되는 AWS 리소스에 자동으로 붙여주고 싶은 tag 리스트

...

Must specify --yes to apply changes

Cluster configuration has been created.

Suggestions:
 * list clusters with: kops get cluster
 * edit this cluster with: kops edit cluster 2dal.k8s.local
 * edit your node instance group: kops edit ig --name=2dal.k8s.local nodes
 * edit your master instance group: kops edit ig --name=2dal.k8s.local master-ap-northeast-1a-1

Finally configure your cluster with: kops update cluster 2dal.k8s.local --yes

kops create 명령만으로는 아직 실제 리소스가 생성되지는 않는다. kops create cluster --yes 혹은 kops update cluster --yes 명령을 수행할 때 실제 Cluster리소스가 생성된다.

kops create의 다양한 파라미터는 kops/kops_create_cluster.md 페이지에 자세히 설명되어 있다.

kops update를 실행하기 전에, CustomResourceValidation 옵션을 활성화 하기 위해 kubeAPIServer.featureGates 항목에 CustomResourceValidation: true를 추가하고 저장한다.

  • kops edit cluster
$ kops edit cluster
spec:
  ...
  kubeAPIServer:
    featureGates:
      CustomResourceValidation: "true"
  • kops update cluster
# dryrun 으로 어떤 리소스가 변경될지 화면에 출력된다.
$ kops update cluster

# 실제 반영
$ kops update cluster --yes

# 아래 명령으로 상태를 5초마다 갱신하다보면... `Your cluster 2dal.k8s.local is ready` 가 출력된다. (인스턴스 사양에 따라 몇분 걸릴 수 있다.)
$ watch -n 5 kops validate cluster

# 성공
Validating cluster 2dal.k8s.local

INSTANCE GROUPS
NAME				ROLE	MACHINETYPE	MIN	MAX	SUBNETS
master-ap-northeast-1a-1	Master	t2.small	1	1	ap-northeast-1a
master-ap-northeast-1a-2	Master	t2.small	1	1	ap-northeast-1a
master-ap-northeast-1c-1	Master	t2.small	1	1	ap-northeast-1c
nodes				Node	t2.small	2	2	ap-northeast-1a,ap-northeast-1c

NODE STATUS
NAME							ROLE	READY
ip-172-16-101-12.ap-northeast-1.compute.internal	master	True
ip-172-16-101-130.ap-northeast-1.compute.internal	master	True
ip-172-16-101-219.ap-northeast-1.compute.internal	node	True
ip-172-16-102-228.ap-northeast-1.compute.internal	node	True
ip-172-16-102-68.ap-northeast-1.compute.internal	master	True

Your cluster 2dal.k8s.local is ready

생성된 K8s Cluster에 서비스 올려보기

K8s Cluster에 LoadBalancer type의 Service와 Hello World를 출력하는 Pod으로 이뤄진 간단한 hello-node 서비스를 올려보자.

kubectl 설치

  • K8s Cluster에 명령을 전달하기 위해 bastion에 kubectl을 설치한다.
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.9", GitCommit:"16236ce91790d4c75b79f6ce96841db1c843e7d2", GitTreeState:"clean", BuildDate:"2019-03-25T06:30:48Z", GoVersion:"go1.10.8", Compiler:"gc", Platform:"linux/amd64"}

hello-node 올려보기

  • hello-node.yaml 작성
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-node
spec:
  replicas: 2
  selector:
    matchLabels:
      service-name: hello-node
  template:
    metadata:
      labels:
        service-name: hello-node
    spec:
      containers:
        - name: hello-node
          image: asbubam/hello-node
          readinessProbe:
            httpGet:
              path: /
              port: 8080
          livenessProbe:
            httpGet:
              path: /
              port: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: hello-node
  #annotations:
  # 이 annotation이 없으면 public ELB를 생성함. 
  #service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
  type: LoadBalancer
  ports:
    - port: 8080
      targetPort: 8080
  selector:
    service-name: hello-node
  • kubectl apply
$ kubectl apply -f hello-world.yaml

$ pod 상태 확인
$ kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
hello-node-6ccd85c84c-2vr2g   1/1     Running   0          2m
hello-node-6ccd85c84c-td7qv   1/1     Running   0          2m

# service 상태 확인
$ kubectl get service hello-node
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   100.68.133.78   <pending>     8080:31637/TCP   2s

# 잠시 후 EXTERNAL-IP에 생성된 LB의 주소가 출력됨
$ kubectl get service hello-node
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                   PORT(S)          AGE
hello-node   LoadBalancer   100.68.133.78   a1a744ca0669311e980fa0673da93ff1-472252039.ap-northeast-1.elb.amazonaws.com   8080:31637/TCP   41s

# 몇초 뒤
$ watch -n 5 curl http://a1a744ca0669311e980fa0673da93ff1-472252039.ap-northeast-1.elb.amazonaws.com:8080

Hello World!
  • kubectl delete
$ kubectl delete -f hello-world.yaml 

Cluster 삭제

kops로 생성한 K8s Cluster의 삭제가 필요한 경우 다음과 같이 삭제할 수 있다.

# bastion instance 접속 후
$ cd kops

# dryrun 으로 어떤 리소스가 삭제되는지 확인
$ kops delete cluster

# 삭제
$ kops delete cluster --yes

bastion 등 인스턴스 삭제

$ cd 2dal-infrastructure/terraform/common/vpc
$ terraform destroy

정리

kops를 사용해서 K8s Cluster를 구축해봤다.

AWS EKS가 서울리전에도 사용할 수 있게 되어 좀 더 쉽고 빠르게 Cluster를 구축할 수 있게 되었지만 요구사항에 모두 부합하는 Cluster를 구축하기 위해 kops를 사용해야하는 경우가 있을거라고 생각한다. K8s Cluster를 생성하는 다양한 방법 중에 하나로 참고가 될 수 있다면 좋겠다.

Cluster를 구축했으니 이제 다음 글부터 Deployment, Service, Ingress, External DNS 등을 하나씩 올려 K8s위에 서비스를 배포하고 운영하는 이야기를 해보려고 한다. Kops로 K8s Cluster를 운영 중에 발생하는 Master, Node의 스케일링이나 설정 업데이트, K8s 버전업 등도 설명할 수 있으면 좋겠다.

아주 오랜기간 블로그가 뜸했음에도 꾸준히 patreon 을 통해 후원해주시는 분들께 감사와 사과의 인사를 하지 않을 수 없다.

감사합니다! 좀 더 여러가지 시도해보고, 정리해서 더 많이 공유할 수 있도록 노력하겠습니다!

참고자료