๋ค์ด๊ฐ๋ฉฐ
์๋
ํ์ธ์,
์ต๊ทผ ํ์ฌ์์ ์ฌ๋ด ๊ฐ๋ฐ๋ง์ ์ธ๋ถ๋ง์ผ๋ก ์ ํํ๋ ์์
์ ๋ด๋นํ๋ฉด์,
์ธํ๋ผ๋ฅผ ์ง์ ๊ตฌ์ถํ ๊ธฐํ๊ฐ ์๊ฒผ์ต๋๋ค.
์ด์ ํ๋ ๊ฑฐ, "์๋ฒ์ CI/CD ํ์ดํ๋ผ์ธ์ ์๋ฒฝํ๊ฒ ์๋ํํด๋ณด์!" ๋ผ๋ ์๋ํ ๋ชฉํ๋ฅผ ์ธ์ฐ๊ฒ ๋์์ฃ ...
์ฌ์ฉํ๊ธฐ๋ก ํ ์คํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- IaC: Ansible (์๋ฒ ํ๋ก๋น์ ๋ ์๋ํ)
- ์ ์ธ์ IaC์ธ Terrafrom์ ์ฌ๋ด ๋ณด์์ ํจํค์ง ์ค์น ๋ฑ os๋ฅผ ๊ฑด๋๋ฆด ์ผ๋ ค๊ฐ ์์ด ์ ์ธํ์ต๋๋ค!
- ์ ์ฐจ์ IaC์ธ Ansible๋ก ์งํํ๋ฉด playbook์ ์ดํด๋ ์ฝ์ง ์์๊น ์๊ฐํ์ต๋๋ค.
- CI: GitLab (SCM + Container Registry), Jenkins
- GitLab์ ๊ธฐ๋ณธ VCS๋ก ์ฌ์ฉํ๊ณ , Webhook์ผ๋ก Jenkins์ ์ฐ๊ฒฐํ์ฌ ์ฌ์ฉํฉ๋๋ค.
- CD: ArgoCD, K3s
- ์๋ฒ ๋ฆฌ์์ค์ k8s๊ฐ ๊ฒฝ๋ํ๋ k3s๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ArgoCD๋ QA ํ๊ฒฝ์ ๋ชจ๋ฐฉํฉ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๊ตฌ์ถ์๋ ์ฑ๊ณตํ๊ณ , ํ์ฌ ์ ๋์๊ฐ๊ณ ์์ต๋๋ค.
๊ทธ ๊ณผ์ ์์ ๊ฒช์๋ ์ํ์ฐฉ์ค๋ค์ ๋ช ๊ฐ์ง ์ ๋ฆฌํด ๋ณด๋ ค ํฉ๋๋ค ๐
ํนํ GitLab ํฌํธ ์ถฉ๋๊ณผ K3s์ ๋ฐํ์ ์ด์์์ ์กฐ๊ธ ์ฝ์ง์ ํ๋๋ฐ์.
์ ์ฒ๋ผ ์ฒ์ ๊ตฌ์ถํ๋ ๋ถ๋ค์ ์ํด ํธ๋ฌ๋ธ์ํ
๋ก๊ทธ๋ฅผ ๋จ๊ฒจ๋ด
๋๋ค.
์ด๋ฐ๊ฑด AI๋ ์ ๋ชจ๋ฅด๋๋ผ๊ตฌ์โ
0. ์ ์ฒด ์ธํ๋ผ ๊ตฌ์ํ๊ธฐ

