git-sync

6 분 소요

git repo를 kubernetes volume으로 구현할수 있는 sidecar pattern git-sync 프로젝트에 대해서 알아본다.

git-sync

Kubernetes Github에 방문하면 다양한 프로젝트들을 볼 수 있다.
Kubernetes Project부터 minikube, kubeadm, kubectl, kubelet, dashboard등 필수적으로 필요하거나 많이 사용되는 프로젝트를 볼 수 있는데, 기존에 storage volume 으로 활용되던 gitrepodeprecated 되어서 방법을 찾다가 유사한 프로젝트를 공식 repo에서 우연히 발견하게 되었다.

git-sync는 sidecar 방식으로 git repository를 clone하는 프로젝트이다.

최초 한번 clone도 가능하고 일정한 간격으로 끌어와서 응용프로그램에 사용할 수 있고 원하는 branch, Tag 또는 특정 git hash 기반으로 pulling이 가능하다.

upstream의 repository에서 대상이 변경되었을때 다시 pulling하고, webhook기능을 추가하여 비동기성으로 POST 요청이 있을때만 git-sync를 수행할수 있기 때문에 Continuous Deployment를 간단하게 구현하는데 활용될 수 있다.

GitHub SSH설정

git 내용을 pulling을 할때 https, ssh 방법을 사용하는데 GitHub ssh key를 kubernetes cluster의 secret으로 사용을 할수 있기 때문에 ssh 방식을 사용하는 방법을 작성하였다.

아래 모든 과정은 MacOS에서 진행하였고 다른 OS는 아래 링크에서 확인 가능하다.
https://help.github.com/en/articles/connecting-to-github-with-ssh

사용하고자 하는 터미널에서 등록키를 확인하자.

기존에 등록된 SSH key 확인

$ ls -al ~/.ssh

새로운 SSH key 생성

$ ssh-keygen -t rsa -b 4096 -C "ddiiwoong@gmail.com"
# Start the SSH key creation process
> Enter file in which the key is (/Users/you/.ssh/id_rsa): [Hit enter]
> Key has comment '/Users/you/.ssh/id_rsa'
> Enter new passphrase (empty for no passphrase): [Type new passphrase]
> Enter same passphrase again: [One more time for luck]
> Your identification has been saved with the new passphrase.

ssh agent 실행중인지 확인

eval “$(ssh-agent -s)”
> Agent pid 59566

생성된 키를 keychain에 저장 및 확인

$ ssh-add -K ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub

복사 및 github에 추가

$ pbcopy < ~/.ssh/id_rsa.pub

Setting - SSH and GPG keys - SSH keys - New SSH key
Title은 구분자로 입력하고 GitHub password를 한번더 입력하고 완료한다.

터미널에서 SSH접속 확인

$ ssh -T git@github.com
Hi ddiiwoong! You've successfully authenticated, but GitHub does not provide shell access.

git-sync를 위한 secret 등록

https://github.com/kubernetes/git-sync/blob/master/docs/ssh.md

secret 생성

위에서 생성한 SSH key를 Kubernetes Cluster에 Secret resource로 저장을 한다.

$ ssh-keyscan github.com > /tmp/known_hosts
# github.com:22 SSH-2.0-babeld-9d924d26
# github.com:22 SSH-2.0-babeld-9d924d26
# github.com:22 SSH-2.0-babeld-9d924d26

known_hosts와 key를 Secret으로 저장한다.

$ kubectl create secret generic git-creds \
    --from-file=ssh=$HOME/.ssh/id_rsa \
    --from-file=known_hosts=/tmp/known_hosts

$ kubectl get secret git-creds
NAME        TYPE      DATA      AGE
git-creds   Opaque    2         1d

sample ngnix 배포

기본적으로 git-sync/cmd/git-sync/main.go 소스를 확인하면 여러가지 flag를 확인할 수 있는데 주로 사용하는 옵션은 다음과 같다.

  • ssh : pulling 방식 (default=false)
  • root : git clone이 수행되는 root directory (default=”$HOME/git”)
  • repo : clone 대상 Repository (default=””)
  • branch : branch (default=master)
  • rev : git revision (tag or hash) to check out
  • depth : commit depth (default=0)
  • dest : repository 배포 directory

기타 옵션들은 git-sync/cmd/git-sync/main.go 에서 확인이 가능하며 해당 옵션들을 변수로 처리하여 활용하면 된다.

git-sync-demo.yaml 작성

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: git-sync-demo
  name: git-sync-demo
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: git-sync-demo
  template:
    metadata:
      labels:
        app: git-sync-demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.14-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: git-sync-volume
          mountPath: /usr/share/nginx
      - name: git-sync
        image: k8s.gcr.io/git-sync:v3.1.1
        imagePullPolicy: Always
        args:
         - "-ssh"
         - "-repo=git@github.com:ddiiwoong/git-sync-demo.git"
         - "-root=/usr/share/nginx"
         - "-dest=html"
         - "-branch=master"
         - "-depth=1"
        volumeMounts:
        - name: git-sync-volume
          mountPath: /usr/share/nginx
        - name: git-secret
          mountPath: /etc/git-secret
      volumes:
      - name: git-sync-volume
        emptyDir: {}
      - name: git-secret
        secret:
          secretName: git-creds
          defaultMode: 288 # = mode 0440
      securityContext:
        fsGroup: 65533 # to make SSH key readable
