ํ๋ก์ ํธ ์ต์์์ .gitlab-ci.yaml ํ์ผ์ ์์ฑํ๊ณ , ์๋์ ๊ฐ์ด ์ค์ ํ๋ค.
stages ์์ฑ
์ฌ์ฉํ ์คํ
์ด์ง๋ฅผ ์ ๋ถ ๋ง๋ค์ด์ค๋ค.
stages:
- build
- testing
- dev
- release
- qa
- prod
ํ์ดํ๋ผ์ธ์์ ์ฌ์ฉํ ๋ณ์ ์ ์ธ
variables:
IMAGE_NAME: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}
LATEST_IMAGE_NAME: ${CI_REGISTRY_IMAGE}:latest
job ์์ฑ
run_job:
stage: dev
image: alpine:3.8
before_script:
- echo pre
script:
- echo hello world
after_script:
- echo post
unit_test_job:
stage: dev
image: alpine:3.8
script:
- echo unit test
run_job์ ํ
์คํธ๋ก ์์ฑํ๊ณ unit_test_job๋ ์์ฑํด๋ณด์๋ค.
๋๋ค stage๊ฐ dev์ธ๊ฒ์ ํ์ธํ ์ ์๋ค.
run_e2e_tests:
stage: testing
image: alpine:3.8
before_script:
- echo pre
script:
- echo hello world
after_script:
- echo post
testing stage ์ job์ ํ๋ ์ถ๊ฐํ๋ค.
docker build
echo "hello world" > index.html
vi Dockerfile
FROM nginx:1.20-alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
CMD ["/bin/sh", "-c", "exec nginx -g 'daemon off;';"]
WORKDIR /usr/share/nginx/html
.gitlab-ci.yaml ์ ์ถ๊ฐํ์.
build stage ์ job์ ํ๋ ์ถ๊ฐํ๋ค.
build:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
before_script:
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
script:
- docker build -f Dockerfile -t ${IMAGE_NAME} -t ${LATEST_IMAGE_NAME} .
- docker push ${IMAGE_NAME}
- docker push ${LATEST_IMAGE_NAME}
after_script:
- docker logout
${xxx}
๋ variable์ ์๋ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค.
CI_REGISTRY_USER, CI_REGISTRY_PASSWORD, CI_REGISTRY ๋ฅผ ์ฌ์ฉํ๋ค.
๊ทธ๋ฆผ์ฒ๋ผ ์์ฑํด์ ๋ฃ์ด์ค์ผํ๋ค.
ํน์ ์ฌ๋ฌ์ฌ๋์ด ๊ณต์ ํ๋ฉด ๊ทธ๋ฃน ๋จ์๋ก ์ ์ฉํ๋๊ฒ ํค๋ฅผ ๋ณดํธํ๋๋ฐ ๋์์ด ๋ ๋ฏ ์ถ๋ค.
change log
$CI_COMMIT_TAG => ํ๊ทธ๋ฅผ ๋ถ์ด๋ ์๊ฐ๋ง ๋์์ ํ๋ค.
changelog:
stage: release
image: docker:git
rules:
- if: $CI_COMMIT_TAG
script:
- git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:'At %ci, %cN committed %h - %s' --decorate --graph >release.md
artifacts:
paths: [release.md]
git log๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ๋ก ์ง์ ํ๊ทธ ์ดํ๋ก๋ถํฐ ์ง๊ธ๊น์ง git log๋ฅผ ๊ฐ์ ธ์ค๊ณ , release.md๋ก ์ ์ฅํ๋ค.
release.md๊ฐ artifactory๋ก ์์ฑ์ด ๋์ ui์์ ๋ค์ด๋ฐ์์ ์๋ค.
release
$CI_COMMIT_TAG => ํ๊ทธ๋ฅผ ๋ถ์ด๋ ์๊ฐ๋ง ๋์์ ํ๋ค.
๋ฐ๋ก ์ง์ ์ ์๊ธด artifact๊ฐ ์๋์ผ๋ก ๋ค์ด์ด ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก cat
ํด์ ๋ฆด๋ฆฌ์ฆ์ ๋ฃ์ผ๋ฉด ๋๋ค.
needs๋ฅผ ์ด์ฉํ๋ฉด ๋ํ๋์๊ฐ ๊ฑธ๋ฆฐ ์์
์ด ๋จผ์ ๋๋ํ ์ด ์ก์ ์คํํ๋ค. changelog๊ฐ ๋๋๋ฉด release๊ฐ ๋๋ค.
release:
stage: release
needs: ['changelog']
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG
script:
- echo "running release_job for $TAG"
release:
tag_name: '$CI_COMMIT_TAG'
name: 'Release $CI_COMMIT_TAG'
description: '$(cat release.md)'
์ด์ ํ๊ทธ๋ฅผ ๋ถ์ด๊ณ push๋ฅผ ํ๋ฉด ๋ฆด๋ฆฌ์ฆ ํ์ด์ง๊ฐ ๋๋ค.
staging ๋ฐฐํฌ
stage๋ฅผ staging์ผ๋ก ๊ตฌ์ฑํ์.
argocd repo๋ฅผ ์
๋ฐ์ดํธ ํ๋๊ฒ์ผ๋ก ๋ฐฐํฌ๊ฐ ๋ง๋ฌด๋ฆฌ ๋๋ค. ๊น์ ํด๋ก ํด์ ๋ค์ด๋ก๋ํํ docker image tag๋ง ๋ฐ๊ฟ์ฃผ๊ณ ๋ค์ ์ปค๋ฐํ๋ฉด๋๋ค.
staging-deploy:
stage: staging
image: alpine:3.8
rules:
- if: $CI_COMMIT_TAG
before_script:
- apk add --no-cache git curl bash
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git clone https://${CI_USER}:${CI_PUSH_TOKEN}@gitlab.com/teamsmiley/staging.git
- cd k8s-c1/apps/default/sample-www-internal
- sed "s/:latest/:${CI_COMMIT_SHORT_SHA}/g" deploy.origin > deploy.yaml
- git commit -am "change docker tag"
- git push
deploy.origin ํ์ผ
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: www
labels:
app: www
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: www
template:
metadata:
labels:
app: www
spec:
containers:
- name: www
image: registry.gitlab.com/teamsmiley/sample:latest
ports:
- containerPort: 80
name: http
imagePullSecrets:
- name: gitlab-regcred
production ๋ฐฐํฌ(job template)
์คํ
์ด์ง ์ฝ๋๋ฅผ ๋ณต์ฌํด์ ๋ง๋ค๋ฉด ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ฝ๋์ ์ค๋ณต์ด ์๊ธด๋ค.
์ฌ๊ธฐ์ job template๋ผ๋ ๊ฐ๋
์ด ์๊ธด๋ค.
job template๋ ์ฌ์ฉํ๊ณณ๋ณด๋ค๋ yamlํ์ผ์ ์๋จ์ ์์นํด์ผํ๋ค. yaml์ ์ถ๊ฐํ์.
jobname์ด .์ผ๋ก ์์ํ๋ค. ์ด๊ฑด ์ค์ ๋ก ๋์ํ์ง๋ ์๋ ์์
์ด๋ค.
.deploy-template: &template
rules:
- if: $CI_COMMIT_TAG
before_script:
- apk add --no-cache git curl bash
- echo ${CI_COMMIT_SHORT_SHA}
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git clone https://${CI_USER}:${CI_PUSH_TOKEN}@gitlab.com/teamsmiley/staging.git
- cd staging/apps/default/sample-www-internal
- sed "s/:latest/:${CI_COMMIT_SHORT_SHA}/g" deploy.origin > deploy.yaml
- git commit -am "change docker tag"
- git push
yaml์ anchor๊ธฐ๋ฅ์ ์ด์ฉํ๋ค.
&template
์ฒ๋ผ &
ํ๊ณ ์ด๋ฆ์ ์ ๋๋ค.
์ด์ ์ฌ์ฉํ ๊ณณ์์ ์ด๋ฆ์ ์ ์ด์ ์ฌ์ฉํ๋ค. <<: *
๋ค์์ ์ด๋ฆ์ ์จ์ ์ฌ์ฉํ๋ค.
staging-deploy:
stage: staging
image: alpine:3.8
rules:
- if: $CI_COMMIT_TAG
<<: *template
์ด๋ ๊ฒ ํ๋ฉด ์ ๋ด์ฉ์ ๊ฐ์ ธ๋ค๊ฐ ๋ถ์ฌ์ค๋ค. ์ฝ๋ ์ค๋ณต์ ์ค์ผ์ ์๋ค.
production๊ณผ staging์ ํ๋ค๋ณด๋ git repo์ ๊ฒฝ๋ก๊ฐ ๋ค๋ฅด๋ค.
staging.git / production.git ์ด๋ค. ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผํ ๊น?
- git clone https://${CI_USER}:${CI_PUSH_TOKEN}@gitlab.com/teamsmiley/staging.git
- cd staging/apps/default/sample-www-internal
์ด๋ถ๋ถ์ด ๋ฌธ์ ์ธ๋ฐ ์ด๊ฑด ๊ฐ๋จํ๊ฒ variable์ ์ฌ์ฉํ๋ฉด๋๋ค.
.deploy-template: &template
rules:
- if: $CI_COMMIT_TAG
before_script:
- apk add --no-cache git curl bash
- echo ${CI_COMMIT_SHORT_SHA}
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git clone https://${CI_USER}:${CI_PUSH_TOKEN}@gitlab.com/teamsmiley/$gitrepo_name.git # $gitrepo_name์ variable์ ์ฌ์ฉํ์ฌ ์ ํด์ค๋ค.
- cd $gitrepo_name/apps/default/sample-www-internal # $gitrepo_name์ variable์ ์ฌ์ฉํ์ฌ ์ ํด์ค๋ค.
- sed "s/:latest/:${CI_COMMIT_SHORT_SHA}/g" deploy.origin > deploy.yaml
- git commit -am "change docker tag"
- git push
staging-deploy:
stage: staging
image: alpine:3.8
rules:
- if: $CI_COMMIT_TAG
# ์ด๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
variables:
gitrepo_name: staging
<<: *template
production-deploy:
stage: production
image: alpine:3.8
rules:
- if: $CI_COMMIT_TAG
# ์ด๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
variables:
gitrepo_name: production
<<: *template
์ด๋ ๊ฒ ํ๋ฉด variable์ ์ฌ์ฉํ์ฌ staging์ staging.git / production์ production.git ์ด๋ ๊ฒ ์ ํด์ค๋ค.
์ฝ๋์ ์ค๋ณต์ ์ ๋ถ job template๋ฅผ ์ด์ฉํ์ฌ ์ฒ๋ฆฌํ ์ ์๋ค.
Approval
environment์์ approval์ ์ฌ์ฉํ๋ฉด ๋๋ค.
production-deploy:
stage: production
image: alpine:3.8
# ์ด๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
environment:
name: prod
url: https://www.aaa.com
rules:
- if: $CI_COMMIT_TAG
variables:
gitrepo_name: production
<<: *template
ci/cd๋ฅผ ์คํํ๋ฉด environment๊ฐ ์์ฑ๋๋ค.
setting >> ci/cd >> protect an environment
์ด์ cicd๋ฅผ ์คํํด๋ณด๋ฉด ํ๋ก๋์
์์ ๋ฉ์ถฐ์๋๊ฒ์ ์์ ์๋ค.
environment ์ ๊ฐ์ productin์ ์ ํํ๊ณ ๋ค์ด๊ฐ๋ฉด ์ปจํ์ ํ ์๊ฐ ์๋ค.
approval์ ํ ์๊ฐ ์๋ค.
approval์ ํ๋ฉด ๋ค์ ํ๋ก์ธ์ค๊ฐ ์งํ๋๋๊ฒ์ ์์ ์๋ค.
์ ์ฒด ci/cd ํ๋ก์ธ์ค
stages:
- build
- testing
- dev
- release
- qa
- prod
variables:
IMAGE_NAME: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}
LATEST_IMAGE_NAME: ${CI_REGISTRY_IMAGE}:latest
run_job:
stage: dev
image: alpine:3.8
before_script:
- echo pre
script:
- echo hello world
after_script:
- echo post
unit_test_job:
stage: dev
image: alpine:3.8
script:
- echo unit test
run_e2e_tests:
stage: testing
image: alpine:3.8
before_script:
- echo pre
script:
- echo hello world
after_script:
- echo post
build:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
before_script:
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
script:
- docker build -f Dockerfile -t ${IMAGE_NAME} -t ${LATEST_IMAGE_NAME} .
- docker push ${IMAGE_NAME}
- docker push ${LATEST_IMAGE_NAME}
after_script:
- docker logout
changelog:
stage: release
image: docker:git
rules:
- if: $CI_COMMIT_TAG
script:
- git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:'At %ci, %cN committed %h - %s' --decorate --graph >release.md
artifacts:
paths: [release.md]
release:
stage: release
needs: ['changelog']
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG
script:
- echo "running release_job for $TAG"
release:
tag_name: '$CI_COMMIT_TAG'
name: 'Release $CI_COMMIT_TAG'
description: '$(cat release.md)'
.deploy-template: &template
image: alpine:3.8
rules:
- if: $CI_COMMIT_TAG
before_script:
- apk add --no-cache git curl bash
- echo ${CI_COMMIT_SHORT_SHA}
- git config --global user.email "gitlab@gitlab.com"
- git config --global user.name "GitLab CI/CD"
script:
- git clone https://${CI_USER}:${CI_PUSH_TOKEN}@gitlab.com/teamsmiley/staging.git
- cd staging/apps/default/sample-www-internal
- sed "s/:latest/:${CI_COMMIT_SHORT_SHA}/g" deploy.origin > deploy.yaml
- git commit -am "change docker tag"
- git push
staging-deploy:
stage: staging
# ์ด๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
variables:
gitrepo_name: staging
<<: *template
production-deploy:
stage: production
# ์ด๋ถ๋ถ์ ์ถ๊ฐํ๋ค.
variables:
gitrepo_name: production
<<: *template
jira ticket create for rtp with release.md
unit_test_job:
stage: qa
image: alpine:3.8
script:
- curl xxxxxxxxxx (jira api with api key)
this will create ma ticket
when we click argocd sync button
deploy
update jira ticket status to start
update jira ticket status to done
rollback
update jira ticket status to rollback-start
update jira ticket status to rollback-done
todo