ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kubernetes] EKS 구축
    kubernetes 2022. 10. 23. 23:34
    반응형

     

    ❗️ AWS에서 제공하는 가이드 문서 예제로 진행한다.

     

    💡 Requires
    1. Terraform
    2. Helm
    3. aws-cli
    4. aws-iam-authenticator
    5. aws 계정 설정

     

    💡 EKS란 ?
    Amazon EKS는 AWS에서 만든 관리형 쿠버네티스 서비스 이다. EKS는 Elastic Kubernetes Service의 약자다.
    EKS를 사용하면 쿠버네티스 마스터노드구성을 하지 않아도 AWS에서 관리해주기 때문에 되기 때문에 쉽고 빠르게
    쿠버네티스를 이용할 수 있다. EKS는 구축하기 위해서 EKS클러스터생성과 노드그룹을 생성해야 한다.


    ❗️ 자세한 설명은 아래 링크 참조
    https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/what-is-eks.html

     

    Terraform을 이용해 AWS EKS를 구성하고 Helm을 이용해서 ingress와 application을 EKS 위에 띄워본다.

     

     

    💡 AWS IAM Authenticator 란?
    aws-iam-authenticator는 쿠버네티스의 RBAC 권한을 AWS IAM을 통해 제어할 수 있도록 해주는 도구이다. 기존에 이미 AWS 상에서 개발자의 권한 관리를 하고 있었다면 이를 그대로 API 서버로 가져와 쿠버네티스에서의 Role을 엮어줄 수 있다고 생각하면 된다. 예를 들어 DevOps 팀의 IAM Role은 kubernetes-admin 권한을 부여하되, 개발팀의 IAM Role에는 개발용 네임스페이스에만 접근 권한을 부여할 수도 있다. EKS에서는 자동으로 내장되어 있다.



    💡 인그레스(Ingress) 란?

    클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, HTTP와 HTTPS 경로를 노출한다. 트래픽 라우팅은 인그레스 리소스에 정의된 규칙에 의해 컨트롤된다.
    인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공할 수 있다.

    인그레스는 임의의 포트 또는 프로토콜을 노출시키지 않는다. HTTP와 HTTPS 이외의 서비스를 인터넷에 노출하려면 보통 Service.Type=NodePort 또는 Service.Type=LoadBalancer 유형의 서비스를 사용한다.

    인그레스 컨트롤러가 있어야 인그레스를 충족할 수 있다. 인그레스 리소스만 생성한다면 효과가 없다.
    ingress-nginx와 같은 인그레스 컨트롤러를 배포해야 할 수도 있다. 여러 인그레스 컨트롤러 중에서 선택할 수도 있다.

     

    출처: https://kubernetes.io/ko/docs/concepts/services-networking/ingress/


     

    📌 시작하기

    Helm / Kubectl / Terraform / aws-cli / aws-iam-authenticator 설치

    $ brew install helm kubectl terraform awscli aws-iam-authenticator

    1. IAM 사용자 생성 및 권한 부여

    • IAM을 사용하여 Amazon EKS에 대한 액세스를 관리하기 위해 IAM 사용자를 생성하고 권한을 부여한다.
    • 사용자 생성 후 Access Key, Secret Key는 별도로 저장해둔다.

    IAM 사용자 생성 링크
    https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/id_users_create.html#id_users_create_cliwpsapi

    권한 부여
    * 편의상 EC2FullAccess, AdministratorAccess 권한을 추가하지만, 운영 환경에서는 고려 해야 한다.

    2. 샘플 Terraform 스크립트 생성

    $ cd ~
    $ git clone https://github.com/terraform-providers/terraform-provider-aws.git
    $ cd terraform-provider-aws/example/eks-getting-started
    

     

    파일을 확인해보면 .tf 확장자가 붙어있다. 이 파일들은 샘플 EKS 클러스터를 구성하도록 되어있다.

    $ ll
    
    eks-cluster.tf  
    eks-worker-nodes.tf  
    outputs.tf  
    providers.tf  
    README.md  
    variables.tf  
    vpc.tf  
    workstation-external-ip.tf

     

    variables.tf 파일의 aws_region default 값이 us-west-2로 되어있다. 원하는 region으로 변경하면 된다. 이 글에서는 서울 리전(ap-northeast-2)으로 변경하여 진행한다.

    variable "aws_region" {
      default = "ap-northeast-2"
    }
    
    variable "cluster-name" {
      default = "terraform-eks-demo"
      type    = string
    }

     

    ❗️ EKS Node Group Default 값은 [t3.medium]이다. 비교적 비싼 요금제이기 때문에, [t3.small] type으로 변경하여 진행한다.
    -> eks-worker-nodes.tf 파일을 보면, node group의 정보가 적혀있다. 이 부분에 Instance type을 설정해준다.

    resource "aws_eks_node_group" "demo" {
      cluster_name    = aws_eks_cluster.demo.name
      node_group_name = "demo"
      node_role_arn   = aws_iam_role.demo-node.arn
      subnet_ids      = aws_subnet.demo[*].id
      instance_types  = ["t3.small"]  // 배열형태로 t3.small 값을 설정해준다.
    
      scaling_config {
        desired_size = 1
        max_size     = 1
        min_size     = 1
      }
    
      depends_on = [
        aws_iam_role_policy_attachment.demo-node-AmazonEKSWorkerNodePolicy,
        aws_iam_role_policy_attachment.demo-node-AmazonEKS_CNI_Policy,
        aws_iam_role_policy_attachment.demo-node-AmazonEC2ContainerRegistryReadOnly,
      ]
    }

    3. AWS Cli Authentication
    aws default profile을 설정하여 aws 인증정보를 입력한다.

    $ aws configure  // **설정이 안되어 있으면 None 으로 설정되어 있다.**
    AWS Access Key ID [None]: 
    AWS Secret Access Key [None]: 
    Default region name [None]: 
    Default output format [None]:

    위에서 저장해둔 IAM User의 Access Key Secret Key를 입력한다.

    region과 output format은 각각 “ap-northeast-2”, “json” 으로 입력한다.

     

    $ aws configure
    AWS Access Key ID [None]: ****************NG6K
    AWS Secret Access Key [None]: ****************WSQh
    Default region name [None]: ap-northeast-2
    Default output format [None]: json

     

     

    설정이 완료 됐으면 Default Profile로 설정한다. (IAM User Nickname)

    $ export AWS_DEFAULT_PROFILE=honggildong

    4. EKS 생성


    Terraform Initialization

    • Terraform을 사용하기 위해 초기화를 하는 작업이다.
    $ terraform init



    Terraform plan

    • .tf 파일의 내용을 실제로 적용 가능한지 확인하는 작업이며 추가, 삭제 되는 내용을 출력해준다.
    $ terraform plan



    Terraform apply

    • .tf 파일의 리소스를 생성, 수정, 삭제하는 작업이다. 현재는 최초로 실행하기 때문에 리소스를 생성만 한다.
    $ terraform apply
    • apply 실행 전에 아래와 같이 진행여부를 물어보는 Enter a value 문구가 뜨면 yes 라고 입력한다.

    5. Kubectl 설정

    • kubectl을 통해 접근하기 위해, aws 인증 정보를 output.tf 을 통해 생성한다.
    $ terraform output -raw kubeconfig > ~/.kube/config
    $ kubectl get namespaces # kubectl로 접근이 가능한지 test
    
    # Kubenetes Master 노드의 ConfigMap에 대해 EKS 클러스터가 접근할 수 있도록 설정
    $ terraform output -raw config_map_aws_auth > configmap.yml
    $ kubectl apply -f configmap.yml
    
    # output.tf 파일 변경시
    $ terraform refresh

    6. Install Nginx-Ingress

    • Helm을 이용해 nginx-stable 레포지토리를 추가하고 stable chart를 설치한다.
    $ helm repo add nginx-stable https://helm.nginx.com/stable
    $ helm repo update
    $ helm install nginx nginx-stable/nginx-ingress --set rbac.create=true
    • 아래와 같이 ingress가 running 중인 것을 확인한다.
    $ kubectl get pod                                         
    NAME                                   READY   STATUS    RESTARTS   AGE
    nginx-nginx-ingress-68d844db84-hchc9   1/1     Running   0          42s

    7. 샘플 Deployment, Service, Ingress yaml 생성

    • 편의상 한번에 Directory Path로 apply를 하기 위해서 mgmt/ingress Directory 하위의 yaml 파일에
      Deployment, Service, Ingress 정의
    >apiVersion: v1
    kind: Namespace
    metadata:
      name: web
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-server
      namespace: web
    spec:
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
            - name: httpd
              image: httpd:2.4.48-alpine3.14
              ports:
                - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web-server-service
      namespace: web
    spec:
      selector:
        app: web
      ports:
        - protocol: TCP
          port: 5000
          targetPort: 80
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: web-server-ingress
      namespace: web
    spec:
      ingressClassName: nginx
      rules:
        - host: web.example.com
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: web-server-service
                    port:
                      number: 80

    7-1. Deployment, Service, Ingress yaml 실행

    $ kubectl apply -f ./mgmt/ingress/single-load-balancer-app.yaml

    7-2. Deployment, Service, Ingress 확인

    • web namespace 확인
    $ kubectl get namespace

     

    • nginx-ingress controller 확인
    $ kubectl get svc
    kubernetes            ClusterIP      172.20.0.1     <none>                                                                        443/TCP                      5h
    nginx-nginx-ingress   LoadBalancer   172.20.77.13   a17c46026a89c46769b6ac5dd21b5a87-878311181.ap-northeast-2.elb.amazonaws.com   80:31128/TCP,443:32175/TCP   144m

     

    • pod, service, deployment, ingress 확인
    $ kubectl get pods,services,deployment,ingress --namespace=web
    NAME                              READY   STATUS    RESTARTS   AGE
    pod/web-server-74cbbc97fc-v48rx   1/1     Running   0          17m
    
    NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    service/web-server-service   ClusterIP   172.20.93.124   <none>        5000/TCP   17m
    
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/web-server   1/1     1            1           17m
    
    NAME                                           CLASS   HOSTS             ADDRESS                                                                       PORTS   AGE
    ingress.networking.k8s.io/web-server-ingress   nginx   web.example.com   a17c46026a89c46769b6ac5dd21b5a87-878311181.ap-northeast-2.elb.amazonaws.com   80      17m

     

    • 정의한 Ingress 파일 코드 중에 ingressClassName: nginx는 nginx-ingress 사용 의미
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: web-server-ingress
      namespace: web
    spec:
      ingressClassName: nginx
      
    ......

     

    • nginx-ingress name 확인
    $ kubectl edit service nginx-nginx-ingress
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        meta.helm.sh/release-name: nginx
        meta.helm.sh/release-namespace: default
      creationTimestamp: "2022-06-07T03:09:35Z"
      finalizers:
      - service.kubernetes.io/load-balancer-cleanup
      labels:
        app.kubernetes.io/instance: nginx
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: nginx-nginx-ingress
        helm.sh/chart: nginx-ingress-0.13.1
      name: nginx-nginx-ingress
    
    .......

    7-3. Access 확인

    curl a17c46026a89c46769b6ac5dd21b5a87-878311181.ap-northeast-2.elb.amazonaws.com -H "Host: web.example.com"
    
    # curl 결과 확인
    <html><body><h1>It works!</h1></body></html>

     

    EKS 예제 구축 끝 🥊

     

     

    References

    http://dveamer.github.io/backend/TerrafromAwsEks.html

    반응형

    'kubernetes' 카테고리의 다른 글

    [Kubernetes] Object  (0) 2022.10.23
    [Kubernetes] Component  (0) 2022.10.23
    [Kubernetes] Basic concepts  (0) 2022.10.23

    댓글

Designed by Tistory.