> For the complete documentation index, see [llms.txt](https://kubernetes.youngwjung.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kubernetes.youngwjung.com/core-concepts/ingress/lab.md).

# 실습

## Ingress-NGINX Controller

### Introduction

1. Helm 차트 리포지토리 추가&#x20;

   ```
   {
       helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
       helm repo update
   }
   ```
2. Ingress-NGINX  Controller 설치&#x20;

   ```
   helm install ingress-nginx ingress-nginx/ingress-nginx -n kube-system \
   --set controller.service.annotations.service\\.beta\\.kubernetes\\.io/aws-load-balancer-type=nlb
   ```
3. 배포된 구성요소 확인&#x20;

   ```
   kubectl -n kube-system get all -l app.kubernetes.io/name=ingress-nginx
   ```
4. 생성된 Service 확인

   ```
   kubectl -n kube-system get svc ingress-nginx-controller
   ```
5. 생성된 NLB 상세 내용 확인

   ```
   aws elbv2 describe-load-balancers --names \
   $(kubectl -n kube-system get svc ingress-nginx-controller \
   -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' \
   | grep -o -E '^[a-z0-9]+' ) --no-cli-pager
   ```
6. 웹 브라우저를 열고 Service의 External IP 주소로 접속 - *아래의 명령어로 주소 확인 가능*&#x20;

   ```
   kubectl -n kube-system get svc ingress-nginx-controller \
   -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}' 
   ```
7. 생성된 NGINX Ingress Controller Pod에서 실행중인 프로세스 확인&#x20;

   ```
   kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
   ps aux
   ```
8. NGINX 설정 파일 리뷰&#x20;

   ```
   kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
   cat /etc/nginx/nginx.conf
   ```
9. 생성된 NLB 주소로 접속했을때 404 Not Found가 나오는 이유 확인

   ```
   kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
   cat /etc/nginx/nginx.conf | grep 404 -B 9 -A 2
   ```

### Virtual hosting

1. Deployment 생성&#x20;

   ```
   {
       kubectl create deployment nginx --image=nginx --port=80
       kubectl create deployment httpd --image=httpd --port=80
   }
   ```
2. Service 생성&#x20;

   ```
   {
       kubectl expose deploy nginx 
       kubectl expose deploy httpd
   }
   ```
3. 생성된 Service 확인&#x20;

   ```
   kubectl get svc -l app
   ```
4. Ingress 생성&#x20;

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: nginx
   spec:
     rules:
     - host: nginx.example.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service:
               name: nginx
               port:
                 number: 80
   ---
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: httpd
   spec:
     rules:
     - host: httpd.example.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service:
               name: httpd
               port:
                 number: 80
   EOF
   ```
5. 생성된 Ingress 확인 &#x20;

   ```
   kubectl get ing
   ```
6. NGINX Ingress Controller 로그 확인

   ```
   kubectl logs -n kube-system deploy/ingress-nginx-controller
   ```
7. 생성된 IngressClass 확인

   ```
   kubectl get ingressclass
   ```
8. Ingress 수정 - *IngressClass 명시*

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: nginx
   spec:
     ingressClassName: nginx
     rules:
     - host: nginx.example.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service:
               name: nginx
               port:
                 number: 80
   ---
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: httpd
   spec:
     ingressClassName: nginx
     rules:
     - host: httpd.example.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service:
               name: httpd
               port:
                 number: 80
   EOF
   ```
9. Ingress 객체에 발생한 Event 확인 &#x20;

   ```
   kubectl describe ing
   ```
10. NGINX Ingress Controller 엔드포인트 확인 &#x20;

    ```
    kubectl -n kube-system get svc ingress-nginx-controller
    ```
11. NGINX Ingress Controller 로그 확인

    ```
    kubectl logs -n kube-system deploy/ingress-nginx-controller
    ```
12. Ingress에 명시한 Host 주소를 HTTP 헤더값에 추가하고 NGINX Ingress Controller 엔드포인트 호출

    ```
    curl -H "Host: nginx.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    ```

    ```
    curl -H "Host: httpd.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    ```
13. NGINX 설정 파일에 위에서 명시한 Host들에 대한 설정들이 추가 되었는지 확인&#x20;

    ```
    kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
    cat /etc/nginx/nginx.conf \
    | grep "server_name nginx.example.com" -B 1 -A 130
    ```

    ```
    kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
    cat /etc/nginx/nginx.conf \
    | grep "server_name httpd.example.com" -B 1 -A 130
    ```
14. Ingress 삭제

    ```
    kubectl delete ing nginx httpd
    ```
15. NGINX 설정 파일에 위에서 삭제한 Ingress 명시한 Host들에 대한 설정들이 삭제 되었는지 확인

    ```
    kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
    cat /etc/nginx/nginx.conf \
    | grep "server_name nginx.example.com" -B 1 -A 130
    ```

    ```
    kubectl -n kube-system exec deploy/ingress-nginx-controller -- \
    cat /etc/nginx/nginx.conf \
    | grep "server_name httpd.example.com" -B 1 -A 130
    ```
16. 리소스 삭제

    ```
    {
        kubectl delete svc nginx httpd
        kubectl delete deploy nginx httpd
    }
    ```

### Path based routing

1. 리소스 생성

   ```
   {
       kubectl create deployment nginx --image=nginx --port=80
       kubectl create deployment httpd --image=httpd --port=80
       kubectl expose deploy nginx 
       kubectl expose deploy httpd
   }
   ```
2. 생성된 리소스 확인

   ```
   kubectl get all -l app
   ```
3. Ingress 생성

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-app
   spec:
     ingressClassName: nginx
     rules:
     - host: myapp.example.com
       http:
         paths:
         - path: /nginx
           pathType: Prefix
           backend:
             service:
               name: nginx
               port:
                 number: 80
         - path: /httpd
           pathType: Prefix
           backend:
             service:
               name: httpd
               port:
                 number: 80
   EOF
   ```
4. Ingress 객체에 발생한 Event 확인 &#x20;

   ```
   kubectl describe ing
   ```
5. NGINX Ingress Controller 로그 확인

   ```
   kubectl logs -n kube-system deploy/ingress-nginx-controller
   ```
6. Ingress에 명시한 Host 주소를 HTTP 헤더값에 추가하고 각각의 경로로 NGINX Ingress Controller 엔드포인트 호출

   ```
   curl -H "Host: myapp.example.com" \
   $(kubectl -n kube-system get svc ingress-nginx-controller \
   -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/nginx
   ```

   ```
   curl -H "Host: myapp.example.com" \
   $(kubectl -n kube-system get svc ingress-nginx-controller \
   -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/httpd
   ```
7. NGINX Ingress Controller 로그 확인

   ```
   kubectl logs -n kube-system deploy/ingress-nginx-controller
   ```

   e.g.

   ```
   52.78.3.76 - - [24/Jul/2022:08:16:10 +0000] "GET /nginx HTTP/1.1" 404 153 "-" "curl/7.79.1" 86 0.003 [default-nginx-80] [] 192.168.44.219:80 153 0.004 404 b69bb70369b94d0208af4cf26d5f19a5
   52.78.3.76 - - [24/Jul/2022:08:16:21 +0000] "GET /httpd HTTP/1.1" 404 196 "-" "curl/7.79.1" 86 0.001 [default-httpd-80] [] 192.168.88.56:80 196 0.000 404 efdfacfbf5858ebc27a01dcb815da8d9
   ```
8. Ingress 수정 - <https://kubernetes.github.io/ingress-nginx/examples/rewrite/>&#x20;

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-app
     annotations:
       nginx.ingress.kubernetes.io/rewrite-target: /
   spec:
     ingressClassName: nginx
     rules:
     - host: myapp.example.com
       http:
         paths:
         - path: /nginx
           pathType: Prefix
           backend:
             service:
               name: nginx
               port:
                 number: 80
         - path: /httpd
           pathType: Prefix
           backend:
             service:
               name: httpd
               port:
                 number: 80
   EOF
   ```
9. NGINX Ingress Controller 로그 확인

   ```
   kubectl logs -n kube-system deploy/ingress-nginx-controller
   ```
10. Ingress에 명시한 Host 주소를 HTTP 헤더값에 추가하고 각각의 경로로 NGINX Ingress Controller 엔드포인트 호출

    ```
    curl -H "Host: myapp.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/nginx
    ```

    ```
    curl -H "Host: myapp.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/httpd
    ```
11. 새로운 리소스 생성

    ```
    {
        kubectl create deployment v1 --image=youngwjung/nginx:v1 --port=80
        kubectl create deployment v2 --image=youngwjung/nginx:v2 --port=80
        kubectl expose deploy v1 
        kubectl expose deploy v2
    }
    ```
12. 새로 배포한 애플리케이션 호출

    ```
    kubectl exec deploy/v1 -- curl -s localhost
    ```

    ```
    kubectl exec deploy/v2 -- curl -s localhost
    ```
13. Ingress 수정

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-app
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      ingressClassName: nginx
      rules:
      - host: myapp.example.com
        http:
          paths:
          - path: /nginx
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
          - path: /httpd
            pathType: Prefix
            backend:
              service:
                name: httpd
                port:
                  number: 80
          - path: /nginx/v1
            pathType: Exact
            backend:
              service:
                name: v1
                port:
                  number: 80
          - path: /httpd/v2
            pathType: Exact
            backend:
              service:
                name: v2
                port:
                  number: 80
    EOF
    ```
14. NGINX Ingress Controller 로그 확인

    ```
    kubectl logs -n kube-system deploy/ingress-nginx-controller
    ```
15. Ingress에 명시한 Host 주소를 HTTP 헤더값에 추가하고 새롭게 명시한 경로들로 NGINX Ingress Controller 엔드포인트 호출

    ```
    curl -H "Host: myapp.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/nginx/v1
    ```

    ```
    curl -H "Host: myapp.example.com" \
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/httpd/v2
    ```
16. 리소스 삭제

    ```
    {
        kubectl delete svc nginx httpd v1 v2
        kubectl delete deploy nginx httpd v1 v2
        kubectl delete ing my-app
    }
    ```

### TLS/SSL

1. CFSSL 설치

   ```
   {
       VERSION=$(curl --silent "https://api.github.com/repos/cloudflare/cfssl/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
       VNUMBER=${VERSION#"v"}
       wget https://github.com/cloudflare/cfssl/releases/download/${VERSION}/cfssl_${VNUMBER}_linux_amd64 -O cfssl
       chmod +x cfssl
       sudo mv cfssl /usr/local/bin
   }
   ```
2. CA 인증서 및 CA 사설키 생성

   ```
   cat > ca.json <<EOF
   {
     "CN": "mycompany",
     "key": {
       "algo": "rsa",
       "size": 2048
     },
     "names": [
       {
         "C": "KR",
         "O": "mycompany",
         "OU": "devops"
       }
     ]
   }
   EOF
   cfssl gencert -initca ca.json | cfssljson -bare ca
   ```
3. CA 설정파일 생성

   ```
   cat > ca-config.json <<EOF
   {
     "signing": {
       "default": {
         "expiry": "8760h"
       },
       "profiles": {
         "mycompany": {
           "usages": ["signing", "key encipherment", "server auth"],
           "expiry": "8760h"
         }
       }
     }
   }
   EOF
   ```
4. 인증서 생성요청 설정파일 생성

   ```
   cat > mycompany-csr.json <<EOF
   {
     "CN": "mycompany",
     "key": {
       "algo": "rsa",
       "size": 2048
     },
     "names": [
       {
         "C": "KR",
         "O": "mycompany",
         "OU": "devops"
       }
     ]
   }
   EOF
   ```
5. 인증서 및 사설키 생성

   ```
   cfssl gencert \
   -ca=ca.pem \
   -ca-key=ca-key.pem \
   -config=ca-config.json \
   -hostname=mycompany.com \
   -profile=mycompany \
   mycompany-csr.json | cfssljson -bare mycompany
   ```
6. Secret 생성

   ```
   kubectl create secret tls mycompany-com \
   --cert=mycompany.pem \
   --key=mycompany-key.pem
   ```
7. 데모 웹사이트 배포

   ```
   {
       kubectl create deployment nginx --image=nginx --port=80
       kubectl expose deploy nginx 
   }
   ```
8. 생성된 리소스 확인

   ```
   kubectl get all -l app=nginx
   ```
9. Ingress 생성

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: nginx
   spec:
     ingressClassName: nginx
     tls: 
     - hosts:
       - mycompany.com
       secretName: mycompany-com
     rules:
     - host: mycompany.com
       http:
         paths:
         - path: /
           pathType: Prefix
           backend:
             service:
               name: nginx
               port:
                 number: 80
   EOF
   ```
10. Ingress 생성 확인 - *ADDRESS에 NGINX Ingress Controller 엔드포인트가 업데이트 되는지 확인*

    ```
    kubectl get ing nginx -w
    ```
11. Ingress에 명시한 Host 주소를 호출하면 NGINX Ingress Controller 엔드포인트로 연결되도록 하고 프로토콜로 데모 웹사이트 호출

    ```
    curl -v --cacert ca.pem https://mycompany.com \
    --connect-to mycompany.com:443:\
    $(kubectl -n kube-system get svc ingress-nginx-controller \
    -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'):443
    ```
12. 리소스 삭제

    ```
    {
        kubectl delete ing nginx
        kubectl delete deploy nginx
        kubectl delete svc nginx
        kubectl delete secret mycompany-com
        rm ca*
        rm mycompany*
    }
    ```

### Clean up

1. NGINX Ingress Controller 삭제&#x20;

   ```
   kubectl delete -f \
   https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml
   ```

## AWS Load Balancer Controller

### Introduction

1. EKS 클러스터가 생성되어 있는 AWS 계정번호 확인하고 환경변수로 저장

   ```
   {
       export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
       echo $ACCOUNT_ID
   }
   ```
2. Node에 부여된 Label을 통해서 EKS 클러스터 이름 확인하고 환경변수로 저장

   ```
   {
       export CLUSTER_NAME=$(kubectl get node \
       -o=jsonpath='{.items[0].metadata.labels.alpha\.eksctl\.io\/cluster-name}')
       echo $CLUSTER_NAME
   }
   ```
3. IAM OIDC 제공자 생성&#x20;

   ```
   eksctl utils associate-iam-oidc-provider \
   --region ap-northeast-2 \
   --cluster $CLUSTER_NAME \
   --approve
   ```
4. AWS Load Balancer Controller에 부여할 IAM 권한이 명시된 JSON 파일 다운로드

   ```
   curl -o aws-loadbalancer-controller-policy.json \
   https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
   ```
5. 다운받은 IAM 정책 JSON 파일 리뷰

   ```
   cat aws-loadbalancer-controller-policy.json
   ```
6. IAM 정책 생성&#x20;

   ```
   aws iam create-policy \
   --policy-name AWSLoadBalancerControllerIAMPolicy \
   --policy-document file://aws-loadbalancer-controller-policy.json
   ```
7. 이미 IAM 정책이 존재할 경우 정책 문서 업데이트&#x20;

   ```
   {
     NON_DEFAULT_VERSIONS=$(aws iam list-policy-versions \
     --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
     --query 'Versions[?IsDefaultVersion==`false`].VersionId' \
     --output text)
     
     for version in $NON_DEFAULT_VERSIONS
     do
       aws iam delete-policy-version \
       --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
       --version-id $version
     done
     
     aws iam create-policy-version \
     --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
     --policy-document file://aws-loadbalancer-controller-policy.json \
     --set-as-default
   }
   ```
8. ServiceAccount 생성&#x20;

   ```
   eksctl create iamserviceaccount \
   --cluster $CLUSTER_NAME \
   --namespace=kube-system \
   --name=aws-load-balancer-controller \
   --attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy \
   --override-existing-serviceaccounts \
   --approve
   ```
9. Helm이 설치되어 있지 않을 경우에는 아래의 명령어로 Helm 설치

   ```
   curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
   ```
10. EKS 리포지토리 추가&#x20;

    ```
    helm repo add eks https://aws.github.io/eks-charts
    ```
11. 위에서 추가한 리포지토리가 추가되었는지 확인

    ```
    helm repo list
    ```
12. 위에서 추가한 리포지토리에 있는 Helm 차트 목록 확인

    ```
    helm search repo eks
    ```
13. AWS Load Balancer Controller 설치

    ```
    helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
    --namespace kube-system \
    --set clusterName=$CLUSTER_NAME \
    --set replicaCount=1 \
    --set serviceAccount.create=false \
    --set serviceAccount.name=aws-load-balancer-controller
    ```
14. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller
    ```
15. 데모 웹사이트 배포

    ```
    {
        kubectl create deployment nginx --image=nginx --port=80
        kubectl expose deploy nginx 
    }
    ```
16. 생성된 리소스 확인

    ```
    kubectl get all -l app=nginx
    ```
17. Ingress 생성

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
    spec:
      ingressClassName: alb
      rules:
      - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
    EOF
    ```
18. 생성된 Ingress 확인

    ```
    kubectl get ing nginx
    ```
19. 위에서 생성한 Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress nginx
    ```
20. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller
    ```
21. 에러 로그 발생원인 확인 - <https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/1695>
22. Ingress 수정

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
      annotations:
        alb.ingress.kubernetes.io/target-type: ip
    spec:
      ingressClassName: alb
      rules:
      - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
    EOF
    ```
23. Ingress 상태 확인

    ```
    kubectl get ing nginx
    ```
24. Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress nginx
    ```
25. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller
    ```
26. 아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인

    ```
    echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    ```
27. 생성된 ALB 이름을 확인하고 환경변수로 저장

    ```
    {
        export LoadBalancerName=$(aws elbv2 describe-load-balancers | \
        jq -r '.LoadBalancers[] | 
        select(.DNSName == "'"$(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')"'") | 
        .LoadBalancerName')

        echo $LoadBalancerName
    }
    ```
28. ALB의 상세 내용 확인

    ```
    aws elbv2 describe-load-balancers --names $LoadBalancerName --no-cli-pager
    ```
29. ALB의 Scheme 확인

    ```
    aws elbv2 describe-load-balancers --names $LoadBalancerName \
    --query 'LoadBalancers[0].Scheme' --output text
    ```
30. ALB가 생성된 서브넷 확인

    ```
    aws elbv2 describe-load-balancers --names $LoadBalancerName \
    --query 'LoadBalancers[0].AvailabilityZones[*]' --no-cli-pager
    ```
31. ALB가 생성된 서브넷에 부여된 태그 확인

    ```
    aws ec2 describe-subnets --subnet-ids --query 'Subnets[*].Tags' \
    $(aws elbv2 describe-load-balancers --names $LoadBalancerName \
    --query 'LoadBalancers[0].AvailabilityZones[*].SubnetId' --output text) \
    --no-cli-pager
    ```
32. AWS Load Balancer Controller가 ALB를 생성한 서브넷을 선택하는 방법 확인 - <https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/deploy/subnet_discovery>
33. AWS Load Balancer Controller로 Ingress 생성할때 요구되는 파라미터 및 기본값 확인 - <https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/ingress/annotations>
34. Ingress 수정

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
      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: nginx
                port:
                  number: 80
    EOF
    ```
35. Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress nginx
    ```
36. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller
    ```
37. 아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인

    ```
    echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    ```
38. 기존에 생성된 ALB가 존재하는지 확인

    ```
    aws elbv2 describe-load-balancers --names $LoadBalancerName
    ```
39. 새롭게 생성된 ALB의 ARN를 확인하고 환경변수로 저장

    ```
    {
        export LoadBalancerArn=$(aws elbv2 describe-load-balancers | \
        jq -r '.LoadBalancers[] | 
        select(.DNSName == "'"$(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')"'") | 
        .LoadBalancerArn')

        echo $LoadBalancerArn
    }
    ```
40. 아파치 웹서버 배포

    ```
    {
        kubectl create deployment httpd --image=httpd
        kubectl expose deployment httpd --port=80
    }
    ```
41. Ingress 수정

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: nginx
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
    spec:
      ingressClassName: alb
      rules:
      - host: nginx.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx
                port:
                  number: 80
      - host: httpd.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: httpd
                port:
                  number: 80
    EOF
    ```
42. 아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인

    ```
    echo $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    ```
43. cURL 명령어로 **Host** 값을 *nginx.example.com*으로 명시하고 ALB 엔드포인트 호출

    ```
    curl -H "Host: nginx.example.com" \
    $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}') 
    ```
44. cURL 명령어로 **Host** 값을 *httpd.example.com*으로 명시하고 ALB 엔드포인트 호출

    ```
    curl -H "Host: httpd.example.com" \
    $(kubectl get ing nginx -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}') 
    ```
45. ALB의 리스너 ARN를 확인하고 환경변수로 저장

    ```
    {
        export ListnerArn=$(aws elbv2 describe-listeners \
        --load-balancer-arn $LoadBalancerArn \
        --query "Listeners[0].ListenerArn" --output text)
        
        echo $ListnerArn
    }
    ```
46. ALB 리스너 확인

    ```
    aws elbv2 describe-listeners --listener-arns $ListnerArn
    ```
47. ALB 리스너 규칙 확인

    ```
    aws elbv2 describe-rules --listener-arn $ListnerArn --no-cli-pager
    ```
48. ALB에 연동된 대상그룹들의 ARN을 확인하고 환경변수로 저장

    ```
    {
        export TG=$(aws elbv2 describe-target-groups \
        --load-balancer-arn $LoadBalancerArn \
        --query "TargetGroups[*].TargetGroupArn" \
        --output text)
        
        echo $TG
    }
    ```
49. 대상그룹 확인

    ```
    aws elbv2 describe-target-groups --target-group-arns $TG --no-cli-pager
    ```
50. 대상그룹에 포함된 대상 목록 확인

    ```
    for target in $TG
    do 
      aws elbv2 describe-target-health --target-group-arn $target --no-cli-pager
    done
    ```
51. Pod 목록 확인

    ```
    kubectl get pod -o wide -l 'app in (nginx,httpd)'
    ```
52. 아파치 Deployment의 Replica 갯수를 3개로 조정

    ```
    kubectl scale deployment httpd --replicas=3
    ```
53. Pod 목록 확인

    ```
    kubectl get pod -o wide -l 'app in (nginx,httpd)'
    ```
54. 대상그룹에 포함된 대상 목록 확인

    ```
    for target in $TG
    do 
      aws elbv2 describe-target-health --target-group-arn $target --no-cli-pager
    done
    ```
55. Ingress 삭제

    ```
    kubectl delete ing nginx
    ```
56. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller
    ```
57. ALB가 삭제되었는지 확인

    ```
    aws elbv2 describe-load-balancers --load-balancer-arns $LoadBalancerArn
    ```
58. 리소스 삭제

    ```
    {
        kubectl delete svc httpd nginx 
        kubectl delete deploy httpd nginx
    }
    ```

### IngressGroup

1. Ingress 생성

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: my-service
     annotations:
       alb.ingress.kubernetes.io/scheme: internet-facing
       alb.ingress.kubernetes.io/target-type: ip
       alb.ingress.kubernetes.io/group.name: my-service
       alb.ingress.kubernetes.io/actions.response-404: >
         {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"Not Found"}}
   spec:
     ingressClassName: alb
     defaultBackend:
       service:
         name: response-404
         port:
           name: use-annotation
   EOF
   ```
2. 생성된 Ingress 확인

   ```
   kubectl get ing my-service
   ```
3. 위에서 생성한 Ingress에 발생한 Event 확인

   ```
   kubectl describe ingress my-service
   ```
4. AWS Load Balancer Controller 로그 확인

   ```
   kubectl -n kube-system logs deploy/aws-load-balancer-controller --tail 15
   ```
5. 아래의 명령어를 실행해서 생성된 ALB 엔드포인트를 확인하고 웹브라우저를 통해서 접근이 되는지 확인

   ```
   echo $(kubectl get ing my-service -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
   ```
6. Product 서비스 배포

   ```
   cat <<'EOF' | kubectl apply -f -
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: product
     labels:
       app: product
   spec:
     selector:
       matchLabels:
         app: product
     template:
       metadata:
         labels:
           app: product
       spec:
         containers:
         - name: product
           image: nginx
           ports:
           - containerPort: 80
           volumeMounts:
           - name: html
             mountPath: /usr/share/nginx/html
         initContainers:
         - name: index
           image: bash
           command:
             - 'bash'
             - '-c'
             - 'echo "<h1>${APP^^}</h1>" > /data/index.html'
           env:
           - name: APP
             valueFrom:
               fieldRef:
                 fieldPath: metadata.labels['app']
           volumeMounts:
           - name: html
             mountPath: /data
         volumes:
         - name: html
           emptyDir: {}
   ---
   apiVersion: v1
   kind: Service
   metadata:
     name: product
     labels:
       app: product
   spec:
     selector:
       app: product
     ports:
     - port: 80
   EOF
   ```
7. 리소스가 정상적으로 생성되었는지 확인

   ```
   kubectl get all -l app=product
   ```
8. */product* 경로로 접속할 경우 위에 배포한 서비스로 연결되도록 Ingress 생성

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: product
     annotations:
       alb.ingress.kubernetes.io/group.name: my-service
   spec:
     ingressClassName: alb
     rules:
     - http:
         paths:
         - path: /product
           pathType: Prefix
           backend:
             service:
               name: product
               port:
                 number: 80
   EOF
   ```
9. 생성된 Ingress 확인

   ```
   kubectl get ing product
   ```
10. 위에서 생성한 Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress product
    ```
11. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller --tail 10
    ```
12. Ingress 수정

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: product
      annotations:
        alb.ingress.kubernetes.io/group.name: my-service
        alb.ingress.kubernetes.io/target-type: ip
    spec:
      ingressClassName: alb
      rules:
      - http:
          paths:
          - path: /product
            pathType: Prefix
            backend:
              service:
                name: product
                port:
                  number: 80
    EOF
    ```
13. Ingress 확인

    ```
    kubectl get ing product
    ```
14. Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress product
    ```
15. 처음에 생성한 Ingress의 ALB 엔드포인트에 방금 생성한 Ingress에 명시한 경로로 웹브라우저를 통해서 접근이 되는지 확인 - *아래의 명령어로 주소 확인 가능*

    ```
    echo $(kubectl get ing my-service -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')/product
    ```
16. Product 서비스의 로그 확인

    ```
    kubectl logs deploy/product
    ```
17. Product 서비스의 루트 경로 호출

    ```
    kubectl exec deploy/product -- curl -s localhost
    ```
18. Product 서비스의 */product* 경로 호출

    ```
    kubectl exec deploy/product -- curl -s localhost/product
    ```
19. Product 서비스 수정

    ```
    cat <<'EOF' | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: product
      labels:
        app: product
    spec:
      selector:
        matchLabels:
          app: product
      template:
        metadata:
          labels:
            app: product
        spec:
          containers:
          - name: product
            image: nginx
            ports:
            - containerPort: 80
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          initContainers:
          - name: index
            image: bash
            command:
              - 'bash'
              - '-c'
              - 'mkdir /data/$APP && echo "<h1>${APP^^}</h1>" > /data/$APP/index.html'
            env:
            - name: APP
              valueFrom:
                fieldRef:
                  fieldPath: metadata.labels['app']
            volumeMounts:
            - name: html
              mountPath: /data
          volumes:
          - name: html
            emptyDir: {}
    EOF
    ```
20. Product 서비스의 루트 경로 호출

    ```
    kubectl exec deploy/product -- curl -s localhost
    ```
21. Product 서비스의 */product* 경로 호출

    ```
    kubectl exec deploy/product -- curl -sL localhost/product
    ```
22. 처음에 생성한 Ingress의 ALB 엔드포인트에 */product* 경로로 웹브라우저를 통해서 접근이 되는지 확인 - *아래의 명령어로 주소 확인 가능*

    ```
    echo $(kubectl get ing my-service -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')/product
    ```
23. Payment 서비스 배포

    ```
    cat <<'EOF' | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: payment
      labels:
        app: payment
    spec:
      selector:
        matchLabels:
          app: payment
      template:
        metadata:
          labels:
            app: payment
        spec:
          containers:
          - name: payment
            image: nginx
            ports:
            - containerPort: 80
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          initContainers:
          - name: index
            image: bash
            command:
              - 'bash'
              - '-c'
              - 'mkdir /data/$APP && echo "<h1>${APP^^}</h1>" > /data/$APP/index.html'
            env:
            - name: APP
              valueFrom:
                fieldRef:
                  fieldPath: metadata.labels['app']
            volumeMounts:
            - name: html
              mountPath: /data
          volumes:
          - name: html
            emptyDir: {}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: payment
      labels:
        app: payment
    spec:
      selector:
        app: payment
      ports:
      - port: 80
    EOF
    ```
24. 리소스가 정상적으로 생성되었는지 확인

    ```
    kubectl get all -l app=payment
    ```
25. */payment* 경로로 접속할 경우 위에 배포한 서비스로 연결되도록 Ingress 생성

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: payment
      annotations:
        alb.ingress.kubernetes.io/group.name: my-service
        alb.ingress.kubernetes.io/target-type: ip
    spec:
      ingressClassName: alb
      rules:
      - http:
          paths:
          - path: /payment
            pathType: Prefix
            backend:
              service:
                name: payment
                port:
                  number: 80
    EOF
    ```
26. 생성된 Ingress 확인

    ```
    kubectl get ing payment
    ```
27. 위에서 생성한 Ingress에 발생한 Event 확인

    ```
    kubectl describe ingress payment
    ```
28. AWS Load Balancer Controller 로그 확인

    ```
    kubectl -n kube-system logs deploy/aws-load-balancer-controller --tail 10
    ```
29. 처음에 생성한 Ingress의 ALB 엔드포인트에 */payment* 경로로 웹브라우저를 통해서 접근이 되는지 확인 - *아래의 명령어로 주소 확인 가능*

    ```
    echo $(kubectl get ing my-service -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')/payment
    ```
30. 위에서 개별로 생성한 3개의 Ingress들이 동일한 ALB를 사용하는지 확인

    ```
    kubectl get ing my-service product payment
    ```
31. 리소스 삭제

    ```
    {
        kubectl delete ing payment product my-service
        kubectl delete deploy payment product
        kubectl delete svc payment product
    }
    ```
