티스토리 뷰

728x90
반응형

개요

DevOps는 최근 가속화 되고 있는 추세이다. 특히 조직의 변화가 어려운 기업에서도 DevOps에 관심을 갖고 체계를 수립해 보고자 변화의 자세를 갖고 있다. 현재 프로젝트 중인 a은행에서도 DevOps에 대한 제언을 요청하고 있으며, 조직과 프로세스 그리고 도구 관점에서 제언할 수 있는 부분들을 지속적으로 검토하고 있다. 특히 Security 관점에서 DecSecOps에 대한 논의 역시 이루어지고 있다. 전체 프로세스에 대한 부분은 이후 다시한번 다뤄보도록 하고, 이번 포스팅에서는 Ops 관점에서 지속적인 배포 프로세스의 속도 개선을 위한 체계 개선 방안 중 하나인 GitOps에 대해 알아보도록 하자.

DevOps를 위해 많은 도구들이 도입되고 활용되고 있지만, 그 중 대표적인이면서, 클라우드 환경에서 빠지지 않는 도구를 이야기 하자면, 단연 Git일 것이다. GitOps는 Git을 기반으로 Ops를 실현하는 방식을 의미하며, Human Error를 줄이고 배포 파이프라인의 안정성을 개선하여 복잡한 클라우드 환경 특히 마이크로서비스 환경에서 더 자주 배포하면서도 오류를 줄이고 배포에 대한 결과를 수집하여 개선할 수 있는 방안들을 마련할 수 있는 일종의 배포 설계 패턴이다.

GitOps는 Git 자체만으로 구현되는 것이 아닌 Git를 활용하여 Ops를 구현하는 도구가 필요하다. 대표적인 도구로는 ArgoCD, Terraform, FluxCD 등이 있다.


GitOps 장점

앞서 이야기한데로 GitOps는 Git을 사용하여 인프라를 구성하는 자동화된 Ops 패턴이다. GitOps를 적용하면 몇가지 유용한 장점을 얻을 수 있다.

먼저 GitOps는 자동화된 파이프라인 구성으로 Git 변경사항이 운영환경에 동시에 반영되어 별도 프로세스 없어 배포 속도를 높일 수 있다.

두번째로 변경사항을 비교하여 클러스터가 Git과 일치하지 않으면 일치하지 않는 코드를 식별하여 알려준다.

세번째로 Kubernetes GitOps 에서는 Git이 Kubernetes 외부에서 수행된 모든 클러스터 변경 사항에 대한 로그를 제공하므로 문제를 추적하기 쉽다. 이 로그를 사용하여 변경 사항을 관리하고 어떤 개발자가 어떤 변경 사항을 푸시했는지, 언제, 어떤 클러스터가 변경되었는지 확인할 수 있다. 이 측면은 시스템의 안정성을 보장한다.

네번째로 버그를 재현하거나 안정적인 롤백을 생성할 때 유용하다. GitOps를 통해 DevOps 엔지니어는 치명적인 오류가 발생한 후에도 시스템 전체를 이전 버전으로 신속하게 복구할 수 있는 신뢰할 수 있는 버전을 관리할 수 있다. 또한 단 몇 분 만에 복구가 가능하므로 데이터 손실을 최소화 할 수 있다.

마지막으로 GitOps를 사용하면 자동화된 피드백을 통해 배포하는 평균 시간을 크게 단축하므로 생산성도 크게 향상된다.


ArgoCD 개요

ArgoCD는 전체 인프라를 빠르고 일관성 있게 롤백할 수 있는 지속적인 배포기능을 제공하여 GitOps 모범 사례를 활용할 수 있도록 지원한다. 특히 Kubernetes와 함께 전 과정을 자동화하고 'source of truth'인 Git Repository의 내용과 항상 일치하는지 지속적으로 점검하여 배포 속도를 높인다. ArgoCD를 통해 DevOps 전문가는 다음 작업을 수행할 수 있다.

  • 버전 추적 수행 
  • 드리프트 감지에 대한 알림 수신
  • 전체 인프라를 빠르게 로드 
  • Git 리포지토리 내에 기록된 모든 지점으로 롤백

또한 ArgoCD는 직관적인 UI, 내장된 웹 인터페이스 및 애플리케이션에 대한 통계를 실시간으로 제공하는 API 서버로 인해 시스템 모니터링을 더 쉽게 만든다. 또한 CI를 지원하는 CLI도 함께 제공된다.

지금부터는 ArgoCD를 구축해 보고, 대시보드를 살펴보도록 하자.


ArgoCD 설치

1) namespace 생성

