ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ืฉืœื•ื! ืœืื—ืจื•ื ื” ืฉื•ื—ืจืจื• ื›ืœื™ ืื•ื˜ื•ืžืฆื™ื” ืžื’ื ื™ื‘ื™ื ืจื‘ื™ื ื”ืŸ ืœื‘ื ื™ื™ืช ืชืžื•ื ื•ืช Docker ื•ื”ืŸ ืœืคืจื™ืกื” ืœ-Kubernetes. ื‘ื”ืงืฉืจ ื”ื–ื”, ื”ื—ืœื˜ืชื™ ืœืฉื—ืง ืขื GitLab, ืœืœืžื•ื“ ื”ื™ื˜ื‘ ืืช ื”ื™ื›ื•ืœื•ืช ืฉืœื” ื•ื›ืžื•ื‘ืŸ ืœื”ืงื™ื ืืช ื”ืฆื™ื ื•ืจ.

ืขื‘ื•ื“ื” ื–ื• ื ื•ืฆืจื” ื‘ื”ืฉืจืืช ื”ืืชืจ kubernetes.io, ืืฉืจ ื ื•ืฆืจ ืž ืงื•ื“ื™ ืžืงื•ืจ ืื•ื˜ื•ืžื˜ื™ืช, ื•ืขื‘ื•ืจ ื›ืœ ื‘ืงืฉืช ืžืื’ืจ ืฉื ืฉืœื—ืช, ื”ืจื•ื‘ื•ื˜ ืžื™ื™ืฆืจ ืื•ื˜ื•ืžื˜ื™ืช ื’ืจืกืช ืชืฆื•ื’ื” ืžืงื“ื™ืžื” ืฉืœ ื”ืืชืจ ืขื ื”ืฉื™ื ื•ื™ื™ื ืฉืœืš ื•ืžืกืคืง ืงื™ืฉื•ืจ ืœืฆืคื™ื™ื”.

ื ื™ืกื™ืชื™ ืœื‘ื ื•ืช ืชื”ืœื™ืš ื“ื•ืžื” ืžืืคืก, ืื‘ืœ ื‘ื ื•ื™ ื›ื•ืœื• ืขืœ Gitlab CI ื•ื›ืœื™ื ื—ื™ื ืžื™ื™ื ืฉื‘ื”ื ืื ื™ ืจื’ื™ืœ ืœื”ืฉืชืžืฉ ื›ื“ื™ ืœืคืจื•ืก ื™ื™ืฉื•ืžื™ื ืœ-Kubernetes. ื”ื™ื•ื ืกื•ืฃ ืกื•ืฃ ืืกืคืจ ืœื›ื ื™ื•ืชืจ ืขืœื™ื”ื.

ื”ืžืืžืจ ื™ื“ื•ืŸ ื‘ื›ืœื™ื ื›ื’ื•ืŸ:
ื”ื•ื’ื•, qbec, ืงืื ื™ืงื•, git-crypt ะธ GitLab CI ืขื ื™ืฆื™ืจืช ืกื‘ื™ื‘ื•ืช ื“ื™ื ืžื™ื•ืช.

ืชื•ึนื›ึถืŸ

  1. ื”ื›ื™ืจื• ืืช ื”ื•ื’ื•
  2. ื”ื›ื ืช ื”-Dockerfile
  3. ื”ื™ื›ืจื•ืช ืขื ืงื ื™ืงื•
  4. ื”ื™ื›ืจื•ืช ืขื qbec
  5. ืžื ืกื” Gitlab-ranner ืขื Kubernetes-executor
  6. ืคืจื™ืกืช ืชืจืฉื™ืžื™ Helm ืขื qbec
  7. ื”ื™ื›ืจื•ืช ืขื git-crypt
  8. ื™ืฆื™ืจืช ืชืžื•ื ืช ืืจื’ื– ื›ืœื™ื
  9. ื”ืฆื™ื ื•ืจ ื”ืจืืฉื•ืŸ ืฉืœื ื• ื•ื”ืจื›ื‘ืช ืชืžื•ื ื•ืช ืœืคื™ ืชื’ื™ื
  10. ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื”
  11. ื—ืคืฆื™ื ื•ื”ืจื›ื‘ื” ื‘ืขืช ื“ื—ื™ืคื” ืœืžืืกื˜ืจ
  12. ืกื‘ื™ื‘ื•ืช ื“ื™ื ืžื™ื•ืช
  13. ืกืงื•ืจ ืืคืœื™ืงืฆื™ื•ืช

1. ื”ื™ื›ืจื•ืช ืขื ื”ื•ื’ื•

ื›ื“ื•ื’ืžื” ืœืคืจื•ื™ืงื˜ ืฉืœื ื•, ื ื ืกื” ืœื™ืฆื•ืจ ืืชืจ ืคืจืกื•ื ืชื™ืขื•ื“ ื‘ื ื•ื™ ืขืœ ื”ื•ื’ื•. ื”ื•ื’ื• ื”ื•ื ืžื—ื•ืœืœ ืชื•ื›ืŸ ืกื˜ื˜ื™.

ืœืžื™ ืฉืœื ืžื›ื™ืจ ื’ื ืจื˜ื•ืจื™ื ืกื˜ื˜ื™ื™ื, ืืกืคืจ ืขืœื™ื”ื ืงืฆืช ื™ื•ืชืจ. ื‘ื ื™ื’ื•ื“ ืœืžื ื•ืขื™ ืืชืจื™ื ืงื•ื ื‘ื ืฆื™ื•ื ืœื™ื™ื ืขื ืžืกื“ ื ืชื•ื ื™ื ื•ืงืฆืช PHP, ืฉืœืคื™ ื‘ืงืฉื” ืขืœ ื™ื“ื™ ืžืฉืชืžืฉ ื™ื•ืฆืจื™ื ื“ืคื™ื ืชื•ืš ื›ื“ื™ ืชื ื•ืขื”, ืžื—ื•ืœืœื™ื ืกื˜ื˜ื™ื™ื ืžืขื•ืฆื‘ื™ื ืงืฆืช ืื—ืจืช. ื”ื ืžืืคืฉืจื™ื ืœืš ืœืงื—ืช ืžืงื•ืจื•ืช, ื‘ื“ืจืš ื›ืœืœ ืงื‘ื•ืฆื” ืฉืœ ืงื‘ืฆื™ื ื‘ืชื‘ื ื™ื•ืช ืกื™ืžื•ืŸ Markdown ื•ืชื‘ื ื™ื•ืช ืขืจื›ืช ื ื•ืฉื, ื•ืื– ืœืงืžืคืœ ืื•ืชื ืœืืชืจ ืžื•ื’ืžืจ ืœื—ืœื•ื˜ื™ืŸ.

ื›ืœื•ืžืจ, ื›ืชื•ืฆืื” ืžื›ืš, ืชืงื‘ืœื• ืžื‘ื ื” ืกืคืจื™ื•ืช ื•ืžืขืจื›ืช ืฉืœ ืงื‘ืฆื™ HTML ืฉื ื•ืฆืจื•, ืื•ืชื ืชื•ื›ืœื• ืคืฉื•ื˜ ืœื”ืขืœื•ืช ืœื›ืœ ืื™ืจื•ื— ื–ื•ืœ ื•ืœืงื‘ืœ ืืชืจ ืชืงื™ืŸ.

ืืชื” ื™ื›ื•ืœ ืœื”ืชืงื™ืŸ ืืช ื”ื•ื’ื• ื‘ืื•ืคืŸ ืžืงื•ืžื™ ื•ืœื ืกื•ืช ืืช ื–ื”:

ืืชื—ื•ืœ ืืชืจ ื—ื“ืฉ:

hugo new site docs.example.org

