Observability/Prometheus

EP10 [Part 4: Grafana 대시보드 마스터하기] Grafana 설치 및 기본 설정

ygtoken 2025. 3. 24. 09:52
728x90

이번 글에서는 쿠버네티스 모니터링 시리즈의 새로운 파트인 "Grafana 대시보드 마스터하기"를 시작합니다. 지금까지 Prometheus를 통해 다양한 메트릭을 수집하는 방법에 중점을 두었다면, 이제는 이 데이터를 효과적으로 시각화하고 분석하기 위한 Grafana 환경을 구축하는 방법을 살펴볼 차례입니다. Grafana의 설치 방법부터 데이터 소스 연결, 사용자 관리, 보안 설정까지 기본 환경 구성에 필요한 모든 요소를 단계별로 자세히 알아보겠습니다. 이를 통해 쿠버네티스 클러스터를 위한 강력하고 안정적인 모니터링 시스템의 기반을 마련할 수 있습니다.


📌 Grafana 소개 및 아키텍처 이해

Grafana는 시계열 데이터 시각화 및 모니터링을 위한 오픈소스 플랫폼입니다. 다양한 데이터 소스와 연동하여 강력한 대시보드를 구성할 수 있습니다.

✅ Grafana의 주요 특징

Grafana가 쿠버네티스 모니터링에 특히 적합한 이유를 살펴보겠습니다:

  • 다양한 데이터 소스 지원: Prometheus, Elasticsearch, InfluxDB, MySQL 등 다양한 데이터 소스 연결 가능
  • 강력한 시각화 도구: 그래프, 히트맵, 테이블, 게이지 등 다양한 패널 타입 제공
  • 알림 시스템: 임계값 기반 알림 설정 및 다양한 알림 채널 지원
  • 대시보드 공유 및 임포트: 커뮤니티에서 공유된 대시보드 활용 가능
  • 사용자 관리 및 권한 제어: 세분화된 접근 제어 기능

✅ Grafana 아키텍처

Grafana의 기본 아키텍처를 이해하는 것은 효과적인 설치와 구성에 도움이 됩니다:

 

Grafana 아키텍쳐

주요 컴포넌트:

  • 프론트엔드: React 기반 UI
  • 백엔드 서버: Go로 작성된 API 서버
  • 데이터베이스: 대시보드, 사용자, 설정 저장(SQLite, MySQL, PostgreSQL)
  • 플러그인 시스템: 데이터 소스, 패널, 앱 플러그인

📌 Grafana 설치 방법

쿠버네티스 환경에 Grafana를 설치하는 다양한 방법을 살펴보겠습니다.

✅ Helm을 사용한 설치

Helm은 쿠버네티스 환경에서 Grafana를 설치하는 가장 일반적인 방법입니다:

# Grafana 네임스페이스 생성
kubectl create namespace grafana
# 'grafana'라는 네임스페이스를 생성합니다
# 네임스페이스는 쿠버네티스에서 리소스를 논리적으로 분리하는 방법입니다
# 모니터링 시스템을 별도 네임스페이스에 두면 관리가 용이합니다

# Grafana Helm 레포지토리 추가
helm repo add grafana https://grafana.github.io/helm-charts
# Grafana 공식 Helm 차트 레포지토리를 추가합니다
# 이를 통해 최신 Grafana 차트를 사용할 수 있습니다

# 레포지토리 업데이트
helm repo update
# 추가한 레포지토리의 최신 차트 정보를 업데이트합니다

# Grafana 설치
helm install grafana grafana/grafana -n grafana
# 'grafana'라는 이름으로 Grafana를 설치합니다
# -n grafana: grafana 네임스페이스에 설치합니다
# 이 명령어는 기본 설정으로 Grafana를 설치합니다

커스텀 설정을 적용하려면 values.yaml 파일을 사용할 수 있습니다:

# Grafana Helm 차트 커스텀 values.yaml
replicas: 2  
# 고가용성을 위해 2개의 복제본을 설정합니다
# 단일 장애점을 방지하기 위해 최소 2개 권장합니다

persistence:
  type: pvc
  # 영구 볼륨 클레임을 사용하여 데이터 저장
  enabled: true
  # 영구 스토리지 활성화 - Grafana 재시작 시에도 데이터 유지
  storageClassName: standard
  # 스토리지 클래스 지정 - 클러스터 환경에 맞게 조정 필요
  accessModes:
    - ReadWriteOnce
    # 하나의 노드에서만 읽기/쓰기 가능한 볼륨
  size: 10Gi
  # 10GB 스토리지 용량 - 대시보드와 사용자 데이터에 충분한 용량

adminPassword: admin  
# 관리자 비밀번호 설정
# 실제 프로덕션 환경에서는 강력한 비밀번호로 변경 필요
# 더 안전한 방법은 Secret을 사용하는 것입니다

# Prometheus 데이터 소스 자동 구성
datasources:
  datasources.yaml:
    apiVersion: 1
    # Grafana 데이터 소스 API 버전
    datasources:
    - name: Prometheus
      # 데이터 소스 이름 - 대시보드에서 이 이름으로 참조
      type: prometheus
      # 데이터 소스 유형 - Prometheus 지정
      url: http://prometheus-server.monitoring.svc.cluster.local
      # Prometheus 서버 URL - 쿠버네티스 서비스 이름으로 접근
      # 형식: http://[서비스명].[네임스페이스].svc.cluster.local
      access: proxy
      # 접근 모드: proxy는 Grafana 서버를 통해 접근
      isDefault: true
      # 기본 데이터 소스로 설정 - 새 패널 생성 시 기본 선택됨

# 대시보드 프로바이더 설정
dashboardProviders:
  dashboardproviders.yaml:
    apiVersion: 1
    # Grafana 대시보드 프로바이더 API 버전
    providers:
    - name: 'default'
      # 프로바이더 이름
      orgId: 1
      # 조직 ID - 기본 조직은 1
      folder: ''
      # 대시보드 폴더 - 빈 문자열은 루트 폴더
      type: file
      # 프로바이더 유형 - 파일 기반 프로바이더
      disableDeletion: false
      # 대시보드 삭제 비활성화 여부 - false는 삭제 허용
      editable: true
      # 대시보드 편집 가능 여부 - true는 UI에서 편집 가능
      options:
        path: /var/lib/grafana/dashboards/default
        # 대시보드 JSON 파일 경로

# 기본 대시보드 설정
dashboards:
  default:
    kubernetes-cluster:
      gnetId: 7249  
      # Grafana.com에서 제공하는 대시보드 ID
      # 이 ID는 쿠버네티스 클러스터 대시보드를 가리킴
      revision: 1
      # 대시보드 수정 버전
      datasource: Prometheus
      # 이 대시보드에서 사용할 데이터 소스 이름

Helm 차트로 커스텀 설정 적용:

# 커스텀 values.yaml 파일을 사용하여 Grafana 설치
helm install grafana grafana/grafana -f values.yaml -n grafana
# -f values.yaml: 앞서 작성한 커스텀 설정 파일을 지정합니다
# 이 명령어는 values.yaml의 설정을 적용하여 Grafana를 설치합니다
# 커스텀 설정은 기본값을 오버라이드합니다

