nGrinder란?


nGrinder는 네이버에서 성능 측정 목적으로 jython(JVM위에서 파이썬이 동작)으로 개발 된 오픈소스 프로젝트이며, 2011년에 공개 하였습니다. 바닥부터 개발을 한 것이 아니라 The Grinder라는 오픈소스 기반에서 개발 하였습니다. nGrinder는서버에 대한 부하를 테스트 하는 것이므로 서버의 성능 측정이라고도 할 수 있습니다. 성능 측정이란 것은 실제 서비스에 투입 되기 전, 실제와 같은 환경을 만들어 놓고 서버가 사용자를 얼마 만큼 수용할 수 있는지를 실험 할 때 사용합니다. 만약 이와 같은 테스트를 하지 않으면, 엔지니어가 동시 접속자를 1000명정도로 예상하고 이에 맞는 설정을 구성하는데 예상에 넘는 동시 접속자가 발생해 버리면 서버가 죽어버려 서비스를 할 수 없는 문제가 있습니다. 이를 방지하기 위해 본 서비스에 앞서 테스트를 해 서버의 성능을 테스트 하는 것입니다. 

nGrinder Architecture


nGrinder는 Controller, Agent, Targer 서버로 나눠져 있습니다.

Controller:

  • 퍼포먼스 테스팅(부하테스트)를 위해 웹 인터페이스를 제공
  • 테스트 프로세스를 체계화
  • 테스트 결과를 수집해 통계로 보여줌

Agent: Controller의 명령을 받아 실행합니다.

  • agent 모드가 실행될 때, target이 된 머신에 프로세스와 스레드를 실행시켜 부하를 발생
  • monitor 모드가 실행되면 대상 시스템의 CPU와 Memory를 모니터링


agent들이 실행될 때, agent들은 컨트롤러와의 연결을 시도합니다. 그것들은 AgentControllerServer 구성요소와 연결이 됩니다. AgentControllerServer는 현재 agent pool을 관리합니다. 유저가 performance test를 시작을 할 때마다, agent들을 조절하는 새로운 콘솔이 생성되고, 요구하는 agent의 수는 AgentControllerServer로부터 조절됩니다. 이 콘솔(SingleConsole이라는 이름의 콘솔은 그라인더 내의 콘솔과 차별화 됩니다.) test script와 test resources를 할당받은 다수의 agent들에게 전송하고 test가 끝날 때까지 test flow 통제를 시작합니다.  이 테스트가 끝난 이후에, 테스트에 사용된 agents들은 AgentControllerServer로 돌아갑니다. 이와 마찬가지로 SingleConsole 또한 ConsoleManager에게 돌아갑니다.

nGrinder와 Grinder사이의 가장 큰 차이점은 nGrinder는 컨트롤러에서 다수의 콘솔 인스턴스와 agents들을 유지하는 것입니다. 각각의 콘솔은 다른 콘솔로부터 독립적이고, 모든 콘솔들은 동시에 실행할 수 있습니다. 많은 agent들은 미리 연결이 될 수 있고, agent가 필요하여 요청을 받을 때마다 언제든지 할달 될 수 있습니다. grinder와 같지 않게, nGrinder는 agent 머신의 활용도를 극대화 하기 위해 개발되었습니다.

'Performance Center' 같이 잘 알려진 부하 테스트 툴은 사용자가 테스트를 시작할 때 agent의 가용성을 보장하기 위해 테스트 예약 기능을 갖습니다. 그러나 예약 기능은 agent 활용도 문제의 원인이 됩니다. 사람들은 실제로 테스트를 하지 않는 동안에도 예방 조치로 에이전트를 보유하는 경향이 있음을 나타냈습니다. 이러한 조사 결과로, 평균적으로 agent의 CPU 활용도는 10% 미만인 것으로 결과가 나왔습니다.

