티스토리 뷰

이전 포스팅에서는 k8s 클러스터 내부 애플리케이션을 외부로 노출하기 위해

서비스를 만들고 NodePort/LoadBalancer를 통해 직접 노출해봤다.

k8s에서는 외부 노출 서비스를 위한 별도의 API 오브젝트를 제공한다.
그것이 바로 인그레스(Ingress)이다.

 

공식 문서에는 클러스터 외부에서 클러스터 내부로 요청할 수 있는 URL(HTTP/HTTPS) 경로를 노출하고
SSL/TLS 인증처리 및 로드 밸런싱을 제공한다고 한다.

인그레스는 반드시 인그레스 컨트롤러(Ingress Controller)와 같이 동작하는데,
쉽게 말하면 인그레스 컨트롤러는 오브젝트로서 실제 트래픽 처리를 하는 구현체이고
인그레스는 인그레스 컨트롤러의 트래픽을 어떻게 처리할지 정책을 결정하는 실체가 없는 추상화이다.

아래 공식문서에서 발취한 간단한 흐름을 보고 이해해보자.

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

이제야 흐름이 일반적인 ALB와 EC2 만으로 웹 서비스를 운영하는 시스템과 비슷해 보인다.

그럼 이제 직접 인그레스를 통해 웹서비스를 노출해보자.
k8s에서 공식 프로젝트로 AWSGCEnginx 인그레스 컨트롤러를 지원한다.

우리는 AWS환경이기에 ALB Ingress Controller를 사용해보자.
(다음 포스팅에는 간단하게 nginx 인그레스도 기재할 것이다.)

 

1. ALB Ingress(Controller)

1) IAM OIDC 공급자 생성

아래 링크의 절차대로 eks 클러스터의 OIDC를 IAM 계정에 추가한다.

https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/enable-iam-roles-for-service-accounts.html

 

2) ALB 를 생성할 subnet에 eks cluster tag 추가하기(Public Subnet 2개에 추가)

웹 콘솔에서 직접 eks vpc public subnet에 아래 태그를 추가하면 된다.

kubernetes.io/cluster/swm-eks-cluster : shared

 

3) IAM 권한 생성

curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.0/docs/install/iam_policy.json
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json


4) kube-system 네임스페이스에 aws-load-balancer-controller ServiceAccount 추가

# OIDC URL주소 확인
aws eks describe-cluster --name swm-eks-cluster --query "cluster.identity.oidc.issuer" --output text  
> https://oidc.eks.ap-northeast-2.amazonaws.com/id/E1C054E38F4BFFBB05B29E0XXXXXXXX

vim load-balancer-role-trust-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::0000000000:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/E1C054E38F4BFFBB05B29E0CE2E4DB9E"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.ap-northeast-2.amazonaws.com/id/E1C054E38F4BFFBB05B29E0XXXXXXXX:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
                }
            }
        }
    ]
}

aws iam create-role \
  --role-name AmazonEKSLoadBalancerControllerRole \
  --assume-role-policy-document file://"load-balancer-role-trust-policy.json"

aws iam attach-role-policy \
  --policy-arn arn:aws:iam::0000000000:policy/AWSLoadBalancerControllerIAMPolicy \
  --role-name AmazonEKSLoadBalancerControllerRole

vim aws-load-balancer-controller-service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::0000000000:role/AmazonEKSLoadBalancerControllerRole

kubectl apply -f aws-load-balancer-controller-service-account.yaml


4. AWS Load Balancer Controller 설치(Ingress Controller)

kubectl apply \
    --validate=false \
    -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml

curl -Lo v2_4_0_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.0/v2_4_0_full.yaml
sed -i.bak -e 's|your-cluster-name|swm-eks-cluster|' ./v2_4_0_full.yaml

vim ./v2_4_0_full.yaml
  # 480-487 라인 제거
  # apiVersion: v1
  # kind: ServiceAccount
  # metadata:
  #  labels:
  #    app.kubernetes.io/component: controller
  #    app.kubernetes.io/name: aws-load-balancer-controller
  #  name: aws-load-balancer-controller
  #  namespace: kube-system

  # 740 라인 아래 파라미터 추가
  - --aws-vpc-id=vpc-02f0248eb6c7fffdf
  - --aws-region=ap-northeast-2

kubectl apply -f v2_4_0_full.yaml
kubectl get deployment -n kube-system aws-load-balancer-controller

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   1/1     1            1           26s

5. ingress 생성

vim alb-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: alb-ingress
  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: test-svc
              port:
                number: 80
kubectl apply -f alb-ingress.yaml
kubectl describe ingress alb-ingress

Name:             alb-ingress
Labels:           <none>
Namespace:        default
Address:          k8s-default-albingre-6adb096be0-1432504096.ap-northeast-2.elb.amazonaws.com
Ingress Class:    alb
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   test-svc:80 (192.168.40.178:80,192.168.57.66:80,192.168.91.200:80)
Annotations:  alb.ingress.kubernetes.io/scheme: internet-facing
              alb.ingress.kubernetes.io/target-type: ip
Events:
  Type    Reason                  Age                   From     Message
  ----    ------                  ----                  ----     -------
  Normal  SuccessfullyReconciled  2m5s (x2 over 2m15s)  ingress  Successfully reconciled

여기까지 완료하면 ingress 가 정상적으로 생성되어 AWS의 ALB를 자동으로 프로비저닝 한다.

ALB의 엔드포인트를 통해 클러스터 내부의 서비스로 접근이 가능해진다.

 

curl -I k8s-default-albingre-6adb096be0-1432504096.ap-northeast-2.elb.amazonaws.com

HTTP/1.1 200 OK
Date: Thu, 02 Jun 2022 02:35:46 GMT
Content-Type: text/html
Content-Length: 612
Connection: keep-alive
Server: nginx/1.14.2
Last-Modified: Tue, 04 Dec 2018 14:44:49 GMT
ETag: "5c0692e1-264"
Accept-Ranges: bytes

이제는 ALB사용에 익숙하다면 DNS 추가와 SSL 인증서만 넣으면 원하는 도메인으로 서비스가 가능해진다.

 

6. ALB DNS 등록

aws route 53으로 dns host 추가 후 별칭을 위에서 생성된 alb를 넣으면 된다.

 

7. ssl 인증서 추가(443 포트)

HTTPS 프로토콜을 사용하기 위해 Ingress annotations으로 ssl인증서와 listen-port 설정값을 추가하면 된다.

vim alb-ingess.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: alb-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:0000000000:certificate/bc1b0e67-555c-436d-9a52-00000000000
    alb.ingress.kubernetes.io/healthcheck-path: /
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: test-svc
              port:
                number: 80
                
kubectl apply -f alb-ingress.yaml

이제 모든 설정이 완료되고 ALB의 보안 그룹, HTTPS 리스너가 생성되었음을 확인 후 요청을 시도해보면 된다.

curl -I https://swm.xxxxxxxxxx.com

HTTP/2 200
date: Thu, 02 Jun 2022 04:33:13 GMT
content-type: text/html
content-length: 612
server: nginx/1.14.2
last-modified: Tue, 04 Dec 2018 14:44:49 GMT
etag: "5c0692e1-264"
accept-ranges: bytes

1차 도메인은 사내 도메인이니 생략하겠다.

 

이렇게 Ingress를 사용하여 서비스를 노출해봤다.

퍼블릭 클라우드에서 클러스터를 운영하지 않는 경우에는 nginx-ingress를 사용해야 하니(물론 다른 ingress-controller 도 존재한다)

다음 포스팅에는 nginx-ingress 도 시도해 보자.

 

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함