Post

CI/CD 4์ฃผ์ฐจ ์ •๋ฆฌ

๐ŸŒŠ ๊นƒ์˜ต์Šค์™€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค

1. kind ํด๋Ÿฌ์Šคํ„ฐ ์ƒ์„ฑ ๋ฐ ๊ธฐ๋ณธ ํ™˜๊ฒฝ ๊ตฌ์„ฑ

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
26
27
28
29
30
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
EOF

# ๊ฒฐ๊ณผ
Creating cluster "myk8s" ...
 โœ“ Ensuring node image (kindest/node:v1.32.8) ๐Ÿ–ผ
 โœ“ Preparing nodes ๐Ÿ“ฆ  
 โœ“ Writing configuration ๐Ÿ“œ 
 โœ“ Starting control-plane ๐Ÿ•น๏ธ 
 โœ“ Installing CNI ๐Ÿ”Œ 
 โœ“ Installing StorageClass ๐Ÿ’พ 
Set kubectl context to "kind-myk8s"
You can now use your cluster with:

kubectl cluster-info --context kind-myk8s

Thanks for using kind!

2. kube-ops-view ์„ค์น˜

1
2
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30001 --set env.TZ="Asia/Seoul" --namespace kube-system

3. GitOps ์‹ค์Šต์šฉ ์†Œ์Šค์ฝ”๋“œ ๋‹ค์šด๋กœ๋“œ

1
2
git clone https://github.com/PacktPublishing/ArgoCD-in-Practice.git
cd ArgoCD-in-Practice/ch01/basic-gitops-operator/

4. GitOps ์˜คํผ๋ ˆ์ดํ„ฐ ์‹คํ–‰ ๋ฐ ์ƒํƒœ ํ™•์ธ

(1) GitOps ์˜คํผ๋ ˆ์ดํ„ฐ ๊ตฌ๋™

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
26
27
28
go run main.go

# ๊ฒฐ๊ณผ
 next sync in 5s 
start repo sync
start manifests apply
deployment.apps/nginx unchanged
namespace/nginx unchanged

 next sync in 5s 
start repo sync
start manifests apply
deployment.apps/nginx unchanged
namespace/nginx unchanged

 next sync in 5s 
start repo sync
start manifests apply
deployment.apps/nginx unchanged
namespace/nginx unchanged

 next sync in 5s 
start repo sync
start manifests apply
deployment.apps/nginx unchanged
namespace/nginx unchanged

...

(2) ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ ํ™•์ธ

1
2
3
4
5
6
7
kubectl get deploy,pod -n nginx

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           2m26s

NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-5869d7778c-xfthr   1/1     Running   0          2m26s

5. ๋ฆฌ์†Œ์Šค ๊ฐ•์ œ ์‚ญ์ œ ํ›„ ์ž๋™ ๋ณต๊ตฌ ํ™•์ธ

(1) Deployment ์ˆ˜๋™ ์‚ญ์ œ

1
2
kubectl delete deploy -n nginx nginx
deployment.apps "nginx" deleted from nginx namespace

(2) Deployment ์ž๋™์œผ๋กœ ์žฌ์ƒ์„ฑ

1
2
3
4
5
6
7
kubectl get deploy,pod -n nginx

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           12s

NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-5869d7778c-jhkpc   1/1     Running   0          12s
  • GitOps์˜ ์ž๊ธฐ๋ณต๊ตฌ(Self-healing) ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ฒ€์ฆ

6. ์‹ค์Šต ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ

1
2
kubectl delete ns nginx
namespace "nginx" deleted

โš“ Argo CD ์„ค์น˜ by Helm

1. Argo CD์šฉ Namespace ๋ฐ Helm values ํŒŒ์ผ ์ƒ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
cd ../..

kubectl create ns argocd

cat <<EOF > argocd-values.yaml
server:
  service:
    type: NodePort
    nodePortHttps: 30002
  extraArgs:
    - --insecure  # HTTPS ๋Œ€์‹  HTTP ์‚ฌ์šฉ
EOF

2. Helm์„ ์ด์šฉํ•œ Argo CD ์„ค์น˜

1
2
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd

3. Argo CD ๊ตฌ์„ฑ์š”์†Œ ๋ฐ ์„œ๋น„์Šค ์ƒํƒœ ํ™•์ธ

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
kubectl get pod,svc,ep,secret,cm -n argocd

NAME                                                   READY   STATUS    RESTARTS   AGE
pod/argocd-application-controller-0                    1/1     Running   0          70s
pod/argocd-applicationset-controller-bbff79c6f-9psnw   1/1     Running   0          70s
pod/argocd-dex-server-6877ddf4f8-nr747                 1/1     Running   0          70s
pod/argocd-notifications-controller-7b5658fc47-vtj57   1/1     Running   0          70s
pod/argocd-redis-7d948674-tmg72                        1/1     Running   0          70s
pod/argocd-repo-server-7679dc55f5-z9x7q                1/1     Running   0          70s
pod/argocd-server-787fb5f956-hxbfc                     1/1     Running   0          70s

NAME                                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/argocd-applicationset-controller   ClusterIP   10.96.232.145   <none>        7000/TCP                     70s
service/argocd-dex-server                  ClusterIP   10.96.16.247    <none>        5556/TCP,5557/TCP            70s
service/argocd-redis                       ClusterIP   10.96.183.36    <none>        6379/TCP                     70s
service/argocd-repo-server                 ClusterIP   10.96.145.59    <none>        8081/TCP                     70s
service/argocd-server                      NodePort    10.96.86.67     <none>        80:30080/TCP,443:30002/TCP   70s

NAME                                         ENDPOINTS                           AGE
endpoints/argocd-applicationset-controller   10.244.0.13:7000                    70s
endpoints/argocd-dex-server                  10.244.0.12:5557,10.244.0.12:5556   70s
endpoints/argocd-redis                       10.244.0.10:6379                    70s
endpoints/argocd-repo-server                 10.244.0.14:8081                    70s
endpoints/argocd-server                      10.244.0.16:8080,10.244.0.16:8080   70s

NAME                                  TYPE                 DATA   AGE
secret/argocd-initial-admin-secret    Opaque               1      68s
secret/argocd-notifications-secret    Opaque               0      70s
secret/argocd-redis                   Opaque               1      74s
secret/argocd-secret                  Opaque               3      70s
secret/sh.helm.release.v1.argocd.v1   helm.sh/release.v1   1      96s

