1. Grafana란

  • 다양한 저장소와의 연동을 지원하고 연동을 통해 데이터를 쿼리, 시각화, 알림 기능을 제공
  • 여러 데이터를 조합하여 대시보드를 쉽게 만들 수 있음
  • notification 기능을 이용하여 텔레그램, 이메일, 라인, 팀즈 등을 이용하여 알림을 받을 수 있음

 

2. Grafana 설치

2.1. 그라파나 다운로드 페이지에 접속하여 원하는 버전과 환경을 선택 가능 → 다운로드 & 설치 방법이 표시되는데 복사해서 사용

 

 

2.2. Grafana 설치

# 특정 rpm yum으로 설치 
$ yum install -y https://dl.grafana.com/oss/release/grafana-10.1.1-1.x86_64.rpm  

 

 

※ 그라파나 설치 경로 : https://grafana.com/grafana/download

 

Download Grafana | Grafana Labs

Overview of how to download and install different versions of Grafana on different operating systems.

grafana.com

 

3. Grafana 실행

# 그라파나 실행 
$ systemctl enable --now grafana-server.service 


# 그라파나 상태 확인 
$ systemctl status grafana-server.service 
● grafana-server.service - Grafana instance
   Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2023-09-17 03:55:10 KST; 2s ago
     Docs: http://docs.grafana.org
 Main PID: 18076 (grafana)
   CGroup: /system.slice/grafana-server.service


 ## 포트 확인
 $ netstat -ntap | grep LISTEN | grep 3000 
  tcp6 0 0 :::3000 :::* LISTEN 18076/grafana

 

 

4. 접속

  • http://yourIP or Domain:3000/login 접속
  • 기본 접속 정보
    • Email or username : admin
    • Password : admin
    • Port : 3000

 

  • 초기 로그인 화면

 

  • admin 로그인 시 사용할 비밀번호로 변경

 

  • 비밀번호 변경 후 로그인 성공 시 첫 메인 화면 출력

 

  • Data sources 설정에서 저장소와 연동하여 대시보드로 데이터를 시각화(Configuration 설정)
  • 그라파나 Data sources 설정에 localhost 서버 프로메테우스 설정 → Acess Auth 설정 시 추가 기입 필요

 

  • 데이터 저장소와 연동 후 대시보드를 생성

 

그라파나(Grafana)란

  • Grafana란, Grafana Labs에서 관리하고 있는 오픈 소스 시각화 및 분석 도구
  • Prometheus 물론 InfluxDB, Elasticsearch 등 여러 데이터 소스와 통합이 가능
  • Prometheus 자체적으로 UI를 제공하고 있지만, 기능이 너무나도 빈약하고 불편해서 상용 환경에서는 Grafana와 함께 연동해서 사용
  • Grafana는 여러 데이터 소스에 대한 대시보드 템플릿을 제공하기 때문에, Prometheus 등의 데이터 소스의 쿼리 방법을 잘 모른다 하더라도 기본적인 대시보드 구성이 가능
  • Grafana는 오픈소스 메트릭 데이터 시각화 도구로 메트릭 분석 플랫폼을 지향
  • Prometheus와 Grafana는 모두 Grafana Labs에서 관리하고 있기 때문에, 궁합이 어떤 데이터 소스와 비교하더라도 매우 좋음
  • grafana/grafana: 공식 GitHub 저장소 : https://github.com/grafana/grafana
  • Grafana 공식 웹사이트 : https://grafana.com/
 

Grafana: The open observability platform | Grafana Labs

Your observability stack Operational dashboards for your data here, there, or anywhere

grafana.com

 

  • Grafana는 오픈소스 메트릭 데이터 시각화 도구로 메트릭 분석 플랫폼을 지향
  • Torkel Ödegaard의 주도로 2014년 처음 릴리스
  • 처음에는 Graphite, DBInfluxDB, OpenTSDB 등을 지원하는 오픈소스 대시보드 도구로 개발
  • 메트릭 정보를 시각화하고 대시보드를 구성한다는 큰 틀은 여전히 변함이 없습니다만, AWS CloudWatch, Azure Monitor와 같은 클라우드 데이터 소스를 비롯해 Loki나 ElasticSearch 등을 기반으로 로그 데이터를 지원하는 등 더 많은 데이터 소스를 지원
  • 엔터프라이즈 플랜에서는 Splunk, New Relic, AppDynamics, Oracle, Dynatrace, ServiceNow, DataDog 등의 외부 서비스들과 통합도 지원

 

  • Grafana는 현재 Grafana Labs에서 개발
  • Grafana LAB은 Grafana와 Loki, Tanka 등의 애플리케이션을 오픈소스를 개발하고 있는 회사
  • Grafana는 Paypal, ebay, Intel, rackspace, Video, TED, Digital Ocean, Bloomberg 등 다양한 기업에서 활용
  • 다양한 도입 사례 : https://grafana.com/success/
 

Success stories and case studies | Grafana Labs

We have been able to enhance our application and infrastructure uptime with Grafana Labs, resulting in stronger business performance. - George Sherman, Global Technology Infrastructure CIO

grafana.com

 

 

그라파나 클라우드(Grafana Cloud)와 그라파나 엔터프라이즈(Grafana Enterprise)

  • Grafana는 오픈소스로 기본적으로는 직접 설치하고 운영해야 함
  • 또한 메트릭 데이터나 로그 데이터에 대한 관리도 직접해야함
  • Grafana LAB에서는 그라파나를 서비스로 제공하는 그라파나 클라우드 서비스를 제공
  • 무료 플랜에서는 5개의 대시보드까지 생성 가능
  • 스탠다드(Standard) 이상의 플랜에서는 다중 유저 기능을 제공하며, 대시보드를 제한없이 생성 가능
  • 메트릭과 로그 데이터를 저장하는 기능을 제공
  • 스토리지 비용은 별도로 발생하니 확인이 필요
  • Grafana Enterprise에서는 SAML을 지원하고, 추가적으로 Splunk, New Relic, AppDynamics, Oracle, Dynatrace, ServiceNow, DataDog 플러그인을 지원
  • 이외에도 협업 관련 기능과 더 강화된 서비스 지원을 받을 수 있음
  • 그라파나 엔터프라이즈(Grafana Enterprise) : https://grafana.com/products/enterprise/
 

Grafana Enterprise | Observability stack overview

Scalable. Simple. Secure. Supported. The Grafana Enterprise Stack includes features that provide better scalability, collaboration, operations, and governance in a self-managed environment.

grafana.com

 

 

그라파나 대시보드(Grafana Dashboard)

 

 

테슬라 대시보드(Teslamate Grafana Dashboard)

  • 자신이 소유한 테슬라 자동차의 데이터를 가져와서 시각화하는 프로젝트들도 다수 공개
  • 그라파나를 대시보드로 사용
  • 테슬라 대시보드 : https://github.com/adriankumpf/teslamate

 

 