- Code Push : Project A์ ์ฝ๋ push๊ฐ ๋ฐ์ํฉ๋๋ค.
- Image Build & Push : Jenkins๊ฐ ๋น๋๋ฅผ ์ํํ๊ณ , GitLab Container Registry์ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํฉ๋๋ค.
- Manifest Update : ์ด๋ฏธ์ง ์ ๋ก๋๊ฐ ์ฑ๊ณตํ๋ฉด, Jenkins๊ฐ Project B์ deployment.yaml ํ๊ทธ๋ฅผ ์์ ํ์ฌ ์ปค๋ฐํฉ๋๋ค.
- CD Sync: ArgoCD๊ฐ Project B์ Git ๋ณ๊ฒฝ ์ฌํญ์ ๊ฐ์งํ๊ณ , K3s ํด๋ฌ์คํฐ์ ๋ฐฐํฌํฉ๋๋ค.
์ด ๋ชจ๋ ํ๊ฒฝ์ Ansible ํ๋๋ก ๊ตฌ์ถํ๋ ๊ฒ์ด ์ด๋ฒ ํฌ์คํ ์ ๋ชฉํ์ ๋๋ค!
1. Ansible๋ก ์ธํ๋ผ ์๋ํํ๊ธฐ
์ฐ์ ๋ชจ๋ ์ค์น ๊ณผ์ ์ Ansible๋ก ์ฝ๋ํํ์ต๋๋ค.
๋์ค์ ์๋ฒ๊ฐ ๋ฐ๋๋๋ผ๋ playbook ํ๋๋ฉด ๋๊ฐ์ ํ๊ฒฝ์ ์ฐ์ด๋ผ ์ ์๋ค๋ ์ ์ด ๋๋ฌด ๋งค๋ ฅ์ ์ด์ง ์๋์?
๋ฉ์ธ ์๋ฒ์์ ๋ฐ๋ก ๋๋ฆด ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ansible_connection=local ์ต์
์ ์ฌ์ฉํ์ต๋๋ค.
๋ง์๊ฐ์์ ์ต์ 2๊ฐ์ ์ธ์คํด์ค ํ๊ฒฝ์์ ์์
์ ํ๊ณ ์ถ์์ง๋ง... ์ด์ฉ ์ ์์ฃ !
ansible_connection=local ์ด๋?
> Ansible์ด SSH๋ฅผ ํตํ์ง ์๊ณ , ๋ก์ปฌํธ์คํธ์ ์ง์ ๋ช ๋ น์ ๋ด๋ฆด ๋ ์ฌ์ฉํ๋ ์ต์ ์ ๋๋ค.
# main-playbook.yml
- name: 1. Docker ์ค์น ๋ฐ ํ๊ฒฝ ๊ตฌ์ฑ
hosts: localhost
become: yes
roles:
- 1-docker
- name: 2. GitLab, Jenkins ์ปจํ
์ด๋ ์คํ (Docker Compose)
hosts: localhost
roles:
- 2-cicd-tools
- name: 3. K3s ๋ฐ ArgoCD ํ๊ฒฝ ๊ตฌ์ถ (K8s)
hosts: localhost
become: yes
roles:
- 3-k3s
- 4-argocd
์์ฒ๋ผ mainPlayBook ์ค์ ์ ํด ๋๊ณ ,
๊ฐ roles ๋ด์ ์คํฌ๋ฆฝํธ๋ค์ ์์ฑ ํด ๋จ์ต๋๋ค.
๊ฒฐ๊ตญ ์ด ์คํฌ๋ฆฝํธ ํ๋๋ง ์คํํ๋ฉด
- Docker๊ฐ ์ค์น๋๊ณ ,
- GitLab๊ณผ Jenkins๊ฐ Docker Compose๋ก ๋จ๊ณ ,
- K3s๊ฐ ์ค์น๋ ๋ค,
- ArgoCD๊น์ง ์๋์ผ๋ก ๋ฐฐํฌ๋๋๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
์ธํ๋ผ ์ค์น ๋!
์ด๋ผ๋ฉฐ ์ข์ํ๋ ๊ฒ๋ ์ ์...
2. GitLab Container Registry์ Nginx์ ์ถฉ๋
Jenkins์์ ์ด์ฌํ ๋น๋ํ Docker ์ด๋ฏธ์ง๋ฅผ ์ฌ๋ด GitLab Registry์ push ํ๋ ค๋๋ฐ,
๊ณ์ 404 Not Found ์๋ฌ๊ฐ ๋จ๋ ๊ฒ๋๋ค.
๋ก๊ทธ์ธ์ ๋๋๋ฐ ํธ์๋ง ์ ๋๋... ์ ๋ง ๊ธฐ์ดํ ์ํฉ์ด์์ฃ .
์์ธ
๋ฒ์ธ์ ๋ฐ๋ก ํฌํธ ์ค์ ์ด์์ต๋๋ค.
GitLab ์น UI ํฌํธ์ Registry ํฌํธ๋ฅผ ๋ ๋ค 8081๋ก ์ค์ ํด๋ฒ๋ฆฐ ๊ฒ ํ๊ทผ์ด์์ด์.
GitLab ๋ด๋ถ์ Nginx๊ฐ docker push ์์ฒญ์ ๋ฐ๊ณ ๋,
"์ด? ์ด๊ฑฐ ์น ํ์ด์ง ์์ฒญ์ธ๊ฐ?" ํ๊ณ ์๋ฑํ ๊ณณ์ผ๋ก ๋ณด๋ด๋ฒ๋ฆฌ๊ณ ์์๋ ๊ฒ๋๋ค.
ํด๊ฒฐ: ํฌํธ ๋ถ๋ฆฌ
๊ฒฐ๊ตญ docker-compose.yml์ ์์ ํด์ ๋ ์๋น์ค์ ํฌํธ๋ฅผ ๋ช
ํํ ์ฐข์ด๋์์ต๋๋ค.
- GitLab Web: 8081
- Registry: 5005
services:
gitlab:
ports:
- "8081:8081" # ์น ์ ์์ฉ
- "5005:5005" # ๋ ์ง์คํธ๋ฆฌ์ฉ
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://xxx.xxx.xxx.xxx:8081'
registry_external_url 'http://xxx.xxx.xxx.xxx:5005'
gitlab_registry_enable = true
๊ทธ๋ฆฌ๊ณ , ๋ณ๋ ๋๋ฉ์ธ์ ์ฌ์ฉํ์ง ์์ SSL ์ธ์ฆ์ ๋ฐ๊ธ์ด ์ด๋ ค์ HTTP๋ฅผ ์ฌ์ฉํ๋๋ฐ์.
Docker๋ ๊ธฐ๋ณธ์ ์ผ๋ก HTTPS๋ง ์ ๋ขฐํ๊ธฐ ๋๋ฌธ์, ํธ์คํธ์ /etc/docker/daemon.json์ ์๋ ์ค์ ์ ์ถ๊ฐํด์ค์ผ ํฉ๋๋ค.
"insecure-registries": ["xxx.xxx.xxx.xxx:5005"]
insecure-registries ๋?
HTTP๋ก ํต์ ํ๋ ๋ ์ง์คํธ๋ฆฌ์ ์ ์์ ํ์ฉํ๋ ์ต์ ์ ๋๋ค.
์ธ๋ถ ์ธํฐ๋ท ์ฐ๊ฒฐ์ ์ฐจ๋จ๋ ํ์๋ง ํ๊ฒฝ์ด๋ผ, ๋ณด์๋ณด๋ค๋ ํธ์์ฑ์ ํํ์ต๋๋ค.
3. ์ธ์ฆ.. Token์ด ์ ์ด๋ ๊ฒ ๋ง์?
ํฌํธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ๋๋, ์ด๋ฒ์ denied ์๋ฌ๊ฐ ์ ๋ฅผ ๋ฐ๊ฒจ์ค๋๋ค.
์๊ณ ๋ณด๋ GitLab์๋ ํ ํฐ์ ์ข
๋ฅ๊ฐ ์ฌ๋ฌ ๊ฐ์ง์๊ณ , ์ ๋ ๊ทธ๊ฑธ ํผ๋ํด์ ์ฐ๊ณ ์์๋๋ผ๊ณ ์.
Deploy Token vs Access Token
| ํ ํฐ ์ข ๋ฅ | ์ฉ๋ | ํ์ํ ๊ถํ |
|---|---|---|
| Deploy Token | ์ด๋ฏธ์ง Push (Docker Login) | write_registry |
| Project Access Token | Git Push (Manifest Update) | write_repository |
- ์ด๋ฏธ์ง ์ฌ๋ฆด ๋: Jenkins๊ฐ Docker ์ด๋ฏธ์ง๋ฅผ ๋ ์ง์คํธ๋ฆฌ์ ์ฌ๋ฆด ๋ Deploy Token์ ์จ์ผ ํฉ๋๋ค.
- Git ์์ ํ ๋: Jenkins๊ฐ ArgoCD๊ฐ ๋ฐ๋ผ๋ณด๋
deployment.yamlํ์ผ(๋ฒ์ ํ๊ทธ)์ ์์ ํด์ Git์ ์ฌ๋ฆด ๋ Project Access Token์ด ํ์ํฉ๋๋ค.
Protected Branch ํจ์
"ํ ํฐ ๊ถํ ๋ค ์คฌ๋๋ฐ ์ ์ ๋์ง?" ์ ์์ธ์ด์๋๋ฐ,
GitLab์ main์ด๋ develop ๋ธ๋์น๋ ๊ธฐ๋ณธ์ ์ผ๋ก Protected ์ํ์
๋๋ค.
Settings > Repository > Protected branches ๋ฉ๋ด์์
ํด๋น ํ ํฐ์ด Protected ๋ธ๋์น์ ํธ์ํ ์ ์๋๋ก Roles ๊ถํ์ ํ์ธ ํด ์ค์ผ ํฉ๋๋ค.
์ ๋ Maintainers๋ง ๊ฐ๋ฅํ๋๋ก ์ค์ ํด ๋๊ณ ์.. ๊ณ์ Denied๊ฐ ๋์ค์ง ํ๋ฉด์ ์ฐพ์๋ค๋
๋ค์.. ๐
4. ์ฟ ๋ฒ๋คํฐ์ค๋ Docker๋ฅผ ์ฐ์ง ์๋๋ค
ArgoCD๊น์ง ์ฐ๋์ ๋ง์ณค์ต๋๋ค.
์ด์ K3s ํด๋ฌ์คํฐ์ ํ๋(Pod)๊ฐ ์์๊ฒ ๋ ์ผ ํ๋๋ฐ...
ImagePullBackOff ์ํ์์ ๋ฌดํ ๋ก๋ฉ์ด ๊ฑธ๋ฆฝ๋๋ค.
๋ถ๋ช
์์์ daemon.json์ insecure-registries ์ค์ ์ ํ์์์?
ํธ์คํธ์์๋ docker pull์ด ์ ๋๋๋ฐ, ์ K3s๋ง ๋ชป ๊ฐ์ ธ์ฌ๊น์?
'containerd'
๋ฒ์ธ์ K3s์ ๋ฐํ์์ด์์ต๋๋ค.
K3s๋ ๊ธฐ๋ณธ ์ปจํ
์ด๋ ๋ฐํ์์ผ๋ก Docker๊ฐ ์๋ containerd๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ฌ๋ /etc/docker/daemon.json์ ์์ ํด๋ด์ผ K3s๋ ์ณ๋ค๋ ์ ๋ณด๋ ๊ฒ์ด์์ฃ ...
๋์ปค ์ง์์ค๋จ ๊ด๋ จ ์ฟ ๋ฒ๋คํฐ์ค ๋ธ๋ก๊ทธ ์ฃผ์
https://kubernetes.io/blog/2022/02/17/dockershim-faq
ํด๊ฒฐ: registries.yaml
K3s๋ฅผ ์ํ ๋ ์ง์คํธ๋ฆฌ ์ค์ ์ /etc/rancher/k3s/registries.yaml์ด๋ผ๋ ๋ณ๋ ํ์ผ์ ํด์ค์ผ ํฉ๋๋ค.
mirrors:
"xxx.xxx.xxx.xxx:5005":
endpoint:
- "http://xxx.xxx.xxx.xxx:5005"
์ด ์ค์ ์ ํด์ฃผ๊ณ K3s๋ฅผ ์ฌ์์ํ๋, ๊ทธ์ ์ผ ์ด๋ฏธ์ง๋ฅผ ์ ์์ ์ผ๋ก ๋น๊ฒจ์ค๊ธฐ ์์ํ์ต๋๋ค.
์ถ๊ฐ๋ก K8s ๋ด๋ถ์ ํค๊ฐ์ ๊ฐ์ง imagePullSecrets๋ฅผ ์์ฑํ์ฌ deployment์ ๋ฃ์ด์ฃผ์ด์ผ Registry์ ์ ๊ทผํ ์ ์์ต๋๋ค.
5. ๋ฐ์ดํฐ ๋ ์๊ฐ๋ฉด ์ ๋๋๊น (๋ฐฑ์ ์๋ํ)
๋ง์ง๋ง์ผ๋ก, ์๋ฒฝ์ ๋์ํ๋ ๋ฐฑ์
์คํฌ๋ฆฝํธ๋ฅผ Ansible์ ์ถ๊ฐํ์ต๋๋ค.
GitLab๊ณผ Jenkins ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋ฉด ์ ๋๋๊น์.
๊ทธ๋ฐ๋ฐ Jenkins ๋ฐฑ์
์ ์ฃผ์ํ ์ ์ด,
Jenkins๋ ์ ํด ์ํ์ผ ๋๋ SCM ํด๋ง์ด๋ ์ค์๊ฐ ๋ก๊ทธ ๊ธฐ๋ก, ๋ด๋ถ DB ๊ฐฑ์ ๋ฑ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ๊ณ์ ์ํํ๋ฉฐ ํ๋ก์ธ์ค๋ฅผ ์ ์ ํ๊ณ ์์ต๋๋ค.
์ด๋ tar๋ก ํ์ผ์ ๋ฌถ์ผ๋ ค ํ๋ฉด "File changed as we read it" ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฑฐ๋, ๋ฐ์ดํฐ ์ ํฉ์ฑ์ด ๊นจ์ ธ์ ๋ง์ ๋ณต๊ตฌํ๋ ค ํ ๋ ์คํจํ ์ ์์ต๋๋ค.
๊ทธ๋์, ๋ฐฑ์ ์คํฌ๋ฆฝํธ ๋ด ์ปจํ ์ด๋๋ฅผ ์ ์ ๋ฉ์ถ๋ ์ฝ๋๋ฅผ ๋ฃ๋ ๋ฐฉ์์ ํํ์ต๋๋ค.
#!/bin/bash
# Jenkins ์ ์ ์ค์ง
docker-compose stop jenkins
tar -czf $BACKUP_DIR/jenkins_backup_$TIMESTAMP.tar.gz -C $SOURCE_DIR .
# ๋ฐฑ์
ํ ์ฌ์์
docker-compose start jenkins
"์๋น์ค๊ฐ ์ค๋จ๋๋ ๊ฑฐ ์๋๊ฐ์?" ๋ผ๊ณ ํ์ค ์ ์์ง๋ง,
์๋ฒฝ 2์์ ๋น๋ ๋๋ฆด ์ฌ๋์ ์๋ค๊ณ ํ๋จํด์ ๊ณผ๊ฐํ๊ฒ ๋ฉ์ท์ต๋๋ค.
๋ฐ๋ฉด GitLab์ gitlab-backup create๋ผ๋ ๋ช
๋ น์ด๊ฐ ์์ด์ ์ค๋จ ์์ด ํธํ๊ฒ ๊ฐ๋ฅํ๋๋ผ๊ตฌ์. ๐
๋ง๋ฌด๋ฆฌ
[Code Push] -> [Jenkins Build] -> [Docker Push] -> [Manifest Update] -> [ArgoCD Sync] -> [K3s Deploy]