이러한 이유로, 예약 대신, nGrinder는 실제 테스트가 실행될 때, 테스트를 위해 동적으로 agents들을 할당하기 위해 다수의 test와 동적인 agent 할당이 가능하도록 하였습니다. 이러한 것은 nGrinder를 모든 부하 테스트 툴 가운데서, unique한 부하 테스트 툴로 만들었습니다.  agent들의 수가 상대적으로 적게 가지고 있으면, 다수의 사용자들은 다수의 테스트를 동시에 실행할 수 있습니다. 동시에 실행할 수 있는 테스트의 수는 free agent(동적으로 할달될 수 있는 agent)의 수에 의존합니다.

nGrinder 성능 향상

nGrinder는 최대한 OS설정과 독립적으로 운영되도록 구현되어 있습니다. 따라서 agent 성능을 최적화 하기 위한 OS 튜닝 포인트가 아래 리스트를 제외하고는 거의 없습니다.

  • ulimit 파일 오픈 가능 카운트를 1만 이상 유지
    • 성능 테스트시, 소켓을 많이 열 수 있기 때문
  • OS영역을 제외하고 3G정도의 Free 메모리를 유지할 것
  • socket linger option 설정을 조정하여, 소켓이 사용 후 바로 반납 되도록 할 것
    • 스크립트의 socket linger를 설정하지 않으면 OS TCP 설정을 따르기 때문에 둘 중 하나를 선택
    • jython socket 패키지를 사용할 경우 스크립트 상에 다음과 같이 설정하면 가능
      •  clientsock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', l_onoff, l_linger))

또한 controller의 성능 향상을 위해 db를 변경해도 개선이 되지 않습니다. (e.g, embedded db -> cubrid)


nGrinder 권장 사양


controlleragentmonitor
Core1~2 Core2 Core1
RAM2GB4GB(free memory 3GB)50MB

agent의 경우, Groovy로 sleep time 없이 단순 HTTP CALL 경우, 6000 vuser까지 15분 가냥 1개의 agent 동작 가능

실제 유저 행위를 시뮬레이션하여 10초 씩 thinktime을 준다면, agent당 1만 vuser(thread)를 견딜 수 있음.

agent는 메모리가 가장 중요한 이슈

nGrinder 사용 용어


Controller:

  • 퍼포먼스 테스팅(부하테스트)를 위해 웹 인터페이스를 제공
  • 테스트 프로세스를 체계화
  • 테스트 결과를 수집해 통계로 보여줌

Agent: Controller의 명령을 받아 실행합니다.

  • agent 모드가 실행될 때, target이 된 머신에 프로세스와 스레드를 실행시켜 부하를 발생
  • monitor 모드가 실행되면 대상 시스템의 CPU와 Memory를 모니터링

Target: 부하 테스트를 받는 머신입니다.

vuser: virtual user로 동시에 접속하는 유저의 수를 의미합니다. 

  • virtual user를 구하는 공식은 vuser=agent*process*thread

TPS: 초당 트랜젝션의 수 - 초당 처리 수  (Tranjaction Per Second)

  • 위 공식으로 에이전트 10개, 프로세스 10개, 각 스레드 300이라면 30,000개의 vuser(thread)가 지속적으로 요청하는 상황. 그래서 30,000번의 요청을 서버에서 1초 미만으로 처리한다면 TPS는 30,000이상이 될 것이고, 30,000번의 요청을 서버에서 2초 이상 으로 처리한다면 TPS는 15,000이하가 됩니다.

트랜잭션:  HTTP Request가 성공할 때마다, 트랜잭션의 수가 1씩 증가합니다.

Peak TPS: 초당 처리 수의 최대치

Response Time: 사용자가 request한 시점(클릭한 시점)에서 시스템이 Response를 할 때까지의 시간

Think Time: 사용자에게 전달된 정보는 사용자가 해당 내용을 인지하고 다음 동작을 취할 때까지의 생각하는 시간이 필요한 시간

nGrinder 설치


nGrinder는 자바기반이기 때문에 사전에 설치할 것들이 필요합니다. nGrinder3.3 버젼에서 필요한 스펙은 아래와 같습니다.