NAME                                      DATA   AGE
configmap/argocd-cm                       18     70s
configmap/argocd-cmd-params-cm            20     70s
configmap/argocd-gpg-keys-cm              0      70s
configmap/argocd-notifications-cm         1      70s
configmap/argocd-rbac-cm                  4      70s
configmap/argocd-redis-health-configmap   2      70s
configmap/argocd-ssh-known-hosts-cm       1      70s
configmap/argocd-tls-certs-cm             0      70s
configmap/kube-root-ca.crt                1      2m57s

4. ๊ธฐ๋ณธ AppProject ์„ค์ • ํ™•์ธ

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
26
kubectl get appproject -n argocd -o yaml

apiVersion: v1
items:
- apiVersion: argoproj.io/v1alpha1
  kind: AppProject
  metadata:
    creationTimestamp: "2025-11-08T07:37:33Z"
    generation: 1
    name: default
    namespace: argocd
    resourceVersion: "2364"
    uid: 6410f993-adb8-427a-be8a-c0cf4929212f
  spec:
    clusterResourceWhitelist:
    - group: '*'
      kind: '*'
    destinations:
    - namespace: '*'
      server: '*'
    sourceRepos:
    - '*'
  status: {}
kind: List
metadata:
  resourceVersion: ""
  • ๋ชจ๋“  Cluster ๋ฆฌ์†Œ์Šค(*/*), ๋ชจ๋“  ๋„ค์ž„์ŠคํŽ˜์ด์Šค, ๋ชจ๋“  Git ์ €์žฅ์†Œ(*)๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ์ •์ฑ…์ด ์„ค์ •๋œ ์ƒํƒœ์ž„์„ ํ™•์ธํ•จ

5. ServiceAccount ๊ตฌ์„ฑ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
ubectl get sa -n argocd

NAME                               SECRETS   AGE
argocd-application-controller      0         2m45s
argocd-applicationset-controller   0         2m45s
argocd-dex-server                  0         2m45s
argocd-notifications-controller    0         2m45s
argocd-redis-secret-init           0         3m11s
argocd-repo-server                 0         2m45s
argocd-server                      0         2m45s
default                            0         4m32s

6. ์ดˆ๊ธฐ ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ ๋ฐ ์›น ์ฝ˜์†” ์ ‘์†

1
2
3
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo

417jqWCgQRqPJtnT
1
2
http://127.0.0.1:30002
admin / 417jqWCgQRqPJtnT

7. ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ

1
qwe12345


๐Ÿš€ ์ฒซ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ํ•˜๊ธฐ

1. Guestbook Helm ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

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
26
27
28
29
30
31
32
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    helm:
      valueFiles:
      - values.yaml
    path: helm-guestbook
    repoURL: https://github.com/argoproj/argocd-example-apps
    targetRevision: HEAD
  syncPolicy:
    automated:
      enabled: true
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: guestbook
    server: https://kubernetes.default.svc
EOF

# ๊ฒฐ๊ณผ
Warning: metadata.finalizers: "resources-finalizer.argocd.argoproj.io": prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers
application.argoproj.io/guestbook created

2. Argo CD์—์„œ ๋™๊ธฐํ™” ๋ฐ ์ƒํƒœ ํ™•์ธ

1
2
3
4
kubectl get applications -n argocd guestbook

NAME        SYNC STATUS   HEALTH STATUS
guestbook   Synced        Healthy

3. Guestbook ๋ฐฐํฌ ๋ฆฌ์†Œ์Šค ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
kubectl get pod,svc,ep -n guestbook

NAME                                            READY   STATUS    RESTARTS   AGE
pod/guestbook-helm-guestbook-6585c766d6-6svkc   1/1     Running   0          85s

NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/guestbook-helm-guestbook   ClusterIP   10.96.200.126   <none>        80/TCP    85s

NAME                                 ENDPOINTS        AGE
endpoints/guestbook-helm-guestbook   10.244.0.17:80   85s
  • ์„œ๋น„์Šค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ClusterIP ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑ๋˜์–ด ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ž„

4. NodePort ๋ณ€๊ฒฝ ์‹œ๋„ ๋ฐ Self-Heal ๋™์ž‘ ๊ด€์ฐฐ

1
2
3
kubectl patch svc -n guestbook guestbook-helm-guestbook -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":30003}]}}'

service/guestbook-helm-guestbook patched
  • kubectl patch๋ฅผ ์‚ฌ์šฉํ•ด Service ํƒ€์ž…์„ NodePort๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  30003 ํฌํŠธ๋กœ ๋…ธ์ถœํ•˜๋ ค๊ณ  ์‹œ๋„ํ•จ

1
2
3
4
kubectl get svc -n guestbook

NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
guestbook-helm-guestbook   ClusterIP   10.96.200.126   <none>        80/TCP    2m47s
  • ํ•˜์ง€๋งŒ Argo CD selfHeal ๊ธฐ๋Šฅ์œผ๋กœ ์ธํ•ด ์›๋ณธ Helm ์ •์˜(ClusterIP) ์ƒํƒœ๋กœ ๊ณ„์† ๋˜๋Œ์•„๊ฐ€๋Š” ํ˜„์ƒ์„ ํ™•์ธํ•จ

5. Self-Heal ๋น„ํ™œ์„ฑํ™” ํ›„ NodePort ์žฌ์„ค์ •

  • Argo CD์—์„œ ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ selfHeal ์˜ต์…˜์„ ๋น„ํ™œ์„ฑํ™”ํ•œ ๋’ค, ๋‹ค์‹œ kubectl patch๋กœ Service๋ฅผ NodePort: 30003์œผ๋กœ ์ˆ˜์ •ํ•จ
1
2
3
4
5
6
kubectl patch svc -n guestbook guestbook-helm-guestbook -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":80,"nodePort":30003}]}}'
service/guestbook-helm-guestbook patched

kubectl get svc -n guestbook
NAME                       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
guestbook-helm-guestbook   NodePort   10.96.200.126   <none>        80:30003/TCP   7m14s

6. NodePort๋ฅผ ํ†ตํ•œ Guestbook ์ ‘์† ๊ฒ€์ฆ

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
26
27
curl http://127.0.0.1:30003

<html ng-app="redis">
  <head>
    <title>Guestbook</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
    <script src="controllers.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.6/ui-bootstrap-tpls.js"></script>
  </head>
  <body ng-controller="RedisCtrl">
    <div style="width: 50%; margin-left: 20px">
      <h2>Guestbook</h2>
    <form>
    <fieldset>
    <input ng-model="msg" placeholder="Messages" class="form-control" type="text" name="input"><br>
    <button type="button" class="btn btn-primary" ng-click="controller.onRedis()">Submit</button>
    </fieldset>
    </form>
    <div>
      <div ng-repeat="msg in messages track by $index">
        
      </div>
    </div>
    </div>
  </body>
</html>

7. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ •๋ฆฌ

1
2
3
kubectl delete applications -n argocd guestbook

application.argoproj.io "guestbook" deleted from argocd namespace

๐Ÿงฐ Argo CLI

1. Argo CD CLI ์„ค์น˜ ๋ฐ ๋ฒ„์ „ ํ™•์ธ

1
sudo pacman -S argocd # Arch Linux
1
2
3
4
5
6
7
8
9
10
argocd version --client

argocd: v3.2.0+unknown
  BuildDate: 2025-11-05T05:15:54Z
  GitCommit: 
  GitTreeState: 
  GitTag: 3.2.0
  GoVersion: go1.25.3 X:nodwarf5
  Compiler: gc
  Platform: linux/amd64

2. Argo CD ์„œ๋ฒ„(NodePort) ์„ค์ • ํ™•์ธ

1
2
3
4
5
6
7
8
kubectl get svc -n argocd

NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
argocd-applicationset-controller   ClusterIP   10.96.232.145   <none>        7000/TCP                     25m
argocd-dex-server                  ClusterIP   10.96.16.247    <none>        5556/TCP,5557/TCP            25m
argocd-redis                       ClusterIP   10.96.183.36    <none>        6379/TCP                     25m
argocd-repo-server                 ClusterIP   10.96.145.59    <none>        8081/TCP                     25m
argocd-server                      NodePort    10.96.86.67     <none>        80:30080/TCP,443:30002/TCP   25m
  • argocd-server ์„œ๋น„์Šค๊ฐ€ 443:30002/TCP NodePort๋กœ ๋…ธ์ถœ๋œ ์ƒํƒœ์ž„์„ ํ™•์ธ

3. Argo CD CLI ๋กœ๊ทธ์ธ ๋ฐ ์ปจํ…์ŠคํŠธ ์„ค์ •

1
2
3
4
5
6
argocd login 127.0.0.1:30002 --plaintext
Username: admin
Password: qwe12345

'admin:login' logged in successfully
Context '127.0.0.1:30002' updated
  • ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ 127.0.0.1:30002 ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑยท์ ์šฉ๋˜์–ด ์ดํ›„ CLI ๋ช…๋ น์ด ํ•ด๋‹น Argo CD ์„œ๋ฒ„์™€ ์—ฐ๋™๋˜๋„๋ก ์„ค์ •ํ•จ

4. ๊ธฐ๋ณธ ๊ณ„์ •/ํ”„๋กœ์ ํŠธ/ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ ์ ๊ฒ€

1
2
3
4
argocd account list

NAME   ENABLED  CAPABILITIES
admin  true     login
1
2
3
4
argocd proj list

NAME     DESCRIPTION  DESTINATIONS  SOURCES  CLUSTER-RESOURCE-WHITELIST  NAMESPACE-RESOURCE-BLACKLIST  SIGNATURE-KEYS  ORPHANED-RESOURCES  DESTINATION-SERVICE-ACCOUNTS
default               *,*           *        */*                         <none>                        <none>          disabled            <none>
1
2
3
argocd repo list

TYPE  NAME  REPO  INSECURE  OCI  LFS  CREDS  STATUS  MESSAGE  PROJECT
1
2
3
4
argocd cluster list

SERVER                          NAME        VERSION  STATUS      MESSAGE  PROJECT
https://kubernetes.default.svc  in-cluster  1.32     Successful           
1
2
3
argocd app list

NAME  CLUSTER  NAMESPACE  PROJECT  STATUS  HEALTH  SYNCPOLICY  CONDITIONS  REPO  PATH  TARGET

5. Argo CLI๋กœ Guestbook ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

1
2
3
4
argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path helm-guestbook \
  --dest-server https://kubernetes.default.svc --dest-namespace guestbook --values values.yaml

application 'guestbook' created
  • ์ƒ์„ฑ ์งํ›„ ์•ฑ์€ Manual Sync ์ •์ฑ…์œผ๋กœ ์„ค์ •๋˜์–ด OutOfSync / Missing ์ƒํƒœ์ธ ๊ฒƒ ํ™•์ธํ•จ
1
2
3
4
argocd app list

NAME              CLUSTER                         NAMESPACE  PROJECT  STATUS     HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                 PATH            TARGET
argocd/guestbook  https://kubernetes.default.svc  guestbook  default  OutOfSync  Missing  Manual      <none>      https://github.com/argoproj/argocd-example-apps.git  helm-guestbook  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
argocd app get argocd/guestbook

Name:               argocd/guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          guestbook
URL:                https://argocd.example.com/applications/guestbook
Source:
- Repo:             https://github.com/argoproj/argocd-example-apps.git
  Target:           
  Path:             helm-guestbook
  Helm Values:      values.yaml
SyncWindow:         Sync Allowed
Sync Policy:        Manual
Sync Status:        OutOfSync from  (0d521c6)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME                      STATUS     HEALTH   HOOK  MESSAGE
       Service     guestbook  guestbook-helm-guestbook  OutOfSync  Missing        
apps   Deployment  guestbook  guestbook-helm-guestbook  OutOfSync  Missing        

6. ์ˆ˜๋™ Sync๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋™๊ธฐํ™”

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
26
27
28
29
30
31
32
33
34
35
36
argocd app sync argocd/guestbook

# ๊ฒฐ๊ณผ
TIMESTAMP                  GROUP        KIND   NAMESPACE                  NAME        STATUS    HEALTH        HOOK  MESSAGE
2025-11-08T17:12:28+09:00   apps  Deployment   guestbook  guestbook-helm-guestbook  OutOfSync  Missing              
2025-11-08T17:12:28+09:00            Service   guestbook  guestbook-helm-guestbook  OutOfSync  Missing              
2025-11-08T17:12:28+09:00            Service   guestbook  guestbook-helm-guestbook    Synced  Healthy              
2025-11-08T17:12:28+09:00            Service   guestbook  guestbook-helm-guestbook    Synced   Healthy              service/guestbook-helm-guestbook created
2025-11-08T17:12:28+09:00   apps  Deployment   guestbook  guestbook-helm-guestbook  OutOfSync  Missing              deployment.apps/guestbook-helm-guestbook created

Name:               argocd/guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          guestbook
URL:                https://argocd.example.com/applications/argocd/guestbook
Source:
- Repo:             https://github.com/argoproj/argocd-example-apps.git
  Target:           
  Path:             helm-guestbook
  Helm Values:      values.yaml
SyncWindow:         Sync Allowed
Sync Policy:        Manual
Sync Status:        Synced to  (0d521c6)
Health Status:      Progressing

Operation:          Sync
Sync Revision:      0d521c6e049889134f3122eb32d7ed342f43ca0d
Phase:              Succeeded
Start:              2025-11-08 17:12:28 +0900 KST
Finished:           2025-11-08 17:12:28 +0900 KST
Duration:           0s
Message:            successfully synced (all tasks run)

GROUP  KIND        NAMESPACE  NAME                      STATUS  HEALTH       HOOK  MESSAGE
       Service     guestbook  guestbook-helm-guestbook  Synced  Healthy            service/guestbook-helm-guestbook created
apps   Deployment  guestbook  guestbook-helm-guestbook  Synced  Progressing        deployment.apps/guestbook-helm-guestbook created

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
argocd app get argocd/guestbook

# ๊ฒฐ๊ณผ
Name:               argocd/guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          guestbook
URL:                https://argocd.example.com/applications/guestbook
Source:
- Repo:             https://github.com/argoproj/argocd-example-apps.git
  Target:           
  Path:             helm-guestbook
  Helm Values:      values.yaml
SyncWindow:         Sync Allowed
Sync Policy:        Manual
Sync Status:        Synced to  (0d521c6)
Health Status:      Healthy

GROUP  KIND        NAMESPACE  NAME                      STATUS  HEALTH   HOOK  MESSAGE
       Service     guestbook  guestbook-helm-guestbook  Synced  Healthy        service/guestbook-helm-guestbook created
apps   Deployment  guestbook  guestbook-helm-guestbook  Synced  Healthy        deployment.apps/guestbook-helm-guestbook created

7. Argo CLI๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ญ์ œ

1
2
3
4
argocd app delete argocd/guestbook
Are you sure you want to delete 'argocd/guestbook' and all its resources? [y/n] y

application 'argocd/guestbook' deleted

8. Argo CD ์ œ๊ฑฐ ๋ฐ ๋‹ค์Œ ์‹ค์Šต ์ค€๋น„

1
2
3
4
5
6
7
8
9
helm uninstall -n argocd argocd && kubectl delete ns argocd

These resources were kept due to the resource policy:
[CustomResourceDefinition] applications.argoproj.io
[CustomResourceDefinition] applicationsets.argoproj.io
[CustomResourceDefinition] appprojects.argoproj.io

release "argocd" uninstalled
namespace "argocd" deleted

๐Ÿค– Argo CD Autopilot

  • https://argocd-autopilot.readthedocs.io/en/stable/
  • Argo CD ์„ค์น˜ ์ž๋™ํ™” + GitOps ํ™˜๊ฒฝ ์ดˆ๊ธฐํ™”, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜/ํด๋Ÿฌ์Šคํ„ฐ ๋“ฑ ์„ ์–ธ์  ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

1. argocd-autopilotย CLIย ์„ค์น˜

1
2
3
4
5
6
7
8
9
VERSION=$(curl --silent "https://api.github.com/repos/argoproj-labs/argocd-autopilot/releases/latest" \
  | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
  
curl -L --output - \
  https://github.com/argoproj-labs/argocd-autopilot/releases/download/"$VERSION"/argocd-autopilot-linux-amd64.tar.gz \
  | tar zx
  
chmod +x argocd-autopilot-linux-amd64
sudo mv argocd-autopilot-linux-amd64 /usr/local/bin/argocd-autopilot
1
2
argocd-autopilot version
v0.4.20

2. GitOps์šฉ Git ์ €์žฅ์†Œ ๋ฐ ํ† ํฐ ์ค€๋น„

(1) ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ƒ์„ฑ

(2) Git Personal access tokens ์ƒ์„ฑ: scope(repo ์ฒดํฌ)

(3) ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •

1
2
export GIT_TOKEN=<์ž์‹ ์˜ Git Token>
export GIT_REPO=<์ž์‹ ์˜ Repo>

3. Autopilot์œผ๋กœ Argo CD ๋ถ€ํŠธ์ŠคํŠธ๋žฉ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
argocd-autopilot repo bootstrap

# ๊ฒฐ๊ณผ
INFO cloning repo: https://github.com/Shinminjin/autopilot.git 
INFO empty repository, initializing a new one with specified remote 
WARNING --provider not specified, assuming provider from url: github 
INFO using revision: "", installation path: ""    
INFO using context: "kind-myk8s", namespace: "argocd" 
INFO applying bootstrap manifests to cluster...   
namespace/argocd created
...
INFO pushing bootstrap manifests to repo          
Resolving deltas: 100% (1/1), done.
...
INFO argocd initialized. password: 9h24-XCC55s5NjVU 
INFO run:

    kubectl port-forward -n argocd svc/argocd-server 8080:80

4. Argo CD ์„ค์น˜ ๋ฐ ์ƒํƒœ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
kubectl get pod -n argocd

NAME                                               READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                    1/1     Running   0          5m24s
argocd-applicationset-controller-fc5545556-vg4qn   1/1     Running   0          5m24s
argocd-dex-server-f59c65cff-4jmb5                  1/1     Running   0          5m24s
argocd-notifications-controller-59f6949d7-j7nrl    1/1     Running   0          5m24s
argocd-redis-75c946f559-szrv7                      1/1     Running   0          5m24s
argocd-repo-server-6959c47c44-24h8r                1/1     Running   0          5m24s
argocd-server-65544f4864-mq7nj                     1/1     Running   0          5m24s
1
2
3
4
kubectl get appprojects.argoproj.io -n argocd

NAME      AGE
default   5m26s
1
2
3
4
5
6
7
kubectl get applications.argoproj.io -n argocd -owide

NAME                           SYNC STATUS   HEALTH STATUS   REVISION                                   PROJECT
argo-cd                        Synced        Healthy         fa1063a8a26351cca9a96597499652ba2a17fade   default
autopilot-bootstrap            Synced        Healthy         fa1063a8a26351cca9a96597499652ba2a17fade   default
cluster-resources-in-cluster   Synced        Healthy         fa1063a8a26351cca9a96597499652ba2a17fade   default
root                           Synced        Healthy         fa1063a8a26351cca9a96597499652ba2a17fade   default

5. Argo CD ๋Œ€์‹œ๋ณด๋“œ ์ ‘์† ๋ฐ ์ดˆ๊ธฐ ๊ณ„์ • ํ™•์ธ

(1) ํฌํŠธํฌ์›Œ๋”ฉ

1
2
3
4
kubectl port-forward -n argocd svc/argocd-server 8080:80

Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

(2) ์ดˆ๊ธฐ ํŒจ์Šค์›Œ๋“œ ํ™•์ธ

1
2
3
# ์ดˆ๊ธฐ ํŒจ์Šค์›Œ๋“œ
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d ; echo
9h24-XCC55s5NjVU

(3) ๋Œ€์‹œ๋ณด๋“œ ์ ‘์†

1
2
http://localhost:8080
admin / 9h24-XCC55s5NjVU

1
2
3
4
5
6
7
8
kubectl get applications.argoproj.io -n argocd autopilot-bootstrap -o yaml | kubectl neat | yq

...
    "source": {
      "path": "bootstrap",
      "repoURL": "https://github.com/Shinminjin/autopilot.git"
    },
...

6. Autopilot ๊ธฐ๋ฐ˜ Project ์ƒ์„ฑ(dev, prd)

1
2
3
4
5
6
7
8
9
10
argocd-autopilot project create dev

INFO cloning git repository: https://github.com/Shinminjin/autopilot.git 
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Compressing objects: 100% (13/13), done.
Total 17 (delta 1), reused 17 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"   
INFO pushing new project manifest to repo         
INFO project created: 'dev'
1
2
3
4
5
6
7
8
9
10
argocd-autopilot project create prd

INFO cloning git repository: https://github.com/Shinminjin/autopilot.git 
Enumerating objects: 18, done.
Counting objects: 100% (18/18), done.
Compressing objects: 100% (15/15), done.
Total 18 (delta 2), reused 17 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"   
INFO pushing new project manifest to repo         
INFO project created: 'prd'
1
2
3
4
5
6
kubectl get appprojects.argoproj.io -n argocd

NAME      AGE
default   17m
dev       66s
prd       32s

7. Autopilot ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌ

1
2
3
4
5
6
7
8
9
10
argocd-autopilot app create hello-world1 --app github.com/argoproj-labs/argocd-autopilot/examples/demo-app/ -p dev --type kustomize

INFO cloning git repository: https://github.com/Shinminjin/autopilot.git 
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Compressing objects: 100% (16/16), done.
Total 19 (delta 3), reused 17 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"   
INFO committing changes to gitops repo...         
INFO installed application: hello-world1
1
2
3
4
5
6
7
8
9
10
argocd-autopilot app create hello-world2 --app github.com/argoproj-labs/argocd-autopilot/examples/demo-app/ -p prd --type kustomize

INFO cloning git repository: https://github.com/Shinminjin/autopilot.git 
Enumerating objects: 26, done.
Counting objects: 100% (26/26), done.
Compressing objects: 100% (22/22), done.
Total 26 (delta 4), reused 23 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"   
INFO committing changes to gitops repo...         
INFO installed application: hello-world2          

1
2
3
4
5
6
7
8
9
argocd-autopilot app delete hello-world2 -p prd

INFO cloning git repository: https://github.com/Shinminjin/autopilot.git 
Enumerating objects: 30, done.
Counting objects: 100% (30/30), done.
Compressing objects: 100% (25/25), done.
Total 30 (delta 5), reused 26 (delta 1), pack-reused 0 (from 0)
INFO using revision: "", installation path: "/"   
INFO committing changes to gitops repo...
1
2
3
4
5
6
7
8
kubectl get applications.argoproj.io -n argocd -owide

NAME                           SYNC STATUS   HEALTH STATUS   REVISION                                   PROJECT
argo-cd                        Synced        Healthy         cfef97378a57430ecf89c48954f9c44a5cd1b808   default
autopilot-bootstrap            Synced        Healthy         cfef97378a57430ecf89c48954f9c44a5cd1b808   default
cluster-resources-in-cluster   Synced        Healthy         cfef97378a57430ecf89c48954f9c44a5cd1b808   default
dev-hello-world1               Synced        Healthy         cfef97378a57430ecf89c48954f9c44a5cd1b808   dev
root                           Synced        Healthy         cfef97378a57430ecf89c48954f9c44a5cd1b808   default

8. GitOps ์†Œ์Šค โ†” ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ ๊ฒ€์ฆ

1
2
3
4
5
6
7
 kubectl get applications.argoproj.io -n argocd dev-hello-world1 -o yaml | kubectl neat | yq

...
    "source": {
      "path": "apps/hello-world1/overlays/dev",
      "repoURL": "https://github.com/Shinminjin/autopilot.git"
    },
  • dev-hello-world1์˜ source.path๊ฐ€ GitOps ๋ ˆํฌ์ง€ํ† ๋ฆฌ์™€ ์ •ํ™•ํžˆ ์—ฐ๊ฒฐ๋œ ๊ฒƒ์„ ํ™•์ธ
1
2
3
4
5
6
7
kubectl get deploy,pod

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/simple-deployment   1/1     1            1           4m10s

NAME                                     READY   STATUS    RESTARTS   AGE
pod/simple-deployment-7854dd65f8-bnxn5   1/1     Running   0          4m10s
  • Git์— ์ •์˜๋œ ์ƒํƒœ๊ฐ€ Autopilot/Argo CD๋ฅผ ํ†ตํ•ด ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐ˜์˜๋˜๊ณ  ์žˆ์Œ์„ ๊ฒ€์ฆ

9. ๋‹ค์Œ ์‹ค์Šต์„ ์œ„ํ•œ ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ

1
2
3
4
kind delete cluster --name myk8s

Deleting cluster "myk8s" ...
Deleted nodes: ["myk8s-control-plane"]

๐Ÿ›ฐ๏ธ Argo CD ์šด์˜

1. ๋ฉ€ํ‹ฐ ๋…ธ๋“œ kind ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
- role: worker
- role: worker
- role: worker
EOF
1
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30001 --set env.TZ="Asia/Seoul" --namespace kube-system

2. Argo CD ๋งค๋‹ˆํŽ˜์ŠคํŠธ ๊ธฐ๋ฐ˜ ์ค€๋น„

1
2
3
4
5
6
7
8
9
10
11
mkdir -p my-sample-app/resources
cat << EOF > resources/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: argocd
EOF
kubectl apply -f resources/namespace.yaml

# ๊ฒฐ๊ณผ
namespace/argocd created
1
2
wget https://raw.githubusercontent.com/argoproj/argo-cd/refs/heads/master/manifests/ha/install.yaml
mv install.yaml resources/

3. GitOps ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ์ดˆ๊ธฐ ์ปค๋ฐ‹ ๋ฐ ํ‘ธ์‹œ

1
git add . && git commit -m "Deploy Argo CD " && git push -u origin main

  • ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ๋ฅผ Git ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ์™€ ๋งคํ•‘ํ•˜์—ฌ ์ดํ›„ Argo CD๊ฐ€ ์„ ์–ธํ˜•์œผ๋กœ ์ž์‹ ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฐ˜์„ ๋งˆ๋ จํ•จ

4. Argo CD ์„ค์น˜ ๋ฐ ์ ‘์† ํ™•์ธ

(1) Argo CD HA ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐฐํฌ

1
kubectl apply -f resources/install.yaml -n argocd

(2) ํฌํŠธํฌ์›Œ๋”ฉ

1
2
3
4
kubectl port-forward svc/argocd-server -n argocd 8080:80

Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

(3) ์ดˆ๊ธฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ

1
2
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d ; echo
zz1h2jv08fPsbSKr

(4) UI ์ ‘์†

1
2
https://127.0.0.1:8080
admin / zz1h2jv08fPsbSKr

(5) ์ •์ƒ ๊ธฐ๋™ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
kubectl get pod -n argocd

NAME                                                READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                     1/1     Running   0          12m
argocd-applicationset-controller-694b4774cd-js5tw   1/1     Running   0          12m
argocd-dex-server-66585dc685-g2ffs                  1/1     Running   0          12m
argocd-notifications-controller-7c584f65cc-vlk56    1/1     Running   0          12m
argocd-redis-ha-haproxy-7487b954d9-hqm74            1/1     Running   0          12m
argocd-redis-ha-haproxy-7487b954d9-l9nxn            1/1     Running   0          12m
argocd-redis-ha-haproxy-7487b954d9-n8rr5            1/1     Running   0          12m
argocd-redis-ha-server-0                            3/3     Running   0          12m
argocd-redis-ha-server-1                            3/3     Running   0          10m
argocd-redis-ha-server-2                            3/3     Running   0          10m
argocd-repo-server-74b54f7cb-42qs6                  1/1     Running   0          12m
argocd-repo-server-74b54f7cb-5sjmh                  1/1     Running   0          12m
argocd-server-8b767f58c-p5v2h                       1/1     Running   0          12m
argocd-server-8b767f58c-wbdfx                       1/1     Running   0          12m

5. Argo CD์— Git ๋ฆฌํฌ์ง€ํ„ฐ๋ฆฌ ์—ฐ๋™

  • Argo CD UI์˜ Settings โ†’ Repositories์—์„œ my-sample-app Git ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋“ฑ๋ก

6. Argo CD ์ž๊ธฐ ์ž์‹ ์„ ๊ด€๋ฆฌํ•˜๋Š” Application ์ƒ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd
  namespace: argocd
spec:
  project: default
  source:
    path: resources
    repoURL: https://github.com/Shinminjin/my-sample-app
    targetRevision: main
  syncPolicy:
    automated: {}
  destination:
    namespace: argocd
    server: https://kubernetes.default.svc
EOF

application.argoproj.io/argocd created

7. Argo CD ๋™๊ธฐํ™” ์ƒํƒœ ๋ฐ ํ—ฌ์Šค ์ฒดํฌ

1
2
3
4
kubectl get applications.argoproj.io -n argocd -owide

NAME     SYNC STATUS   HEALTH STATUS   REVISION                                   PROJECT
argocd   Synced        Healthy         aa92beaa6920fff4518a10c8e1a5930ab22b9e69   default

8. PRUNE ๋™์ž‘ ํ…Œ์ŠคํŠธ

(1) PRUNE RESOURCES ํ™œ์„ฑํ™”

(2) Networkpolicy ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
12
kubectl get networkpolicies.networking.k8s.io -n argocd

NAME                                              POD-SELECTOR                                              AGE
argocd-application-controller-network-policy      app.kubernetes.io/name=argocd-application-controller      35m
argocd-applicationset-controller-network-policy   app.kubernetes.io/name=argocd-applicationset-controller   35m
argocd-dex-server-network-policy                  app.kubernetes.io/name=argocd-dex-server                  35m
argocd-notifications-controller-network-policy    app.kubernetes.io/name=argocd-notifications-controller    35m
argocd-redis-ha-proxy-network-policy              app.kubernetes.io/name=argocd-redis-ha-haproxy            35m
argocd-redis-ha-server-network-policy             app.kubernetes.io/name=argocd-redis-ha                    35m
argocd-repo-server-network-policy                 app.kubernetes.io/name=argocd-repo-server                 35m
argocd-server-network-policy                      app.kubernetes.io/name=argocd-server                      35m

(3) NetworkPolicy ์ •์˜ ์‚ญ์ œ

(4) ์›๊ฒฉ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ์ปค๋ฐ‹ ํ›„, ํ‘ธ์‹œ

1
2
cd ..
git add . && git commit -m "Delete Network Policy Resource" && git push -u origin main

(5) Argo CD๊ฐ€ Git ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๊ฐ์ง€ํ•˜๊ณ  Sync + Prune ์ˆ˜ํ–‰

1
watch -d kubectl get networkpolicies.networking.k8s.io -n argocd


๐Ÿ“ˆ ๊ด€์ฐฐ ๊ฐ€๋Šฅ์„ฑ ์‹ค์Šต

1. kube-prometheus-stack Helm ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋“ฑ๋ก

1
2
cd ..
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

2. ๋ชจ๋‹ˆํ„ฐ๋ง ์„ค์ • ๊ฐ’ ํŒŒ์ผ ์ •์˜

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
cat <<EOT > monitor-values.yaml
prometheus:
  prometheusSpec:
    scrapeInterval: "15s"
    evaluationInterval: "15s"
  service:
    type: NodePort
    nodePort: 30002

grafana:
  defaultDashboardsTimezone: Asia/Seoul
  adminPassword: prom-operator
  service:
    type: NodePort
    nodePort: 30003

alertmanager:
  enabled: false
defaultRules:
  create: false
prometheus-windows-exporter:
  prometheus:
    monitor:
      enabled: false
EOT

3. kube-prometheus-stack ๋ฐฐํฌ

1
2
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version 75.15.1 \
-f monitor-values.yaml --create-namespace --namespace monitoring

4. ๋ชจ๋‹ˆํ„ฐ๋ง ์ปดํฌ๋„ŒํŠธ ์ƒํƒœ ๋ฐ ๋ฆฌ์†Œ์Šค ํ™•์ธ

1
2
3
4
helm list -n monitoring

NAME                 	NAMESPACE 	REVISION	UPDATED                                	STATUS  	CHART                        	APP VERSION
kube-prometheus-stack	monitoring	1       	2025-11-08 23:34:24.378026088 +0900 KST	deployed	kube-prometheus-stack-75.15.1	v0.83.0    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
kubectl get pod,svc,ingress,pvc -n monitoring

NAME                                                            READY   STATUS    RESTARTS   AGE
pod/kube-prometheus-stack-grafana-7d9c86798d-jbl4m              3/3     Running   0          91s
pod/kube-prometheus-stack-kube-state-metrics-684f8c7558-zlkwq   1/1     Running   0          91s
pod/kube-prometheus-stack-operator-68589744f5-gfs2t             1/1     Running   0          91s
pod/kube-prometheus-stack-prometheus-node-exporter-2dgwz        1/1     Running   0          91s
pod/kube-prometheus-stack-prometheus-node-exporter-fqh48        1/1     Running   0          91s
pod/kube-prometheus-stack-prometheus-node-exporter-k78rw        1/1     Running   0          91s
pod/kube-prometheus-stack-prometheus-node-exporter-nvn2r        1/1     Running   0          91s
pod/prometheus-kube-prometheus-stack-prometheus-0               2/2     Running   0          81s

NAME                                                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
service/kube-prometheus-stack-grafana                    NodePort    10.96.195.107   <none>        80:30003/TCP                    91s
service/kube-prometheus-stack-kube-state-metrics         ClusterIP   10.96.168.95    <none>        8080/TCP                        91s
service/kube-prometheus-stack-operator                   ClusterIP   10.96.71.163    <none>        443/TCP                         91s
service/kube-prometheus-stack-prometheus                 NodePort    10.96.237.122   <none>        9090:30002/TCP,8080:30649/TCP   91s
service/kube-prometheus-stack-prometheus-node-exporter   ClusterIP   10.96.93.44     <none>        9100/TCP                        91s
service/prometheus-operated                              ClusterIP   None            <none>        9090/TCP                        81s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kubectl get prometheus,servicemonitors -n monitoring

NAME                                                                VERSION   DESIRED   READY   RECONCILED   AVAILABLE   AGE
prometheus.monitoring.coreos.com/kube-prometheus-stack-prometheus   v3.5.0    1         1       True         True        116s

NAME                                                                                  AGE
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-apiserver                  116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-coredns                    116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-grafana                    116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kube-controller-manager    116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kube-etcd                  116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kube-proxy                 116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kube-scheduler             116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kube-state-metrics         116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-kubelet                    116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-operator                   116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-prometheus                 116s
servicemonitor.monitoring.coreos.com/kube-prometheus-stack-prometheus-node-exporter   116s

5. Prometheus CRD ๋ฐ ์˜คํผ๋ ˆ์ดํ„ฐ ์—ฐ๋™ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
12
kubectl get crd | grep monitoring

alertmanagerconfigs.monitoring.coreos.com   2025-11-08T14:34:22Z
alertmanagers.monitoring.coreos.com         2025-11-08T14:34:22Z
podmonitors.monitoring.coreos.com           2025-11-08T14:34:22Z
probes.monitoring.coreos.com                2025-11-08T14:34:22Z
prometheusagents.monitoring.coreos.com      2025-11-08T14:34:23Z
prometheuses.monitoring.coreos.com          2025-11-08T14:34:23Z
prometheusrules.monitoring.coreos.com       2025-11-08T14:34:23Z
scrapeconfigs.monitoring.coreos.com         2025-11-08T14:34:23Z
servicemonitors.monitoring.coreos.com       2025-11-08T14:34:23Z
thanosrulers.monitoring.coreos.com          2025-11-08T14:34:23Z

6. Prometheus ์ธ์Šคํ„ด์Šค ์„ค์ • ๋ฐ ๋ฒ„์ „ ๊ฒ€์ฆ

1
2
3
4
5
6
7
8
9
kubectl exec -it sts/prometheus-kube-prometheus-stack-prometheus -n monitoring -c prometheus -- prometheus --version

# ๊ฒฐ๊ณผ
prometheus, version 3.5.0 (branch: HEAD, revision: 8be3a9560fbdd18a94dedec4b747c35178177202)
  build user:       root@4451b64cb451
  build date:       20250714-16:15:23
  go version:       go1.24.5
  platform:         linux/amd64
  tags:             netgo,builtinassets

7. ServiceMonitor ๋ผ๋ฒจ ๋งค์นญ ํ™•์ธ

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
26
27
28
kubectl get prometheuses.monitoring.coreos.com -n monitoring -o yaml | kubectl neat | yq

...
        "podMonitorSelector": {
          "matchLabels": {
            "release": "kube-prometheus-stack"
          }
        },
        "portName": "http-web",
        "probeSelector": {
          "matchLabels": {
            "release": "kube-prometheus-stack"
          }
        },
        "replicas": 1,
        "retention": "10d",
        "routePrefix": "/",
        "ruleSelector": {
          "matchLabels": {
            "release": "kube-prometheus-stack"
          }
        },
        "scrapeConfigSelector": {
          "matchLabels": {
            "release": "kube-prometheus-stack"
          }
        },
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl get servicemonitors.monitoring.coreos.com -n monitoring kube-prometheus-stack-apiserver -o yaml | grep labels: -A10
  
# ๊ฒฐ๊ณผ  
  labels:
    app: kube-prometheus-stack-apiserver
    app.kubernetes.io/instance: kube-prometheus-stack
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/part-of: kube-prometheus-stack
    app.kubernetes.io/version: 75.15.1
    chart: kube-prometheus-stack-75.15.1
    heritage: Helm
    release: kube-prometheus-stack
  name: kube-prometheus-stack-apiserver
  namespace: monitoring
  • release: kube-prometheus-stack ๋“ฑ ๊ณตํ†ต ๋ผ๋ฒจ์ด ์„ค์ •๋˜์–ด ์žˆ๊ณ , Prometheus ๋ฆฌ์†Œ์Šค์˜ Selector์™€ ์ผ์น˜ํ•จ

๐Ÿ“ก Argo CD ๊ตฌ์„ฑ์š”์†Œ์— ๋Œ€ํ•œ ServiceMonitor ์ƒ์„ฑ

1. ํ…Œ์ŠคํŠธ์šฉ NGINX ํŒŒ๋“œ ๊ธฐ๋™

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
EOF

pod/nginx created

2. Argo CD Metrics ์„œ๋น„์Šค ํ™•์ธ

1
2
3
4
5
6
7
kubectl get svc,ep -n argocd -l app.kubernetes.io/name=argocd-metrics

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/argocd-metrics   ClusterIP   10.96.243.251   <none>        8082/TCP   58m

NAME                       ENDPOINTS         AGE
endpoints/argocd-metrics   10.244.1.5:8082   58m
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
26
27
28
29
30
31
32
33
34
35
36
37
kubectl get svc -n argocd argocd-metrics -o yaml | kubectl neat | yq

{
  "apiVersion": "v1",
  "kind": "Service",
  "metadata": {
    "annotations": {
      "argocd.argoproj.io/tracking-id": "argocd:/Service:argocd/argocd-metrics"
    },
    "labels": {
      "app.kubernetes.io/component": "metrics",
      "app.kubernetes.io/name": "argocd-metrics",
      "app.kubernetes.io/part-of": "argocd"
    },
    "name": "argocd-metrics",
    "namespace": "argocd"
  },
  "spec": {
    "clusterIP": "10.96.243.251",
    "clusterIPs": [
      "10.96.243.251"
    ],
    "ipFamilies": [
      "IPv4"
    ],
    "ipFamilyPolicy": "SingleStack",
    "ports": [
      {
        "name": "metrics",
        "port": 8082
      }
    ],
    "selector": {
      "app.kubernetes.io/name": "argocd-application-controller"
    }
  }
}
1
2
3
4
kubectl get pod -n argocd -l app.kubernetes.io/name=argocd-application-controller

NAME                              READY   STATUS    RESTARTS   AGE
argocd-application-controller-0   1/1     Running   0          59m

3. Argo CD Application Controller์šฉ ServiceMonitor ์ƒ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-metrics
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF

servicemonitor.monitoring.coreos.com/argocd-metrics created

4. Argo CD ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ๋ณ„ ServiceMonitor ์ถ”๊ฐ€

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-server-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-server-metrics
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF

servicemonitor.monitoring.coreos.com/argocd-server-metrics created
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-repo-server-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-repo-server
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF

servicemonitor.monitoring.coreos.com/argocd-repo-server-metrics created
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-applicationset-controller-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-applicationset-controller
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-dex-server
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-dex-server
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-redis-haproxy-metrics
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-redis-ha-haproxy
  endpoints:
    - port: http-exporter-port
  namespaceSelector:
    matchNames:
      - argocd
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-notifications-controller
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-notifications-controller-metrics
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
      - argocd
EOF

servicemonitor.monitoring.coreos.com/argocd-applicationset-controller-metrics created
servicemonitor.monitoring.coreos.com/argocd-dex-server created
servicemonitor.monitoring.coreos.com/argocd-redis-haproxy-metrics created
servicemonitor.monitoring.coreos.com/argocd-notifications-controller created

5. ServiceMonitor ๋“ฑ๋ก ๊ฒฐ๊ณผ ๋ฐ ์Šคํฌ๋žฉ ๋Œ€์ƒ ํ™•์ธ

1
2
3
4
5
6
7
8
9
kubectl get servicemonitors -n monitoring | grep argocd

argocd-applicationset-controller-metrics         19s
argocd-dex-server                                19s
argocd-metrics                                   4m42s
argocd-notifications-controller                  19s
argocd-redis-haproxy-metrics                     19s
argocd-repo-server-metrics                       46s
argocd-server-metrics                            75s

6. Grafana์—์„œ Argo CD ๋Œ€์‹œ๋ณด๋“œ ๊ตฌ์„ฑ

1
2
3
4
5
http://127.0.0.1:30003
admin / prom-operator

# ๋Œ€์‹œ๋ณด๋“œ Import
https://github.com/argoproj/argo-cd/blob/master/examples/dashboard.json

7. Guestbook ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

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
26
27
28
29
30
31
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    helm:
      valueFiles:
      - values.yaml
    path: helm-guestbook
    repoURL: https://github.com/argoproj/argocd-example-apps
    targetRevision: HEAD
  syncPolicy:
    automated:
      enabled: true
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: guestbook
    server: https://kubernetes.default.svc
EOF

Warning: metadata.finalizers: "resources-finalizer.argocd.argoproj.io": prefer a domain-qualified finalizer name including a path (/) to avoid accidental conflicts with other finalizer writers
application.argoproj.io/guestbook created

This post is licensed under CC BY 4.0 by the author.