[root@ip-192-168-78-195 ~]# kubectl create namespace argocd
namespace/argocd created
[root@ip-192-168-78-195 ~]# kubectl get namespace argocd
NAME     STATUS   AGE
argocd   Active   8s
[root@ip-192-168-78-195 ~]#

2) ArgoCD Manifest download 및 install

[root@ip-192-168-78-195 ~]# kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io created
serviceaccount/argocd-application-controller created
serviceaccount/argocd-dex-server created
serviceaccount/argocd-redis created
serviceaccount/argocd-server created
role.rbac.authorization.k8s.io/argocd-application-controller created
role.rbac.authorization.k8s.io/argocd-dex-server created
role.rbac.authorization.k8s.io/argocd-server created
clusterrole.rbac.authorization.k8s.io/argocd-application-controller created
clusterrole.rbac.authorization.k8s.io/argocd-server created
rolebinding.rbac.authorization.k8s.io/argocd-application-controller created
rolebinding.rbac.authorization.k8s.io/argocd-dex-server created
rolebinding.rbac.authorization.k8s.io/argocd-redis created
rolebinding.rbac.authorization.k8s.io/argocd-server created
clusterrolebinding.rbac.authorization.k8s.io/argocd-application-controller created
clusterrolebinding.rbac.authorization.k8s.io/argocd-server created
configmap/argocd-cm created
configmap/argocd-cmd-params-cm created
configmap/argocd-gpg-keys-cm created
configmap/argocd-rbac-cm created
configmap/argocd-ssh-known-hosts-cm created
configmap/argocd-tls-certs-cm created
secret/argocd-secret created
service/argocd-dex-server created
service/argocd-metrics created
service/argocd-redis created
service/argocd-repo-server created
service/argocd-server created
service/argocd-server-metrics created
deployment.apps/argocd-dex-server created
deployment.apps/argocd-redis created
deployment.apps/argocd-repo-server created
deployment.apps/argocd-server created
statefulset.apps/argocd-application-controller created
networkpolicy.networking.k8s.io/argocd-application-controller-network-policy created
networkpolicy.networking.k8s.io/argocd-dex-server-network-policy created
networkpolicy.networking.k8s.io/argocd-redis-network-policy created
networkpolicy.networking.k8s.io/argocd-repo-server-network-policy created
networkpolicy.networking.k8s.io/argocd-server-network-policy created
[root@ip-192-168-78-195 ~]# kubectl get all -n argocd
NAME                                      READY   STATUS    RESTARTS   AGE
pod/argocd-application-controller-0       1/1     Running   0          42s
pod/argocd-dex-server-66f865ffb4-2jrrd    1/1     Running   0          43s
pod/argocd-redis-5b6967fdfc-xw8pn         1/1     Running   0          43s
pod/argocd-repo-server-656c76778f-8999w   1/1     Running   0          43s
pod/argocd-server-cd68f46f8-rzs2t         1/1     Running   0          43s

NAME                            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/argocd-dex-server       ClusterIP   10.100.24.138    <none>        5556/TCP,5557/TCP,5558/TCP   43s
service/argocd-metrics          ClusterIP   10.100.133.53    <none>        8082/TCP                     43s
service/argocd-redis            ClusterIP   10.100.27.165    <none>        6379/TCP                     43s
service/argocd-repo-server      ClusterIP   10.100.42.130    <none>        8081/TCP,8084/TCP            43s
service/argocd-server           ClusterIP   10.100.183.103   <none>        80/TCP,443/TCP               43s
service/argocd-server-metrics   ClusterIP   10.100.53.55     <none>        8083/TCP                     43s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argocd-dex-server    1/1     1            1           43s
deployment.apps/argocd-redis         1/1     1            1           43s
deployment.apps/argocd-repo-server   1/1     1            1           43s
deployment.apps/argocd-server        1/1     1            1           43s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/argocd-dex-server-66f865ffb4    1         1         1       43s
replicaset.apps/argocd-redis-5b6967fdfc         1         1         1       43s
replicaset.apps/argocd-repo-server-656c76778f   1         1         1       43s
replicaset.apps/argocd-server-cd68f46f8         1         1         1       43s

NAME                                             READY   AGE
statefulset.apps/argocd-application-controller   1/1     43s
[root@ip-192-168-78-195 ~]#

3) ArgoCD CLI Download

[root@ip-192-168-78-195 ~]# curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
[root@ip-192-168-78-195 ~]# chmod +x /usr/local/bin/argocd
[root@ip-192-168-78-195 ~]#

4) NodePort 설정

[root@ip-192-168-78-195 ~]# kubectl edit service argocd-server -n argocd
...
...
spec:
  clusterIP: 10.100.183.103
  clusterIPs:
  - 10.100.183.103
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 31000
    name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  - nodePort: 31443
    name: https
    port: 443
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server
  sessionAffinity: None
  type: NodePort