ื•ื‘ืื•ืชื• ื”ื–ืžืŸ ืžืื’ืจ git:

cd docs.example.org
git init

ืขื“ ื›ื”, ื”ืืชืจ ืฉืœื ื• ื”ื•ื ื‘ืชื•ืœื™ ื•ื›ื“ื™ ืฉืžืฉื”ื• ื™ื•ืคื™ืข ื‘ื•, ืื ื—ื ื• ืฆืจื™ื›ื™ื ืงื•ื“ื ื›ืœ ืœื—ื‘ืจ ืขืจื›ืช ื ื•ืฉื; ืขืจื›ืช ื ื•ืฉื ื”ื™ื ืจืง ืงื‘ื•ืฆื” ืฉืœ ืชื‘ื ื™ื•ืช ื•ื›ืœืœื™ื ืžื•ื’ื“ืจื™ื ืฉืœืคื™ื”ื ื”ืืชืจ ืฉืœื ื• ื ื•ืฆืจ.

ืœื ื•ืฉื ื‘ื• ื ืฉืชืžืฉ ืœืœืžื•ื“, ืฉืœื“ืขืชื™ ืžืชืื™ื ื‘ืื•ืคืŸ ืžื•ืฉืœื ืœืืชืจ ืชื™ืขื•ื“.

ื‘ืจืฆื•ื ื™ ืœื”ืงื“ื™ืฉ ืชืฉื•ืžืช ืœื‘ ืžื™ื•ื—ื“ืช ืœืขื•ื‘ื“ื” ืฉืื™ื ื ื• ืฆืจื™ื›ื™ื ืœืฉืžื•ืจ ืืช ืงื‘ืฆื™ ืขืจื›ืช ื”ื ื•ืฉื ื‘ืžืื’ืจ ืฉืœ ื”ืคืจื•ื™ืงื˜ ืฉืœื ื•; ื‘ืžืงื•ื ื–ืืช, ืื ื• ื™ื›ื•ืœื™ื ืคืฉื•ื˜ ืœื—ื‘ืจ ืื•ืชื• ื‘ืืžืฆืขื•ืช ืชืช ืžื•ื“ื•ืœ git:

git submodule add https://github.com/matcornic/hugo-theme-learn themes/learn

ืœืคื™ื›ืš, ื”ืžืื’ืจ ืฉืœื ื• ื™ื›ื™ืœ ืจืง ืงื‘ืฆื™ื ื”ืงืฉื•ืจื™ื ื™ืฉื™ืจื•ืช ืœืคืจื•ื™ืงื˜ ืฉืœื ื•, ื•ื”ื ื•ืฉื ื”ืžื—ื•ื‘ืจ ื™ื™ืฉืืจ ื›ืงื™ืฉื•ืจ ืœืžืื’ืจ ืกืคืฆื™ืคื™ ื•-commit ื‘ื•, ื›ืœื•ืžืจ ืชืžื™ื“ ื ื™ืชืŸ ืœืฉืœื•ืฃ ืื•ืชื• ืžื”ืžืงื•ืจ ื”ืžืงื•ืจื™ ื•ืœื ืœืคื—ื“ ืžืžื ื• ืฉื™ื ื•ื™ื™ื ืฉืื™ื ื ืชื•ืืžื™ื.

ื‘ื•ื ื ืชืงืŸ ืืช ื”ืชืฆื•ืจื” config.toml:

baseURL = "http://docs.example.org/"
languageCode = "en-us"
title = "My Docs Site"
theme = "learn"

ื›ื‘ืจ ื‘ืฉืœื‘ ื–ื” ื ื™ืชืŸ ืœื”ืจื™ืฅ:

hugo server

ื•ื‘ื›ืชื•ื‘ืช http://localhost:1313/ ื‘ื“ื•ืง ืืช ื”ืืชืจ ื”ื—ื“ืฉ ืฉืœื ื• ืฉื ื•ืฆืจ, ื›ืœ ื”ืฉื™ื ื•ื™ื™ื ืฉื ืขืฉื• ื‘ืกืคืจื™ื™ื” ืžืขื“ื›ื ื™ื ืื•ื˜ื•ืžื˜ื™ืช ืืช ื”ื“ืฃ ื”ืคืชื•ื— ื‘ื“ืคื“ืคืŸ, ืžืื•ื“ ื ื•ื—!

ื‘ื•ืื• ื ื ืกื” ืœื™ืฆื•ืจ ื“ืฃ ืฉืขืจ ื‘ content/_index.md:

# My docs site

## Welcome to the docs!

You will be very smart :-)

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ื“ืฃ ื”ื—ื“ืฉ ืฉื ื•ืฆืจ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื›ื“ื™ ืœื™ืฆื•ืจ ืืชืจ, ืคืฉื•ื˜ ื”ืคืขืœ:

hugo

ืชื•ื›ืŸ ื”ืžื“ืจื™ืš ืฆื™ื‘ื•ืจื™ / ื•ื™ื”ื™ื” ืืชืจ ื”ืื™ื ื˜ืจื ื˜ ืฉืœืš.
ื›ืŸ, ืื’ื‘, ืžื™ื“ ื ื•ืกื™ืฃ ืืช ื–ื” .ื’ื ื™ื˜ื•ืจ:

echo /public > .gitignore

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add .
git commit -m "New site created"

2. ื”ื›ื ืช ื”-Dockerfile

ื”ื’ื™ืข ื”ื–ืžืŸ ืœื”ื’ื“ื™ืจ ืืช ืžื‘ื ื” ื”ืžืื’ืจ ืฉืœื ื•. ืื ื™ ื‘ื“ืจืš ื›ืœืœ ืžืฉืชืžืฉ ื‘ืžืฉื”ื• ื›ืžื•:

.
โ”œโ”€โ”€ deploy
โ”‚   โ”œโ”€โ”€ app1
โ”‚   โ””โ”€โ”€ app2
โ””โ”€โ”€ dockerfiles
    โ”œโ”€โ”€ image1
    โ””โ”€โ”€ image2

  • dockerfiles/ - ืžื›ื™ืœ ืกืคืจื™ื•ืช ืขื Dockerfiles ื•ื›ืœ ื”ื“ืจื•ืฉ ืœื‘ื ื™ื™ืช ืชืžื•ื ื•ืช Docker ืฉืœื ื•.
  • ืœืคืจื•ืก/ - ืžื›ื™ืœ ืกืคืจื™ื•ืช ืœืคืจื™ืกืช ื”ื™ื™ืฉื•ืžื™ื ืฉืœื ื• ืœ-Kubernetes

ืœืคื™ื›ืš, ื ื™ืฆื•ืจ ืืช ื”-Dockerfile ื”ืจืืฉื•ืŸ ืฉืœื ื• ืœืื•ืจืš ื”ื ืชื™ื‘ dockerfiles/website/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 ืžื›ื™ืœ ืฉื ื™ื™ื ืžืŸ, ืชื›ื•ื ื” ื–ื• ื ืงืจืืช ื‘ื ื™ื™ื” ืจื‘ ืฉืœื‘ื™ืช ื•ืžืืคืฉืจ ืœืš ืœื ืœื›ืœื•ืœ ื›ืœ ืžื™ื•ืชืจ ืžืชืžื•ื ืช ื”ื“ื•ืงืจ ื”ืกื•ืคื™ืช.
ืœืคื™ื›ืš, ื”ืชืžื•ื ื” ื”ืกื•ืคื™ืช ืชื›ื™ืœ ืจืง darkhttpd (ืฉืจืช HTTP ืงืœ ืžืฉืงืœ) ื• ืฆื™ื‘ื•ืจื™ / - ื”ืชื•ื›ืŸ ืฉืœ ืืชืจ ื”ืื™ื ื˜ืจื ื˜ ืฉืœื ื• ืฉื ื•ืฆืจ ื‘ืื•ืคืŸ ืกื˜ื˜ื™.

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add dockerfiles/website
git commit -m "Add Dockerfile for website"

