k8s에서build &push docker 이미지

개인이 개발할 수 있는 환경을 고려할 때 유력한 선택은gitlab의 구축[1]이다.
이번 k8s에서는 kubernetes 기능만 사용해 gitlab의 창고에서 관리되는 dockerfiledocker build & push, 컨테이너 등록표에 push를 넣는 기구 = k8s에서docker build 가능한 gitlab-runner Pod를 디자인했다.(helm 등 관리 도구는 필요 없습니다.)

gitlab 정보


gitlab는 개인 클라우드/로컬에서github를 구축할 수 있는 패키지입니다.
https://about.gitlab.com
클라우드 코드 관리, 팀 개발 등 기본 기능 외에도 컨테이너 레지스트리 구축, CI/CD 등 다양한 확장 기능을 통해 맞춤형으로 제작할 수 있다.

gitlab-runner


gitlab-runner는gitlab의 발행을 받고CI를 실시하는 기구입니다.
gitlab 창고의push를 감지하고, 각executor를 사용하여 미리 정의된 명령을 실행할 수 있습니다.

gitlab-runner 실행 executor 은 명령의 실행을 실현합니다.
https://docs.gitlab.com/runner/executors/index.html
이번에는gitlab-runner내docker에서 명령을 수행할 수 있고docker 컨테이너 이미지를 사용하여docker executor와 같은 절차를 실행할 수 있습니다.
https://hub.docker.com/_/docker

자동 액세스 토큰 등록


gitlab는 등록된gitlab-runner가 요청하는 구조를 허용하기 때문에 모든runner는 방문 영패를 발행해야 합니다.
방문 영패 발행은 러너 측에서 등록할 때 수동으로 해야 하지만 k8s 기능, init 컨테이너 Lifecycle Events를 사용하여 이 부분을 자동화할 수 있다.

컨테이너


init 컨테이너는 주로 Pod로 구성된 컨테이너 동작 이전에 실행되는 컨테이너입니다.
주 용기에 사용할 파일을 미리 만들거나 설치를 실행할 수 있습니다.
https://kubernetes.io/ja/docs/concepts/workloads/pods/init-containers/

Lifecycle Events 소개


Lifecycle Events는 Pod 내 컨테이너에 대해 특정 시간에 명령을 수행할 수 있는 기능입니다.
컨테이너의 프로세스는 루트 프로세스로, Lifecycle Events는 다른 컨테이너의 프로세스로 수행됩니다.
https://kubernetes.io/ja/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/

컨테이너와 Lifecycle Events의 차이