✅ Grafana Operator를 사용한 설치

Grafana Operator는 쿠버네티스 환경에서 Grafana를 선언적으로 관리할 수 있게 해줍니다:

# Grafana Operator 네임스페이스 생성
kubectl create namespace grafana-operator
# Operator를 위한 별도 네임스페이스를 생성합니다
# Operator는 일반적으로 자체 네임스페이스에서 실행됩니다

# Grafana Operator 설치
helm repo add grafana-operator https://grafana-operator.github.io/grafana-operator/
# Grafana Operator Helm 차트 레포지토리를 추가합니다
# Operator는 쿠버네티스 컨트롤러로 Grafana 인스턴스를 관리합니다

helm repo update
# 레포지토리 정보를 최신 상태로 업데이트합니다

# Operator 설치
helm install grafana-operator grafana-operator/grafana-operator -n grafana-operator
# 'grafana-operator'라는 이름으로 Operator를 설치합니다
# -n grafana-operator: grafana-operator 네임스페이스에 설치합니다
# Operator가 설치되면 Grafana CR을 사용하여 Grafana 인스턴스를 관리할 수 있습니다

Grafana 인스턴스 생성을 위한 CR(Custom Resource) 정의:

# grafana-instance.yaml
apiVersion: grafana.integreatly.org/v1beta1
# Grafana Operator API 버전
kind: Grafana
# 커스텀 리소스 종류 - Grafana 인스턴스 정의
metadata:
  name: grafana
  # Grafana 인스턴스 이름
  namespace: grafana-operator
  # 인스턴스가 생성될 네임스페이스
spec:
  deployment:
    replicas: 1
    # 배포할 Grafana 복제본 수
    # 프로덕션 환경에서는 고가용성을 위해 2 이상 권장
  ingress:
    enabled: true
    # 인그레스 활성화 - 외부에서 Grafana 접근 가능
    hostname: grafana.example.com
    # 호스트 이름 - 실제 도메인으로 변경 필요
    path: "/"
    # 인그레스 경로 - 루트 경로
  config:
    log:
      level: info
      # 로그 레벨 설정 - info, debug, warn, error 등
    auth:
      disable_login_form: false
      # 로그인 폼 비활성화 여부 - false는 로그인 폼 표시
    security:
      admin_user: admin
      # 관리자 사용자 이름
      admin_password: admin
      # 관리자 비밀번호 - 프로덕션에서는 변경 필요
  persistence:
    enabled: true
    # 영구 스토리지 활성화
    storageClassName: standard
    # 스토리지 클래스 이름
    accessModes:
      - ReadWriteOnce
      # 접근 모드 - 하나의 노드에서만 읽기/쓰기
    size: 10Gi
    # 스토리지 크기 - 10GB

그리고 데이터 소스 생성을 위한 CR:

# prometheus-datasource.yaml
apiVersion: grafana.integreatly.org/v1beta1
# Grafana Operator API 버전
kind: GrafanaDataSource
# 커스텀 리소스 종류 - Grafana 데이터 소스 정의
metadata:
  name: prometheus-datasource
  # 데이터 소스 이름
  namespace: grafana-operator
  # 데이터 소스가 생성될 네임스페이스
spec:
  instanceSelector:
    matchLabels:
      dashboards: "grafana"
    # 이 데이터 소스를 연결할 Grafana 인스턴스 선택
    # 레이블을 통해 인스턴스 선택
  datasources:
    - name: Prometheus
      # Grafana UI에 표시될 데이터 소스 이름
      type: prometheus
      # 데이터 소스 유형 - prometheus
      url: http://prometheus-server.monitoring.svc.cluster.local
      # Prometheus 서버 URL
      # 쿠버네티스 서비스 이름을 통해 접근
      isDefault: true
      # 기본 데이터 소스로 설정
      version: 1
      # 데이터 소스 API 버전
      editable: true
      # UI에서 편집 가능 여부
      jsonData:
        timeInterval: "5s"
        # 시계열 데이터 간격 - 5초
        # Prometheus 스크래핑 간격과 일치시키는 것이 좋음
        tlsSkipVerify: true
        # TLS 인증서 검증 건너뛰기
        # 자체 서명 인증서 사용 시 유용

CR 적용:

# Grafana 인스턴스 및 데이터 소스 생성
kubectl apply -f grafana-instance.yaml
# Grafana 인스턴스 CR을 적용합니다
# Grafana Operator가 이 CR을 감지하고 실제 Grafana 배포를 생성합니다

kubectl apply -f prometheus-datasource.yaml
# 데이터 소스 CR을 적용합니다
# Grafana Operator가 이 CR을 감지하고 Grafana 인스턴스에 데이터 소스를 추가합니다

✅ kube-prometheus-stack을 통한 설치

이전 글에서 다룬 kube-prometheus-stack은 Prometheus와 Grafana를 함께 설치합니다:

# kube-prometheus-stack을 통한 설치 (참고)
# Prometheus 설치 시 함께 설치한 경우 별도 설치 불필요
# helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring
# 이 방법은 이전 글에서 다루었으므로 참고용으로만 제시합니다.

✅ 설치 확인

설치가 완료되었다면 다음 명령어로 상태를 확인합니다:

# 파드 상태 확인
kubectl get pods -n grafana
# grafana 네임스페이스의 모든 파드 목록을 조회합니다
# 모든 파드가 Running 상태인지 확인합니다
# READY 열이 모두 n/n 형태로 표시되어야 합니다
# RESTARTS 열의 값이 낮아야 합니다 (여러 번 재시작은 문제 의심)

# 서비스 확인
kubectl get svc -n grafana
# grafana 네임스페이스의 모든 서비스를 조회합니다
# 서비스 타입(ClusterIP/LoadBalancer/NodePort)과 포트를 확인합니다
# EXTERNAL-IP 열을 통해 외부 액세스 가능 여부를 확인합니다

# 인그레스 확인 (설정한 경우)
kubectl get ingress -n grafana
# grafana 네임스페이스의 모든 인그레스를 조회합니다
# 인그레스 호스트 및 경로를 확인합니다
# HOSTS 열에 설정한 도메인을 확인합니다

관리자 비밀번호 확인 (기본 설치 시):

# 관리자 비밀번호 확인
kubectl get secret --namespace grafana grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
# grafana 네임스페이스의 grafana 시크릿에서 admin-password 키의 값을 추출합니다
# base64로 인코딩된 비밀번호를 디코딩하여 출력합니다
# 기본 관리자 계정은 'admin'입니다
# 보안을 위해 출력된 비밀번호는 나중에 변경하는 것이 좋습니다

외부 접속 설정 (로컬 테스트용):

# 포트 포워딩 (로컬 테스트용)
kubectl port-forward svc/grafana 3000:80 -n grafana
# 로컬 머신의 3000 포트를 grafana 서비스의 80 포트로 포워딩합니다
# 브라우저에서 http://localhost:3000 으로 접속 가능합니다
# 이 방법은 개발/테스트 환경에서만 사용하는 것이 좋습니다
# 프로덕션 환경에서는 인그레스나 로드밸런서를 사용해야 합니다