3. ื”ื™ื›ืจื•ืช ืขื ืงื ื™ืงื•

ื‘ืชื•ืจ ื‘ื•ื ื” ืชืžื•ื ื•ืช docker, ื”ื—ืœื˜ืชื™ ืœื”ืฉืชืžืฉ ืงืื ื™ืงื•, ืžื›ื™ื•ื•ืŸ ืฉื”ืคืขื•ืœื” ืฉืœื• ืื™ื ื” ื“ื•ืจืฉืช ื“ืžื•ืŸ docker, ื•ื”ื‘ื ื™ื™ื” ืขืฆืžื” ื™ื›ื•ืœื” ืœื”ืชื‘ืฆืข ื‘ื›ืœ ืžื—ืฉื‘ ื•ื ื™ืชืŸ ืœืื—ืกืŸ ืืช ื”ืžื˜ืžื•ืŸ ื™ืฉื™ืจื•ืช ื‘ืจื™ืฉื•ื, ื•ื‘ื›ืš ืœื‘ื˜ืœ ืืช ื”ืฆื•ืจืš ื‘ืื—ืกื•ืŸ ืžืชืžืฉืš ืžืœื.

ื›ื“ื™ ืœื‘ื ื•ืช ืืช ื”ืชืžื•ื ื”, ืคืฉื•ื˜ ื”ืคืขืœ ืืช ื”ืžื™ื›ืœ ืขื ืžื•ืฆื™ื ืœืคื•ืขืœ ืฉืœ ืงื ื™ืงื• ื•ืœื”ืขื‘ื™ืจ ืœื• ืืช ื”ืงืฉืจ ื”ื‘ื ื™ื™ื” ื”ื ื•ื›ื—ื™; ื ื™ืชืŸ ืœืขืฉื•ืช ื–ืืช ื’ื ื‘ืื•ืคืŸ ืžืงื•ืžื™, ื‘ืืžืฆืขื•ืช 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 ืฉืœืš; ืœืื—ืจ ื”ื‘ื ื™ื™ื”, ื”ื™ื ืชื•ืฉืง ืื•ื˜ื•ืžื˜ื™ืช ืœ- Docker Registry.

ืคืจืžื˜ืจ --ืžื˜ืžื•ืŸ ืžืืคืฉืจ ืœืš ืœืฉืžื•ืจ ืฉื›ื‘ื•ืช ื‘ืžื˜ืžื•ืŸ ื‘ืจื™ืฉื•ื docker; ืขื‘ื•ืจ ื”ื“ื•ื’ืžื” ืฉื ื™ืชื ื”, ื”ืŸ ื™ื™ืฉืžืจื• ื‘ registry.gitlab.com/kvaps/docs.example.org/website/cache, ืื‘ืœ ืืชื” ื™ื›ื•ืœ ืœืฆื™ื™ืŸ ื ืชื™ื‘ ืื—ืจ ื‘ืืžืฆืขื•ืช ื”ืคืจืžื˜ืจ --cache-repo.

ืฆื™ืœื•ื ืžืกืš ืฉืœ docker-registry

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

4. ื”ื™ื›ืจื•ืช ืขื qbec

Qbec ื”ื•ื ื›ืœื™ ืคืจื™ืกื” ื”ืžืืคืฉืจ ืœืš ืœืชืืจ ื‘ืื•ืคืŸ ื”ืฆื”ืจืชื™ ืืช ืžื ื™ืคืกื˜ื™ ื”ื™ื™ืฉื•ื ืฉืœืš ื•ืœืคืจื•ืก ืื•ืชื ืœ-Kubernetes. ื”ืฉื™ืžื•ืฉ ื‘-Jsonnet ื›ืชื—ื‘ื™ืจ ื”ืจืืฉื™ ืžืืคืฉืจ ืœืš ืœืคืฉื˜ ืžืื•ื“ ืืช ืชื™ืื•ืจ ื”ื”ื‘ื“ืœื™ื ืขืœ ืคื ื™ ืžืกืคืจ ืกื‘ื™ื‘ื•ืช, ื•ื’ื ืžื‘ื˜ืœ ื›ืžืขื˜ ืœื—ืœื•ื˜ื™ืŸ ืืช ื—ื–ืจืช ื”ืงื•ื“.

ื–ื” ื™ื›ื•ืœ ืœื”ื™ื•ืช ื ื›ื•ืŸ ื‘ืžื™ื•ื—ื“ ื‘ืžืงืจื™ื ืฉื‘ื”ื ืืชื” ืฆืจื™ืš ืœืคืจื•ืก ืืคืœื™ืงืฆื™ื” ืœืžืกืคืจ ืืฉื›ื•ืœื•ืช ืขื ืคืจืžื˜ืจื™ื ืฉื•ื ื™ื ื•ืจื•ืฆื™ื ืœืชืืจ ืื•ืชื ื‘ืฆื•ืจื” ื”ืฆื”ืจืชื™ืช ื‘-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: {}

ื›ืืŸ ืื ื—ื ื• ืžืชืขื ื™ื™ื ื™ื ื‘ืขื™ืงืจ spec.environments, qbec ื›ื‘ืจ ื™ืฆืจื” ืขื‘ื•ืจื ื• ืกื‘ื™ื‘ืช ื‘ืจื™ืจืช ืžื—ื“ืœ ื•ืœืงื—ื” ืืช ื›ืชื•ื‘ืช ื”ืฉืจืช, ื›ืžื• ื’ื ืืช ืžืจื—ื‘ ื”ืฉืžื•ืช ืžื”-kubeconfig ื”ื ื•ื›ื—ื™ ืฉืœื ื•.
ื›ืขืช ื‘ืขืช ืคืจื™ืกื” ืœ ื‘ืจื™ืจืช ืžื—ื“ืœ ืกื‘ื™ื‘ืช, qbec ืชืžื™ื“ ื™ืคืจื•ืก ืจืง ืœืืฉื›ื•ืœ Kubernetes ืฉืฆื•ื™ืŸ ื•ืœืžืจื—ื‘ ื”ืฉืžื•ืช ืฉืฆื•ื™ืŸ, ื›ืœื•ืžืจ, ืื™ื ืš ืฆืจื™ืš ืขื•ื“ ืœืขื‘ื•ืจ ื‘ื™ืŸ ื”ืงืฉืจื™ื ื•ืžืจื—ื‘ื™ ืฉืžื•ืช ื›ื“ื™ ืœืคืจื•ืก.
ื‘ืžื™ื“ืช ื”ืฆื•ืจืš, ืชืžื™ื“ ืชื•ื›ืœ ืœืขื“ื›ืŸ ืืช ื”ื”ื’ื“ืจื•ืช ื‘ืงื•ื‘ืฅ ื–ื”.

ื›ืœ ื”ืกื‘ื™ื‘ื•ืช ืฉืœืš ืžืชื•ืืจื•ืช ื‘ qbec.yaml, ื•ื‘ืงื•ื‘ืฅ params.libsonnet, ืฉื ื›ืชื•ื‘ ื”ื™ื›ืŸ ื ื™ืชืŸ ืœื”ืฉื™ื’ ืืช ื”ืคืจืžื˜ืจื™ื ืขื‘ื•ืจื.