참고 자료

1. YUM Repository 추가

  • Influxdata에서 제공하는 influxdb.repo 저장소를 Yum Repository에 추가
  • influxdb.repo 정보는 influxdata 홈페이지에서 참고
    $ cat <<EOF | tee /etc/yum.repos.d/influxdb.repo
    [influxdb]
    name = InfluxDB Repository - RHEL \$releasever
    baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
    enabled = 1
    gpgcheck = 1
    gpgkey = https://repos.influxdata.com/influxdb.key
    EOF
  • 저장소 리스트를 확인하여 정상적으로 추가된 것을 확인
    $ yum repolist | grep influxdb
    influxdb/7/x86_64                       InfluxDB Repository - RHEL 7         252

2. InfluxDB 설치 및 구동

  • InfluxDB 설치 및 상태 확인

    # 설치 및 구동
    $ yum install influxdb -y
    $ systemctl enable --now influxdb
    
    # 서비스 상태 확인
    $ systemctl status influxdb
    ● influxdb.service - InfluxDB is an open-source, distributed, time series database
       Loaded: loaded (/usr/lib/systemd/system/influxdb.service; enabled; vendor preset: disabled)
       Active: active (running) since Thu 2021-12-02 15:44:39 KST; 1s ago
         Docs: https://docs.influxdata.com/influxdb/
      Process: 9253 ExecStart=/usr/lib/influxdb/scripts/influxd-systemd-start.sh (code=exited, status=0/SUCCESS)
     Main PID: 9254 (influxd)
        Tasks: 19
       Memory: 9.5M
       CGroup: /system.slice/influxdb.service
               └─9254 /usr/bin/influxd -config /etc/influxdb/influxdb.conf

3. InfluxDB 포트 확인

  • InfluxDB는 8086, 8088 포트를 사용
  • 8086 포트 : InfluxDB의 HTTP API 통신을 위한 용도
  • 8088 포트 : 백업과 리스토어를 위한 RPC 서비스 용도
    $ netstat -anpot | grep influx
    tcp        0      0 127.0.0.1:8088          0.0.0.0:*               LISTEN      9254/influxd         off (0.00/0/0)
    tcp        0      0 180.70.134.124:42518    52.85.231.23:443        ESTABLISHED 9254/influxd         keepalive (11.82/0/0)
    tcp6       0      0 :::8086                 :::*                    LISTEN      9254/influxd         off (0.00/0/0)

4. InfluxDB 데이터 베이스 생성

  • fluentdb 이름의 데이터 베이스 생성

      $ influx
    
      # 초기 데이터베이스 확인
      > show databases
      name: databases
      name
      ----
      _internal
    
      # fluentdb 이름을 가지는 데이터베이스 생성
      > create database fluentdb
    
      #  생성 확인
      > show databases
      name: databases
      name
      ----
      _internal
      fluentdb
    
      # 생성한 fluentdb 데이터베이스 접근
      > use fluentdb
      Using database fluentdb

1. github에 cdn_vtx_nginx Repository 생성

  • github의 Repository 생성

  • VS Code의 코드를 통해 github에 등록하기 위해 기초 적업 진행 → 향후 add, commit, push를 통해 쉽게 github에 동기화 가능
    $ echo "# cdn_vtx_nginx" >> README.md
    $ git init
    $ git add README.md
    $ git commit -m "first commit"
    $ git branch -M main
    $ git remote add origin https://github.com/HippoMans/cdn_vtx_nginx.git
    $ git push -u origin main

  • Jenkins에서 자동으로 Repository를 일기 위해서 Webhook 설정 →Payload URL의 설정은 Jenkins IP:12080

2. 이미지를 push, pull할 Docker Private Repository에 cdn_vtx_nginx Repository 생성

  • Docker Private Repository는 Harbor Private Repository를 사용


3. Jenkins Pipeline 생성


4. ArgoCD에 cdn_vtx_nginx APP 생성


