kubernetes 를 사용하면서 불편했던 점 중에 하나는 서비스 로깅이었다. 로컬에서 가장 자주 사용하던 명령어가 바로...

 

> kubectl logs -n namespace -f <pod-name>

 

배포(deployment) 하고 나서 로깅/디버깅을 위해 pod 리스트를 나열하고 pod-name 으로 로깅하는 짓이 가장 번거로웠다. 지금은 pod 가 한 10개 정도인데... 창을 10개를 띄워놓을 수도 없고... 그래서 실시간으로 pods 정보를 보여주고, 해당 로그를 스트리밍으로 좀 더 편하게 볼 수 있는 툴을 찾아보기로 했다.

 

쿠버네티스 모니터링 도구를 찾아보니 꽤나 많이 보이는데 그 중에 몇 가지만 테스트해 보았다.

 

  1. Kubernetes Dashboard
    심플하다. 시스템 모니터는 다른 모든 툴들도 기본적으로 잘 동작한다. CPU / RAM / Workload 등... 하지만 서비스 로깅이 불편하다. 5초 reload 방식... 이것도 대부분의 툴들이 마찬가지.

  2. Prometheus / Grafana
    설치 개복잡. Helm 을 사용하면 조금 편함. 잘나가다가 promtail 설정에서 막혔음. Fargate 사용 유저는 엄청난 고뇌가 필요할 듯... 몇가지 대안은 있었지만 로그 하나 보겠다고 굳이 일 벌리고 싶지 않았음. 가장 보편적이기도 하고, Custom / 확장도 좋은 것 같고... 대부분의 회사들이 사용하니 이건 써봐야겠지?

  3. Datadog
    시스템 통합으로 사용하고는 있으나... 쿠버네티스에 특화되어 있다기 보다는 로깅 분석에 어울리는... 그렇다고 안되는 건 없는... 그렇다고 굳이 유료 결제할 필요도 없는...?

  4.  Lens (Desktop) 
    Kubernetes IDE 답게 쿠버네티스에 특화되어 있음. 얼핏보면 외관은 Prometheus 와 흡사. 클릭 몇번으로 설치 완료. Attach Pod / logs 메뉴로 실시간 로깅은 잘됨. 혼자쓰기 괜츈.

 

kubernetes-lens

 

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

 

Oauth2.0 에서 Token 발급에 필요한 ClientId 와 SecretKey 생성하기.

 

 

ClientId

 

  • 일반적으로 길이 16~32자 16진수 문자열로 생성.
  • 모든 클라이언트에서 고유함.

 

SecretKey

 

  • 일반적으로 길이 32~64자 16진수 문자열로 생성.
  • TimeStamp / UUID 라이브러리 등은 지양.
  • 일반 암호와 동일하므로 DB 에는 암호화 되거나 해시된 버전으로 저장.

 

ClientId ex)

 

Foursquare: ZYDPLLBWSK3MVQJSIYHB1OR2JXCY0X2C5UJ2QAR2MAAIT5Q
Github: 6779ef20e75817b79602
Google: 292085223830.apps.googleusercontent.com
Instagram: f2a1ed52710d4533bde25be6da03b6e3
SoundCloud: 269d98e4922fb3895e9ae2108cbb5064
Windows Live: 00000000400ECB04
Okta: 0oa2hl2inow5Uqc6c357

 

 

Client Id / Secret Key 생성

 

commons-lang3 의 RandomStringUtils 를 사용하여 특정 길이의 랜덤한 문자열을 생성할 수 있다.

 

dependencies {
    implementation 'org.apache.commons:commons-lang3:3.12.0'
}

...

RandomStringUtils.randomAlphanumeric(32));  
// 1JhGTHmGlCP037aATyJzph983FRl5r14
RandomStringUtils.randomAlphanumeric(64));  
// 84ldr2jaagfMiIwzj2wFnaPxXBV2Yc9WC1AbJPaugEj5qHSWHkPjt2HInLdlzV7S

 

spring-security 를 사용할 경우, SecretKey 를 한번 더 암호화 하기 위해 BCryptPasswordEncoder 클래스를 사용한다.

 

PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodeKey = passwordEncoder.encode(secretKey);

 

PasswordEncoder.encode 는 항상 랜덤키를 생성하기 때문에 인코딩된 결과끼리의 비교는 불가능하지만, secretKey 와 encodeKey 의 비교는 가능하다.

 

if (passwordEncoder.matches(secretKey, encodeKey)) {
    System.out.println("matching~");
}

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Gradle Wrapper in IDEA

Tool/Gradle 2021. 10. 18. 22:14

Gradle 프로젝트 소스를 실행할 때, 로컬 컴퓨터에 프로젝트와 동일한 버전의 gradle 이 필요할 수 있는데 Wrapper 를 사용하면 해당 버전을 수동 설치할 필요가 없다. Gradle Wrapper 를 사용하면 지정된 버전의 gradle 이 없을 경우 자동으로 다운로드 및 설치를 하여, 해당 프로젝트를 동일한 gradle 버전으로 빌드할 수 있다. 구성원들의 안정적이고 표준화된 실행을 보장하기 위해 항상 Wrapper 로 빌드를 실행하는 것을 권장한다.

 

 

1. Wrapper 파일 생성

 

누군가 해당 소스를 받아서 Wrapper 를 사용할 수 있게 하려면, 미리 wrapper 파일을 생성해야 한다. 이 때는 gradle 이 로컬 컴퓨터에 설치되어 있어야 한다. 기본적으로 Gradle 프로젝트를 생성하는 init task 로 wrapper task 까지 실행된다. wrapper task 는 "Build Setup" 그룹에 존재하며, 이를 실행할 경우 프로젝트 디렉토리에 wrapper 파일을 생성해 준다.

 

