Post

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

๐Ÿš€ 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
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
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

Not sure what to do next? ๐Ÿ˜…  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

๐Ÿงฉ Creating a Helm Project

1. ํ—ฌ๋ฆ„ ์ฐจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ ˆ์ด์•„์›ƒ ์ƒ์„ฑ

1
2
3
mkdir pacman
mkdir pacman/templates
cd pacman

2. ์ฐจํŠธ ์ •์˜ ํŒŒ์ผ(Chart.yaml) ์ž‘์„ฑ

1
2
3
4
5
6
7
8
cat << EOF > Chart.yaml
apiVersion: v2
name: pacman
description: A Helm chart for Pacman
type: application
version: 0.1.0        # ์ฐจํŠธ ๋ฒ„์ „, ์ฐจํŠธ ์ •์˜๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์—…๋ฐ์ดํŠธํ•œ๋‹ค
appVersion: "1.0.0"   # ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฒ„์ „
EOF

3. ๋ฐฐํฌ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํ…œํ”Œ๋ฆฟ(deployment.yaml) ์ž‘์„ฑ

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
cat << EOF > templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name:             # Chart.yaml ํŒŒ์ผ์— ์„ค์ •๋œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์™€ ์„ค์ •
  labels:
    app.kubernetes.io/name:      # Chart.yaml ํŒŒ์ผ์— appVersion ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ฒ„์ „์„ ์„ค์ •
    app.kubernetes.io/version:      # appVersion ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ง€์ •ํ•˜๊ณ  ๋”ฐ์›€ํ‘œ ์ฒ˜๋ฆฌ
spec:
  replicas:      # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
  selector:
    matchLabels:
      app.kubernetes.io/name: 
  template:
    metadata:
      labels:
        app.kubernetes.io/name: 
    spec:
      containers:
        - image: ":"   # ์ด๋ฏธ์ง€ ์ง€์ • placeholder, ์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„ฃ๊ณ , ์—†์œผ๋ฉด Chart.yaml์— ๊ฐ’์„ ์„ค์ •
          imagePullPolicy: 
          securityContext: # securityContext์˜ ๊ฐ’์„ YAML ๊ฐ์ฒด๋กœ ์ง€์ •ํ•˜๋ฉฐ 14์นธ ๋“ค์—ฌ์“ฐ๊ธฐ
          name: 
          ports:
            - containerPort: 
              name: http
              protocol: TCP
EOF

4. ์„œ๋น„์Šค ํ…œํ”Œ๋ฆฟ(service.yaml) ์ž‘์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat << EOF > templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: 
  name: 
spec:
  ports:
    - name: http
      port: 
      targetPort: 
  selector:
    app.kubernetes.io/name: 
EOF

5. ๊ธฐ๋ณธ๊ฐ’(values.yaml) ์ž‘์„ฑ

1
2
3
4
5
6
7
8
9
10
cat << EOF > values.yaml
image:     # image ์ ˆ ์ •์˜
  repository: quay.io/gitops-cookbook/pacman-kikd
  tag: "1.0.0"
  pullPolicy: Always
  containerPort: 8080

replicaCount: 1
securityContext: {}     # securityContext ์†์„ฑ์˜ ๊ฐ’์„ ๋น„์šด๋‹ค
EOF

6. ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ ˆ์ด์•„์›ƒ ํ™•์ธ

1
2
3
4
5
6
7
8
9
tree
.
โ”œโ”€โ”€ Chart.yaml
โ”œโ”€โ”€ templates
โ”‚ย ย  โ”œโ”€โ”€ deployment.yaml
โ”‚ย ย  โ””โ”€โ”€ service.yaml
โ””โ”€โ”€ values.yaml

2 directories, 4 files

7. ๋กœ์ปฌ ๋ Œ๋”๋ง์œผ๋กœ ํ…œํ”Œ๋ฆฟ ๊ฒ€์ฆ

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
helm template .

# ๊ฒฐ๊ณผ
---
# Source: pacman/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: pacman
  name: pacman
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
    app.kubernetes.io/name: pacman
---
# Source: pacman/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pacman            # Chart.yaml ํŒŒ์ผ์— ์„ค์ •๋œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์™€ ์„ค์ •
  labels:
    app.kubernetes.io/name: pacman     # Chart.yaml ํŒŒ์ผ์— appVersion ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ฒ„์ „์„ ์„ค์ •
    app.kubernetes.io/version: "1.0.0"     # appVersion ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ง€์ •ํ•˜๊ณ  ๋”ฐ์›€ํ‘œ ์ฒ˜๋ฆฌ
spec:
  replicas: 1     # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
  selector:
    matchLabels:
      app.kubernetes.io/name: pacman
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pacman
    spec:
      containers:
        - image: "quay.io/gitops-cookbook/pacman-kikd:1.0.0"   # ์ด๋ฏธ์ง€ ์ง€์ • placeholder, ์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„ฃ๊ณ , ์—†์œผ๋ฉด Chart.yaml์— ๊ฐ’์„ ์„ค์ •
          imagePullPolicy: Always
          securityContext:
              {} # securityContext์˜ ๊ฐ’์„ YAML ๊ฐ์ฒด๋กœ ์ง€์ •ํ•˜๋ฉฐ 14์นธ ๋“ค์—ฌ์“ฐ๊ธฐ
          name: pacman
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
  • Service/Deployment๊ฐ€ ๊ธฐ๋Œ€ ๊ฐ’(์ด๋ฆ„, ๋ผ๋ฒจ, ์ด๋ฏธ์ง€, ํฌํŠธ, replicas ๋“ฑ)์œผ๋กœ ์ถœ๋ ฅ
  • securityContext: {}๊ฐ€ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜๋จ(์ดˆ๊ธฐ ์ƒํƒœ)

8. ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„๋ผ์ด๋“œ(โ€“set) ํ…Œ์ŠคํŠธ

1
2
3
4
5
6
7
helm template --set replicaCount=3 .

# ๊ฒฐ๊ณผ
...
spec:
  replicas: 3     # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
...
  • --set replicaCount=3 ์‚ฌ์šฉ ์‹œ ๋ Œ๋” ๊ฒฐ๊ณผ replicas: 3๋กœ ๋ฐ˜์˜

9. ์ฐจํŠธ ์„ค์น˜

1
2
3
4
5
6
7
8
9
helm install pacman .

# ๊ฒฐ๊ณผ
NAME: pacman
LAST DEPLOYED: Sat Oct 25 12:45:00 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

10. ๋ฆด๋ฆฌ์Šค ๋ฆฌ์ŠคํŠธ ํ™•์ธ

1
2
3
4
helm list

NAME  	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART       	APP VERSION
pacman	default  	1       	2025-10-25 12:45:00.039857183 +0900 KST	deployed	pacman-0.1.0	1.0.0

11. ๋ฐฐํฌ๋œ ๋ฆฌ์†Œ์Šค ์กฐํšŒ

1
kubectl get deploy,pod,svc,ep

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/pacman   1/1     1            1           59s

NAME                          READY   STATUS    RESTARTS   AGE
pod/pacman-576769bb86-dnb4x   1/1     Running   0          59s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    12m
service/pacman       ClusterIP   10.96.122.128   <none>        8080/TCP   59s

NAME                   ENDPOINTS         AGE
endpoints/kubernetes   172.18.0.2:6443   12m
endpoints/pacman       10.244.0.5:8080   59s

12. securityContext ์ ์šฉ ์ƒํƒœ ์ ๊ฒ€

1
kubectl get pod -o json | grep securityContext -A1

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
                        "securityContext": {},
                        "terminationMessagePath": "/dev/termination-log",
--
                "securityContext": {},
                "serviceAccount": "default",
  • ํ˜„์žฌ ํŒŒ๋“œ ์ปจํ…Œ์ด๋„ˆ์— ๋ณด์•ˆ ์ปจํ…์ŠคํŠธ ๋น„์–ด์žˆ์Œ์„ ํ™•์ธ

13. ๋ฐฐํฌ ์ด๋ ฅ ํ™•์ธ

1
2
3
4
helm history pacman

REVISION	UPDATED                 	STATUS  	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 12:45:00 2025	deployed	pacman-0.1.0	1.0.0      	Install complete

14. Helm ๋ฆด๋ฆฌ์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ Secret ํ™•์ธ

1
2
3
4
kubectl get secret

