반응형

1. Git-Sync란?

  • Git-Sync 는 Kubernetes 클러스터 내에서 git repository 를 동기화하는 sidecar 기능이다 (1)
  • airflow 와 같은 워크플로우 도구를 사용할 때, DAG 파일들을 git 에서 관리하고 있을 때 사용한다.
  • helm 을 통한 쿠버네티스 배포 시에만 지원하는 기능으로 보인다.

 

2. 왜 GitSync 기능을? 

  • 일반적으로 python 으로 작성한 airflow dag 파일은 airflow component(worker, scheduler) 에서 access 할 수 있는 파일 시스템에 저장되어야 한다.
  • git sync 기능을 사용하면, git repository 에 저장된 DAG 파일을 kubernetes pod 내부에 동기화 할 수 있다.
  • 반대로 git sync 를 사용하지 않는다면, DAG 파일을 kubernetes pod 에 복사하는 방식을 사용해야 한다.
    • s3 로 부터 주기적으로 sync 를 받는 sidecar 컨테이너를 개발
    • efs 와 같은 네트워크 파일 시스템을 사용 

 

3. Git-Sync 사용하기 

절차

  • git repository 를 생성한다.
  • 2가지 인증 방식 중 한 가지를 선택한다.
  • 선택한 인증방식의 credential 을 준비한다.
  • 인증 정보를 쿠버네티스 secret(시크릿) 으로 생성한다
  • helm chart 에서 git-sync 를 활성화 한다. (2)

 

인증 2가지 방식 소개 

  • SSH 프로토콜을 이용한 인증 방식 (Github 기준 )
  • HTTPS 프로토콜을 이용한 인증 방식

 

A.SSH  프로토콜을 이용한 인증 방식

SSH 키 생성

$ ssh-keygen -t rsa -b 4096 -C "jssvs@test.com"

# 복제할 키 문자열
$ cat ~/.ssh/id_rsa.pub

 

 

Git에 SSH 키 등록 

GIthub 키등록

 

쿠버네티스 시크릿 리소스 생성

kubectl create secret generic airflow-git-ssh-secret --from-file=gitSshKey=~/.ssh/id_rsa -네임스페이스

 

helm chart 값 작성

..... 생략
dags:
  gitSync:
    enabled: true
    repo: git@git repository url 
    branch: main
    rev: HEAD
    depth: 1
    maxFailures: 0
    subPath: ""

    sshKeySecret: airflow-git-ssh-secret
    
.... 생략

 

B.HTTPS 프로토콜을 이용한 인증 방식

PAT 생성 (Setting -> Developer settings -> Personal access tokens -> Generate new token)

Github PAT 생성

 

 

 

시크릿 yaml 작성하기
** 주의 : username 과 pat 는 base64 인코딩을 해서 저장해야 한다. 
** 또 주의: linux 에서 echo 를 이용할 경우 -n 옵션을 추가하여 뉴라인을 제거한다 

apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
data:
  GIT_SYNC_USERNAME: github username
  GIT_SYNC_PASSWORD: PAT 비밀번호
  GITSYNC_USERNAME: github username
  GITSYNC_PASSWORD: PAT 비밀번호

 

 

helm chart값 작성

.....
dags:
  gitSync:
    enabled: true
    repo: https://git repository url 
    branch: main
    rev: HEAD
    depth: 1
    maxFailures: 0
    subPath: ""

    credentialsSecret: git-credentials
 .....

 

helm 을 이용한 설치 후 git-syn-init 컨테이너에서 아래와 같은 로그가 찍혔다면 성공이다.

 

 

 

동작 스크린샷

Git Repository

 

 

Sample Dag
Airflow Dag 등록 화면

 

 

4. Reference

(1) https://airflow.apache.org/docs/helm-chart/stable/manage-dags-files.html#using-git-sync

 

Manage DAGs files — helm-chart Documentation

 

airflow.apache.org

(2) https://artifacthub.io/packages/helm/apache-airflow/airflow

 

airflow 1.15.0 · apache-airflow/apache-airflow

The official Helm chart to deploy Apache Airflow, a platform to programmatically author, schedule, and monitor workflows

artifacthub.io

 

 

반응형
반응형
오늘은 쿠버네티스의 스테이트풀셋 리소스를 이용해 오픈소스 ElasticSearch 를 배포해보겠습니다.

스테이트풀셋은 디플로이먼트와 성질이 비슷하지만, 파드에 고유한 이름이 부여되고 여러 개의 파드 사이에 순서를 지정해서 실행할 수 있습니다.