📌 Grafana 기본 설정

Grafana 설치 후 기본적인 설정을 구성해 보겠습니다.

✅ 데이터 소스 설정

Prometheus를 Grafana의 데이터 소스로 연결하는 방법:

  1. Grafana UI에서 데이터 소스 추가:
    • 좌측 메뉴에서 Configuration(설정) > Data Sources(데이터 소스) 선택
    • "Add data source" 버튼 클릭
    • Prometheus 선택
  2. Prometheus 연결 정보 입력:

데이터 소스를 코드로 정의하는 방법:

# datasource.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: ConfigMap
# 리소스 타입 - ConfigMap으로 설정
metadata:
  name: grafana-datasources
  # ConfigMap 이름
  namespace: grafana
  # 네임스페이스 지정
data:
  prometheus.yaml: |-
    # 데이터 소스 설정 파일 내용
    apiVersion: 1
    # Grafana 데이터 소스 API 버전
    datasources:
    - name: Prometheus
      # 데이터 소스 이름 - 대시보드에서 이 이름으로 참조
      type: prometheus
      # 데이터 소스 유형 - prometheus 지정
      url: http://prometheus-server.monitoring.svc.cluster.local
      # Prometheus 서버 URL
      # 쿠버네티스 서비스 이름을 사용하여 접근
      access: proxy
      # 접근 모드: proxy는 Grafana 서버를 통해 접근
      # direct는 브라우저에서 직접 접근 (CORS 고려 필요)
      isDefault: true
      # 기본 데이터 소스로 설정
      jsonData:
        timeInterval: "5s"
        # 시계열 데이터 간격 - 5초
        # Prometheus 스크래핑 간격과 일치시키는 것이 좋음
        tlsSkipVerify: true
        # TLS 인증서 검증 건너뛰기
        httpMethod: "POST"
        # HTTP 메서드 설정 - 큰 쿼리에는 POST 권장
      version: 1
      # 데이터 소스 버전
      editable: true
      # UI에서 편집 가능 여부

ConfigMap 적용 및 Grafana에 마운트:

# ConfigMap 생성
kubectl apply -f datasource.yaml
# 앞서 정의한 ConfigMap을 적용하여 데이터 소스 설정을 생성합니다
# 이 ConfigMap은 Grafana 파드에 마운트되어야 합니다

# Grafana 배포에 ConfigMap 마운트 (values.yaml에 추가)
# sidecar.datasources.enabled: true
# sidecar.datasources.label: grafana_datasource
# 재배포 시 이 설정으로 자동으로 데이터 소스를 로드할 수 있습니다
# 이 설정은 Grafana Helm 차트의 values.yaml에 추가해야 합니다

✅ 사용자 관리 및 권한 설정

Grafana의 사용자 및 권한 관리 방법:

  1. 기본 인증 설정 (grafana.ini):
# grafana.ini 설정 (ConfigMap으로 구성)
[auth]
# 인증 관련 설정
disable_login_form = false
# 로그인 폼 비활성화 여부
# false: 로그인 폼 표시, true: 로그인 폼 숨김
# OAuth 또는 프록시 인증만 사용할 경우 true로 설정 가능

# OAuth, LDAP 등 외부 인증 설정
# enable_google_oauth = true
# oauth_auto_login = false

[auth.anonymous]
# 익명 액세스 설정
enabled = false
# 익명 액세스 허용 여부
# true: 로그인 없이 접근 가능, false: 로그인 필요
# org_name = Main Org.
# org_role = Viewer
# 익명 사용자에게 부여할 기본 조직 및 역할

[users]
# 사용자 관련 설정
allow_sign_up = false
# 새 사용자 자동 생성 여부
# true: 외부 인증 시 사용자 자동 생성, false: 수동 생성만 허용
auto_assign_org_role = Viewer
# 새 사용자 기본 역할
# 가능한 역할: Viewer, Editor, Admin

[security]
# 보안 관련 설정
admin_user = admin
# 관리자 계정 사용자 이름
admin_email = admin@example.com
# 관리자 이메일 주소
# 보안 주의: 실제 환경에서는 Secret으로 관리해야 함
# admin_password = StrongPassword123
# 관리자 비밀번호 - 실제 프로덕션에서는 Secret으로 관리
  1. LDAP 통합 설정 (ldap.toml):
# LDAP 통합 설정 예시
[[servers]]
# LDAP 서버 설정
host = "ldap.example.com"
# LDAP 서버 호스트 이름 또는 IP
port = 389
# LDAP 서버 포트 (389: 기본, 636: SSL)
use_ssl = false
# SSL 사용 여부
start_tls = true
# StartTLS 사용 여부 (일반 연결을 TLS로 업그레이드)
bind_dn = "cn=admin,dc=example,dc=com"
# 바인딩에 사용할 DN (LDAP 서버 접근 계정)
bind_password = "admin_password"
# 바인딩 계정 비밀번호
search_filter = "(uid=%s)"
# 사용자 검색 필터 (%s는 로그인 시 입력한 사용자 이름으로 대체)
search_base_dns = ["ou=users,dc=example,dc=com"]
# 사용자 검색 기준 DN

[servers.attributes]
# LDAP 속성과 Grafana 필드 매핑
name = "givenName"
# Grafana 사용자 이름에 매핑할 LDAP 속성
surname = "sn"
# Grafana 성에 매핑할 LDAP 속성
username = "uid"
# Grafana 로그인 이름에 매핑할 LDAP 속성
member_of = "memberOf"
# 그룹 멤버십 확인을 위한 LDAP 속성
email = "mail"
# Grafana 이메일에 매핑할 LDAP 속성

[[servers.group_mappings]]
# LDAP 그룹과 Grafana 역할 매핑
group_dn = "cn=admins,ou=groups,dc=example,dc=com"
# LDAP 관리자 그룹 DN
org_role = "Admin"
# 매핑할 Grafana 역할 (Admin)

[[servers.group_mappings]]
# 편집자 그룹 매핑
group_dn = "cn=editors,ou=groups,dc=example,dc=com"
# LDAP 편집자 그룹 DN
org_role = "Editor"
# 매핑할 Grafana 역할 (Editor)

[[servers.group_mappings]]
# 기타 모든 사용자에 대한 기본 매핑
group_dn = "*"
# 모든 그룹 매칭 와일드카드
org_role = "Viewer"
# 매핑할 Grafana 역할 (Viewer)
  1. 쿠버네티스에서 Secret으로 LDAP 설정 관리:
# ldap-config.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: Secret
# 리소스 타입 - Secret으로 설정 (민감 정보 포함)
metadata:
  name: grafana-ldap-config
  # Secret 이름
  namespace: grafana
  # 네임스페이스 지정