$ gradle wrapper

gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
gradlew(.bat)

 

  • jar 파일은 properties 파일에 기반하여 Gradle 배포판을 다운로드하는 코드가 포함된다.
  • gradlew 파일은 Wrapper 로 빌드를 실행하기 위한 스크립트이다.
  • properties 파일에는 gradle 버전과 배포판 타입을 선택할 수 있으며 기본적으로 사용중인 gradle 버전을 따른다.

 

명령줄에서 직접 버전과 배포판 타입을 지정하여 wrapper 파일을 생성할 수도 있고,

 

$ gradle wrapper --gradle-version 7.2 --distribution-type all

 

이미 민들어진 properties 파일을 수정하여 동일한 결과를 만들 수도 있다.

 

distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip

 

 

2. Wrapper 사용

 

$ gradlew build

 


 

※ IDEA 에서의 Gradle 설정

 

Wrapper 를 활용하는 가장 일반적인 방법은 프로젝트 생성하는 사람이 Wrapper 설정까지 마쳐놓고, 다른 개발자들이 IDEA 설정에서 wrapper 파일을 사용하도록 설정하는 것이다. 

 

intellij-settings-gradle

 

간혹 수동으로 설치한 gradle 과 프로젝트 설정의 gradle 버전에 혼동을 느낄 수 있다. 로컬에서 프로젝트 gradle 버전 설정은 [File] - [Settings...] - [Build, Execution, Deployment] - [Build Tools] - [Gradle] 에서 설정한다. 그렇게 설정한 버전은 [View] - [Tool Windows] - [gradle] 창에서 사용된다.

 

intellij-gradle-tool-window

 

하지만 [View] - [Tool Windows] - [Terminal] 에서의 gradle 은 수동 설치 후 로컬 컴퓨터의 환경 변수에 지정된 gradle 버전과 연결되어 있다. Terminal 에서 프로젝트 디렉토리 안에 있더라도 [Settings...] 에서 설정한 프로젝트의 gradle 버전과 연관이 없다. IDEA Terminal 이지만 CMD 와 같다.  [File] - [Settings...] - [Tools] - [Terminal] 에서 사용할 터미널 종류를 선택할 수 있다.

 

intellij-terminal

 


 

You can configure gradle wrapper to use distribution with sources. It will provide IDE with Gradle API/DSL documentation.

 

IDEA 에서 gradle-wrapper 사용시 배포판 타입이 바이너리 전용 파일을 사용하도록 설정되어 있는 경우 발생하는 알림이다. 수락하면 docs/source 를 포함한 all 버전의 gradle 로 설치되고 사용된다. (무시해도 상관없음)

 

 

Gradle 설치 파일의 배포판 타입(DistributionType).

 

  1. gradle-version-bin.zip (bin: 바이너리만)
  2. gradle-version-all.zip (all: docs, source 포함)

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

intellij-event-log

 

Windows Defender might be impacting your build and IDE performance. IntelliJ IDEA checked the following directories:

 

IntelliJ 실행시 간혹 보이는 알림이다. 바이러스 백신 프로그램에서 실시간 검색이 활성화되어 있는 경우, IDE 빌드시 새로 생성되는 파일들과 관련하여 여러 간섭을 하게 될 수 있고 그로 인해 빌드 성능에 영향을 미칠 수 있으니, 해당 IDE 프로세스(idea64.exe, fsnotifier64.exe, ...) 를 바이러스 실시간 검색에서 제외시키거나, IDE 관련 디렉토리들을 제외시키는 것을 권장하고 있다.

 

위 알림처럼 Windows Defender 알림이 발생했을 때, 자동 fix 시킨다면, 윈도우즈의 [바이러스 위협 방지] 에서 해당 디렉토리들을 자동으로 제외시킨다.

 

  • 프로젝트 작업 디렉토리
  • Gradle 캐시 디렉토리( %USERPROFILE%\.gradle)
  • IntelliJ IDEA 에서 설정 및 캐시 를 저장하는 데 사용하는 디렉토리
    - Configuration (idea.config.path): %APPDATA%\JetBrains\IntelliJIdea2020.3
    - System (idea.system.path): %LOCALAPPDATA%\JetBrains\IntelliJIdea2020.3

 

어떤 경우 위처럼 제외 설정을 마쳤는데도 계속해서 알림이 뜬다면, don't show me again 을 선택했는데도 계속해서 알림이 뜬다면 (idea.config.path)/options/other.xml 파일을 편집하여 해당  알림을 무시할 수도 있다.

 

<component name="PropertiesComponent"> 
    ...
    <property name="ignore.virus.scanning.warn.message" value="true" />
    ...
</component>

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,
import pandas as pd
print(pd.__version__)
cs


Traceback (most recent call last):

  File "~\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3343, in run_code

    exec(code_obj, self.user_global_ns, self.user_ns)

  File "<ipython-input-2-22947d009327>", line 1, in <module>

    runfile('D:/Project_CTLab/Hong_Test2/pandas.py', wdir='D:/Project_CTLab/Hong_Test2')

  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 197, in runfile

    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script

  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile

    exec(compile(contents+"\n", file, 'exec'), glob, loc)

  File "D:/Project_CTLab/Hong_Test2/pandas.py", line 1, in <module>

    import pandas as pd

  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_import_hook.py", line 21, in do_import

    module = self._system_import(name, *args, **kwargs)

  File "D:\Project_CTLab\Hong_Test2\pandas.py", line 3, in <module>

    print(pd.__version__)

AttributeError: partially initialized module 'pandas' has no attribute '__version__' (most likely due to a circular import)


pandas 모듈 불러오면서 파일명을 pandas.py 로 저장했더니...ㅋㅋ







WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,