ElasticSearch 는 RestAPI 기반으로 json 도큐먼트 데이터를 분산 저장하여, 빠르게 조회할 수 있는 검색 엔진이죠.

빅데이터 엔지니어링 분야에서 kibana, Logstash 와 함께 ELK 로 많이 사용되는 소프트웨어 스택이기도 합니다.

아래 과정을 통해 손쉽게 쿠버네티스로 배포해보겠습니다.

 

 

1. 준비 과정

  • 데이터 영속성을 보장하기 위해 영구 볼륨 (PersistentVolume)생성
  • ElasticSearch 애플리케이션 배포를 위한 스테이트풀셋 생성
  • ElasticSearch 파드를 외부로 노출하기 위한 Service(쿠버네티스의 서비스) 생성
  • curlImage로 기본 파드를 띄우고 Elastic Search 의 서비스 확인

 

2. Statefulset 이용해 ElasticSearch 배포

 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sf-es
  namespace: work
spec:
  replicas: 2
  serviceName: "my-es"
  selector:
    matchLabels:
      app: sf-es
  volumeClaimTemplates:
  - metadata:
      name: vol-es-data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: gp3
      resources:
        requests:
          storage: 1Gi
  template:
    metadata:
      labels:
        app: sf-es
    spec:
      containers:
      - name: sf-es
        image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
        env:
        - name: discovery.type
          value: "single-node" # Elasticsearch 노드 타입 설정
        - name: cluster.name
          value: my-es # Elasticsearch 클러스터 이름 설정
        - name: network.host
          value: 0.0.0.0 # 모든 네트워크 인터페이스에서 수신하도록 설정
        ports:
        - containerPort: 9200
          name: es1 # HTTP 포트
        - containerPort: 9300
          name: es2 # Transport 포트
        volumeMounts:
        - name: vol-es-data
          mountPath: /usr/share/elasticsearch/data
        livenessProbe:
          httpGet:
            path: /
            port: 9200
          initialDelaySeconds: 60 # 초기 지연 시간
          periodSeconds: 10 # 주기 시간
          timeoutSeconds: 5 # 타임아웃 시간
          failureThreshold: 3 # 실패 허용 임계값
      initContainers:
      - name: init-container
        image: busybox:latest
        command: ["sh","-c","chown -R 1000:1000 /usr/share/elasticsearch/data"]
        securityContext:
          privileged: true # 루트 권한으로 실행
        volumeMounts:
        - name: vol-es-data
          mountPath: /usr/share/elasticsearch/data # 데이터 볼륨 마운트 경로
---
apiVersion: v1
kind: Service
metadata:
  name: svc-es
  namespace: work
spec:
  clusterIP: None
  ports:
  - port: 9200
    name: es1
  - port: 9300
    name: es2
  selector:
    app: sf-es

 

몇가지 설정에 대한 설명을 추가해보겠습니다.

디플로이먼트와 다르게 VolumeClaimTemplate 속성을 주면서 동적 프로비저닝을 할 수 있구요.

9200,9300 port는 엘라스틱서치가 사용되는 named port 입니다.

livenessProbe 속성값으로 실행된 컨테이너의 서비스 healthcheck 를 파드 차원에서 할 수 있습니다.

서비스 리소스를 생성하면 서비스 이름의 DNS 로 다른 파드에서 접근할 수 있습니다.

 

아래처럼 statefulset 을 배포하구요.

 

kubectl 또는 k9s 로 배포 상태를 확인해줍니다.

앞서 설명한 것 처럼 pod 의 이름에 임의의 문자열로 되어있지 않고, 이름과 인덱스로 고유한 이름을 갖고 있습니다.

 

 

3. 서비스 확인

별도의 파드를 띄워서 조금 전에 띄운 ElasticSearch 파드가 정상적으로 운영되는지, 접근이 되는지 확인해보겠습니다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-conn-test
  namespace: work
spec:
  containers:
  - name: es-conn
    image: curlimages/curl
    command: ["sleep","3600"]

 

ElasticSearch는 RestAPI 기반으로 데이터를 핸들링할 수 있기 때문에, 리눅스 curl 이미지를 이용해 아래와 같이 테스트 파드를 띄웠습니다.

 

 

해당 파드의 컨테이너에 쉘에 진입해서 서비스 정보를 출력해봤습니다.

 

여기서 중요한 것은 ElasticSearch 의 DNS 입니다.

 

제가 만든 서비스의 이름으로 접근이 되는 것을 볼 수 있습니다.

 

 

미리 생성했던 인덱스도 조회해봤습니다.

 