...
...
[root@ip-192-168-78-195 ~]#

# AWS Worker Node가 사용하는 보안그룹에 Local IP와 Workstation EC2 Node에서 사용하는 보안그룹에서 31000 노드 포트가 접근할 수 있도록 인바운드 규칙 추가

5) 대시보드 접속

  • Host : http://external_ip:31000
  • Username : admin
  • Password : kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo

6) Password 변경 (login > account update-password)

[root@ip-192-168-78-195 ~]# argocd login 192.168.89.241:31000
WARNING: server certificate had error: x509: cannot validate certificate for 192.168.89.241 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password: 
'admin:login' logged in successfully
Context '192.168.89.241:31000' updated
[root@ip-192-168-78-195 ~]# argocd account update-password
*** Enter password of currently logged in user (admin): 
*** Enter new password for user admin: 
*** Confirm new password for user admin: 
Password updated
Context '192.168.89.241:31000' updated
[root@ip-192-168-78-195 ~]#

7) 대시보드 로그인

8) GitLab 구성

root path에 deployment.yaml 파일과 service.yaml 파일을 생성한다. 물론 이후 관리는 IDE를 통해 하는 것을 권장하며, 운영자 관점에서 권한 분리를 통해 반영 가능한 MAINTAINER의 역할에 따라 프로젝트가 관리될 수 있도록 한다.

[deployment.yaml]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
[service.yaml]
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: NodePort
  ports:
  - nodePort: 32000
    port: 80
    protocol: TCP
  selector:
    run: my-nginx

9) New App Add

[GENERAL]

  • Application Name : 배포할 어플리케이션 이름 (sample-argocd-test)
  • Project : ArgoCD 내 어플리케이션 그룹 (default)
  • SYNC POLICY : (Manual, Automatic) Git 변동사항을 자동으로 반영할 것인지, 수동으로 반영할 것인지 선택 (Manual)

# 자주 발생하는 Error

Unable to create application: Application.argoproj.io "ArgoCDSample" is invalid: metadata.name: Invalid value: "ArgoCDSample": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')
해결방안
> Applicaton Name은 소문자, 숫자, ., -만 허용함. 대문자나, 허용되지 않은 특수문자가 포함될 경우 위 에러 발생

[SOURCE]

  • Repository URL : Git 저장소 URL (git 또는 helm) (http://192.168.84.159:8090/root/myargocdproject.git)
  • Revision : Git의 어떤 Revision을 바라 볼 것인지 지정 (HEAD, main, tag 등) (main)
  • Path : Repository 내 변경사항을 관리할 파일이 위치한 경로 지정 (. 일 경우 root) (.)

# 자주 발생하는 Error

Unable to create application: application spec for sample-argocd-test is invalid: InvalidSpecError: repository not accessible: rpc error: code = Unknown desc = error testing repository connectivity: Get "http://192.168.84.159:8090/root/myargocdproject.git/info/refs?service=git-upload-pack": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
해결방안
> gitlab 서버와의 통신 문제로 gitlab이 설치된 E2C 인스턴스가 사용하는 보안그룹의 인바운드 규칙에 GitLab이 사용중인 Port(8090)를 Worker Node가 사용하는 보안그룹 허용

[DESTINATION & DIRECTORY]

  • Cluster URL : 배포 대상 Kubernetes Cluster 지정 (https://kubernetes.default.svc)
  • Namespace : 배포 할 Kubernetes Cluster 내 Namespace 지정 (default)
  • DIRECTORY RECURSE : Path 하위 경로 디렉토리의 변동사항 체크 확인 여부

위와 같이 입력 후 CREATE 버튼을 클릭한다.

10) SYNC APPS

초기 NEW APP으로 추가된 APPS는 SYNC를 수행하기 전 상태로 OutOfSync 상태의 App으로 기동된다. 하단의 SYNC 버튼을 클릭한다.

  • SYNCHRONIZE RESOURCES : Git Repository로 부터 동기화 된 Resource로 반영할 대상 선택

# 자주 발생하는 Error

문제발생 : Sync Failed 발생

장애진단 : argocd cli 활용

[root@ip-192-168-78-195 ~]# argocd app get sample-argocd-test 
Name:               sample-argocd-test
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://192.168.89.241:31000/applications/sample-argocd-test
Repo:               http://192.168.84.159:8090/root/myargocdproject.git
Target:             main
Path:               .
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from main (c7ac08f)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME      STATUS     HEALTH   HOOK  MESSAGE
       Service     default    my-nginx  OutOfSync  Missing        error validating data: ValidationError(Service.spec.ports[0]): unknown field "nodePotr" in io.k8s.api.core.v1.ServicePort
apps   Deployment  default    my-nginx  OutOfSync  Missing        
[root@ip-192-168-78-195 ~]#

argocd app get [Application Name]으로 현재 app의 상태를 확인 (MESSAGE 부분). 대부분의 경우 "error validating data: ValidationError(Service.spec.ports[0]): unknown field "nodePotr" in io.k8s.api.core.v1.ServicePort"와 같이 yaml 파일 수정 시 오타로 인한 field 식별 오류 또는 yaml Syntax 오류 등으로 인해 OutOfSync 상태가 유지되며, Sync Failed가 발생한다.

현재는 nodePort가 nodePotr로 오기입된 상태이므로 kubernetes에 반영하기전 validation에서 오류가 발생한 상태이다. 이 경우 Git Repository의 yaml 파일을 반영한 후 재 시도를 한다.

11) Application 배포 확인