Oracle JDK 1.6 이상 또는 오픈 JDK 1.7 이상, 톰캣 6.X 이상이 필요합니다. 이 테스트에서는 우분투를 사용하기 때문에 우분투 설치 시, TOMCAT 서버를 선택, 설치하여 넘어가겠습니다.

Controller 설치

아래의 명령어로 webapps로 이동하여 내부의 파일 및 폴더를 전부 지운 다음, ngrinder를 설치합니다.

$ cd /var/lib/tomcat7/webapps
$ sudo rm -rf ROOT
$ sudo wget http://sourceforge.net/projects/ngrinder/files/ngrinder-3.3/ngrinder-controller-3.3.war


1 직접 실행하기

nGrinder는 편리하게 한 개의 패키지로 구성하다 보니 꽤 많은 Perm Gen 메모리를 필요로 합니다. 왜냐하면 많은 라이브러리(SVNKit, Maven, Groovy, Jython 등)을 하나로 포함하게 되어 메모리 요구량이 많아 졌기 때문입니다.

아래 명령어를 실행시켜 최대 PermSize를 정해 실행시킵니다

java -XX:MaxPermSize=200m -jar  ngrinder-controller-3.3.war --port 8081

만약 포트를 기본포트인 8080이 아닌, 다른 포트를 사용하고 싶을 경우, --port 포트번호 입력을 하면 됩니다.

2016-01-25 14:58:38,257 INFO  Config.java:115 : nGrinder is starting...
2016-01-25 14:58:38,288 INFO  Config.java:310 : nGrinder home directory:/home/controller/.ngrinder.
2016-01-25 14:58:38,316 INFO  Config.java:341 : nGrinder ex home directory:/home/controller/.ngrinder_ex.
2016-01-25 14:58:38,376 INFO  Home.java:116 : /home/controller/.ngrinder/org_conf
INFO 1/25/16 2:58 PM:liquibase: Reading from DATABASECHANGELOG
INFO 1/25/16 2:58 PM:liquibase: Reading from DATABASECHANGELOG
2016-01-25 15:00:32.613:INFO:/:Initializing Spring FrameworkServlet 'appServlet'
2016-01-25 15:00:49.364:INFO::Started SocketConnector@0.0.0.0:8801

위와 같이 로그를 출력했다면, http://localhost:8081로 접근할 수 있습니다.



2 톰캣에 설치하기

다운로드가 성공 되었으면, http://{설치IP}:8080/ngrinder-controller-3.3로 웹에서 접속할 수 있습니다. 이처럼 접근이 불편할 시, ngrinder-controller-3.3.war 파일을 ROOT.war로 변경할 경우, http://{설치IP}:8080으로 접속할 수 있습니다.


nGrinder 컨트롤러는 메모리를 많이 쓰기 때문에 메모리 설정이 필요합니다. 아래 설정을 안할 경우, 몇 가지 관리자 기능이 동작하지 않습니다. 

  • (리눅스 사용 시) /usr/share/tomcat7/bin/catalina.sh 또는 (윈도우즈 사용 시) 톰캣의 /bin/catalina.bat 파일의 맨 처음에 아래를 입력해 줍니다.
# catalina.sh
JAVA_OPTS="-Xms600m -Xmx1024m -XX:MaxPermSize=200m"    # for catalina.sh
 
# catalina.bat
set JAVA_OPTS=-Xms600m -Xmx1024m -XX:MaxPermSize=200m   # for catalina.bat


간혹 어떤 시스템은 다수의 IP를 가지고 있는 경우가 있습니다. nGrinder는 자동으로 이들 중 하나를 agent의 접속을 기다릴 IP로 선정합니다. 만약 특정 IP를 접속 IP로 설정하고 싶으면 다음과 같은 필드를 ${NGRINDER_HOME}/system.conf 에 기재하면 됩니다.

ngrinder.controller.ipaddress=에이전트가 접속할 IP Address

다음 아래 파일을 실행합니다.

$ /usr/share/tomcat7/bin/startup.sh


