ALB Ingress Controller
ALB Ingress Controller는 Kubernetes Ingress를 Application LoadBalancer 상품에 연동하여 HTTP, HTTPS 트래픽을 클러스터의 Pod에 라우팅되도록 합니다.
동작 방식
- Ingress가 생성되면 Ingress Controller는 Ingress에 설정된 값들을 활용하여 Application Load Balancer를 생성합니다.
- Ingress Rule에 설정된 Service들의 NodePort로 Worker Node들에 대한 Target Group들을 생성하고 Load Balancer에 등록합니다.
시작하기
시작하기 전에 Ingress Controller를 설치 할 Kubernetes Service 클러스터와 kubectl 설치 및 kubeconfig 설정이 선행되어야합니다.
클러스터에 ALB Ingress Controller 설치하기
아래 명령을 사용하면 kube-system 네임스페이스에 alb-ingress-controller가 생성되며, 그에 필요한 ServiceAccount, ClusterRole, ClusterRoleBinding이 생성됩니다.
kubectl --kubeconfig=$KUBE_CONFIG apply -f https://raw.githubusercontent.com/NaverCloudPlatform/nks-alb-ingress-controller/main/docs/install/pub/install.yaml
사용법
kubernetes.io/ingress.class: alb
- ALB Ingress Controller를 사용하려면 Ingress Resource에
kubernetes.io/ingress.class: alb
Annotation을 추가해야합니다.
- ALB Ingress Controller를 사용하려면 Ingress Resource에
- Service type: NodePort
- Ingress를 통해 노출시킬 Service는 모두 NodePort type으로 생성하여야 합니다.
- Default Rule
- Default Rule은 매칭되는 rule이 한 개도 없을 때 적용되는 rule이며 spec.backend에 설정할 수 있습니다.
- 별도의 rule 및 use-annotation 설정은 불가능하며, 설정하지 않았을 경우 80포트로 설정된 기본 Target Group이 생성됩니다.
- Rule Priority
- Ingress에 정의한 rule의 순서에 따라 우선순위가 결정됩니다. 가장 위에 있는 rule의 우선순위가 1로 설정됩니다.
Ingress Annotations
Ingress 및 Service 오브젝트에 annotation을 사용하여 설정을 변경할 수 있습니다.
alb ingress annotation은 모두 alb.ingress.kubernetes.io/
로 시작합니다.
Annotation | 기본값 | 적용 Resource | 설명 |
---|---|---|---|
alb.ingress.kubernetes.io/listen-ports |
[{"HTTP":80}] (인증서 번호가 설정되었다면 [{"HTTPS":443}] ) |
Ingress | Listener의 프로토콜 및 포트 설정 리스트. - 사용 가능한 프로토콜: HTTP ,HTTPS |
alb.ingress.kubernetes.io/description |
N/A | Ingress | 로드밸런서 메모 |
alb.ingress.kubernetes.io/ssl-certificate-no |
N/A | Ingress | 프로토콜이 HTTPS 인 리스너에 적용할 Certificate Manager의 인증서 번호 - 인증서 번호는 Resource Manager의 nrn에서 확인할 수 있습니다. (예: nrn:PUB:CertificateManager::000:Certificate/External/${certificateNo}) |
alb.ingress.kubernetes.io/load-balancer-size |
small |
Ingress | 로드밸런서의 부하처리 성능 설정 - 설정 가능한 값: small , medium , large |
alb.ingress.kubernetes.io/network-type |
public |
Ingress | 로드밸런서의 네트워크 유형 설정이며 값 변경 시 로드밸런서가 재생성됩니다. - 사설: private , 공인: public |
alb.ingress.kubernetes.io/subnet-id |
kube-system configmap(ncloud-config) 의 lbSubnetNo 값 |
Ingress | 로드밸런서 생성을 위한 로드밸런서 전용 서브넷의 ID 값이며 생성할 때만 사용됩니다. |
alb.ingress.kubernetes.io/actions.${actionName} |
N/A | Ingress | Listener Rule의 기능들을 사용하기 위한 설정(하단 설명 참고) |
alb.ingress.kubernetes.io/conditions.${conditionName} |
N/A | Ingress | Ingress Rule의 Host, Path 조건에 추가 조건을 적용하기 위한 설정(하단 설명 참고) |
alb.ingress.kubernetes.io/algorithm-type |
round-robin |
Ingress, Service | Target Group의 로드밸런싱 알고리즘 설정 - 설정 가능한 값: round-robin , least-connection , source-ip-hash |
alb.ingress.kubernetes.io/unhealthy-threshold-count |
2 |
Ingress, Service | Health Check 실패 임계값 |
alb.ingress.kubernetes.io/healthy-threshold-count |
2 |
Ingress, Service | Health Check 성공 임계값 |
alb.ingress.kubernetes.io/healthcheck-port |
TargetGroup 포트 | Ingress, Service | Health Check 포트 |
alb.ingress.kubernetes.io/healthcheck-path |
/ |
Ingress, Service | Health Check URL 경로 |
alb.ingress.kubernetes.io/healthcheck-interval-seconds |
30 |
Ingress, Service | Health Check 주기(초) |
alb.ingress.kubernetes.io/healthcheck-protocol |
HTTP |
Ingress, Service | Health Check 프로토콜 - HTTP , HTTPS |
alb.ingress.kubernetes.io/backend-protocol |
HTTP |
Ingress, Service | Target Group의 프로토콜 - HTTP , HTTPS |
alb.ingress.kubernetes.io/enable-sticky-session |
false |
Ingress, Service | Target Group의 Sticky Session 설정 |
alb.ingress.kubernetes.io/actions.${actionName}
: actions 모델에 맞게 json 형태의 string으로 작성하여 Listener Rule의 추가적인 기능들을 설정할 수 있습니다. Ingress에 설정된 Rule의 serviceName을 사용하고자 하는${actionName}
으로 설정하고, servicePort를use-annotation
으로 설정하면 Annotation이 적용됩니다.
Property | Type | 설명 |
---|---|---|
type | string | action의 type을 정의합니다. - 설정 가능한 값 targetGroup , redirection |
targetGroup | object | action의 type을 targetGroup 으로 설정한 경우 사용됩니다. |
targetGroup.targetGroups | array | 트래픽을 전달할 service의 목록입니다. |
targetGroup.targetGroups[n].serviceName | string | service name |
targetGroup.targetGroups[n].servicePort | number | service port |
targetGroup.enableStickySession | boolean | sticky session 활성화 여부 - 기본값: false |
redirection | object | action의 type을 redirection 으로 설정한 경우 사용됩니다. |
redirection.host | string | - 기본값: #{host} |
redirection.path | string | - 기본값: /#{path} |
redirection.query | string | - 기본값: #{query} |
redirection.port | string | redirection 포트 - 기본값: #{port} |
redirection.protocol | string | - 설정 가능한 프로토콜: HTTP , HTTPS - 기본값: #{protocol} |
redirection.statusCode | number | - 설정 가능한 코드: 301 , 302 |
- 예시
- 경로
/example
에 actionName이targets
인 Annotation을 설정하여 두 개의 Service(a, b)로 가중치 기반 라우팅이 되도록 설정apiVersion: extensions/v1beta1 kind: Ingress metadata: name: example-alb-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]' alb.ingress.kubernetes.io/actions.targets: > {"type":"targetGroup","targetGroup":{"targetGroups":[{"serviceName":"a","servicePort":80,"weight":40},{"serviceName":"b","servicePort":80,"weight":60}],"enableStickySession":false}} labels: app: example-alb-ingress spec: rules: - http: paths: - path: /example backend: serviceName: targets servicePort: use-annotation
- 경로
alb.ingress.kubernetes.io/conditions.${conditionName}
: conditions 모델에 맞게 json 형태의 string으로 작성하여 Ingress에 정의된 Host, Path 조건 외에 추가 조건들을 설정할 수 있습니다. Ingress Rule에서${conditionName}
과 일치하는 serviceName을 가진 Service에 대해 조건을 적용합니다.
Property | Type | 설명 |
---|---|---|
field | string | 추가할 조건을 정의합니다. - 설정 가능한 값 hostHeader , pathPattern |
hostHeader | object | condition의 field를 hostHeader 으로 설정한 경우 사용됩니다. |
hostHeader.values | array | host 목록입니다. |
hostHeader.values[n] | string | host |
pathPattern | object | condition의 field를 pathPattern 으로 설정한 경우 사용됩니다. |
pathPattern.values | array | path 목록입니다. |
pathPattern.values[n] | string | path |
- 예시
- 기존 rule에 설정된 경로
/example
에 host 조건example.com
과 path 조건/example2
를 추가apiVersion: extensions/v1beta1 kind: Ingress metadata: name: example-alb-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/conditions.example: > [{"field":"hostHeader","hostHeader":{"values":["example.com"]}},{"field":"pathPattern","pathPattern":{"values":["/example2"]}}] labels: app: example-alb-ingress spec: rules: - http: paths: - path: /example backend: serviceName: example servicePort: 80
- 기존 rule에 설정된 경로
Example
라우팅 예제
서로 다른 3개의 Service에 대해 다양한 방법으로 라우팅하는 예제입니다.
아래 명령을 실행하면 3개의 Sample용 Deployment 및 Service가 생성됩니다. 각 서비스의 이름은 naver
, cloud
, platform
입니다.
kubectl --kubeconfig=$KUBE_CONFIG apply -f https://gist.githubusercontent.com/NaverCloudPlatformDeveloper/0e6262b996f74229719807cb5ae007fc/raw/3ce72e7961bc2407bfb87e153c94672e6ee6a1cf/nks-alb-ingress-sample-services.yaml
생성한 서비스들에 대해 아래와 같이 동작하도록 Ingress를 생성해보겠습니다.
- 경로별 동작
- /platform: Service
platform
으로 라우팅합니다. - /navercloud: 50 대 50의 가중치로
naver
,cloud
두 Service로 라우팅합니다. - 그 외의 모든 경로: Service
naver
로 라우팅합니다.
- /platform: Service
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: sample-alb-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
alb.ingress.kubernetes.io/description: 'alb ingress controller'
alb.ingress.kubernetes.io/actions.navercloud: >
{"type":"targetGroup","targetGroup":{"targetGroups":[{"serviceName":"naver","servicePort":80,"weight":50},{"serviceName":"cloud","servicePort":80,"weight":50}]}}
labels:
app: sample-alb-ingress
spec:
backend:
serviceName: naver
servicePort: 80
rules:
- http:
paths:
- path: /platform
backend:
serviceName: platform
servicePort: 80
- path: /navercloud
backend:
serviceName: navercloud
servicePort: use-annotation
위 내용으로 ingress.yaml 파일을 생성 후 아래의 명령으로 클러스터에 Ingress를 생성합니다.
kubectl --kubeconfig=$KUBE_CONFIG apply -f ./ingress.yaml
Ingress가 생성되면 Application Load Balancer를 생성하고, 생성이 완료되면 Ingress의 ADDRESS에 Load Balancer 접속정보가 업데이트 되는 것을 확인할 수 있습니다.
kubectl --kubeconfig=$KUBE_CONFIG get ingress
NAME HOSTS ADDRESS PORTS AGE
sample-alb-ingress * ing-default-samplealbing-e5bde-1494091-0687c0712561.kr.lb.naverncp.com 80 21s
Load Balancer의 주소를 호출하여 ingress에 설정한 경로들이 각각 다른 Service의 Pod로 연결되는지 Server name에서 확인할 수 있습니다.
/navercloud (여러번 호출 하여 naver, cloud로 라우팅 확인)
$ curl http://ing-default-samplealbing-e5bde-1494091-0687c0712561.kr.lb.naverncp.com/navercloud Server address: 198.18.0.160:80 Server name: cloud-868dcd94cb-7lpl6 Date: 15/Oct/2020:12:31:25 +0000 URI: /navercloud Request ID: 6eaff95fa4000943b9aea8903ba8e598 $ curl http://ing-default-samplealbing-e5bde-1494091-0687c0712561.kr.lb.naverncp.com/navercloud Server address: 198.18.0.75:80 Server name: naver-5b64c89ff8-gwqxx Date: 15/Oct/2020:12:35:59 +0000 URI: /navercloud Request ID: 9aa7cc193798ce3bce89718570fb9cb9
- /platform
$ curl http://ing-default-samplealbing-e5bde-1494091-0687c0712561.kr.lb.naverncp.com/platform Server address: 198.18.0.35:80 Server name: platform-85f9569d46-9zx6v Date: 15/Oct/2020:12:31:34 +0000 URI: /platform Request ID: 2c9ef5533e8eb3421f129a095ab0b418
- /navercloudplatform(설정에 없는 경로)
$ curl http://ing-default-samplealbing-e5bde-1494091-0687c0712561.kr.lb.naverncp.com/navercloudplatform Server address: 198.18.0.75:80 Server name: naver-5b64c89ff8-gwqxx Date: 15/Oct/2020:12:31:46 +0000 URI: /navercloudplatform Request ID: aa95fbc807f305e6a8a07aa6a57884b2
HTTP를 HTTPS로 리다이렉트하기
action type이 redirection인 annotation을 활용하여 HTTP(80)
로 들어오는 트래픽을 HTTPS(443)
으로 redirect하는 예제입니다.
이 예제를 수행하기 위해서는 먼저 도메인이 필요하며, 해당 도메인에 대한 Certificate Manager 상품에 등록 된 인증서가 필요합니다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-certificate-no: "1004"
alb.ingress.kubernetes.io/actions.ssl-redirect: |
{"type":"redirection","redirection":{"port": "443","protocol":"HTTPS","statusCode":301}}
labels:
app: sample-alb-ingress
name: sample-alb-ingress
namespace: sample
spec:
backend:
serviceName: my-service
servicePort: 80
rules:
- http:
paths:
- path: /*
backend:
serviceName: ssl-redirect
servicePort: use-annotation
- path: /*
backend:
serviceName: my-service
servicePort: 80
80 포트를 443 포트로 redirection하기 위해 두개의 port를 등록합니다.
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS":443}]'
HTTPS 리스너에 등록할 인증서 번호입니다. 인증서 번호는 Resource Manager의 nrn에서 확인할 수 있습니다. (예: nrn:PUB:CertificateManager::000:Certificate/External/${certificateNo})
alb.ingress.kubernetes.io/ssl-certificate-no: "1004"
443 포트로 redirect하는 action을 등록합니다.
alb.ingress.kubernetes.io/actions.ssl-redirect: | {"type":"redirection","redirection":{"port": "443","protocol":"HTTPS","statusCode":301}}
/*
경로에 트래픽이 들어오면 ssl-redirect에 등록한 action 설정대로 443 포트로 redirect 합니다.(이 rule은 최상단에 위치해야 합니다.)- path: /* backend: serviceName: ssl-redirect servicePort: use-annotation
443 포트로 들어온 트래픽이 my-service로 전달됩니다.
- path: /* backend: serviceName: my-service servicePort: 80
기본적으로 alb-ingress-controller는 ingress에 등록된 rule들을 모든 listener에 동일하게 등록합니다. 하지만 redirect 설정의 경우 redirect loop가 발생할 수 있는 케이스에서는 해당하는 포트의 listener에는 redirect rule을 등록하지 않습니다. 따라서 위의 예제에서는 80포트의 리스너에만 redirect rule이 등록이 됩니다.