Ingress는 앞서 소개된 Loadbalancer 방식과 다르게 URL 패스에 대한 설정을 담당하는 자원입니다. 외부에서 요청하는 HTTP에 대한 트래픽 처리를 지원하게 됩니다. (eg. 도메인 기반 라우팅) 사용자들이 외부에서 접근이 가능한 URL을 제공하여 , 사용자의 접근성을 편리하게 제공합니다.
Ingress는 Ingress Controller가 존재하고, Ingress 에 정의된 트래픽 라우팅 규칙에 따라 라우팅을 처리합니다.
2. Ingress Controller
Ingress 는 반드시 Ingress Controller가 존재 해야하며, 외부에서 내부로 요청되는 트래픽을 읽고 서비스로 전달하는 역할을 합니다. 다른 컨트롤러와 다르게 목적에 맞게 수동으로 설치해야 합니다.
AWS EKS 환경에서는 AWS Load Balancer Controller 를 별도로 설치하고, Ingress는 ALB를 통해 구성됩니다
NGINX Ingress Controller
HA Proxy
AWS Load Balancer Controller (이전 이름 : ALB Ingress Controller)
Kube-API에 의해 업데이트 된 정보를 가지고 ALB에서 Loadbalancing 처리를 합니다.
아래와 같은 구성 단계로 ALB Loadbalancer Controller를 구성합니다.
IAM OIDC 공급자 생성
AWS Loadbalancer 컨트롤러에 대한 IAM 정책 다운로드.
AWSLoadBalancerControllerIAMPolicy 이름의 IAM 정책 생성.
AWS Load Balancer 컨트롤러에 대한 IAM역할 및 ServiceAccount 생성
EKS Cluster에 컨트롤러 추가
7. IAM OIDC Provider 생성
AWS IAM(Identity and Access Management)에서는 OpenID Connect(OIDC)를 사용해 연동 자격 증명을 지원하는 기능을 추가하였습니다. 이 기능을 사용하면 지원되는 자격 증명 공급자를 이용해 AWS API 호출을 인증하고 유효한 OIDC JWT(JSON WebToken)을 수신할 수 있습니다.
이 토큰을 AWS STS AssumeRoleWithWebIdentity API 작업에 전달하고 IAM 임시 역할 자격 증명을 수신할 수 있습니다. 이 자격 증명을 사용하여 AWS 서비스 자원들을 Kubernetes 자원들이 사용할 수 있습니다.
IAM OIDC Provider는 기본으로 활성화되어 있지 않습니다. eksctl을 사용하여 IAM OIDC Provider를 생성합니다.
이를 통해 EKS에서 실행되고 다른 AWS 서비스를 사용하는 앱에 대해 세분화 된 권한 관리를 제공합니다. S3, 다른 데이터 서비스 (RDS, MQ, STS, DynamoDB) , AWS ALB Ingress 컨트롤러 또는 ExternalDNS와 같은 Kubernetes 구성 요소를 사용하는 어플리케이션 들이 대표적입니다. IAM OIDC Provider는 기본적으로 활성화되어 있지 않습니다. 따라서 앞선 과정들을 수행해야 합니다.
11. 인증서 관리자 설치
아래와 같이 Cert Manager (인증서 관리자)를 설치합니다. 설치 후에 pod가 모두 READY가 되는 것을 확인 하고 다음 단계를 진행합니다.
앞서서 Service Account와 IAM Role을 연결하는 작업을 이미 완료했으므로, kind: ServiceAccount 섹션은 삭제하거나 주석처리하는 것이 좋습니다.
# apiVersion: v1
# kind: ServiceAccount
이미 git을 통해 사전에 다운로드 받아 두었습니다. 해당 AWS Loadbalancer Controller Pod의 yaml에는 Cluster Name이 eksworkshop으로 수정되어 있고 kine: ServiceAccount 섹션은 주석처리되어 있습니다. 해당 yaml을 배포합니다. pod가 정상적으로 Running 되는지 확인하고 다음 단계를 진행합니다.
cd ~/environment/myeks/alb-controller
kubectl apply -f v2_4_4_full.yaml
kubectl -n kube-system get pods | grep balancer
12.Ingress Annotation
kubernetes Ingress 및 Service Object에 Annotation을 추가하여 동작을 상세하게 지정할 수 있습니다
annotations:
## IngressGroup
### Ingress가 속한 그룹 이름을 지정합니다.
alb.ingress.kubernetes.io/group.name: my-team.awesome-group
### IngressGroup 내의 모든 Ingress에 대한 순서를 지정합니다. default 0
alb.ingress.kubernetes.io/group.order: '10'
## Traffic Listening
## ALB가 수신 대기하는 데 사용한 포트를 지정합니다.
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}, {"HTTP": 8080}, {"HTTPS": 8443}]'
## SSLRedirect를 활성화하고 리디렉션할 SSL 포트를 지정합니다.단일 Ingress에 정의되면 IngressGroup 내의 모든 Ingress에 영향을 미칩니다.
alb.ingress.kubernetes.io/ssl-redirect: '443'
## ALB 의 IP 주소 유형 을 지정합니다 .
alb.ingress.kubernetes.io/ip-address-type: ipv4
## Outpost의 ALB에 대한 고객 소유 IPv4 주소 풀을 지정합니다.
alb.ingress.kubernetes.io/customer-owned-ipv4-pool: ipv4pool-coip-xxxxxxxx
## Traffic Routing
## 로드 밸런서에 사용할 사용자 지정 이름을 지정합니다. 32자보다 긴 이름은 오류로 처리됩니다.
alb.ingress.kubernetes.io/load-balancer-name: custom-name
## 트래픽을 포드로 라우팅하는 방법을 지정합니다.
## instance모드는 서비스에 대해 오픈된 NodePort 의 클러스터 내의 모든 ec2 인스턴스로 트래픽을 라우팅합니다 .
## instance모드 를 사용하려면 서비스 유형이 "NodePort" 또는 "LoadBalancer" 가 되어야 합니다.
alb.ingress.kubernetes.io/target-type: instance
## ip모드는 트래픽을 포드 IP로 직접 라우팅합니다.
## CNI가 VPC CNI이어야 합니다. ENI의 Secondary IP, 즉 PoD IP를 사용하기 때문입니다.
## Sticky Session을 사용하려면 이 모드가 필요합니다.
alb.ingress.kubernetes.io/target-type: ip
### LB 대상 그룹 등록에 포함할 노드를 지정합니다.
alb.ingress.kubernetes.io/target-node-labels: label1=value1, label2=value2
### 트래픽을 포드로 라우팅할 때 사용되는 프로토콜을 지정합니다.
alb.ingress.kubernetes.io/backend-protocol: HTTPS
### 트래픽을 포드로 라우팅하는 데 사용되는 애플리케이션 프로토콜을 지정
### HTTP2
alb.ingress.kubernetes.io/backend-protocol-version: HTTP2
### GRPC
alb.ingress.kubernetes.io/backend-protocol-version: GRPC
### ALB가 트래픽을 라우팅할 가용 영역을 지정
alb.ingress.kubernetes.io/subnets: subnet-xxxx, mySubnet
## 리디렉션 작업과 같은 Listener에서 Custom Action 작업을 구성하는 방법을 제공합니다.
alb.ingress.kubernetes.io/actions.${action-name}
## Ingress 사양의 원래 호스트/경로 조건 외에 라우팅 조건을 지정하는 방법을 제공합니다.
alb.ingress.kubernetes.io/conditions.${conditions-name}
## Access Control
## LoadBalancer가 인터넷에 연결되는지 여부를 지정합니다.
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/scheme: internet-facing
## LoadBalancer에 액세스할 수 있는 CIDR을 지정합니다.
## alb.ingress.kubernetes.io/security-groups지정된 경우 무시됩니다.
alb.ingress.kubernetes.io/inbound-cidrs: 10.0.0.0/24
## LoadBalancer에 연결할 securityGroups를 지정합니다.securityGroups의 이름 또는 ID가 모두 지원
alb.ingress.kubernetes.io/security-groups: sg-xxxx, nameOfSg1, nameOfSg2
## Authentication
## 인증은 HTTPS 리스너에 대해서만 지원됩니다.
## 대상에 대한 인증 유형을 지정합니다.
alb.ingress.kubernetes.io/auth-type: cognito
## oidc idp 구성을 지정합니다.
alb.ingress.kubernetes.io/auth-idp-oidc: '{"issuer":"https://example.com","authorizationEndpoint":"https://authorization.example.com","tokenEndpoint":"https://token.example.com","userInfoEndpoint":"https://userinfo.example.com","secretName":"my-k8s-secret"}'
## 사용자가 인증되지 않은 경우 동작을 지정합니다.
alb.ingress.kubernetes.io/auth-on-unauthenticated-request: authenticate
## 공백으로 구분된 목록에서 IDP(cognito 또는 oidc)에서 요청할 사용자 클레임 집합을 지정합니다.
alb.ingress.kubernetes.io/auth-scope: 'email openid'
## 세션 정보를 유지하는 데 사용되는 쿠키의 이름을 지정합니다.
alb.ingress.kubernetes.io/auth-session-cookie: custom-cookie
## 인증 세션의 최대 지속 시간을 초 단위로 지정합니다.
alb.ingress.kubernetes.io/auth-session-timeout: '86400'
## Health Check
## Target에서 상태 확인을 수행할 때 사용되는 프로토콜을 지정합니다.
alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
## Target에서 상태 확인을 수행할 때 사용되는 포트를 지정합니다.
## 상태 확인 포트를 트래픽 포트로 설정
alb.ingress.kubernetes.io/healthcheck-port: traffic-port
## 상태 확인 포트를 명명된 포트의 NodePort(target-type=instance일 때) 또는 TargetPort(target-type=ip일 때)로 설정합니다.
alb.ingress.kubernetes.io/healthcheck-port: my-port
## 상태 확인 포트를 80/tcp로 설정
alb.ingress.kubernetes.io/healthcheck-port: '80'
## 대상에서 상태 확인을 수행할 때 HTTP 경로를 지정합니다.
## HTTP
alb.ingress.kubernetes.io/healthcheck-path: /ping
## GRPC
alb.ingress.kubernetes.io/healthcheck-path: /package.service/method
## 개별 target 의 상태 확인 간격(초)을 지정합니다. default 15
alb.ingress.kubernetes.io/healthcheck-interval-seconds: '10'
## Target 에서 응답이 없으면 상태 확인이 실패했음을 의미하는 시간 초과(초)를 지정합니다. default 5
alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '8'
## 지정된 상태 확인 경로에 대해 상태 확인을 수행할 때 예상해야 하는 HTTP 상태 코드를 지정합니다.
alb.ingress.kubernetes.io/success-codes: 200-300
## 비정상 대상을 정상으로 간주하기 전에 필요한 연속적인 상태 확인 성공을 지정합니다. default 2
alb.ingress.kubernetes.io/healthy-threshold-count: '2'
## 대상을 비정상으로 간주하기 전에 필요한 연속적인 상태 확인 실패를 지정합니다. default 2
alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
## SSL
## AWS Certificate Manager 에서 관리하는 하나 이상의 인증서의 ARN을 지정합니다.
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxxx:certificate/xxxxxxx
## 프로토콜과 암호를 제어할 수 있도록 ALB에 할당해야 하는 보안 정책 을 지정합니다 .
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-1-2017-01
## Custom attributes
## ALB에 적용해야 하는 로드 밸런서 속성 을 지정합니다.
## s3에 대한 액세스 로그 활성화
alb.ingress.kubernetes.io/load-balancer-attributes: access_logs.s3.enabled=true,access_logs.s3.bucket=my-access-log-bucket,access_logs.s3.prefix=my-app
## 삭제 방지 활성화
alb.ingress.kubernetes.io/load-balancer-attributes: deletion_protection.enabled=true
## 유효하지 않은 헤더 필드 제거 활성화
alb.ingress.kubernetes.io/load-balancer-attributes: routing.http.drop_invalid_header_fields.enabled=true
## http2 지원 활성화
alb.ingress.kubernetes.io/load-balancer-attributes: routing.http2.enabled=true
## idle_timeout 지연을 600초로 설정
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=600
## target-group 에 적용해야 하는 속성을 지정합니다 .
## slow start 지속시간을 설정
alb.ingress.kubernetes.io/target-group-attributes: slow_start.duration_seconds=30
## 등록 취소 지연 시간 설정
alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30
## Stickiness 세션 활성화, alb.ingress.kubernetes.io/target-type 이 반드시 IP 모드이어야 합니다.
alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=60
alb.ingress.kubernetes.io/target-type: ip
## LB 알고리즘을 least outstanding requests 로 설정.
alb.ingress.kubernetes.io/target-group-attributes: load_balancing.algorithm.type=least_outstanding_requests
### Resource Tag
## 생성한 AWS 리소스(ALB/TargetGroups/SecurityGroups/Listener/ListenerRule)에 다음 태그를 자동으로 적용합니다.
elbv2.k8s.aws/cluster: ${clusterName}
ingress.k8s.aws/stack: ${stackID}
ingress.k8s.aws/resource: ${resourceID}
## 생성된 AWS 리소스에 적용할 추가 태그를 지정
alb.ingress.kubernetes.io/tags: Environment=dev,Team=test
### Add On
## alb.ingress.kubernetes.io/waf-acl-idAmzon WAF 웹 ACL의 식별자를 지정합니다.
## Regional WAF만 지원
alb.ingress.kubernetes.io/waf-acl-id: 499e8b99-6671-4614-a86d-adb1810b7fbe
## Regional WAFv2 만 지원
alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:us-west-2:xxxxx:regional/webacl/xxxxxxx/3ab78708-85b0-49d3-b4e1-7a9615a6613b
## 로드 밸런서에 대한 AWS Shield Advanced 보호를 켜거나 끕니다.
alb.ingress.kubernetes.io/shield-advanced-protection: 'true'
13.ALB Ingress Traffic 흐름 확인
ALB Ingress를 시험하기 위해 아래와 같이 namespace와 pod,service를 배포합니다.
아래와 같은 결과를 확인하고 ingress LB의 외부 A Record를 확인합니다. 해당 A Record를 Cloud9 IDE Terminal에서 Curl을 통해 접속하거나 브라우저에서 접속해 봅니다.
앞서 생성된 ALB 주소로 접속을 시도해 봅니다.Cloud9 IDE Terminal에서 ALB External IP:80 으로 접속합니다.
## alb-ing-01-svc external hostname 변수 등록
kubectl -n alb-ing-01 get ingress alb-ing-01 --output jsonpath='{.status.loadBalancer.ingress[*].hostname}'
export alb_ing_01_svc_name=$(kubectl -n alb-ing-01 get ingress alb-ing-01 --output jsonpath='{.status.loadBalancer.ingress[*].hostname}')
echo "export alb_ing_01_svc_name=${alb_ing_01_svc_name}" | tee -a ~/.bash_profile
source ~/.bash_profile
## alb-ing-01-svc external hostname 으로 접속
curl $alb_ing_01_svc_name
아래와 같이 배포된 pod에 접속을 편리하게 하기 위해 Cloud9 IDE terminal Shell에 등록 합니다.
export alb_ing_01_Pod01=$(kubectl -n alb-ing-01 get pod -o wide | awk 'NR==2' | awk '/alb-ing-01/{print $1 } ')
export alb_ing_01_Pod02=$(kubectl -n alb-ing-01 get pod -o wide | awk 'NR==3' | awk '/alb-ing-01/{print $1 } ')
export alb_ing_01_Pod03=$(kubectl -n alb-ing-01 get pod -o wide | awk 'NR==4' | awk '/alb-ing-01/{print $1 } ')
echo "export alb_ing_01_Pod01=${alb_ing_01_Pod01}" | tee -a ~/.bash_profile
echo "export alb_ing_01_Pod02=${alb_ing_01_Pod02}" | tee -a ~/.bash_profile
echo "export alb_ing_01_Pod03=${alb_ing_01_Pod03}" | tee -a ~/.bash_profile
source ~/.bash_profile
alb-ing-01에 container 접속해서 아래와 같이 확인해 봅니다.
#K9으로 접속 할 경우
k9s -n alb-ing-01
# Cloud9 에서 접속할 경
kubectl -n alb-ing-01 exec -it $alb_ing_01_Pod01 -- /bin/sh