Ssoon

[9주차] AWS EKS : VPC CNI : Service & AWS LoadBalancer Controller / Ingress 본문

쿠버네티스 네트워크 스터디 3기

[9주차] AWS EKS : VPC CNI : Service & AWS LoadBalancer Controller / Ingress

구구달스 2024. 10. 28. 22:02
CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 3기

✅ Service & AWS LoadBalancer Controller

  • AWS Load Balancer Controller + NLB IP 모드 동작 with AWS VPC CNI

🧿 IP Target Mode

  • IP Target Mode는 NLB가 특정 IP 주소(예: 파드의 IP)를 대상으로 트래픽을 분배하는 방식입니다. 이 모드를 사용하면 NLB가 클러스터 내의 개별 파드에 직접 트래픽을 보낼 수 있게 됩니다.
  • 기존 방식에서는 NLB가 EC2 인스턴스(노드)에 트래픽을 전달하고, 그 노드가 다시 파드로 트래픽을 전달했습니다. 하지만 IP Target Mode에서는 노드가 아닌 파드의 IP를 직접 타겟으로 설정할 수 있습니다.
  • externalTrafficPolicy
    • 클라이언트의 요청이 서비스에 도달할 때, 원래 클라이언트의 IP 주소를 유지할지 여부를 제어합니다.
    • 두 가지 모드:
      • Cluster: 기본값입니다. 이 모드에서는 클라이언트의 IP 주소가 서비스의 Cluster IP로 변환됩니다. 이 경우, 노드가 요청을 처리하더라도 클라이언트의 원래 IP를 알 수 없습니다.
      • Local: 이 모드에서는 클라이언트의 요청이 해당 서비스의 엔드포인트가 실행 중인 노드로만 전달됩니다. 따라서 요청이 처리되는 노드는 원래 클라이언트의 IP를 유지할 수 있습니다.

🧿 Instance mode

  • 인스턴스 모드에서는 NLB가 Kubernetes의 EC2 인스턴스를 대상으로 하여 트래픽을 라우팅합니다. NLB가 수신한 트래픽은 지정된 EC2 인스턴스로 전달되며, 이 인스턴스가 해당 인스턴스 내에서 실행 중인 파드로 트래픽을 다시 전달합니다.

  • Proxy Protocol v2는 클라이언트와 로드 밸런서 간의 원래 IP 주소와 포트 정보를 전달하기 위해 사용되는 프로토콜입니다.
  • AWS Load Balancer Controller에서 인스턴스 모드를 사용할 때 Proxy Protocol v2를 설정하면, 클라이언트의 IP 주소를 로드 밸런서가 타겟 인스턴스에 전달할 수 있습니다. 이를 통해 인스턴스는 클라이언트의 원래 IP 주소로 트래픽을 처리할 수 있습니다.
    • Proxy Protocol v2 비활성화 ⇒ NLB에서 바로 파드로 인입, 단 ClientIP가 NLB로 SNAT 되어 Client IP 확인 불가능
    • Proxy Protocol v2 활성화 ⇒ NLB에서 바로 파드로 인입 및 ClientIP 확인 가능(→ 단 PPv2 를 애플리케이션이 인지할 수 있게 설정 필요)

🧿 AWS LoadBalancer Controller 배포

  • Helm을 사용하여 AWS EKS 클러스터에 AWS Load Balancer Controller를 설치하는 과정입니다.
  • 이 컨트롤러는 Kubernetes 클러스터 내에서 Elastic Load Balancer (ELB)를 자동으로 관리하고 구성하는 데 사용됩니다. 
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# helm repo add eks https://aws.github.io/eks-charts
"eks" has been added to your repositories
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "eks" chart repository
...Successfully got an update from the "geek-cookbook" chart repository
Update Complete. ⎈Happy Helming!⎈
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME
NAME: aws-load-balancer-controller
LAST DEPLOYED: Mon Oct 28 22:42:56 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

🧿 Kubernetes 클러스터에서 Custom Resource Definition (CRD)을 조회

  • cninodes.vpcresources.k8s.aws
    • AWS VPC CNI 플러그인에서 사용하는 CRD로, Kubernetes 클러스터의 노드에 대한 정보를 저장합니다.
  • eniconfigs.crd.k8s.amazonaws.com
    • AWS VPC CNI 플러그인에 사용되는 CRD로, ENI(Elastic Network Interface) 구성 정보를 정의합니다.
  • ingressclassparams.elbv2.k8s.aws
    • AWS ELB Ingress Controller와 관련된 CRD로, ELB Ingress에 대한 클래스 매개변수를 정의합니다. 이를 통해 사용자 정의 Ingress 리소스의 동작을 제어할 수 있습니다.
  • policyendpoints.networking.k8s.aws
    • AWS 네트워킹 관련 CRD로, 정책 기반 엔드포인트를 정의합니다. Kubernetes의 네트워킹 정책과 통합하여 보다 세밀한 네트워크 제어를 가능하게 합니다.
  • securitygrouppolicies.vpcresources.k8s.aws
    • AWS VPC의 보안 그룹 정책을 정의하는 CRD입니다. 이를 통해 Kubernetes 리소스에 대한 보안 그룹 규칙을 관리할 수 있습니다.
  • targetgroupbindings.elbv2.k8s.aws
    • AWS ELB의 타겟 그룹과 관련된 CRD입니다. Kubernetes 서비스와 AWS ELB 타겟 그룹 간의 바인딩을 관리합니다. 이를 통해 서비스에 대한 트래픽을 ELB를 통해 전달할 수 있습니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get crd
NAME                                         CREATED AT
cninodes.vpcresources.k8s.aws                2024-10-28T12:21:04Z
eniconfigs.crd.k8s.amazonaws.com             2024-10-28T12:24:32Z
ingressclassparams.elbv2.k8s.aws             2024-10-28T13:42:54Z
policyendpoints.networking.k8s.aws           2024-10-28T12:21:04Z
securitygrouppolicies.vpcresources.k8s.aws   2024-10-28T12:21:04Z
targetgroupbindings.elbv2.k8s.aws            2024-10-28T13:42:54Z

🧿 kube-system 네임스페이스에 배포된 aws-load-balancer-controller의 상태를 조회

  • READY: 현재 준비 상태인 파드 수를 나타냅니다. 2/2는 2개의 파드가 모두 준비 상태임을 의미합니다.
    • 즉, 두 개의 파드가 실행 중이고, 두 개 모두 정상적으로 요청을 처리할 준비가 되었다는 것을 나타냅니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get deployment -n kube-system aws-load-balancer-controller
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           32s

🧿 aws-load-balancer-controller의 상세 정보

  • 이 컨트롤러는 Kubernetes 클러스터 내에서 Elastic Load Balancer를 동적으로 생성하고 관리하는 역할을 합니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe deploy -n kube-system aws-load-balancer-controller