NAME                           TYPE                 DATA   AGE
sh.helm.release.v1.pacman.v1   helm.sh/release.v1   1      3m16s
  • Helm์ด ๋ฆด๋ฆฌ์Šค ๋ฉ”ํƒ€์ •๋ณด๋ฅผ Secret์— ์ €์žฅํ•จ์„ ํ™•์ธ

15. ์ฐจํŠธ ์—…๊ทธ๋ ˆ์ด๋“œ

1
2
3
4
5
6
7
8
9
10
helm upgrade pacman --reuse-values --set replicaCount=2 .

# ๊ฒฐ๊ณผ
Release "pacman" has been upgraded. Happy Helming!
NAME: pacman
LAST DEPLOYED: Sat Oct 25 12:49:01 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None

16. ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„ ๋ฆด๋ฆฌ์Šค/์ด๋ ฅ ์žฌํ™•์ธ

1
2
3
4
helm list

NAME  	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART       	APP VERSION
pacman	default  	2       	2025-10-25 12:49:01.423753811 +0900 KST	deployed	pacman-0.1.0	1.0.0 
1
2
3
4
5
helm history pacman

REVISION	UPDATED                 	STATUS    	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 12:45:00 2025	superseded	pacman-0.1.0	1.0.0      	Install complete
2       	Sat Oct 25 12:49:01 2025	deployed  	pacman-0.1.0	1.0.0      	Upgrade complete
  • ๋ฆฌ๋น„์ „ ์ฆ๊ฐ€ ๋ฐ ์ƒํƒœ ๊ฐฑ์‹  ํ™•์ธ

17. Secret ๋ฆฌ๋น„์ „ ๋ˆ„์  ํ™•์ธ

1
2
3
4
5
kubectl get secret

NAME                           TYPE                 DATA   AGE
sh.helm.release.v1.pacman.v1   helm.sh/release.v1   1      6m28s
sh.helm.release.v1.pacman.v2   helm.sh/release.v1   1      2m27s

18. ์Šค์ผ€์ผ ๋ณ€ํ™” ํ™•์ธ

1
2
3
4
5
kubectl get pod                                   

NAME                      READY   STATUS    RESTARTS   AGE
pacman-576769bb86-dnb4x   1/1     Running   0          6m51s
pacman-576769bb86-t4g9l   1/1     Running   0          2m50s

19. ๋ฐฐํฌ ์ƒ์„ธ ํ™•์ธ

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
helm get all pacman

NAME: pacman
LAST DEPLOYED: Sat Oct 25 12:49:01 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
CHART: pacman
VERSION: 0.1.0
APP_VERSION: 1.0.0
TEST SUITE: None
USER-SUPPLIED VALUES:
replicaCount: 2

COMPUTED VALUES:
image:
  containerPort: 8080
  pullPolicy: Always
  repository: quay.io/gitops-cookbook/pacman-kikd
  tag: 1.0.0
replicaCount: 2
securityContext: {}

HOOKS:
MANIFEST:
---
# Source: pacman/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: pacman
  name: pacman
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
    app.kubernetes.io/name: pacman
---
# Source: pacman/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pacman            # Chart.yaml ํŒŒ์ผ์— ์„ค์ •๋œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์™€ ์„ค์ •
  labels:
    app.kubernetes.io/name: pacman     # Chart.yaml ํŒŒ์ผ์— appVersion ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ฒ„์ „์„ ์„ค์ •
    app.kubernetes.io/version: "1.0.0"     # appVersion ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ง€์ •ํ•˜๊ณ  ๋”ฐ์›€ํ‘œ ์ฒ˜๋ฆฌ
spec:
  replicas: 2     # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
  selector:
    matchLabels:
      app.kubernetes.io/name: pacman
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pacman
    spec:
      containers:
        - image: "quay.io/gitops-cookbook/pacman-kikd:1.0.0"   # ์ด๋ฏธ์ง€ ์ง€์ • placeholder, ์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„ฃ๊ณ , ์—†์œผ๋ฉด Chart.yaml์— ๊ฐ’์„ ์„ค์ •
          imagePullPolicy: Always
          securityContext:
              {} # securityContext์˜ ๊ฐ’์„ YAML ๊ฐ์ฒด๋กœ ์ง€์ •ํ•˜๋ฉฐ 14์นธ ๋“ค์—ฌ์“ฐ๊ธฐ
          name: pacman
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP

20. ์ฐจํŠธ ์‚ญ์ œ

1
2
3
4
helm uninstall pacman
kubectl get secret

No resources found in default namespace.

โ™ป๏ธ Reusing Statements Between Templates

1. _helpers.tpl ํŒŒ์ผ ์ž‘์„ฑ

1
2
3
cat << EOF > templates/_helpers.tpl# stetement ์ด๋ฆ„์„ ์ •์˜
app.kubernetes.io/name:  # ํ•ด๋‹น stetement ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ •์˜
EOF
  • ์—ฌ๋Ÿฌ ํ…œํ”Œ๋ฆฟ์—์„œ ๋™์ผ ๊ตฌ๋ฌธ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ

2. deployment/service์— ํ—ฌํผ ์ ์šฉ

1
2
3
4
5
6
7
8
9
10
11
## deployment.yaml ์ˆ˜์ •
spec:
  replicas: 
  selector:
    matchLabels:   # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 6๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
  template:
    metadata:
      labels: # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 8๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
        
## service.yaml ์ˆ˜์ •
  selector:

3. ๋กœ์ปฌ ๋ Œ๋”๋ง์œผ๋กœ ์ ์šฉ ํ™•์ธ

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
helm template .

---
# Source: pacman/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: pacman
  name: pacman
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
      # stetement ์ด๋ฆ„์„ ์ •์˜
      app.kubernetes.io/name: pacman # ํ•ด๋‹น stetement ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ •์˜
---
# Source: pacman/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pacman            # Chart.yaml ํŒŒ์ผ์— ์„ค์ •๋œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์™€ ์„ค์ •
  labels:
    app.kubernetes.io/name: pacman     # Chart.yaml ํŒŒ์ผ์— appVersion ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ฒ„์ „์„ ์„ค์ •
    app.kubernetes.io/version: "1.0.0"     # appVersion ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ง€์ •ํ•˜๊ณ  ๋”ฐ์›€ํ‘œ ์ฒ˜๋ฆฌ
spec:
  replicas: 1     # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
  selector:
    matchLabels:
      # stetement ์ด๋ฆ„์„ ์ •์˜
      app.kubernetes.io/name: pacman # ํ•ด๋‹น stetement ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ •์˜   # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 6๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
  template:
    metadata:
      labels:
        # stetement ์ด๋ฆ„์„ ์ •์˜
        app.kubernetes.io/name: pacman # ํ•ด๋‹น stetement ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์ •์˜ # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 8๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
    spec:
      containers:
        - image: "quay.io/gitops-cookbook/pacman-kikd:1.0.0"   # ์ด๋ฏธ์ง€ ์ง€์ • placeholder, ์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„ฃ๊ณ , ์—†์œผ๋ฉด Chart.yaml์— ๊ฐ’์„ ์„ค์ •
          imagePullPolicy: Always
          securityContext:
              {} # securityContext์˜ ๊ฐ’์„ YAML ๊ฐ์ฒด๋กœ ์ง€์ •ํ•˜๋ฉฐ 14์นธ ๋“ค์—ฌ์“ฐ๊ธฐ
          name: pacman
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
  • app.kubernetes.io/name: pacman ๋ผ๋ฒจ ๋ฐ˜์˜ ํ™•์ธ

4. _helpers.tpl ํ™•์žฅ

1
2
3
cat << EOF > templates/_helpers.tplapp.kubernetes.io/name: 
app.kubernetes.io/version: 
EOF
  • app.kubernetes.io/version: ์ถ”๊ฐ€

5. ์žฌ๋ Œ๋”๋ง์œผ๋กœ ๋ฒ„์ „ ๋ผ๋ฒจ ํ™•์ธ

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
helm template .

---
# Source: pacman/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: pacman
  name: pacman
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
      app.kubernetes.io/name: pacman
      app.kubernetes.io/version: 1.0.0
---
# Source: pacman/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pacman            # Chart.yaml ํŒŒ์ผ์— ์„ค์ •๋œ ์ด๋ฆ„์„ ๊ฐ€์ ธ์™€ ์„ค์ •
  labels:
    app.kubernetes.io/name: pacman     # Chart.yaml ํŒŒ์ผ์— appVersion ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ฒ„์ „์„ ์„ค์ •
    app.kubernetes.io/version: "1.0.0"     # appVersion ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ง€์ •ํ•˜๊ณ  ๋”ฐ์›€ํ‘œ ์ฒ˜๋ฆฌ