ืœืื—ืจ ืžื›ืŸ ืื ื• ืจื•ืื™ื ืฉืชื™ ืกืคืจื™ื•ืช:

  • ืจื›ื™ื‘ื™ื / - ื›ืœ ื”ืžื ื™ืคืกื˜ื™ื ืขื‘ื•ืจ ื”ืืคืœื™ืงืฆื™ื” ืฉืœื ื• ื™ืื•ื—ืกื ื• ื›ืืŸ; ื ื™ืชืŸ ืœืชืืจ ืื•ืชื ื”ืŸ ื‘ืงื‘ืฆื™ jsonnet ื•ื”ืŸ ื‘ืงื‘ืฆื™ yaml ืจื’ื™ืœื™ื
  • ืกื‘ื™ื‘ื•ืช/ - ื›ืืŸ ื ืชืืจ ืืช ื›ืœ ื”ืžืฉืชื ื™ื (ืคืจืžื˜ืจื™ื) ืขื‘ื•ืจ ื”ืกื‘ื™ื‘ื•ืช ืฉืœื ื•.

ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื™ืฉ ืœื ื• ืฉื ื™ ืงื‘ืฆื™ื:

  • environments/base.libsonnet - ื”ื•ื ื™ื›ื™ืœ ืคืจืžื˜ืจื™ื ืžืฉื•ืชืคื™ื ืœื›ืœ ื”ืกื‘ื™ื‘ื•ืช
  • environments/default.libsonnet - ืžื›ื™ืœ ืคืจืžื˜ืจื™ื ืฉื ื“ื—ืงื• ืขื‘ื•ืจ ื”ืกื‘ื™ื‘ื” ื‘ืจื™ืจืช ืžื—ื“ืœ

ื‘ื•ืื• ื ืคืชื— environments/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 ื‘ื‘ืช ืื—ืช, ืืœื” ื”ืŸ: ืคึผึฐืจึดื™ืกึธื”, ืฉืึตืจื•ึผืช ะธ Ingress. ืื ื”ื™ื™ื ื• ืจื•ืฆื™ื, ื™ื›ื•ืœื ื• ืœื”ื›ื ื™ืก ืื•ืชื ืœืžืจื›ื™ื‘ื™ื ืฉื•ื ื™ื, ืื‘ืœ ื‘ืฉืœื‘ ื–ื” ืื—ื“ ื™ืกืคื™ืง ืœื ื•.

ืชื—ื‘ื™ืจ 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. ืžื ืกื” ืืช Gitlab-ranner ืขื Kubernetes-executor

ืขื“ ืœืื—ืจื•ื ื” ื”ืฉืชืžืฉืชื™ ืจืง ื‘ืจื’ื™ืœ gitlab-ranner ืขืœ ืžื›ื•ื ื” ืžื•ื›ื ื” ืžืจืืฉ (ืžื™ื›ืœ LXC) ืขื ืžืขื˜ืคืช ืื• docker-executor. ื‘ืชื—ื™ืœื”, ื”ื™ื• ืœื ื• ื›ืžื” ืจืฆื™ื ื›ืืœื” ืฉื”ื•ื’ื“ืจื• ื‘ืจื—ื‘ื™ ื”ืขื•ืœื ื‘-gitlab ืฉืœื ื•. ื”ื ืืกืคื• ืชืžื•ื ื•ืช ื“ื•ืงืจ ืขื‘ื•ืจ ื›ืœ ื”ืคืจื•ื™ืงื˜ื™ื.

ืื‘ืœ ื›ืคื™ ืฉื”ืจืื” ื‘ืคื•ืขืœ, ืืคืฉืจื•ืช ื–ื• ืื™ื ื” ื”ืื™ื“ื™ืืœื™ืช ื‘ื™ื•ืชืจ, ื”ืŸ ืžื‘ื—ื™ื ืช ืคืจืงื˜ื™ื•ืช ื•ื”ืŸ ืžื‘ื—ื™ื ืช ื‘ื˜ื™ื—ื•ืช. ื”ืจื‘ื” ื™ื•ืชืจ ื˜ื•ื‘ ื•ื ื›ื•ืŸ ืื™ื“ื™ืื•ืœื•ื’ื™ืช ืœืคืจื•ืก ืจืฆื™ื ื ืคืจื“ื™ื ืœื›ืœ ืคืจื•ื™ืงื˜, ืื• ืืคื™ืœื• ืœื›ืœ ืกื‘ื™ื‘ื”.

ืœืžืจื‘ื” ื”ืžื–ืœ, ื–ื• ืื™ื ื” ื‘ืขื™ื” ื›ืœืœ, ืฉื›ืŸ ื›ืขืช ืื ื• ื ืคืจื•ืก gitlab-ranner ื™ืฉื™ืจื•ืช ื›ื—ืœืง ืžื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ืžืžืฉ ื‘-Kubernetes.

Gitlab ืžืกืคืง ืชืจืฉื™ื ื”ื’ื” ืžื•ื›ืŸ ืœืคืจื™ืกืช gitlab-runner ืœ-Kubernetes. ืื– ื›ืœ ืžื” ืฉืืชื” ืฆืจื™ืš ืœืขืฉื•ืช ื–ื” ืœื‘ืจืจ ืืกื™ืžื•ืŸ ืจื™ืฉื•ื ืขื‘ื•ืจ ื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ื‘ ื”ื’ื“ืจื•ืช -> CI / CD -> ืจืฆื™ื ื•ื”ืขื‘ื™ืจื• ืื•ืชื• ืœื”ื’ื”:

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.

ืื ื”ื›ืœ ื ืขืฉื” ื ื›ื•ืŸ, ืืชื” ืืžื•ืจ ืœืจืื•ืช ืจืฅ ืจืฉื•ื ื‘ืงื˜ืข ืจืฆื™ื, ื‘ื”ื’ื“ืจื•ืช ื”ืคืจื•ื™ืงื˜ ืฉืœืš.

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืจืฅ ืฉื ื•ืกืฃ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื”ืื ื–ื” ื›ืœ ื›ืš ืคืฉื•ื˜? - ื›ืŸ, ื–ื” ื›ืœ ื›ืš ืคืฉื•ื˜! ืื™ืŸ ื™ื•ืชืจ ื˜ืจื—ื” ื‘ืจื™ืฉื•ื ื™ื“ื ื™ ืฉืœ ืจืฆื™ื, ืžืขืชื” ื”ืจืฆื™ื ื™ื™ื•ื•ืฆืจื• ื•ื™ื™ื”ืจืกื• ืื•ื˜ื•ืžื˜ื™ืช.

6. ืคืจื•ืก ืชืจืฉื™ืžื™ Helm ืขื QBEC

ืžืื– ื”ื—ืœื˜ื ื• ืœืฉืงื•ืœ gitlab-ranner ื—ืœืง ืžื”ืคืจื•ื™ืงื˜ ืฉืœื ื•, ื”ื’ื™ืข ื”ื–ืžืŸ ืœืชืืจ ืื•ืชื• ื‘ืžืื’ืจ Git ืฉืœื ื•.

ื ื•ื›ืœ ืœืชืืจ ืืช ื–ื” ื›ืžืจื›ื™ื‘ ื ืคืจื“ ืืชืจ ืื™ื ื˜ืจื ื˜, ืืš ื‘ืขืชื™ื“ ืื ื• ืžืชื›ื ื ื™ื ืœืคืจื•ืก ืขื•ืชืงื™ื ืฉื•ื ื™ื ืืชืจ ืื™ื ื˜ืจื ื˜ ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืžืื•ื“, ื‘ื ื™ื’ื•ื“ gitlab-ranner, ืฉื™ื™ืคืจืก ืจืง ืคืขื ืื—ืช ื‘ื›ืœ ืืฉื›ื•ืœ Kubernetes. ืื– ื‘ื•ืื• ื ืืชื—ืœ ืขื‘ื•ืจื• ืืคืœื™ืงืฆื™ื” ื ืคืจื“ืช:

cd deploy
qbec init gitlab-runner
cd gitlab-runner