stringData:
  # 인코딩하지 않은 문자열 데이터 (쿠버네티스가 자동으로 base64 인코딩)
  ldap.toml: |-
    # LDAP 설정 파일 내용
    [[servers]]
    host = "ldap.example.com"
    # LDAP 서버 호스트
    port = 389
    # LDAP 서버 포트
    use_ssl = false
    # SSL 사용 여부
    start_tls = true
    # StartTLS 사용 여부
    bind_dn = "cn=admin,dc=example,dc=com"
    # 바인딩 DN
    bind_password = "admin_password"
    # 바인딩 비밀번호 - Secret에 저장하므로 직접 기입 가능
# ldap-config.yaml (계속)
   search_filter = "(uid=%s)"
   # 사용자 검색 필터 - %s는 사용자 입력으로 대체됨
   search_base_dns = ["ou=users,dc=example,dc=com"]
   # 사용자 검색 기준 DN - LDAP 디렉토리 구조에 맞게 조정 필요
   
   [servers.attributes]
   # Grafana 사용자 속성과 LDAP 속성 매핑
   name = "givenName"
   # 사용자 이름에 사용할 LDAP 속성
   surname = "sn"
   # 사용자 성에 사용할 LDAP 속성
   username = "uid"
   # 로그인 ID에 사용할 LDAP 속성
   member_of = "memberOf"
   # 그룹 멤버십 확인에 사용할 LDAP 속성
   email = "mail"
   # 이메일에 사용할 LDAP 속성
   
   [[servers.group_mappings]]
   # LDAP 그룹과 Grafana 역할 매핑 (관리자)
   group_dn = "cn=admins,ou=groups,dc=example,dc=com"
   # 관리자 그룹 DN - 조직 LDAP 구조에 맞게 조정
   org_role = "Admin"
   # 이 그룹 멤버에게 부여할 Grafana 역할 (Admin)
   
   [[servers.group_mappings]]
   # LDAP 그룹과 Grafana 역할 매핑 (편집자)
   group_dn = "cn=editors,ou=groups,dc=example,dc=com"
   # 편집자 그룹 DN
   org_role = "Editor"
   # 이 그룹 멤버에게 부여할 Grafana 역할 (Editor)
   
   [[servers.group_mappings]]
   # 기본 매핑 - 다른 모든 사용자
   group_dn = "*"
   # 와일드카드 - 다른 모든 그룹 매칭
   org_role = "Viewer"
   # 기본 부여 역할 (Viewer)

 

LDAP 설정 적용:

# Secret 생성
kubectl apply -f ldap-config.yaml
# LDAP 설정이 포함된 Secret을 생성합니다
# 민감한 LDAP 바인딩 정보는 Secret으로 보호됩니다

# Grafana 배포에 Secret 마운트 (values.yaml에 추가)
# extraSecretMounts:
# - name: ldap
#   secretName: grafana-ldap-config
#   defaultMode: 0440
#   mountPath: /etc/grafana/ldap.toml
#   subPath: ldap.toml
# env:
#   - name: GF_AUTH_LDAP_ENABLED
#     value: "true"
#   - name: GF_AUTH_LDAP_CONFIG_FILE
#     value: "/etc/grafana/ldap.toml"
# 이 설정을 Helm 차트 values.yaml에 추가하고 업데이트하면 LDAP 인증이 적용됩니다
# Secret이 /etc/grafana/ldap.toml 경로에 마운트되고 환경 변수로 활성화됩니다

✅ 대시보드 프로비저닝 설정

미리 정의된 대시보드를 자동으로 불러오는 방법:

  1. 대시보드 프로비저닝 설정:
# dashboard-provider.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: ConfigMap
# 리소스 타입 - ConfigMap으로 설정
metadata:
  name: grafana-dashboard-provider
  # ConfigMap 이름
  namespace: grafana
  # 네임스페이스 지정
data:
  provider.yaml: |-
    # 대시보드 프로바이더 설정 파일 내용
    apiVersion: 1
    # Grafana 대시보드 프로바이더 API 버전
    providers:
    - name: 'default'
      # 프로바이더 이름 - UI에 표시됨
      orgId: 1
      # 조직 ID - 기본 조직은 1
      folder: ''
      # 대시보드 폴더 - 빈 문자열은 루트 폴더
      type: file
      # 프로바이더 유형 - 파일 시스템 기반
      disableDeletion: false
      # 대시보드 삭제 비활성화 여부 - false는 삭제 허용
      updateIntervalSeconds: 30
      # 파일 시스템 확인 간격 (초) - 30초마다 변경 확인
      allowUiUpdates: true
      # UI에서 업데이트 허용 여부 - true는 UI에서 편집 가능
      options:
        path: /var/lib/grafana/dashboards
        # 대시보드 JSON 파일이 저장된 경로
  1. 샘플 대시보드 ConfigMap:
# kubernetes-dashboard.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: ConfigMap
# 리소스 타입 - ConfigMap으로 설정
metadata:
  name: kubernetes-dashboard
  # ConfigMap 이름
  namespace: grafana
  # 네임스페이스 지정
  labels:
    grafana_dashboard: "1"  
    # 대시보드 자동 로드를 위한 레이블
    # 사이드카 컨테이너가 이 레이블을 가진 ConfigMap을 찾아 로드함
data:
  kubernetes-dashboard.json: |-
    {
      "annotations": {
        "list": [
          {
            "builtIn": 1,
            "datasource": "-- Grafana --",
            "enable": true,
            "hide": true,
            "iconColor": "rgba(0, 211, 255, 1)",
            "name": "Annotations & Alerts",
            "target": {
              "limit": 100,
              "matchAny": false,
              "tags": [],
              "type": "dashboard"
            },
            "type": "dashboard"
          }
        ]
      },
      "editable": true,
      # 대시보드 편집 가능 여부
      "fiscalYearStartMonth": 0,
      "graphTooltip": 0,
      # 그래프 툴팁 모드 (0: 기본, 1: 공유, 2: 공유+크로스헤어)
      "id": 9,
      "links": [],
      "liveNow": false,
      "panels": [
        // ... 대시보드 패널 정의 (실제로는 매우 긺)
      ],
      "schemaVersion": 34,
      # 대시보드 스키마 버전
      "style": "dark",
      # 대시보드 스타일 (dark 또는 light)
      "tags": ["kubernetes"],
      # 대시보드 태그 - 검색과 필터링에 사용
      "templating": {
        "list": []
      },
      "time": {
        "from": "now-6h",
        "to": "now"
      },
      # 기본 시간 범위 설정 (현재부터 6시간 전까지)
      "timepicker": {},
      "timezone": "",
      # 시간대 설정 (빈 문자열은 브라우저 시간대 사용)
      "title": "Kubernetes Cluster Dashboard",
      # 대시보드 제목
      "uid": "kubernetes-cluster",
      # 대시보드 고유 ID - URL에 사용됨
      "version": 1,
      # 대시보드 버전
      "weekStart": ""
      # 주 시작일 설정
    }

대시보드 프로비저닝 적용:

# ConfigMap 생성
kubectl apply -f dashboard-provider.yaml
# 대시보드 프로바이더 ConfigMap을 적용합니다
# 이 ConfigMap은 대시보드 프로바이더 설정을 정의합니다

kubectl apply -f kubernetes-dashboard.yaml
# 대시보드 ConfigMap을 적용합니다
# 이 ConfigMap은 실제 대시보드 JSON을 포함합니다

