ArgoCD는 쿠버네티스 환경에서 운영을 위한 GitOps 도구 이다. GitOps는 Git과 Operations의 합성어이다. 현재 쿠버네티스 상태를 git으로 관리하는 문화것이다.즉, 쿠버네티스에 배포하려고 하는 상태를 Git에 저장하면 ArgoCD가 git에 있는 내용을 쿠버네티스 환경의 pod 에 배포를 하게 된다.
작성자의 경우 EKS 생성을 프라이빗으로 하여 VPC 외부에서 접근하지 못하게 하여 Bastion 에 접속하여 EKS 호출을 하였다. (API 서버 액세스는 프라이빗)
관련한 아키텍쳐는 Terraform 을 통한 EKS 생성 을 참고하면 좋을거 같다.
기본적인 EKS 구성은 완료 되었다는 가정하에 ArgoCD 설치를 진행한다.
# Bastion 에서 진행
# ArgoCD 설치
% kubectl create ns argocd
% kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 설치 확인 (argocd 컴퍼넌트와 DB(redis)가 pod로 실행)
% kubectl get all -n argocd
# Argocd CLI 설치
% VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
% curl -LO https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64
% chmod u+x argocd-linux-amd64
% sudo mv argocd-linux-amd64 /usr/local/bin/argocd
# Argocd ALB 접근을 위한 작업
% mkdir argocd
% cd argocd
% vi ingress.yaml (아래 yaml 참고)
% kubectl apply -f ingress.yaml -n argocd
# Argocd 패스워드 확인
% kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
mjNB8mWtLMoCu6Z1 (예시)
# Argocd 로그인
% argocd login <argocd server 쿠버네티스 서비스 Cluster IP>:<port> --insecure
or
% argocd login <매핑된 도메인> (ALB에 매핑한 도메인이 있는 경우)
WARN[0000] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
Username: admin
Password:
'admin:login' logged in successfully
Context '<매핑된 도메인>' updated
# Argocd 패스워드 변경
% argocd account update-password
WARN[0000] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
*** Enter password of currently logged in user (admin): 현재 패스워드
*** Enter new password for user admin:
*** Confirm new password for user admin:
Password updated
Context '<매핑된 도메인>' updated
작성자는 "kubectl apply -f ingress.yaml -n argocd" 명령어를 통해 배포한 ALB 에 도매인을 연결하였다.
# argocd/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/certificate-arn: <AWS ACM ARN>
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-2016-08
alb.ingress.kubernetes.io/backend-protocol: HTTPS
alb.ingress.kubernetes.io/healthcheck-path: /login
alb.ingress.kubernetes.io/target-type: 'ip'
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80,"HTTPS": 443}]'
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
finalizers:
- ingress.k8s.aws/resources
labels:
app: argocd-ingress
spec:
rules:
- http:
paths:
- path: /
backend:
service:
name: argocd-server
port:
number: 443
pathType: Prefix
argocd 자체에는 인증서를 가지고 있어 위와 같이 yaml 을 정의 하였다. 인증서 처리를 하지 않으려면 argocd 에서 설정 파일 수정이 필요한데 작성자는 도메인을 가지고 있기에 따로 진행하지는 않았다.
AWS Load Balancer Controller
위 링크는 Annotations 관련한 링크이며, 참고하면 좋을거 같다.
계정의 ID 는 Admin 이고, 패스워드를 변경하였다면 변경된 패스워드를 입력 후 접속을 하면 위와 같이 확인을 할 수 있다.
작성자의 경우 AWS LoadBalancer Controller 를 통해 ArgoCD 에 접속 가능한 ALB 에 ACM 인증서 작업과 도메인 매핑을 해둔 상태이다.
Github 에 올라온 manifest 파일의 변경 사항을 ArgoCD 가 감지하여 배포를 하기 위해 Github Repository 를 생성하였고, Private 로 생성을 하였다. (이미 생성을 하였기에 경고 문구가 떴다.)
Developer Settings
깃허브에 로그인 후 위 URL 에 접속을 하여 Token 을 발급 받는다. Public으로 생성한 Repo 라면 상관 없지만, Private로 만든 저장소이기에 발급이 필요하다.
==토큰 값은 어딘가에 무조건 저장하자!!!!==
아래는 쿠버네티스 환경에 Argocd 를 통해 배포하기 위한 yaml 내용이다. 설정쪽에서도 설명을 하겠지만, ArgoCD 에서 path 를 지정하는 곳이 있는데 나는 templates 아래에 있는 yaml 을 확인하도록 설정을 할 것이다.
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Deployment는 ReplicaSet의 상위 개념으로, Pod와 ReplicaSet에 대한 배포를 관리한다. 운영 중에 어플리케이션의 새 버전을 배포해야하거나 부하가 증가하면서 Pod를 추가하는 등 여러 가지 동작을 Deployment로 관리할 수 있다고 한다. (아직 뉴비라 이 부분은 잘 모르겠음)
또한, Deployment는 배포에 대한 이력을 관리하는데 만약 배포한 새버전의 문제가 생긴 경우 Deployment를 통해 쉽게 이전 버전으로 롤백할 수 있다. 쿠버네티스로 서비스를 운영하는 상황이라면 ReplicaSet만으로 운영하기 보다는 대부분 Deployment단위로 Pod와 ReplicaSet을 관리하여 운영을 한다.
# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
Service는 쿠버네티스에서 서비스는 라벨링을 통해 같은 라벨을 가진 Pod를 묶어 단일 엔드포인트를 제공해주는 기능이다.
클러스터 내부에서 실행되는 Pod들은 언제든지 삭제됬다 생성될 수 있는 반 영속적인 특성을 지니고 있는데, Pod가 생성될 때마다 새로운 내부 IP를 할당하게 되므로, 클러스터 내/외부와 통신을 계속 유지하기 어렵다. 따라서 쿠버네티스는 서비스에 고정적인 IP를 할당해 Pod가 외부와의 통신을 계속 유지할 수 있도록해준다.
왼쪽의 Settings 에서 Repositories 를 선택 후 왼쪽 상단의 +CONNECT REPO 를 클릭하여 설정을 진행한다.
connection method : HTTPS
Type : git
Project : default
Repository URL : Github repo URL
Username : Github Name
Password : Token
설정이 끝나면 위와 같이 Successful 이 확인이 되어야 한다.
Applications에서 +NEW APP 을 클릭하여 파드 배포를 위한 설정을 진행한다.
Application Name : nginx
Project Name : default (선택)
SYNC POLICY : Automatic (변경 사항이 있다면 자동으로 Sync 를 맞춘다.)
Repository URL : Github Repo URL (Github와 연결이 끝나면 선택할 수 있도록 보일 것임)
Revision : main
Path : templates
Cluster URL : https://kubernetes.default.svc
Namespace : default (실습을 위해 기본 네임스페이스를 선택)
설정이 끝나면 위 화면처럼 보일 것이다. Nginx 이미지로 올라간 Pod 가 2개가 있지만, 접속할 수 있는 도메인이나 ALB 는 없어 의문이 들 것이다. 분명 ArgoCD 에서 AWS LoadBalancer 를 통한 설정을 할 수도 있지만, AWS 리소스도 함께 삭제가 되는 위험이 있어 AWS 자원은 Bastion 에서 nginx-ingress.yaml 파일을 만들어 관리를 생각하였다.
EKS Cluster 를 프라이빗으로 구성하였기에 VPC 내부에서만 호출을 할 수 있다. 그렇기에 Bastion 에서 yaml을 통해 ALB 를 생성하고자 한다.
# 경로 확인
$ pwd
/home/ec2-user/nginx
$ ls -al
합계 12
drwxrwxr-x 2 ec2-user ec2-user 69 3월 15 05:34 .
drwx------ 9 ec2-user ec2-user 294 3월 15 05:34 ..
-rw-rw-r-- 1 ec2-user ec2-user 316 3월 15 02:31 deployment.yaml
-rw-rw-r-- 1 ec2-user ec2-user 531 3월 15 02:45 ingress.yaml
-rw-rw-r-- 1 ec2-user ec2-user 133 3월 15 02:44 service.yaml
$ cat ingress.yaml
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/load-balancer-name: nginx-load-balancer
alb.ingress.kubernetes.io/target-type: 'instance'
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
Ingress는 클러스터의 서비스(일반적으로 HTTP)에 대한 외부 액세스를 관리하는 API 개체이다.
Ingress는 로드 밸런싱, SSL 종료 및 이름 기반 가상 호스팅을 제공할 수 있다.
# AWS Load Balancer Contoller 를 통한 리소스 생성
$ kubectl apply -f ingress.yaml
**Warning:** annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/nginx-ingress created
위와 같이 apply 가 정상적으로 되었다면 AWS 로드밸런서에서 프로비저닝 상태를 확인할 수 있을것이다.
또한 타겟 그룹에도 인스턴스 설정과 NodePort Type 으로 하였기에 30000번 대의 동적 포트도 할당이 되어 있는 것 또한 확인할 수 있었다.
ALB 의 프로비저닝이 완료가 되어 해당 ALB DNS 를 통해 접속을 해본다면 정상적으로 Nginx 쪽으로 접근할 수 있는 것을 확인 하였다.