ื”ืคืขื ืœื ื ืชืืจ ื™ืฉื•ื™ื•ืช Kubernetes ื‘ืื•ืคืŸ ื™ื“ื ื™, ืืœื ื ื™ืงื— ืชืจืฉื™ื Helm ืžื•ื›ืŸ. ืื—ื“ ื”ื™ืชืจื•ื ื•ืช ืฉืœ qbec ื”ื•ื ื”ื™ื›ื•ืœืช ืœื”ืฆื™ื’ ืชืจืฉื™ืžื™ Helm ื™ืฉื™ืจื•ืช ืžืžืื’ืจ Git.

ื‘ื•ืื• ื ื—ื‘ืจ ืื•ืชื• ื‘ืืžืฆืขื•ืช ืชืช-ืžื•ื“ื•ืœ git:

git submodule add https://gitlab.com/gitlab-org/charts/gitlab-runner vendor/gitlab-runner

ืขื›ืฉื™ื• ื”ืกืคืจื™ื™ื” ืกืคืง/gitlab-ranner ื™ืฉ ืœื ื• ืžืื’ืจ ืขื ืชืจืฉื™ื ืขื‘ื•ืจ 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 ืื– ื ืขื‘ื™ืจ ืืช ื”ืฉื‘ื™ืœ ืœืชืจืฉื™ื params.values, ืฉืื ื• ืœื•ืงื—ื™ื ืžืคืจืžื˜ืจื™ ื”ืกื‘ื™ื‘ื”, ื•ืื– ืžื’ื™ืข ื”ืื•ื‘ื™ื™ืงื˜ ืื™ืชื•

  • nameTemplate - ื›ื•ืชืจืช ื”ื”ืคืฆื”
  • ืžืจื—ื‘ ืฉืžื•ืช - ืžืจื—ื‘ ื”ืฉืžื•ืช ื”ื•ืขื‘ืจ ืœื”ื’ื”
  • ื”ืงื•ื‘ืฅ ื”ื–ื” - ืคืจืžื˜ืจ ื ื“ืจืฉ ื”ืžืขื‘ื™ืจ ืืช ื”ื ืชื™ื‘ ืœืงื•ื‘ืฅ ื”ื ื•ื›ื—ื™
  • ืžึดืœื•ึผืœึดื™ - ืžืฆื™ื’ ืืช ื”ืคืงื•ื“ื” ืชื‘ื ื™ืช ื”ื’ื” ืขื ื›ืœ ื”ื˜ื™ืขื•ื ื™ื ื‘ืขืช ืขื™ื‘ื•ื“ ื”ืชืจืฉื™ื

ื›ืขืช ื ืชืืจ ืืช ื”ืคืจืžื˜ืจื™ื ืขื‘ื•ืจ ื”ืจื›ื™ื‘ ืฉืœื ื• ื‘ environments/base.libsonnet:

local secrets = import '../secrets/base.libsonnet';

{
  components: {
    gitlabRunner: {
      name: 'gitlab-runner',
      values: {
        gitlabUrl: 'https://gitlab.com/',
        rbac: {
          create: true,
        },
        runnerRegistrationToken: secrets.runnerRegistrationToken,
      },
    },
  },
}

ืฉื™ื ืœื‘ runnerRegistrationToken ืื ื—ื ื• ืœื•ืงื—ื™ื ืžืงื•ื‘ืฅ ื—ื™ืฆื•ื ื™ secrets/base.libsonnet, ื‘ื•ืื• ื ื™ืฆื•ืจ ืื•ืชื•:

{
  runnerRegistrationToken: 'yga8y-jdCusVDn_t4Wxc',
}

ื‘ื•ื ื ื‘ื“ื•ืง ืื ื”ื›ืœ ืขื•ื‘ื“:

qbec show default

ืื ื”ื›ืœ ืชืงื™ืŸ, ืื– ื ื•ื›ืœ ืœืžื—ื•ืง ืืช ื”ืžื”ื“ื•ืจื” ืฉื ืคืจืกื” ื‘ืขื‘ืจ ื“ืจืš Helm:

helm uninstall gitlab-runner

ื•ืคืจื•ืก ืื•ืชื• ื‘ืื•ืชื• ืื•ืคืŸ, ืื‘ืœ ื“ืจืš qbec:

qbec apply default

7. ืžื‘ื•ื ืœ-git-crypt

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 ื–ื” ืœื ื‘ื˜ื•ื—, ื ื›ื•ืŸ? ืื– ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ืฆืคื™ืŸ ืื•ืชื ื›ืจืื•ื™.

ื‘ื“ืจืš ื›ืœืœ, ืœืžืขืŸ ืžืฉืชื ื” ืื—ื“, ื–ื” ืœื ืชืžื™ื“ ื”ื’ื™ื•ื ื™. ืืชื” ื™ื›ื•ืœ ืœื”ืขื‘ื™ืจ ืกื•ื“ื•ืช ืœ qbec ื•ื“ืจืš ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ืฉืœ ืžืขืจื›ืช ื”-CI ืฉืœืš.
ืื‘ืœ ืจืื•ื™ ืœืฆื™ื™ืŸ ืฉื™ืฉ ื’ื ืคืจื•ื™ืงื˜ื™ื ืžื•ืจื›ื‘ื™ื ื™ื•ืชืจ ืฉื™ื›ื•ืœื™ื ืœื”ื›ื™ืœ ื”ืจื‘ื” ื™ื•ืชืจ ืกื•ื“ื•ืช; ื”ืขื‘ืจืช ื›ื•ืœื ื“ืจืš ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ืชื”ื™ื” ืงืฉื” ื‘ื™ื•ืชืจ.

ื™ืชืจ ืขืœ ื›ืŸ, ื‘ืžืงืจื” ื–ื” ืœื ืื•ื›ืœ ืœืกืคืจ ืœืš ืขืœ ื›ืœื™ ื ืคืœื ื›ืžื• git-crypt.

git-crypt ื–ื” ื’ื ื ื•ื— ื‘ื›ืš ืฉื”ื•ื ืžืืคืฉืจ ืœืฉืžื•ืจ ืืช ื›ืœ ื”ื”ื™ืกื˜ื•ืจื™ื” ืฉืœ ื”ืกื•ื“ื•ืช, ื›ืžื• ื’ื ืœื”ืฉื•ื•ืช, ืœืžื–ื’ ื•ืœืคืชื•ืจ ืงื•ื ืคืœื™ืงื˜ื™ื ื‘ืื•ืชื• ืื•ืคืŸ ื›ืžื• ืฉืื ื—ื ื• ืจื’ื™ืœื™ื ืœืขืฉื•ืช ื‘ืžืงืจื” ืฉืœ Git.

ื“ื‘ืจ ืจืืฉื•ืŸ ืœืื—ืจ ื”ื”ืชืงื ื” git-crypt ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื™ืฆื•ืจ ืžืคืชื—ื•ืช ืœืžืื’ืจ ืฉืœื ื•:

git crypt init

ืื ื™ืฉ ืœืš ืžืคืชื— PGP, ืืชื” ื™ื›ื•ืœ ืžื™ื“ ืœื”ื•ืกื™ืฃ ืืช ืขืฆืžืš ื›ืžืฉืชืฃ ืคืขื•ืœื” ืขื‘ื•ืจ ื”ืคืจื•ื™ืงื˜ ื”ื–ื”:

git-crypt add-gpg-user [email protected]

ื›ืš ืืชื” ืชืžื™ื“ ื™ื›ื•ืœ ืœืคืขื ื— ืืช ื”ืžืื’ืจ ื”ื–ื” ื‘ืืžืฆืขื•ืช ื”ืžืคืชื— ื”ืคืจื˜ื™ ืฉืœืš.