# Grafana 배포에 ConfigMap 마운트 (values.yaml에 추가)
# sidecar.dashboards.enabled: true
# sidecar.dashboards.label: grafana_dashboard
# 이 설정을 Helm 차트 values.yaml에 추가하고 업데이트하면 대시보드가 자동으로 로드됩니다
# sidecar 컨테이너가 레이블이 있는 ConfigMap을 감시하고 로드합니다

Grafana Helm 차트의 values.yaml에 대시보드 프로비저닝 설정 추가:

# Grafana Helm 차트 values.yaml의 dashboardProviders 및 dashboards 섹션
dashboardProviders:
  dashboardproviders.yaml:
    apiVersion: 1
    # 대시보드 프로바이더 API 버전
    providers:
    - name: 'default'
      # 프로바이더 이름
      orgId: 1
      # 조직 ID
      folder: ''
      # 대시보드 폴더 - 빈 문자열은 루트 폴더
      type: file
      # 프로바이더 유형 - 파일 시스템 기반
      disableDeletion: false
      # 대시보드 삭제 비활성화 여부
      editable: true
      # 대시보드 편집 가능 여부
      options:
        path: /var/lib/grafana/dashboards/default
        # 대시보드 파일 경로

dashboards:
  default:
    # 네임스페이스 내의 기본 폴더에 로드할 대시보드
    kubernetes-cluster:
      gnetId: 7249  
      # Grafana.com 대시보드 ID
      # 이 ID는 쿠버네티스 클러스터 모니터링용 대시보드
      revision: 1
      # 대시보드 수정 버전
      datasource: Prometheus
      # 데이터 소스 이름 - Prometheus로 설정
    
    node-exporter:
      gnetId: 1860
      # Node Exporter 대시보드 ID
      revision: 30
      # 대시보드 수정 버전
      datasource: Prometheus
      # 데이터 소스 이름
    
    pod-resources:
      gnetId: 10000  
      # 파드 리소스 대시보드 ID (예시)
      revision: 1
      # 대시보드 수정 버전
      datasource: Prometheus
      # 데이터 소스 이름

✅ Grafana 보안 설정

Grafana 보안 강화를 위한 설정:

  1. TLS/SSL 설정:
# ingress-tls.yaml
apiVersion: networking.k8s.io/v1
# 쿠버네티스 API 버전
kind: Ingress
# 리소스 타입 - Ingress로 설정
metadata:
  name: grafana
  # 인그레스 이름
  namespace: grafana
  # 네임스페이스 지정
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # 인그레스 컨트롤러 클래스 지정
    # Let's Encrypt 인증서 자동 발급 (cert-manager 사용 시)
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    # cert-manager ClusterIssuer 이름
    # Let's Encrypt 프로덕션 환경용 인증서 발급
spec:
  tls:
  - hosts:
    - grafana.example.com
    # TLS 인증서를 적용할 호스트 이름
    secretName: grafana-tls
    # TLS 인증서가 저장될 Secret 이름
  rules:
  - host: grafana.example.com
    # 호스트 이름 - 실제 도메인으로 변경 필요
    http:
      paths:
      - path: /
        # 경로 - 루트 경로
        pathType: Prefix
        # 경로 타입 - Prefix는 지정된 경로로 시작하는 모든 요청 매칭
        backend:
          service:
            name: grafana
            # 대상 서비스 이름
            port:
              number: 80
              # 대상 서비스 포트
  1. Grafana에 OAuth 설정 (GitHub 예시):
# grafana.ini OAuth 설정 
[auth.github]
# GitHub OAuth 설정 섹션
enabled = true
# GitHub OAuth 활성화 여부
allow_sign_up = true
# OAuth로 로그인한 사용자 자동 생성 허용
client_id = YOUR_GITHUB_CLIENT_ID
# GitHub OAuth 앱 클라이언트 ID
client_secret = YOUR_GITHUB_CLIENT_SECRET
# GitHub OAuth 앱 클라이언트 시크릿
scopes = user:email,read:org
# 요청할 GitHub API 권한 범위
# user:email - 사용자 이메일 접근 권한
# read:org - 사용자 조직 정보 읽기 권한
auth_url = https://github.com/login/oauth/authorize
# GitHub 인증 URL
token_url = https://github.com/login/oauth/access_token
# GitHub 토큰 발급 URL
api_url = https://api.github.com/user
# GitHub API URL
team_ids =
# 접근을 제한할 특정 GitHub 팀 ID (비워두면 모든 팀)
allowed_organizations = your-github-org
# 접근을 허용할 GitHub 조직 이름
# 이 조직의 멤버만 로그인 가능
  1. 중요 설정을 위한 쿠버네티스 Secret 사용:
# grafana-secrets.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: Secret
# 리소스 타입 - Secret으로 설정
metadata:
  name: grafana-security-config
  # Secret 이름
  namespace: grafana
  # 네임스페이스 지정
stringData:
  # 인코딩하지 않은 문자열 데이터 (쿠버네티스가 자동으로 base64 인코딩)
  admin-user: admin
  # 관리자 사용자 이름
  admin-password: StrongPassword123
  # 관리자 비밀번호 - 강력한 비밀번호 사용 권장
  github-client-id: YOUR_GITHUB_CLIENT_ID
  # GitHub OAuth 앱 클라이언트 ID
  github-client-secret: YOUR_GITHUB_CLIENT_SECRET
  # GitHub OAuth 앱 클라이언트 시크릿

Secret을 환경 변수로 마운트:

# Grafana Helm 차트 values.yaml의 env 섹션
env:
  GF_SECURITY_ADMIN_USER:
    valueFrom:
      secretKeyRef:
        name: grafana-security-config
        # Secret 이름
        key: admin-user
        # Secret의 키 이름
  # 관리자 사용자 이름을 Secret에서 가져와 환경 변수로 설정
  
  GF_SECURITY_ADMIN_PASSWORD:
    valueFrom:
      secretKeyRef:
        name: grafana-security-config
        # Secret 이름
        key: admin-password
        # Secret의 키 이름
  # 관리자 비밀번호를 Secret에서 가져와 환경 변수로 설정
  
  GF_AUTH_GITHUB_CLIENT_ID:
    valueFrom:
      secretKeyRef:
        name: grafana-security-config
        # Secret 이름
        key: github-client-id
        # Secret의 키 이름
  # GitHub 클라이언트 ID를 Secret에서 가져와 환경 변수로 설정
  
  GF_AUTH_GITHUB_CLIENT_SECRET:
    valueFrom:
      secretKeyRef:
        name: grafana-security-config
        # Secret 이름
        key: github-client-secret
        # Secret의 키 이름
  # GitHub 클라이언트 시크릿을 Secret에서 가져와 환경 변수로 설정
  
  # OAuth 활성화
  GF_AUTH_GITHUB_ENABLED: "true"
  # GitHub OAuth 활성화 (문자열 "true")
  
  GF_AUTH_GITHUB_ALLOW_SIGN_UP: "true"
  # GitHub OAuth로 로그인 시 사용자 자동 생성 허용
  
  GF_AUTH_GITHUB_SCOPES: "user:email,read:org"
  # GitHub API 권한 범위 설정
  
  GF_AUTH_GITHUB_ALLOWED_ORGANIZATIONS: "your-github-org"
  # 접근을 허용할 GitHub 조직 이름