---
kind: Service
apiVersion: v1
metadata:
  name: git-sync-demo
spec:
  type: NodePort
  selector:
    app: git-sync-demo
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

확인사항

일단 ngnix로 1.14-alpine Image를 기본으로 하고 git-sync container가 sidecar로 들어가도록 작성하였다.
실제 동작하는 순서대로 manifest를 아래서부터 살펴보자.

  • git-sync-volume은 emptyDir, git-secret은 secret volume 설정
    ...
        volumes:
        - name: git-sync-volume
          emptyDir: {}
        - name: git-secret
          secret:
            secretName: git-creds
            defaultMode: 288 # = mode 0440
    ...
    
  • sidecar container image를 k8s.gcr.io/git-sync:v3.1.1로 설정
  • git-sync-volume, git-sync-volume volume을 git-sync sidecar에 마운트
  • 위에서 이야기한 git-sync flag, args로 설정
    ...
        containers:
        - name: git-sync
          image: k8s.gcr.io/git-sync:v3.1.1
          imagePullPolicy: Always
          args:
           - "-ssh"
           - "-repo=git@github.com:ddiiwoong/git-sync-demo.git"
           - "-root=/usr/share/nginx"
           - "-dest=html"
           - "-branch=master"
           - "-depth=1"
          volumeMounts:
          - name: git-sync-volume
            mountPath: /usr/share/nginx
          - name: git-secret
            mountPath: /etc/git-secret
    ...
    
  • nginx 기본 위치가 /usr/share/nginx 이므로 mount 위치를 git-sync-volume으로 설정
    ...
      spec:
        containers:
        - name: nginx
          image: nginx:1.14-alpine
          ports:
          - containerPort: 80
          volumeMounts:
          - name: git-sync-volume
            mountPath: /usr/share/nginx
    ...
    

위 nginx를 배포하고 접속하면 Hello git-sync demo v1.0를 확인할 수 있다.

결국 git repo code (static html page)는 /usr/share/nginx/html 위치에 clone 되는것처럼 보이지만 실제 clone 위치를 확인해보면 symbolic link로 특정 revision dir를 가리키고 있다.

$ kubectl exec -it git-sync-demo-665c9c9ddf-6nwc4 sh
Defaulting container name to nginx.
Use 'kubectl describe pod/git-sync-demo-665c9c9ddf-6nwc4 -n default' to see all of the containers in this pod.
/ # cd /usr/share/nginx/
/usr/share/nginx # ls -al
total 16
drwxrwsrwx    4 root     nogroup       4096 Mar 21 06:54 .
drwxr-xr-x    1 root     root          4096 Mar  8 03:09 ..
drwxr-sr-x    9 65533    nogroup       4096 Mar 21 06:54 .git
lrwxrwxrwx    1 65533    nogroup         44 Mar 21 06:54 html -> rev-07aa36f719091d75b5665203fa5846a549e7d540
drwxr-sr-x    2 65533    nogroup       4096 Mar 21 06:54 rev-07aa36f719091d75b5665203fa5846a549e7d540
/usr/share/nginx # cat ./html/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello git-sync demo</title>
  </head>
  <body>
    <h1>Hello git-sync demo v1.0</h1>
  </body>
</html>

github에 있는 위 index.html 내용을 수정하고 commit을 하게 되면 실시간으로 아래와 같이 revision 정보 및 내용이 바뀐것을 확인할수 있다.

/usr/share/nginx # ls -al
total 16
drwxrwsrwx    4 root     nogroup       4096 Mar 21 13:40 .
drwxr-xr-x    1 root     root          4096 Mar  8 03:09 ..
drwxr-sr-x    9 65533    nogroup       4096 Mar 21 13:40 .git
lrwxrwxrwx    1 65533    nogroup         44 Mar 21 13:40 html -> rev-b125908649135856d79c515c17decba68797a6cb
drwxr-sr-x    2 65533    nogroup       4096 Mar 21 13:40 rev-b125908649135856d79c515c17decba68797a6cb
/usr/share/nginx # cat ./html/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello git-sync demo</title>
  </head>
  <body>
    <h1>Hello git-sync demo v1.1</h1>
  </body>
</html>

정리

git-sync를 간단하게 테스트해봤다.
간단하게 sidecar 방식의 clone tool로서 git-sync를 활용하면 여러가지로 충분히 활용이 가능할 것이다.
포스팅을 작성하면서 떠오른 활용용도를 정리하면 아래와 같다. 어찌보면 sidecar pattern의 활용방안이라고도 볼수 있다.

  • CDN을 사용하지 않고 git에서 소규모로 컨텐츠를 가져올때
  • DBMS가 필요없을 정도의 적은 데이터를 가져올때
  • jekyll이나 hugo 같은 정적 사이트(블로그)의 sidecar 패턴 (GitPage처럼 markdown을 추가하고 git commit하면 바로 사이트에 반영되는 방식)
  • nginx, haproxy, apache와 같이 config 변경이 필요할때 webhook방식으로 설정을 변경한후 pod를 재기동하는 GitOps 구현

댓글남기기