ืื ืื™ืŸ ืœืš ืžืคืชื— PGP ื•ืื™ื ืš ืžืฆืคื” ืœื•, ืื– ืืชื” ื™ื›ื•ืœ ืœืœื›ืช ื‘ื“ืจืš ืื—ืจืช ื•ืœื™ื™ืฆื ืืช ืžืคืชื— ื”ืคืจื•ื™ืงื˜:

git crypt export-key /path/to/keyfile

ืœืคื™ื›ืš, ื›ืœ ืžื™ ืฉื™ืฉ ืœื• ืžื™ื•ืฆื ืงื•ื‘ืฅ ืžืคืชื— ื™ื•ื›ืœ ืœืคืขื ื— ืืช ื”ืžืื’ืจ ืฉืœืš.

ื”ื’ื™ืข ื”ื–ืžืŸ ืœื”ื’ื“ื™ืจ ืืช ื”ืกื•ื“ ื”ืจืืฉื•ืŸ ืฉืœื ื•.
ื”ืจืฉื• ืœื™ ืœื”ื–ื›ื™ืจ ืœื›ื ืฉืื ื—ื ื• ืขื“ื™ื™ืŸ ื‘ืžื“ืจื™ืš deploy/gitlab-runner/, ืฉื‘ื• ื™ืฉ ืœื ื• ืกืคืจื™ื™ื” ืกื•ื“ื•ืช/, ื‘ื•ืื• ื ืฆืคื™ืŸ ืืช ื›ืœ ื”ืงื‘ืฆื™ื ื‘ื•, ืœืฉื ื›ืš ื ื™ืฆื•ืจ ืงื•ื‘ืฅ secrets/gitattributes ืขื ื”ืชื•ื›ืŸ ื”ื‘ื:

* filter=git-crypt diff=git-crypt
.gitattributes !filter !diff

ื›ืคื™ ืฉื ื™ืชืŸ ืœืจืื•ืช ืžื”ืชื•ื›ืŸ, ื›ืœ ื”ืงื‘ืฆื™ื ืžื›ื•ืกื™ื * ื™ื•ืกืข ื“ืจืš git-crypt, ื—ื•ืฅ ืžื”ืจื•ื‘ ืชื›ื•ื ื•ืช

ื ื•ื›ืœ ืœื‘ื“ื•ืง ื–ืืช ืขืœ ื™ื“ื™ ื”ืคืขืœืช:

git crypt status -e

ื”ืคืœื˜ ื™ื”ื™ื” ืจืฉื™ืžื” ืฉืœ ื›ืœ ื”ืงื‘ืฆื™ื ื‘ืžืื’ืจ ืฉืขื‘ื•ืจื ืžื•ืคืขืœืช ื”ื”ืฆืคื ื”

ื–ื” ื”ื›ืœ, ืขื›ืฉื™ื• ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื• ื‘ื‘ื˜ื—ื”:

cd ../..
git add .
git commit -m "Add deploy for gitlab-runner"

ื›ื“ื™ ืœื—ืกื•ื ืžืื’ืจ, ืคืฉื•ื˜ ื”ืจืฅ:

git crypt lock

ื•ืžื™ื“ ื›ืœ ื”ืงื‘ืฆื™ื ื”ืžื•ืฆืคื ื™ื ื™ื”ืคื›ื• ืœืžืฉื”ื• ื‘ื™ื ืืจื™, ืื™ ืืคืฉืจ ื™ื”ื™ื” ืœืงืจื•ื ืื•ืชื.
ื›ื“ื™ ืœืคืขื ื— ืืช ื”ืžืื’ืจ, ื”ืคืขืœ:

git crypt unlock

8. ืฆื•ืจ ืชืžื•ื ืช ืืจื’ื– ื›ืœื™ื

ืชืžื•ื ืช ืืจื’ื– ื›ืœื™ื ื”ื™ื ืชืžื•ื ื” ืขื ื›ืœ ื”ื›ืœื™ื ืฉื‘ื”ื ื ืฉืชืžืฉ ืœืคืจื™ืกืช ื”ืคืจื•ื™ืงื˜ ืฉืœื ื•. ื”ื•ื ื™ืฉืžืฉ ืืช ื”ืจืฅ ืฉืœ Gitlab ืœื‘ื™ืฆื•ืข ืžืฉื™ืžื•ืช ืคืจื™ืกื” ื˜ื™ืคื•ืกื™ื•ืช.

ื”ื›ืœ ืคืฉื•ื˜ ื›ืืŸ, ื‘ื•ืื• ื ื™ืฆื•ืจ ืื—ื“ ื—ื“ืฉ dockerfiles/toolbox/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.

ื›ื“ื™ ืœืขืฉื•ืช ื–ืืช, ื‘ื•ื ื ืœืš ืœืกืคืจื™ื™ื” ืขื 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,
      },
    ],
  },
]

ื ืชืืจ ื’ื ืืช ื”ืคืจืžื˜ืจื™ื ื”ื—ื“ืฉื™ื ื‘ environments/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',
    },
  },
}

ืฉื™ื ืœื‘ $.components.rbac.name ืžืชื™ื™ื—ืก ืœ ืฉื ืขื‘ื•ืจ ืจื›ื™ื‘ rbac

ื‘ื•ื ื ื‘ื“ื•ืง ืžื” ื”ืฉืชื ื”:

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. ื›ืœ ื“ื—ื™ืคื” ืขื ืชื’ ื—ื“ืฉ ืชืืชื—ืœ ืืช ื‘ื ื™ื™ืช ื”ืชืžื•ื ื•ืช ืขื ืชื’ ื–ื”.

ื‘ื•ื ื ืขืฉื” ืืช ื–ื” git push --tags, ื•ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื”ืฆื™ื ื•ืจ ื”ืจืืฉื•ืŸ ืฉืœื ื•:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืฆื™ื ื•ืจ ื”ืจืืฉื•ืŸ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื›ื“ืื™ ืœื”ืกื‘ ืืช ืชืฉื•ืžืช ืœื‘ื›ื ืœืขื•ื‘ื“ื” ืฉื”ืจื›ื‘ื” ืœืคื™ ืชื’ื™ื ืžืชืื™ืžื” ืœื‘ื ื™ื™ืช ืชืžื•ื ื•ืช docker, ืืš ืื™ื ื” ืžืชืื™ืžื” ืœืคืจื™ืกืช ืืคืœื™ืงืฆื™ื” ืœ-Kubernetes. ืžื›ื™ื•ื•ืŸ ืฉื ื™ืชืŸ ืœื”ืงืฆื•ืช ืชื’ื™ื ื—ื“ืฉื™ื ื’ื ืœ-commits ื™ืฉื ื™ื, ื‘ืžืงืจื” ื–ื”, ืืชื—ื•ืœ ื”ืฆื™ื ื•ืจ ืขื‘ื•ืจื ื™ื•ื‘ื™ืœ ืœืคืจื™ืกื” ืฉืœ ื”ื’ืจืกื” ื”ื™ืฉื ื”.