📌 Grafana 플러그인 관리

Grafana의 기능을 확장하는 플러그인 설치 및 관리 방법을 살펴보겠습니다.

✅ 주요 플러그인 유형

Grafana에는 세 가지 유형의 플러그인이 있습니다:

  1. 데이터 소스 플러그인: 다양한 데이터 소스에 연결
  2. 패널 플러그인: 새로운 시각화 유형 제공
  3. 앱 플러그인: 통합된 애플리케이션 경험 제공

✅ 유용한 플러그인 추천

쿠버네티스 모니터링에 특히 유용한 플러그인:

  1. Kubernetes App: 쿠버네티스 클러스터 모니터링을 위한 통합 앱
  2. Status Panel: 시스템 상태를 직관적으로 표시
  3. Pie Chart: 리소스 사용 분포를 시각화
  4. Heatmap: 시간별 분포 데이터 시각화
  5. Clock Panel: 여러 시간대 모니터링
  6. JSON API: 외부 API 데이터 시각화

✅ 플러그인 설치 방법

Helm 차트를 통한 플러그인 설치:

# Grafana Helm 차트 values.yaml의 plugins 섹션
plugins:
  - grafana-kubernetes-app
  # 쿠버네티스 앱 플러그인 - 클러스터 상태 종합 대시보드 제공
  
  - grafana-clock-panel
  # 시계 패널 플러그인 - 대시보드에 현재 시간과 다양한 시간대 표시
  
  - grafana-piechart-panel
  # 파이 차트 패널 플러그인 - 분포 시각화에 유용
  
  - grafana-worldmap-panel
  # 세계 지도 패널 - 지리적 데이터 시각화
  
  - natel-discrete-panel
  # 이산 패널 - 상태 변경 시각화에 유용
  
  - michaeldmoore-multistat-panel
  # 다중 통계 패널 - 여러 시계열 데이터를 한 패널에 표시

ConfigMap과 Init Container를 이용한 플러그인 설치:

# plugin-install.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: ConfigMap
# 리소스 타입 - ConfigMap으로 설정
metadata:
  name: grafana-plugin-installer
  # ConfigMap 이름
  namespace: grafana
  # 네임스페이스 지정
data:
  install-plugins.sh: |-
    #!/bin/bash
    # 플러그인 설치 스크립트
    set -e
    # 오류 발생 시 스크립트 종료
    
    PLUGINS=(
      "grafana-kubernetes-app"
      "grafana-clock-panel"
      "grafana-piechart-panel"
      "grafana-worldmap-panel"
    )
    # 설치할 플러그인 목록 배열
    
    for plugin in "${PLUGINS[@]}"; do
      grafana-cli --pluginsDir "/var/lib/grafana/plugins" plugins install $plugin
      # grafana-cli를 사용하여 각 플러그인 설치
      # --pluginsDir: 플러그인 설치 경로 지정
    done
    
    # 사용자 권한 조정
    chown -R grafana:grafana /var/lib/grafana/plugins
    # 플러그인 디렉토리 소유자를 grafana 사용자로 변경
    # 이는 권한 문제 방지를 위해 필요

Deployment에 Init Container 추가:

# Grafana Helm 차트 values.yaml의 initContainers 섹션
initContainers:
  - name: plugin-installer
    # 초기화 컨테이너 이름
    image: grafana/grafana:8.4.0
    # Grafana 이미지 사용 (메인 컨테이너와 동일 버전 권장)
    command: ["/bin/bash", "/scripts/install-plugins.sh"]
    # 실행할 명령어 - 플러그인 설치 스크립트 실행
    volumeMounts:
      - name: plugins
        mountPath: /var/lib/grafana/plugins
        # 플러그인 디렉토리 마운트
      - name: plugin-installer
        mountPath: /scripts/install-plugins.sh
        subPath: install-plugins.sh
        # 설치 스크립트 마운트

볼륨 설정:

# Grafana Helm 차트 values.yaml의 extraVolumes 및 extraVolumeMounts 섹션
extraVolumes:
  - name: plugin-installer
    # 볼륨 이름
    configMap:
      name: grafana-plugin-installer
      # 설치 스크립트가 있는 ConfigMap 이름
      defaultMode: 0755
      # 실행 권한 설정 (755 = 실행 가능)

extraVolumeMounts:
  - name: plugin-installer
    # 마운트할 볼륨 이름
    mountPath: /scripts/install-plugins.sh
    # 마운트 경로
    subPath: install-plugins.sh
    # 단일 파일만 마운트 (전체 ConfigMap이 아님)

📌 Grafana 백업 및 복구 전략

운영 환경에서 Grafana 데이터를 안전하게 백업하고 복구하는 방법을 알아보겠습니다.

✅ 백업 대상 데이터

Grafana에서 백업해야 할 주요 데이터:

  1. 데이터베이스: 대시보드, 사용자, 알림 설정 등 포함
  2. 설정 파일: grafana.ini, LDAP 설정 등
  3. 플러그인: 커스텀 플러그인이 있는 경우
  4. 프로비저닝 설정: 대시보드, 데이터 소스 프로비저닝 파일

✅ 쿠버네티스에서 Grafana 백업 방법

CronJob을 사용한 정기 백업 설정:

# grafana-backup.yaml
apiVersion: batch/v1
# 쿠버네티스 API 버전
kind: CronJob
# 리소스 타입 - CronJob으로 설정 (정기적 작업 실행)
metadata:
  name: grafana-backup
  # CronJob 이름
  namespace: grafana
  # 네임스페이스 지정