양자의 특징은 다음과 같다.

  • 컨테이너
  • Pod를 설정하고 Pod로 설정된 용기 앞에서 추출합니다.

  • init 용기가 실패하면 주 용기를 실행하지 않습니다.
  • init 용기를 끝내야 합니다.init 컨테이너가 끝난 후 주 처리(용기)와 격리됩니다.
  • k8s의 template.spec.containers 요령에 따라 선언을 기술할 수 있기 때문에volume 등을 설치할 수 있다
  • 따라서 주 용기에 사용되는 필요한 데이터 등을 만드는 데 주로 사용된다.

  • LifecycleEvents
  • 용기를 설정하고postStart와preStop을 설정할 수 있습니다.
  • 용기의 루트 프로세스가 실행되기 전에postStart를 실행합니다.
  • 컨테이너가 끝나기 전에 preStop을 실행합니다.

  • postStart/preStop 실패 시 컨테이너가 강제로 종료됩니다.

  • LifecycleEvents는 컨테이너의 하위 프로세스로 실행됩니다.
  • 루트 프로세스 이후postStart를 실행할 수 있습니다.
  • preStop은 Pod 자체 종료 시에도 작동하지만, 처리 종료 전에 Pod를 삭제할 가능성도 있다.
  • template.spec.terminationGracePeriodSeconds(v1.20~)의 설정을 통해 처리 종료 시간을 확보할 수 있음
  • 실행 분류에 따라 케이스/해석기(exec)
  • 필요

    이용 방법


    gitlab-runner에서 init 용기에서 초기 영패 제작을 실시하고 config를 제작합니다.이 용기를 사용해서 여기에서 만든 config입니다.gitlab-runner가 불법으로 정지되었을 때,preStop을 실행하면gitlab의gitlab-runner 목록에서 제외할 수 있습니다.

    구축 방법


    동작 개요


    본 보도에 구축된 선언은 다음과 같은 구조로 동작할 것이다.

    gitlab의 구축


    gitlab는 다음과 같은 방법으로 구축할 수 있습니다.
    https://www.gitlab.jp/install/?version=ce#ubuntu
    이번RaspberryPi를 사용한 HA 클러스터 구축에는 ansible로 구축되어 있습니다.

    초기 토큰 고정화


    보통 register 영패에 관해서는 gitlab의 WebUI를 보지 않으면 register 영패를 모른다.
    단,gitlab 초기 구축일 경우,config에 기재하여 방문 영패를 고정시킬 수 있습니다./etc/gitlab/gitlab.rb의 임의의 위치에 다음과 같은 내용을 추가합니다.
    /etc/gitlab/gitlab.rb
    gitlab_rails['initial_shared_runners_registration_token'] = 'gitlabtoken'
    
    설정을 변경한 후gitlab-ctl reconfigure.

    docker 설치


    이번에는 Dood(docker out of docker) 구축을 위해gitlab-runner를 실행하는 노드에 docker를 설치해야 합니다.[2]
    https://docs.docker.com/engine/install/ubuntu/

    선언의 절차


    선언에서 init 용기를 통해 설정 파일을 만들고 주 용기에서 설정 파일이 존재하는 디렉터리를 마운트하는 절차를 기술합니다.
    container-builder.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: container-builder
    spec:
      replicas: 2 # レプリカを用意すると、それぞれのPodがregisterされるため、並列実行できます。
      selector:
        matchLabels:
          name: container-builder
      template:
        metadata:
          labels:
            name: container-builder
        spec:
          nodeSelector:
            interface: ethernet
          initContainers:
            - name: init-runner
              image: gitlab/gitlab-runner:latest
              command:
                - gitlab-runner
                - register
                - --non-interactive
                - --url=http://<gitlabのURLを入力>/
                - --registration-token=<gitlabから確認できるregister-tokenを入力>
                - --description=container-builder
                - --tag-list=docker
                - --executor=docker
                - --docker-image=docker:latest
                - --docker-network-mode=host
                - --docker-volumes=/var/run/docker.sock:/var/run/docker.sock
                # - --docker-extra-hosts=<urlが名前解決できない場合はIPアドレスでURLを設定>
              volumeMounts:
                - name: config
                  readOnly: false
                  mountPath: /etc/gitlab-runner/
          containers:
            - image: gitlab/gitlab-runner:latest
              name: gitlab-runner
              ports:
                - containerPort: 80
                  name: http
                - containerPort: 443
                  name: https
              volumeMounts:
                - name: config
                  mountPath: /etc/gitlab-runner/
                  readOnly: false
                - name: socket
                  mountPath: /var/run/docker.sock
                  readOnly: true
              lifecycle:
                preStop:
                  exec:
                    command: ["gitlab-runner", "unregister", "--all-runners"]
          volumes:
            - name: config
              emptyDir: {}
            - name: socket
              hostPath:
                path: /var/run/docker.sock
          restartPolicy: Always
    
    상기 내용kubectl apply -f이 있으면runner는gitlab에 등록하고 CI의 실행 준비가 끝납니다.

    .gitlab-ci.yml 만들기


    gitlab에서 CI를 실행하려면 git 창고의 루트 디렉터리에 다음 파일을 설정하십시오.
    .gitlab-ci.yml
    stages:
      - build
    
    sample-app:
      tags: [docker]
      stage: build
      script:
        - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
        - docker build ./${CI_JOB_NAME} -t "${CI_REGISTRY_IMAGE}/${CI_JOB_NAME}:${CI_COMMIT_TAG:=latest}"
        - docker push "${CI_REGISTRY_IMAGE}/${CI_JOB_NAME}:${CI_COMMIT_TAG:=latest}"
    
    상기는push 후gitlab의 용기 등록표<registryURL>/<gitプロジェクト名>/sample-app:latest(tagがpushされた場合はtag)를 등록 처리한 샘플이다.${CI_***}의 환경 변수는gitlab의 내장 변수로 환경에 따라 자동으로 값을 대입한다.
    https://qiita.com/ynott/items/4c5085b4cd6221bb71c5
    이상 설정이 완료되었습니다.

    앞으로의 과제


    이번에 컨테이너 건설을 실시할 수 있는 기구의 구축 방법을 고려한 결과,kubernetes의 init 컨테이너와 Lifecyclea Enters를 이용하여gitlab-runner를 사용하여 실현하였다.
    gitlab CI/CD 프로젝트의 자동화는 구축뿐만 아니라 테스트와 디자인에도 국한되기 때문에 앞으로 이를 어떻게 실현할 것인가를 고려할 것이다.

    참고 자료


    https://www.skyarch.net/blog/?p=16552
    https://kubernetes.io/ja/docs/concepts/containers/container-lifecycle-hooks/
    각주
    개인 클라우드/로컬 제한이 없으면github도 선택할 수 있습니다.CI/CDGitHub Actions는 가능합니다.↩︎
    Dind(docker in docker)도 수법으로 존재하지만, docker-daemon 과정을 따로 실행해야 하는데, kubernetes의 CRI와 이중 실행으로 자원을 낭비했기 때문에 이번에는 선택할 수 있는 방안이 되지 못했다.↩︎

    좋은 웹페이지 즐겨찾기