spec:
  replicas: 1     # replicaCount ์†์„ฑ์„ ๋„ฃ์„ ์ž๋ฆฌ placeholder
  selector:
    matchLabels:
      app.kubernetes.io/name: pacman
      app.kubernetes.io/version: 1.0.0   # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 6๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pacman
        app.kubernetes.io/version: 1.0.0 # pacman.selectorLabels๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฐ๊ณผ๋ฅผ 8๋งŒํผ ๋“ค์—ฌ์“ฐ๊ธฐํ•˜์—ฌ ์ฃผ์ž…
    spec:
      containers:
        - image: "quay.io/gitops-cookbook/pacman-kikd:1.0.0"   # ์ด๋ฏธ์ง€ ์ง€์ • placeholder, ์ด๋ฏธ์ง€ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„ฃ๊ณ , ์—†์œผ๋ฉด Chart.yaml์— ๊ฐ’์„ ์„ค์ •
          imagePullPolicy: Always
          securityContext:
              {} # securityContext์˜ ๊ฐ’์„ YAML ๊ฐ์ฒด๋กœ ์ง€์ •ํ•˜๋ฉฐ 14์นธ ๋“ค์—ฌ์“ฐ๊ธฐ
          name: pacman
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
  • ์ด๋ฆ„ยท๋ฒ„์ „ ๋ผ๋ฒจ ๋ชจ๋‘ ๊ณตํ†ต ํ—ฌํผ์—์„œ ๊ด€๋ฆฌ๋˜์–ด ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐ ๋ณ€๊ฒฝ ์šฉ์ด์„ฑ ํ–ฅ์ƒ

๐Ÿ”„ Updating a Container Image in Helm

1. _helpers.tpl ์ดˆ๊ธฐํ™”

1
2
cat << EOF > templates/_helpers.tplapp.kubernetes.io/name: 
EOF
  • selector ๊ณตํ†ต ํ•จ์ˆ˜์—์„œ name๋งŒ ์‚ฌ์šฉํ•˜๋„๋ก ์›๋ณต

2. ์ดˆ๊ธฐ ๋ฐฐํฌ(REVISION 1)

1
2
3
4
5
6
7
8
9
helm install pacman .

# ๊ฒฐ๊ณผ
NAME: pacman
LAST DEPLOYED: Sat Oct 25 13:10:58 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
1
2
helm history pacman
kubectl get deploy -owide

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
REVISION	UPDATED                 	STATUS  	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 13:10:58 2025	deployed	pacman-0.1.0	1.0.0      	Install complete

NAME     READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                                      SELECTOR
pacman   1/1     1            1           30s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.0.0   app.kubernetes.io/name=pacman

3. ์ด๋ฏธ์ง€ ํƒœ๊ทธ 1.1.0์œผ๋กœ ๊ฐฑ์‹ 

1
2
3
4
5
6
7
8
9
10
cat << EOF > values.yaml
image:
  repository: quay.io/gitops-cookbook/pacman-kikd
  tag: "1.1.0"
  pullPolicy: Always
  containerPort: 8080

replicaCount: 1
securityContext: {}
EOF
1
2
3
4
5
6
7
8
cat << EOF > Chart.yaml
apiVersion: v2
name: pacman
description: A Helm chart for Pacman
type: application
version: 0.1.0
appVersion: "1.1.0"
EOF
  • values.yaml์˜ image.tag๋ฅผ "1.1.0"์œผ๋กœ, Chart.yaml์˜ appVersion์„ "1.1.0"์œผ๋กœ ์—…๋ฐ์ดํŠธ

4. ์—…๊ทธ๋ ˆ์ด๋“œ ์ ์šฉ(REVISION 2)

1
2
3
4
5
6
7
8
9
10
helm upgrade pacman .

# ๊ฒฐ๊ณผ
Release "pacman" has been upgraded. Happy Helming!
NAME: pacman
LAST DEPLOYED: Sat Oct 25 13:13:30 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
1
2
helm history pacman
kubectl get secret

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
REVISION	UPDATED                 	STATUS    	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 13:10:58 2025	superseded	pacman-0.1.0	1.0.0      	Install complete
2       	Sat Oct 25 13:13:30 2025	deployed  	pacman-0.1.0	1.1.0      	Upgrade complete

NAME                           TYPE                 DATA   AGE
sh.helm.release.v1.pacman.v1   helm.sh/release.v1   1      3m
sh.helm.release.v1.pacman.v2   helm.sh/release.v1   1      28s
  • REVISION 2 / APP VERSION 1.1.0 / Upgrade complete

5. ๋ฆฌ์†Œ์Šค ์ƒํƒœ ํ™•์ธ

1
kubectl get deploy,replicaset -owide

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                                      SELECTOR
deployment.apps/pacman   1/1     1            1           3m34s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.1.0   app.kubernetes.io/name=pacman

NAME                                DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                                      SELECTOR
replicaset.apps/pacman-576769bb86   0         0         0       3m34s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.0.0   app.kubernetes.io/name=pacman,pod-template-hash=576769bb86
replicaset.apps/pacman-64c54b85f9   1         1         1       62s     pacman       quay.io/gitops-cookbook/pacman-kikd:1.1.0   app.kubernetes.io/name=pacman,pod-template-hash=64c54b85f9
  • ๋ฐฐํฌ: deployment.apps/pacman ์ด๋ฏธ์ง€ :1.1.0 ์ ์šฉ
  • ๋ ˆํ”Œ๋ฆฌ์นด์…‹: :1.0.0(์ด์ „)๊ณผ :1.1.0(ํ˜„์žฌ) ๊ณต์กด, ์ด์ „ RS๋Š” ํŒŒ๋“œ 0

6. ์ด์ „ ๋ฒ„์ „์œผ๋กœ ๋กค๋ฐฑ(REVISION 3)

1
2
3
4
5
helm history pacman

REVISION	UPDATED                 	STATUS    	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 13:10:58 2025	superseded	pacman-0.1.0	1.0.0      	Install complete
2       	Sat Oct 25 13:13:30 2025	deployed  	pacman-0.1.0	1.1.0      	Upgrade complete
1
2
3
4
5
6
7
8
9
10
11
helm rollback pacman 1 && kubectl get pod -w

Rollback was a success! Happy Helming!
NAME                      READY   STATUS              RESTARTS   AGE
pacman-576769bb86-gvgv4   0/1     ContainerCreating   0          0s
pacman-64c54b85f9-4bgs2   1/1     Running             0          3m52s
pacman-576769bb86-gvgv4   1/1     Running             0          2s
pacman-64c54b85f9-4bgs2   1/1     Terminating         0          3m54s
pacman-64c54b85f9-4bgs2   0/1     Error               0          3m54s
pacman-64c54b85f9-4bgs2   0/1     Error               0          3m55s
pacman-64c54b85f9-4bgs2   0/1     Error               0          3m55s
1
2
3
4
5
6
7
8
9
10
11
12
helm history pacman
kubectl get secret

REVISION	UPDATED                 	STATUS    	CHART       	APP VERSION	DESCRIPTION     
1       	Sat Oct 25 13:10:58 2025	superseded	pacman-0.1.0	1.0.0      	Install complete
2       	Sat Oct 25 13:13:30 2025	superseded	pacman-0.1.0	1.1.0      	Upgrade complete
3       	Sat Oct 25 13:17:22 2025	deployed  	pacman-0.1.0	1.0.0      	Rollback to 1   

NAME                           TYPE                 DATA   AGE
sh.helm.release.v1.pacman.v1   helm.sh/release.v1   1      7m11s
sh.helm.release.v1.pacman.v2   helm.sh/release.v1   1      4m39s
sh.helm.release.v1.pacman.v3   helm.sh/release.v1   1      47s
  • helm history์— REVISION 3 / APP VERSION 1.0.0 / Rollback to 1
  • Secret: sh.helm.release.v1.pacman.v3 ์ถ”๊ฐ€
1
2
3
4
5
6
7
8
9
kubectl get deploy,replicaset -owide

# ๊ฒฐ๊ณผ
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                                      SELECTOR
deployment.apps/pacman   1/1     1            1           7m45s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.0.0   app.kubernetes.io/name=pacman

