AWS Load Balancer Controller 추가 기능 설치를 참고하여 작성하였습니다.
EKS 클러스터에는 OpenID Connect (OIDC) 발급자 URL이 연결되어 있습니다. 서비스 계정에 IAM 역할을 사용하려면 클러스터의 OIDC 발급자 URL에 IAM OIDC 제공업체가 있어야 합니다.
Kubernetes Service Account에 IAM Role을 부여하기 위해서는 IAM OIDC Provider가 활성화되어 있어야 합니다. 여기서 말하는 '활성화'는 EKS 클러스터와 IAM OIDC Provider의 association을 의미합니다.
IAM OIDC Provider는 기본적으로 활성화되어 있지 않기 때문에 (default: not enabled) 하기 명령어를 이용하여 OIDC provider를 생성합니다.
$ eksctl utils associate-iam-oidc-provider --cluster=<EKS_CLUSTER_NAME> --approve
위 명령어로 생성되는 Provider 명은 oidc.eks.ap-northeast-2.amazonaws.com/id/<CLUSTER_ID>
이며 생성된 IAM OIDC provider는 IAM 콘솔의 Identity providers 항목에서 확인할 수 있습니다.
위와 같이 IAM OIDC provider가 생성된 것을 확인했다면 이제 AWS Load Balancer Controller가 사용할 IAM Role을 생성해 보겠습니다.
IAM Policy는 다음과 같으며 하기 링크를 통해 다운로드가 가능합니다.
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy_us-gov.json
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
저는 서울 리전(ap-northeast-2)을 사용하고 있으므로 '기타 모든 AWS 리전' Policy를 다운받아 IAM Policy를 생성하였습니다.
# 기타 모든 AWS 리전
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": "elasticloadbalancing.amazonaws.com"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInternetGateways",
...
...
IAM Role을 생성하여 위에서 생성한 IAM Policy를 붙입니다. 그 다음 생성한 IAM Role의 Trust relationship을 수정합니다.
하기 예시에서 ACCOUNT_ID
, REGION_CODE
, CLUSTER_ID
를 변경하면 됩니다.
(클러스터가 '미국 동부(us-east)' or '미국 서부(us-west)' 리전에 있는 경우는 arn:aws:
를 arn:aws-us-gov:
로 바꿔야 합니다.)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>:aud": "sts.amazonaws.com",
"oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
}
}
}
]
}
생성한 IAM Role을 annotation으로 사용하는 ServiceAccount를 kube-system
네임스페이스에 배포합니다.
# 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::<ACCOUNT_ID>:role/<위에서_생성한_IAM_ROLE_NAME>
# ServiceAccount 배포
$ kubectl apply -f aws-load-balancer-controller-service-account.yaml
# 생성 확인
kubectl get serviceaccount -n kube-system
NAME SECRETS AGE
attachdetach-controller 0 145d
aws-cloud-provider 0 145d
aws-load-balancer-controller 0 18s # 생성됨
...
이제 사전 준비가 완료되었으니 helm을 사용하여 AWS Load balancer controller를 설치해 보겠습니다.
helm V3 이상을 사용하여야 합니다.
$ helm version
version.BuildInfo{Version:"v3.8.2", GitCommit:"6e3701edea09e5d55a8ca2aae03a68917630e91b", GitTreeState:"clean", GoVersion:"go1.17.5"}
eks-charts 리포지토리를 추가합니다.
$ helm repo add eks https://aws.github.io/eks-charts
"eks" has been added to your repositories
$ helm repo list
NAME URL
eks https://aws.github.io/eks-charts
최신 차트가 적용되도록 local repository를 업데이트합니다.
$ helm repo update eks
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "eks" chart repository
Update Complete. ⎈Happy Helming!⎈
AWS Load Balancer Controller를 설치합니다.
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=<CLUSTER_NAME> \
--set serviceAccount.create=false \
--set serviceAccount.name=<위에서_생성한_ServiceAccount_NAME>
kube-system
네임스페이스 설치된 리소스들을 확인합니다.
$ k get all -n kube-system
NAME READY STATUS RESTARTS AGE
pod/aws-load-balancer-controller-58df668c77-5k4gj 0/1 Pending 0 2m17s
pod/aws-load-balancer-controller-58df668c77-6nk9h 0/1 Pending 0 2m17s
...
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/aws-load-balancer-webhook-service ClusterIP 172.20.195.78 <none> 443/TCP 2m17s
...
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/aws-load-balancer-controller 0/2 2 0 2m17s
...
NAME DESIRED CURRENT READY AGE
replicaset.apps/aws-load-balancer-controller-58df668c77 2 2 0 2m17s
...
nginx 생성
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
name: nginx
spec:
containers:
- image: nginx:latest
name: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: service-nginx
annotations:
alb.ingress.kubernetes.io/healthcheck-path: "/"
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
mario 생성
apiVersion: v1
kind: Pod
metadata:
labels:
app: mario
name: mario
spec:
containers:
- image: pengbai/docker-supermario
name: mario
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: service-mario
annotations:
alb.ingress.kubernetes.io/healthcheck-path: "/"
spec:
selector:
app: mario
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 8080
ingress 생성
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-test
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/load-balancer-name: <생성할_LB_NAME>
alb.ingress.kubernetes.io/subnets: <SUBNET_ID_1>,<SUBNET_ID_2>
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:<REGION-CODE>:<ACCOUNT_ID>:certificate/<CERTIFICATE_ID>
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
rules:
- host: nginx.mytestdomain.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: service-nginx
port:
number: 80
- host: mario.mytestdomain.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: service-mario
port:
number: 80
콘솔에서 ingress(ALB) 생성 확인
도메인 설정
서비스 접속 확인
개인적으로 공부하며 작성한 글로, 내용에 오류가 있을 수 있습니다.