안녕하세요? DevOps Engineer 제이디입니다.
이번 포스팅에서는 AWS Cross-Account EKS 클러스터 간 ArgoCD 기반 Helm Chart GitOps 배포 가이드를 공유하겠습니다.
목차는 다음과 같습니다.
- IRSA (IAM Role for Service Accounts)
- Assume Role
- ArgoCD Cluster Add
- Helm Repo (w/ Kustomize)
- GitOps Deploy
AWS EKS 환경에서 GitOps를 구성하기 위해 ArgoCD와 같은 도구는 필수입니다. 워크로드가 늘어나면서 EKS 클러스터가 확장되면 ArgoCD를 어떻게 구축하고 운영하게 될지 고민하게됩니다. 이번 포스팅은 단일 ArgoCD에 여러개의 EKS 클러스터를 등록하면서 구축하고 운영하는 배포 가이드입니다.
현재 구성해서 사용중인 아키텍처는 아래와 같습니다.
IRSA (IAM Role for Service Accounts)
아키텍처의 번호 순서대로 하나씩 살펴보시죠!
첫번째로 이해해야하는 내용은 IRSA (IAM Role for Service Accounts)입니다. 쉽게 생각해보시죠!
ArgoCD를 구축하면 실제 EKS에 서비스를 배포하는 Pod가 생성됩니다. ArgoCD Application Controller입니다.
Application Controller가 어떻게 EKS에 서비스를 배포할 수 있을까요? AWS에는 그런 권한을 IAM (Identity and Access Management)이라는 서비스로 제공하고 있습니다. 그러면 Application Controller라는 Pod가 어떻게 적절한 IAM을 갖을 수 있을까요? 그 연결자가 바로 ServiceAccount입니다.
즉 ServiceAccount는 EKS에서 Pod가 IAM Role을 갖을 수 있게 해주는 연결자 역할을합니다.
실제로 코드로 살펴보시죠.
ArgoCD를 EKS에 Helm으로 구성할때 values.yaml에 아래와 같이 설정합니다.
# ───── ServiceAccounts ─────
controller:
serviceAccount:
create: true
name: argocd-application-controller
annotations:
eks.amazonaws.com/role-arn: $ARGOCD_IAM_ROLE_ARN
# ───── ArgoCD Config ─────
configs:
cm:
kustomize.buildOptions: --enable-helm=true
Application Controller에서 사용하는 ServiceAccount를 생성할때 Annotation를 추가합니다.
바로 내가 생성한 IAM Role의 ARN (Amazon Resource Name) 즉, 리소스의 ID이죠!
자 그러면 Annotaion에 추가할 IAM Role은 어떻게 생성해야 할까요?
ArgoCD 설치는 아래 링크를 참고해주세요
https://github.com/argoproj/argo-helm/tree/main/charts/argo-cd
Assume Role
ArgoCD Application Controller에서 사용하는 IAM Role을 생성하기 위해서 처음에 Trust Policy를 설정합니다.
Trust Policy는 누가 이 IAM Role을 사용 할 수 있을지? 정의하는 부분입니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::$ACCOUNT_ID:oidc-provider/$OIDC"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"$OIDC:sub": "system:serviceaccount:$ARGOCD_NAMESPACE:argocd-application-controller"
}
}
}
]
}
AWS Account ID를 입력 후 ArgoCD를 설치한 AWS EKS를 보면 OIDC (OpenID Connect Provider URL)를 확인 할 수 있습니다.
http 프로토콜을 제외하고 입력합니다. ArgoCD를 설치한 NameSpace까지 입력하면 설정이 완료됩니다.
위 내용을 보면, ArgoCD를 설치한 EKS에서 ArgoCD NameSpace의 ArgoCD Application Controller가 해당 IAM Role를 사용 할 수 있게 되겠네요 (바로 Service Account에 의해서요)
Trust Policy를 구성하면 다음에 설정할건 바로 권한입니다. 즉 Role에 아래와 같이 Policy를 설정합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"$SERVICE_IAM_ROLE_ARN"
]
}
]
}
Policy는 ArgoCD의 Application Controller에 맵핑된 Service Account가 사용 할 수 있는 권한입니다. 여기에 어떤 권한이 필요할까요? 바로 Cross-Account 환경의 EKS 클러스터에 배포할 수 있는 권한이겠죠. Service IAM Role를 만들고나면 이해가 쉬워지실거에요!
Service Account 환경에 IAM Role을 생성할때 Trust Policy는 아래와 같이 생성합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "$ARGOCD_IAM_ROLE_ARN"
},
"Action": "sts:AssumeRole"
}
]
}
위 코드 내용을 보면 ArgoCD Account의 IAM Role이 지금 생성하는 Service Account의 IAM Role를 사용하게 해주는거죠. 이 개념이 바로 AssumeRole입니다. 실제로 Assume 이라는 개념은 아까도 했었는데요. ArgoCD Application Controller의 Pod가 ArgoCD IAM Role를 사용할 수 있게 해주는게 바로 Service Acounnt가 Pod와 IAM Role간에 Assume를 해준거였습니다.
마지막으로 Servce Account에서 EKS에 배포할 수 있는 권한을 Policy에 설정해야합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:List*",
"eks:AccessKubernetesApi"
],
"Resource": "*"
}
]
}
이렇게 Role에 EKS에 배포 가능한 권한을 설정하면, EKS에도 아래와 같이 권한을 설정해야합니다. AWS Console에서 EKS를 통해서 Access 탭을 선택하고 IAM Access entries를 추가합니다. IAM에는 $SERVICE_IAM_ROLE_ARN 정보를 입력합니다. Type은 Standard로 선택하고 Access Policy에 AmazonEKSClusterAdminPolicy를 선택합니다.
자 이제 Service Account가 대상 EKS에 배포할 수 있는 권한 셋팅이 모두 끝났습니다.
ArgoCD Cluster Add
ArgoCD에서 대상 EKS에 배포하기 위해서 사전에 Cluster Add를 진행합니다. 이번에는 kubeconfig 파일을 통해서 Cluster Add를 설명드리겠습니다. 대상 EKS에 kubeconfig 파일을 어떻게 생성 할 수 있을까요? 바로 앞에서 설정한 Service Account를 이용해보시죠
kubeconfig 파일을 생성하는 임시 Pod는 아래와 같이 생성합니다.
apiVersion: v1
kind: Pod
metadata:
name: kubeconfig-pod
namespace: argocd
spec:
serviceAccountName: argocd-application-controller
containers:
- name: tools
image: amazonlinux:2
command: ["/bin/sh", "-c"]
args:
- |
yum -y install jq unzip curl tar gzip shadow-utils gettext;
# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" &&
unzip awscliv2.zip &&
./aws/install;
# Install kubectl (latest stable version)
KUBECTL_VERSION=$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) &&
curl -LO "https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" &&
chmod +x kubectl &&
mv kubectl /usr/local/bin;
# Install Argo CD CLI
ARGOCD_VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest | grep tag_name | cut -d '"' -f 4) &&
curl -sSL -o /usr/local/bin/argocd "https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-linux-amd64" &&
chmod +x /usr/local/bin/argocd;
tail -f /dev/null
내용이 조금 길지만 하나씩 살펴보시죠, 가장 중요한건 kubeconfig를 생성하는 Pod에 앞에서 작업한 Service Account를 맵핑하는 내용입니다. 그래야 ArgoCD IAM Role 정보를 Assume해서 사용할 수 있겠죠?
그 외 내용은 ArgoCD Cluster Add를 진행하기 위해서 필요한 유틸을 설치하는 init 스크립트입니다.
ArgoCD가 설치된 Name Space에 kubeconfig-pod를 실행하고 exec 명령어를 통해 Pod 안으로 접속합니다. 이제 kubeconfig를 아래와 같이 생성 할 수 있습니다.
# role 기반 config 생성
export ROLE_ARN="$SERVICE_IAM_ROLE_ARN"
export SESSION_NAME="service-eks"
export CREDS_JSON=$(aws sts assume-role --role-arn "$ROLE_ARN" --role-session-name "$SESSION_NAME" --output json)
export AWS_ACCESS_KEY_ID=$(echo $CREDS_JSON | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS_JSON | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $CREDS_JSON | jq -r .Credentials.SessionToken)
aws eks update-kubeconfig \
--name $SERVICE_EKS_CLUSTER_NAME \
--region ap-northeast-2 \
--kubeconfig /tmp/service-eks
# kubeconfig 등록된 NAME 확인
kubectl config --kubeconfig /tmp/service-eks get-contexts
# argocd login
argocd login argocd-server.argocd.svc.cluster.local:443
# argocd cluster add
argocd cluster add $SERVICE_EKS_CLUSTER_ARN \
--kubeconfig /tmp/service-eks \
--name service-eks
Service Account에 Assume된 ArgoCD IAM Role를 통해서 Service IAM Role를 이용해 kubeconfig를 생성합니다.
kubeconfig를 생성하고 ArgoCD를 로그인 후 Cluster Add를 통해 Service EKS를 등록합니다.
Helm Repo (w/ Kustomize)
자 이제 서비스를 배포해보시죠! ArgoCD에서 서비스를 배포할때 여러 방식이 있는데 이번 포스팅에서는 Helm Chart를 Kustomize 기반으로 배포해보겠습니다. ArgoCD에서 Helm Chart를 Kustomize 기반으로 배포하기 위해서 아까 설치시 Config에 옵션을 추가했었습니다.
오늘 배포할 Helm Chart는 Grafana에서 제공하는 RUM (Real User Monitoring) 데이터 수집 Agent인 Grafana Alloy입니다.
Alloy 관련된 내용은 지난번 포스팅 (Grafana로 Frontend 모니터링하기 https://jd-vlog.tistory.com/11)를 참고해주세요.
GitLab에서 Helm Repo를 생성하고 Grafana Alloy의 values.yaml을 아래와 같은 형태로 구성합니다.
---
alloy:
metrics:
enabled: false
extraPorts:
- name: "faro"
port: 12347
targetPort: 12347
configMap:
content: |-
// Write your Alloy config here:
logging {
level = "info"
format = "logfmt"
}
...
그리고 values.yaml를 배포할 kustomization.yaml 파일을 같은 위치에 아래와 같이 생성합니다.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: $FRONTEND_NAME_SPACE
helmCharts:
- name: alloy
repo: https://grafana.github.io/helm-charts
version: 1.0.3
releaseName: grafana-alloy
valuesFile: values.yaml
GitOps Deploy
자 이제 Helm Chart를 Kustomize 기반으로 GitOps 배포하기 위해서 ArgoCD에 Application를 생성합니다.
ArgoCD에서 Application을 생성하기 위해서 NEW APP를 누르면 오른쪽에 EDIT AS YAML 버튼이 있습니다. 아래 형태로 입력합니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: grafana-alloy
spec:
project: defualt
destination:
name: service-eks
namespace: $FRONTEND_NAME_SPACE
source:
repoURL: $GITLAB_HELM_REPO_URL
targetRevision: $GIT_BRANCH_NAME
path: grafana-alloy
kustomize:
enableHelm: true
정상적으로 생성 후 SYNC를 누르면 아래와 같은 형태로 배포가 완료됩니다!
앞으로의 방향성
앞으로 고민할 방향성은 크게 두 가지로 정리할 수 있습니다.
- ArgoCD 운영 측면 수많은 고민
- 어떻게 하면 엔터프라이즈 환경에서 GitOps 사례를 더 만들 수 있을까?
앞으로도 할일이 참 많네요! 🚀
이번 포스팅에서는 AWS Cross-Account EKS 클러스터 간 ArgoCD 기반 Helm Chart GitOps 배포 가이드를 알아보았습니다.
앞으로도 더 좋은 포스팅으로 찾아뵙겠습니다.
감사합니다! 🙇♂️
'IT' 카테고리의 다른 글
AWS Serverless를 활용한 사내 메신저(Teams) 알림 메시지 발송하기 (0) | 2025.02.01 |
---|---|
Grafana로 Frontend 모니터링하기 (Image Renderer를 곁들인) (0) | 2024.12.07 |
AWS EKS 업그레이드 시 발생했던 이슈들 공유 (3) | 2024.07.20 |
GitHub-Flow 브랜치 전략에서 Develop 브랜치를 지워야하는 이유 (0) | 2024.06.30 |
Feature 브랜치 전략에 따른 개발 문화의 중요성 (1) | 2024.04.26 |