์ด ํ ์ค์ ํ์ดํ๋ผ์ธ์ ์์ฑํ๊ธฐ ์ํด ๊ฒช์๋ ์๋ง์ ์๋ฌ...
๋น์์ ๋จธ๋ฆฌ๋ฅผ ์ฅ์ด๋ฏ์์ง๋ง, ๋๋ถ์ Docker์ K3s, GitLab์ ๊ถํ ์ฒด๊ณ ๋ฑ์ ๋ถ๋ชํ๋ฉฐ ์ดํดํ๊ฒ ๋ ๊ฒ ๊ฐ์ต๋๋ค.
ํน์ ์ ์ฒ๋ผ ์จํ๋ ๋ฏธ์ค ํ๊ฒฝ์์ ๋งจ๋
์ CI/CD๋ฅผ ๊ตฌ์ถํ๋ ค๋ ๋ถ๋ค์ด ๊ณ์ ๋ค๋ฉด,
์ด ์ฝ์ง ๊ธฐ๋ก์ด ์กฐ๊ธ์ด๋๋ง ๋์์ด ๋๊ธธ ๋ฐ๋๋๋ค. ๐
ํ๋ฆฐ ๋ถ๋ถ์ด๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ค๋ฉด ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์!
๊ฐ์ฌํฉ๋๋ค.