추가적인 API 는 https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html 에서 확인하실 수 있습니다.

 

 

4. 마치며

과거 프로젝트 진행으로 ElasticSearch를  여러 서버에 멀티클러스터링으로 직접 설치해본 경험도 있고, Docker 를 이용해 구축해본 경험도 있습니다.  쿠버네티스를 알게되고 나서 구축의 편의성을 크게 느낍니다..

느낌적으로 앞으로는 데이터엔지니어링의 서비스 배포 및 관리도 쿠버네티스로 많이 넘어갈 것 같아요.

 

 

오늘은 여기까지 쓰겠습니다.

 

끝 

 

 

반응형
반응형

쿠버네티스 데이터 엔지니어링을 시작한지 1년 정도가 지난 것 같습니다.

지금까지 학습하며 경험한 내용을 바탕으로 지식을 정리하면서 관련 포스팅을 시작하려고 합니다.

 

이론적인 내용도 다루겠지만, 시간이 되면 실제 운용 사례 기반으로 내용을 작성하려고 합니다.

이번 MySQL 배포도, 실제 서비스의 메타 데이터로 활용해봤는데 큰 문제가 없었습니다.

 

관리형 DB(예를 들어 AWS RDS 등) 를 사용하시는 분들께서 비용절감의 고민이 있으시다면, 게다가 쿠버네티스 환경이 준비된 분들이라면 스테이트풀셋을 이용한 MySQL 파드를 배포해서 사용하시는 것을 추천드립니다. 

 

스테이트풀셋을 이용해 MySQL 을 배포하는 방법도 가능합니다만 이번 글에서는 디플로이먼트를 이용해보겠습니다.

 

1. 준비 과정 

  • 데이터 영속성을 보장하기 위해 영구 볼륨 (PersistentVolume)생성
  • MySQL 애플리케이션 배포를 위한 디플로이먼트 생성
  • MySQL 파드를 외부로 노출하기 위한 Service(쿠버네티스의 서비스) 생성

** 아시는 것 처럼 쿠버네티스의 모든 리소스는 yaml 파일로 작성할겁니다.

 

2. 디플로이먼트를 이용해 MySQL 배포  

a. 데이터 영속성을 보장하기 위해 영구 볼륨 (PersistentVolume)생성

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-study-mysql
  namespace: work
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: gp3
  resources:
    requests:
      storage: 1Gi

** pvc 를 동적 볼륨 프로비저닝 하기 위해서는 스토리지클래스 에 provisioner 를 명시해줘야 합니다. 저는 미리 만들어둔 스토리지 클래스를 사용했고, 이 내용은 다음에 자세히 다루겠습니다.

 

b. MySQL 애플리케이션 배포를 위한 디플로이먼트 생성

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: study-mysql
  namespace: work
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
      - name: study-volume
        persistentVolumeClaim:
          claimName: pvc-study-mysql
      containers:
        - name: study-mysql
          image: mysql:latest
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: root
          - name: MYSQL_DATABASE
            value: test
          ports:
          - containerPort: 3306
          volumeMounts:
          - name: study-volume
            mountPath: /var/lib/mysql

 

 

c. MySQL 파드를 외부로 노출하기 위한 Service(쿠버네티스의 서비스) 생성

apiVersion: v1
kind: Service
metadata:
  name: svc-study-mysql
  namespace: work
spec:
  selector:
    app: mysql
  ports:
  - port: 3306

 

d. 서비스 노출 확인을 위한 파드 생성과 통신 테스트

apiVersion: v1
kind: Pod
metadata:
  name: mysql-client
  namespace: work
  labels:
    app: mysql-client
spec:
  containers:
  - name: mysql-client
    image: mysql:latest
    command: [ "sleep", "infinity" ] # 파드가 무기한으로 동작하도록 설정

 

 

** 위 3개의 리소스 yaml 파일을 kubectl 을 이용해 배포해줍니다.

 

3. 서비스 확인

a.파드의 상태 확인 

 

 

b.통신테스트를 위해 띄운 파드에 쉘에 진입해 서비스 노출 확인

 

 

c.mysql 파드에 쉘에 진입해 데이터베이스 확인

 

 

4. 마치며

configmap 을 이용해서 database 의 설정을 동적으로 적용하며 운영을 할 수 있습니다.

stastefulset 으로 배포하면 운영의 안정성을 높일 수 있습니다. ( 파드의 고유성이 부여되고 영구적인 호스트 이름이 부여됩니다.) 

다음에는  statefulset 을 이용해 엘라스틱 서치를 배포해보겠습니다.

반응형

+ Recent posts