์๋ ํ์ธ์! ์ต๊ทผ Docker ์ด๋ฏธ์ง ๊ตฌ์ถ๊ณผ Kubernetes ๋ฐฐํฌ๋ฅผ ์ํ ๋ฉ์ง ์๋ํ ๋๊ตฌ๊ฐ ๋ง์ด ์ถ์๋์์ต๋๋ค. ์ด๋ฐ ์ ์์ ๋๋ GitLab์ ์ํํด๋ณด๊ณ ๊ทธ ๊ธฐ๋ฅ์ ์ฒ ์ ํ๊ฒ ์ฐ๊ตฌํ๊ณ ๋ฌผ๋ก ํ์ดํ๋ผ์ธ์ ์ค์ ํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๋ณธ ์ํ์ ํํ์ด์ง์์ ์๊ฐ์ ๋ฐ์ ์ ์๋์์ต๋๋ค
์ ์ฌํ ํ๋ก์ธ์ค๋ฅผ ์ฒ์๋ถํฐ ๊ตฌ์ถํ๋ ค๊ณ ์๋ํ์ง๋ง Kubernetes์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ๋ ๋ฐ ์ฌ์ฉํ๋ Gitlab CI์ ๋ฌด๋ฃ ๋๊ตฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ ํ ๊ตฌ์ถ๋์์ต๋๋ค. ์ค๋์ ๋ง์นจ๋ด ๊ทธ๋ค์ ๋ํด ๋ ์์ธํ ์๋ ค ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ด ๊ธฐ์ฌ์์๋ ๋ค์๊ณผ ๊ฐ์ ๋๊ตฌ์ ๋ํด ์ค๋ช
ํฉ๋๋ค.
ํด๊ณ , ํ๋ฒก, ์นด๋์ฝ, ์์ ์ํธ ะธ ๊น๋ฉ CI ์ญ๋์ ์ธ ํ๊ฒฝ์ ์กฐ์ฑํฉ๋๋ค.
๋ด์ฉ๋ฌผ
ํด๊ณ ๋ฅผ ๋ง๋๋ณด์ธ์ Dockerfile ์ค๋น ์นด๋์ฝ๋ฅผ ์์๊ฐ๋ ์ค qbec์ ๋ํด ์์๊ฐ๊ธฐ Kubernetes-executor๋ก Gitlab-runner ์ฌ์ฉํด ๋ณด๊ธฐ qbec์ ์ฌ์ฉํ์ฌ Helm ์ฐจํธ ๋ฐฐํฌ git-crypt ์๊ฐ ๋๊ตฌ ์์ ์ด๋ฏธ์ง ๋ง๋ค๊ธฐ ์ฒซ ๋ฒ์งธ ํ์ดํ๋ผ์ธ๊ณผ ํ๊ทธ๋ณ ์ด๋ฏธ์ง ์กฐ๋ฆฝ ๋ฐฐํฌ ์๋ํ ๋ง์คํฐ๋ก ํธ์ํ ๋ ์ํฐํฉํธ ๋ฐ ์ด์ ๋ธ๋ฆฌ ๋์ ํ๊ฒฝ ์ฑ ๊ฒํ
1. ํด๊ณ ์ ๋ํด ์์๊ฐ๊ธฐ
์ฐ๋ฆฌ ํ๋ก์ ํธ์ ์๋ก Hugo๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋ ๋ฌธ์ ๊ฒ์ ์ฌ์ดํธ๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. Hugo๋ ์ ์ ์ฝํ ์ธ ์์ฑ๊ธฐ์ ๋๋ค.
์ ์ ์์ฑ๊ธฐ์ ๋ํด ์ ๋ชจ๋ฅด์๋ ๋ถ๋ค์ ์ํด ์กฐ๊ธ ๋ ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค. ์ฌ์ฉ์๊ฐ ์์ฒญํ ๋ ์ฆ์ ํ์ด์ง๋ฅผ ์์ฑํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ผ๋ถ PHP๋ฅผ ๊ฐ์ถ ๊ธฐ์กด ์น ์ฌ์ดํธ ์์ง๊ณผ ๋ฌ๋ฆฌ ์ ์ ์์ฑ๊ธฐ๋ ์ฝ๊ฐ ๋ค๋ฅด๊ฒ ์ค๊ณ๋์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ผ๋ฐ์ ์ผ๋ก Markdown ๋งํฌ์ ๋ฐ ํ ๋ง ํ ํ๋ฆฟ์ ํ์ผ ์ธํธ์ธ ์์ค๋ฅผ ๊ฐ์ ธ์จ ๋ค์ ์์ ํ ์์ฑ๋ ์น ์ฌ์ดํธ๋ก ์ปดํ์ผํ ์ ์์ต๋๋ค.
์ฆ, ๊ฒฐ๊ณผ์ ์ผ๋ก ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ ์์ฑ๋ HTML ํ์ผ ์ธํธ๋ฅผ ๋ฐ๊ฒ ๋๋ฉฐ, ์ด๋ฅผ ์ ๋ ดํ ํธ์คํ ์ ์ ๋ก๋ํ๊ณ ์๋ํ๋ ์น์ฌ์ดํธ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
Hugo๋ฅผ ๋ก์ปฌ์ ์ค์นํ๊ณ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค.
์ ์ฌ์ดํธ ์ด๊ธฐํ:
hugo new site docs.example.org
๋์์ git ์ ์ฅ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
cd docs.example.org
git init
์ง๊ธ๊น์ง ์ฐ๋ฆฌ ์ฌ์ดํธ๋ ๊นจ๋ํ์ผ๋ฉฐ ์ฌ๊ธฐ์ ๋ญ๊ฐ๋ฅผ ํ์ํ๋ ค๋ฉด ๋จผ์ ํ ๋ง๋ฅผ ์ฐ๊ฒฐํด์ผ ํฉ๋๋ค. ํ ๋ง๋ ์ฌ์ดํธ๊ฐ ์์ฑ๋๋ ํ ํ๋ฆฟ๊ณผ ์ง์ ๋ ๊ท์น์ ์งํฉ์ผ ๋ฟ์ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ํ
๋ง๋
ํ ๋ง ํ์ผ์ ํ๋ก์ ํธ ์ ์ฅ์์ ์ ์ฅํ ํ์๊ฐ ์๋ค๋ ์ฌ์ค์ ํน๋ณํ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด๊ณ ์ถ์ต๋๋ค. ๋์ ๋ค์์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ์์ ํ์ ๋ชจ๋:
git submodule add https://github.com/matcornic/hugo-theme-learn themes/learn
๋ฐ๋ผ์ ์ ์ฅ์์๋ ํ๋ก์ ํธ์ ์ง์ ๊ด๋ จ๋ ํ์ผ๋ง ํฌํจ๋๋ฉฐ ์ฐ๊ฒฐ๋ ํ ๋ง๋ ํน์ ์ ์ฅ์์ ๋ํ ๋งํฌ์ ์ปค๋ฐ์ผ๋ก ์ ์ง๋ฉ๋๋ค. ์ฆ, ํญ์ ์๋ณธ ์์ค์์ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฉฐ ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค. ํธํ๋์ง ์๋ ๋ณ๊ฒฝ ์ฌํญ.
์ค์ ์ ์์ ํด๋ณด์ config.toml:
baseURL = "http://docs.example.org/"
languageCode = "en-us"
title = "My Docs Site"
theme = "learn"
์ด๋ฏธ ์ด ๋จ๊ณ์์ ๋ค์์ ์คํํ ์ ์์ต๋๋ค.
hugo server
๊ทธ๋ฆฌ๊ณ ์ฃผ์์๋
ํ์ง๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ฝํ ์ธ /_index.md:
# My docs site
## Welcome to the docs!
You will be very smart :-)
์๋ก ์์ฑ๋ ํ์ด์ง์ ์คํฌ๋ฆฐ์ท
์ฌ์ดํธ๋ฅผ ์์ฑํ๋ ค๋ฉด ๋ค์์ ์คํํ์ธ์.
hugo
๋๋ ํ ๋ฆฌ ๋ด์ฉ ๊ณต๊ณต์/ ๊ทธ๋ฆฌ๊ณ ๋น์ ์ ์น์ฌ์ดํธ๊ฐ ๋ ๊ฒ์
๋๋ค.
๋ค, ๊ทธ๋ฐ๋ฐ ์ฆ์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. .gitignore:
echo /public > .gitignore
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .
git commit -m "New site created"
2. Dockerfile ์ค๋น
์ด์ ์ ์ฅ์์ ๊ตฌ์กฐ๋ฅผ ์ ์ํ ์ฐจ๋ก์ ๋๋ค. ๋๋ ๋ณดํต ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํฉ๋๋ค.
.
โโโ deploy
โ โโโ app1
โ โโโ app2
โโโ dockerfiles
โโโ image1
โโโ image2
- ๋์ปคํ์ผ/ โ Dockerfiles๊ฐ ์๋ ๋๋ ํฐ๋ฆฌ์ Docker ์ด๋ฏธ์ง๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ๊ฒ์ด ํฌํจ๋์ด ์์ต๋๋ค.
- ๋ฐฐํฌ/ โ ์ ํ๋ฆฌ์ผ์ด์ ์ Kubernetes์ ๋ฐฐํฌํ๊ธฐ ์ํ ๋๋ ํฐ๋ฆฌ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
๋ฐ๋ผ์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ฒซ ๋ฒ์งธ Dockerfile์ ์์ฑํฉ๋๋ค. dockerfiles/์น์ฌ์ดํธ/Dockerfile
FROM alpine:3.11 as builder
ARG HUGO_VERSION=0.62.0
RUN wget -O- https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-64bit.tar.gz | tar -xz -C /usr/local/bin
ADD . /src
RUN hugo -s /src
FROM alpine:3.11
RUN apk add --no-cache darkhttpd
COPY --from=builder /src/public /var/www
ENTRYPOINT [ "/usr/bin/darkhttpd" ]
CMD [ "/var/www" ]
๋ณด์๋ค์ํผ Dockerfile์๋ ๋ ๊ฐ์ง๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. FROM, ์ด๋ฒ ๊ธฐํ๋ฅผ
๋ฐ๋ผ์ ์ต์ข
์ด๋ฏธ์ง์๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ๋ง ํฌํจ๋ฉ๋๋ค. darkhttpd (๊ฒฝ๋ HTTP ์๋ฒ) ๋ฐ ๊ณต๊ณต์/ โ ์ ์ ์ผ๋ก ์์ฑ๋ ์น์ฌ์ดํธ์ ์ฝํ
์ธ .
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add dockerfiles/website
git commit -m "Add Dockerfile for website"
3. ์นด๋์ฝ๋ฅผ ์์๊ฐ๋ค
๋์ปค ์ด๋ฏธ์ง ๋น๋๋ก์ ์ ๋ ๋ค์์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๋ ค๋ฉด ๋ค์์ ์ฌ์ฉํ์ฌ ์ปจํ ์ด๋๋ฅผ ์คํํ์ธ์. ์นด๋์ฝ ์งํ์ ํ์ฌ ๋น๋ ์ปจํ ์คํธ๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ด๋ docker๋ฅผ ํตํด ๋ก์ปฌ๋ก ์ํํ ์๋ ์์ต๋๋ค.
docker run -ti --rm
-v $PWD:/workspace
-v ~/.docker/config.json:/kaniko/.docker/config.json:ro
gcr.io/kaniko-project/executor:v0.15.0
--cache
--dockerfile=dockerfiles/website/Dockerfile
--destination=registry.gitlab.com/kvaps/docs.example.org/website:v0.0.1
ะะดะต Registry.gitlab.com/kvaps/docs.example.org/website โ ๋์ปค ์ด๋ฏธ์ง์ ์ด๋ฆ, ๋น๋ ํ ๋์ปค ๋ ์ง์คํธ๋ฆฌ์์ ์๋์ผ๋ก ์์๋ฉ๋๋ค.
๋งค๊ฐ ๋ณ์ --์๋์ฒ docker ๋ ์ง์คํธ๋ฆฌ์์ ๋ ์ด์ด๋ฅผ ์บ์ํ ์ ์์ต๋๋ค. ์ฃผ์ด์ง ์์์๋ ํด๋น ๋ ์ด์ด๊ฐ ๋ค์ ์์น์ ์ ์ฅ๋ฉ๋๋ค. Registry.gitlab.com/kvaps/docs.example.org/website/cacheํ์ง๋ง ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค. --์บ์ ์ ์ฅ์.
docker-registry ์คํฌ๋ฆฐ์ท
4. qbec์ ๋ํด ์์๊ฐ๊ธฐ
์ด๋ ์๋ก ๋ค๋ฅธ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ํด๋ฌ์คํฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํด์ผ ํ๊ณ ์ด๋ฅผ Git์์ ์ ์ธ์ ์ผ๋ก ์ค๋ช ํ๋ ค๋ ๊ฒฝ์ฐ์ ํนํ ๊ทธ๋ ์ต๋๋ค.
Qbec์ ์ฌ์ฉํ๋ฉด ํ์ํ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ์ฌ Helm ์ฐจํธ๋ฅผ ๋ ๋๋งํ ๋ค์ ๋ค์ํ ๋ณํ์ ์ ์ฉํ ์ ์๋ ๊ฒ์ ํฌํจํ์ฌ ์ผ๋ฐ ๋งค๋ํ์คํธ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์๋ํ ์ ์์ต๋๋ค. ChartMuseum์ ์ฌ์ฉํ์ธ์. ์ฆ, ์ฐจํธ๊ฐ ์ํ Git์์ ์ง์ ์ฐจํธ๋ฅผ ์ ์ฅํ๊ณ ๋ ๋๋งํ ์ ์์ต๋๋ค.
์์ ๋งํ๋ฏ์ด ์ฐ๋ฆฌ๋ ๋ชจ๋ ๋ฐฐํฌ๋ฅผ ๋๋ ํฐ๋ฆฌ์ ์ ์ฅํฉ๋๋ค. ๋ฐฐํฌ/:
mkdir deploy
cd deploy
์ฒซ ๋ฒ์งธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐํํด ๋ณด๊ฒ ์ต๋๋ค.
qbec init website
cd website
์ด์ ์ฐ๋ฆฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
.
โโโ components
โโโ environments
โ โโโ base.libsonnet
โ โโโ default.libsonnet
โโโ params.libsonnet
โโโ qbec.yaml
ํ์ผ์ ์ดํด๋ณด์ qbec.yaml:
apiVersion: qbec.io/v1alpha1
kind: App
metadata:
name: website
spec:
environments:
default:
defaultNamespace: docs
server: https://kubernetes.example.org:8443
vars: {}
์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ์ฃผ๋ก ๋ค์ ์ฌํญ์ ๊ด์ฌ์ด ์์ต๋๋ค. ์ฌ์ ํ๊ฒฝ, qbec์ ์ด๋ฏธ ์ฐ๋ฆฌ๋ฅผ ์ํ ๊ธฐ๋ณธ ํ๊ฒฝ์ ์์ฑํ์ผ๋ฉฐ ํ์ฌ kubeconfig์์ ์๋ฒ ์ฃผ์์ ๋ค์์คํ์ด์ค๋ฅผ ๊ฐ์ ธ์์ต๋๋ค.
์ด์ ๋ฐฐํฌํ ๋ ๋ํดํธ ๊ฐ ํ๊ฒฝ์์ qbec์ ํญ์ ์ง์ ๋ Kubernetes ํด๋ฌ์คํฐ์ ์ง์ ๋ ๋ค์์คํ์ด์ค์๋ง ๋ฐฐํฌ๋ฉ๋๋ค. ์ฆ, ๋ฐฐํฌ๋ฅผ ์ํํ๊ธฐ ์ํด ๋ ์ด์ ์ปจํ
์คํธ์ ๋ค์์คํ์ด์ค ์ฌ์ด๋ฅผ ์ ํํ ํ์๊ฐ ์์ต๋๋ค.
ํ์ํ ๊ฒฝ์ฐ ์ธ์ ๋ ์ง ์ด ํ์ผ์ ์ค์ ์ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
๋ชจ๋ ํ๊ฒฝ์ ๋ค์์ ์ค๋ช ๋์ด ์์ต๋๋ค. qbec.yaml, ๊ทธ๋ฆฌ๊ณ ํ์ผ์์ params.libsonnet, ์ฌ๊ธฐ์๋ ํด๋น ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ ์์น๊ฐ ๋์ ์์ต๋๋ค.
๋ค์์ผ๋ก ๋ ๊ฐ์ ๋๋ ํฐ๋ฆฌ๊ฐ ํ์๋ฉ๋๋ค.
- ๊ตฌ์ฑ ์์ / โ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ๋งค๋ํ์คํธ๊ฐ ์ฌ๊ธฐ์ ์ ์ฅ๋ฉ๋๋ค. jsonnet ๋ฐ ์ผ๋ฐ yaml ํ์ผ ๋ชจ๋์์ ์ค๋ช ํ ์ ์์ต๋๋ค.
- ํ๊ฒฝ/ โ ์ฌ๊ธฐ์๋ ํ๊ฒฝ์ ๋ํ ๋ชจ๋ ๋ณ์(๋งค๊ฐ๋ณ์)๋ฅผ ์ค๋ช ํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๊ฐ์ ํ์ผ์ด ์์ต๋๋ค.
- ํ๊ฒฝ/base.libsonnet - ๋ชจ๋ ํ๊ฒฝ์ ๋ํ ๊ณตํต ๋งค๊ฐ๋ณ์๊ฐ ํฌํจ๋ฉ๋๋ค.
- ํ๊ฒฝ/default.libsonnet โ ํ๊ฒฝ์ ๋ํด ์ฌ์ ์๋ ๋งค๊ฐ๋ณ์๋ฅผ ํฌํจํฉ๋๋ค. ๋ํดํธ ๊ฐ
์ด์ด๋ณด์ ํ๊ฒฝ/base.libsonnet ๊ฑฐ๊ธฐ์ ์ฒซ ๋ฒ์งธ ๊ตฌ์ฑ์์์ ๋ํ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
{
components: {
website: {
name: 'example-docs',
image: 'registry.gitlab.com/kvaps/docs.example.org/website:v0.0.1',
replicas: 1,
containerPort: 80,
servicePort: 80,
nodeSelector: {},
tolerations: [],
ingressClass: 'nginx',
domain: 'docs.example.org',
},
},
}
์ฒซ ๋ฒ์งธ ๊ตฌ์ฑ ์์๋ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ๊ตฌ์ฑ ์์/website.jsonnet:
local env = {
name: std.extVar('qbec.io/env'),
namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.website;
[
{
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: {
labels: { app: params.name },
name: params.name,
},
spec: {
replicas: params.replicas,
selector: {
matchLabels: {
app: params.name,
},
},
template: {
metadata: {
labels: { app: params.name },
},
spec: {
containers: [
{
name: 'darkhttpd',
image: params.image,
ports: [
{
containerPort: params.containerPort,
},
],
},
],
nodeSelector: params.nodeSelector,
tolerations: params.tolerations,
imagePullSecrets: [{ name: 'regsecret' }],
},
},
},
},
{
apiVersion: 'v1',
kind: 'Service',
metadata: {
labels: { app: params.name },
name: params.name,
},
spec: {
selector: {
app: params.name,
},
ports: [
{
port: params.servicePort,
targetPort: params.containerPort,
},
],
},
},
{
apiVersion: 'extensions/v1beta1',
kind: 'Ingress',
metadata: {
annotations: {
'kubernetes.io/ingress.class': params.ingressClass,
},
labels: { app: params.name },
name: params.name,
},
spec: {
rules: [
{
host: params.domain,
http: {
paths: [
{
backend: {
serviceName: params.name,
servicePort: params.servicePort,
},
},
],
},
},
],
},
},
]
์ด ํ์ผ์์๋ ์ธ ๊ฐ์ง Kubernetes ์ํฐํฐ๋ฅผ ํ ๋ฒ์ ์ค๋ช ํ์ต๋๋ค. ์ ๊ฐ, ์๋ฐฐ ะธ ์ ๊ตฌ. ์ํ๋ค๋ฉด ์ด๋ฅผ ๋ค๋ฅธ ๊ตฌ์ฑ ์์์ ๋ฃ์ ์ ์์ง๋ง ์ด ๋จ๊ณ์์๋ ํ๋๋ง ์์ด๋ ์ถฉ๋ถํฉ๋๋ค.
๊ตฌ๋ฌธ jsonnet ์ผ๋ฐ json๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ์์น์ ์ผ๋ก ์ผ๋ฐ json์ ์ด๋ฏธ ์ ํจํ jsonnet์ด๋ฏ๋ก ์ฒ์์๋ ๋ค์๊ณผ ๊ฐ์ ์จ๋ผ์ธ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ฌ์ธ ์ ์์ต๋๋ค. yaml2json ์ผ๋ฐ์ ์ธ yaml์ json์ผ๋ก ๋ณํํ๊ฑฐ๋ ๊ตฌ์ฑ ์์์ ๋ณ์๊ฐ ํฌํจ๋์ด ์์ง ์์ ๊ฒฝ์ฐ ์ผ๋ฐ yaml ํ์์ผ๋ก ์ค๋ช ํ ์ ์์ต๋๋ค.
์์ ํ ๋ jsonnet ํธ์ง๊ธฐ์ฉ ํ๋ฌ๊ทธ์ธ์ ์ค์นํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์๋ฅผ ๋ค์ด vim์ฉ ํ๋ฌ๊ทธ์ธ์ด ์์ต๋๋ค. vim-jsonnet, ๊ตฌ๋ฌธ ๊ฐ์กฐ๋ฅผ ์ผ๊ณ ์๋์ผ๋ก ์คํ๋ฉ๋๋ค. jsonnet fmt ์ ์ฅํ ๋๋ง๋ค(jsonnet ์ค์น ํ์)
๋ชจ๋ ๊ฒ์ด ์ค๋น๋์์ต๋๋ค. ์ด์ ๋ฐฐํฌ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ป์ ๊ฒ์ ํ์ธํ๊ธฐ ์ํด ๋ค์์ ์คํํด ๋ด ์๋ค:
qbec show default
์ถ๋ ฅ์๋ ๊ธฐ๋ณธ ํด๋ฌ์คํฐ์ ์ ์ฉ๋ ๋ ๋๋ง๋ yaml ๋งค๋ํ์คํธ๊ฐ ํ์๋ฉ๋๋ค.
์ข์ต๋๋ค. ์ด์ ์ ์ฒญํ์ธ์.
qbec apply default
์ถ๋ ฅ์์ ํด๋ฌ์คํฐ์์ ์ํ๋ ์์ ์ ํญ์ ๋ณผ ์ ์์ผ๋ฉฐ, qbec๋ ๋ค์์ ์ ๋ ฅํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ๋์ํ๋๋ก ์์ฒญํฉ๋๋ค. y ๋น์ ์ ์๋๋ฅผ ํ์ธํ ์ ์์ ๊ฒ์ ๋๋ค.
์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ค๋น๋์ด ๋ฐฐํฌ๋์์ต๋๋ค!
๋ณ๊ฒฝํ๋ ๊ฒฝ์ฐ ์ธ์ ๋ ์ง ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
qbec diff default
์ด๋ฌํ ๋ณ๊ฒฝ ์ฌํญ์ด ํ์ฌ ๋ฐฐํฌ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ํ์ธํ๋ ค๋ฉด
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
cd ../..
git add deploy/website
git commit -m "Add deploy for website"
5. Kubernetes-executor๋ก Gitlab-runner ์ฌ์ฉํด ๋ณด๊ธฐ
์ต๊ทผ๊น์ง๋ ์ผ๋ฐ๋ง ์ฌ์ฉํ๋๋ฐ gitlab ๋ฌ๋ ์ ๋๋ docker-executor๊ฐ ์๋ ์ฌ์ ์ค๋น๋ ๋จธ์ (LXC ์ปจํ ์ด๋)์์. ์ฒ์์๋ gitlab์ ์ ์ญ์ ์ผ๋ก ์ ์๋ ์ฌ๋ฌ ๋ฌ๋๊ฐ ์์์ต๋๋ค. ๊ทธ๋ค์ ๋ชจ๋ ํ๋ก์ ํธ์ ๋ํ ๋์ปค ์ด๋ฏธ์ง๋ฅผ ์์งํ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ค์ต์์ ์ ์ ์๋ฏ์ด ์ด ์ต์ ์ ์ค์ฉ์ฑ๊ณผ ์์ ์ฑ ์ธก๋ฉด์์ ๊ฐ์ฅ ์ด์์ ์ธ ๊ฒ์ ์๋๋๋ค. ๊ฐ ํ๋ก์ ํธ ๋๋ ๊ฐ ํ๊ฒฝ์ ๋ํด ๋ณ๋์ ์คํ๊ธฐ๋ฅผ ๋ฐฐํฌํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ข๊ณ ์ด๋ ์ ์ผ๋ก ๋ ์ ํํฉ๋๋ค.
๋คํํ๋ ์ด๋ ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ๋ ๋ฐฐํฌํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. gitlab ๋ฌ๋ Kubernetes์์ ํ๋ก์ ํธ์ ์ผ๋ถ๋ก ์ง์ ์ ์ผ๋ก.
Gitlab์ Kubernetes์ gitlab-runner๋ฅผ ๋ฐฐํฌํ๊ธฐ ์ํด ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง Helm ์ฐจํธ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋น์ ์ด ํด์ผ ํ ์ผ์ ์์๋ด๋ ๊ฒ๋ฟ์ ๋๋ค ๋ฑ๋ก ํ ํฐ ์ฐ๋ฆฌ ํ๋ก์ ํธ๋ฅผ ์ํด ์ค์ -> CI/CD -> ๋ฐ๋ ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ helm์ ์ ๋ฌํฉ๋๋ค.
helm repo add gitlab https://charts.gitlab.io
helm install gitlab-runner
--set gitlabUrl=https://gitlab.com
--set runnerRegistrationToken=yga8y-jdCusVDn_t4Wxc
--set rbac.create=true
gitlab/gitlab-runner
์ฅ์ :
https://gitlab.com โ Gitlab ์๋ฒ์ ์ฃผ์์ ๋๋ค.- yga8y-jdCusVDn_t4Wxc โ ํ๋ก์ ํธ์ ๋ฑ๋ก ํ ํฐ.
- rbac.create=true โ kubernetes-executor๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ์ํํ๊ธฐ ์ํ ํฌ๋๋ฅผ ์์ฑํ๋ ๋ฐ ํ์ํ ๊ถํ์ ์คํ์์๊ฒ ์ ๊ณตํฉ๋๋ค.
๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ฃ๋๋ฉด ํด๋น ์น์ ์ ๋ฑ๋ก๋ ์ฃผ์๊ฐ ํ์๋ฉ๋๋ค. ์ฃผ์, ํ๋ก์ ํธ ์ค์ ์์.
์ถ๊ฐ๋ ์คํ๊ธฐ์ ์คํฌ๋ฆฐ์ท
๊ทธ๋ ๊ฒ ๊ฐ๋จํฉ๋๊น? - ๋ค, ์ ๋ง ๊ฐ๋จํด์! ๋ ์ด์ ์๋์ผ๋ก ๋ฌ๋๋ฅผ ๋ฑ๋กํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์์ต๋๋ค. ์ด์ ๋ถํฐ ๋ฌ๋๋ ์๋์ผ๋ก ์์ฑ๋๊ณ ์ญ์ ๋ฉ๋๋ค.
6. QBEC๋ฅผ ์ฌ์ฉํ์ฌ Helm ์ฐจํธ ๋ฐฐํฌ
์ฐ๋ฆฌ๊ฐ ๊ณ ๋ คํ๊ธฐ๋ก ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ gitlab ๋ฌ๋ ํ๋ก์ ํธ์ ์ผ๋ถ์ด๋ฏ๋ก Git ์ ์ฅ์์ ์ค๋ช ํ ์ฐจ๋ก์ ๋๋ค.
๋ณ๋์ ๊ตฌ์ฑ ์์๋ก ์ค๋ช ํ ์ ์์ต๋๋ค. ์น ์ฌ์ดํธํ์ง๋ง ์์ผ๋ก๋ ๋ค๋ฅธ ๋ณต์ฌ๋ณธ์ ๋ฐฐํฌํ ๊ณํ์ ๋๋ค. ์น ์ฌ์ดํธ ๋งค์ฐ ์์ฃผ, ๋ฌ๋ฆฌ gitlab ๋ฌ๋, ์ด๋ Kubernetes ํด๋ฌ์คํฐ๋น ํ ๋ฒ๋ง ๋ฐฐํฌ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ด๋ฅผ ์ํ ๋ณ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐํํด ๋ณด๊ฒ ์ต๋๋ค.
cd deploy
qbec init gitlab-runner
cd gitlab-runner
์ด๋ฒ์๋ Kubernetes ์ํฐํฐ๋ฅผ ์๋์ผ๋ก ์ค๋ช ํ์ง ์๊ณ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง Helm ์ฐจํธ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. qbec์ ์ฅ์ ์ค ํ๋๋ Git ์ ์ฅ์์์ ์ง์ Helm ์ฐจํธ๋ฅผ ๋ ๋๋งํ๋ ๊ธฐ๋ฅ์ ๋๋ค.
git ํ์ ๋ชจ๋์ ์ฌ์ฉํ์ฌ ์ฐ๊ฒฐํด ๋ณด๊ฒ ์ต๋๋ค.
git submodule add https://gitlab.com/gitlab-org/charts/gitlab-runner vendor/gitlab-runner
์ด์ ๋๋ ํ ๋ฆฌ ๋ฒค๋/gitlab-runner gitlab-runner์ ๋ํ ์ฐจํธ๊ฐ ์๋ ์ ์ฅ์๊ฐ ์์ต๋๋ค.
๋น์ทํ ๋ฐฉ์์ผ๋ก ๋ค๋ฅธ ์ ์ฅ์(์: ๊ณต์ ์ฐจํธ๊ฐ ์๋ ์ ์ฒด ์ ์ฅ์)๋ฅผ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
https://github.com/helm/charts
๊ตฌ์ฑํ์ ์ค๋ช ํ์๋ฉด ๊ตฌ์ฑ ์์/gitlab-runner.jsonnet:
local env = {
name: std.extVar('qbec.io/env'),
namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.gitlabRunner;
std.native('expandHelmTemplate')(
'../vendor/gitlab-runner',
params.values,
{
nameTemplate: params.name,
namespace: env.namespace,
thisFile: std.thisFile,
verbose: true,
}
)
์ฒซ ๋ฒ์งธ ์ฃผ์ฅ ExpandHelmTemplate ์ฐจํธ์ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ ๋ค์ ๋งค๊ฐ๋ณ์.๊ฐ, ํ๊ฒฝ ๋งค๊ฐ๋ณ์์์ ๊ฐ์ ธ์จ ๋ค์
- ์ด๋ฆํ ํ๋ฆฟ โ ๋ฆด๋ฆฌ์ค ์ด๋ฆ
- ๋ค์ ์คํ์ด์ค โ helm์ผ๋ก ๋ค์์คํ์ด์ค๊ฐ ์ ์ก๋จ
- ์ด ํ์ผ โ ํ์ฌ ํ์ผ์ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ๋ ํ์ ๋งค๊ฐ๋ณ์
- ๋ง ์๊ฐ ๋ง์ - ๋ช ๋ น์ ๋ณด์ฌ์ค๋๋ค ์กฐํ ํ ํ๋ฆฟ ์ฐจํธ๋ฅผ ๋ ๋๋งํ ๋ ๋ชจ๋ ์ธ์ ํฌํจ
์ด์ ๊ตฌ์ฑ์์์ ๋งค๊ฐ๋ณ์๋ฅผ ์ค๋ช ํ๊ฒ ์ต๋๋ค. ํ๊ฒฝ/base.libsonnet:
local secrets = import '../secrets/base.libsonnet';
{
components: {
gitlabRunner: {
name: 'gitlab-runner',
values: {
gitlabUrl: 'https://gitlab.com/',
rbac: {
create: true,
},
runnerRegistrationToken: secrets.runnerRegistrationToken,
},
},
},
}
์ฃผ์ ๋ฌ๋๋ฑ๋กํ ํฐ ์ฐ๋ฆฌ๋ ์ธ๋ถ ํ์ผ์์ ๊ฐ์ ธ์ต๋๋ค ๋น๋ฐ/base.libsonnet, ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
{
runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}
๋ชจ๋ ๊ฒ์ด ์๋ํ๋์ง ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
qbec show default
๋ชจ๋ ๊ฒ์ด ์ ์์ด๋ฉด Helm์ ํตํด ์ด์ ์ ๋ฐฐํฌํ ๋ฆด๋ฆฌ์ค๋ฅผ ์ญ์ ํ ์ ์์ต๋๋ค.
helm uninstall gitlab-runner
๋์ผํ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌํ๋, qbec์ ํตํด:
qbec apply default
7. git-crypt ์๊ฐ
ํ์ฌ gitlab-runner์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
.
โโโ components
โ โโโ gitlab-runner.jsonnet
โโโ environments
โ โโโ base.libsonnet
โ โโโ default.libsonnet
โโโ params.libsonnet
โโโ qbec.yaml
โโโ secrets
โ โโโ base.libsonnet
โโโ vendor
โโโ gitlab-runner (submodule)
ํ์ง๋ง Git์ ๋น๋ฐ์ ์ ์ฅํ๋ ๊ฒ์ ์์ ํ์ง ์์ต๋๋ค. ๊ทธ๋ ์ฃ ? ๊ทธ๋์ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ์ ์ ํ๊ฒ ์ํธํํด์ผ ํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ํ๋์ ๋ณ์ ๋๋ฌธ์ ์ด๊ฒ์ด ํญ์ ์๋ฏธ๊ฐ ์๋ ๊ฒ์ ์๋๋๋ค. ๋ค์์ผ๋ก ๋น๋ฐ์ ์ ์กํ ์ ์์ต๋๋ค. ํ๋ฒก CI ์์คํ ์ ํ๊ฒฝ ๋ณ์๋ฅผ ํตํด.
๊ทธ๋ฌ๋ ๋ ๋ง์ ๋น๋ฐ์ ํฌํจํ ์ ์๋ ๋ ๋ณต์กํ ํ๋ก์ ํธ๋ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ผ๋ฉฐ, ์ด๋ฅผ ๋ชจ๋ ํ๊ฒฝ ๋ณ์๋ฅผ ํตํด ์ ์กํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค.๊ฒ๋ค๊ฐ ์ด ๊ฒฝ์ฐ์๋ ๋ค์๊ณผ ๊ฐ์ ํ๋ฅญํ ๋๊ตฌ์ ๋ํด ๋งํ ์ ์์ต๋๋ค. ์์ ์ํธ.
์์ ์ํธ Git์ ๊ฒฝ์ฐ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ๋น๋ฐ์ ์ ์ฒด ๊ธฐ๋ก์ ์ ์ฅํ๊ณ ์ถฉ๋์ ๋น๊ต, ๋ณํฉ ๋ฐ ํด๊ฒฐํ ์ ์๋ค๋ ์ ์์๋ ํธ๋ฆฌํฉ๋๋ค.
์ค์น ํ ๊ฐ์ฅ ๋จผ์ ํ ์ผ์ ์์ ์ํธ ์ ์ฅ์์ ๋ํ ํค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
git crypt init
PGP ํค๊ฐ ์์ผ๋ฉด ์ฆ์ ์ด ํ๋ก์ ํธ์ ๊ณต๋ ์์ ์๋ก ์์ ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
git-crypt add-gpg-user [email protected]
์ด๋ ๊ฒ ํ๋ฉด ์ธ์ ๋ ์ง ๊ฐ์ธ ํค๋ฅผ ์ฌ์ฉํ์ฌ ์ด ์ ์ฅ์์ ์ํธ๋ฅผ ํด๋ ํ ์ ์์ต๋๋ค.
PGP ํค๊ฐ ์๊ณ ์์ํ์ง ๋ชปํ ๊ฒฝ์ฐ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํ๋ก์ ํธ ํค๋ฅผ ๋ด๋ณด๋ผ ์ ์์ต๋๋ค.
git crypt export-key /path/to/keyfile
๋ฐ๋ผ์ ์์ถ์ ํ ์ฌ๋์ ๋๊ตฌ๋ ํค ํ์ผ ์ ์ฅ์๋ฅผ ํด๋ ํ ์ ์์ต๋๋ค.
์ด์ ์ฒซ ๋ฒ์งธ ๋น๋ฐ์ ์ค์ ํ ์๊ฐ์
๋๋ค.
์ฐ๋ฆฌ๊ฐ ์์ง ๋๋ ํ ๋ฆฌ์ ์๋ค๋ ๊ฒ์ ์๊ธฐ์์ผ ๋๋ฆฌ๊ฒ ์ต๋๋ค. ๋ฐฐํฌ/gitlab-runner/, ๋๋ ํ ๋ฆฌ๊ฐ ์๋ ๊ณณ ๋น๋ฐ/, ๊ทธ ์์ ์๋ ๋ชจ๋ ํ์ผ์ ์ํธํํ๊ฒ ์ต๋๋ค. ์ด๋ฅผ ์ํด ํ์ผ์ ์์ฑํ๊ฒ ์ต๋๋ค. ๋น๋ฐ/.gitattributes ๋ค์ ๋ด์ฉ์ผ๋ก:
* filter=git-crypt diff=git-crypt
.gitattributes !filter !diff
๋ด์ฉ์์ ๋ณผ ์ ์๋ฏ์ด ๋ชจ๋ ํ์ผ์ด ๋ง์คํฌ๋์ด ์์ต๋๋ค. * ํตํด ๊ตฌ๋๋ฉ๋๋ค ์์ ์ํธ, ๋๋ถ๋ถ์ ์ ์ธํ๊ณ .git์์ฑ
๋ค์์ ์คํํ์ฌ ์ด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
git crypt status -e
์ถ๋ ฅ์ ์ํธํ๊ฐ ํ์ฑํ๋ ์ ์ฅ์์ ๋ชจ๋ ํ์ผ ๋ชฉ๋ก์ ๋๋ค.
๊ทธ๊ฒ ๋ค์ ๋๋ค. ์ด์ ๋ณ๊ฒฝ ์ฌํญ์ ์์ ํ๊ฒ ์ปค๋ฐํ ์ ์์ต๋๋ค.
cd ../..
git add .
git commit -m "Add deploy for gitlab-runner"
์ ์ฅ์๋ฅผ ์ฐจ๋จํ๋ ค๋ฉด ๋ค์์ ์คํํ์ธ์.
git crypt lock
์ํธํ๋ ๋ชจ๋ ํ์ผ์ ์ฆ์ ๋ฐ์ด๋๋ฆฌ๋ก ๋ณํ๋์ด ์ฝ์ ์ ์๊ฒ ๋ฉ๋๋ค.
์ ์ฅ์๋ฅผ ๋ณตํธํํ๋ ค๋ฉด ๋ค์์ ์คํํ์ธ์.
git crypt unlock
8. ๋๊ตฌ ์์ ์ด๋ฏธ์ง ๋ง๋ค๊ธฐ
๋๊ตฌ ์์ ์ด๋ฏธ์ง๋ ํ๋ก์ ํธ๋ฅผ ๋ฐฐํฌํ๋ ๋ฐ ์ฌ์ฉํ ๋ชจ๋ ๋๊ตฌ๊ฐ ํฌํจ๋ ์ด๋ฏธ์ง์ ๋๋ค. Gitlab ์คํ๊ธฐ๊ฐ ์ผ๋ฐ์ ์ธ ๋ฐฐํฌ ์์ ์ ์ํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์ฌ๊ธฐ์๋ ๋ชจ๋ ๊ฒ์ด ๊ฐ๋จํฉ๋๋ค. ์ ๊ฒ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. dockerfiles/๋๊ตฌ ์์/Dockerfile ๋ค์ ๋ด์ฉ์ผ๋ก:
FROM alpine:3.11
RUN apk add --no-cache git git-crypt
RUN QBEC_VER=0.10.3
&& wget -O- https://github.com/splunk/qbec/releases/download/v${QBEC_VER}/qbec-linux-amd64.tar.gz
| tar -C /tmp -xzf -
&& mv /tmp/qbec /tmp/jsonnet-qbec /usr/local/bin/
RUN KUBECTL_VER=1.17.0
&& wget -O /usr/local/bin/kubectl
https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/linux/amd64/kubectl
&& chmod +x /usr/local/bin/kubectl
RUN HELM_VER=3.0.2
&& wget -O- https://get.helm.sh/helm-v${HELM_VER}-linux-amd64.tar.gz
| tar -C /tmp -zxf -
&& mv /tmp/linux-amd64/helm /usr/local/bin/helm
๋ณด์๋ค์ํผ ์ด ์ด๋ฏธ์ง์์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ๋ ๋ฐ ์ฌ์ฉํ ๋ชจ๋ ์ ํธ๋ฆฌํฐ๋ฅผ ์ค์นํฉ๋๋ค. ์ฌ๊ธฐ์๋ ํ์ํ์ง ์์ต๋๋ค. ์ฟ ๋ฒ ํ, ๊ทธ๋ฌ๋ ํ์ดํ๋ผ์ธ ์ค์ ๋จ๊ณ์์ ์ด๋ฅผ ๊ฐ์ง๊ณ ๋๊ณ ์ถ์ ์๋ ์์ต๋๋ค.
๋ํ Kubernetes์ ํต์ ํ๊ณ ๋ฐฐํฌํ๋ ค๋ฉด gitlab-runner์์ ์์ฑ๋ Pod์ ๋ํ ์ญํ ์ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด gitlab-runner๊ฐ ์๋ ๋๋ ํฐ๋ฆฌ๋ก ์ด๋ํด ๋ณด๊ฒ ์ต๋๋ค.
cd deploy/gitlab-runner
๊ทธ๋ฆฌ๊ณ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ์ถ๊ฐํ์ธ์ ๊ตฌ์ฑ ์์/rbac.jsonnet:
local env = {
name: std.extVar('qbec.io/env'),
namespace: std.extVar('qbec.io/defaultNs'),
};
local p = import '../params.libsonnet';
local params = p.components.rbac;
[
{
apiVersion: 'v1',
kind: 'ServiceAccount',
metadata: {
labels: {
app: params.name,
},
name: params.name,
},
},
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'Role',
metadata: {
labels: {
app: params.name,
},
name: params.name,
},
rules: [
{
apiGroups: [
'*',
],
resources: [
'*',
],
verbs: [
'*',
],
},
],
},
{
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'RoleBinding',
metadata: {
labels: {
app: params.name,
},
name: params.name,
},
roleRef: {
apiGroup: 'rbac.authorization.k8s.io',
kind: 'Role',
name: params.name,
},
subjects: [
{
kind: 'ServiceAccount',
name: params.name,
namespace: env.namespace,
},
],
},
]
๋ํ ํ๊ฒฝ/base.libsonnet, ์ด์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
local secrets = import '../secrets/base.libsonnet';
{
components: {
gitlabRunner: {
name: 'gitlab-runner',
values: {
gitlabUrl: 'https://gitlab.com/',
rbac: {
create: true,
},
runnerRegistrationToken: secrets.runnerRegistrationToken,
runners: {
serviceAccountName: $.components.rbac.name,
image: 'registry.gitlab.com/kvaps/docs.example.org/toolbox:v0.0.1',
},
},
},
rbac: {
name: 'gitlab-runner-deploy',
},
},
}
์ฃผ์ $.comComponents.rbac.name ~์ ์ฐธ๊ณ ํ์ฌ name ๊ตฌ์ฑ์์์ฉ ๋ฐฑํฉ
๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
qbec diff default
Kubernetes์ ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ฉํฉ๋๋ค.
qbec apply default
๋ํ ๋ณ๊ฒฝ ์ฌํญ์ git์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
cd ../..
git add dockerfiles/toolbox
git commit -m "Add Dockerfile for toolbox"
git add deploy/gitlab-runner
git commit -m "Configure gitlab-runner to use toolbox"
9. ์ฒซ ๋ฒ์งธ ํ์ดํ๋ผ์ธ๊ณผ ํ๊ทธ๋ณ ์ด๋ฏธ์ง ์กฐ๋ฆฝ
ํ๋ก์ ํธ์ ๋ฃจํธ์์ ์ฐ๋ฆฌ๋ ๋ง๋ค ๊ฒ์ ๋๋ค .gitlab-ci.yml ๋ค์ ๋ด์ฉ์ผ๋ก:
.build_docker_image:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug-v0.15.0
entrypoint: [""]
before_script:
- echo "{"auths":{"$CI_REGISTRY":{"username":"$CI_REGISTRY_USER","password":"$CI_REGISTRY_PASSWORD"}}}" > /kaniko/.docker/config.json
build_toolbox:
extends: .build_docker_image
script:
- /kaniko/executor --cache --context $CI_PROJECT_DIR/dockerfiles/toolbox --dockerfile $CI_PROJECT_DIR/dockerfiles/toolbox/Dockerfile --destination $CI_REGISTRY_IMAGE/toolbox:$CI_COMMIT_TAG
only:
refs:
- tags
build_website:
extends: .build_docker_image
variables:
GIT_SUBMODULE_STRATEGY: normal
script:
- /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_TAG
only:
refs:
- tags
์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๊ฒ์ ์ฐธ๊ณ ํ์ญ์์ค GIT_SUBMODULE_STRATEGY: ์ ์ ์คํ ์ ์ ํ์ ๋ชจ๋์ ๋ช ์์ ์ผ๋ก ์ด๊ธฐํํด์ผ ํ๋ ์์ ์ ๊ฒฝ์ฐ.
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .gitlab-ci.yml
git commit -m "Automate docker build"
๋๋ ์ด๊ฒ์ ๋ฒ์ ์ด๋ผ๊ณ ์์ ํ๊ฒ ๋ถ๋ฅผ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. v0.0.1 ํ๊ทธ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
git tag v0.0.1
์ ๋ฒ์ ์ ์ถ์ํด์ผ ํ ๋๋ง๋ค ํ๊ทธ๋ฅผ ์ถ๊ฐํ ๊ฒ์ ๋๋ค. Docker ์ด๋ฏธ์ง์ ํ๊ทธ๋ Git ํ๊ทธ์ ์ฐ๊ฒฐ๋ฉ๋๋ค. ์ ํ๊ทธ๊ฐ ํฌํจ๋ ๊ฐ ํธ์๋ ์ด ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ๋น๋๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
ํด๋ณด์ ์์ ํธ์ --ํ๊ทธ, ์ฒซ ๋ฒ์งธ ํ์ดํ๋ผ์ธ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฒซ ๋ฒ์งธ ํ์ดํ๋ผ์ธ์ ์คํฌ๋ฆฐ์ท
ํ๊ทธ๋ฅผ ํตํ ์ด์ ๋ธ๋ฆฌ๋ Docker ์ด๋ฏธ์ง ๊ตฌ์ถ์๋ ์ ํฉํ์ง๋ง Kubernetes์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ๋ ๋ฐ๋ ์ ํฉํ์ง ์๋ค๋ ์ฌ์ค์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ์ด์ ์ปค๋ฐ์ ์ ํ๊ทธ๋ฅผ ํ ๋นํ ์ ์์ผ๋ฏ๋ก ์ด ๊ฒฝ์ฐ ํด๋น ํ๊ทธ์ ๋ํ ํ์ดํ๋ผ์ธ์ ์ด๊ธฐํํ๋ฉด ์ด์ ๋ฒ์ ์ด ๋ฐฐํฌ๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ผ๋ฐ์ ์ผ๋ก ๋์ปค ์ด๋ฏธ์ง ๋น๋๊ฐ ํ๊ทธ์ ์ฐ๊ฒฐ๋๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ถ๊ธฐ์ ๋ฐฐํฌ๋ฉ๋๋ค. ์์ฌ, ์์ง๋ ์ด๋ฏธ์ง์ ๋ฒ์ ์ด ํ๋์ฝ๋ฉ๋ฉ๋๋ค. ๊ฐ๋จํ ๋๋๋ฆฌ๊ธฐ๋ก ๋กค๋ฐฑ์ ์ด๊ธฐํํ ์ ์๋ ๊ณณ์ ๋๋ค. ์์ฌ-๊ฐ์ง.
10. ๋ฐฐํฌ ์๋ํ
Gitlab-runner๊ฐ ๋น๋ฐ์ ํด๋ ํ๋ ค๋ฉด ์ ์ฅ์ ํค๋ฅผ ๋ด๋ณด๋ด๊ณ ์ด๋ฅผ CI ํ๊ฒฝ ๋ณ์์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
git crypt export-key /tmp/docs-repo.key
base64 -w0 /tmp/docs-repo.key; echo
๊ฒฐ๊ณผ ์ค์ Gitlab์ ์ ์ฅํ๊ฒ ์ต๋๋ค. ์ด๋ฅผ ์ํด ํ๋ก์ ํธ ์ค์ ์ผ๋ก ์ด๋ํ๊ฒ ์ต๋๋ค.
์ค์ -> CI/CD -> ๋ณ์
๊ทธ๋ฆฌ๊ณ ์ ๋ณ์๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
ํ์
ํค
๊ฐ์น๊ด
๋ณดํธ
๊ฐ๋ฉด
๋ฒ์
File
GITCRYPT_KEY
<your string>
true
(ํ๋ จ ์ค์ ๋น์ ์ ํ ์ ์์ต๋๋ค false
)
true
All environments
์ถ๊ฐ๋ ๋ณ์์ ์คํฌ๋ฆฐ์ท
์ด์ ์ ๋ฐ์ดํธํด ๋ณด๊ฒ ์ต๋๋ค. .gitlab-ci.yml ๊ทธ๊ฒ์ ์ถ๊ฐ :
.deploy_qbec_app:
stage: deploy
only:
refs:
- master
deploy_gitlab_runner:
extends: .deploy_qbec_app
variables:
GIT_SUBMODULE_STRATEGY: normal
before_script:
- base64 -d "$GITCRYPT_KEY" | git-crypt unlock -
script:
- qbec apply default --root deploy/gitlab-runner --force:k8s-context __incluster__ --wait --yes
deploy_website:
extends: .deploy_qbec_app
script:
- qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes
์ฌ๊ธฐ์์๋ qbec์ ๋ํ ๋ช ๊ฐ์ง ์๋ก์ด ์ต์ ์ ํ์ฑํํ์ต๋๋ค.
- --์ผ๋ถ/์ฑ ๋ฃจํธ โ ํน์ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
- --force:k8s-์ปจํ ์คํธ __incluster__ - ์ด๋ gtilab-runner๊ฐ ์คํ ์ค์ธ ๋์ผํ ํด๋ฌ์คํฐ์์ ๋ฐฐํฌ๊ฐ ๋ฐ์ํจ์ ๋ํ๋ด๋ ๋ง๋ฒ ๋ณ์์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด qbec์ด kubeconfig์์ ์ ํฉํ Kubernetes ์๋ฒ๋ฅผ ์ฐพ์ผ๋ ค๊ณ ์๋ํ๊ธฐ ๋๋ฌธ์ ์ด๋ ํ์ํฉ๋๋ค.
- --๊ธฐ๋ค๋ฆฌ๋ค โ qbec์ด ์์ฑํ ๋ฆฌ์์ค๊ฐ ์ค๋น ์ํ๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ๋ค์ ์ฑ๊ณต์ ์ธ ์ข ๋ฃ ์ฝ๋๋ก ์ข ๋ฃํ๋๋ก ๊ฐ์ ํฉ๋๋ค.
- -์ - ๋จ์ํ ๋ํํ ์์ ๋นํ์ฑํํฉ๋๋ค. ํ์คํฉ๋๊น? ๋ฐฐํฌํ ๋.
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .gitlab-ci.yml
git commit -m "Automate deploy"
๊ทธ๋ฆฌ๊ณ ํ์ git push ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ป๊ฒ ๋ฐฐํฌ๋์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ ๋ฒ์งธ ํ์ดํ๋ผ์ธ์ ์คํฌ๋ฆฐ์ท
11. ๋ง์คํฐ๋ก ํธ์ํ ๋ ์ํฐํฉํธ ๋ฐ ์ด์
๋ธ๋ฆฌ
์ผ๋ฐ์ ์ผ๋ก ์์ ์ค๋ช ๋ ๋จ๊ณ๋ ๊ฑฐ์ ๋ชจ๋ ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ๊ตฌ์ถํ๊ณ ์ ๊ณตํ๋ ๋ฐ ์ถฉ๋ถํ์ง๋ง ์ฌ์ดํธ๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํ ๋๋ง๋ค ํ๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ง๋ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ณด๋ค ๋์ ์ธ ๊ฒฝ๋ก๋ฅผ ์ ํํ๊ณ ๋ง์คํฐ ๋ธ๋์น์ ๋ค์ด์ ์คํธ ๋ฐฐํฌ๋ฅผ ์ค์ ํ๊ฒ ์ต๋๋ค.
์์ด๋์ด๋ ๊ฐ๋จํฉ๋๋ค. ์ด์ ์ฐ๋ฆฌ์ ์ด๋ฏธ์ง๋ ์น ์ฌ์ดํธ ๋ฐ์ด๋ฃ์ ๋๋ง๋ค ๋ค์ ์์ฑ๋ฉ๋๋ค. ์์ฌ, Kubernetes์ ์๋์ผ๋ก ๋ฐฐํฌ๋ฉ๋๋ค.
์ด ๋ ๊ฐ์ง ์์ ์ ์ ๋ฐ์ดํธํด ๋ณด๊ฒ ์ต๋๋ค. .gitlab-ci.yml:
build_website:
extends: .build_docker_image
variables:
GIT_SUBMODULE_STRATEGY: normal
script:
- mkdir -p $CI_PROJECT_DIR/artifacts
- /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_REF_NAME --digest-file $CI_PROJECT_DIR/artifacts/website.digest
artifacts:
paths:
- artifacts/
only:
refs:
- master
- tags
deploy_website:
extends: .deploy_qbec_app
script:
- DIGEST="$(cat artifacts/website.digest)"
- qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"
์ค๋ ๋๋ฅผ ์ถ๊ฐํ์ต๋๋ค. ์์ฌ ะบ ์ฌํ ์ผ์๋ฆฌ๋ฅผ ์ํด build_website ์ด์ ์ฐ๋ฆฌ๋ $CI_COMMIT_REF_NAME ๋์ $CI_COMMIT_TAG์ฆ, Git์ ํ๊ทธ์์ ์ฐ๊ฒฐ์ด ํด์ ๋์์ผ๋ฉฐ ์ด์ ํ์ดํ๋ผ์ธ์ ์ด๊ธฐํํ ์ปค๋ฐ ๋ธ๋์น์ ์ด๋ฆ์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ํธ์ํฉ๋๋ค. ์ด๋ ํ๊ทธ์ ํจ๊ป ์๋ํ๋ฏ๋ก docker-registry์ ํน์ ๋ฒ์ ์ผ๋ก ์ฌ์ดํธ์ ์ค๋ ์ท์ ์ ์ฅํ ์ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
์ฌ์ดํธ์ ์ ๋ฒ์ ์ ๋ํ Docker ํ๊ทธ ์ด๋ฆ์ ๋ณ๊ฒฝํ ์ ์๋ ๊ฒฝ์ฐ์๋ Kubernetes์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ ์ค๋ช ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ ์ด๋ฏธ์ง์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฐฐํฌํ์ง ์์ต๋๋ค. ๋ฐฐํฌ ๋งค๋ํ์คํธ.
์ต์ โvm:ext-str ๋ค์ด์ ์คํธ=โ$DIGESTโ qbec์ ๊ฒฝ์ฐ - ์ธ๋ถ ๋ณ์๋ฅผ jsonnet์ ์ ๋ฌํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฆด๋ฆฌ์ค๋ ๋๋ง๋ค ํด๋ฌ์คํฐ์ ์ด๋ฅผ ์ฌ๋ฐฐํฌํ๊ธฐ๋ฅผ ์ํฉ๋๋ค. ์ด๋ฏธ์ง์ ํน์ ๋ฒ์ ์ ์ฐ๊ฒฐํ๊ณ ๋ณ๊ฒฝ ์ ๋ฐฐํฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํด์ผ ํ๋ฏ๋ก ์ด์ ๋ณ๊ฒฝํ ์ ์๋ ํ๊ทธ ์ด๋ฆ์ ๋ ์ด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์์๋ ๋ค์ด์ ์คํธ ์ด๋ฏธ์ง๋ฅผ ํ์ผ์ ์ ์ฅํ๋ Kaniko์ ๊ธฐ๋ฅ์ ํตํด ๋์์ ๋ฐ์ ์ ์์ต๋๋ค(์ต์
--๋ค์ด์ ์คํธ ํ์ผ)
๊ทธ๋ฐ ๋ค์ ์ด ํ์ผ์ ์ ์กํ๊ณ ๋ฐฐํฌ ์ ์ฝ์ด๋ณด๊ฒ ์ต๋๋ค.
๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฐ์ดํธํด ๋ณด๊ฒ ์ต๋๋ค. ๋ฐฐํฌ/์น์ฌ์ดํธ/ํ๊ฒฝ/base.libsonnet ์ด์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ๊ฒ์ ๋๋ค:
{
components: {
website: {
name: 'example-docs',
image: 'registry.gitlab.com/kvaps/docs.example.org/website@' + std.extVar('digest'),
replicas: 1,
containerPort: 80,
servicePort: 80,
nodeSelector: {},
tolerations: [],
ingressClass: 'nginx',
domain: 'docs.example.org',
},
},
}
์๋ฃ๋์์ต๋๋ค. ์ด์ ๋ชจ๋ ์ปค๋ฐ์ด ์๋ฃ๋์์ต๋๋ค. ์์ฌ ๋์ปค ์ด๋ฏธ์ง ๋น๋๋ฅผ ์ด๊ธฐํํฉ๋๋ค. ์น ์ฌ์ดํธ, Kubernetes์ ๋ฐฐํฌํฉ๋๋ค.
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .
git commit -m "Configure dynamic build"
๋์ค์ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค git push ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ๋ณด๊ฒ ๋ ๊ฒ์ ๋๋ค:
๋ง์คํฐ์ฉ ํ์ดํ๋ผ์ธ ์คํฌ๋ฆฐ์ท
์์น์ ์ผ๋ก ํธ์ํ ๋๋ง๋ค gitlab-runner๋ฅผ ๋ค์ ๋ฐฐํฌํ ํ์๋ ์์ต๋๋ค. ๋ฌผ๋ก ๊ตฌ์ฑ์ด ๋ณ๊ฒฝ๋์ง ์์ ํ ์์ ํด ๋ณด๊ฒ ์ต๋๋ค. .gitlab-ci.yml:
deploy_gitlab_runner:
extends: .deploy_qbec_app
variables:
GIT_SUBMODULE_STRATEGY: normal
before_script:
- base64 -d "$GITCRYPT_KEY" | git-crypt unlock -
script:
- qbec apply default --root deploy/gitlab-runner --force:k8s-context __incluster__ --wait --yes
only:
changes:
- deploy/gitlab-runner/**/*
๋ณ๊ฒฝ ๋ณ๊ฒฝ์ฌํญ์ ๋ชจ๋ํฐ๋งํ ์ ์์ต๋๋ค. ๋ฐฐํฌ/gitlab-runner/ ์๋ ๊ฒฝ์ฐ์๋ง ์์ ์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .gitlab-ci.yml
git commit -m "Reduce gitlab-runner deploy"
git push, ๊ทธ๊ฒ ๋ซ๋ค:
์ ๋ฐ์ดํธ๋ ํ์ดํ๋ผ์ธ์ ์คํฌ๋ฆฐ์ท
12. ๋์ ํ๊ฒฝ
์ด์ ์ญ๋์ ์ธ ํ๊ฒฝ์ผ๋ก ํ์ดํ๋ผ์ธ์ ๋ค์ํํ ๋์ ๋๋ค.
๋จผ์ ์์ ์ ์ ๋ฐ์ดํธํ๊ฒ ์ต๋๋ค. build_website ์ฐ๋ฆฌ์ .gitlab-ci.yml, ๋ธ๋ก์ ์ ๊ฑฐํฉ๋๋ค. ๋ง, ์ด๋ Gitlab์ด ๋ชจ๋ ๋ธ๋์น์ ๋ํ ์ปค๋ฐ์์ ์ด๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋๋ก ๊ฐ์ ํฉ๋๋ค.
build_website:
extends: .build_docker_image
variables:
GIT_SUBMODULE_STRATEGY: normal
script:
- mkdir -p $CI_PROJECT_DIR/artifacts
- /kaniko/executor --cache --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/website/Dockerfile --destination $CI_REGISTRY_IMAGE/website:$CI_COMMIT_REF_NAME --digest-file $CI_PROJECT_DIR/artifacts/website.digest
artifacts:
paths:
- artifacts/
๊ทธ๋ฐ ๋ค์ ์์ ์ ์ ๋ฐ์ดํธํ์ธ์. ๋ฐฐํฌ_์น์ฌ์ดํธ, ๊ฑฐ๊ธฐ์ ๋ธ๋ก์ ์ถ๊ฐํ์ธ์ ํ๊ฒฝ:
deploy_website:
extends: .deploy_qbec_app
environment:
name: prod
url: https://docs.example.org
script:
- DIGEST="$(cat artifacts/website.digest)"
- qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"
์ด๋ฅผ ํตํด Gitlab์ ์์ ์ ๋ค์๊ณผ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ์ฐ๋ฅด๋ค ํ๊ฒฝ์ ๋ํ ์ฌ๋ฐ๋ฅธ ๋งํฌ๋ฅผ ํ์ํฉ๋๋ค.
์ด์ ๋ ๊ฐ์ง ์์ ์ ๋ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
deploy_website:
extends: .deploy_qbec_app
environment:
name: prod
url: https://docs.example.org
script:
- DIGEST="$(cat artifacts/website.digest)"
- qbec apply default --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST"
deploy_review:
extends: .deploy_qbec_app
environment:
name: review/$CI_COMMIT_REF_NAME
url: http://$CI_ENVIRONMENT_SLUG.docs.example.org
on_stop: stop_review
script:
- DIGEST="$(cat artifacts/website.digest)"
- qbec apply review --root deploy/website --force:k8s-context __incluster__ --wait --yes --vm:ext-str digest="$DIGEST" --vm:ext-str subdomain="$CI_ENVIRONMENT_SLUG" --app-tag "$CI_ENVIRONMENT_SLUG"
only:
refs:
- branches
except:
refs:
- master
stop_review:
extends: .deploy_qbec_app
environment:
name: review/$CI_COMMIT_REF_NAME
action: stop
stage: deploy
before_script:
- git clone "$CI_REPOSITORY_URL" master
- cd master
script:
- qbec delete review --root deploy/website --force:k8s-context __incluster__ --yes --vm:ext-str digest="$DIGEST" --vm:ext-str subdomain="$CI_ENVIRONMENT_SLUG" --app-tag "$CI_ENVIRONMENT_SLUG"
variables:
GIT_STRATEGY: none
only:
refs:
- branches
except:
refs:
- master
when: manual
๋ง์คํฐ๋ฅผ ์ ์ธํ ๋ชจ๋ ๋ถ๊ธฐ์ ํธ์ํ๋ฉด ์์๋๋ฉฐ ์ฌ์ดํธ์ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ ๋ฒ์ ์ด ๋ฐฐํฌ๋ฉ๋๋ค.
qbec์ ๋ํ ์๋ก์ด ์ต์
์ด ํ์๋ฉ๋๋ค. --์ฑ ํ๊ทธ โ ๋ฐฐํฌ๋ ์ ํ๋ฆฌ์ผ์ด์
๋ฒ์ ์ ํ๊ทธ๋ฅผ ์ง์ ํ๊ณ ์ด ํ๊ทธ ๋ด์์๋ง ์์
ํ ์ ์์ต๋๋ค. Kubernetes์์ ๋ฆฌ์์ค๋ฅผ ์์ฑํ๊ณ ์ญ์ ํ ๋ qbec์ ํด๋น ๋ฆฌ์์ค๋ก๋ง ์๋ํฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ๋ฆฌ๋ทฐ๋ง๋ค ๋ณ๋์ ํ๊ฒฝ์ ๋ง๋ค ์ ์๊ณ ๋จ์ํ ๋์ผํ ํ๊ฒฝ์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ์ฌ์ฉํฉ๋๋ค qbec ์ ์ฉ ๊ฒํ ๋์ ์ qbec ๊ธฐ๋ณธ๊ฐ ์ ์ฉ - ์ด๊ฒ์ด ๋ฐ๋ก ํ๊ฒฝ(๊ฒํ ๋ฐ ๊ธฐ๋ณธ๊ฐ)์ ์ฐจ์ด์ ์ ์ค๋ช ํ๋ ค๊ณ ์๋ํ๋ ์๊ฐ์ ๋๋ค.
์ถ๊ฐ ๋ฆฌ๋ทฐ ํ๊ฒฝ ๋ฐฐํฌ/์น์ฌ์ดํธ/qbec.yaml
spec:
environments:
review:
defaultNamespace: docs
server: https://kubernetes.example.org:8443
๊ทธ๋ฌ๋ฉด ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์ ์ธํ ๊ฒ์ด๋ค. ๋ฐฐํฌ/์น์ฌ์ดํธ/params.libsonnet:
local env = std.extVar('qbec.io/env');
local paramsMap = {
_: import './environments/base.libsonnet',
default: import './environments/default.libsonnet',
review: import './environments/review.libsonnet',
};
if std.objectHas(paramsMap, env) then paramsMap[env] else error 'environment ' + env + ' not defined in ' + std.thisFile
๊ทธ๋ฆฌ๊ณ ์ด์ ๋ํ ๋ง์ถค ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ด๋์ธ์. ๋ฐฐํฌ/์น์ฌ์ดํธ/ํ๊ฒฝ/review.libsonnet:
// this file has the param overrides for the default environment
local base = import './base.libsonnet';
local slug = std.extVar('qbec.io/tag');
local subdomain = std.extVar('subdomain');
base {
components+: {
website+: {
name: 'example-docs-' + slug,
domain: subdomain + '.docs.example.org',
},
},
}
์กฐ๋ถ๋ ์ข ๋ ์์ธํ ์ดํด๋ณด์ stop_review, ๋ธ๋์น๊ฐ ์ญ์ ๋๋ฉด ํธ๋ฆฌ๊ฑฐ๋๋ฉฐ gitlab์ด ์ฒดํฌ์์์ ์๋ํ์ง ์๋๋ก ์ฌ์ฉ๋ฉ๋๋ค. GIT_STRATEGY: ์์, ๋์ค์ ๋ณต์ ํฉ๋๋ค ์์ฌ-๋ธ๋์น๋ฅผ ํตํด ๋ฆฌ๋ทฐ๋ฅผ ์ญ์ ํฉ๋๋ค.
์กฐ๊ธ ํท๊ฐ๋ฆฌ๊ธด ํ์ง๋ง ์์ง์ ์ด๋ณด๋ค ๋ ์๋ฆ๋ค์ด ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
๋ ๋ค๋ฅธ ์ต์
์ ๊ฐ ๋ฆฌ๋ทฐ๋ฅผ ํธํ
๋ค์์คํ์ด์ค์ ๋ฐฐํฌํ๋ ๊ฒ์
๋๋ค. ์ด ๋ค์์คํ์ด์ค๋ ํญ์ ์์ ํ ์ฒ ๊ฑฐ๋ ์ ์์ต๋๋ค.
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .
git commit -m "Enable automatic review"
git push, ์์ ์ฒดํฌ ์์ -b ํ ์คํธ, git ํธ์ ์ค๋ฆฌ์ง ํ ์คํธ, ํ์ธํ๋ค:
Gitlab์์ ์์ฑ๋ ํ๊ฒฝ์ ์คํฌ๋ฆฐ์ท
๋ชจ๋ ๊ฒ์ด ์๋ํ๊ณ ์๋์? - ์ข์ต๋๋ค. ํ ์คํธ ๋ธ๋์น๋ฅผ ์ญ์ ํ์ธ์. ์์ ์ฒดํฌ ์์ ๋ง์คํฐ, git push ์์ : ํ ์คํธ, ํ๊ฒฝ ์ญ์ ์์ ์ด ์ค๋ฅ ์์ด ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
์ฌ๊ธฐ์๋ ํ๋ก์ ํธ์ ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ๋ธ๋์น๋ฅผ ์์ฑํ ์ ์๊ณ ๋ณ๊ฒฝํ ์๋ ์๋ค๋ ์ ์ ์ฆ์ ๋ช ํํ ํ๊ณ ์ถ์ต๋๋ค. .gitlab-ci.yml ํ์ผ์ ์ ์ฅํ๊ณ ๋น๋ฐ ๋ณ์์ ์ก์ธ์คํฉ๋๋ค.
๋ฐ๋ผ์ ๋ณดํธ๋ ๋ถ๊ธฐ์๋ง ์ฌ์ฉ์ ํ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์์ฌ, ๋๋ ๊ฐ ํ๊ฒฝ์ ๋ํด ๋ณ๋์ ๋ณ์ ์ธํธ๋ฅผ ์์ฑํฉ๋๋ค.
13. ์ฑ ๊ฒํ
์ด ๋ฒํผ์ ํ์ํ๋ ค๋ฉด ํ์ผ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. .gitlab/route-map.yml ๊ทธ๋ฆฌ๊ณ ๊ทธ ์์ ๋ชจ๋ ๊ฒฝ๋ก ๋ณํ์ ์ค๋ช ํฉ๋๋ค. ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ์๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
# Indices
- source: /content/(.+?)_index.(md|html)/
public: '1'
# Pages
- source: /content/(.+?).(md|html)/
public: '1/'
๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
git add .gitlab/
git commit -m "Enable review apps"
git push, ํ์ธ:
์ฑ ๊ฒํ ๋ฒํผ ์คํฌ๋ฆฐ์ท
์์ ์ด ์๋ฃ๋์์ต๋๋ค!
ํ๋ก์ ํธ ์์ค:
- Gitlab์์:
https://gitlab.com/kvaps/docs.example.org - GitHub์์:
https://github.com/kvaps/docs.example.org
๊ด์ฌ์ ๊ฐ์ ธ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋ง์์ ๋์ จ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
์ถ์ฒ : habr.com