다음 톰캣을 재시작 합니다.

$ sudo service tomcat7 restart

nGrinder 설치 - docker


앞으로 controller, agent는 docker에 설치하는 것을 설명하겠습니다.

Controller 설치

아래 명령어로 controller의 이미지를 받습니다.

$ docker pull ngrinder/controller:3.3

다음 아래의 명령어로 컨테이너를 생성합니다.

$ docker run -d -v ~/.ngrinder:/root/.ngrinder -p controller_web_port:80 -p 16001:16001 -p 12000-12009:12000-12009 ngrinder/controller:3.3

controller_web_port는 사용자가 원하는 포트 번호를 입력하면 됩니다. (ex. 8080)



default id와 pw는 admin입니다.

포트

Agent : Any ==> Controller : 16001 
Agent : Any ==> Controller : 12000 ~ 1200x(the number of concurrent tests allowed) 

==>은 단방향 통신을 뜻합니다.

16001 포트는 테스트를 하지 않은 에이전트가 컨트롤러에게 "할 일없으니 테스트 가능" 이란 메세지를 알려주는 포트입니다. 또한 컨트롤러는 "테스트가 실행하는데 해당 테스트는 1200x에서 발생하니, 해당 포트에 접속해서 테스트 실행 준비"라는 메세지를 에이전트에게 지시를 합니다.

12000~1200x 포트는 "테스트 실행, 테스트 종료"와 같은 컨트롤러 명령어와 에이전트별 테스트 실행 통계를 초별로 수집하는 포트입니다.

Agent 설치

아래 명령어로 agent의 이미지를 받습니다.

$ docker pull ngrinder/agent:3.3

다음 명령어로 agent 컨테이너를 생성합니다.

$ docker run -d -e 'CONTROLLER_ADDR=controller_ip:controller_web_port' ngrinder/agent:3.3
controller_ip: controller의 아이피
controller_web_port: 앞서 controller의 컨테이너르 생성할 때, 정한 포트



'nGrinder' 카테고리의 다른 글

[nGrinder]Instrumentation  (0) 2016.05.21
[nGrinder]스크립트(Groovy) 작성법  (0) 2016.05.21
[nGrinder] 사용법 및 테스트  (0) 2016.05.21
[nGrinder]nGrinder란? & docker 설치 방법  (0) 2016.05.21

base.py 