NAME                                DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                                      SELECTOR
replicaset.apps/pacman-576769bb86   1         1         1       7m45s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.0.0   app.kubernetes.io/name=pacman,pod-template-hash=576769bb86
replicaset.apps/pacman-64c54b85f9   0         0         0       5m13s   pacman       quay.io/gitops-cookbook/pacman-kikd:1.1.0   app.kubernetes.io/name=pacman,pod-template-hash=64c54b85f9
  • Deployment ์ด๋ฏธ์ง€ :1.0.0, ์ด์ „ :1.1.0 RS๋Š” ํŒŒ๋“œ 0

7. values ์˜ค๋ฒ„๋ผ์ด๋“œ๋กœ ํ…œํ”Œ๋ฆฟ๋งŒ ๊ฒ€์ฆ

1
2
3
4
cat << EOF > newvalues.yaml
image:
  tag: "1.2.0"
EOF
1
2
3
4
5
6
helm template pacman -f newvalues.yaml .

# ๊ฒฐ๊ณผ
...
        - image: "quay.io/gitops-cookbook/pacman-kikd:1.2.0"
...
  • ๋ Œ๋”๋œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ์ด๋ฏธ์ง€๊ฐ€ :1.2.0์œผ๋กœ ์ถœ๋ ฅ(์‹ค์ œ ๋ฐฐํฌ ๋ณ€๊ฒฝ ์—†์Œ)

๐Ÿ“ฆ Packaging and Distributing a Helm Chart

1. ์ฐจํŠธ ํŒจํ‚ค์ง•(.tgz ์ƒ์„ฑ)

1
2
3
4
helm package .

# ๊ฒฐ๊ณผ
Successfully packaged chart and saved it to: /home/devshin/workspace/cicd/chapters/chapters/pacman/pacman-0.1.0.tgz

2. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ธ๋ฑ์Šค ์ƒ์„ฑ

1
helm repo index .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat index.yaml

# ๊ฒฐ๊ณผ
apiVersion: v1
entries:
  pacman:
  - apiVersion: v2
    appVersion: 1.1.0
    created: "2025-10-25T13:24:19.927801229+09:00"
    description: A Helm chart for Pacman
    digest: 055ede949ae3c3d13e1088ae55dffd887bc6f2c7c224dfa5acd911a0e476732d
    name: pacman
    type: application
    urls:
    - pacman-0.1.0.tgz
    version: 0.1.0
generated: "2025-10-25T13:24:19.926665757+09:00"

๐Ÿ”” Bitnami ๊ณต๊ฐœ ์นดํƒˆ๋กœ๊ทธ ์‚ญ์ œ

1. BSI nginx ์ด๋ฏธ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ

1
2
3
4
5
6
7
8
docker pull bitnamisecure/nginx:latest

# ๊ฒฐ๊ณผ
latest: Pulling from bitnamisecure/nginx
1492e1542a25: Pull complete 
Digest: sha256:1a6d9b279f8e272e170f9632df0183d22b50372b7465b77d2ba6071b88b8c803
Status: Downloaded newer image for bitnamisecure/nginx:latest
docker.io/bitnamisecure/nginx:latest

2. ์ด๋ฏธ์ง€ ๋ชฉ๋ก ํ™•์ธ

1
2
3
4
docker images

REPOSITORY                                  TAG                                                           IMAGE ID       CREATED        SIZE
bitnamisecure/nginx                         latest                                                        2aa2aa2b771f   27 hours ago   100MB                                             2574b2ca2237   55 years ago   281MB

3. ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰

1
2
3
4
docker run -d -p 8080:8080 --name nginx bitnamisecure/nginx:latest

# ๊ฒฐ๊ณผ
c7113c60789a765e6276b91774f4d8fc2ca1070082f564ffd7a2e5f509456869

4. ๋™์ž‘ ํ™•์ธ

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
curl -s 127.0.0.1:8080

# ๊ฒฐ๊ณผ
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

5. ๋กœ๊ทธ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
docker logs nginx

# ๊ฒฐ๊ณผ
nginx 04:30:24.11 INFO  ==> 
nginx 04:30:24.11 INFO  ==> Welcome to the Bitnami nginx container
nginx 04:30:24.11 INFO  ==> Subscribe to project updates by watching https://github.com/bitnami/containers
nginx 04:30:24.11 INFO  ==> NOTICE: Starting August 28th, 2025, only a limited subset of images/charts will remain available for free. Backup will be available for some time at the 'Bitnami Legacy' repository. More info at https://github.com/bitnami/containers/issues/83267
nginx 04:30:24.12 INFO  ==> 
nginx 04:30:24.12 INFO  ==> ** Starting NGINX setup **
nginx 04:30:24.13 INFO  ==> Validating settings in NGINX_* env vars
Certificate request self-signature ok
subject=CN = example.com
nginx 04:30:24.78 INFO  ==> No custom scripts in /docker-entrypoint-initdb.d
nginx 04:30:24.78 INFO  ==> Initializing NGINX
realpath: /bitnami/nginx/conf/vhosts: No such file or directory
nginx 04:30:24.80 INFO  ==> ** NGINX setup finished! **