Sync가 완료된 Application을 클릭하면 위와 같이 상세 상태를 확인할 수 있다.

  • sample-argocd-test : New App으로 배포한 argocd application
  • svc (my-nginx) : kubernetes service
  • ep (my-nginx) : kubernetes enpoint
  • endpointslice (my-ngnix-xxxxx) : kubernetes endpoint tracer
  • deploy (my-nginx) : kubernetest deployment
  • rs (my-nginx-xxxxxxxxxx) : kubernetes replicaset
  • pod (my-nginx-rsname-xxxxx) : kubernetes pod (현재 2개 pod 기동 중)

왼쪽 상단의 APP DETAILS를 클릭하여 sample-argocd-test application의 전체 정보를 확인할 수 있다.

특히 SUMMARY TAB의 EDIT를 통해 Configuration을 수정하거나, STATUS Field를 통해 현재 반영되어 있는 Commit SHA 정보를 확인할 수 있다. ENABLE AUTO-SYNC 설정으로 변경하여 자동 반영 설정을 적용할 수 있다.

12) GitLab 수정 후 반영

GitLab에 반영되어 있는 deployment.yaml 파일의 replicas를 2에서 1로 수정 후 SYNC 버튼을 클릭하면 위와 같이 Pod하나가 중지되는 것을 확인할 수 있다.

위와 같이 반영된 것을 확인할 수 있다.

[root@ip-192-168-78-195 ~]# kubectl get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/my-nginx-5b56ccd65f-n2bdb   1/1     Running   0          32m

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.100.0.1       <none>        443/TCP        3h15m
service/my-nginx     NodePort    10.100.128.191   <none>        80:32000/TCP   32m

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   1/1     1            1           32m

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/my-nginx-5b56ccd65f   1         1         1       32m
[root@ip-192-168-78-195 ~]#

kubernetes 상에서도 위와 같이 반영된 것을 확인할 수 있다.

13) 롤백 처리

배포를 처리하다 보면 때로 아래와 같은 장애 상황이 발생될 수 있다.

이 경우 몇번의 클릭만으로 이전 revision으로 되 돌릴 수 있다.

상단의 HISTORY AND ROLLBACK 클릭 후 > 원하는 Revision 확인 후 > 오른쪽 Rollback 클릭

위와 같이 몇번의 클릭만으로 pod가 2개로 복원된 것을 확인할 수 있다.

14) 추가 기능

그 밖에 유용한 기능 몇가지 더 소개하고 포스팅을 마치도록 하자.

> DIFF 기능

변경된 Application Revision에 대해 Diff 기능을 통해 확인할 수 있다.

> LOGS

Pod 로그를 대시보드에서 확인할 수 있다.

> FILTER

FILTER를 통해 그룹핑하여 대량의 서비스가 배포되는 환경에서 빠르게 원하는 조건의 어플리케이션을 찾아 갈 수 있도록 도와준다.

> Settings (Repository, Cluster, Project)

위와 같이 사전에 Repository, Cluster, Project를 등록하여 관리할 수 있다. 이는 상태를 점검하는 측면에서 활용되거나, 여러 구성에서 해당 항목을 손쉽게 등록할 수 있도록 도와주는 역할을 하는 기능이다.


결론

GitOps는 자동배포와 인프라 관리를 위해 다양한 정보를 모니터링하고 추적할 수 있는 도구와 연계되어야 한다.
이와 같은 측면에서 볼때 ArgoCD는 Git 및 Kubernetes에 최적화된 도구로 손쉬운 구성과 대시보드 제공, 높은 추적성과 안정성을 보장하는 GitOps 프로세스와 체계를 설계하는 단계의 프로젝트에 적용하기 적합한 도구라 할 수 있을 것이다.

728x90
반응형