"""
Django settings for polalis project.

Generated by 'django-admin startproject' using Django 1.8.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'p5^ykf!%2(8q3lxqfi_+&ivv*xy7!77bcjc9-9^uw#eopu6e7o'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


PROJECT_APPS = (
    'account',
    'bankbook',
    'cashbook',
    'cashreceipt',
    'credit',
    'ebill',
    'etaxbill',
    'finment',
    'library',
    'login',
    'polalis',
    'process',
    'scrapping',
    'situation',
    'slipfix',
    'statement',
    'trade',
    'trialbalance',

)

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_jenkins',
    'rest_framework',
    'rest_framework_swagger',
    'django_crontab',
    'account',
    'bankbook',
    'cashbook',
    'cashreceipt',
    'credit',
    'ebill',
    'etaxbill',
    'finment',
    'library',
    'login',
    'polalis',
    'process',
    'scrapping',
    'situation',
    'slipfix',
    'statement',
    'trade',
    'trialbalance',
)

JENKINS_TASKS = (
    'django_jenkins.tasks.run_pylint',
)

PYLINT_LOAD_PLUGIN = (
    'pylint_django',
)
'''
REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}
'''

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'polalis.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, '../templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

CRONJOBS = [
    ('*/10 * * * *', 'scrapping.cron.scrapping_cron', '>> /tmp/scrapping_cron.log')
]

WSGI_APPLICATION = 'polalis.wsgi.application'



SWAGGER_SETTINGS = {
    'exclude_namespaces': [],
    'api_version': '0.1',
    'api_path': '/',
    'enabled_methods': [
        'get',
        'post',
        'put',
        'patch',
        'delete'
    ],
    'is_authenticated': False,
    'is_superuser': False,
    'unauthenticated_user': 'django.contrib.auth.models.AnonymousUser',
    'permission_denied_handler': None,
    'info': {
        'title': 'Polaris API',
    },
    'doc_expansion': 'none',
}

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Seoul'

USE_I18N = True

USE_L10N = True

USE_TZ = True



# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, '../static'),
    './static/',
)


dev.py

from polalis.settings.base import *

CRONTAB_DJANGO_SETTINGS_MODULE = 'polalis.settings.dev'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'polaris',
        'USER': 'sunrise',
        'PASSWORD': '1234',
        'HOST': 'postgres',
        'PORT': '5432'
    },
    'trialbalance': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'polaris_0108',
        'USER': 'sunrise',
        'PASSWORD': '1234',
        'HOST': 'postgres',
        'PORT': '5432'
    },
    'cashbook': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'cashbook',
        'USER': 'sunrise',
        'PASSWORD': '123',
        'HOST': 'postgres',
        'PORT': '5432'
    },
    'papyrus': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'polaris_papyrus',
        'USER': 'sunrise',
        'PASSWORD': '1234',
        'HOST': 'postgres',
        'PORT': '5432'
    },
    'polaris_0108': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'polaris_0108',
        'USER': 'sunrise',
        'PASSWORD': '1234',
        'HOST': 'postgres',
        'PORT': '5432'
    }
}


base.py는 공통적으로 사용하는 부분을 작성하는 파일입니다.

local.py, dev.py 등 세팅환경을 분리하여 작성할 때 사용되며 from polalis.settings.base import * 와 같이 base.py를 참조합니다.

파일경로

SUNRISE(프로젝트) / SUNRISE (앱) / settings(폴더) / base.py, server.py, __init__.py (빨간색 부분은 생성해야함)

세팅

  1. 기존에 사용하던 settings.py 안의 코드를 local.py에 전부 복사/붙여넣기합니다.
  2. TEMPLATES =[  { ... 'DIRS': [os.path.join(BASE_DIR'../../templates')] ... } ] 이와 같이 구성되어 있다면 DIRS를 다음과 같이 변경합니다.
    1. -> 'DIRS': [os.path.join(BASE_DIR'../templates')]
  3. STATICFILES_DIRS = ( os.path.join(BASE_DIR"../static"), ... 이와 같이 구성되어 있다면 os.path.join의 경로를 다음과 같이 변경합니다.

    1. -> os.path.join(BASE_DIR"../static")

  4. local.py는 로컬에서 실행하기 위해 설정한 파일이고, dev.py는 서버에서 실행시키기 위해 만든 파일입니다. 현재 server에서 변경할 부분은 databases의 속성밖에 없으므로, databases의 속성만 변경합니다. (위 코드 참조)
  5. /SUNRISE 앱 내의 wsgi.py 폴더를 살펴보면 os.environ.setdefault("DJANGO_SETTINGS_MODULE""SUNRISE.settings") 이렇게 실행 시, default로 참조할 settings 파일 경로 부분을 다음과 같이 변경합니다.
    1. -> os.environ.setdefault("DJANGO_SETTINGS_MODULE""SUNRISE.settings.local") - 서버일 경우 local 대신 dev를 입력합니다.

실행법

  • 파이참에서 실행할 경우

    1. 상단 메뉴 탭의 Run - Run - Edit Configrations... - Environment - Environment variables: 우측의 ... 버튼 클릭 - DJANGO_SETTINGS_MODULE의 Value값을 SUNRISE.settings.local로 변경


  • 터미널에서 실행할 경우

    • 터미널 창에서 python manage.py runserver (호출할 URL) -- settings파일이 존재하는 폴더=project.폴더.실행시킬 파일
      • e.g,) python manage.py runserver ip주소:80 -- settings=SUNRISE.settings.server


이전 장고의 settings.py 파일을 분리했던 것과 같은 이유로 환경변수를 분리하는 방법을 설명하겠습니다.


코드

import sys


def get(func):
    try:
        for i in range(1, len(sys.argv)):
            settings_str = "--settings="
            settings_index = sys.argv[i].find(settings_str)
            # 받은 argument 중 좌변이 환경변수 분리 키 값일 경우, 우변의 값을 경로를 저장합니다.
            if settings_index != -1:
                # 입력받은 값을 변수에 저장
                actions = sys.argv[i][settings_index + len(settings_str):]

        # 받은 값으로 import로 선언
        tmp = __import__(actions)
        # 선택할 settings 파일명만 선택
        env_name = actions[actions.rfind(".") + 1:]
        # 위에서 구한 함수이름으로 호출
        instance = getattr(tmp, env_name)

    except Exception as e:
        # 아무 입력안될 시, 에러를 내고 프로그램 종료
        print(e)
        print("입력한 파라미터를 확인해주세요")
        exit()

    try:
        # 파라미터로 받은 값을 사용해 동적으로 함수 및 변수들을 호출
        return getattr(instance, func)

    except Exception as e:
        raise e


databases = {
    'default': {
        'DBNAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': '1234',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    },
	'other': {
		'DBNAME': 'postgres2',
        'USER': 'postgres',
        'PASSWORD': '1234',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    }
} 


from env import get

# default로 정의되어 있는 데이터베이스 정보를 호출하고 싶은 경우,
get('databases')['default']

파일경로

untitled(패키지) / settings(폴더) / base.py, local.py, ...  (빨간색 부분은 생성해야함)


세팅

직접 파일생성하여 실행할 경우

  1. env.py를 생성하여 위에 작성된 코드를 넣습니다.
  2. main이나 데이터베이스를 호출하는 파일에서 from env import get를 넣어줍니다.
  3. get() 함수를 사용

pip로 다운로드받아서 사용할 경우

virtualenv를 사용하는데 터미널에서 그냥 해당 명령어를 실행시켜 다운로드 받을 경우, 파이썬의 인터프리터는 virtualenv를 바라보고 있는데 설치는 virtualenv가 아닌 파이썬 자체에 모듈이 설치되기 때문에 인식을 할 수 없습니다.

virtualenv를 사용할 경우

  1. 터미널 실행
  2. 사용하고 있는 virtualenv 폴더로 이동
  3. source bin/activate 명령어 실행
  4. pip3 install --trusted-host ip주소 --index-url http://ip주소/simple/ env 명령어 실행

  5. from env import get를 추가하여 get()함수를 사용

virtualenv를 사용하지 않는 경우

  1. 터미널 실행
  2. pip3 install --trusted-host ip주소 --index-url http://ip주소/simple/ env 명령어 실행
  3. from env import get를 추가하여 get()함수를 사용

실행법

파이참에서 실행할 경우

상단 메뉴 탭의 Run - Run... - Edit Configrations... Script parameters에 환경변수가 들어있는 폴더 및 파일명을 작성합니다.

예) 

현재버전은 Script Parameters 부분에 --settings=settings.base 로 입력해야 합니다.


터미널에서 실행할 경우

python 실행파이썬파일 폴더.파일 과 같은 형식으로 호출합니다.

예) python main.py --settings=settings.base

사용법

settings

  • local.py

main.py

databases = {
    'default': {
        'DBNAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': '1234',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    },
	'other': {
		'DBNAME': 'postgres2',
        'USER': 'postgres',
        'PASSWORD': '1234',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    }
} 


from env import get
 
print(env('databases')['default'])


와 같이 폴더 구조와 local.py, main.py의 코드가 잡혀있다고 가정합니다.

위 세팅법을 통해 먼저 설치를 한 후, main.py에 from env import get를 추가합니다.

다음 터미널에서 python main.py --settings=settings.local을 입력하여 main.py를 실행시킵니다.

실행결과는 local.py 파일의 databases라는 dict 변수를 읽고 그 중, default에 정의되어 있는 DB 정보를 출력하게 됩니다.

privated pypi 서버

privated pypi서버에 올라온 패키지들의 목록이 궁금하면 등록ip주소/simple url을 입력하면 올라와있는 서버의 패키지를 확인할 수 있습니다.



아래와 같은 dict 타입의 변수가 존재한다고 할 때, 첫 번째와 두 번쨰의 차이점은 무엇일까?

dict_test={"a":"1","b":"2"}
#1
dict_test.clear()
#2
dict_test={}


두 코드 기능은 "지운다" 라는 점에 있어 동일합니다. 하지만 dict_test라는 변수를 재사용할 때, 큰 차이점이 있습니다.


#1의 경우입니다.

dict_test={"a":"1","b":"2"}
 
temp_dict=dict_test
 
dict_test.clear()
print(temp_dict)
 
결과: {}


#2의 경우입니다.

dict_test={"a":"1","b":"2"}
 
temp_dict=dict_test
 
dict_test={}
print(temp_dict)
 
결과: {"a":"1","b":"2"}


#2의 경우, dict_test={}를 할 때, 새로운 {} (비어있는 dict 타입)을 새로 생성하고 dict_test의 값을 {}에 할당합니다. 이 때, temp_dict는 값이 할당되어 있는 예전 변수의 값인 {"a":"1","b":"2"}를 가리키고 있기 때문에, dict_test를 추가하거나 삭제해도 그대로 값이 존재합니다.

반면 #1의 경우, dict_test.clear()를 할 경우, dict_test와 temp_dict 둘 다 가리키고 있는 point의 값을 지워버리기 때문에 temp_dict에 값을 할당하고 clear()를 해도 가리키고 있는 point의 값이 존재하지 않게 됩니다.


정의

  • Docker Container Image를 저장하기 위한 저장소이다.
  • 기본적으로 hub.docker.com 에서 이미지를 다운로드 할 수 있고, 비공개된 저장소를 사용하려면 비용을 지불해야 합니다.
  • Docker에서 개인저장소를 구축할 수 있는 시스템을 공개하였고, 저장소 시스템을 Docker Registry라고 부릅니다.
  • Docker Registry 역시 Docker로 제작 되었습니다.

설치

Docker 레지스트리에는 로그인 기능이 없습니다. 따라서 Nginx의 기본 인증(Basic Authentication) 기능을 사용해야 합니다. HTTP 프로토콜에서는 인증을 지원하지 않으므로 반드시 HTTPS 프로토콜을 사용해야 합니다.

SSL 인증서

HTTPS를 사용하기 위해서는 SSL 인증서가 필요한데, 인증서가 없다면 아래의 명령어로 사설 인증서를 만들어서 등록해야 합니다. 사설 인증서 생성시 인증서 서명 요청(Certificate signing request) 파일을 생성하는데 아래의 필요한 정보를 입력해야합니다.

  • Country Name: 국가 코드입니다. 대문자로 KO를 입력합니다.
  • State or Province Name: 주 또는 도입니다. 자신의 상황에 맞게 입력합니다.
  • Locality Name: 도시입니다. 자신의 상황에 맞게 입력합니다.
  • Organization Name: 회사 이름을 입력합니다.
  • Organizational Unit Name: 조직 이름을 입력합니다.
  • Common Name: Docker Registry 실행하는 서버의 도메인입니다. 정확하게 입력하지 않으면 인증서를 사용해도 로그인할 때 에러가 발생합니다. 사용할 도메인을 docker.example.com 입력합니다.
  • Email Address: 이메일 주소입니다.

Step1

$ openssl genrsa -out docker.example.com.key 2048

Step2

$ openssl req -new -key docker.example.com.key -out docker.example.com.csr

Step3

$ openssl x509 -req -days 365 -in docker.example.com.csr -signkey docker.example.com.key -out docker.example.com.crt 

Step4

사설 인증서 사용시 다른 시스템에서 Docker Registry에 접근하기 위해 아래처럼 생성한 인증서를 등록해야 합니다.

Ubuntu 인증서 등록

$ sudo cp docker.example.com.crt /usr/share/ca-certificates/
$ echo "docker.example.com.crt" | sudo tee -a /etc/ca-certificates.conf
$ sudo update-ca-certificates

CentOS 인증서 등록

$ sudo cp docker.example.com.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust enable
$ sudo update-ca-trust extract


Step5

$ sudo service docker restart 

사용자 계정 설정

사용자 계정을 설정하기 위해서 .htpasswd 파일을 생성해야 합니다.

Step1

Ubuntu 패키지 설치

$ sudo apt-get install apache2-utils 

CentOS 패키지 설치

$ sudo yum install httpd-tools


Step2

$ htpasswd -c .htpasswd <아이디 입력>
New password:<비밀번호 입력>
Re-type new password:<비밀번호 입력>
Adding password for user <아이디 입력> 

Nginx 설정

아래의 내용을 nginx.conf 이름의 파일을 만들어야 합니다.

worker_processes  4; 
events {
    worker_connections  1024;
}
 
http {
    server {
        listen       443;
        server_name  docker.example.com;
 
        ssl on;
        ssl_certificate /etc/docker.example.com.crt;
        ssl_certificate_key /etc/docker.example.com.key;
 
        proxy_set_header Host           $http_host;
        proxy_set_header X-Real-IP      $remote_addr;
        proxy_set_header Authorization  "";
 
        client_max_body_size 0;
 
        chunked_transfer_encoding on;
 
        location / {
            proxy_pass          http://docker-registry:5000;
            proxy_set_header    Host  $host;
            proxy_read_timeout  900;
 
            auth_basic            "Restricted";
            auth_basic_user_file  .htpasswd;
        }
    }
} 

Docker Image Pull

docker registry와 nginx 이미지를 다운로드 합니다.

$ sudo docker pull registry
$ sudo docker pull nginx

Docker Run

Docker를 실행합니다.

$ sudo docker run -d --name=docker-registry \
    -v /home/registry:/tmp/registry \
    registry
 
$ sudo docker run -d --name=nginx \
    -v ./nginx.conf:/etc/nginx/nginx.conf \
    -v ./.htpasswd:/etc/nginx/.htpasswd \
    -v ./docker.example.com.key:/etc/docker.example.com.key \
    -v ./docker.example.com.crt:/etc/docker.example.com.crt \
    --link=docker-registry:docker-registry \
    -p 443:443 \
    nginx

Docker Login

위의 설정된 정보로 로그인을 합니다.

$ sudo docker login https://docker.example.com
Username: <아이디 입력>
Password: <비밀번호>
Email:
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded 


우분투14.04 설치시 postgres를 선택해 설치할 수 있습니다.


권한을 postgres로 변경한 다음, postgres 데이터베이스에 들어갑니다.

1
2
$ sudo su postgres
$ psql -d postgres -U postgres
cs

psql을 입력하면 postgres데이터베이스에 현재 로그인된 계정으로 로그인을 시도합니다. 


1
2
3
postgres=# create user test with password '1234';
CREATE ROLE
 
cs

postgres 데이터베이스에 비밀번호 1234를 가진 test라는 유저를 생성합니다. 


1
2
3
postgres=# create database test;
CREATE DATABASE
 
cs

test라는 데이터베이스를 생성합니다.


다음 /etc/psotgresql/9.3/main/postgresql.conf를 편집기로 열어서 #listen_address='localhost'부분을 listen_address='*'로 바꿉니다.


/etc/psotgresql/9.3/main/pg_hba.conf를 편집기로 엽니다.


마지막 부분을 아래와 같이 변경해줍니다.

1
2
3
# TYPE DATABASE USER ADDRESS METHOD
local   all                    md5
host    all     all  0.0.0.0/32 md5
cs

만약 

local  postgres         peer 라는 줄이 있으면 지웁니다.

다음 sudo service postgresql restart 또는 sudo /etc/init.d/postgresql restart로 재시작합니다.


pgadmin3을 실행해 서버를 추가합니다.





+ Random Posts