5. Jenkinsfile 생성 내용

  • Jenkins Pipeline 내용 → Github Repository에 Jenkisfile으로 업로드

    $ vi Jenkinsfile
    podTemplate(label: 'docker-build',
      containers: [
        containerTemplate(
          name: 'git',
          image: 'alpine/git',
          command: 'cat',
          ttyEnabled: true
        ),
        containerTemplate(
          name: 'docker',
          image: 'docker',
          command: 'cat',
          ttyEnabled: true
        ),
      ],
      volumes: [
        hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
      ]
    ) {
        node('docker-build') {
            def dockerHubCred = "private-docker-registry-ID"
            def appImage
    
            stage('Start'){
                slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Start -> URL : ${env.BUILD_URL}")
            }
    
            stage('Checkout'){
                container('git'){
                    try{
                        checkout scm
                        slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Checkout Success.")
                    }catch(e){
                        slackSend(Channel: '#hippo_cicd', color: '#ff0000', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Checkout Failed.")
                        throw e
                    }
                }
            }
    
            stage('Build'){
                try{
                    container('docker'){
                        script {
                            appImage = docker.build("cdn_vtx_nginx/nginx")
                        }
                        slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Build Success.")
                    }
                }catch(e){
                    slackSend(Channel: '#hippo_cicd', color: '#ff0000', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Build Failed.")
                    throw e
                }
            }
    
            stage('Test'){
                container('docker'){
                    try {
                        script {
                            appImage.inside {
                                sh 'nginx -t'
                            }
                            slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Test Success.")
                        }
                    }catch(e){
                        slackSend(Channel: '#hippo_cicd', color: '#ff0000', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Test Failed.")
                        throw e
                    }
                }
            }
    
            stage('Push'){
                container('docker'){
                    try {
                        script {
                            docker.withRegistry('https://www.hippo.com', dockerHubCred){
                            appImage.push("${env.BUILD_NUMBER}")
                            appImage.push("latest")
                            }
                        slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Push Success.")
                        }   
                    }catch(e){
                        slackSend(Channel: '#hippo_cicd', color: '#ff0000', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Push Failed.")
                        throw e
                    }
                }
            }
            stage('Complete') {
                sh "echo 'Checkout & Build & Test & Push is finished'"
                slackSend(Channel: '#hippo_cicd', color: '#000dff', message: "${env.JOB_NAME}[#${env.BUILD_NUMBER}] Pipeline Complete.")
            }
        }   
    }

6. Dockerfile 생성 내용

  • 생성된 Dockerfile 내용 → Github Repository에 Dockerfile으로 업로드

    $ vi Dockerfile
    FROM centos:7
    
    RUN yum update -y && \
        yum install -y GeoIP \
                 wget \
                 nginx-module-geoip \
                 perl-ExtUtils-Embed \
                 geoip-devel \
                 gperftools-devel \
                 gcc \
                 g++ \
                 cpp \
                 gcc-c++ \
                 openssl \
                 openssl-devel \
                 gd \
                 gd-devel \
                 libxml2-devel \
                 bzip2-devel \
                 curl-devel \
                 libicu-devel \
                 libmcrypt \
                 libmcrypt-devel \
                 openldap \
                 openldap-devel \
                 git \
                 libxslt-devel
    
    WORKDIR /root
    
    RUN wget http://nginx.org/download/nginx-1.20.1.tar.gz && \
        tar -C /root/ -xzvf nginx-1.20.1.tar.gz
    
    RUN git clone git://github.com/vozlt/nginx-module-vts.git
    
    WORKDIR /root/nginx-1.20.1
    
    RUN  ./configure --prefix=/usr/share/nginx \
                 --sbin-path=/usr/sbin/nginx \
                 --modules-path=/usr/lib64/nginx/modules \
                 --conf-path=/etc/nginx/nginx.conf \
                 --error-log-path=/var/log/nginx/error.log \
                 --http-log-path=/var/log/nginx/access.log \
                 --http-client-body-temp-path=/var/lib/nginx/tmp/client_body \
                 --http-proxy-temp-path=/var/lib/nginx/tmp/proxy \
                 --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi \
                 --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi \
                 --http-scgi-temp-path=/var/lib/nginx/tmp/scgi \
                 --pid-path=/run/nginx.pid \
                 --lock-path=/run/lock/subsys/nginx \
                 --user=nginx \
                 --group=nginx \
                 --with-compat \
                 --with-debug \
                 --with-file-aio \
                 --with-ipv6 \
                 --with-google_perftools_module \
                 --with-http_addition_module \
                 --with-http_auth_request_module \
                 --with-http_dav_module \
                 --with-http_degradation_module \
                 --with-http_flv_module \
                 --with-http_gunzip_module \
                 --with-http_gzip_static_module \
                 --with-http_image_filter_module=dynamic \
                 --with-http_mp4_module \
                 --with-http_perl_module=dynamic \
                 --with-http_random_index_module \
                 --with-http_realip_module \
                 --with-http_secure_link_module \
                 --with-http_image_filter_module \
                 --with-http_slice_module \
                 --with-http_ssl_module \
                 --with-http_stub_status_module \
                 --with-http_sub_module \
                 --with-http_v2_module \
                 --with-http_xslt_module=dynamic \
                 --with-mail=dynamic \
                 --with-mail_ssl_module \
                 --with-pcre \
                 --with-pcre-jit \
                 --with-stream=dynamic \
                 --with-stream_ssl_module \
                 --with-stream_ssl_preread_module \
                 --with-threads \
                 --with-http_xslt_module=dynamic \
                 --with-http_image_filter_module=dynamic \
                 --with-http_geoip_module \
                 --with-http_perl_module=dynamic \
                 --with-mail=dynamic \
                 --add-module=/root/nginx-module-vts/ \
                 --with-stream=dynamic
    
    RUN make && make install
    
    WORKDIR /root
    RUN useradd -r nginx
    RUN mkdir -p /var/lib/nginx/tmp/client_body
    RUN mkdir -p /etc/nginx/sites-available
    RUN mkdir -p /var/cache/nginx/temp/
    
    ADD http://20.10.195.172/nginx_config/nginx_cache_default.conf /etc/nginx/nginx.conf  # nginx 설정 파일 (제공 X)
    ADD http://20.10.195.172/nginx_config/nginx_sites_cache.conf /etc/nginx/sites-available/cache.conf   # vhost 파일 (제공 X)
    ADD http://20.10.195.172/nginx_config/cache_params /etc/nginx/cache_params  # cache_params 내용 (제공 X)
    
    VOLUME ["/cache1/", "/cache1/"]
    VOLUME ["/cache2/", "/cache2/"]
    
    EXPOSE 80
    EXPOSE 443
    
    CMD ["nginx", "-g", "daemon off;"]

7. 쿠버네티스 배포 yaml 파일

  • 쿠버네티스에 nginx 배포할 yaml 파일 내용 → Github Repository에 업로드되면 ArgoCD에서 해당 내용 배포

    $ vi cdn_vtx_nginx.yml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: cdn-vtx-nginx
    ---
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: cdn-vtx-nginx-deployment
      namespace: cdn-vtx-nginx
    spec:
      selector:
        matchLabels:
          nginx: cdn-vtx-nginx
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            nginx: cdn-vtx-nginx
        spec:
          containers:
          - name: container
            image: www.hippo.com/cdn_vtx_nginx/nginx:latest    ## harbor private registry의 Repository 위치
            ports:
            - containerPort: 80
            volumeMounts:
             - name: cache1
               mountPath: /cache1
             - name: cache2
               mountPath: /cache2
          nodeSelector:
            kubernetes.io/hostname: [worker node의 hostname]
          volumes:
          - name: cache1
            hostPath:
              path: /cache1
              type: Directory
          - name: cache2
            hostPath:
              path: /cache2
              type: Directory
          imagePullSecrets:
          - name: harbor-secret
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: cdn-vtx-nginx-loadbalancer
      namespace: cdn-vtx-nginx
    spec:
      selector:
        nginx: cdn-vtx-nginx
      ports:
        - name: http
          port: 80
          targetPort: 80
          protocol: TCP
      type: NodePort
    ---
    
    apiVersion: v1
    kind: Service
    metadata:
      name: cdn-vtx-nginx-service
      namespace: cdn-vtx-nginx
    spec:
      selector:
        nginx: cdn-vtx-nginx
      type: ClusterIP
      ports:
        - name: http
          port: 80
          targetPort: 80
          protocol: TCP
    ---
    
    apiVersion: v1
    data:
      .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL3Rlc3RoaXBwby5teXNrY2RuLmNvbSI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJIYXJib3JBZG1pbjEyMzQiLCJlbWFpbCI6InRlQGdtYWlsLmNvbSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5UVdSdGFXNHhNak0wIn19fQ==
    kind: Secret
    metadata:
      name: harbor-secret
      namespace: cdn-vtx-nginx
    type: kubernetes.io/dockerconfigjson

8. 최초 Jenkins Build는 직접 해야함 → 이후 Webhook을 통해 자동 갱신

  • Jenkins CI Build 실행

  • SLACK을 통해 Jeknis 작업 내용 전달 → 성공은 파랑색, 실패는 빨강색

9. Docker Private Repository(Harbor) 이미지 생성 확인

  • Jenkins의 Build 번호가 Tag로 표시
  • latest는 가장 최근에 Push한 파일이 들어있음

10. ArgoCD 배포 확인(쿠버네티스에서 배포되는 형태)

  • 생성된 내용은 간략한 그림으로 제공

11. 쿠버네티스의 최종 배포 확인과 테스트 서비스 유무 확인

  • cdn-vtx-nginx 네임스페이스에 배포 확인

  • gitlab에서 container registry를 사용
  • IP를 사용했기에 SSL 적용 불가
  • SSL을 사용하지 않고 container registry를 사용하에 불안정
  • 향후 gitlab에 SSL 인증서를 사용하여 적용하는 방법 테스트 필요

container registry 활성화를 위하여 gitlab.rb 설정파일 변경

  • container registry 사용하기 위해서는 아래 내용 설정 필요

    $ vi /etc/gitlab/gitlab.rb
    #### ...중략...
    gitlab_rails['gitlab_default_projects_features_container_registry'] = true
    
    ####... 중략...
    ####################################################################
    ## Container Registry settings
    ##! Docs: https://docs.gitlab.com/ee/administration/container_registry.html
    ####################################################################
    
    registry_external_url 'https://IP:8001'
  • gitlab 설정을 변경하였다면 재설정과 재시작
    $ gitlab-ctl reconfigure
  • gitlab 페이지에 container resitry 생성 확인

flask를 활용하여 version 1을 확인할 수 있는 docker 이미지 생성

1. docker 이미지에 사용할 파일 내용 소개

  • version1의 flask 내용 → server.py

    $ vi server.py
    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello, world!\n'
    
    @app.route('/version')
    def version():
        return 'version 1\n'
    
    if __name__ == '__main__':
        app.run('0.0.0.0', port=9000, debug=True)
  • python 서버를 실행하기 위해 필요한 flask 패키지 다운 → pip을 통해 flask 패키지를 docker 이미지 내에 다운
    $ vi requirements.txt
    Flask==1.1.2
  • docker 이미지를 생성하기 위한 Dockerfile 파일 내용

    $ vi Dockerfile
    FROM python:3.7-alpine
    
    WORKDIR /usr/src/app
    
    COPY . .
    
    RUN pip install --no-cache-dir -r requirements.txt
    EXPOSE 9000
    
    ENTRYPOINT ["python3"]
    
    CMD ["server.py"]

2. docker 이미지 생성 → hippo_flask:v1으로 생성

  • 이미지 이름 : hippo_flask
  • 이미지 tag : v1
    $ docker build -t hippo_flask:v1 ./
    Sending build context to Docker daemon  4.096kB
    Step 1/7 : FROM python:3.7-alpine
    3.7-alpine: Pulling from library/python
    59bf1c3509f3: Already exists
    8786870f2876: Already exists
    [...생략...]
    Step 6/7 : ENTRYPOINT ["python3"]
     ---> Running in 1cc769d232d6
    Removing intermediate container 1cc769d232d6
     ---> 07e5df487c7e
    Step 7/7 : CMD ["server.py"]
     ---> Running in 0383d99cef58
    Removing intermediate container 0383d99cef58
     ---> 64d54ca5156c
    Successfully built 64d54ca5156c
    Successfully tagged hippo_flask:v1
  • 생성한 docker 이미지 확인
    $ docker images hippo_flask
    REPOSITORY    TAG       IMAGE ID       CREATED              SIZE
    hippo_flask      v1        64d54ca5156c   About a minute ago   51.7MB

3. hippo_flask:v1 docker 이미지를 통해 컨테이너 생성과 확인

  • 컨테이너 생성
    $ docker run --name version1 -d -p 9000:9000 hippo_flask:v1
    3d75997676b1f71d80eb72070ac3dbba9695ead6810b8d2a6cefcc1bad83b939
  • 생성된 컨테이너 확인
    $ docker ps | grep version1
    3d75997676b1   hippo_flask:v1         "python3 server.py"      14 seconds ago   Up 13 seconds   0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   version1


생성된 컨테이너 통신 테스트

1. 생성된 컨테이너에 트래픽 전송하여 정상적으로 통신 되는지 curl 트래픽 전송 테스트

  • curl 명령어를 통해 통신 확인
    $ curl localhost:9000/version
    version 1

2. 생성된 컨테이너에 for문을 활용하여 연속적으로 트래픽 전송

  • 배포하는 과정에서 변화를 알기 위해 curl를 for 통해 무한 사용
    $ for (( ; ; )) do curl localhost:9000/version; sleep 1; done
    version 1
    version 1
    version 1
    version 1
    version 1
    version 1
    version 1
    ^C

3. 생성한 컨테이너 종료

# 종료할 hippo_flask:v1 컨테이너 확인
$ docker ps | grep hippo_flask
3d75997676b1   hippo_flask:v1         "python3 server.py"      2 minutes ago   Up 2 minutes   0.0.0.0:9000->9000/tcp, :::9000->9000/tcp   version1

# 해당 컨테이너 종료
$ docker rm -f 3d75997676b1


# 컨테이너가 출력되지 않았으므로 정상적으로 삭제된 것 확인
$ docker ps | grep hippo_flask



gitlab private container registry에 이미지 올리기

1. gitlab private container registry 로그인

  • gitlab에 container registry에 로그인 작업 필요 → [서버 IP]:8001로 로그인 시도

  • docker login 명령어 입력 후 Username과 Password를 입력하면 로그인됨

    $ docker login [서버 IP]:8001
    Username: root
    Password:
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
  • ※ 참고 → docker repository에 http로 접근하면 오류 발생
    $ docker login [서버 IP]:8001
    Username: root
    Password:
    Error response from daemon: Get "https://서버 IP:8001/v2/": http: server gave HTTP response to HTTPS client
  • 해결 방법 → 접근 시도하는 서버의 docker 설정 변경(insecure-registries 내용 부분 추가)

    $ vi /etc/docker/daemon.json
    {
      "insecure-registries": ["서버 IP:8001"],
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m"
      },
      "storage-driver": "overlay2",
      "storage-opts": [
        "overlay2.override_kernel_check=true"
      ]
    }
    
    # daemon.json를 적용하기 위해 docker 재실행
    $ systemctl retart docker

2. gitlab private container registry에 등록할 image 생성

  • [서버 IP]:8001 주소를 가진 gitlab에 /root/test 경로로 이미지 생성
    $ docker build -t [서버 IP]:8001/root/test .
    Sending build context to Docker daemon  4.096kB
    Step 1/7 : FROM python:3.7-alpine
     ---> a1034fd13493
    Step 2/7 : WORKDIR /usr/src/app
     ---> Using cache
     ---> 5ab0544a8338
    Step 3/7 : COPY . .
     ---> Using cache
     ---> e1867730ab46
    Step 4/7 : RUN pip install --no-cache-dir -r requirements.txt
     ---> Using cache
     ---> 6bb03c2fca00
    Step 5/7 : EXPOSE 9000
     ---> Using cache
     ---> fbbd26c4f799
    Step 6/7 : ENTRYPOINT ["python3"]
     ---> Using cache
     ---> 07e5df487c7e
    Step 7/7 : CMD ["server.py"]
     ---> Using cache
     ---> 64d54ca5156c
    Successfully built 64d54ca5156c
    Successfully tagged 180.70.134.124:8001/root/test:latest
  • 생성 이미지 이름 확인
    $ docker images | grep -i "[서버 IP]:8001"
    [서버 IP]:8001/root/test                    latest         64d54ca5156c   33 minutes ago   51.7MB

3. gitlab private container registry에 이미지 push

  • gitlab private container registry에 push 후http://[서버 IP]:8001/root/test/container_registry 접속해서 로그인하면 업로드된 화면을 확인 가능
    $ docker push hippo7788/hippo_flask:v1
    The push refers to repository [docker.io/hippo7788/hippo_flask]
    fca7f999dd38: Pushed
    07a451b20a57: Pushed
    20093ec82cc4: Pushed
    4df147e7bcb6: Pushed
    880c61470517: Mounted from library/python
    45d4d0cf56eb: Mounted from library/python
    619b8ea44798: Mounted from library/python
    a2f23be74558: Mounted from library/python
    e2eb06d8af82: Mounted from library/python
    v1: digest: sha256:d8a803d8b0d05dd42d0563c4151d370b5f9a50808611a62bdaeffd22332bcdce size: 2204
  • gitlab private container registry에 업로드 확인
  • docker hub에 업로그한 이미지 다운받아서 확인 → 이전에 사용한 컨테이너와 이미지는 삭제

    # 컨테이너 삭제 -> docker ps로 확인 가능
    $ docker rm -f 5fefc9b6e072
    5fefc9b6e072
    
    # 이미지 삭제 -> docker images로 확인 가능
    $ docker rmi -f hippo_flask
    Untagged: hippo_flask:v1
    
    # 이미지 삭제 -> docker images로 확인 가능
    $ docker rmi -f 8dc659fae720
    Untagged: hippo7788/hippo_flask:v1
    Untagged: hippo7788/hippo_flask@sha256:d8a803d8b0d05dd42d0563c4151d370b5f9a50808611a62bdaeffd22332bcdce
    Deleted: sha256:8dc659fae720e2989a727e504fc712a6433500a55ef8bba911fcd802dde65f74
    Deleted: sha256:aa987e77dfe966494d486e3a7d49bcda9e46b3620471911ba59eecd4ca9c7736
    Deleted: sha256:a4c264e5cc48f12f09b0a57670de350bc9ccd4aec7210411a21261938c4bee51
    Deleted: sha256:ea20f857309d14f754678a3de6d98037473656f0654c4392ffb30f3d61d1716c
    Deleted: sha256:9c5b47ae8a6edd9e6d8549dde338997b5cd0e32f97d1b973c36301520afb2590
    Deleted: sha256:be4379647236972f9cee3f1508c8821e619703060c2bb79058f746b36c8a31c3
    Deleted: sha256:54ebb48e2f85190b5ac7a315e667becad4520727455c8e061861d89609dc3d31
    Deleted: sha256:0458e8557286e301e0e59bc2555979a3ebbd0212012b54c25670d7375714b697
    Deleted: sha256:bf7be436ba34ac4068d4c1f1eaf07d1d46ffc6457bc73dc2fd9a1dda39d0cd2b
    Deleted: sha256:38f374f0f73da0d857c17772f78c586cebfc3354f5fe8419a0bdb14a7a47b235
    Deleted: sha256:a944a01d620ff5361172590ce45ea48dc38b8c564a154a99f876ae0bc0e01827



Docker Hub에 올린 이미지를 다운 후 컨테이너 실행 → hippo7788/hippo_flask:v1

1. Docker Hub에 있는 hippo7788/hippo_flask:v1 이미지를 통해 컨테이너 생성

  • 이미지 다운 후 컨테이너 확인

    $ docker run --name version1 -d -p 9000:9000 hippo7788/hippo_flask:v1
    Unable to find image 'hippo7788/hippo_flask:v1' locally
    v1: Pulling from hippo7788/hippo_flask
    a0d0a0d46f8b: Already exists
    c11246b421be: Already exists
    c5f7759615a9: Already exists
    6dc4dde3f226: Already exists
    f2db6ae633c1: Already exists
    9c864080a3a4: Pull complete
    615272ced259: Pull complete
    82808996193e: Pull complete
    71f74dbb2c6d: Pull complete
    Digest: sha256:d8a803d8b0d05dd42d0563c4151d370b5f9a50808611a62bdaeffd22332bcdce
    Status: Downloaded newer image for hippo7788/hippo_flask:v1
    f478fb738e1f7cf8f10a787581910cc8cf5e966bf6c9bc2d328199c996947be1
    
    # 생성된 컨테이너 확인
    $ docker ps | grep version1
    f478fb738e1f        hippo7788/hippo_flask:v1   "python3 server.py"      42 seconds ago      Up 41 seconds       0.0.0.0:9000->9000/tcp   version1
    
    # 생성된 이미지 확인
    $ docker images hippo7788/hippo_flask
    REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
    hippo7788/hippo_flask   v1                  8dc659fae720        2 hours ago         54MB

2. 생성된 컨테이너에 트래픽 전송하여 정상적으로 통신 되는지 curl 트래픽 전송 테스트

  • 다운받은 이미지의 컨테이너가 실행되는 지 테스트
    $ curl localhost:9000/version
    version 1

  • gitlab 공식 사이트의 설치 가이드 제공 URL → https://about.gitlab.com/install/#centos-7?version=ce
  • gitlab을 docker container registry로 사용 가능
  • 쿠버네티스 CI/CD 파이프라인으로 활용 가능
  • 무료 버전인 ce(Community Edition)을 찾아서 설치해야 라이선스 없이 설치 가능
  • 공식사이트의 설치가이드를 따라 설치하면 ee(Enterprise Edition)의 가이드를 보여주기 때문에 ee버전을 설치 → 주의 필요

gitlab을 설치하기 전의 사전작업 (메일서버 설치)

  • gitlab에서 사용자 가입 인증이나 관리자에게 Alerts이나 기타 이유로 메일을 보내야 하므로 메일 서버를 설치
    $ yum install postfix -y
    $ systemctl enable --now postfix
    $ systemctl status postfix


gitlab 패키지 설치하기

1. 패키지 저장소 등록

  • curl를 이용하여 gitlab package repository를 등록
    $ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

2. 패키지 설치

  • yum을 이용하여 등록된 패키지를 설치
  • EXTERNAL_URL은 지금 설치한 gitlab 웹사이트에 접속할 URL을 입력
  • 보통 도메인이 있으면 도메인명을 입력하지만 도메인이 없는 경우 일단 그냥 IP번호를 작성해도 됨
  • Port를 다른 포트로 사용한다면 port번호도 :으로 구분하여 작성 → port는 8001로 가정
  • yum install -y gitlab-ce 설치
    # EXTERNAL_URL="자신의 도메인이나 접속가능한 IP:접속할 Port번호" yum install -y gitlab-ce
    $ EXTERNAL_URL="[서버 IP]:8001 또는 도메인" yum install -y gitlab-ce

3. 설치한 gitlab 실행

  • 설치에 별 문제가 없는 경우는 설치가 완료
  • 도메인 또는 [서버 IP]:8001을 웹브라우저에 입력하면 gitlab 로그인 화면 출력되면 설치에 반은 성공


4. 설치한 gitlab에 로그인

  • 최초 접속 시 로그인 아이디는 root
  • 최초 접속시 root 비밀번호 갱신 → qwer1234
    $ gitlab-rails console -e production
    irb(main):005:0> user = User.where(id: 1).first
    => #<User id:1 @root>
    irb(main):006:0> user.password='qwer1234'
    => "qwer1234"
    irb(main):007:0> user.password_confirmation='qwer1234'
    => "qwer1234"
    irb(main):008:0> user.save
    => true
  • root 계정 로그인 성공

gitlab 설정하기

  • gitlab의 설정은 설치된 폴더에서 gitlab.rb을 변경
  • 보통 설치 위치는 /etc/gitlab/gitlab.rb → gitlab 많은 설정이 해당 파일에서 적용 가능
    $ vi /etc/gitlab/gitlab.rb

1. 업로드 파일 용량 변경

  • 한번에 업로드해야 할 파일의 용량이 큰 경우 사이즈 조정 필요 → 업로드 파일 용량을 1G로 제한
  • 앞에 주석(#)을 제거해야 반영됨
    $ vi /etc/gitlab/gitlab.rb
    ## ...중략...
    nginx['enable'] = true
    nginx['client_max_body_size'] = '1G'

2. 레파지토리 저장 디렉토리 위치 변경

  • 기본은 지정된 레파지토리 저장위치가 있으나 드라이브를 별도로 추가하여 운영하는 경우는 다른 드라이브로 저장 위치를 변경해야함

  • git_data_dirs 함수 아래에 원하는 저장 디렉토리를 지정

  • /dev/sdb1와 mount된 /data 디렉토리 아래에 gitlab_data에 저장(/data/gitlab_data)

  • /data/gitlab_data/ 디렉토리가 없다면 해당 디렉토리 생성 필요

    $ mkdir /data/gitlab_data
    
    # 레파지토리 저장 디렉토리 위치 변경
    $ vi /etc/gitlab/gitlab.rb
    ## ...중략...
    git_data_dirs({
      "default" => {
        "path" => "/data/gitlab_data"
       }
    })

3. 도메인 생성 및 SSL 적용

  • IP를 사용할 경우 SSL 사용 X

  • SSL을 사용하는 경우 도메인 필요

  • /etc/gitlab/ssl 디렉토리로 crt, key 파일 복사 필요

    $ vi /etc/gitlab/gitlab.rb
    
    external_url 'https:/도메인'
    nginx['redirect_http_to_https'] = true
    nginx['redirect_http_to_https_port'] = 80
    
    nginx['ssl_certificate'] = "/etc/gitlab/ssl/도메인.crt"
    nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/도메인.key"
    
    # 도메인 생성 및 SSL 설정 적용
    $ gitlab-ctl reconfigure



gitlab 터미널 명령어

  • 대표적인 gitlab의 터미널 명령어

1. gitlab 재설정 후 재시작

  • gitlab 설정을 변경하였다면 재설정과 재시작
    $ gitlab-ctl reconfigure

2. gitlab 시작

  • gitlab 시작
    $ gitlab-ctl start

3. gitlab 종료

  • gitlab 종료
    $ gitlab-ctl stop

4. gilab 재시작

  • gitlab 재시작
    $ gitlab-ctl restart


gitlab 삭제

  • gitlab를 삭제해야 할 경우는 아래의 명령어로 삭제
  • 남아있는 폴더나 파일이 있는경우 수동으로 삭제 필요

1. gitlab 명령어 삭제

  • gitlab 삭제
    $ gitlab-ctl uninstall
    $ gitlab-ctl cleanse
    $ gitlab-ctl remove-accounts
    $ dpkg -P gitlab-ce || sudo yum -y remove gitlab-ce

2. 수동삭제 → rm -rf 명령어로 해당 디렉토리 삭제

  • gitlab 삭제에 필요한 디렉토리 목록
    - /opt/gitlab
    - /var/opt/gitlab
    - /etc/gitlab
    - /var/log/gitlab

  • multi masters의 단일 진입점인 LoadBalancer(LB) 구성 → 사실상 HA 클러스터 구성
  • 192.168.0.100 IP를 사용하는 서버에 Nginx를 이용하여 LB 구성
  • Nginx docker 이미지를 이용하여 LB 사용 → docker 컨테이너 운영 관리에 쉬움

1. nginx 구성 파일을 만들어서 master들의 단일 진입점을 구성

# nginx로 Load Balancer할 수 있게 nginx.conf 파일 생성
$ mkdir /etc/nginx
$ cat << END > /etc/nginx/nginx.conf
events {}
stream {
  upstream stream_backend {
    least_conn;
    server 192.168.0.200:6443;
    server 192.168.0.201:6443;
    server 192.168.0.202:6443;
  }

  server {
    listen    6443;
    proxy_pass stream_backend;
    proxy_timeout 300s;
    proxy_connect_timeout 1s;
  }
}
END

2. 도커 컨테이너로 NGINX를 실행하면서 LB를 운영

# nginx 컨테이너 실행
$ docker run --name proxy -v /etc/nginx/nginx.conf:/etc/nginx/nginx.cof:ro --restart=always -p 6443:6443 -d nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
b380bbd43752: Pull complete
fca7e12d1754: Pull complete
745ab57616cb: Pull complete
a4723e260b6f: Pull complete
1c84ebdff681: Pull complete
858292fd2e56: Pull complete
Digest: sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Status: Downloaded newer image for nginx:latest
4324e6beaef0bd05d76af525fa415c4bcdf34fb807e4280e952108bf0a957630


# nginx 컨테이너가 실행 중 확인
$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                               NAMES
4324e6beaef0   nginx     "/docker-entrypoint.…"   54 seconds ago   Up 53 seconds   80/tcp, 0.0.0.0:6443->6443/tcp, :::6443->6443/tcp   proxy


# 통신이 되는지 확인
$ curl 192.168.0.100:6443

  • HAProxy는 모바일 환경이 발달 → 모바일 환경에서는 빠르고 유연한 확장성이 필수 요소
  • 최초 서비스 구축 시 확장성을 고려해서 L4/L7 스위치 분산까지는 고려
  • 지역간 분산(GSLB 구성)을 고려해서 설계하는 것은 일부 업체를 제외하고는 비용 및 경험 부재로 어려움
  • 'DNS + HAProxy + 클라우드 서비스'를 조합하여 서비스를 진행하면 적은 비용으로 GSLB 구성과 동일한 수준으로 구축 가능
  • HAProxy를 이해하기 위해서 로드 밸런서의 기본 개념과 HAProxy의 동작 방식을 이해 필요


1. 오픈 소스 로드 밸런서 HAProxy

  • HAProxy는 기존의 하드웨어 스위치를 대체하는 소프트웨어 로드 밸런서
  • 네트워크 스위치에서 제공하는 L4, L7 기능 및 로드 밸런서 기능을 제공
  • HAProxy는 설치가 쉽고, 환경 설정도 어렵지 않음
  • 서비스 이중화를 빠르게 구성 가능

2. 로드 밸런싱이란

  • 로드 밸런싱이란 부하 분산을 위해서 가상(virtual) IP를 통해 여러 서버에 접속하도록 분배하는 기능
  • 로드 밸런싱에서 사용하는 주요 기술

2.1. NAT(Network Address Translation)

  • 사설 IP 주소를 공인 IP 주소로 바꾸는 데 사용하는 통신망의 주소 변조기

2.2. DSR(Dynamic Source Routing protocol)

  • 로드 밸런서 사용 시 서버에서 클라이언트로 되돌아가는 경우 목적지 주소를 스위치의 IP 주소가 아닌 클라이언트의 IP 주소로 전달해서 네트워크 스위치를 거치지 않고 바로 클라이언트를 전달

2.3. Tunneling

  • 인터넷상에서 눈에 보이지 않는 통로를 만들어 통신할 수 있게 하는 개념
  • 데이터를 캡슐화해서 연결된 상호 간에만 캡슐화된 패킷을 구별해 캡슐화를 해제 가능


3. 로드 밸런서 동작 방식

  • 네트워크에서 IP 주소와 MAC 주소를 이용해 목적지(destination) IP 주소를 찾아가고 출발지로 되돌아오는 구조
  • 4가지의 로드 밸런서 동작 방식 설명

3.1. Bridge/Transparent Mode

  • 사용자(client)가 서비스(server)를 요청하면 L4로 전달된 목적지 IP 주소를 real server IP 주소로 변조하고, MAC 주소를 변조해서 목적지를 찾아가는 방식
    3.1.1. 요청 전달 시 변조

      사용자(client) → L4 → NAT(IP/MAC 주소 변조) → real server(server)

    3.1.2. 응답 전달 시 변조

      real server(server) → NAT → L4 → 사용자

3.2. Router Mode

  • Bridge/Transparent Mode와 유사하지만 출발지(source) MAC 주소도 변조

3.3. One Arm Mode

  • 사용자(client)가 real server(server)에 접근할 때 목적지 IP는 L4 스위치 IP를 설정
  • L4에 도달하면 L4가 클라이언트에게 받은 목적지 IP 주소를 L4 IP 주소에서 real server IP와 real server MAC 주소로 변조
  • 응답으로 되돌아가는 IP는 L4의 IP pool의 IP 주소로 변조

3.4. DSR (Direct Server Return) Mode

  • 사용자가 real server(server)에 접근할 때 출발지와 목적지의 IP 주소를 변조하지 않고, L4에서 관리하는 real server의 MAC 주소 테이블을 확인해서 MAC 주소만 변조


4. HAProxy 동작 방식

  • HAProxy는 기본적으로 reverse proxy 형태로 동작
  • 브라우저에서 사용하는 proxy는 클라이언트 앞에서 처리하는 기능 → forward proxy라 칭함
  • reverse proxy의 역할은 서비스 요청에 대해서 서버 앞 단에 존재하여, 서버로 들어오는 요청을 대신 받아서 서버에 전달하고 요청한 곳에 결과를 다시 전달하는 것
  • HAProxy의 동작 방식을 알면, HAProxy를 이용해서 어떤 구조로 확장 가능한지 알 수 있음
  • HAProxy의 동작 흐름
    1. 최초 접근 시 서버에 요청 전달
    2. 응답 시 쿠키(cookie)에 서버 정보 추가 후 반환
    3. 재요청 시 proxy에서 쿠키 정보 확인 → 최초 요청 서버로 전달
    4. 다시 접근 시 쿠키 추가 없이 전달 → 클라이언트에 쿠키 정보가 계속 존재함(쿠키 재사용)


5. HAProxy HA(High availability) 구성

  • HAProxy는 기본적으로 VRRP(Virtual Router Redundancy Protocol)를 지원
  • HAProxy는 초당 8만 건 정도의 연결을 처리 가능
  • HAProxy는 소프트웨어 기반의 솔루션이기 때문에 HAProxy가 설치된 서버에서 문제가 발생하면 하드웨어 L4보다는 불안정
  • HA 구성으로 master HAProxy에 문제가 생기는 경우에 slave HAProxy에서 서비스가 원활하게 제공되어야함

5.1. HAProxy HA(High availability) 기본 구성 설명 → HAProxy 무정지하기 위한 Active - Standby 구성

  • 가상 IP 주소를 공유하는 active HAProxy 서버와 standby HAProxy 서버가 heartbeat를 주고 받으면서 서로 정상적으로 동작하는지 여부를 확인
  • active 상태의 서버에 문제가 발생하면 standby HAProxy가 active 상태로 변경
  • 기존 active HAProxy의 가상 IP 주소를 standby HAProxy가 가져오면서 서비스가 무정지 상태를 유지
  • 1초 정도의 순단 현상은 발생


5.2. HAProxy HA(High availability) 기본 구성이 단일 HAPRoxy와 다른 점

  • 단일 HAProxy와 다른 점은 최초 접근 시 쿠키에 바로 서버 정보를 입력하지 않고 서버에서 jsessionid가 전달될 때 서버 정보를 합쳐서 전달
  • 쿠키에 정보 추가 없고 X-Forwarded-For에 정보 추가
  • 쿠키에 추가 없음
  • Jsessionid 추가
  • 서버 정보 + jsessionid를 쿠키에 추가
  • 쿠키에서 서버 판별 후 jsessionid만 전달




6. L4 + HAProxy HA 구성 및 Global 환경에서 구성

  • HAProxy와 기존 하드웨어 스위치를 이용해서 더 확장된 형태의 고가용성 구조를 설계 가능

6.1. 하드웨어 L4 + HAProxy

  • 클라이언트에서 연결되는 부분은 가상 IP 주소 + L4의 구성으로 하드웨어 이중화를 구축
  • L4에서 서버 앞 단에 HAProxy를 구축해서 HAProxy를 더 확장할 수 있는 구조로 설계 가능
  • L4 + HAProxy 구성


6.2. GSLB(Global Service Load Balancing) + HAProxy

  • global 서비스가 증가되면서 IDC 간 이중화 및 global 환경에서의 무정지 서비스를 위한 DR(Disaster Recovery, 재해 복구) 시스템 구축이 필수 요구사항
  • GSLB + HAProxy를 이용하면 global한 무정지 서비스 구축이 가능
  • GSLB 구축에 L4 스위치를 사용할 수도 있지만 GSLB 구성용 L4는 고가의 장비
  • L4를 이용한 GSLB 대신 DNS(BIND)를 이용한 구축 형태 → Global 환경에서 GSLB+HAProxy 구성
    1. 클라이언트에서 DNS로 도메인 조회
    2. 근거리 IDC 정보 전달




7. HAProxy Ncloud 적용 사례

  • 사내 Ncloud 시스템의 DNS RR을 HAProxy로 교체 → DNS를 HA 구성
  • DNS를 HA 구성함으로써 기존 DNS로 구성할 때보다 서버 증설 및 삭제에 있어 유연성이 증가, 서비스 안정성 증가
  • DNS를 HA로 구성함으로써 애플리케이션 서버에서 클라이언트 IP 주소를 찾아서 처리하는 로직에 문제가 발생
    • 문제 발생 이유 → 사용자의 요청이 HAProxy를 거치면서 클라이언트 IP 주소 정보가 HAProxy의 정보로 변조
    • 해결 방안 → 애플리케이션 서버가 HTTP 헤더에서 클라이언트 IP 주소를 조회하면 실제 클라이언트 IP 주소가 반환되도록 보완
      1. HAProxy에서 제공하는 X-Forwarded-For 옵션을 적용
      2. Apache에서 mod_rpaf 모듈을 설치




8. HAProxy 어드민 페이지

9. HAProxy 성능

  • HAProxy가 설치되는 서버의 사양에 따라 어느 정도 성능이 제공되는지 확인하기 위해 성능을 측정
  • nGrinder(http://www.nhnopensource.org/ngrinder/) 테스트 결과와 해외 사례를 공유

1. 해외 운영 사례

  • 서버 사양(저사양) : Dell PowerEdge 2850, Intel PCI3 4x Gigabit Fiber card (CPU 1.6GHz dual core x 1)
  • 제공 서비스: 영화 다운로드 서비스
  • 결과: 일별 2.47TB 전송 + 81일 동안 운영

2. nGrinder 테스트

  • 환경: HAProxy (1core), apache 서버 2대
  • 결과: 6,603 TPS


3. 해외 성능 사례

  • 듀얼 CPU 환경에서 초당 2만 세션까지 연결 가능 → CPU 성능이 높아지면 연결 가능 세션 수 증가
  • 초당 1만 건 세션 연결 시 응답에 100밀리초(ms) 소요 → 최대 연결 개수는 하드웨어의 RAM과 file descriptor에 의해 결정됨 → 세션당 16KB 사용 시 6만 세션당 1G RAM 필요




HAProxy 설치 및 옵션 → HAProxy의 중요 옵션 설명

1. HAProxy 운영 시 필요한 옵션

  • HAProxy의 경우 튜닝 옵션을 비롯하여 매우 많은 옵션을 지원 → 실제 구축 시 필요한 옵션만 설명
  • 옵션을 변경하려면 haproxy.cfg 파일을 수정 필요
  • HAProxy 설정 매뉴얼 → https://runebook.dev/ko/docs/haproxy/-index-

2. HAProxy 옵션

  • 전역 옵션(global) 섹션과 기본 옵션(defaults) 섹션, 프록시 옵션 섹션(listen)의 주요 옵션에 관한 설명
  • global # 전역 옵션 섹션
    1. daemon → 백그라운드 모드(background mode)로 실행
    2. log → syslog 설정
    3. log-send-hostname → hostname 설정
    4. uid → 프로세스의 userid를 number로 변경
    5. user → 프로세스의 userid를 name으로 변경
    6. node → 두 개 이상의 프로세스나 서버가 같은 IP 주소를 공유할 때 name 설정(HA 설정)
    7. maxconn → 프로세스당 최대 연결 개수
  • Defaults # 기본 옵션 섹션
    1. log → syslog 설정
    2. maxconn → 프로세스당 최대 연결 개수
  • listen
    1. listen webfarm 10.101.22.76:80→ listen haproxy name ip:port
    2. mode http → 연결 프로토콜
    3. option httpchk → health check
    4. option log-health-checks → health 로그 남김 여부
    5. option forwardfor → 클라이언트 정보 전달
    6. option httpclose → keep-alive 문제 발생 시 off 옵션
    7. cookie SERVERID rewrite → 쿠키로 서버 구별 시 사용 여부
    8. cookie JSESSIONID prefix → HA 구성 시 prefix 이후에 서버 정보 주입 여부
    9. balance roundrobin → 순환 분배 방식
    10. stats enable → 서버 상태 보기 가능 여부
    11. stats uri /admin → 서버 상태 보기 uri
    12. server xvadm01.ncli 10.101.22.18:80 cookie admin_portal_1 check inter 1000 rise 2 fall 5 → real server 정보(server [host명] [ip]:[port] cookie [서버쿠키명] check inter [주기(m/s)] rise [서버구동여부점검횟수], fall [서비스중단여부점검횟수])

3. balance 옵션

  • 로드 밸런싱의 경우 round robin 방식을 일반적으로 사용하지만 다른 여러 방식이 있음 → 옵션에 적용할 수 있는 로드 밸런싱 알고리즘
    1. roundrobin → 순차적으로 분배(최대 연결 가능 서버 4128개)
    2. static-rr → 서버에 부여된 가중치에 따라서 분배
    3. leastconn → 접속 수가 가장 적은 서버로 분배
    4. source → 운영 중인 서버의 가중치를 나눠서 접속자 IP를 해싱(hashing)해서 분배
    5. uri → 접속하는 URI를 해싱해서 운영 중인 서버의 가중치를 나눠서 분배(URI의 길이 또는 depth로 해싱)
    6. url_param → HTTP GET 요청에 대해서 특정 패턴이 있는지 여부 확인 후 조건에 맞는 서버로 분배(조건 없는 경우 round robin으로 처리)
    7. hdr → HTTP 헤더 에서 hdr()으로 지정된 조건이 있는 경우에 대해서만 분배(조건 없는 경우 round robin으로 처리)
    8. rdp-cookie → TCP 요청에 대한 RDP 쿠키에 따른 분배

참고 URL : https://d2.naver.com/helloworld/284659


+ Recent posts