ื›ื“ื™ ืœืคืชื•ืจ ื‘ืขื™ื” ื–ื•, ื‘ื“ืจืš ื›ืœืœ ื”ื‘ื ื™ื™ื” ืฉืœ ืชืžื•ื ื•ืช docker ืงืฉื•ืจื” ืœืชื’ื™ื•ืช, ื•ืคืจื™ืกื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ืœืกื ื™ืฃ ืื‘, ืฉื‘ื”ืŸ ื’ืจืกืื•ืช ืฉืœ ื”ืชืžื•ื ื•ืช ืฉื ืืกืคื• ืžืงื•ื“ื“ื•ืช ืงืฉื”. ื–ื” ื”ืžืงื•ื ืฉื‘ื• ืืชื” ื™ื›ื•ืœ ืœืืชื—ืœ ืืช ื”ื—ื–ืจื” ืœืื—ื•ืจ ืขื ื”ื—ื–ืจื” ืคืฉื•ื˜ื” ืื‘-ืขื ืคื™ื.

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

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืžืฉืชื ื” ืฉื ื•ืกืฃ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ืขื›ืฉื™ื• ื‘ื•ืื• ื ืขื“ื›ืŸ ืืช ืฉืœื ื• .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:

  • --root some/app โ€” ืžืืคืฉืจ ืœืš ืœืงื‘ื•ืข ืืช ื”ืกืคืจื™ื™ื” ืฉืœ ื™ื™ืฉื•ื ืกืคืฆื™ืคื™
  • --force:k8s-context __incluster__ - ื–ื”ื• ืžืฉืชื ื” ืงืกื ืฉืื•ืžืจ ืฉื”ืคืจื™ืกื” ืชืชืจื—ืฉ ื‘ืื•ืชื• ืืฉื›ื•ืœ ื‘ื• ืคื•ืขืœ gtilab-runner. ื–ื” ื”ื›ืจื—ื™ ื›ื™ ืื—ืจืช qbec ื™ื ืกื” ืœืžืฆื•ื ืฉืจืช Kubernetes ืžืชืื™ื ื‘-kubeconfig ืฉืœืš
  • --ืœึทื—ึฒื›ื•ึนืช - ืžืืœืฅ ืืช qbec ืœื”ืžืชื™ืŸ ืขื“ ืฉื”ืžืฉืื‘ื™ื ืฉื”ื™ื ื™ื•ืฆืจืช ื™ื›ื ืกื• ืœืžืฆื‘ Ready ื•ืจืง ืื– ืœืฆืืช ืขื ืงื•ื“ ื™ืฆื™ืื” ืžื•ืฆืœื—.
  • -ื›ืŸ - ืคืฉื•ื˜ ืžืฉื‘ื™ืช ืืช ื”ืžืขื˜ืคืช ื”ืื™ื ื˜ืจืืงื˜ื™ื‘ื™ืช ื”ืื ืืชื” ื‘ื˜ื•ื—? ื›ืืฉืจ ื ืคืจืก.

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add .gitlab-ci.yml
git commit -m "Automate deploy"

ื•ืื—ืจื™ ื“ื—ื™ืคืช ื’ื™ื˜ ื ืจืื” ื›ื™ืฆื“ ื”ื™ื™ืฉื•ืžื™ื ืฉืœื ื• ื ืคืจืกื•:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืฆื™ื ื•ืจ ื”ืฉื ื™

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

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 ื•ืขื›ืฉื™ื• ื ื“ื—ื•ืฃ ืชืžื•ื ื” ืขื ืฉื ืกื ื™ืฃ ื”-commit ืฉืืชื—ืœ ืืช ื”-pipeline. ืจืื•ื™ ืœืฆื™ื™ืŸ ืฉื–ื” ื™ืขื‘ื•ื“ ื’ื ืขื ืชื’ื™ื•ืช, ืฉื™ืืคืฉืจื• ืœื ื• ืœืฉืžื•ืจ ืฆื™ืœื•ืžื™ ืžืฆื‘ ืฉืœ ืืชืจ ืขื ื’ืจืกื” ืกืคืฆื™ืคื™ืช ื‘-docer-registry.

ื›ืืฉืจ ื”ืฉื ืฉืœ ืชื’ docker ืขื‘ื•ืจ ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ื”ืืชืจ ื™ื›ื•ืœ ืœื”ื™ื•ืช ืœืœื ืฉื™ื ื•ื™, ืขื“ื™ื™ืŸ ืขืœื™ื ื• ืœืชืืจ ืืช ื”ืฉื™ื ื•ื™ื™ื ื‘- Kubernetes, ืื—ืจืช ื”ื•ื ืคืฉื•ื˜ ืœื ื™ืคืจื•ืก ืžื—ื“ืฉ ืืช ื”ืืคืœื™ืงืฆื™ื” ืžื”ืชืžื•ื ื” ื”ื—ื“ืฉื”, ืžื›ื™ื•ื•ืŸ ืฉื”ื•ื ืœื ื™ื‘ื—ื™ืŸ ื‘ืฉื™ื ื•ื™ื™ื ื‘ืคืจื™ืกื” ืœึฐื”ึทืคึฐื’ึดื™ืŸ.

ืืคืฉืจื•ืช โ€”vm:ext-str digest="$DIGEST" ืขื‘ื•ืจ qbec - ืžืืคืฉืจ ืœื”ืขื‘ื™ืจ ืžืฉืชื ื” ื—ื™ืฆื•ื ื™ ืœ-jsonnet. ืื ื—ื ื• ืจื•ืฆื™ื ืฉื”ื•ื ื™ื™ืคืจืก ืžื—ื“ืฉ ื‘ืืฉื›ื•ืœ ืขื ื›ืœ ืžื”ื“ื•ืจื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ืฉืœื ื•. ืื ื—ื ื• ื›ื‘ืจ ืœื ื™ื›ื•ืœื™ื ืœื”ืฉืชืžืฉ ื‘ืฉื ื”ืชื’, ืฉื›ืขืช ื™ื›ื•ืœ ืœื”ื™ื•ืช ื‘ืœืชื™ ื ื™ืชืŸ ืœืฉื™ื ื•ื™, ืžื›ื™ื•ื•ืŸ ืฉืื ื—ื ื• ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ืงืฉื•ืจื™ื ืœื’ืจืกื” ืกืคืฆื™ืคื™ืช ืฉืœ ื”ืชืžื•ื ื” ื•ืœื”ืคืขื™ืœ ืืช ื”ืคืจื™ืกื” ื›ืฉื”ื™ื ืžืฉืชื ื”.

ื›ืืŸ ื ื™ืขื–ืจ ื‘ื™ื›ื•ืœืช ืฉืœ ืงื ื™ืงื• ืœืฉืžื•ืจ ืชืžื•ื ืช ืชืงืฆื™ืจ ืœืงื•ื‘ืฅ (ืืคืฉืจื•ืช --digest-file)
ืœืื—ืจ ืžื›ืŸ ื ืขื‘ื™ืจ ืืช ื”ืงื•ื‘ืฅ ื”ื–ื” ื•ื ืงืจื ืื•ืชื• ื‘ื–ืžืŸ ื”ืคืจื™ืกื”.

ื‘ื•ืื• ื ืขื“ื›ืŸ ืืช ื”ืคืจืžื˜ืจื™ื ืฉืœื ื• deploy/website/environments/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',
    },
  },
}

ืกื™ื™ื, ืขื›ืฉื™ื• ื›ืœ ื”ืชื—ื™ื™ื‘ื•ืช ืื‘ ืžืืชื—ืœ ืืช ื”ื‘ื ื™ื™ื” ืฉืœ ืชืžื•ื ืช docker ืขื‘ื•ืจ ืืชืจ ืื™ื ื˜ืจื ื˜, ื•ืœืื—ืจ ืžื›ืŸ ืœืคืจื•ืก ืื•ืชื• ืœ-Kubernetes.

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add .
git commit -m "Configure dynamic build"

ื ื‘ื“ื•ืง ืžืื•ื—ืจ ื™ื•ืชืจ ื“ื—ื™ืคืช ื’ื™ื˜ ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืจืื•ืช ืžืฉื”ื• ื›ื–ื”:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืฆื™ื ื•ืจ ืœืžืืกื˜ืจ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื‘ืื•ืคืŸ ืขืงืจื•ื ื™, ืื ื—ื ื• ืœื ืฆืจื™ื›ื™ื ืœืคืจื•ืก ืžื—ื“ืฉ ืืช 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/**/*