spec:
  schedule: "0 1 * * *"  
  # 백업 실행 일정 (cron 형식)
  # "0 1 * * *" = 매일 01:00에 실행
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: grafana-backup-sa  
          # 적절한 권한이 있는 서비스 계정
          # 파드 exec 및 cp 권한이 필요함
          containers:
          - name: grafana-backup
            # 컨테이너 이름
            image: bitnami/kubectl:latest
            # kubectl 명령어가 포함된 이미지
            command:
            - /bin/sh
            - -c
            - |
              # SQLite 데이터베이스 백업 (기본 설정 사용 시)
              kubectl exec -n grafana $(kubectl get pods -n grafana -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}') -- \
                sh -c "sqlite3 /var/lib/grafana/grafana.db .dump > /tmp/grafana_db_backup.sql"
              # Grafana 파드에 접속하여 SQLite 데이터베이스 덤프 생성
              # kubectl exec: 파드 내부에서 명령 실행
              # $(kubectl get pods ...): Grafana 파드 이름 동적 조회
              # sqlite3 ... .dump: SQLite 데이터베이스 덤프 명령
              
              # 백업 파일 가져오기
              kubectl cp grafana/$(kubectl get pods -n grafana -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}'):/tmp/grafana_db_backup.sql \
                /backup/grafana_db_$(date +%Y%m%d).sql
              # kubectl cp: 파드에서 로컬로 파일 복사
              # /backup/grafana_db_$(date +%Y%m%d).sql: 날짜가 포함된 백업 파일 이름
              
              # ConfigMap 백업
              kubectl get configmaps -n grafana -o yaml > /backup/grafana_configmaps_$(date +%Y%m%d).yaml
              # grafana 네임스페이스의 모든 ConfigMap YAML 저장
              
              # Secret 백업
              kubectl get secrets -n grafana -o yaml > /backup/grafana_secrets_$(date +%Y%m%d).yaml
              # grafana 네임스페이스의 모든 Secret YAML 저장
              
              # PVC 백업 (옵션)
              # kubectl get pvc -n grafana -o yaml > /backup/grafana_pvc_$(date +%Y%m%d).yaml
              # PVC 설정 백업 (필요시 주석 해제)
              
              # 백업 파일 압축
              tar -czf /backup/grafana_backup_$(date +%Y%m%d).tar.gz /backup/grafana_*_$(date +%Y%m%d).*
              # 모든 백업 파일을 tar.gz로 압축
              
              # 보관 기간이 지난 백업 삭제 (30일)
              find /backup -name "grafana_backup_*.tar.gz" -type f -mtime +30 -delete
              # 30일이 지난 백업 파일 자동 삭제 (공간 관리)
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
              # 백업 저장소 볼륨 마운트
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: grafana-backup-pvc
              # 백업 데이터를 저장할 PVC
          restartPolicy: OnFailure
          # 작업 실패 시 재시작 정책

백업용 PVC 생성:

# backup-pvc.yaml
apiVersion: v1
# 쿠버네티스 API 버전
kind: PersistentVolumeClaim
# 리소스 타입 - PVC로 설정
metadata:
  name: grafana-backup-pvc
  # PVC 이름
  namespace: grafana
  # 네임스페이스 지정
spec:
  accessModes:
    - ReadWriteOnce
    # 접근 모드 - 하나의 노드에서만 읽기/쓰기
  resources:
    requests:
      storage: 5Gi
      # 요청 스토리지 크기 - 5GB
      # 백업 데이터 양에 따라 조정 필요
  storageClassName: standard
  # 스토리지 클래스 이름
  # 클러스터 환경에 맞게 적절한 스토리지 클래스 지정

✅ Grafana 복구 방법

백업에서 Grafana 복구 방법:

# grafana-restore.yaml
apiVersion: batch/v1
# 쿠버네티스 API 버전
kind: Job
# 리소스 타입 - 일회성 작업
metadata:
  name: grafana-restore
  # Job 이름
  namespace: grafana
  # 네임스페이스 지정
spec:
  template:
    spec:
      serviceAccountName: grafana-backup-sa  
      # 적절한 권한이 있는 서비스 계정
      # 파드 exec 및 cp 권한이 필요함
      containers:
      - name: grafana-restore
        # 컨테이너 이름
        image: bitnami/kubectl:latest
        # kubectl 명령어가 포함된 이미지
        command:
        - /bin/sh
        - -c
        - |
          # 복구할 백업 파일 지정
          BACKUP_DATE="20230615"  
          # 복구할 백업 날짜 - 실제 복구 시 적절한 날짜로 변경
          
          # 백업 아카이브 압축 해제
          tar -xzf /backup/grafana_backup_${BACKUP_DATE}.tar.gz -C /tmp
          # 압축된 백업 파일을 /tmp 디렉토리에 해제
          
          # Grafana 스케일 다운
          kubectl scale deployment -n grafana grafana --replicas=0
          # 복구 작업 중 충돌 방지를 위해 Grafana 파드 수를 0으로 축소
          
          # 데이터베이스 복구 (새 파드 생성 후)
          kubectl scale deployment -n grafana grafana --replicas=1
          # 복구를 위해 Grafana 파드 1개 생성
          sleep 30  
          # 파드가 준비될 때까지 대기 (30초)
          
          # SQLite 데이터베이스 복원
          kubectl cp /tmp/backup/grafana_db_${BACKUP_DATE}.sql \
            grafana/$(kubectl get pods -n grafana -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}'):/tmp/grafana_db_backup.sql
          # 백업된 SQL 파일을 Grafana 파드로 복사
          
          kubectl exec -n grafana $(kubectl get pods -n grafana -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}') -- \
            sh -c "mv /var/lib/grafana/grafana.db /var/lib/grafana/grafana.db.bak && \
                  sqlite3 /var/lib/grafana/grafana.db < /tmp/grafana_db_backup.sql"
          # 현재 데이터베이스 백업 후 복원
          # mv: 기존 DB 파일 백업
          # sqlite3: SQL 파일로부터 데이터베이스 복원
          
          # Grafana 재시작
          kubectl rollout restart deployment -n grafana grafana
          # 변경사항 적용을 위해 Grafana 배포 재시작
        volumeMounts:
        - name: backup-storage
          mountPath: /backup
          # 백업 저장소 볼륨 마운트
      volumes:
      - name: backup-storage
        persistentVolumeClaim:
          claimName: grafana-backup-pvc
          # 백업 데이터가 저장된 PVC
      restartPolicy: OnFailure
      # 작업 실패 시 재시작 정책

📌 고가용성 Grafana 구성

운영 환경을 위한 고가용성 Grafana 설정 방법을 알아보겠습니다.

✅ 데이터베이스 고가용성

기본 SQLite 대신 외부 데이터베이스(MySQL, PostgreSQL) 사용:

# grafana.ini 데이터베이스 설정
[database]
# 데이터베이스 설정 섹션
type = postgres
# 데이터베이스 유형 (mysql, postgres)
# SQLite는 단일 파일 DB로 고가용성에 적합하지 않음
host = grafana-postgres:5432
# 데이터베이스 호스트 및 포트
# 쿠버네티스 서비스 이름 사용
name = grafana
# 데이터베이스 이름
user = grafana-user
# 데이터베이스 사용자
# Secret에서 관리
# password = grafana-password
# 데이터베이스 비밀번호 - Secret으로 관리 권장
ssl_mode = disable
# SSL 모드 (disable, require 등)
# 프로덕션 환경에서는 require 권장

PostgreSQL 데이터베이스 배포:

# postgres-values.yaml
# Bitnami PostgreSQL Helm 차트 values.yaml
global:
  postgresql:
    auth:
      username: grafana-user
      # PostgreSQL 사용자 이름
      password: grafana-password
      # PostgreSQL 비밀번호
      # 프로덕션에서는 Secret으로 관리 권장
      database: grafana
      # Grafana용 데이터베이스 이름

primary:
  persistence:
    enabled: true
    # 영구 스토리지 활성화
    size: 10Gi
    # 스토리지 크기 - 10GB
  
  resources:
    requests:
      memory: 256Mi
      # 메모리 요청 - 256MB
      cpu: 250m
      # CPU 요청 - 0.25 코어
    limits:
      memory: 512Mi
      # 메모리 제한 - 512MB
      cpu: 500m
      # CPU 제한 - 0.5 코어

PostgreSQL 설치:

# Bitnami PostgreSQL 차트 설치
helm repo add bitnami https://charts.bitnami.com/bitnami
# Bitnami 레포지토리 추가
# Bitnami는 안정적인 차트를 제공하는 주요 공급자

helm repo update
# 레포지토리 정보 업데이트

helm install grafana-postgres bitnami/postgresql -f postgres-values.yaml -n grafana
# 'grafana-postgres'라는 이름으로 PostgreSQL 설치
# -f postgres-values.yaml: 커스텀 설정 파일 적용
# -n grafana: grafana 네임스페이스에 설치

✅ Grafana 스케일링 및 고가용성 설정

Grafana 수평 확장 설정:

# Grafana Helm 차트 values.yaml의 고가용성 설정
replicas: 2
# 복제본 수 - 고가용성을 위해 2개 이상 권장
# 한 노드에 장애가 발생해도 서비스 지속 가능

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      # 우선순위 가중치 - 높을수록 중요
      podAffinityTerm:
        labelSelector:
          matchExpressions:
          - key: app.kubernetes.io/name
            operator: In
            values:
            - grafana
            # Grafana 파드 레이블과 일치하는 파드
        topologyKey: kubernetes.io/hostname
        # 토폴로지 키 - 다른 호스트에 파드 분산
    # Grafana 파드를 다른 노드에 분산 배치하여 노드 장애 대비

podDisruptionBudget:
  enabled: true
  # 파드 중단 예산 활성화
  minAvailable: 1
  # 최소 유지 파드 수 - 항상 1개 이상 유지

persistence:
  type: pvc
  # 영구 볼륨 클레임 사용
  enabled: true
  # 영구 스토리지 활성화
  storageClassName: standard
  # 스토리지 클래스 이름
  accessModes:
    - ReadWriteOnce
    # 접근 모드 - 하나의 노드에서만 읽기/쓰기
  size: 10Gi
  # 스토리지 크기 - 10GB
  finalizers:
    - kubernetes.io/pvc-protection
    # PVC 보호 활성화 - 실수로 인한 삭제 방지

✅ 인그레스 고가용성

인그레스 컨트롤러를 통한 로드 밸런싱:

# ingress-values.yaml
# NGINX Ingress Controller 설정
controller:
  replicaCount: 2
  # 컨트롤러 복제본 수 - 고가용성을 위해 2개 이상 권장
  
  service:
    type: LoadBalancer
    # 서비스 유형 - 외부 접근을 위한 로드밸런서
  
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        # 우선순위 가중치 - 높을수록 중요
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app.kubernetes.io/name
              operator: In
              values:
              - ingress-nginx
              # Ingress NGINX 파드 레이블과 일치하는 파드
          topologyKey: kubernetes.io/hostname
          # 토폴로지 키 - 다른 호스트에 파드 분산
      # Ingress 컨트롤러 파드를 다른 노드에 분산 배치

NGINX Ingress Controller 설치:

# NGINX Ingress Controller 설치
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# NGINX Ingress Controller 레포지토리 추가

helm repo update
# 레포지토리 정보 업데이트

helm install ingress-nginx ingress-nginx/ingress-nginx -f ingress-values.yaml -n ingress-nginx --create-namespace
# 'ingress-nginx'라는 이름으로 Ingress Controller 설치
# -f ingress-values.yaml: 커스텀 설정 파일 적용
# -n ingress-nginx: ingress-nginx 네임스페이스에 설치
# --create-namespace: 네임스페이스가 없으면 생성

📌 Summary

이번 포스트에서는 쿠버네티스 환경에 Grafana를 설치하고 기본 설정을 구성하는 방법에 대해 자세히 알아보았습니다. 다음과 같은 내용을 다루었습니다:

  • Grafana 아키텍처 및 역할: Grafana의 기본 아키텍처와 모니터링 환경에서의 중요한 역할에 대해 이해했습니다. 프론트엔드, 백엔드 서버, 데이터베이스, 플러그인 시스템으로 구성된 Grafana의 구조를 파악하고, 다양한 데이터 소스 지원, 강력한 시각화 기능, 알림 시스템과 같은 핵심 특징을 확인했습니다.
  • 설치 방법: Helm 차트, Grafana Operator, kube-prometheus-stack 등 쿠버네티스 환경에서 Grafana를 설치하는 다양한 방법을 살펴보았습니다. 각 방법의 장단점과 사용 사례를 이해하여 환경에 맞는 최적의 설치 방법을 선택할 수 있게 되었습니다. 특히 Helm 차트를 사용한 설치와 커스텀 설정 적용 방법에 중점을 두었습니다.
  • 데이터 소스 연결: Prometheus를 비롯한 다양한 데이터 소스를 Grafana에 연결하는 방법을 배웠습니다. UI를 통한 수동 설정과 ConfigMap을 통한 자동화된 설정 방법을 모두 알아보았으며, 쿠버네티스 서비스 디스커버리를 활용한 효율적인 데이터 소스 구성 방법을 이해했습니다.
  • 사용자 관리 및 인증: 기본 인증부터 LDAP, OAuth까지 다양한 인증 방식을 설정하는 방법을 학습했습니다. 특히 엔터프라이즈 환경에서 중요한 LDAP 통합과 권한 관리 방법, GitHub OAuth 설정을 통한 소셜 로그인 구현 방법을 자세히 알아보았습니다.
  • 대시보드 프로비저닝: 미리 정의된 대시보드를 자동으로 불러오는 프로비저닝 설정 방법을 배웠습니다. ConfigMap과 사이드카 컨테이너를 활용하여 대시보드를 코드로 관리하고, Grafana.com에서 제공하는 커뮤니티 대시보드를 효율적으로 가져오는 방법을 익혔습니다.
  • 보안 강화: TLS/SSL 설정, Secret 관리, OAuth 인증 등을 통한 Grafana 보안 강화 방법을 알아보았습니다. 특히 인그레스에 TLS를 적용하는 방법과 중요한 설정 정보를 쿠버네티스 Secret으로 안전하게 관리하는 방법에 중점을 두었습니다.
  • 플러그인 관리: 유용한 플러그인 설치 및 관리 방법을 배웠습니다. 다양한 플러그인 유형과 쿠버네티스 모니터링에 유용한 추천 플러그인을 소개하고, Helm 차트와 Init Container를 활용한 자동화된 플러그인 설치 방법을 알아보았습니다.
  • 백업 및 복구: 운영 환경에서 필수적인 데이터 백업 및 복구 전략을 수립하는 방법을 배웠습니다. CronJob을 활용한 정기 백업 설정, 백업 데이터 관리, 그리고 장애 발생 시 백업에서 복구하는 체계적인 절차를 이해했습니다.
  • 고가용성 구성: 운영 환경을 위한 고가용성 Grafana 설정 방법을 알아보았습니다. SQLite 대신 PostgreSQL과 같은 외부 데이터베이스 사용, 복제본 확장, 파드 분산 배치, 인그레스 로드 밸런싱 등을 통해 안정적이고 확장 가능한 Grafana 환경을 구축하는 방법을 살펴보았습니다.
728x90