Name:                   aws-load-balancer-controller
Namespace:              kube-system
CreationTimestamp:      Mon, 28 Oct 2024 22:42:58 +0900
Labels:                 app.kubernetes.io/instance=aws-load-balancer-controller
                        app.kubernetes.io/managed-by=Helm
                        app.kubernetes.io/name=aws-load-balancer-controller
                        app.kubernetes.io/version=v2.9.2
                        helm.sh/chart=aws-load-balancer-controller-1.9.2
Annotations:            deployment.kubernetes.io/revision: 1
                        meta.helm.sh/release-name: aws-load-balancer-controller
                        meta.helm.sh/release-namespace: kube-system
Selector:               app.kubernetes.io/instance=aws-load-balancer-controller,app.kubernetes.io/name=aws-load-balancer-controller
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:           app.kubernetes.io/instance=aws-load-balancer-controller
                    app.kubernetes.io/name=aws-load-balancer-controller
  Annotations:      prometheus.io/port: 8080
                    prometheus.io/scrape: true
  Service Account:  aws-load-balancer-controller
  Containers:
   aws-load-balancer-controller:
    Image:       public.ecr.aws/eks/aws-load-balancer-controller:v2.9.2
    Ports:       9443/TCP, 8080/TCP
    Host Ports:  0/TCP, 0/TCP
    Args:
      --cluster-name=myeks
      --ingress-class=alb
    Liveness:     http-get http://:61779/healthz delay=30s timeout=10s period=10s #success=1 #failure=2
    Readiness:    http-get http://:61779/readyz delay=10s timeout=10s period=10s #success=1 #failure=2
    Environment:  <none>
    Mounts:
      /tmp/k8s-webhook-server/serving-certs from cert (ro)
  Volumes:
   cert:
    Type:               Secret (a volume populated by a Secret)
    SecretName:         aws-load-balancer-tls
    Optional:           false
  Priority Class Name:  system-cluster-critical
  Node-Selectors:       <none>
  Tolerations:          <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   aws-load-balancer-controller-85d6d654 (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  37s   deployment-controller  Scaled up replica set aws-load-balancer-controller-85d6d654 to 2

🧿 ClusterRoleBinding 정보

  • Kubernetes에서 RBAC(Role-Based Access Control) 설정의 일환으로 특정 리소스에 대한 접근 권한을 정의합니다.
  • aws-load-balancer-controller ServiceAccount에 aws-load-balancer-controller-role이라는 ClusterRole을 연결합니다.
  • 이를 통해 이 ServiceAccount는 AWS Load Balancer Controller가 클러스터 내에서 필요한 작업을 수행할 수 있도록 필요한 권한을 가지게 됩니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
Name:         aws-load-balancer-controller-rolebinding
Labels:       app.kubernetes.io/instance=aws-load-balancer-controller
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=aws-load-balancer-controller
              app.kubernetes.io/version=v2.9.2
              helm.sh/chart=aws-load-balancer-controller-1.9.2
Annotations:  meta.helm.sh/release-name: aws-load-balancer-controller
              meta.helm.sh/release-namespace: kube-system
Role:
  Kind:  ClusterRole
  Name:  aws-load-balancer-controller-role
Subjects:
  Kind            Name                          Namespace
  ----            ----                          ---------
  ServiceAccount  aws-load-balancer-controller  kube-system

🧿ClusterRole 정보

  • aws-load-balancer-controller-role은 AWS Load Balancer Controller가 Kubernetes 리소스와 상호작용하고 AWS의 로드 밸런서를 관리할 수 있도록 하는 권한을 부여합니다. 
  • 이 역할은 다양한 Kubernetes 리소스(예: 서비스, 인그레스, 엔드포인트 등)에 대한 CRUD 작업을 수행할 수 있는 권한을 포함하고 있으며, 로드 밸런서를 설정하고 관리하는 데 필수적인 역할을 합니다.

이 ClusterRole과 관련된 RoleBinding(aws-load-balancer-controller-rolebinding)이 연결되어 있기 때문에, aws-load-balancer-controller ServiceAccount가 이 권한을 사용할 수 있게 됩니다. 

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
Name:         aws-load-balancer-controller-role
Labels:       app.kubernetes.io/instance=aws-load-balancer-controller
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=aws-load-balancer-controller
              app.kubernetes.io/version=v2.9.2
              helm.sh/chart=aws-load-balancer-controller-1.9.2
Annotations:  meta.helm.sh/release-name: aws-load-balancer-controller
              meta.helm.sh/release-namespace: kube-system
PolicyRule:
  Resources                                     Non-Resource URLs  Resource Names  Verbs
  ---------                                     -----------------  --------------  -----
  targetgroupbindings.elbv2.k8s.aws             []                 []              [create delete get list patch update watch]
  events                                        []                 []              [create patch]
  ingresses                                     []                 []              [get list patch update watch]
  services                                      []                 []              [get list patch update watch]
  ingresses.extensions                          []                 []              [get list patch update watch]
  services.extensions                           []                 []              [get list patch update watch]
  ingresses.networking.k8s.io                   []                 []              [get list patch update watch]
  services.networking.k8s.io                    []                 []              [get list patch update watch]
  endpoints                                     []                 []              [get list watch]
  namespaces                                    []                 []              [get list watch]
  nodes                                         []                 []              [get list watch]
  pods                                          []                 []              [get list watch]
  endpointslices.discovery.k8s.io               []                 []              [get list watch]
  ingressclassparams.elbv2.k8s.aws              []                 []              [get list watch]
  ingressclasses.networking.k8s.io              []                 []              [get list watch]
  ingresses/status                              []                 []              [update patch]
  pods/status                                   []                 []              [update patch]
  services/status                               []                 []              [update patch]
  targetgroupbindings/status                    []                 []              [update patch]
  ingresses.elbv2.k8s.aws/status                []                 []              [update patch]
  pods.elbv2.k8s.aws/status                     []                 []              [update patch]
  services.elbv2.k8s.aws/status                 []                 []              [update patch]
  targetgroupbindings.elbv2.k8s.aws/status      []                 []              [update patch]
  ingresses.extensions/status                   []                 []              [update patch]
  pods.extensions/status                        []                 []              [update patch]
  services.extensions/status                    []                 []              [update patch]
  targetgroupbindings.extensions/status         []                 []              [update patch]
  ingresses.networking.k8s.io/status            []                 []              [update patch]
  pods.networking.k8s.io/status                 []                 []              [update patch]
  services.networking.k8s.io/status             []                 []              [update patch]
  targetgroupbindings.networking.k8s.io/status  []                 []              [update patch]

🧿 deploy-echo Deployment와 svc-nlb-ip-type Service 생성

Service: svc-nlb-ip-type

기본 정보

  • apiVersion: v1
  • kind: Service
  • metadata:
    • name: svc-nlb-ip-type
    • annotations:
      • service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip (타겟 타입을 IP로 설정)
      • service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing (인터넷에서 접근 가능한 로드 밸런서)
      • service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080" (헬스 체크 포트 설정)
      • service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" (크로스 존 로드 밸런싱 활성화)

사양 (spec)

  • ports:
    • port: 80 (서비스의 포트)
    • targetPort: 8080 (컨테이너의 포트로 매핑)
    • protocol: TCP (TCP 프로토콜 사용)
  • type: LoadBalancer (AWS의 Load Balancer 생성)
  • loadBalancerClass: service.k8s.aws/nlb (Kubernetes Service 객체가 특정 Load Balancer 구현에 어떻게 매핑되는지를 정의 - 어떤 종류의 Load Balancer를 사용할 것인지 선택)
  • selector:
    • app: deploy-websrv (이 레이블을 가진 Pod와 연결)
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# cat echo-service-nlb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-echo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: akos-websrv
        image: k8s.gcr.io/echoserver:1.5
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: svc-nlb-ip-type
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer
  loadBalancerClass: service.k8s.aws/nlb
  selector:
    app: deploy-websrv(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl apply -f echo-service-nlb.yaml
deployment.apps/deploy-echo created
service/svc-nlb-ip-type created

🧿 EKS 클러스터에서 네트워크 로드 밸런서(NLB)를 사용하여 애플리케이션을 성공적으로 생성하고 배포

서비스의 엔드포인트(Endpoints):

  • svc-nlb-ip-type 서비스는 두 개의 파드와 연결되어 있으며, 이는 로드 밸런서가 이 파드들로 트래픽을 라우팅한다는 것을 의미합니다.

타겟 그룹 바인딩(Target Group Binding):

  • k8s-default-svcnlbip-88642fcd9b라는 이름의 타겟 그룹 바인딩은 서비스와 AWS의 타겟 그룹을 연결합니다.
  • 타겟 타입: ip, 즉 NLB가 파드의 IP 주소로 직접 트래픽을 라우팅한다는 것을 의미합니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get deploy,pod
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-echo   2/2     2            2           24s

NAME                               READY   STATUS    RESTARTS   AGE
pod/deploy-echo-857b6cfb88-7b6wd   1/1     Running   0          24s
pod/deploy-echo-857b6cfb88-84xgg   1/1     Running   0          24s

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get svc,ep,ingressclassparams,targetgroupbindings
NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP                                                                         PORT(S)        AGE
service/kubernetes        ClusterIP      10.100.0.1      <none>                                                                              443/TCP        85m
service/svc-nlb-ip-type   LoadBalancer   10.100.175.82   k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com   80:30109/TCP   28s

NAME                        ENDPOINTS                               AGE
endpoints/kubernetes        192.168.1.234:443,192.168.2.214:443     85m
endpoints/svc-nlb-ip-type   192.168.1.187:8080,192.168.3.104:8080   28s

NAME                                   GROUP-NAME   SCHEME   IP-ADDRESS-TYPE   AGE
ingressclassparams.elbv2.k8s.aws/alb                                           3m20s

NAME                                                               SERVICE-NAME      SERVICE-PORT   TARGET-TYPE   AGE
targetgroupbinding.elbv2.k8s.aws/k8s-default-svcnlbip-88642fcd9b   svc-nlb-ip-type   80             ip            24s

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get targetgroupbindings -o json | jq
{
  "apiVersion": "v1",
  "items": [
    {
      "apiVersion": "elbv2.k8s.aws/v1beta1",
      "kind": "TargetGroupBinding",
      "metadata": {
        "annotations": {
          "elbv2.k8s.aws/checkpoint": "7G0fZ_PRVaPWDkA6Wb2YWPLGtAuQiJ_TqXfrhrsRkW4/QAaIlH_z9wyW9-zuZgGhIBmqPz7_0dRkx4Opm00QGRI",
          "elbv2.k8s.aws/checkpoint-timestamp": "1730123157"
        },
        "creationTimestamp": "2024-10-28T13:45:54Z",
        "finalizers": [
          "elbv2.k8s.aws/resources"
        ],
        "generation": 1,
        "labels": {
          "service.k8s.aws/stack-name": "svc-nlb-ip-type",
          "service.k8s.aws/stack-namespace": "default"
        },
        "name": "k8s-default-svcnlbip-88642fcd9b",
        "namespace": "default",
        "resourceVersion": "18252",
        "uid": "fb046d26-02e5-4613-9cf3-8cc655f9a969"
      },
      "spec": {
        "ipAddressType": "ipv4",
        "networking": {
          "ingress": [
            {
              "from": [
                {
                  "securityGroup": {
                    "groupID": "sg-09b43eda8319a8174"
                  }
                }
              ],
              "ports": [
                {
                  "port": 8080,
                  "protocol": "TCP"
                }
              ]
            }
          ]
        },
        "serviceRef": {
          "name": "svc-nlb-ip-type",
          "port": 80
        },
        "targetGroupARN": "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:targetgroup/k8s-default-svcnlbip-88642fcd9b/c04963c2e941ca94",
        "targetType": "ip",
        "vpcID": "vpc-05d4b16d1fe5aff62"
      },
      "status": {
        "observedGeneration": 1
      }
    }
  ],
  "kind": "List",
  "metadata": {
    "resourceVersion": ""
  }
}

🧿  AWS Network Load Balancer를 설정하여, Kubernetes 클러스터의 파드에 트래픽을 직접 전달하고, 외부에서 접근할 수 있도록 구성

  • service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip:
    • NLB가 파드의 IP 주소로 직접 트래픽을 라우팅하도록 설정합니다. 즉, 트래픽은 서비스가 아니라 파드로 직접 전달됩니다.
  • service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing:
    • 로드 밸런서가 인터넷에 노출되도록 설정합니다. 이를 통해 외부에서 접근할 수 있게 됩니다.
  • service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080":
    • 로드 밸런서의 헬스 체크를 수행할 포트를 지정합니다. 이 경우, 파드의 8080 포트에서 헬스 체크가 수행됩니다.
  • service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true":
    • 여러 가용 영역에 걸쳐 트래픽을 분산시키는 크로스 존 로드 밸런싱을 활성화합니다. 이를 통해 높은 가용성을 확보할 수 있습니다.
  • service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: deregistration_delay.timeout_seconds=60:
    • 타겟 그룹에서 인스턴스가 삭제되기 전에 대기하는 시간(초)을 설정합니다. 여기서는 60초로 설정되어 있어, 인스턴스가 종료되기 전에 요청을 처리할 수 있는 시간을 제공합니다.

  • port: 80: 클라이언트가 요청을 보낼 때 사용할 포트입니다.
  • targetPort: 8080: 요청이 내부적으로 라우팅될 파드의 포트입니다. 클라이언트는 포트 80으로 접근하고, NLB는 이를 파드의 8080 포트로 전달합니다.
apiVersion: v1
kind: Service
metadata:
  name: svc-nlb-ip-type
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
    service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: deregistration_delay.timeout_seconds=60
spec:
  ports:
    - port: 80
      targetPort: 8080

🧿 Kubernetes 클러스터에 echo-service-nlb.yaml 파일을 적용

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl apply -f echo-service-nlb.yaml
deployment.apps/deploy-echo unchanged
service/svc-nlb-ip-type configured

🧿 현재 클러스터에 설정된 Network Load Balancer(NLB)의 상태

가용 영역(Availability Zones)

  • ap-northeast-2b
    • Subnet ID: subnet-093db66b37a73a7b6
  • ap-northeast-2c
    • Subnet ID: subnet-0f1b3dc4334a90ffc
  • ap-northeast-2a
    • Subnet ID: subnet-07847246b9450f59b

NLB는 여러 가용 영역에서 생성되어 있으며, 각 영역의 서브넷에 연결되어 있습니다.

보안 그룹(Security Groups)

  • sg-05182ea4a2342d4ae
  • sg-09b43eda8319a8174
    • NLB에 연결된 보안 그룹입니다. 이 보안 그룹의 규칙에 따라 NLB로 들어오고 나가는 트래픽이 제어됩니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-load-balancers | jq
{
  "LoadBalancers": [
    {
      "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/net/k8s-default-svcnlbip-36e9d416f7/23e42f718d98518f",
      "DNSName": "k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com",
      "CanonicalHostedZoneId": "ZIBE1TIR4HY56",
      "CreatedTime": "2024-10-28T13:45:54.177000+00:00",
      "LoadBalancerName": "k8s-default-svcnlbip-36e9d416f7",
      "Scheme": "internet-facing",
      "VpcId": "vpc-05d4b16d1fe5aff62",
      "State": {
        "Code": "active"
      },
      "Type": "network",
      "AvailabilityZones": [
        {
          "ZoneName": "ap-northeast-2b",
          "SubnetId": "subnet-093db66b37a73a7b6",
          "LoadBalancerAddresses": []
        },
        {
          "ZoneName": "ap-northeast-2c",
          "SubnetId": "subnet-0f1b3dc4334a90ffc",
          "LoadBalancerAddresses": []
        },
        {
          "ZoneName": "ap-northeast-2a",
          "SubnetId": "subnet-07847246b9450f59b",
          "LoadBalancerAddresses": []
        }
      ],
      "SecurityGroups": [
        "sg-05182ea4a2342d4ae",
        "sg-09b43eda8319a8174"
      ],
      "IpAddressType": "ipv4"
    }
  ]
}

🧿 Network Load Balancer(NLB)에 대한 Target Group의 세부 정보

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-default-svcnlbip`) == `true`].LoadBalancerArn' | jq -r '.[0]')
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq
{
  "TargetGroups": [
    {
      "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:targetgroup/k8s-default-svcnlbip-88642fcd9b/c04963c2e941ca94",
      "TargetGroupName": "k8s-default-svcnlbip-88642fcd9b",
      "Protocol": "TCP",
      "Port": 8080,
      "VpcId": "vpc-05d4b16d1fe5aff62",
      "HealthCheckProtocol": "TCP",
      "HealthCheckPort": "8080",
      "HealthCheckEnabled": true,
      "HealthCheckIntervalSeconds": 10,
      "HealthCheckTimeoutSeconds": 10,
      "HealthyThresholdCount": 3,
      "UnhealthyThresholdCount": 3,
      "LoadBalancerArns": [
        "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/net/k8s-default-svcnlbip-36e9d416f7/23e42f718d98518f"
      ],
      "TargetType": "ip",
      "IpAddressType": "ipv4"
    }
  ]
}

🧿 NLB의 Target Group에 대한 상태를 조회

Target Health 정보

  • 타겟 1
    • ID: 192.168.3.104
    • 포트: 8080
    • 가용 영역: ap-northeast-2c
    • 헬스 체크 포트: 8080
    • 상태: healthy 
  • 타겟 2
    • ID: 192.168.1.187
    • 포트: 8080
    • 가용 영역: ap-northeast-2a
    • 헬스 체크 포트: 8080
    • 상태: healthy
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN | jq
{
  "TargetHealthDescriptions": [
    {
      "Target": {
        "Id": "192.168.3.104",
        "Port": 8080,
        "AvailabilityZone": "ap-northeast-2c"
      },
      "HealthCheckPort": "8080",
      "TargetHealth": {
        "State": "healthy"
      },
      "AdministrativeOverride": {
        "State": "no_override",
        "Reason": "AdministrativeOverride.NoOverride",
        "Description": "No override is currently active on target"
      }
    },
    {
      "Target": {
        "Id": "192.168.1.187",
        "Port": 8080,
        "AvailabilityZone": "ap-northeast-2a"
      },
      "HealthCheckPort": "8080",
      "TargetHealth": {
        "State": "healthy"
      },
      "AdministrativeOverride": {
        "State": "no_override",
        "Reason": "AdministrativeOverride.NoOverride",
        "Description": "No override is currently active on target"
      }
    }
  ]
}

🧿 NLB(네트워크 로드 밸런서)의 외부 DNS 이름을 가져와서 Pod 웹 URL을 생성

  • 배포한 echoserver 애플리케이션에 접근
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'
Pod Web URL = http://k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com


🧿 curl 명령어를 통해 로드 밸런서의 DNS 이름에 대한 HTTP 요청을 실행

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# curl -s $NLB


Hostname: deploy-echo-857b6cfb88-7b6wd

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.0 - lua: 10008

Request Information:
        client_address=192.168.1.140
        method=GET
        real path=/
        query=
        request_version=1.1
        request_uri=http://k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com:8080/

Request Headers:
        accept=*/*
        host=k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com
        user-agent=curl/8.3.0

Request Body:
        -no body in request-

 

  • deploy-websrv라는 레이블을 가진 Pod의 로그를 실시간으로 확인
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl logs -l app=deploy-websrv -f
192.168.2.111 - - [28/Oct/2024:13:50:45 +0000] "GET / HTTP/1.1" 200 1094 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
192.168.2.111 - - [28/Oct/2024:13:50:45 +0000] "GET /favicon.ico HTTP/1.1" 200 1116 "http://k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
192.168.1.140 - - [28/Oct/2024:13:51:50 +0000] "GET / HTTP/1.1" 200 690 "-" "curl/8.3.0"

🧿 LoadBalancer의 URL에 대해 100번의 요청

  • deploy-echo-857b6cfb88-7b6wd: 이 호스트는 52번 요청을 처리했습니다.
  • deploy-echo-857b6cfb88-84xgg: 이 호스트는 48번 요청을 처리했습니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     52 Hostname: deploy-echo-857b6cfb88-7b6wd
     48 Hostname: deploy-echo-857b6cfb88-84xgg

🧿 deploy-echo라는 Deployment의 복제본 수를 1로 변경

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl scale deployment deploy-echo --replicas=1
deployment.apps/deploy-echo scaled

Service 상태

  • Service: svc-nlb-ip-type
    • TYPE: LoadBalancer (로드 밸런서 서비스)
    • CLUSTER-IP: 10.100.175.82 (클러스터 내 IP 주소)
    • EXTERNAL-IP: k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com (외부 접근을 위한 IP 주소)
    • PORT(S): 80:30109/TCP (외부 포트 80이 내부 포트 30109와 연결됨)
    • AGE: 10분

Endpoints 상태

  • Endpoints: svc-nlb-ip-type
    • ENDPOINTS: 192.168.3.104:8080 (현재 서비스가 연결된 Pod의 IP 주소와 포트)
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get deploy,pod,svc,ep
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-echo   1/1     1            1           10m

NAME                               READY   STATUS    RESTARTS   AGE
pod/deploy-echo-857b6cfb88-7b6wd   1/1     Running   0          10m

NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP                                                                         PORT(S)        AGE
service/kubernetes        ClusterIP      10.100.0.1      <none>                                                                              443/TCP        95m
service/svc-nlb-ip-type   LoadBalancer   10.100.175.82   k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com   80:30109/TCP   10m

NAME                        ENDPOINTS                             AGE
endpoints/kubernetes        192.168.1.234:443,192.168.2.214:443   95m
endpoints/svc-nlb-ip-type   192.168.3.104:8080                    10m

🧿 curl 명령어를 통해 NLB (Network Load Balancer)로 배포한 서비스를 테스트

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# curl -s $NLB


Hostname: deploy-echo-857b6cfb88-7b6wd

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.0 - lua: 10008

Request Information:
        client_address=192.168.3.121
        method=GET
        real path=/
        query=
        request_version=1.1
        request_uri=http://k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com:8080/

Request Headers:
        accept=*/*
        host=k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com
        user-agent=curl/8.3.0

Request Body:
        -no body in request-

🧿 curl 명령어를 사용하여 NLB (Network Load Balancer)로 100번의 요청

  • 모든 요청이 동일한 Pod에서 처리되었습니다.
  • 총 100번의 요청 중 100번이 모두 deploy-echo-857b6cfb88-7b6wd라는 Pod에서 응답을 받았다는 것을 의미합니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
    100 Hostname: deploy-echo-857b6cfb88-7b6wd

🧿 kubectl scale 명령어를 통해 deploy-echo 배포의 복제본 수를 3으로 조정

  • 서비스 상태 (Service)
    • 서비스 이름: svc-nlb-ip-type
    • 유형: LoadBalancer
    • 클러스터 IP: 10.100.175.82
    • 외부 IP (NLB): k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com
    • 포트: 80:30109/TCP
  • 엔드포인트 (Endpoints)
    • svc-nlb-ip-type의 엔드포인트:
      • 192.168.1.187:8080
      • 192.168.2.96:8080
      • 192.168.3.104:8080
    • NLB가 3개의 Pod를 가리키고 있음을 확인할 수 있습니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl scale deployment deploy-echo --replicas=3
deployment.apps/deploy-echo scaled

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get deploy,pod,svc,ep
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-echo   3/3     3            3           12m

NAME                               READY   STATUS    RESTARTS   AGE
pod/deploy-echo-857b6cfb88-7b6wd   1/1     Running   0          12m
pod/deploy-echo-857b6cfb88-pxxn9   1/1     Running   0          20s
pod/deploy-echo-857b6cfb88-zznb8   1/1     Running   0          20s

NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP                                                                         PORT(S)        AGE
service/kubernetes        ClusterIP      10.100.0.1      <none>                                                                              443/TCP        96m
service/svc-nlb-ip-type   LoadBalancer   10.100.175.82   k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com   80:30109/TCP   12m

NAME                        ENDPOINTS                                                 AGE
endpoints/kubernetes        192.168.1.234:443,192.168.2.214:443                       96m
endpoints/svc-nlb-ip-type   192.168.1.187:8080,192.168.2.96:8080,192.168.3.104:8080   12m

🧿 curl 명령어를 통해 NLB (Network Load Balancer)로 배포한 서비스를 테스트

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# curl -s $NLB


Hostname: deploy-echo-857b6cfb88-pxxn9

Pod Information:
        -no pod information available-

Server values:
        server_version=nginx: 1.13.0 - lua: 10008

Request Information:
        client_address=192.168.3.121
        method=GET
        real path=/
        query=
        request_version=1.1
        request_uri=http://k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com:8080/

Request Headers:
        accept=*/*
        host=k8s-default-svcnlbip-36e9d416f7-23e42f718d98518f.elb.ap-northeast-2.amazonaws.com
        user-agent=curl/8.3.0

Request Body:
        -no body in request-

 


🧿 curl 명령어를 사용하여 NLB (Network Load Balancer)로 100번의 요청

  • deploy-echo-857b6cfb88-pxxn9: 38 요청
  • deploy-echo-857b6cfb88-zznb8: 32 요청
  • deploy-echo-857b6cfb88-7b6wd: 30 요청

이 결과는 NLB가 여러 Pod로 요청을 균등하게 분산하고 있다는 것을 나타냅니다.

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     38 Hostname: deploy-echo-857b6cfb88-pxxn9
     32 Hostname: deploy-echo-857b6cfb88-zznb8
     30 Hostname: deploy-echo-857b6cfb88-7b6wd

🧿 aws-load-balancer-controller 배포의 세부 정보 "Service Account" 항목 확인

  • "Service Account" 항목에서 aws-load-balancer-controller가 표시되었습니다. 이는 AWS Load Balancer Controller가 사용하는 서비스 계정을 나타냅니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe deploy -n kube-system aws-load-balancer-controller | grep -i 'Service Account'
  Service Account:  aws-load-balancer-controller

🧿 aws-load-balancer-controller-rolebinding에 대한 세부 정보

AWS Load Balancer Controller가 사용하고 있는 ClusterRole은 aws-load-balancer-controller-role이라는 이름으로 설정되어 있으며, 이 역할이 부여한 권한은 다음과 같은 Kubernetes API 작업을 포함할 수 있습니다:

  • LoadBalancer 서비스 생성 및 삭제
  • ELB (Elastic Load Balancer) 관련 리소스 관리
  • Health Check 설정 및 모니터링
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
Name:         aws-load-balancer-controller-rolebinding
Labels:       app.kubernetes.io/instance=aws-load-balancer-controller
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=aws-load-balancer-controller
              app.kubernetes.io/version=v2.9.2
              helm.sh/chart=aws-load-balancer-controller-1.9.2
Annotations:  meta.helm.sh/release-name: aws-load-balancer-controller
              meta.helm.sh/release-namespace: kube-system
Role:
  Kind:  ClusterRole
  Name:  aws-load-balancer-controller-role
Subjects:
  Kind            Name                          Namespace
  ----            ----                          ---------
  ServiceAccount  aws-load-balancer-controller  kube-system

🧿 aws-load-balancer-controller-role에 대한 세부 정보

리소스 작업(Verbs) 설명
targetgroupbindings.elbv2.k8s.aws create, delete, get, list, patch, update, watch Target Group Bindings 생성 및 관리
events create, patch Kubernetes 이벤트 생성 및 수정
ingresses, services, endpoints, namespaces, nodes, pods, endpointslices, ingressclasses  get, list, patch, update, watch 다양한 Kubernetes 리소스에 대한 조회 및 수정 권한
ingresses/status, pods/status, services/status  update, patch 특정 리소스의 상태 업데이트
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
Name:         aws-load-balancer-controller-role
Labels:       app.kubernetes.io/instance=aws-load-balancer-controller
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=aws-load-balancer-controller
              app.kubernetes.io/version=v2.9.2
              helm.sh/chart=aws-load-balancer-controller-1.9.2
Annotations:  meta.helm.sh/release-name: aws-load-balancer-controller
              meta.helm.sh/release-namespace: kube-system
PolicyRule:
  Resources                                     Non-Resource URLs  Resource Names  Verbs
  ---------                                     -----------------  --------------  -----
  targetgroupbindings.elbv2.k8s.aws             []                 []              [create delete get list patch update watch]
  events                                        []                 []              [create patch]
  ingresses                                     []                 []              [get list patch update watch]
  services                                      []                 []              [get list patch update watch]
  ingresses.extensions                          []                 []              [get list patch update watch]
  services.extensions                           []                 []              [get list patch update watch]
  ingresses.networking.k8s.io                   []                 []              [get list patch update watch]
  services.networking.k8s.io                    []                 []              [get list patch update watch]
  endpoints                                     []                 []              [get list watch]
  namespaces                                    []                 []              [get list watch]
  nodes                                         []                 []              [get list watch]
  pods                                          []                 []              [get list watch]
  endpointslices.discovery.k8s.io               []                 []              [get list watch]
  ingressclassparams.elbv2.k8s.aws              []                 []              [get list watch]
  ingressclasses.networking.k8s.io              []                 []              [get list watch]
  ingresses/status                              []                 []              [update patch]
  pods/status                                   []                 []              [update patch]
  services/status                               []                 []              [update patch]
  targetgroupbindings/status                    []                 []              [update patch]
  ingresses.elbv2.k8s.aws/status                []                 []              [update patch]
  pods.elbv2.k8s.aws/status                     []                 []              [update patch]
  services.elbv2.k8s.aws/status                 []                 []              [update patch]
  targetgroupbindings.elbv2.k8s.aws/status      []                 []              [update patch]
  ingresses.extensions/status                   []                 []              [update patch]
  pods.extensions/status                        []                 []              [update patch]
  services.extensions/status                    []                 []              [update patch]
  targetgroupbindings.extensions/status         []                 []              [update patch]
  ingresses.networking.k8s.io/status            []                 []              [update patch]
  pods.networking.k8s.io/status                 []                 []              [update patch]
  services.networking.k8s.io/status             []                 []              [update patch]
  targetgroupbindings.networking.k8s.io/status  []                 []              [update patch]

🧿 리소스 삭제

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl delete deploy deploy-echo; kubectl delete svc svc-nlb-ip-type
deployment.apps "deploy-echo" deleted
service "svc-nlb-ip-type" deleted

✅ Ingress

  • HTTP(S) 요청 라우팅: Ingress는 주로 HTTP 또는 HTTPS 요청을 처리합니다. 클러스터 외부에서 들어오는 요청을 기반으로, 요청의 URL 경로(path) 또는 호스트(host)에 따라 특정 서비스를 선택하여 전달합니다.
  • 여러 서비스 통합: 하나의 인그레스 리소스를 통해 여러 서비스를 관리할 수 있습니다. 예를 들어, 같은 도메인에서 /api 요청은 API 서비스로, /web 요청은 웹 애플리케이션 서비스로 라우팅할 수 있습니다.
    • 중앙화된 트래픽 관리: 여러 서비스를 하나의 Ingress로 통합하여 외부 요청을 효율적으로 관리할 수 있습니다.
    • SSL 종료: HTTPS 요청을 처리할 수 있어, SSL 인증서 관리 및 HTTPS로의 트래픽 암호화를 쉽게 설정할 수 있습니다.
    • 로드 밸런싱: Ingress Controller는 요청을 적절히 분산시켜 클러스터 내의 서비스에 부하를 효율적으로 분산합니다.

🧿 Ingress Controller

Ingress 리소스만으로는 트래픽을 관리할 수 없으며, Ingress Controller가 필요합니다. Ingress Controller는 Ingress 리소스의 설정을 모니터링하고, 실제로 외부 트래픽을 내부 서비스로 라우팅하는 역할을 합니다.

  • AWS에서의 Ingress Controller
    • AWS Load Balancer Controller: AWS EKS에서 가장 많이 사용되는 Ingress Controller로, Application Load Balancer(ALB)와 Network Load Balancer(NLB)를 사용하여 Ingress 리소스를 처리합니다.

 


🧿 ingress1.yaml 구성을 적용하여 Kubernetes 클러스터에 2048 게임 애플리케이션을 위한 새로운 네임스페이스, 배포, 서비스 및 인그레스를 생성

서비스 (Service)

  • 이름: service-2048
  • 유형: NodePort
  • 포트: 80
  • 이 서비스는 포트 80에서 애플리케이션에 접근할 수 있도록 노출하며, NodePort 유형은 각 노드에서 할당된 포트를 통해 이 서비스로 트래픽을 라우팅합니다.

인그레스 (Ingress)

  • 이름: ingress-2048
  • 주석:
    • alb.ingress.kubernetes.io/scheme: internet-facing: 애플리케이션 로드 밸런서를 공개적으로 접근 가능하게 만듭니다.
    • alb.ingress.kubernetes.io/target-type: ip: 로드 밸런서의 타겟이 IP 주소가 됨을 지정합니다.
  • 규칙: HTTP 트래픽을 백엔드 서비스로 라우팅하는 규칙을 정의합니다:
    • / 경로와 일치하는 트래픽은 포트 80의 service-2048로 전달됩니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ingress1.yaml
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# cat ingress1.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game-2048
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 2
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
        imagePullPolicy: Always
        name: app-2048
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: game-2048
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:
                number: 80(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl apply -f ingress1.yaml
namespace/game-2048 created
deployment.apps/deployment-2048 created
service/service-2048 created
ingress.networking.k8s.io/ingress-2048 created

🧿 Kubernetes 클러스터에서 game-2048 네임스페이스에 있는 모든 리소스

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get-all -n game-2048
NAME                                                               NAMESPACE  AGE
configmap/kube-root-ca.crt                                         game-2048  34s
endpoints/service-2048                                             game-2048  34s
pod/deployment-2048-85f8c7d69-h4v4q                                game-2048  34s
pod/deployment-2048-85f8c7d69-tr5sr                                game-2048  34s
serviceaccount/default                                             game-2048  34s
service/service-2048                                               game-2048  34s
deployment.apps/deployment-2048                                    game-2048  34s
replicaset.apps/deployment-2048-85f8c7d69                          game-2048  34s
endpointslice.discovery.k8s.io/service-2048-mqc4r                  game-2048  34s
targetgroupbinding.elbv2.k8s.aws/k8s-game2048-service2-8a026736f8  game-2048  29s
ingress.networking.k8s.io/ingress-2048                             game-2048  34s

🧿  game-2048 네임스페이스에서 ingress, service, endpoints, pod의 상태

Ingress

  • 이름: ingress-2048
  • 클래스: alb (AWS Application Load Balancer 사용)
  • 호스트: * (모든 호스트 요청을 처리)
  • 주소: AWS ELB의 DNS 주소 (클러스터 외부에서 접근 가능)
  • 포트: 80 (HTTP 기본 포트)

Service

  • 이름: service-2048
  • 유형: NodePort (클러스터의 모든 노드에서 접근 가능)
  • 클러스터 IP: 10.100.233.143 (클러스터 내에서의 서비스 주소)
  • 외부 IP: <none> (NodePort 타입이라 외부 IP 없음)
  • 포트: 80:30617/TCP (서비스 포트 80을 NodePort 30617로 매핑)

Endpoints

  • 이름: endpoints/service-2048
  • 엔드포인트: 192.168.1.162:80, 192.168.3.104:80 (서비스가 요청을 전달할 Pod의 IP 주소)
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get ingress,svc,ep,pod -n game-2048
NAME                                     CLASS   HOSTS   ADDRESS                                                                       PORTS   AGE
ingress.networking.k8s.io/ingress-2048   alb     *       k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com   80      60s

NAME                   TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/service-2048   NodePort   10.100.233.143   <none>        80:30617/TCP   60s

NAME                     ENDPOINTS                           AGE
endpoints/service-2048   192.168.1.162:80,192.168.3.104:80   60s

NAME                                  READY   STATUS    RESTARTS   AGE
pod/deployment-2048-85f8c7d69-h4v4q   1/1     Running   0          60s
pod/deployment-2048-85f8c7d69-tr5sr   1/1     Running   0          60s

🧿 TargetGroupBinding 리소스

  • 이름: k8s-game2048-service2-8a026736f8
  • 서비스 이름: service-2048 (대상 서비스의 이름)
  • 서비스 포트: 80 (서비스가 사용하는 포트)
  • 타겟 타입: ip (대상으로 사용되는 IP 주소)
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get targetgroupbindings -n game-2048
NAME                               SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE
k8s-game2048-service2-8a026736f8   service-2048   80             ip            60s

🧿 k8s-game2048로 이름이 포함된 로드 밸런서에 대한 정보

  • Load Balancer ARN: arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/app/k8s-game2048-ingress2-70d50ce3fd/c8ccd68d149c6cfa
    • 로드 밸런서를 고유하게 식별하는 Amazon 리소스 이름입니다.
  • DNS 이름: k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com
    • 외부에서 접근할 수 있는 로드 밸런서의 DNS 주소입니다.
  • 유형: application
    • 애플리케이션 로드 밸런서입니다.

가용성 영역

  • ap-northeast-2a, ap-northeast-2b, ap-northeast-2c
    • 로드 밸런서가 배포된 가용성 영역입니다. 각 영역은 서로 다른 서브넷에 속해 있습니다.

보안 그룹

  • Security Groups: sg-0230ab46b51aa0987, sg-09c1d9d6680a6db2f
    • 로드 밸런서에 적용된 보안 그룹입니다. 이는 네트워크 트래픽을 제어하는 역할을 합니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`]' | jq
[
  {
    "LoadBalancerArn": "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/app/k8s-game2048-ingress2-70d50ce3fd/c8ccd68d149c6cfa",
    "DNSName": "k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com",
    "CanonicalHostedZoneId": "ZWKZPGTI48KDX",
    "CreatedTime": "2024-10-28T14:03:28.765000+00:00",
    "LoadBalancerName": "k8s-game2048-ingress2-70d50ce3fd",
    "Scheme": "internet-facing",
    "VpcId": "vpc-05d4b16d1fe5aff62",
    "State": {
      "Code": "provisioning"
    },
    "Type": "application",
    "AvailabilityZones": [
      {
        "ZoneName": "ap-northeast-2a",
        "SubnetId": "subnet-07847246b9450f59b",
        "LoadBalancerAddresses": []
      },
      {
        "ZoneName": "ap-northeast-2b",
        "SubnetId": "subnet-093db66b37a73a7b6",
        "LoadBalancerAddresses": []
      },
      {
        "ZoneName": "ap-northeast-2c",
        "SubnetId": "subnet-0f1b3dc4334a90ffc",
        "LoadBalancerAddresses": []
      }
    ],
    "SecurityGroups": [
      "sg-0230ab46b51aa0987",
      "sg-09c1d9d6680a6db2f"
    ],
    "IpAddressType": "ipv4"
  }
]

🧿 Application Load Balancer (ALB)에서 사용 중인 대상 그룹에 대한 정보

Target Group 정보

  • Target Group ARN: arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:targetgroup/k8s-game2048-service2-8a026736f8/c12e0c9e323fd83e
    • 대상 그룹을 고유하게 식별하는 Amazon 리소스 이름입니다.
  • Target Group Name: k8s-game2048-service2-8a026736f8
  • 프로토콜: HTTP
    • 대상 그룹이 사용하는 프로토콜입니다.
  • 포트: 80
    • HTTP 요청을 처리하는 포트입니다.
  • VPC ID: vpc-05d4b16d1fe5aff62
    • 대상 그룹이 속한 VPC의 ID입니다.

헬스 체크 설정

  • 헬스 체크 프로토콜: HTTP
  • 헬스 체크 포트: traffic-port (대상 그룹에서 사용 중인 포트)
  • 헬스 체크 활성화: true (헬스 체크가 활성화됨)
  • 헬스 체크 간격: 15초 (헬스 체크 주기)
  • 헬스 체크 타임아웃: 5초 (응답 대기 시간)
  • Healthy Threshold Count: 2 (헬스 체크가 성공으로 간주되기 위해 필요한 연속 성공 횟수)
  • Unhealthy Threshold Count: 2 (헬스 체크가 실패로 간주되기 위해 필요한 연속 실패 횟수)
  • 헬스 체크 경로: / (헬스 체크 요청을 보낼 경로)
  • 매처: HttpCode: 200 (헬스 체크 성공 조건으로, HTTP 200 응답을 기대)

로드 밸런서 ARN

  • LoadBalancerArns:
    • arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/app/k8s-game2048-ingress2-70d50ce3fd/c8ccd68d149c6cfa
    • 이 대상 그룹에 연결된 로드 밸런서의 ARN입니다.

타겟 타입

  • 타겟 타입: ip
    • 대상 그룹이 IP 주소를 사용하여 트래픽을 분배합니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`].LoadBalancerArn' | jq -r '.[0]')
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN
{
    "TargetGroups": [
        {
            "TargetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:targetgroup/k8s-game2048-service2-8a026736f8/c12e0c9e323fd83e",
            "TargetGroupName": "k8s-game2048-service2-8a026736f8",
            "Protocol": "HTTP",
            "Port": 80,
            "VpcId": "vpc-05d4b16d1fe5aff62",
            "HealthCheckProtocol": "HTTP",
            "HealthCheckPort": "traffic-port",
            "HealthCheckEnabled": true,
            "HealthCheckIntervalSeconds": 15,
            "HealthCheckTimeoutSeconds": 5,
            "HealthyThresholdCount": 2,
            "UnhealthyThresholdCount": 2,
            "HealthCheckPath": "/",
            "Matcher": {
                "HttpCode": "200"
            },
            "LoadBalancerArns": [
                "arn:aws:elasticloadbalancing:ap-northeast-2:992382835044:loadbalancer/app/k8s-game2048-ingress2-70d50ce3fd/c8ccd68d149c6cfa"
            ],
            "TargetType": "ip",
            "ProtocolVersion": "HTTP1",
            "IpAddressType": "ipv4"
        }
    ]
}

🧿 대상 그룹의 Target Health 정보

1. 첫 번째 타겟

  • ID: 192.168.3.104
    • Pod의 IP 주소입니다.
  • 포트: 80
    • 헬스 체크가 수행되는 포트입니다.
  • 가용성 영역: ap-northeast-2c
    • 이 타겟이 위치한 AWS 가용성 영역입니다.
  • 헬스 체크 포트: 80
    • 실제 헬스 체크가 수행되는 포트입니다.
  • 상태: healthy
    • 헬스 체크 결과 이 타겟이 정상 상태임을 나타냅니다.

2. 두 번째 타겟

  • ID: 192.168.1.162
    • 다른 Pod의 IP 주소입니다.
  • 포트: 80
    • 헬스 체크가 수행되는 포트입니다.
  • 가용성 영역: ap-northeast-2a
    • 이 타겟이 위치한 AWS 가용성 영역입니다.
  • 헬스 체크 포트: 80
    • 실제 헬스 체크가 수행되는 포트입니다.
  • 상태: healthy
    • 헬스 체크 결과 이 타겟이 정상 상태임을 나타냅니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN | jq
{
  "TargetHealthDescriptions": [
    {
      "Target": {
        "Id": "192.168.3.104",
        "Port": 80,
        "AvailabilityZone": "ap-northeast-2c"
      },
      "HealthCheckPort": "80",
      "TargetHealth": {
        "State": "healthy"
      }
    },
    {
      "Target": {
        "Id": "192.168.1.162",
        "Port": 80,
        "AvailabilityZone": "ap-northeast-2a"
      },
      "HealthCheckPort": "80",
      "TargetHealth": {
        "State": "healthy"
      }
    }
  ]
}

🧿 ingress-2048 리소스의 세부 정보

Ingress 정보

  • 이름: ingress-2048
  • 네임스페이스: game-2048
  • 주소: k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com
    • 이 Ingress를 통해 외부에서 접근할 수 있는 AWS ELB의 DNS 이름입니다.
  • Ingress 클래스: alb
    • AWS의 Application Load Balancer(ALB)를 사용하고 있음을 나타냅니다.
  • 디폴트 백엔드: <default>
    • 기본 백엔드가 설정되어 있지 않음을 나타냅니다.

규칙

  • 호스트: * (모든 호스트)
    • 모든 호스트의 요청을 처리하도록 설정되어 있습니다.
  • 경로: /
    • 모든 경로의 요청을 처리합니다.
  • 백엔드: service-2048:80
    • 요청이 service-2048 서비스의 80번 포트로 전달됩니다.
    • 대상 IP 주소: 192.168.1.162:80, 192.168.3.104:80
      • 이 서비스에 연결된 두 개의 Pod의 IP 주소입니다.

주석 (Annotations)

  • alb.ingress.kubernetes.io/scheme: internet-facing
    • 이 Ingress가 인터넷에서 접근 가능하다는 것을 의미합니다.
  • alb.ingress.kubernetes.io/target-type: ip
    • 트래픽이 IP 주소를 통해 전달됨을 나타냅니다.
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl describe ingress -n game-2048 ingress-2048
Name:             ingress-2048
Labels:           <none>
Namespace:        game-2048
Address:          k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com
Ingress Class:    alb
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   service-2048:80 (192.168.1.162:80,192.168.3.104:80)
Annotations:  alb.ingress.kubernetes.io/scheme: internet-facing
              alb.ingress.kubernetes.io/target-type: ip
Events:
  Type    Reason                  Age    From     Message
  ----    ------                  ----   ----     -------
  Normal  SuccessfullyReconciled  3m24s  ingress  Successfully reconciled
  
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get ingress -n game-2048 ingress-2048 -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"
k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com

🧿 game-2048 네임스페이스에 배포된 서비스에 접근

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get ingress -n game-2048 ingress-2048 -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Game URL = http://"$1 }'
Game URL = http://k8s-game2048-ingress2-70d50ce3fd-808030810.ap-northeast-2.elb.amazonaws.com


🧿 game-2048 네임스페이스에서 실행 중인 Pod의 상세 정보

  • 두 Pod는 각각 다른 노드에서 실행되고 있습니다:
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl get pod -n game-2048 -owide
NAME                              READY   STATUS    RESTARTS   AGE     IP              NODE                                               NOMINATED NODE   READINESS GATES
deployment-2048-85f8c7d69-h4v4q   1/1     Running   0          4m46s   192.168.1.162   ip-192-168-1-111.ap-northeast-2.compute.internal   <none>
<none>
deployment-2048-85f8c7d69-tr5sr   1/1     Running   0          4m46s   192.168.3.104   ip-192-168-3-215.ap-northeast-2.compute.internal   <none>
<none>


🧿 game-2048 네임스페이스에 있는 deployment-2048의 복제본 수를 3으로 조정

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl scale deployment -n game-2048 deployment-2048 --replicas 3
deployment.apps/deployment-2048 scaled


🧿 game-2048 네임스페이스에 있는 deployment-2048의 복제본 수를 1으로 조정

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl scale deployment -n game-2048 deployment-2048 --replicas 1
deployment.apps/deployment-2048 scaled


🧿 리소스 삭제

(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl delete ingress ingress-2048 -n game-2048
ingress.networking.k8s.io "ingress-2048" deleted
(iam-root-account@myeks:N/A) [root@myeks-bastion ~]# kubectl delete svc service-2048 -n game-2048 && kubectl delete deploy deployment-2048 -n game-2048 && kubectl delete ns game-2048
service "service-2048" deleted
deployment.apps "deployment-2048" deleted
namespace "game-2048" deleted
Comments