최종 프로젝트 인프라 구축⑫ - EKS와 LB로 ArgoCD 엔드포인트 만들기
우수상!
프로젝트가 18일 끝났고, 심사위원들에게서 우수상을 수여받을 수 있었다!
물론 당직(当職)은 인프라 만들어주고, CI/CD 해주고 이런것밖에 없고
서비스 구현은 우리 개발자 분들이 다 해주었으니..(겸손)
아무튼 기억이 잊혀지기 전에 마저 클라우드 작업을 마무리지어보고자 한다!!
Bastion 서버로 EKS 접속
지난번에도 말했듯이 테라폼 코드로 EKS를 구축했다. 테라폼 파일은 여기서 eks_cluster.tf와 eks_node_group.tf를 참고하면 된다.
아무튼 이렇게 EKS를 구축하고 나서…
(참고로 당직의 EKS는 노드 2~4개, 각 노드는 t3.large 사양이다.)
당직의 EKS는 private subnet에 들어가 있기 때문에 공인 IP가 없다.
즉 인터넷에서 접속이 불가능하다는 것이다.
보안을 위해 이렇게 했기 때문에(아무나 서버 들어가서 kubectl delete 할 수는 없잖니) 우리는 외부(인터넷)에서 이 프라이빗에 들어갈 방법을 찾아야 한다.(그래야 kubectl을 하던가 뭐던가 하니)
예전 당직이 근무할 떈 Site to Site VPN으로 사내망과 VPC를 연결해서 개인 IP로private subnet에 들어갈 수 있었지만,
그건 기업이니까 그랬던 것이고 지금은 다른 방법을 써 줘야 한다.(플젝실 방화벽에 어떻게 접근할 수 있는가!)
그것은 바로 Bastion 서버!
위 사진처럼 바스티온 서버는 public subnet에 위치해 있어 공인 IP, 즉 인터넷으로 접속할 수 있다.
public subnet와 private subnet은 어차피 라우팅 테이블로 연결되어 있으니,
이 바스티온 서버에 먼저 들어간 다음 여기서 원격으로 EKS를 다루면 되는 것이다!
같은 원리로, 프라이빗 써브넷에 있는 EC2에 접속해야 할 때도 여기서 EC2의 사설 IP로 ssh 연결하면 된다.
(물론 최소한의 보안 그룹 설정-특정 IP대역만 bastion에 접속 가능-은 해 줘야겠죠?)
아무튼 바스티온 서버는 중개만 해 주는 것이니까 최소사양(t3.medium)으로 하나 만들고…
이렇게 EC2를 만들 때마다 접속하기 위한 pem키를 하나 만들어야 하는데,
최초 접속할 때는 pem키가 있는 디렉토리에서 콘솔창을 켜고
ssh -i (pem키 파일) ec2-user@(EC2 공인IP)
이렇게 접속해줘야 한다.
막간 - public, private 써브넷 만드는 법
사실 AWS VPC의 써브넷 생성에서는 private, public 구분이 없습니다. 그냥 사설 IP 대역만 선택할 수 있을 뿐이죠.
이 써브넷들을 퍼블릭, 프라이빗으로 만들어주는 것은 라우팅 테이블에서 합니다.
프라이빗, 퍼블릭 하나씩 라우팅 테이블을 만들어 준 다음
라우팅 테이블의 라우팅 편집에서
- private/public 공통으로 VPC 사설IP 대역
- private는 NAT 게이트웨이
- public은 인터넷 게이트웨이
이렇게 라우팅을 추가해 주면 됩니다..
public 예시: ::/0은 ‘IPv6 주소 전체’라는 뜻입니다.
EKS 연결
바스티온 서버에 들어왔으면 거기서 아래와 같은 일을 해 줘야 한다.
1
2
3
4
5
6
7
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws configure #IAM키입력
이렇게 aws cli를 설치한 다음 aws configure로 cli에 로그인해 주고
(aws configure로 로그인하려면 액세스 키와 씨크릿 키가 필요한데, 예전 테라폼 만들 때 포스트를 참고하세요~)
1
2
3
4
5
6
7
curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.30.2/2024-07-12/bin/linux/amd64/kubectl
chmod +x ./kubectl
mkdir -p $HOME/bin && mv ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH
aws eks update-kubeconfig --region ap-northeast-2 --name (내 eks 클라스터 이름)
이렇게 kubectl을 다운로드한 다음 aws eks update-kubeconfig로 bastion의 kubectl이 eks를 바라보도록 업데이트해 준다.
참고로 당연하겠지만, 사전에 eks 보안 그룹에 bastion 서버의 보안 그룹을 허용해줘야 한다.
만약 당직과 같이 bastion 서버를 AMI로 만들어놓았고, EKS를 매번 지웠다 설치해서 kubectl을 재연결해야 할 경우에는
1
aws eks describe-cluster --name cloud-eks --query cluster.resourcesVpcConfig.clusterSecurityGroupId
한 다음에
1
aws eks update-kubeconfig --region ap-northeast-2 --name (내 eks 클라스터 이름)
를 다시 해주면 된다.
ArgoCD LB 엔드포인트 만들기
ArgoCD 설치
개발환경 때와 동일하게
1
2
3
4
# 아르곶CD설치
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
해주면 된다. 다만 이번에는 EKS가 프라이빗에 있으니 개발환경처럼 노드포트를 통한 연결이 아닌, aws alb를 사용해서 접속해야 한다.
AWS ALB란
이 alb가 뭐냐면 AWS에서 제공해 주는 로드밸런서(LB)이다.
(AWS에는 alb 말고도 nlb라는 LB도 지원하는데, 이건 L7/L4 단위의 차이이고…지금은 안알아도돼)
로드밸런서는 흔히 부하 분산, 트래픽 제어 등 네트워크 구성을 위해 사용되는데, 이번에는 트래픽 제어의 용도로 사용할 것이다.
즉 alb가 외부(인터넷)에서 접속할 엔드포인트(주소)를 마련해 주고,
이 주소의 특정 포트로 접근하면 해당 포트로 들어오는 트래픽을 특정 서비스로 가도록 설정하는 것이다.
이를 리버스 프록시라고 하며, 로드밸런서의 주요 기능이기도 하다.
(온프레미스 환경에서는 Nginx로 구현할 수 있어요)
보통은(EC2 내 서비스로 연결하려면) 콘솔에서 직접 설정하지만, EKS 환경에서는 별도로 aws load balancer로 설치해줘야 한다.
aws load balancer controller 설치
일단 EKS 클라스터에 aws load balancer controller 서비스를 설치해야 alb가 작동할 환경이 만들어진다.
아래는 공식 문서를 기반으로, 제가 제멋대로 구성한 설정 방법입니다.
일단 위 문서대로 설치하려면, eksctl과 helm을 설치해줘야 한다.
eksctl은 eks 제어에, helm은 컨트롤러 설치에 필요하기 때문이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# eksctl(https://docs.aws.amazon.com/eks/latest/eksctl/installation.html 에서 가져옴)
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
# (Optional) Verify checksum
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check
tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
sudo install -m 0755 /tmp/eksctl /usr/local/bin && rm /tmp/eksctl
# 헬름(https://helm.sh/docs/intro/install/ 에서 가져옴)
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
이렇게 설치 했으면, 컨트롤러를 설치할 수 있다!…는 아니고
컨트롤러가 EKS에 제대로 작동할 수 있도록 IAM 사전 설정을 해줘야 한다.
1
2
3
4
5
6
7
8
# IAM OICD 공급자 설정
cluster_name=cloud-eks
oidc_id=$(aws eks describe-cluster --name $cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
echo $oidc_id
aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4
# 위 명령어 결과가 없으면
eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve
다시 말하지만, aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4를 했을 때 이상한 문자 모음이 나오지 않으면,
eksctl utils associate-iam-oidc-provider --cluster $cluster_name --approve를 해줘야 한다.
위처럼 IAM OIDC 공급자인가 뭔가 하는 설정을 해 주고, EKS IAM에 LB 컨트롤러 역할을 추가해 준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 이하 https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/lbc-helm.html 기반
# IAM역할생성
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.13.3/docs/install/iam_policy.json
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json
eksctl create iamserviceaccount \
--cluster=cloud-eks \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::414901227428:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--region ap-northeast-2 \
--approve
이렇게 하면 ALB 컨트롤러 설치를 위한 IAM 셋팅이 되었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
# LB컨설치
helm repo add eks https://aws.github.io/eks-charts
helm repo update eks
helm upgrade --install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=(내 eks 클라스터 이름) \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set vpcId=(내 VPC ID) \
--set region=ap-northeast-2 \
--version 1.13.0
참고로 VPC와 EKS를 삭제했다 다시 만드는 등 재설치가 필요한 경우,
1
2
3
4
5
6
7
8
9
# EKS 새로 열 때마다
aws eks update-kubeconfig --region ap-northeast-2 --name cloud-eks
# 이걸로 바스티온-EKS 재연결한 다음
eksctl delete iamserviceaccount \
--cluster=cloud-eks \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--region ap-northeast-2
# 이거 수행 후 eksctl create...부터 진행(안그럼 LB컨이 안먹어)
먼저 IAM 권한을 지우고(삭제했던 VPC에 묶여있던 설정 제거) eksctl create iamserviceaccount ...부터 다시 해줘야 한다.
이렇게 하고 kubectl get svc -n kube-system을 해 보면
이렇게 노드당 하나씩 서비스가 생기고, Running으로 되어 있어야 정상이다!
ArgoCD 엔드포인트용 ingress 생성
이제 드디어 ALB를 설치할 수 있다.
아까도 말했지만 ArgoCD 접속을 위해 노드포트 대신 Ingress라는 걸 사용할 것인데,
잉그레스는 간단히 말해서 클러스터 외부와 내부 서비스 간의 연결 통로이다.
노드포트는 IP:포트로 연결하고 포트도 30000번대를 사용하기 때문에 개발환경에 사용했고,
실제 운영을 위해서는 도메인을 적용하는 등 확장성이 높은 Ingress를 사용할 것이다.
이번에도 공식 문서를 제멋대로 번형한 설치 가이드입니다.
쿠버네티스는 이 잉그레스를 Nginx, HAProxy 등 다양한 기반으로 제공하는데, 이번에는 ALB를 기반으로 구성할 거니까 아래와 같이 작업을 해 준다.
1
2
3
4
5
6
apiVersion: eks.amazonaws.com/v1
kind: IngressClassParams
metadata:
name: alb
spec:
scheme: internet-facing
이렇게 alb-ingressclassparams.yaml 파일을 만들어 준 다음kubectl apply -f alb-ingressclassparams.yaml을 하고
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: alb
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: eks.amazonaws.com/alb
parameters:
apiGroup: eks.amazonaws.com
kind: IngressClassParams
name: alb
또 alb-ingressclass.yaml 파일을 만들어 kubectl apply -f alb-ingressclass.yaml를 해 줘야 한다.
눈치가 빠른 분들은 아시겠지만, 위 IngressClassParam을 IngressClass에 적용하는 것이다.
그럼 이제 이 ALB 기반 IngressClass를 ArgoCD에 써먹기 위해
1
2
3
4
5
6
apiVersion: eks.amazonaws.com/v1
kind: IngressClassParams
metadata:
name: alb
spec:
scheme: internet-facing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
alb.ingress.kubernetes.io/healthcheck-path: /healthz # ArgoCD의 기본 헬스체크 주소
alb.ingress.kubernetes.io/healthcheck-protocol: HTTP # HTTPS 안 쓸 거임
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}]' # HTTPS 안 쓸 거임
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/backend-protocol: HTTP # HTTPS 안 쓸 거임
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: (argocd 서비스명)
port:
number: 80
이렇게 argocd-ingress.yaml을 구성해 준다.
그런데 여기서 잠깐!
ArgoCD의 엔드포인트는 인증서 구성할 시간이 없어 HTTP로 구성할 것인데, 아르고CD는 기본적으로 HTTPS 통신을 전제로 하고 있기 때문에
이대로 kubectl apply를 하면 헬스체크 단계부터 307 오류가 뜬다.
307 오류는 HTTP 요청이 HTTPS로 리다이렉트되었다는 것으로,
따라서 ArgoCD가 HTTP 통신으로 작동하도록 해 줘야 하는데, 이는
1
2
3
4
5
6
7
8
9
10
# HTTPS 리다이렉트 제거-이거 없으면 LB에서 307오류
kubectl -n argocd edit configmap argocd-cmd-params-cm
#yaml파일 내
#apiVersion: v1
#data: # <-- 이 라인을 추가하세요.
# server.insecure: "true" # <-- 이 라인을 추가하세요.
#kind: ConfigMap
kubectl -n argocd delete pod $(kubectl -n argocd get pods -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[0].metadata.name}')
이렇게 ArgoCD의 configmap에서 server.insecure 항목을 true로 해 주는 data 옵션을 추가해준 다음 argocd-server pod를 재시작하면 된다.
이러고 진짜 kubectl apply -f argocd-ingress.yaml을 하면…
이렇게 kubectl get ingress를 했을 때 ADDRESS 항목에 엔드포인트가 나와야 정상이다!
위처럼 Ingress를 만들면 자동으로 로드밸런서가 한 개 생성되는데, AWS 콘솔에서 생성된 LB를 보면 LB의 DNS 주소가 저 엔드포인트로 되어있는 것을 볼 수 있다.
(추가로 LB 보안그룹도 yaml에서 설정한 80 포트만 들어오도록 자동 생성돼요)
아무튼 저 엔드포인트로 접속하면 ArgoCD 콘솔에 들어갈 수 있다!
그런데 지금은 HTTPS 연결이 필수불가결한 시대잖아, 너무 보안에 취약한 거 아니야? 하시는 분들이 있을 텐데,
이를 위해 다음 시간에 계속됩니다…











