๐ง ์ค์ตํ๊ฒฝ ๊ตฌ์ฑ
1. docker-compose-plugin ์ค์น - x86_64
1
2
3
4
| sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
docker compose version
|
2. ์์
๋๋ ํ ๋ฆฌ ์์ฑ ํ ์ด๋
1
2
| mkdir cicd-labs
cd cicd-labs
|
3. Docker Compose ํ์ผ ์์ฑ ํ์ผ ์์ฑ
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
| cat <<EOT > docker-compose.yaml
services:
jenkins:
container_name: jenkins
image: jenkins/jenkins
restart: unless-stopped
networks:
- cicd-network
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- jenkins_home:/var/jenkins_home
gogs:
container_name: gogs
image: gogs/gogs
restart: unless-stopped
networks:
- cicd-network
ports:
- "10022:22"
- "3000:3000"
volumes:
- gogs-data:/data
volumes:
jenkins_home:
gogs-data:
networks:
cicd-network:
driver: bridge
EOT
|
4. Docker Compose ์คํ
โ
ย ์ถ๋ ฅ
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
| [+] Running 21/21
โ jenkins Pulled 20.4s
โ 7cd785773db4 Pull complete 9.6s
โ 4323b613447d Pull complete 11.4s
โ eec1952536a9 Pull complete 11.6s
โ b9fcd549558d Pull complete 11.6s
โ 743c1c69eb66 Pull complete 11.6s
โ 2b005e8acf52 Pull complete 15.3s
โ e7e22a1da8f6 Pull complete 15.4s
โ 5daee7ea5eb6 Pull complete 15.5s
โ bbb418a8a466 Pull complete 17.0s
โ ccfc3f9a95cb Pull complete 17.0s
โ b6a32e0eef53 Pull complete 17.0s
โ 5faefa2d0cdc Pull complete 17.0s
โ gogs Pulled 22.8s
โ f18232174bc9 Pull complete 14.2s
โ b6b017e7a7f5 Pull complete 16.8s
โ c80b57c5e4ee Pull complete 16.8s
โ 1760f004baf4 Pull complete 16.8s
โ 629cc8eb21da Pull complete 16.9s
โ 894de22ca6a0 Pull complete 19.3s
โ af5aa0b7df25 Pull complete 19.4s
[+] Running 5/5
โ Network cicd-labs_cicd-network Created 0.0s
โ Volume "cicd-labs_gogs-data" Created 0.0s
โ Volume "cicd-labs_jenkins_home" Created 0.0s
โ Container gogs Started 0.2s
โ Container jenkins Started 0.2s
|
5. ์ปจํ
์ด๋ ์ํ ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
| NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
gogs gogs/gogs "/app/gogs/docker/stโฆ" gogs 12 seconds ago Up 12 seconds (health: starting) 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp, 0.0.0.0:10022->22/tcp, [::]:10022->22/tcp
jenkins jenkins/jenkins "/usr/bin/tini -- /uโฆ" jenkins 12 seconds ago Up 12 seconds 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp
|
6. ์ปจํ
์ด๋ ๊ธฐ๋ณธ ์ ๋ณด ํ์ธ
1
| for i in gogs jenkins ; do echo ">> container : $i <<"; docker compose exec $i sh -c "whoami && pwd"; echo; done
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
| >> container : gogs <<
root
/app/gogs
>> container : jenkins <<
jenkins
/
|
7. ์ปจํ
์ด๋ ๋ด๋ถ ์ ์ ๋ฐ ์ข
๋ฃ
1
2
3
4
| docker compose exec jenkins bash
jenkins@12f4b7ed7515:/$ exit
exit
|
1
2
3
4
| docker compose exec gogs bash
a0dda4a63d1b:/app/gogs# exit
exit
|
8. Jenkins ์ด๊ธฐ ์ํธ ํ์ธ
1
| docker compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
|
โ
ย ์ถ๋ ฅ
1
| 57a5b0cc2ff2402ba1ccb00d8fda37f0
|
9. Jenkins ์น ์ด๊ธฐ ์ค์ ์งํ
(1) http://127.0.0.1:8080 ์ ์ ํ, ์ด๊ธฐ ์ํธ ์
๋ ฅ
(2) Install suggested plugins
(3) ๊ธฐ๋ณธ ๊ด๋ฆฌ์ ๊ณ์ (admin / qwe123) ์ค์
(4) IP ํ์ธ ๋ฐ ์ค์
1
| ifconfig | grep 192.168.
|
โ
ย ์ถ๋ ฅ
1
2
| inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
inet 192.168.219.103 netmask 255.255.255.0 broadcast 192.168.219.255
|
(5) http://192.168.219.103:8080 ์ ์ ํ, ๋ก๊ทธ์ธ (admin / qwe123)
๐ณ Jenkins ์ปจํ
์ด๋์์ ํธ์คํธ์ ๋์ปค ๋ฐ๋ชฌ ์ฌ์ฉ ์ค์
1. Jenkins ์ปจํ
์ด๋์ root ๊ด๋ฆฌ์ ๊ถํ์ผ๋ก ์ ์
1
2
3
4
| docker compose exec --privileged -u root jenkins bash
# ๊ฒฐ๊ณผ
root@12f4b7ed7515:/#
|
2. Docker CLI ์ค์น ๋ฐ ํ๊ฒฝ ๊ตฌ์ฑ
1
2
3
4
5
6
7
8
9
| root@12f4b7ed7515:/# id
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update && apt install docker-ce-cli curl tree jq yq -y
|
โ
ย ์ถ๋ ฅ
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
75
76
| uid=0(root) gid=0(root) groups=0(root)
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Get:4 https://download.docker.com/linux/debian bookworm InRelease [47.0 kB]
Get:5 http://deb.debian.org/debian bookworm/main amd64 Packages [8792 kB]
Get:6 https://download.docker.com/linux/debian bookworm/stable amd64 Packages [38.1 kB]
Get:7 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [512 B]
Get:8 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [250 kB]
Fetched 9382 kB in 1s (7293 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
curl is already the newest version (7.88.1-10+deb12u12).
The following additional packages will be installed:
docker-buildx-plugin docker-compose-plugin libjq1 libnsl2 libonig5 libpython3-stdlib libpython3.11-minimal libpython3.11-stdlib
libtirpc-common libtirpc3 libyaml-0-2 media-types python3 python3-argcomplete python3-importlib-metadata python3-minimal
python3-more-itertools python3-toml python3-typing-extensions python3-xmltodict python3-yaml python3-zipp python3.11 python3.11-minimal
Suggested packages:
python3-doc python3-tk python3-venv python3.11-venv python3.11-doc binutils binfmt-support
The following NEW packages will be installed:
docker-buildx-plugin docker-ce-cli docker-compose-plugin jq libjq1 libnsl2 libonig5 libpython3-stdlib libpython3.11-minimal
libpython3.11-stdlib libtirpc-common libtirpc3 libyaml-0-2 media-types python3 python3-argcomplete python3-importlib-metadata python3-minimal
python3-more-itertools python3-toml python3-typing-extensions python3-xmltodict python3-yaml python3-zipp python3.11 python3.11-minimal tree
yq
0 upgraded, 28 newly installed, 0 to remove and 1 not upgraded.
Need to get 71.5 MB of archives.
After this operation, 240 MB of additional disk space will be used.
Get:1 http://deb.debian.org/debian bookworm/main amd64 libpython3.11-minimal amd64 3.11.2-6+deb12u5 [816 kB]
Get:2 https://download.docker.com/linux/debian bookworm/stable amd64 docker-buildx-plugin amd64 0.22.0-1~debian.12~bookworm [35.3 MB]
Get:3 http://deb.debian.org/debian bookworm/main amd64 python3.11-minimal amd64 3.11.2-6+deb12u5 [2067 kB]
Get:4 http://deb.debian.org/debian bookworm/main amd64 python3-minimal amd64 3.11.2-1+b1 [26.3 kB]
Get:5 http://deb.debian.org/debian bookworm/main amd64 media-types all 10.0.0 [26.1 kB]
Get:6 http://deb.debian.org/debian bookworm/main amd64 libtirpc-common all 1.3.3+ds-1 [14.0 kB]
Get:7 http://deb.debian.org/debian bookworm/main amd64 libtirpc3 amd64 1.3.3+ds-1 [85.2 kB]
Get:8 http://deb.debian.org/debian bookworm/main amd64 libnsl2 amd64 1.3.0-2 [39.5 kB]
Get:9 http://deb.debian.org/debian bookworm/main amd64 libpython3.11-stdlib amd64 3.11.2-6+deb12u5 [1797 kB]
Get:10 http://deb.debian.org/debian bookworm/main amd64 python3.11 amd64 3.11.2-6+deb12u5 [573 kB]
Get:11 http://deb.debian.org/debian bookworm/main amd64 libpython3-stdlib amd64 3.11.2-1+b1 [9312 B]
Get:12 http://deb.debian.org/debian bookworm/main amd64 python3 amd64 3.11.2-1+b1 [26.3 kB]
Get:13 http://deb.debian.org/debian bookworm/main amd64 libonig5 amd64 6.9.8-1 [188 kB]
Get:14 http://deb.debian.org/debian bookworm/main amd64 libjq1 amd64 1.6-2.1 [135 kB]
Get:15 http://deb.debian.org/debian bookworm/main amd64 jq amd64 1.6-2.1 [64.9 kB]
Get:16 http://deb.debian.org/debian bookworm/main amd64 libyaml-0-2 amd64 0.2.5-1 [53.6 kB]
Get:17 http://deb.debian.org/debian bookworm/main amd64 python3-typing-extensions all 4.4.0-1 [45.2 kB]
Get:18 http://deb.debian.org/debian bookworm/main amd64 python3-more-itertools all 8.10.0-2 [53.0 kB]
Get:19 http://deb.debian.org/debian bookworm/main amd64 python3-zipp all 1.0.0-6 [6696 B]
Get:20 http://deb.debian.org/debian bookworm/main amd64 python3-importlib-metadata all 4.12.0-1 [24.9 kB]
Get:21 http://deb.debian.org/debian bookworm/main amd64 python3-argcomplete all 2.0.0-1 [34.7 kB]
Get:22 http://deb.debian.org/debian bookworm/main amd64 python3-toml all 0.10.2-1 [16.2 kB]
Get:23 http://deb.debian.org/debian bookworm/main amd64 python3-xmltodict all 0.13.0-1 [16.7 kB]
Get:24 http://deb.debian.org/debian bookworm/main amd64 python3-yaml amd64 6.0-3+b2 [119 kB]
Get:25 http://deb.debian.org/debian bookworm/main amd64 tree amd64 2.1.0-1 [52.5 kB]
Get:26 http://deb.debian.org/debian bookworm/main amd64 yq all 3.1.0-3 [19.2 kB]
Get:27 https://download.docker.com/linux/debian bookworm/stable amd64 docker-ce-cli amd64 5:28.0.4-1~debian.12~bookworm [15.8 MB]
Get:28 https://download.docker.com/linux/debian bookworm/stable amd64 docker-compose-plugin amd64 2.34.0-1~debian.12~bookworm [14.1 MB]
Fetched 71.5 MB in 4s (18.9 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libpython3.11-minimal:amd64.
(Reading database ... 10537 files and directories currently installed.)
Preparing to unpack .../libpython3.11-minimal_3.11.2-6+deb12u5_amd64.deb ...
Unpacking libpython3.11-minimal:amd64 (3.11.2-6+deb12u5) ...
Selecting previously unselected package python3.11-minimal.
Preparing to unpack .../python3.11-minimal_3.11.2-6+deb12u5_amd64.deb ...
Unpacking python3.11-minimal (3.11.2-6+deb12u5) ...
Setting up libpython3.11-minimal:amd64 (3.11.2-6+deb12u5) ...
Setting up python3.11-minimal (3.11.2-6+deb12u5) ...
Selecting previously unselected package python3-minimal.
(Reading database ... 10844 files and directories currently installed.)
Preparing to unpack .../0-python3-minimal_3.11.2-1+b1_amd64.deb ...
Unpacking python3-minimal (3.11.2-1+b1) ...
Selecting previously unselected package media-types.
Preparing to unpack .../1-media-types_10.0.0_all.deb ...
Unpacking media-types (10.0.0) ...
....
|
3. ์ค์น ํ์ธ ๋ฐ ๋์ปค ์ ๋ณด ๊ฒ์ฆ
(1) ๋์ปค ํด๋ผ์ด์ธํธ ๋ฐ ์๋ฒ ์ ๋ณด ํ์ธ
1
| root@12f4b7ed7515:/# docker info
|
โ
ย ์ถ๋ ฅ
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
| Client: Docker Engine - Community
Version: 28.0.4
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.22.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.34.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 5
Running: 5
Paused: 0
Stopped: 0
Images: 6
Server Version: 28.0.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: true
Native Overlay Diff: false
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 1a43cb6a1035441f9aca8f5666a9b3ef9e70ab20.m
runc version:
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.13.7-arch1-1
Operating System: Arch Linux
OSType: linux
Architecture: x86_64
CPUs: 18
Total Memory: 30.9GiB
Name: gram88
ID: 7b6ceb90-0683-4037-a905-12f0f9197c48
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
::1/128
127.0.0.0/8
Live Restore Enabled: false
|
(2) ์คํ ์ค์ธ ์ปจํ
์ด๋ ๋ชฉ๋ก ์กฐํ
1
| root@12f4b7ed7515:/# docker ps
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
| CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
12f4b7ed7515 jenkins/jenkins "/usr/bin/tini -- /uโฆ" 25 minutes ago Up 25 minutes 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp jenkins
a0dda4a63d1b gogs/gogs "/app/gogs/docker/stโฆ" 25 minutes ago Up 25 minutes (healthy) 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp, 0.0.0.0:10022->22/tcp, [::]:10022->22/tcp gogs
0730dcf6eb6f kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 50 minutes myk8s-worker
720250bf1479 kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 50 minutes myk8s-worker2
12914ca62737 kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 50 minutes 0.0.0.0:30000-30002->30000-30002/tcp, 127.0.0.1:44509->6443/tcp myk8s-control-plane
|
(3) ๋์ปค ์คํ ํ์ผ ์์น ํ์ธ
1
| root@12f4b7ed7515:/# which docker
|
โ
ย ์ถ๋ ฅ
4. Jenkins ์ ์ ์ ๋ํ Docker ์คํ ๊ถํ ๋ถ์ฌ
1
2
3
4
5
6
7
8
9
10
11
12
13
| root@12f4b7ed7515:/# groupadd -g 1001 -f docker
root@12f4b7ed7515:/# chgrp docker /var/run/docker.sock
root@12f4b7ed7515:/# ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 Mar 29 02:44 /var/run/docker.sock
root@12f4b7ed7515:/# usermod -aG docker jenkins
root@12f4b7ed7515:/# cat /etc/group | grep docker
docker:x:1001:jenkins
root@12f4b7ed7515:/# exit
exit
|
5. Jenkins ์ปจํ
์ด๋ ์ฌ๊ธฐ๋
1
| docker compose restart jenkins
|
โ
ย ์ถ๋ ฅ
1
2
| [+] Restarting 1/1
โ Container jenkins Started
|
6. Jenkins ์ปจํ
์ด๋ ๋ด ๋์ปค ํ๊ฒฝ ์ํ ๋ฐ ์ฌ์ฉ์ ๊ถํ ์ ๊ฒ
(1) Jenkins ์ปจํ
์ด๋ ๋ด๋ถ ์ฌ์ฉ์ ๋ฐ ๊ถํ ํ์ธ
1
| docker compose exec jenkins id
|
โ
ย ์ถ๋ ฅ
1
| uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins),1001(docker)
|
(2) ๋์ปค ์ ๋ณด ํ์ธ
1
| docker compose exec jenkins docker info
|
โ
ย ์ถ๋ ฅ
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
| Client: Docker Engine - Community
Version: 28.0.4
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.22.0
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.34.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 5
Running: 5
Paused: 0
Stopped: 0
Images: 6
Server Version: 28.0.4
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: true
Native Overlay Diff: false
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 1a43cb6a1035441f9aca8f5666a9b3ef9e70ab20.m
runc version:
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.13.8-arch1-1
Operating System: Arch Linux
OSType: linux
Architecture: x86_64
CPUs: 18
Total Memory: 30.9GiB
Name: gram88
ID: 7b6ceb90-0683-4037-a905-12f0f9197c48
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
::1/128
127.0.0.0/8
Live Restore Enabled: false
|
(3) ์คํ ์ค์ธ ์ปจํ
์ด๋ ๋ชฉ๋ก ํ์ธ
1
| docker compose exec jenkins docker ps
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
| CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
12f4b7ed7515 jenkins/jenkins "/usr/bin/tini -- /uโฆ" About an hour ago Up About a minute 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp jenkins
a0dda4a63d1b gogs/gogs "/app/gogs/docker/stโฆ" About an hour ago Up 5 minutes (healthy) 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp, 0.0.0.0:10022->22/tcp, [::]:10022->22/tcp gogs
0730dcf6eb6f kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 5 minutes myk8s-worker
720250bf1479 kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 5 minutes myk8s-worker2
12914ca62737 kindest/node:v1.30.4 "/usr/local/bin/entrโฆ" 2 days ago Up 5 minutes 0.0.0.0:30000-30002->30000-30002/tcp, 127.0.0.1:44509->6443/tcp myk8s-control-plane
|
7. Gogs ์ด๊ธฐ ์ค์น ์ ์ (http://127.0.0.1:3000/install)
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ํ: SQLite3
์ ํ๋ฆฌ์ผ์ด์
URL: 192.168.219.103
๊ด๋ฆฌ์ ๊ณ์ : devops
/ qwe123
8. Gogs ํ ํฐ ์์ฑ ๋ฐ ์ค์
9. ๋ ๊ฐ์ ๋ ํฌ์งํ ๋ฆฌ ์์ฑ ๋ฐ ์ค์
๐ Gogs ์ค์ต์ ์ํ ์ ์ฅ์ ์ค์
1. ํ๊ฒฝ ๋ณ์ ์ค์
1
2
3
4
5
| TOKEN=<๊ฐ์ Gogs Token>
TOKEN=fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04
MyIP=<๊ฐ์ ์์ ์ PC IP>
MyIP=192.168.219.103
|
2. ๊ฐ๋ฐํ์ฉ ์ ์ฅ์ ํด๋ก ๋ฐ Git ์ด๊ธฐ ์ค์
(1) Gogs์ ์์ฑ๋ ๊ฐ๋ฐํ์ฉ ์ ์ฅ์(dev-app) ํด๋ก
1
2
3
4
5
6
7
8
9
| git clone http://devops:$TOKEN@$MyIP:3000/devops/dev-app.git
# ๊ฒฐ๊ณผ
Cloning into 'dev-app'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (4/4), 692 bytes | 692.00 KiB/s, done.
|
(2) ํด๋ก ํ ์์
๋๋ ํ ๋ฆฌ๋ก ์ด๋
(3) ๋ก์ปฌ Git ์ค์ ๋ณ๊ฒฝ
1
2
3
4
5
6
| git --no-pager config --local --list
git config --local user.name "devops"
git config --local user.email "abc@abc.com"
git config --local init.defaultBranch main
git config --local credential.helper store
git --no-pager config --local --list
|
(4) .git/config
ํ์ผ ํ์ธ
โ
ย ์ถ๋ ฅ
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
| core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=http://devops:fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04@192.168.219.103:3000/devops/dev-app.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=http://devops:fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04@192.168.219.103:3000/devops/dev-app.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
user.name=devops
user.email=abc@abc.com
init.defaultbranch=main
credential.helper=store
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://devops:fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04@192.168.219.103:3000/devops/dev-app.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
[user]
name = devops
email = abc@abc.com
[init]
defaultBranch = main
[credential]
helper = store
|
(5) ํ์ฌ ๋ธ๋์น ๋ฐ ์๊ฒฉ ์ ๋ณด ํ์ธ
1
2
| git --no-pager branch
git remote -v
|
โ
ย ์ถ๋ ฅ
1
2
3
| * main
origin http://devops:fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04@192.168.219.103:3000/devops/dev-app.git (fetch)
origin http://devops:fef3afd3ae1c5e0869a5e6d3233ff0949f1e4e04@192.168.219.103:3000/devops/dev-app.git (push)
|
3. ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ์์ฑ ๋ฐ ํ
์คํธ
(1) server.py
ํ์ผ ์์ฑ
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
| cat > server.py <<EOF
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from datetime import datetime
import socket
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
match self.path:
case '/':
now = datetime.now()
hostname = socket.gethostname()
response_string = now.strftime("The time is %-I:%M:%S %p, VERSION 0.0.1\n")
response_string += f"Server hostname: {hostname}\n"
self.respond_with(200, response_string)
case '/healthz':
self.respond_with(200, "Healthy")
case _:
self.respond_with(404, "Not Found")
def respond_with(self, status_code: int, content: str) -> None:
self.send_response(status_code)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(bytes(content, "utf-8"))
def startServer():
try:
server = ThreadingHTTPServer(('', 80), RequestHandler)
print("Listening on " + ":".join(map(str, server.server_address)))
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
if __name__== "__main__":
startServer()
EOF
|
(2) ์๋ฒ ์คํ ๋ฐ ํ
์คํธ
1
2
3
| sudo python3 server.py
curl localhost
curl localhost/healthz
|
4. Dockerfile ๋ฐ ๋ฒ์ ํ์ผ ์์ฑ
(1) Dockerfile
์์ฑ
1
2
3
4
5
6
7
| cat > Dockerfile <<EOF
FROM python:3.12
ENV PYTHONUNBUFFERED 1
COPY . /app
WORKDIR /app
CMD python3 server.py
EOF
|
(2) VERSION
ํ์ผ ์์ฑ
(3) ํ๋ก์ ํธ ๊ตฌ์กฐ ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
| .
โโโ Dockerfile
โโโ README.md
โโโ server.py
โโโ VERSION
1 directory, 4 files
|
5. Git ์ปค๋ฐ ๋ฐ ์๊ฒฉ ์ ์ฅ์๋ก ํธ์
(1) ๋ณ๊ฒฝ ์ฌํญ ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
| On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
Dockerfile
VERSION
server.py
nothing added to commit but untracked files present (use "git add" to track)
|
(2) ์คํ
์ด์ง
(3) ์ปค๋ฐ
1
| git commit -m "Add dev-app"
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
| [main 99e9476] Add dev-app
3 files changed, 40 insertions(+)
create mode 100644 Dockerfile
create mode 100644 VERSION
create mode 100644 server.py
|
(4) ์ปค๋ฐ ๋ด์ฉ์ ์๊ฒฉ ์ ์ฅ์์ ํธ์ํ์ฌ ๋ฐ์
1
| git push -u origin main
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
| Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 18 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1015 bytes | 1015.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To http://192.168.219.103:3000/devops/dev-app.git
1b07e97..99e9476 main -> main
branch 'main' set up to track 'origin/main'.
|
6. Docker Hub ์ ์ฅ์ ์์ฑ ๋ฐ Personal Access Token(PAT) ๋ฐ๊ธ
(1) ์์ ์ Docker Hub ๊ณ์ ์ dev-app (Private) ์ ์ฅ์ ์์ฑ
(2) ๊ณ์ โ Account settings
(3) Security โ Personal access tokens โ Generate new token
๋ง๋ฃ์ผ(ํธํ๋๋ก), Access permissions(Read, Write, Delete)
์์ฑ๋ ํ ํฐ์ ๋ฉ๋ชจํ์ฌ ์ดํ ์ธ์ฆ ๋ฐ ํธ์ ์์
์ ํ์ฉ
๐ kind ๋ก k8s ๋ฐฐํฌ
1. ํ๊ฒฝ ๋ณ์ ์ค์
1
2
| MyIP=<๊ฐ์ ์์ ์ PC IP>
MyIP=192.168.219.103
|
2. ํด๋ฌ์คํฐ ๊ตฌ์ฑ ํ์ผ ์์ฑ
- cicd-labs ๋๋ ํฐ๋ฆฌ์์ ์๋ ํ์ผ ์์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| cd ..
cat > kind-3node.yaml <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "$MyIP"
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
EOF
|
3. ํด๋ฌ์คํฐ ์์ฑ
1
| kind create cluster --config kind-3node.yaml --name myk8s --image kindest/node:v1.32.2
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Creating cluster "myk8s" ...
โ Ensuring node image (kindest/node:v1.32.2) ๐ผ
โ Preparing nodes ๐ฆ ๐ฆ ๐ฆ
โ Writing configuration ๐
โ Starting control-plane ๐น๏ธ
โ Installing CNI ๐
โ Installing StorageClass ๐พ
โ Joining worker nodes ๐
Set kubectl context to "kind-myk8s"
You can now use your cluster with:
kubectl cluster-info --context kind-myk8s
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community ๐
|
4. ๋
ธ๋ ๋ชฉ๋ก ํ์ธ
1
| kind get nodes --name myk8s
|
โ
ย ์ถ๋ ฅ
1
2
3
| myk8s-worker
myk8s-worker2
myk8s-control-plane
|
5. ๊ธฐ๋ณธ ๋ค์์คํ์ด์ค ํ์ฑํ
โ
ย ์ถ๋ ฅ
1
| โ Active namespace is "default"
|
6. Docker ๋คํธ์ํฌ ๋ชฉ๋ก ํ์ธ
(1) Docker ๋คํธ์ํฌ ๋ชฉ๋ก ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
| NETWORK ID NAME DRIVER SCOPE
823451dd3cf5 bridge bridge local
8dc45b4bfaf3 cicd-labs_cicd-network bridge local
bb4d74152d4a host host local
dbf072d0a217 kind bridge local
056dcb2c01d1 none null local
|
(2) kind ๋คํธ์ํฌ ์์ธ ์ ๋ณด ํ์ธ
1
| docker inspect kind | jq
|
โ
ย ์ถ๋ ฅ
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
| [
{
"Name": "kind",
"Id": "dbf072d0a217f53e0b62f42cee01bcecc1b2f6ea216475178db001f2e38681f5",
"Created": "2025-01-26T16:18:22.33980443+09:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv4": true,
"EnableIPv6": true,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
},
{
"Subnet": "fc00:f853:ccd:e793::/64",
"Gateway": "fc00:f853:ccd:e793::1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"33b78e624fbd6ec1dc97e16c3a0accfb709d191ac8ebf2d3a632daaab2bfed7e": {
"Name": "myk8s-worker2",
"EndpointID": "2408ab1a6b39536a8ce5f13b1c65538e1093687cbe24e0d0605cfcd3c37e5fb8",
"MacAddress": "7e:91:b1:5c:f9:f8",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": "fc00:f853:ccd:e793::3/64"
},
"921a8848ddd4294e46a8e1531e206702b919d0f1e3d1fef1c7b621020b9ec05a": {
"Name": "myk8s-worker",
"EndpointID": "4757fa8c31137275765f9f9558975032574808b70c2d2c55256aae4b0fa22c2a",
"MacAddress": "d6:1f:1a:3b:8f:15",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": "fc00:f853:ccd:e793::2/64"
},
"f4b058d07f4a2710b835d42a1d8499d43b7f26c7f737735010ab0d1587cf3373": {
"Name": "myk8s-control-plane",
"EndpointID": "e2c1ffbc055525505bb4ed6c8a84261cdaaa2f829b135a099c21dafe363ded1c",
"MacAddress": "e6:5f:e9:6b:10:06",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": "fc00:f853:ccd:e793::4/64"
}
},
"Options": {
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
|
7. ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ ๋ณด ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
| Kubernetes control plane is running at https://192.168.219.103:36865
CoreDNS is running at https://192.168.219.103:36865/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
|
8. ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋ ์ ๋ณด ํ์ธ
1
| kubectl get node -o wide
|
โ
ย ์ถ๋ ฅ
1
2
3
4
| NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
myk8s-control-plane Ready control-plane 20m v1.32.2 172.18.0.4 <none> Debian GNU/Linux 12 (bookworm) 6.13.8-arch1-1 containerd://2.0.3
myk8s-worker Ready <none> 20m v1.32.2 172.18.0.2 <none> Debian GNU/Linux 12 (bookworm) 6.13.8-arch1-1 containerd://2.0.3
myk8s-worker2 Ready <none> 20m v1.32.2 172.18.0.3 <none> Debian GNU/Linux 12 (bookworm) 6.13.8-arch1-1 containerd://2.0.3
|
9. ์ฟ ๋ฒ๋คํฐ์ค ํ๋ ์ํ ํ์ธ
1
| kubectl get pod -A -o wide
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-668d6bf9bc-9jr7l 1/1 Running 0 20m 10.244.0.3 myk8s-control-plane <none> <none>
kube-system coredns-668d6bf9bc-wwd8c 1/1 Running 0 20m 10.244.0.2 myk8s-control-plane <none> <none>
kube-system etcd-myk8s-control-plane 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
kube-system kindnet-gjp2z 1/1 Running 0 20m 172.18.0.3 myk8s-worker2 <none> <none>
kube-system kindnet-m45kh 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
kube-system kindnet-sbjrk 1/1 Running 0 20m 172.18.0.2 myk8s-worker <none> <none>
kube-system kube-apiserver-myk8s-control-plane 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
kube-system kube-controller-manager-myk8s-control-plane 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
kube-system kube-proxy-8zvnt 1/1 Running 0 20m 172.18.0.2 myk8s-worker <none> <none>
kube-system kube-proxy-pqrln 1/1 Running 0 20m 172.18.0.3 myk8s-worker2 <none> <none>
kube-system kube-proxy-xjbwl 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
kube-system kube-scheduler-myk8s-control-plane 1/1 Running 0 20m 172.18.0.4 myk8s-control-plane <none> <none>
local-path-storage local-path-provisioner-7dc846544d-7hx2m 1/1 Running 0 20m 10.244.0.4 myk8s-control-plane <none> <none>
|
10. ์ฟ ๋ฒ๋คํฐ์ค ๋ค์์คํ์ด์ค ๋ชฉ๋ก ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
| NAME STATUS AGE
default Active 21m
kube-node-lease Active 21m
kube-public Active 21m
kube-system Active 21m
local-path-storage Active 21m
|
11. ๋์ปค ์ปจํ
์ด๋ ์ํ ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
| CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
921a8848ddd4 kindest/node:v1.32.2 "/usr/local/bin/entrโฆ" 21 minutes ago Up 21 minutes myk8s-worker
33b78e624fbd kindest/node:v1.32.2 "/usr/local/bin/entrโฆ" 21 minutes ago Up 21 minutes myk8s-worker2
f4b058d07f4a kindest/node:v1.32.2 "/usr/local/bin/entrโฆ" 21 minutes ago Up 21 minutes 0.0.0.0:30000-30003->30000-30003/tcp, 192.168.219.103:36865->6443/tcp myk8s-control-plan
|
12. 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
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
| NAME: kube-ops-view
LAST DEPLOYED: Sat Mar 29 14:50:17 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace kube-system -o jsonpath="{.spec.ports[0].nodePort}" services kube-ops-view)
export NODE_IP=$(kubectl get nodes --namespace kube-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
|
13. kube-ops-view ์ค์น ํ์ธ
1
| kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
| NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kube-ops-view 1/1 1 1 53s
NAME READY STATUS RESTARTS AGE
pod/kube-ops-view-6658c477d4-w247s 1/1 Running 0 53s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-ops-view NodePort 10.96.236.75 <none> 8080:30001/TCP 53s
NAME ENDPOINTS AGE
endpoints/kube-ops-view 10.244.3.2:8080 53s
|
http://127.0.0.1:30001/#scale=1.5
์ ์
โ๏ธ ์ ํจ์ค ์ค์ ๋ฐ CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ฑ
1. ์ ํจ์ค ํ๋ฌ๊ทธ์ธ ์ค์น
2. ์๊ฒฉ์ฆ๋ช
์ค์
- ๋์ปค ํ๋ธ ์๊ฒฉ์ฆ๋ช
์ค์ :
dockerhub-crd
- Kind :
Username with password
- Username :
shinminjin
/ Password : xxxxxxxxxxxxxxxxxxxxx
/ ID : dockerhub-crd
- k8s(kind) ์๊ฒฉ์ฆ๋ช
์ค์ : k8s-crd
- Kind :
Secret file
/ File : <kubeconfig ํ์ผ ์
๋ก๋>
/ ID : k8s-crd
1
| cp ~/.kube/config ./kube-config
|
- 3๊ฐ์ ์๊ฒฉ์ฆ๋ช
์
ํ
์๋ฃ
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
| pipeline {
agent any
environment {
DOCKER_IMAGE = 'shinminjin/dev-app' // Docker ์ด๋ฏธ์ง ์ด๋ฆ, <์์ ์ ๋์ปค ํ๋ธ ๊ณ์ >/dev-app
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.219.103:3000/devops/dev-app.git', // Git์์ ์ฝ๋ ์ฒดํฌ์์, <์์ ์ ์ง IP>
credentialsId: 'gogs-crd' // Credentials ID
}
}
stage('Read VERSION') {
steps {
script {
// VERSION ํ์ผ ์ฝ๊ธฐ
def version = readFile('VERSION').trim()
echo "Version found: ${version}"
// ํ๊ฒฝ ๋ณ์ ์ค์
env.DOCKER_TAG = version
}
}
}
stage('Docker Build and Push') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
// DOCKER_TAG ์ฌ์ฉ
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
|
4. ํ์ดํ๋ผ์ธ ์คํ
๐ก k8s ์ ํ๋ฆฌ์ผ์ด์
๋ฐฐํฌ ๋ฐ ๊ฒ์ฆ (Jenkins Pipeline CI)
1. Timeserver Deployment ์์ฑ
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
| DHUSER=<๋์ปค ํ๋ธ ๊ณ์ ๋ช
>
DHUSER=shinminjin
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: timeserver
spec:
replicas: 2
selector:
matchLabels:
pod: timeserver-pod
template:
metadata:
labels:
pod: timeserver-pod
spec:
containers:
- name: timeserver-container
image: docker.io/$DHUSER/dev-app:0.0.1
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 30
httpGet:
path: /healthz
port: 80
scheme: HTTP
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
EOF
# ๊ฒฐ๊ณผ
deployment.apps/timeserver created
|
2. ์ด๋ฏธ์ง ํ ์๋ฌ ๋ฐ ์ด๋ฒคํธ ํ์ธ
1
| kubectl get events -w --sort-by '.lastTimestamp'
|
โ
ย ์ถ๋ ฅ
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
| warning: --watch requested, --sort-by will be ignored for watch events received
LAST SEEN TYPE REASON OBJECT MESSAGE
11m Normal Starting node/myk8s-control-plane
96s Normal Scheduled pod/timeserver-6cd9654cc7-l4v9d Successfully assigned default/timeserver-6cd9654cc7-l4v9d to myk8s-worker
96s Normal Scheduled pod/timeserver-6cd9654cc7-f7ck7 Successfully assigned default/timeserver-6cd9654cc7-f7ck7 to myk8s-worker2
11m Normal Starting node/myk8s-worker2
11m Normal Starting node/myk8s-worker
11m Normal NodeAllocatableEnforced node/myk8s-worker2 Updated Node Allocatable limit across pods
11m Normal Starting node/myk8s-worker2 Starting kubelet.
11m Normal Starting node/myk8s-worker Starting kubelet.
11m Normal NodeHasSufficientPID node/myk8s-control-plane Node myk8s-control-plane status is now: NodeHasSufficientPID
11m Normal NodeHasNoDiskPressure node/myk8s-control-plane Node myk8s-control-plane status is now: NodeHasNoDiskPressure
11m Normal Starting node/myk8s-control-plane Starting kubelet.
11m Normal NodeAllocatableEnforced node/myk8s-worker Updated Node Allocatable limit across pods
11m Normal NodeAllocatableEnforced node/myk8s-control-plane Updated Node Allocatable limit across pods
11m Normal NodeHasSufficientMemory node/myk8s-control-plane Node myk8s-control-plane status is now: NodeHasSufficientMemory
11m Normal NodeHasNoDiskPressure node/myk8s-worker Node myk8s-worker status is now: NodeHasNoDiskPressure
11m Normal NodeHasSufficientMemory node/myk8s-worker2 Node myk8s-worker2 status is now: NodeHasSufficientMemory
11m Normal NodeHasNoDiskPressure node/myk8s-worker2 Node myk8s-worker2 status is now: NodeHasNoDiskPressure
11m Normal NodeHasSufficientPID node/myk8s-worker2 Node myk8s-worker2 status is now: NodeHasSufficientPID
11m Normal NodeHasSufficientPID node/myk8s-worker Node myk8s-worker status is now: NodeHasSufficientPID
11m Normal NodeHasSufficientMemory node/myk8s-worker Node myk8s-worker status is now: NodeHasSufficientMemory
11m Normal RegisteredNode node/myk8s-worker Node myk8s-worker event: Registered Node myk8s-worker in Controller
11m Normal RegisteredNode node/myk8s-worker2 Node myk8s-worker2 event: Registered Node myk8s-worker2 in Controller
11m Normal RegisteredNode node/myk8s-control-plane Node myk8s-control-plane event: Registered Node myk8s-control-plane in Controller
96s Normal ScalingReplicaSet deployment/timeserver Scaled up replica set timeserver-6cd9654cc7 from 0 to 2
96s Normal SuccessfulCreate replicaset/timeserver-6cd9654cc7 Created pod: timeserver-6cd9654cc7-f7ck7
96s Normal SuccessfulCreate replicaset/timeserver-6cd9654cc7 Created pod: timeserver-6cd9654cc7-l4v9d
24s Warning Failed pod/timeserver-6cd9654cc7-l4v9d Error: ImagePullBackOff
24s Normal BackOff pod/timeserver-6cd9654cc7-l4v9d Back-off pulling image "docker.io/shinminjin/dev-app:0.0.1"
23s Normal BackOff pod/timeserver-6cd9654cc7-f7ck7 Back-off pulling image "docker.io/shinminjin/dev-app:0.0.1"
23s Warning Failed pod/timeserver-6cd9654cc7-f7ck7 Error: ImagePullBackOff
9s Normal Pulling pod/timeserver-6cd9654cc7-f7ck7 Pulling image "docker.io/shinminjin/dev-app:0.0.1"
9s Normal Pulling pod/timeserver-6cd9654cc7-l4v9d Pulling image "docker.io/shinminjin/dev-app:0.0.1"
7s Warning Failed pod/timeserver-6cd9654cc7-f7ck7 Error: ErrImagePull
7s Warning Failed pod/timeserver-6cd9654cc7-l4v9d Error: ErrImagePull
7s Warning Failed pod/timeserver-6cd9654cc7-l4v9d Failed to pull image "docker.io/shinminjin/dev-app:0.0.1": failed to pull and unpack image "docker.io/shinminjin/dev-app:0.0.1": failed to resolve reference "docker.io/shinminjin/dev-app:0.0.1": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
7s Warning Failed pod/timeserver-6cd9654cc7-f7ck7 Failed to pull image "docker.io/shinminjin/dev-app:0.0.1": failed to pull and unpack image "docker.io/shinminjin/dev-app:0.0.1": failed to resolve reference "docker.io/shinminjin/dev-app:0.0.1": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
0s Normal BackOff pod/timeserver-6cd9654cc7-f7ck7 Back-off pulling image "docker.io/shinminjin/dev-app:0.0.1"
0s Warning Failed pod/timeserver-6cd9654cc7-f7ck7 Error: ImagePullBackOff
|
- Private ์ ์ฅ์๋ผ ์ด๋ฏธ์ง ํ ๊ถํ์ด ์์ด์
ImagePullBackOff
์๋ฌ ๋ฐ์
3. ๋์ปค ๋ ์ง์คํธ๋ฆฌ ์๊ฒฉ์ฆ๋ช
์ค์
1
2
| DHUSER=<๋์ปค ํ๋ธ ๊ณ์ >
DHPASS=<๋์ปค ํ๋ธ ์ํธ ํน์ ํ ํฐ>
|
1
2
3
4
5
6
7
| kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
# ๊ฒฐ๊ณผ
secret/dockerhub-secret created
|
4. ์ฟ ๋ฒ๋คํฐ์ค Secret ๋ชฉ๋ก ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
| NAME TYPE DATA AGE
dockerhub-secret kubernetes.io/dockerconfigjson 1 22s
|
5. ๋ฐฐํฌ ์ํ ๋ฐ ํ๋ ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
| NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/timeserver 2/2 2 2 9m2s
NAME READY STATUS RESTARTS AGE
pod/timeserver-69c87f9f8c-jn2zv 1/1 Running 0 51s
pod/timeserver-69c87f9f8c-r5j6l 1/1 Running 0 83s
|
6. ์ ์ ํ
์คํธ๋ฅผ ์ํ Curl ํ๋ ์์ฑ
1
2
3
4
| kubectl run curl-pod --image=curlimages/curl:latest --command -- sh -c "while true; do sleep 3600; done"
# ๊ฒฐ๊ณผ
pod/curl-pod created
|
7. Timeserver ํ๋ IP ํ์ธ ๋ฐ ์ ์ ํ
์คํธ
(1) Timeserver ํ๋ IP ํ์ธ
โ
ย ์ถ๋ ฅ
1
2
3
4
| NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
curl-pod 1/1 Running 0 20s 10.244.1.4 myk8s-worker <none> <none>
timeserver-69c87f9f8c-jn2zv 1/1 Running 0 2m34s 10.244.1.3 myk8s-worker <none> <none>
timeserver-69c87f9f8c-r5j6l 1/1 Running 0 3m6s 10.244.3.4 myk8s-worker2 <none> <none
|
(2) Timeserver ํ๋ ์ค ํ ๊ฐ์ IP(ex. 10.244.1.3)๋ฅผ ๋ณ์ PODIP1
์ ํ ๋น
1
2
| PODIP1=<timeserver-Y ํ๋ IP>
PODIP1=10.244.1.3
|
(3) curl-pod ์์ ํด๋น IP๋ก ์ ์ํ์ฌ ๊ธฐ๋ณธ ์๋ํฌ์ธํธ(/
) ์๋ต ํ์ธ
1
| kubectl exec -it curl-pod -- curl $PODIP1
|
โ
ย ์ถ๋ ฅ
1
2
| The time is 6:53:49 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
|
(4) /healthz
์๋ํฌ์ธํธ์ ๋ํ ์๋ต ํ์ธ
1
| kubectl exec -it curl-pod -- curl $PODIP1/healthz
|
โ
ย ์ถ๋ ฅ
8. ํ๋ ๋ก๊ทธ ๋ชจ๋ํฐ๋ง
1
| kubectl stern deploy/timeserver
|
โ
ย ์ถ๋ ฅ
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
| + timeserver-69c87f9f8c-r5j6l โบ timeserver-container
+ timeserver-69c87f9f8c-jn2zv โบ timeserver-container
timeserver-69c87f9f8c-jn2zv timeserver-container Listening on 0.0.0.0:80
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:50:49] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:51:19] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:51:49] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:52:19] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:52:49] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:53:19] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.4 - - [29/Mar/2025 06:53:49] "GET / HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:53:49] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:54:19] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.4 - - [29/Mar/2025 06:54:22] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-jn2zv timeserver-container 10.244.1.1 - - [29/Mar/2025 06:54:49] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container Listening on 0.0.0.0:80
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:50:17] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:50:47] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:51:17] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:51:47] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:52:17] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:52:47] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:53:17] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:53:47] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:54:17] "GET /healthz HTTP/1.1" 200 -
timeserver-69c87f9f8c-r5j6l timeserver-container 10.244.3.1 - - [29/Mar/2025 06:54:47] "GET /healthz HTTP/1.1" 200 -
|
9. ์๋น์ค ์์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: timeserver
spec:
selector:
pod: timeserver-pod
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 30000
type: NodePort
EOF
# ๊ฒฐ๊ณผ
service/timeserver created
|
10. ์์ฑ๋ ์๋น์ค์ ์๋ํฌ์ธํธ ํ์ธ
1
| kubectl get service,ep timeserver -owide
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
| NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/timeserver NodePort 10.96.206.165 <none> 80:30000/TCP 68s pod=timeserver-pod
NAME ENDPOINTS AGE
endpoints/timeserver 10.244.1.3:80,10.244.3.4:80 68s
|
11. ์๋น์ค ์ ์ ๋ฐ ์ธ๋ถ ์ ๊ทผ ํ์ธ
(1) curl-pod ๋ด์์ ์ ๊ทผ ํ์ธ
1
2
| kubectl exec -it curl-pod -- curl timeserver
kubectl exec -it curl-pod -- curl timeserver/healthz
|
โ
ย ์ถ๋ ฅ
1
2
3
4
| The time is 7:02:54 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
Healthy%
|
(2) ๋ก์ปฌ์์ ์ ๊ทผ ํ์ธ
1
2
| curl http://127.0.0.1:30000
curl http://127.0.0.1:30000/healthz
|
โ
ย ์ถ๋ ฅ
1
2
3
4
| The time is 7:04:09 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
Healthy%
|
12. ๋ถํ ๋ถ์ฐ ํ
์คํธ
(1) ๋ฌดํ ๋ฐ๋ณต์ผ๋ก curl
๋ช
๋ น ์คํ
1
| while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; sleep 1 ; done
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
| The time is 9:08:08 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-r5j6l
The time is 9:08:09 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
The time is 9:08:10 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
The time is 9:08:11 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-r5j6l
The time is 9:08:12 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-r5j6l
The time is 9:08:13 AM, VERSION 0.0.1
Server hostname: timeserver-69c87f9f8c-jn2zv
...
|
(2) 100๋ฒ์ ํธ์ถ ๊ฒฐ๊ณผ ์ง๊ณ
1
| for i in {1..100}; do curl -s http://127.0.0.1:30000 | grep name; done | sort | uniq -c | sort -nr
|
โ
ย ์ถ๋ ฅ
1
2
| 59 Server hostname: timeserver-69c87f9f8c-jn2zv
41 Server hostname: timeserver-69c87f9f8c-r5j6l
|
๐ ์ ํจ์ค ํ์ดํ๋ผ์ธ์ ํ์ฉํ ์ ํ๋ฆฌ์ผ์ด์
์
๋ฐ์ดํธ
1. ์ํ ์ฑ server.py ์ฝ๋ ๋ณ๊ฒฝ
VERSION
ํ์ผ ๋ณ๊ฒฝ : 0.0.2
server.py
ํ์ผ ๋ณ๊ฒฝ : 0.0.2
2. Git ์ปค๋ฐ / ํธ์
1
| git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
| [main e0e3cf9] VERSION 0.0.2 Changed
2 files changed, 2 insertions(+), 2 deletions(-)
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 18 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 343 bytes | 343.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
To http://192.168.219.103:3000/devops/dev-app.git
99e9476..e0e3cf9 main -> main
branch 'main' set up to track 'origin/main'.
|
3. ์ฟ ๋ฒ๋คํฐ์ค Deployment ์
๋ฐ์ดํธ ์๋ ๋ฐ ๋ฌธ์ ๋ฐ์
1
| kubectl set image deployment timeserver timeserver-container=$DHUSER/dev-app:0.0.2 && watch -d "kubectl get deploy,ep timeserver; echo; kubectl get rs,pod"
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| Every 2.0s: kubectl get deploy,ep timeserver; echo; kubectl get rs,pod gram88: 06:20:02 PM
in 0.175s (0)
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/timeserver 2/2 1 2 158m
NAME ENDPOINTS AGE
endpoints/timeserver 10.244.1.3:80,10.244.3.4:80 138m
NAME DESIRED CURRENT READY AGE
replicaset.apps/timeserver-69c87f9f8c 2 2 2 151m
replicaset.apps/timeserver-6cd9654cc7 0 0 0 158m
replicaset.apps/timeserver-79d564b95c 1 1 0 7s
NAME READY STATUS RESTARTS AGE
pod/curl-pod 1/1 Running 0 148m
pod/timeserver-69c87f9f8c-jn2zv 1/1 Running 0 150m
pod/timeserver-69c87f9f8c-r5j6l 1/1 Running 0 151m
pod/timeserver-79d564b95c-nck7r 0/1 ErrImagePull 0 7s
|
- ์ ํ๊ทธ
0.0.2
์ ์ด๋ฏธ์ง๊ฐ ์กด์ฌํ์ง ์์ ์ด๋ฏธ์ง ํ ์๋ฌ(ErrImagePull
) ๋ฐ์
4. ์ ํจ์ค ๋น๋๋ฅผ ํตํ ์๋ก์ด ์ด๋ฏธ์ง ์์ฑ ๋ฐ ๋ฐฐํฌ ์
๋ฐ์ดํธ
1
| kubectl set image deployment timeserver timeserver-container=$DHUSER/dev-app:0.0.2 && watch -d "kubectl get deploy,ep timeserver; echo; kubectl get rs,pod"
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| Every 2.0s: kubectl get deploy,ep timeserver; echo; kubectl get rs,pod gram88: 06:27:20 PM
in 0.243s (0)
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/timeserver 2/2 2 2 166m
NAME ENDPOINTS AGE
endpoints/timeserver 10.244.1.5:80,10.244.3.5:80 146m
NAME DESIRED CURRENT READY AGE
replicaset.apps/timeserver-69c87f9f8c 0 0 0 158m
replicaset.apps/timeserver-6cd9654cc7 0 0 0 166m
replicaset.apps/timeserver-79d564b95c 2 2 2 7m25s
NAME READY STATUS RESTARTS AGE
pod/curl-pod 1/1 Running 0 155m
pod/timeserver-79d564b95c-74gpz 1/1 Running 0 113s
pod/timeserver-79d564b95c-nck7r 1/1 Running 0 7m25s
|
5. Gogs ์ค์ ๋ณ๊ฒฝ ๋ฐ ์นํ
๋ฑ๋ก
(1) gogs ์ปจํ
์ด๋ ๋ด /data/gogs/conf/app.ini
ํ์ผ ์์
1
2
3
4
| docker compose exec gogs bash
a0dda4a63d1b:/# cd /data/gogs/conf/
a0dda4a63d1b:/data/gogs/conf# vi app.ini
|
LOCAL_NETWORK_ALLOWLIST = 192.168.219.103
์ถ๊ฐ
1
2
3
4
| [security]
INSTALL_LOCK = true
SECRET_KEY = 0QLuknjrgYnZbGu
LOCAL_NETWORK_ALLOWLIST = 192.168.219.103
|
(2) ์ปจํ
์ด๋ ์ฌ๊ธฐ๋
1
2
3
4
5
| docker compose restart gogs
# ๊ฒฐ๊ณผ
[+] Restarting 1/1
โ Container gogs Started
|
(3) Gogs Webhook ์ค์
Webhooks > Gogs ์ ํ
- Payload URL :
http://192.168.219.103:8080/gogs-webhook/?job=SCM-Pipeline/
<์์ ์ ์ง="" IP="">์์ ์> - Content Type :
application/json
/ Secret : qwe123
- When should this webhook be triggered? :
Just the push event
/ Active : Check
6. ์ ํจ์ค ํ์ดํ๋ผ์ธ ์ค์
7. Jenkinsfile ๋ฐ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ์
๋ฐ์ดํธ
1
2
3
4
5
| # Jenkinsfile ๋น ํ์ผ ์์ฑ
touch Jenkinsfile
# VERSION ํ์ผ : 0.0.3 ์์
# server.py ํ์ผ : 0.0.3 ์์
|
Jenkinsfile
์์ฑ
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
| pipeline {
agent any
environment {
DOCKER_IMAGE = 'shinminjin/dev-app' // Docker ์ด๋ฏธ์ง ์ด๋ฆ, <์์ ์ ๋์ปค ํ๋ธ ๊ณ์ >/dev-app
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.219.103:3000/devops/dev-app.git', // Git์์ ์ฝ๋ ์ฒดํฌ์์, <์์ ์ ์ง IP>:3000
credentialsId: 'gogs-crd' // Credentials ID
}
}
stage('Read VERSION') {
steps {
script {
// VERSION ํ์ผ ์ฝ๊ธฐ
def version = readFile('VERSION').trim()
echo "Version found: ${version}"
// ํ๊ฒฝ ๋ณ์ ์ค์
env.DOCKER_TAG = version
}
}
}
stage('Docker Build and Push') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
// DOCKER_TAG ์ฌ์ฉ
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
|
8. ๋ณ๊ฒฝ์ฌํญ ์ปค๋ฐ ๋ฐ Git Push
1
| git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
|
โ
ย ์ถ๋ ฅ
1
2
3
4
5
6
7
8
9
10
11
12
| [main 6f80ffb] VERSION 0.0.3 Changed
3 files changed, 48 insertions(+), 2 deletions(-)
create mode 100644 Jenkinsfile
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 18 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 1.07 KiB | 1.07 MiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
To http://192.168.219.103:3000/devops/dev-app.git
e0e3cf9..6f80ffb main -> main
branch 'main' set up to track 'origin/main'.
|
9. ์ ํจ์ค Job ๋น๋ ์คํ