EKS 생성 & 셋업
5. oidc 조회 및 클러스터 service account 생성

5. oidc 조회 및 클러스터 service account 생성

AWS Loadbalancer Controller 의 공식 깃헙 블로그는 kubernetes-sigs.github.io/aws-load-balancer-controller (opens in a new tab) 이다.


로드밸런서 컨트롤러를 설정하기 위해서 가장 먼저 확인해야 할 내용은 Open Id Connect 가 쿠버네티스와 잘 연결되어 사용되고 있는지이다.


쿠버네티스는 인그레스나 이런 것들을 배포를 하고 나면 Amazon 의 ALB 등을 제어를 해야 하는데, 이렇게 AWS 에 존재하는 ALB등을 제어하기 위해서 인증 방식의 다양한 방법 들 중 OAuth 방식의 Open Id Connect 를 지원해주고 있다.


참고


환경변수 선언

cluster_name , oidc 선언

terminal
$ export cluster_name=gitops-study-k8scluster
 
## eks cluster 에 대한 oidc_id 를 조회한다.
$ oidc_id=$(aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
 
## 구한 eks cluster 에 대한 oidc 를 출력해본다. 
$ echo $oidc_id
8889A26B47C0F157228D712D894CA629

생성한 oidc_id 는 필요할 때마다 아래의 명령을 수행해도 되지만 복사해서 따로 보관해두면 편하다.

terminal
$ aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5

만약 출력된 결과가 없다면 oidc 가 없다는 것인데, 아래의 명령을 통해 OIDC 자격증명 공급자를 생성해야 한다.

terminal
$ eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve
2023-12-24 13:56:17 [ℹ]  will create IAM Open ID Connect provider for cluster "gitops-study-k8scluster" in "ap-northeast-2"
2023-12-24 13:56:17 [✔]  created IAM Open ID Connect provider for cluster "gitops-study-k8scluster" in "ap-northeast-2"

내 경우에는 cluster 에 대한 iamserviceaccount 를 생성시에 오류가 났고, 위의 명령어를 그대로 수행하라는 출력이 나타났다. 그래서 위의 명령어를 수행한 후에 iamserviceaccount 를 다시 생성했다.



IAM 정책 json 다운로드 & AWS CLI로 정책 생성

kubernetes 공식 깃헙 계정(github.com/kubernetes-sigs) 내의 리포지터리인 github.com/kubernetes-sigs/aws-load-balancer-controller (opens in a new tab) 에서는 kubernetes 에서 AWS 환경에 맞도록 Ingress Controller 를 설치하기 위해 aws-load-balancer-controller 를 구성할 때 필요한 IAM Policy 부터 여러가지 다양한 AWS 환경 내에서의 리소스 Json 및 예제 등을 제공하고 있다.


아래 iam_policy.json 은 위에서 공식 깃헙 계정 내의 https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/docs/install/iam_policy.json (opens in a new tab) 에서 제공하는 IAM 정책 json 파일이다.


Cloud9 에서 다 귀찮다 싶으면 raw 파일 링크 (opens in a new tab) 을 통해 curl 로 다운받아서 사용하면 된다.



iam-policy
{
    "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",
                "ec2:DescribeVpcs",
                "ec2:DescribeVpcPeeringConnections",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeInstances",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeTags",
                "ec2:GetCoipPoolUsage",
                "ec2:DescribeCoipPools",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeLoadBalancerAttributes",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeListenerCertificates",
                "elasticloadbalancing:DescribeSSLPolicies",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetGroupAttributes",
                "elasticloadbalancing:DescribeTargetHealth",
                "elasticloadbalancing:DescribeTags"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cognito-idp:DescribeUserPoolClient",
                "acm:ListCertificates",
                "acm:DescribeCertificate",
                "iam:ListServerCertificates",
                "iam:GetServerCertificate",
                "waf-regional:GetWebACL",
                "waf-regional:GetWebACLForResource",
                "waf-regional:AssociateWebACL",
                "waf-regional:DisassociateWebACL",
                "wafv2:GetWebACL",
                "wafv2:GetWebACLForResource",
                "wafv2:AssociateWebACL",
                "wafv2:DisassociateWebACL",
                "shield:GetSubscriptionState",
                "shield:DescribeProtection",
                "shield:CreateProtection",
                "shield:DeleteProtection"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:RevokeSecurityGroupIngress"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSecurityGroup"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags"
            ],
            "Resource": "arn:aws:ec2:*:*:security-group/*",
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": "CreateSecurityGroup"
                },
                "Null": {
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags",
                "ec2:DeleteTags"
            ],
            "Resource": "arn:aws:ec2:*:*:security-group/*",
            "Condition": {
                "Null": {
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "true",
                    "aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:RevokeSecurityGroupIngress",
                "ec2:DeleteSecurityGroup"
            ],
            "Resource": "*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:CreateLoadBalancer",
                "elasticloadbalancing:CreateTargetGroup"
            ],
            "Resource": "*",
            "Condition": {
                "Null": {
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:CreateListener",
                "elasticloadbalancing:DeleteListener",
                "elasticloadbalancing:CreateRule",
                "elasticloadbalancing:DeleteRule"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:RemoveTags"
            ],
            "Resource": [
                "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
            ],
            "Condition": {
                "Null": {
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "true",
                    "aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddTags",
                "elasticloadbalancing:RemoveTags"
            ],
            "Resource": [
                "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*",
                "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*",
                "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*",
                "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:ModifyLoadBalancerAttributes",
                "elasticloadbalancing:SetIpAddressType",
                "elasticloadbalancing:SetSecurityGroups",
                "elasticloadbalancing:SetSubnets",
                "elasticloadbalancing:DeleteLoadBalancer",
                "elasticloadbalancing:ModifyTargetGroup",
                "elasticloadbalancing:ModifyTargetGroupAttributes",
                "elasticloadbalancing:DeleteTargetGroup"
            ],
            "Resource": "*",
            "Condition": {
                "Null": {
                    "aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:AddTags"
            ],
            "Resource": [
                "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
            ],
            "Condition": {
                "StringEquals": {
                    "elasticloadbalancing:CreateAction": [
                        "CreateTargetGroup",
                        "CreateLoadBalancer"
                    ]
                },
                "Null": {
                    "aws:RequestTag/elbv2.k8s.aws/cluster": "false"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:DeregisterTargets"
            ],
            "Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:SetWebAcl",
                "elasticloadbalancing:ModifyListener",
                "elasticloadbalancing:AddListenerCertificates",
                "elasticloadbalancing:RemoveListenerCertificates",
                "elasticloadbalancing:ModifyRule"
            ],
            "Resource": "*"
        }
    ]
}