nginx 04:30:24.81 INFO  ==> ** Starting NGINX **
172.17.0.1 - - [25/Oct/2025:04:30:41 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.16.0" "-"

6. ์ •๋ฆฌ(์‚ญ์ œ)

1
docker rm -f nginx

๐Ÿ“ฅ Deploying a Chart from a Repository

1. ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ถ”๊ฐ€

1
2
3
4
helm repo add bitnami https://charts.bitnami.com/bitnami

# ๊ฒฐ๊ณผ
"bitnami" has been added to your repositories

2. ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋ชฉ๋ก ํ™•์ธ

1
2
3
4
helm repo list

NAME                	URL                                               
bitnami             	https://charts.bitnami.com/bitnami                

3. ์ฐจํŠธ ๊ฒ€์ƒ‰

1
2
3
4
5
6
7
8
helm search repo postgresql

NAME                                             	CHART VERSION	APP VERSION	DESCRIPTION                                       
bitnami/postgresql                               	18.1.1       	18.0.0     	PostgreSQL (Postgres) is an open source object-...
bitnami/postgresql-ha                            	16.3.2       	17.6.0     	This PostgreSQL cluster solution includes the P...
bitnami/cloudnative-pg                           	1.0.11       	1.26.1     	CloudNativePG is an open-source tool for managi...
bitnami/supabase                                 	5.3.6        	1.24.7     	DEPRECATED Supabase is an open source Firebase ...
bitnami/minio-operator                           	0.2.9        	7.1.1      	MinIO(R) Operator is a Kubernetes-native tool f...

4. ์ฐจํŠธ ๋ฐฐํฌ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
helm install my-db \
--set postgresql.postgresqlUsername=my-default,postgresql.postgresqlPassword=postgres,postgresql.postgresqlDatabase=mydb,postgresql.persistence.enabled=false \
bitnami/postgresql

# ๊ฒฐ๊ณผ
bitnami/postgresql
NAME: my-db
LAST DEPLOYED: Sat Oct 25 13:42:05 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: postgresql
CHART VERSION: 18.1.1
APP VERSION: 18.0.0
...

5. ๋ฆด๋ฆฌ์Šค ๋ชฉ๋ก ํ™•์ธ

1
2
3
4
5
6
helm list

# ๊ฒฐ๊ณผ
NAME  	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART            	APP VERSION
my-db 	default  	1       	2025-10-25 13:42:05.165856775 +0900 KST	deployed	postgresql-18.1.1	18.0.0     
pacman	default  	3       	2025-10-25 13:17:22.363146125 +0900 KST	deployed	pacman-0.1.0     	1.0.0      

6. ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋ฆฌ์†Œ์Šค ํ™•์ธ

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 sts,pod,svc,ep,secret

# ๊ฒฐ๊ณผ
NAME                                READY   AGE
statefulset.apps/my-db-postgresql   1/1     57s

NAME                          READY   STATUS    RESTARTS   AGE
pod/my-db-postgresql-0        1/1     Running   0          57s
pod/pacman-576769bb86-gvgv4   1/1     Running   0          25m

NAME                          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/kubernetes            ClusterIP   10.96.0.1      <none>        443/TCP    69m
service/my-db-postgresql      ClusterIP   10.96.175.98   <none>        5432/TCP   57s
service/my-db-postgresql-hl   ClusterIP   None           <none>        5432/TCP   57s
service/pacman                ClusterIP   10.96.36.104   <none>        8080/TCP   32m

NAME                            ENDPOINTS          AGE
endpoints/kubernetes            172.18.0.2:6443    69m
endpoints/my-db-postgresql      10.244.0.11:5432   57s
endpoints/my-db-postgresql-hl   10.244.0.11:5432   57s
endpoints/pacman                10.244.0.9:8080    32m

NAME                                  TYPE                 DATA   AGE
secret/my-db-postgresql               Opaque               1      57s
secret/sh.helm.release.v1.my-db.v1    helm.sh/release.v1   1      57s
secret/sh.helm.release.v1.pacman.v1   helm.sh/release.v1   1      32m
secret/sh.helm.release.v1.pacman.v2   helm.sh/release.v1   1      29m
secret/sh.helm.release.v1.pacman.v3   helm.sh/release.v1   1      25m

7. ์„œ๋“œ ํŒŒํ‹ฐ ์ฐจํŠธ ๊ฐ’ ํ™•์ธ ๋ฐฉ๋ฒ•

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
helm show values bitnami/postgresql

# ๊ฒฐ๊ณผ
# Copyright Broadcom, Inc. All Rights Reserved.
# SPDX-License-Identifier: APACHE-2.0

## @section Global parameters
## Please, note that this will override the parameters, including dependencies, configured to use the global value
##
global:
  ## @param global.imageRegistry Global Docker image registry
  ##
  imageRegistry: ""
  ## @param global.imagePullSecrets Global Docker registry secret names as an array
  ## e.g.
  ## imagePullSecrets:
  ##   - myRegistryKeySecretName
  ##
  imagePullSecrets: []
  ## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s)
## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead
  ##
  defaultStorageClass: ""
  storageClass: ""
  ## Security parameters
  ##
  security:
    ## @param global.security.allowInsecureImages Allows skipping image verification
    allowInsecureImages: false
  postgresql:
    ## @param global.postgresql.fullnameOverride Full chart name (overrides `fullnameOverride`)
    ## @param global.postgresql.auth.postgresPassword Password for the "postgres" admin user (overrides `auth.postgresPassword`)
    ## @param global.postgresql.auth.username Name for a custom user to create (overrides `auth.username`)
    ## @param global.postgresql.auth.password Password for the custom user to create (overrides `auth.password`)
    ## @param global.postgresql.auth.database Name for a custom database to create (overrides `auth.database`)
    ## @param global.postgresql.auth.existingSecret Name of existing secret to use for PostgreSQL credentials (overrides `auth.existingSecret`).
    ## @param global.postgresql.auth.secretKeys.adminPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.adminPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set.
    ## @param global.postgresql.auth.secretKeys.userPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.userPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set.
    ## @param global.postgresql.auth.secretKeys.replicationPasswordKey Name of key in existing secret to use for PostgreSQL credentials (overrides `auth.secretKeys.replicationPasswordKey`). Only used when `global.postgresql.auth.existingSecret` is set.
    ##
    fullnameOverride: ""
    
    auth:
      postgresPassword: ""
      username: ""
      password: ""
      database: ""
      existingSecret: ""
      secretKeys:
        adminPasswordKey: ""
        userPasswordKey: ""
        replicationPasswordKey: ""
    ## @param global.postgresql.service.ports.postgresql PostgreSQL service port (overrides `service.ports.postgresql`)
    ##
    service:
      ports:
        postgresql: ""
...
  • ๊ธฐ๋ณธ๊ฐ’๊ณผ ์˜ค๋ฒ„๋ผ์ด๋“œ ๊ฐ€๋Šฅํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง์ ‘ ํŒŒ์ผ๋กœ ๋ณด์ง€ ๋ชปํ•˜๋ฏ€๋กœ helm show values ์‚ฌ์šฉ

8. ์‹ค์Šต ํ›„ ์ œ๊ฑฐ

1
2
helm uninstall my-db
release "my-db" uninstalled

๐Ÿ” Deploying a Chart with a Dependency

1. ์ฐจํŠธ ์Šค์ผˆ๋ ˆํ†ค ์ƒ์„ฑ

1
2
3
4
cd ..
mkdir music
mkdir music/templates
cd music

2. ๋„์ „๊ณผ์ œ2. music helm ๋ฐฐํฌ ์‹คํŒจ ํ•ด๊ฒฐ

(1) Deployment ํ…œํ”Œ๋ฆฟ ์ž‘์„ฑ (DB ๋Œ€๊ธฐ ํฌํ•จ)

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
cat << 'EOF' > templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
  labels:
    app.kubernetes.io/name: 
    app.kubernetes.io/version: 
spec:
  replicas: 
  selector:
    matchLabels:
      app.kubernetes.io/name: 
  template:
    metadata:
      labels:
        app.kubernetes.io/name: 
    spec:
      initContainers:
        - name: wait-db
          image: postgres:16
          command: ["sh","-c"]
          args: ["until pg_isready -h -postgresql -p 5432 -t 5; do echo waiting for db; sleep 2; done"]
      containers:
        - image: ":"
          imagePullPolicy: 
          name: 
          ports:
            - containerPort: 
              name: http
              protocol: TCP
          env:
            - name: QUARKUS_DATASOURCE_JDBC_URL
              value: 
            - name: QUARKUS_DATASOURCE_USERNAME
              value: 
            - name: QUARKUS_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: 
                  key: 
EOF

(2) DB ์ดˆ๊ธฐํ™” Job ํ…œํ”Œ๋ฆฟ ์ž‘์„ฑ (Hook)

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
cat << 'EOF' > templates/db-init-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: -db-init
  labels:
    app.kubernetes.io/name: 
  annotations:
    "helm.sh/hook": post-install,post-upgrade
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  backoffLimit: 12
  activeDeadlineSeconds: 600
  template:
    metadata:
      labels:
        app.kubernetes.io/name: 
    spec:
      restartPolicy: OnFailure
      containers:
        - name: psql
          image: postgres:16
          env:
            - name: PGPASSWORD
              valueFrom:
                secretKeyRef:
                  name: 
                  key: 
          command: ["bash","-lc"]
          args:
            - |
              set -euo pipefail
              DBNAME=''
              PGUSER=''
              PGHOST=''
              export PGHOST PGUSER

              echo "Waiting for postgres at ${PGHOST}..."
              until pg_isready -h "${PGHOST}" -p 5432 -U "${PGUSER}" -t 5; do
                echo "postgres not ready yet, retrying..."
                sleep 2
              done

              echo "Ensuring database '${DBNAME}' on ${PGHOST} as ${PGUSER}"
              psql -tc "SELECT 1 FROM pg_database WHERE datname='${DBNAME}';" | grep -q 1 || \
              psql -c "CREATE DATABASE \"${DBNAME}\";"
EOF

(3) Service ํ…œํ”Œ๋ฆฟ ์ž‘์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat << 'EOF' > templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: 
  name: 
spec:
  ports:
    - name: http
      port: 
      targetPort: 
  selector:
    app.kubernetes.io/name: 
EOF

(4) Chart.yaml์— ์˜์กด์„ฑ ์„ ์–ธ

1
2
3
4
5
6
7
8
9
10
11
12
cat << 'EOF' > Chart.yaml
apiVersion: v2
name: music
description: A Helm chart for Music service
type: application
version: 0.1.0
appVersion: "1.0.0"
dependencies:
  - name: postgresql
    version: 18.0.17
    repository: "https://charts.bitnami.com/bitnami"
EOF

(5) values.yaml ๊ตฌ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat << 'EOF' > values.yaml
image:
  repository: quay.io/gitops-cookbook/music
  tag: "1.0.0"
  pullPolicy: Always
  containerPort: 8080

replicaCount: 1

postgresql:
  server: jdbc:postgresql://music-db-postgresql:5432/mydb
  postgresqlUsername: postgres
  postgresqlDatabase: mydb
  secretName: music-db-postgresql
  secretKey: postgres-password   # Bitnami + postgres ์‚ฌ์šฉ์ž ๊ธฐ๋ณธ ํ‚ค
EOF

3. ๋””๋ ‰ํ„ฐ๋ฆฌ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
tree
.
โ”œโ”€โ”€ Chart.yaml
โ”œโ”€โ”€ templates
โ”‚ย ย  โ”œโ”€โ”€ db-init-job.yaml
โ”‚ย ย  โ”œโ”€โ”€ deployment.yaml
โ”‚ย ย  โ””โ”€โ”€ service.yaml
โ””โ”€โ”€ values.yaml

2 directories, 5 files

4. ์˜์กด์„ฑ ๋‹ค์šด๋กœ๋“œ

1
2
3
4
5
6
7
8
9
10
11
helm dependency update

# ๊ฒฐ๊ณผ
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. โŽˆHappy Helming!โŽˆ
Saving 1 charts
Downloading postgresql from repo https://charts.bitnami.com/bitnami
Pulled: registry-1.docker.io/bitnamicharts/postgresql:18.0.17
Digest: sha256:84b63af46f41ac35e3cbcf098e8cf124211c250807cfed43f7983c39c6e30b72
Deleting outdated charts
1
2
3
4
5
6
7
8
9
10
11
12
13
tree
.
โ”œโ”€โ”€ Chart.lock
โ”œโ”€โ”€ charts
โ”‚ย ย  โ””โ”€โ”€ postgresql-18.0.17.tgz
โ”œโ”€โ”€ Chart.yaml
โ”œโ”€โ”€ templates
โ”‚ย ย  โ”œโ”€โ”€ db-init-job.yaml
โ”‚ย ย  โ”œโ”€โ”€ deployment.yaml
โ”‚ย ย  โ””โ”€โ”€ service.yaml
โ””โ”€โ”€ values.yaml

3 directories, 7 files
  • charts/postgresql-18.0.17.tgz
  • Chart.lock ์ƒ์„ฑ ๋ฐ ๋‹ค์ด์ œ์ŠคํŠธ ๊ณ ์ •

5. ๋ Œ๋” & ๋ฌธ๋ฒ• ์‚ฌ์ „๊ฒ€์ฆ(๋“œ๋ผ์ด๋Ÿฐ)

1
2
3
4
5
6
7
8
9
10
11
12
13
helm template music-db . | kubectl apply --dry-run=client -f -

# ๊ฒฐ๊ณผ
networkpolicy.networking.k8s.io/music-db-postgresql created (dry run)
poddisruptionbudget.policy/music-db-postgresql created (dry run)
serviceaccount/music-db-postgresql created (dry run)
secret/music-db-postgresql created (dry run)
service/music-db-postgresql-hl created (dry run)
service/music-db-postgresql created (dry run)
service/music created (dry run)
deployment.apps/music created (dry run)
statefulset.apps/music-db-postgresql created (dry run)
job.batch/music-db-db-init created (dry run)

6. ์„ค์น˜(๋Œ€๊ธฐ/ํƒ€์ž„์•„์›ƒ ํฌํ•จ)

1
2
3
4
5
6
7
8
9
10
helm upgrade --install music-db . --wait --timeout 5m

# ๊ฒฐ๊ณผ
Release "music-db" does not exist. Installing it now.
NAME: music-db
LAST DEPLOYED: Sat Oct 25 16:30:24 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

7. ๋ฆฌ์†Œ์Šค ์ƒํƒœ ์ ๊ฒ€

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 sts,pod,svc,ep,secret,pv,pvc

# ๊ฒฐ๊ณผ
NAME                                   READY   AGE
statefulset.apps/music-db-postgresql   1/1     50s

NAME                          READY   STATUS    RESTARTS   AGE
pod/music-6cf5758b57-qn4nl    1/1     Running   0          50s
pod/music-db-postgresql-0     1/1     Running   0          50s
pod/pacman-576769bb86-gvgv4   1/1     Running   0          3h13m

NAME                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kubernetes               ClusterIP   10.96.0.1       <none>        443/TCP    3h57m
service/music                    ClusterIP   10.96.177.103   <none>        8080/TCP   50s
service/music-db-postgresql      ClusterIP   10.96.86.68     <none>        5432/TCP   50s
service/music-db-postgresql-hl   ClusterIP   None            <none>        5432/TCP   50s
service/pacman                   ClusterIP   10.96.36.104    <none>        8080/TCP   3h20m

NAME                               ENDPOINTS          AGE
endpoints/kubernetes               172.18.0.2:6443    3h57m
endpoints/music                    10.244.0.39:8080   50s
endpoints/music-db-postgresql      10.244.0.41:5432   50s
endpoints/music-db-postgresql-hl   10.244.0.41:5432   50s
endpoints/pacman                   10.244.0.9:8080    3h20m

NAME                                    TYPE                 DATA   AGE
secret/music-db-postgresql              Opaque               1      50s
secret/sh.helm.release.v1.music-db.v1   helm.sh/release.v1   1      50s
secret/sh.helm.release.v1.pacman.v1     helm.sh/release.v1   1      3h20m
secret/sh.helm.release.v1.pacman.v2     helm.sh/release.v1   1      3h17m
secret/sh.helm.release.v1.pacman.v3     helm.sh/release.v1   1      3h13m

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pvc-7346aabd-297e-4ad8-b163-d39e97b0881d   8Gi        RWO            Delete           Bound    default/data-music-db-postgresql-0   standard       <unset>                          47s

NAME                                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/data-music-db-postgresql-0   Bound    pvc-7346aabd-297e-4ad8-b163-d39e97b0881d   8Gi        RWO            standard       <unset>                 50s

8. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™•์ธ(ํฌํŠธํฌ์›Œ๋”ฉ)

1
2
3
4
5
6
kubectl port-forward service/music 8080:8080

# ๊ฒฐ๊ณผ
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080
1
2
3
4
curl -s http://localhost:8080/song

# ๊ฒฐ๊ณผ
[{"id":1,"artist":"DT","name":"Quiero Munchies"},{"id":2,"artist":"Lin-Manuel Miranda","name":"We Don't Talk About Bruno"},{"id":3,"artist":"Imagination","name":"Just An Illusion"},{"id":4,"artist":"Txarango","name":"Tanca Els Ulls"},{"id":5,"artist":"Halsey","name":"Could Have Been Me"}]

9. ์ •๋ฆฌ(์–ธ์ธ์Šคํ†จ & ์Šคํ† ๋ฆฌ์ง€ ํ•ด์ œ)

1
2
helm uninstall music-db        
release "music-db" uninstalled
1
2
kubectl delete pvc --all
persistentvolumeclaim "data-music-db-postgresql-0" deleted from default namespace

๐Ÿ”ง Install Tekton

1. Tekton Pipeline ์„ค์น˜

1
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

2. Tekton Pipeline ์„ค์น˜ ํ™•์ธ

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

# ๊ฒฐ๊ณผ                  
NAME                                       CREATED AT
customruns.tekton.dev                      2025-10-25T07:49:14Z
pipelineruns.tekton.dev                    2025-10-25T07:49:14Z
pipelines.tekton.dev                       2025-10-25T07:49:14Z
resolutionrequests.resolution.tekton.dev   2025-10-25T07:49:14Z
stepactions.tekton.dev                     2025-10-25T07:49:14Z
taskruns.tekton.dev                        2025-10-25T07:49:15Z
tasks.tekton.dev                           2025-10-25T07:49:14Z
verificationpolicies.tekton.dev            2025-10-25T07:49:15Z
1
2
3
4
5
kubectl get ns | grep tekton

# ๊ฒฐ๊ณผ
tekton-pipelines             Active   86s
tekton-pipelines-resolvers   Active   85s
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
kubectl get all -n tekton-pipelines

# ๊ฒฐ๊ณผ
NAME                                               READY   STATUS    RESTARTS   AGE
pod/tekton-events-controller-99665746c-6qhvv       1/1     Running   0          2m27s
pod/tekton-pipelines-controller-7595d6585d-hg2lh   1/1     Running   0          2m27s
pod/tekton-pipelines-webhook-5967d74cc4-w2vpv      1/1     Running   0          2m27s

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                              AGE
service/tekton-events-controller      ClusterIP   10.96.175.34    <none>        9090/TCP,8008/TCP,8080/TCP           2m27s
service/tekton-pipelines-controller   ClusterIP   10.96.150.58    <none>        9090/TCP,8008/TCP,8080/TCP           2m27s
service/tekton-pipelines-webhook      ClusterIP   10.96.125.255   <none>        9090/TCP,8008/TCP,443/TCP,8080/TCP   2m27s

NAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tekton-events-controller      1/1     1            1           2m27s
deployment.apps/tekton-pipelines-controller   1/1     1            1           2m27s
deployment.apps/tekton-pipelines-webhook      1/1     1            1           2m27s

NAME                                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/tekton-events-controller-99665746c       1         1         1       2m27s
replicaset.apps/tekton-pipelines-controller-7595d6585d   1         1         1       2m27s
replicaset.apps/tekton-pipelines-webhook-5967d74cc4      1         1         1       2m27s

NAME                                                           REFERENCE                             TARGETS               MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook   Deployment/tekton-pipelines-webhook   cpu: <unknown>/100%   1         5         1          2m27s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl get all -n tekton-pipelines-resolvers

# ๊ฒฐ๊ณผ
NAME                                                     READY   STATUS    RESTARTS   AGE
pod/tekton-pipelines-remote-resolvers-86f56b6664-frrqj   1/1     Running   0          3m11s

NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/tekton-pipelines-remote-resolvers   ClusterIP   10.96.172.248   <none>        9090/TCP,8008/TCP,8080/TCP   3m11s

NAME                                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tekton-pipelines-remote-resolvers   1/1     1            1           3m11s

NAME                                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/tekton-pipelines-remote-resolvers-86f56b6664   1         1         1       3m11s
1
2
3
4
5
6
7
kubectl get pod -n tekton-pipelines

# ๊ฒฐ๊ณผ
NAME                                           READY   STATUS    RESTARTS   AGE
tekton-events-controller-99665746c-6qhvv       1/1     Running   0          3m30s
tekton-pipelines-controller-7595d6585d-hg2lh   1/1     Running   0          3m30s
tekton-pipelines-webhook-5967d74cc4-w2vpv      1/1     Running   0          3m30s

3. Tekton Triggers ์„ค์น˜

1
2
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml

4. Tekton Trigger ์„ค์น˜ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
kubectl get crd | grep triggers

# ๊ฒฐ๊ณผ
clusterinterceptors.triggers.tekton.dev      2025-10-25T07:53:44Z
clustertriggerbindings.triggers.tekton.dev   2025-10-25T07:53:44Z
eventlisteners.triggers.tekton.dev           2025-10-25T07:53:44Z
interceptors.triggers.tekton.dev             2025-10-25T07:53:44Z
triggerbindings.triggers.tekton.dev          2025-10-25T07:53:44Z
triggers.triggers.tekton.dev                 2025-10-25T07:53:44Z
triggertemplates.triggers.tekton.dev         2025-10-25T07:53:44Z
1
2
3
4
5
6
kubectl get deploy -n tekton-pipelines | grep triggers

# ๊ฒฐ๊ณผ
tekton-triggers-controller          1/1     1            1           89s
tekton-triggers-core-interceptors   1/1     1            1           88s
tekton-triggers-webhook             1/1     1            1           89s

5. Tekton Dashboard ์„ค์น˜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
kubectl apply -f https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml

# ๊ฒฐ๊ณผ
customresourcedefinition.apiextensions.k8s.io/extensions.dashboard.tekton.dev created
serviceaccount/tekton-dashboard created
role.rbac.authorization.k8s.io/tekton-dashboard-info created
clusterrole.rbac.authorization.k8s.io/tekton-dashboard-backend-edit created
clusterrole.rbac.authorization.k8s.io/tekton-dashboard-backend-view created
clusterrole.rbac.authorization.k8s.io/tekton-dashboard-tenant-view created
rolebinding.rbac.authorization.k8s.io/tekton-dashboard-info created
clusterrolebinding.rbac.authorization.k8s.io/tekton-dashboard-backend-view created
configmap/dashboard-info created
service/tekton-dashboard created
deployment.apps/tekton-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/tekton-dashboard-tenant-view created
clusterrolebinding.rbac.authorization.k8s.io/tekton-dashboard-pipelines-view created
clusterrolebinding.rbac.authorization.k8s.io/tekton-dashboard-triggers-view created

6. Tekton Dashboard ์ƒํƒœ ํ™•์ธ

1
2
3
kubectl get crd | grep dashboard

extensions.dashboard.tekton.dev              2025-10-25T07:56:57Z
1
2
3
4
5
kubectl get deploy -n tekton-pipelines
                
NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
tekton-dashboard                    1/1     1            1           80s
...
1
2
3
4
5
6
kubectl get svc,ep -n tekton-pipelines tekton-dashboard
NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/tekton-dashboard   ClusterIP   10.96.31.229   <none>        9097/TCP   2m5s

NAME                         ENDPOINTS          AGE
endpoints/tekton-dashboard   10.244.0.51:9097   2m5s
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
kubectl get svc -n tekton-pipelines tekton-dashboard -o yaml | kubectl neat | yq
{
  "apiVersion": "v1",
  "kind": "Service",
  "metadata": {
    "labels": {
      "app": "tekton-dashboard",
      "app.kubernetes.io/component": "dashboard",
      "app.kubernetes.io/instance": "default",
      "app.kubernetes.io/name": "dashboard",
      "app.kubernetes.io/part-of": "tekton-dashboard",
      "app.kubernetes.io/version": "v0.62.0",
      "dashboard.tekton.dev/release": "v0.62.0",
      "version": "v0.62.0"
    },
    "name": "tekton-dashboard",
    "namespace": "tekton-pipelines"
  },
  "spec": {
    "clusterIP": "10.96.31.229",
    "clusterIPs": [
      "10.96.31.229"
    ],
    "ipFamilies": [
      "IPv4"
    ],
    "ipFamilyPolicy": "SingleStack",
    "ports": [
      {
        "name": "http",
        "port": 9097
      }
    ],
    "selector": {
      "app.kubernetes.io/component": "dashboard",
      "app.kubernetes.io/instance": "default",
      "app.kubernetes.io/name": "dashboard",
      "app.kubernetes.io/part-of": "tekton-dashboard"
    }
  }
}

7. Tekton Dashboard NodePort ๋…ธ์ถœ

1
2
3
4
kubectl patch svc -n tekton-pipelines tekton-dashboard -p '{"spec":{"type":"NodePort","ports":[{"port":9097,"targetPort":9097,"nodePort":30000}]}}'

# ๊ฒฐ๊ณผ
service/tekton-dashboard patched
1
2
3
4
5
6
7
8
kubectl get svc,ep -n tekton-pipelines tekton-dashboard

# ๊ฒฐ๊ณผ
NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/tekton-dashboard   NodePort   10.96.31.229   <none>        9097:30000/TCP   7m10s

NAME                         ENDPOINTS          AGE
endpoints/tekton-dashboard   10.244.0.51:9097   7m10s
  • 9097:30000/TCP

http://localhost:30000๋กœ ๋Œ€์‹œ๋ณด๋“œ ์ ‘๊ทผ

8. Tekton CLI ์„ค์น˜(Arch Linux)

1
2
3
4
5
6
7
8
sudo pacman -Syu tekton-cli
tkn version

# ๊ฒฐ๊ณผ
Client version: 0.33.0
Pipeline version: v1.5.0
Triggers version: v0.33.0
Dashboard version: v0.62.0

๐Ÿ‘‹ Create a Hello World Task

1. Task ๋ฆฌ์†Œ์Šค ์ŠคํŽ™ ํ™•์ธ

1
2
3
4
5
6
7
kubectl explain tasks.tekton.dev

# ๊ฒฐ๊ณผ
GROUP:      tekton.dev
KIND:       Task
VERSION:    v1
...

2. Task ์ƒ์„ฑ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat << EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: hello
spec:
  steps:
    - name: echo    # step ์ด๋ฆ„
      image: alpine # step ์ˆ˜ํ–‰ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€
      script: |
        #!/bin/sh
        echo "Hello World"
EOF

# ๊ฒฐ๊ณผ
task.tekton.dev/hello created

3. Task ๋ชฉ๋ก ํ™•์ธ

1
2
3
4
5
tkn task list

# ๊ฒฐ๊ณผ
NAME    DESCRIPTION   AGE
hello                 35 seconds ago

4. ์ƒ์„ฑ ๋ฆฌ์†Œ์Šค ํ™•์ธ(JSON/YAML)

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 tasks -o yaml | kubectl neat | yq

{
  "apiVersion": "v1",
  "items": [
    {
      "apiVersion": "tekton.dev/v1",
      "kind": "Task",
      "metadata": {
        "name": "hello",
        "namespace": "default"
      },
      "spec": {
        "steps": [
          {
            "image": "alpine",
            "name": "echo",
            "script": "#!/bin/sh\necho \"Hello World\"\n"
          }
        ]
      }
    }
  ],
  "kind": "List",
  "metadata": {}
}

5. ๋Œ€์‹œ๋ณด๋“œ์—์„œ Task ํ™•์ธ

6. ํŒŒ๋“œ ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง

1
kubectl get pod -w

7. Task ์‹คํ–‰ (tkn)

1
tkn task start --showlog hello

โœ…ย ์ถœ๋ ฅ

1
2
3
TaskRun started: hello-run-zmcrx
Waiting for logs to be available...
[echo] Hello World

8. ํŒŒ๋“œ ์ƒ์„ธ(Init ์ปจํ…Œ์ด๋„ˆ ํฌํ•จ)

1
kubectl describe pod -l tekton.dev/task=hello

โœ…ย ์ถœ๋ ฅ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Init Containers:
  prepare:
    Container ID:  containerd://d1808b262006d24f4087ea30b11f89749d4e1c88d5bae6277fe4ef615c93a359
    Image:         ghcr.io/tektoncd/pipeline/entrypoint-bff0a22da108bc2f16c818c97641a296:v1.5.0@sha256:ff5ee925ff7b08853cc4caa93e5e3e0ee761a2db6ae0a1ae6a0f6f120f170b56
    ...
  place-scripts:
    Container ID:  containerd://fea7fa128981845f6446c722a799d549473ed41bce1407d9c5fbfd8b16d298bd
    Image:         cgr.dev/chainguard/busybox@sha256:19f02276bf8dbdd62f069b922f10c65262cc34b710eea26ff928129a736be791
    ...
Containers:
  step-echo:
    Container ID:  containerd://141ca7131e149fc96b3b6aea900d519ae2517b0e7a14652f653d041cf1abec11
    Image:         alpine
    Image ID:      docker.io/library/alpine@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412

9. ์ปจํ…Œ์ด๋„ˆ๋ณ„ ๋กœ๊ทธ ์ ๊ฒ€

1
2
3
4
5
6
7
8
kubectl logs -l tekton.dev/task=hello -c prepare
2025/10/25 08:32:54 Entrypoint initialization

kubectl logs -l tekton.dev/task=hello -c place-scripts
2025/10/25 08:32:57 Decoded script /tekton/scripts/script-0-h8svq

kubectl logs -l tekton.dev/task=hello -c step-echo
Hello World

10. tkn ๋กœ๊ทธ/์„ค๋ช… ๋ช…๋ น ํ™œ์šฉ

1
2
3
4
tkn task logs hello

# ๊ฒฐ๊ณผ
Hello World
1
2
3
4
5
6
7
8
9
10
11
12
13
14
tkn task describe hello

# ๊ฒฐ๊ณผ
Name:        hello
Namespace:   default

๐Ÿฆถ Steps

 โˆ™ echo

๐Ÿ—‚  Taskruns

NAME              STARTED         DURATION   STATUS
hello-run-zmcrx   6 minutes ago   16s        Succeeded

๐Ÿ—‚๏ธ Create a Task to Compile and Package an App from Git

  • https://tekton.dev/docs/how-to-guides/clone-repository/

1. ํŒŒ์ดํ”„๋ผ์ธ ํŒŒ์ผ ์ž‘์„ฑ

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: tekton.dev/v1
kind: Pipeline
metadata:
  name: clone-read
spec:
  description: | 
    This pipeline clones a git repo, then echoes the README file to the stout.
  params:     # ๋งค๊ฐœ๋ณ€์ˆ˜ repo-url
  - name: repo-url
    type: string
    description: The git repo URL to clone from.
  workspaces: # ๋‹ค์šด๋กœ๋“œํ•  ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•  ๊ณต์œ  ๋ณผ๋ฅจ์ธ ์ž‘์—… ๊ณต๊ฐ„์„ ์ถ”๊ฐ€
  - name: shared-data
    description: | 
      This workspace contains the cloned repo files, so they can be read by the
      next task.
  tasks:      # task ์ •์˜
  - name: fetch-source
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    params:
    - name: url
      value: \$(params.repo-url)
EOF

# ๊ฒฐ๊ณผ
pipeline.tekton.dev/clone-read created

2. ํŒŒ์ดํ”„๋ผ์ธ ์ƒ์„ฑ ํ™•์ธ

1
2
3
4
5
tkn pipeline list

# ๊ฒฐ๊ณผ
NAME         AGE              LAST RUN   STARTED   DURATION   STATUS
clone-read   32 seconds ago   ---        ---       ---        ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
tkn pipeline describe

# ๊ฒฐ๊ณผ
Name:          clone-read
Namespace:     default
Description:   This pipeline clones a git repo, then echoes the README file to the stout.

โš“ Params

 NAME         TYPE     DESCRIPTION              DEFAULT VALUE
 โˆ™ repo-url   string   The git repo URL to...   ---

๐Ÿ“‚ Workspaces

 NAME            DESCRIPTION              OPTIONAL
 โˆ™ shared-data   This workspace cont...   false

๐Ÿ—’  Tasks

 NAME             TASKREF     RUNAFTER   TIMEOUT   PARAMS
 โˆ™ fetch-source   git-clone              ---       url: string

3. PipelineRun ์ƒ์„ฑ(์‹คํ–‰ ์ธ์Šคํ„ด์Šคํ™”)

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
cat << EOF | kubectl create -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: clone-read-run-
spec:
  pipelineRef:
    name: clone-read
  taskRunTemplate:
    podTemplate:
      securityContext:
        fsGroup: 65532
  workspaces: # ์ž‘์—… ๊ณต๊ฐ„ ์ธ์Šคํ„ด์Šคํ™”, PVC ์ƒ์„ฑ
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
  params:    # ์ €์žฅ์†Œ URL ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’ ์„ค์ •
  - name: repo-url
    value: https://github.com/tektoncd/website
EOF

# ๊ฒฐ๊ณผ
pipelinerun.tekton.dev/clone-read-run-g89cg created

4. ์ดˆ๊ธฐ ์‹คํŒจ ์ง„๋‹จ

1
2
3
kubectl get pipelineruns
NAME                   SUCCEEDED   REASON           STARTTIME   COMPLETIONTIME
clone-read-run-g89cg   False       CouldntGetTask   2m10s       2m10s
1
2
3
tkn pipelinerun list
NAME                   STARTED         DURATION   STATUS
clone-read-run-g89cg   2 minutes ago   0s         Failed(CouldntGetTask)
1
2
3
4
tkn pipelinerun logs clone-read-run-g89cg

# ๊ฒฐ๊ณผ
Pipeline default/clone-read can't be Run; it contains Tasks that don't exist: Couldn't retrieve Task "git-clone": tasks.tekton.dev "git-clone" not found
  • ํŒŒ์ดํ”„๋ผ์ธ์ด ์ฐธ์กฐํ•˜๋Š” git-clone Task๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฏธ์„ค์น˜

5. ๋ˆ„๋ฝ Task ์„ค์น˜(ํ…Œํฌํ†ค ํ—ˆ๋ธŒ)

1
2
3
4
5
tkn hub install task git-clone

# ๊ฒฐ๊ณผ
WARN: This version has been deprecated
Task git-clone(0.9) installed in default namespace
1
2
3
4
5
6
kubectl get tasks

# ๊ฒฐ๊ณผ
NAME        AGE
git-clone   27s
hello       28m

6. PipelineRun ์žฌ์‹คํ–‰

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
cat << EOF | kubectl create -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: clone-read-run-
spec:
  pipelineRef:
    name: clone-read
  taskRunTemplate:
    podTemplate:
      securityContext:
        fsGroup: 65532
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
  params:
  - name: repo-url
    value: https://github.com/tektoncd/website
EOF

# ๊ฒฐ๊ณผ
pipelinerun.tekton.dev/clone-read-run-6zd5t created

7. ์‹คํ–‰ ์‚ฐ์ถœ๋ฌผ/์Šคํ† ๋ฆฌ์ง€ ํ™•์ธ

1
2
3
4
5
6
7
8
9
10
11
12
kubectl get pod,pv,pvc

# ๊ฒฐ๊ณผ
NAME                                        READY   STATUS      RESTARTS   AGE
pod/clone-read-run-6zd5t-fetch-source-pod   0/1     Completed   0          115s
pod/hello-run-zmcrx-pod                     0/1     Completed   0          27m

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pvc-bc02a33b-e54e-458e-a411-db06ca17bed0   1Gi        RWO            Delete           Bound    default/pvc-55505f842f   standard       <unset>                          112s

NAME                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/pvc-55505f842f   Bound    pvc-bc02a33b-e54e-458e-a411-db06ca17bed0   1Gi        RWO            standard       <unset>                 115s
This post is licensed under CC BY 4.0 by the author.