ืฉื™ื ื•ื™ื™ื ื™ืืคืฉืจ ืœืš ืœืขืงื•ื‘ ืื—ืจ ืฉื™ื ื•ื™ื™ื ื‘ deploy/gitlab-runner/ ื•ื™ืคืขื™ืœ ืืช ื”ืขื‘ื•ื“ื” ืฉืœื ื• ืจืง ืื ื™ื”ื™ื• ื›ืืœื”

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add .gitlab-ci.yml
git commit -m "Reduce gitlab-runner deploy"

ื“ื—ื™ืคืช ื’ื™ื˜, ื–ื” ื™ื•ืชืจ ื˜ื•ื‘:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื”ืฆื™ื ื•ืจ ื”ืžืขื•ื“ื›ืŸ

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

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, ื”ื•ืกืฃ ืฉื ื‘ืœื•ืง ืกื‘ื™ื‘ื”:

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_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 ืœื”ื—ื™ืœ ื‘ืจื™ืจืช ืžื—ื“ืœ - ื–ื” ื‘ื“ื™ื•ืง ื”ืจื’ืข ืฉื‘ื• ื ื ืกื” ืœืชืืจ ืืช ื”ื”ื‘ื“ืœื™ื ื‘ืกื‘ื™ื‘ื•ืช ืฉืœื ื• (ืกืงื™ืจื” ื•ื‘ืจื™ืจืช ืžื—ื“ืœ):

ื”ื•ืกืฃ ืกืงื™ืจื” ืกื‘ื™ื‘ื” ื‘ deploy/website/qbec.yaml

spec:
  environments:
    review:
      defaultNamespace: docs
      server: https://kubernetes.example.org:8443

ืื– ื ื›ืจื™ื– ืขืœ ื–ื” deploy/website/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

ื•ืจืฉื•ื ืืช ื”ืคืจืžื˜ืจื™ื ื”ืžื•ืชืืžื™ื ืื™ืฉื™ืช ืขื‘ื•ืจื• deploy/website/environments/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',
    },
  },
}

ื‘ื•ืื• ื’ื ื ืกืชื›ืœ ืžืงืจื•ื‘ ืขืœ jobu stop_review, ื”ื•ื ื™ื•ืคืขืœ ื›ืืฉืจ ื”ืกื ื™ืฃ ื™ื™ืžื—ืง ื•ื›ื“ื™ ืฉ-gitlab ืœื ื™ื ืกื” ืœื‘ืฆืข ืืช ื”ืชืฉืœื•ื ื”ื•ื ื‘ืฉื™ืžื•ืฉ GIT_STRATEGY: ืื™ืŸ, ืžืื•ื—ืจ ื™ื•ืชืจ ืื ื—ื ื• ืžืฉื‘ื˜ื™ื ืื‘- ืœื”ืกื ื™ืฃ ื•ืœืžื—ื•ืง ื‘ื™ืงื•ืจืช ื“ืจื›ื•.
ื–ื” ืงืฆืช ืžื‘ืœื‘ืœ, ืื‘ืœ ืขื“ื™ื™ืŸ ืœื ืžืฆืืชื™ ื“ืจืš ื™ืคื” ื™ื•ืชืจ.
ืืคืฉืจื•ืช ื—ืœื•ืคื™ืช ืชื”ื™ื” ืœืคืจื•ืก ื›ืœ ื‘ื™ืงื•ืจืช ืœืžืจื—ื‘ ืฉืžื•ืช ืฉืœ ืžืœื•ืŸ, ืฉืชืžื™ื“ ื ื™ืชืŸ ืœื”ืจื•ืก ืœื—ืœื•ื˜ื™ืŸ.

ืืœ ืชืฉื›ื— ืœื‘ืฆืข ืืช ื”ืฉื™ื ื•ื™ื™ื ืฉืœื ื•:

git add .
git commit -m "Enable automatic review"

ื“ื—ื™ืคืช ื’ื™ื˜, git checkout -b test, ื‘ื“ื™ืงืช ืžืงื•ืจ git push, ื—ืฉื‘ื•ืŸ:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ืกื‘ื™ื‘ื•ืช ืฉื ื•ืฆืจื• ื‘-Gitlab

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื”ื›ืœ ืขื•ื‘ื“? - ืžืขื•ืœื”, ืžื—ืง ืืช ืกื ื™ืฃ ื”ื‘ื“ื™ืงื” ืฉืœื ื•: ืžืืกื˜ืจ ืœืงื•ืคื•ืช, git push origin :test, ืื ื• ื‘ื•ื“ืงื™ื ืฉืขื‘ื•ื“ื•ืช ืžื—ื™ืงืช ื”ืกื‘ื™ื‘ื” ืขื‘ื“ื• ืœืœื ืฉื’ื™ืื•ืช.

ื›ืืŸ ืื ื™ ืจื•ืฆื” ืœื”ื‘ื”ื™ืจ ืžื™ื“ ืฉื›ืœ ื™ื–ื ื‘ืคืจื•ื™ืงื˜ ื™ื›ื•ืœ ืœื™ืฆื•ืจ ืกื ื™ืคื™ื, ื”ื•ื ื™ื›ื•ืœ ื’ื ืœืฉื ื•ืช .gitlab-ci.yml ืงื•ื‘ืฅ ื•ื’ื™ืฉื” ืœืžืฉืชื ื™ื ืกื•ื“ื™ื™ื.
ืœื›ืŸ, ืžื•ืžืœืฅ ืžืื•ื“ ืœืืคืฉืจ ืฉื™ืžื•ืฉ ื‘ื”ื ืจืง ืœืขื ืคื™ื ืžื•ื’ื ื™ื, ืœืžืฉืœ ื‘ ืื‘, ืื• ืฆื•ืจ ืงื‘ื•ืฆื” ื ืคืจื“ืช ืฉืœ ืžืฉืชื ื™ื ืขื‘ื•ืจ ื›ืœ ืกื‘ื™ื‘ื”.

13. ืกืงื™ืจืช ืืคืœื™ืงืฆื™ื•ืช

ืกืงื•ืจ ืืคืœื™ืงืฆื™ื•ืช ื–ื•ื”ื™ ืชื›ื•ื ืช GitLab ื”ืžืืคืฉืจืช ืœื”ื•ืกื™ืฃ ืœื—ืฆืŸ ืขื‘ื•ืจ ื›ืœ ืงื•ื‘ืฅ ื‘ืžืื’ืจ ื›ื“ื™ ืœื”ืฆื™ื’ ืื•ืชื• ื‘ืžื”ื™ืจื•ืช ื‘ืกื‘ื™ื‘ื” ืคืจื•ืกื”.

ื›ื“ื™ ืฉื”ืœื—ืฆื ื™ื ื”ืืœื” ื™ื•ืคื™ืขื•, ืขืœื™ืš ืœื™ืฆื•ืจ ืงื•ื‘ืฅ .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"

ื“ื—ื™ืคืช ื’ื™ื˜, ื•ืœื‘ื“ื•ืง:

ืฆื™ืœื•ื ืžืกืš ืฉืœ ื›ืคืชื•ืจ ื”-Review App

ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ื”ืขื‘ื•ื“ื” ื‘ื•ืฆืขื”!

ืžืงื•ืจื•ืช ื”ืคืจื•ื™ืงื˜:

ืชื•ื“ื” ืขืœ ืชืฉื•ืžืช ื”ืœื‘, ืื ื™ ืžืงื•ื•ื” ืฉืื”ื‘ืช ืžื ืกื” ื›ืœื™ื ื—ื“ืฉื™ื ืœื‘ื ื™ื™ื” ื•ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืคืจื™ืกื” ื‘-Kubernetes

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”