git repo를 kubernetes volume으로 구현할수 있는 sidecar pattern git-sync
프로젝트에 대해서 알아본다.
git-sync
Kubernetes Github에 방문하면 다양한 프로젝트들을 볼 수 있다.
Kubernetes Project부터 minikube, kubeadm, kubectl, kubelet, dashboard등 필수적으로 필요하거나 많이 사용되는 프로젝트를 볼 수 있는데,
기존에 storage volume 으로 활용되던 gitrepo가 deprecated
되어서 방법을 찾다가 유사한 프로젝트를 공식 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 구현