이번 실습에서는 curl 을 통해서 IAM 정책을 적용하기로 했다.
메인 브랜치 IAM Policy json 링크


v2.5.4 브랜치 IAM Policy json 링크


나는 메인 브랜치의 IAM Policy Json 을 사용하기로 했다.

terminal
## iam policy 다운로드
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8386  100  8386    0     0  28407      0 --:--:-- --:--:-- --:--:-- 28523
 
## 다운로드 받은 json 파일인 iam_policy.json 을 이용해서 IAM Policy 생성 
$ aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
 
실행결과
{
    "Policy": {
        "PolicyName": "AWSLoadBalancerControllerIAMPolicy",
        "PolicyId": "ANPARSRDIIP7ERQMT63QE",
        "Arn": "arn:aws:iam::{IAM 계정 ID}:policy/AWSLoadBalancerControllerIAMPolicy",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2023-12-24T12:55:42+00:00",
        "UpdateDate": "2023-12-24T12:55:42+00:00"
    }
}
 

Service Account 생성

terminal
$ eksctl create iamserviceaccount \
> --cluster=gitops-study-k8scluster \
> --namespace=kube-system \
> --name=aws-load-balancer-controller \
> --role-name AmazoneEKSLoadBalancerControllerRole \
> --attach-policy-arn=arn:aws:iam::{IAM 계정 ID}:policy/AWSLoadBalancerControllerIAMPolicy \
> --approve

결과를 확인해본다.

terminal
$ aws sts get-caller-identity
{
    "UserId": "AIDARSRDIIP7JGE4QNBL7",
    "Account": "108521866238",
    "Arn": "arn:aws:iam::108521866238:user/gitops-study-argocd"
}

생성된 service account 를 확인해본다.

terminal
$ kubectl describe sa aws-load-balancer-controller -n kube-system
Name:                aws-load-balancer-controller
Namespace:           kube-system
Labels:              app.kubernetes.io/managed-by=eksctl
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::108521866238:role/AmazoneEKSLoadBalancerControllerRole
Image pull secrets:  <none>
Mountable secrets:   <none>
Tokens:              <none>
Events:              <none>
 
## 또는 아래와 같이 serviceaccount 를 모두 적어주어도 된다.
$ kubectl describe serviceaccount aws-load-balancer-controller -n kube-system                                         
Name:                aws-load-balancer-controller
Namespace:           kube-system
Labels:              app.kubernetes.io/managed-by=eksctl
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::108521866238:role/AmazoneEKSLoadBalancerControllerRole
Image pull secrets:  <none>
Mountable secrets:   <none>
Tokens:              <none>
Events:              <none>