본문으로 건너뛰기

맥 추천 패키지

· 약 5분

여러 맥 기기의 환경을 구성하다보니 적어 놓는 게 나을 듯 싶었다.

brew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

formulae

main formulae

brew install azure-cli \
fzf \
git \
go \
kubernetes-cli \
mas \
node \
python \
stern \
tree \
wget
  • azure-cli
  • fzf
  • git
  • go
  • java
  • kubernetes-cli
  • mas
  • node
  • python
  • stern
  • tree
  • wget

sub formulae

docker for mac

brew tap spring-io/tap
brew install git \
gitui \
hadolint \
helm \
kubectx \
k9s \
spring-boot \
thefuck \
volta \
youtube-dl \
zsh-autosuggestions \
zsh-syntax-highlighting
  • git
  • gitui
  • helm
  • kubectx
  • springboot
  • thefuck
  • volta
  • youtube-dl
  • zsh-autosuggestions
  • zsh-syntax-highlighting

cask

brew tap homebrew/cask-fonts
brew cask install adguard \
appcleaner \
authy \
bitwarden \
cheatsheet \
firefox \
flutter \
font-cascadia \
font-hack-nerd-font \
fork \
gather \
google-chrome \
hiddenbar \
iina \
iterm2 \
java \
jetbrains-toolbox \
keepingyouawake \
keka \
macs-fan-control \
monitorcontrol \
microsoft-edge \
postman \
rancher \
sequel-pro \
slack \
telegram-desktop \
udeler \
visual-studio-code \
yt-music \
zoom \
zulu
  • adguard: 💰
  • appcleaner: 앱 클리너
  • authy: 2차 인증
  • bitwarden: 비밀번호 관리
  • cheatsheet: ⌘ 키를 오래 누르면 해당 프로그램의 모든 단축키를 볼 수 있음
  • devtoys: 개발용 툴
  • firefox: 파이어폭스
  • flutter: 플러터
  • font-cascadia: Cascadis Code 폰트
  • font-hack-nerd-font: iTerm2 용 터미널 폰트
  • fork: 무료 중 최고의 git client
  • gather: 게더타운
  • google-chrome: 크롬
  • hiddenbar: 작업표시줄의 프로그램 숨기기
  • iina: 깔끔한 인터페이스의 미디어 플레이어
  • iterm2: 터미널
  • jetbrains-toolbox: jetbrains IDE 버전 관리
  • keepingyouawake: 잠자기 모드 제어
  • keka: 압축 프로그램
  • macs-fan-control: 팬 조절
  • monitorcontrol: 외장모니터 제어
  • microsoft-edge: edge
  • postman: 포스트맨
  • rancher: rancher-desktop
  • rectangle: 창 크기 조절
  • sequel-pro: MySQL GUI client
  • slack: 슬랙
  • telegram-desktop: 텔레그램
  • udeler: udemy 강의 다운로더
  • visual-studio-code: vscode
  • yt-music: 유튜브 뮤직 플레이어
  • zoom: 줌
  • zulu: 자바

App store

mas install 497799835 \
1355679052 \
869223134 \
1295203466 \
1471801525 \
897118787 \
425424353 \
1475628500
  • xcode: 497799835
  • dropover: 1355679052 드래그 후 흔들면 가상폴더로 저장
  • kakaotalk: 869223134 카카오톡
  • microsoft remote desktop: 1295203466 윈도우 원격
  • polyglot: 1471801525 사파리 번역기
  • shazam: 897118787 음악 찾기
  • unicorn https: 1475628500 Encrypt DNS query

Bunblefile

bundle

brew bundle install

Brewfile
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-drivers"
tap "homebrew/cask-fonts"
tap "spring-io/tap"

cask_args appdir: "~/Applications", require_sha: true

brew "fzf" # fuzzy finder
brew "gh" # github clone
brew "git" # git
brew "gitui" # git cui
brew "hadolint" # dockerfile linter
brew "helm" # helm chart
brew "k9s" # k8s dashboard
brew "kubectx" # k8s context switcher
brew "mas" # app store
brew "mkcert" # local certification
brew "skaffold" # k8s deploy
brew "thefuck" # fix typo
brew "tree" # tree
brew "volta" # nodejs version manager
brew "wget" # wget
brew "zsh" # zsh
brew "zsh-autosuggestions"
brew "zsh-syntax-highlighting"
brew "spring-io/tap/spring-boot" # spring cli

cask "appcleaner" # 앱 클리너
cask "authy" # 2차 인증
cask "bitwarden" # 비밀번호 관리
cask "cheatsheet" # 단축키
cask "devtoys" # 개발 툴
cask "firefox" # 파이어폭스
cask "flutter" # 플러터
cask "font-cascadia-code" # ms 개발 폰트
cask "font-hack-nerd-font" # 터미널 폰트
cask "fork" # git gui
cask "gather" # gathertown
cask "hiddenbar" # 작업표시줄 숨기기
cask "iina" # 플레이어
cask "iterm2" # 터미널
cask "jetbrains-toolbox"
cask "keepingyouawake" # 잠자기 해제
cask "keka" # 압축 프로그램
## cask "logitech-options" # 로지텍 사용자만
cask "macs-fan-control" # 팬 조절
cask "microsoft-edge" # edge
cask "monitorcontrol" # 외장 모니터 조절
cask "postman" # postman
cask "rancher" # docker desktop `alias docker=nerdctl`
cask "rectangle" # 창 조절
cask "sequel-pro" # mysql gui
cask "slack" # slack
cask "telegram-desktop" # telegram
## cask "udeler" # udemy downloader
cask "visual-studio-code" # vscode
## cask "yt-music" # youtube music
cask "zoom" # zoom
cask "zulu" # zulu jdk

## mas "Bitwarden", id: 1352778147
## mas "Dropover", id: 1355679052
mas "Microsoft Remote Desktop", id: 1295203466 # remote desktop
mas "Polyglot", id: 1471801525 # translator
mas "Shazam", id: 897118787 # music finder
mas "Xcode", id: 497799835 # xcode
mas "카카오톡", id: 869223134 # kakaotalk

쿠버네티스 롤링 업데이트와 배포

· 약 5분

Deployment

Deployment 의 파드 교체 전략에는 RollingUpdateRecreate 가 있다. 기본 값은 RollingUpdate 이며 간단한 설정이 적용된 디플로이먼트는 아래와 같을 것이다.

apiVersion: apps/v1
kind: Deployment
metadata:
name: test-rolling-update
label:
app: test
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 3
maxSerge: 4
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: test
image: echo
ports:
- containerPort: 8080

여기서 롤링업데이트 속성을 좀 더 자세히 알아보자.

RollingUpdate

maxUnavailable

  • 롤링 업데이트 중 동시에 삭제할 수 있는 파드의 최대 갯수
  • 기본 값은 replicas의 25% 이다.
  • replicas: 4의 경우 1개 파드 삭제, replicas: 8의 경우 2개 파드 동시 삭제
  • 퍼센트 및 직접 지정이 가능하다.
  • 위의 예시 디플로이먼트에서 롤링업데이트 시작 시 파드 3개가 바로 죽는다.
  • 이 값을 높게 설정하면 동시에 교체되는 파드가 늘어나므로 롤링 업데이트 시간이 줄어든다.
    • 하지만 롤링업데이트 중에 남아 있는 파드에 요청 수가 몰릴 수 있다.
    • 따라서 1로 설정해 파드를 하나씩 교체하는 것이 안전할 수 있다.

maxSurge

  • 롤링 업데이트 중 동시에 생성하는 파드 갯수
  • 기본 값은 replicas의 25% 이다.
  • replicas: 4면서 maxSurge: 4면 롤링 업데이트 시작 시 새 버전의 파드가 4개 추가로 생성된다.
  • 이 값을 높게 설정하면 필요한 파드를 빨리 생성하므로 파드 교체 시간이 단축된다.
    • 하지만 필요한 시스템 자원이 급증할 수 있다.

Probe

세부 설정은 Docs를 참조하자

livenessProbe

  • 애플리케이션 헬스 체크 기능
  • 애플리케이션이 의존하는 컨테이너 안의 파일의 존재여부 확인
  • Unhealthy 상태의 경우 파드 재시작

readinessProbe

  • 컨테이너 외부에서 HTTP 등의 트래픽을 발생시켜 처리할 수 있는 상태인지 확인
  • tcpSocket으로 포트 지정도 가능하다.

응답 중인 파드 교체

응답 중인 파드가 교체되는 경우 SIGTERM 신호를 보내 파드가 삭제되는데, Graceful Shutdown 상태로 만들기 위해서 종료 처리가 오래 걸리는 파드엔 terminationGracePeriodSeconds 를 설정해주는 것이 좋다.

spec:
# 기본값 30
terminationGracePeriodSeconds: 40
containers:
- name: maria
image: maria:latest

Nginx처럼 SIGTERM 시그널을 받고 바로 종료되는 어플리케이션이 있는 파드라면, 라이플사이클 훅을 활용해 안전하게 종료시키는 것이 중요하다.

spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
lifecycle:
# 파드 종료 전 훅
preStop:
exec:
command: ["/usr/sbin/nginx", "-s", "quit"]

파드 1:1 교체

그렇다면 replicas: 1인 파드를 1:1 교체 시에는 어떤 전략을 가져가야할까 답은 아래와 같다.

strategy:
type: RollingUpdate
rollingUpdate:
# 롤링 업데이트 시 삭제 되는 파드 수
maxUnavailable: 0
# 롤링 업데이트 시 새로 생성되는 파드 수
maxSurge: 1

여기에 파드가 트래픽을 받을 수 있는지 readinessProbe를 추가해주면 된다.

readinessProbe:
httpGet:
path: /ping
port: 80
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
timeoutSeconds: 3

5초 후에 5초마다 /ping 을 보내 성공여부를 확인한다. 타임아웃은 3초며 3번까지 재시도한다.

Blue/Green

  • 디플로이먼트를 2개 만들고, 서비스의 selector 값을 라벨에 따라 변경하자.
  • 서비스메시를 연동하면 카나리아 배포 방식도 가능하다.

Pythonic - 기본기

· 약 8분

The Basics

Types

  • 아무 것도 없는 타입은 None
  • 주석
    • #
    • """ """
  • 포매팅
    • f’test {변수}'
    • "test {}".format(변수)
  • list, dict, set 등은 immutable 하지 않아 copy 메소드를 사용해 복사 필요
  • 스왑
    • a, b = b, a 로 한 줄로 가능
  • set
    • {} 으로 set 지정가능
    • 집합연산 가능
    • set([]) 로 배열을 set으로 변환 가능
  • enum
    • 튜플로 지정하면 됨
    • 튜플은 freeze 되어 있다.
    • ('a', 'b', 'c')
  • list
    • merge는 더하기로 가능 [] + []

Operaters

  • if
    • 값 체킹에는 0.0 '' [] () {} set() 등 모든 빈 값이 false 로 떨어진다.
      • 따라서 len(foo) > 0 보다 권장
    • if foo != True 보다 if not foo 를 권장
    • dict 키 검증 시에는 if 'key' in d: 를 권장 if 'key' in d.keys(): 필요없다.
    • y=None x = 1 if y else 2 면 x=2 라는 문법이 된다.
  • is 문은 값이 None 인지 확인할 때 권장
    • if foo == None 보다 if foo is None 을 권장
    • if foo is not None
  • while
    • while else 구문 가능 else 는 while 에 break 가 없을 경우 while 끝나고 실행
  • for
    • for in
    • for in else 구문 가능 else는 for 에 break 가 없을 경우 for 끝나고 실행
    • for _ in range(10) 처럼 underscore 는 index 를 안쓸때 권장
    • for i, item in enumerate(['a', 'b', 'c']) 처럼 index 넣어줄 수 있음
    • for day, fruit in zip(days, fruit) 처럼 패킹(zip) 함수 기본 제공
    • for k, v in d.items() 로 dict 타입 반복 가능
  • func
    • def func(): 로 함수선언
    • def add(a: int, b: int) -> int: 처럼 파라미터 및 리턴 타입 정의 가능
      • compile error 발생 안 함
      • 보여주기 위한 타입 기능
    • 매개변수를 위치 인수로 넣을 수 있음
      • def menu(entree, drink)라면 menu(drink='a', entree='b') 로 호출 가능
    • list 매개변수는 기본값으로 넣으면 안 됨 def foo(list=[]) 면 리스트가 한 번만 생성됨 (함수 내부 초기화 필요)
    • def func(*args) 로 동적매개변수 처리 가능 튜플로 처리됨
    • def func(**kargs) 로 넣으면 dict로 전달가능 func(key1='val', key2='val')
    • 두 구문을 같이쓸 수 있지만 *args**kargs 보다 먼저 와야한다.
    • 함수 내부 """ """ doc 주석을 넣으면 help(func.__doc__), help(func) 로 도움말 호출 가능
    • 클로져로 wrapper 함수를 만들면 데코레이터로 바로 적용 가능
    • func(lists, lambda item: item.value()) 람다 처리가능 (value: returnValue)
  • 비추천 dic = {x: y for x, y in (zip(w, f)} 처럼 한 번에 for문 dictionary 선언 가능
  • genarator
    • def + yield
    • gen = (i for i in range(10) if i % 2 == 0) 처럼 한 번에 선언하면 제네레이터가 된다.
    • tuple(gen) 하면 튜플로 처리된다.
    • for 보다 빠를 수 있다.
  • globals(), locals() 로 전역, 로컬변수 확인가능
  • excpetion
    • try: except IndexError as ex: finally:
    • try: except: else: finally: 가 있다면 try => else => finally 로 실행
    • raise IndexError('test error') 처럼 raise 로 에러 발생 가능
    • 기본에러는 exception hierarchy 참조

Package

  • __init__.py 가 있어야한다.
  • import package.utils 또는 from package import utils 해서 utils.func 롤 호출
  • from package import utils as NamedUtil 처럼 as 문으로 네임스페이스 변경 가능
  • 비추천 from package.folder import * 로 folder 레벨의 모든 python import 가 가능한데 folder.__init__.py__all__ = ['py', 'py2'] 처럼 선언해줘야한다.
  • setup.py 를 만들어 패키지를 배포시킬 수 있다.
    • PyCharm: Tools > Create setup.py > run setup.py > sdist 로 출력
    • Cli: python setup.py sdist
  • PyPI 에 서드파티 라이브러리를 등록하면 pip install termcolor 처럼 설치 가능
  • import 라이브러리 순서는 위에서부터 표준, pip, 로컬패키지, 로컬파일
  • if __name__ == '__main__': main()entrypoint 스크립트에서 사용되는 패턴이다.

Class

  • 생성자 __init__(self):, Instance() 로 new 없이 생성
  • 소멸자 __del__(self):, del instance 로 삭제
  • class method 의 첫 인자로는 self를 받아야 this처럼 사용이 가능하다. 두 번째 부터 파라미터를 받을 수 있다.

protected

  • proteced 변수는 _var 처럼 underscore 하나를 넣는다.
  • @property, @property_name.setter 데코레이터를 통해 getter/setter 처리가 가능하다.
class Instance(object):
@property
def foo(self):
return self._foo

@foo.setter
def foo(self, bar):
self._foo = bar

intance = Instance()
instance.foo = bar

private

  • private 변수는 self.__foo 로 underscore 두 개를 넣는다.
  • 인스턴스 밖에서 접근이 불가능하다.

class variable

  • 클래스 변수는 모든 오브젝트 초기화시에 공유되므로 list, dict.. 등을 사용하지 않아야한다.
  • 상수처럼 쓰는게 좋을 듯

class method

  • class 메소드는 @classmethod 데코레이터로 가능하다.
class Instance(object):
@classmethod
def foo(cls):
# cls 로 클래스 접근가능
return cls.bar

Instance.foo()

static method

  • static 메소드는 @staticmethod 데코레이터로 정의할 수 있으나 잘 사용되지는 않는다.

상속

class Parent(object):
def __init__(self):
pass

class Child(Parent):
def __init__(self):
super().__init__
  • 다중상속 하지말자
  • class Twins(Parent, Parent2) 로 되지만 메소드명이 같을 경우 왼쪽에 선언된 것만 실행된다.

추상

import abc

class Parent(metaclass=abc.ABCMeta):
@abc.abstractmethod
def foo(self):
pass

class Child(Parent):
def foo(self):
print('foo')

특수 메소드

  • 많지만 __str__ 이 제일 많이 쓴다. toString() 과 같다.
  • __len__ (len(instance))
  • __eq__ (instance == instance2)
  • __add__ (instance + instance2)
  • 등등..
  • 클래스 기본기능을 해치는 개인적인 느낌

여담

  • MSA의 시대에 살고 있는 어플리케이션 레이어의 개발자는 어쩔 수 없이 폴리글랏 프로그래머가 되기 마련이다.
  • 하나의 언어에 능통하면 다른 언어로 넘어가는 데에는 익숙함의 문제지만, 그 언어를 제대로 사용하기 위해 가장 중요한 건 스타일 가이드, 린팅과 주기적인 Docs, Release Notes 확인이라고 생각한다.

Carbon 으로 timestamp 파싱하기

· 약 1분

Timestamp

Carbon으로 타임스탬프를 파싱하는 데에는 createFromTimestamp 메소드가 있다.

Carbon::createFromTimestamp(1576249805)->format();

하지만 더 쉽게 parse 메소드를 사용해 파싱할 수도 있다.

$timestamp = 1576249805;
Carbon::parse('@' . $timestamp)->format();

여기서의 @는 오류를 무시하는 기분이 들어서 찾아보았는데 표준이였다.

Example #2 DateTime::setTimestamp() alternative in PHP 5.2

$ts = 1171502725;
$date = new DateTime("@$ts");
echo $date->format('U = Y-m-d H:i:s') . "\n";
?>

참조

타입스크립트에서 json import 방법

· 약 1분

TS5071

node 에서 즐겨쓰는 package.json import 방법은 아래와 같다.

import packageJson from "../package.json";
console.log(packageJson.version);

편안하게 잘 사용되는 로직인데 타입스크립트로 변경시에는 몇 가지 설정을 해줘야한다. 설명에 필요없는 설정은 생략했다.

tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true
}
}

또는 tsc 실행시에 --esModuleInterop, --resolveJsonModule 옵션을 추가해 빌드해줘야한다.

참조

vee-validate3 모든 규칙 추가시 TS7053 오류

· 약 2분

TS7053

3.0 버전이 되면서 HOC 기반으로 변경되며 rules를 상위 컴포넌트에서 확장하게 되었다. 문제는 typescript 기반에서 룰 전체 등록이 TS(7053) 에러를 발생시킨다.

import { ValidationProvider, ValidationObserver, extend } from "vee-validate";
import * as rules from "vee-validate/dist/rules";

Object.keys(rules).forEach((rule) => {
extend(rule, rules[rule]); // rules[rule] 에서 타입오류 발생
});
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof import(".../node_modules/vee-validate/dist/rules")'.
No index signature with a parameter of type 'string' was found on type 'typeof import(".../node_modules/vee-validate/dist/rules")'.ts(7053)

원인

import, export 의 모듈명은 string index 로 쳐지지 않아 발생한다.

해결방법

Object.entriesfor of를 사용해 타입에 안전하게 돌려주면 된다.

import { extend } from "vee-validate";
import * as rules from "vee-validate/dist/rules";

for (const [rule, validation] of Object.entries(rules)) {
extend(rule, {
...validation,
});
}

여담

  • 새로운 구문 (async/await, import/export)를 사용해 돌릴 땐 먼저 for of를 사용하는 습관을 들여야겠다.
  • 머지되어서 다음 사람의 삽질은 없을 듯 하다.

참조

Helm chart의 모든 것

· 약 5분

Helm

Helm is a tool for manaing Kubernetes charts. Charts are packages of pre-configured Kubernetes resources.

  • 헬름은 쿠버네티스 차트를 관리하기 위한 도구
  • 차트는 사전 구성된 쿠버네티스 리소스의 패키지
  • 같은 어플레케이션을 여러 환경에 배포시 환경 변수, 도메인 등의 manifest 파일을 차트를 통해 관리
  • 차트를 중심으로 하는 쿠버네티스 개발 종합 관리 도구

설치

## 설치
brew install kubernetes-helm

## 초기화
helm init

## tiller 파드 확인
kubectl -n kube-system get service,deployment,pod --selector app=helm

## 버전 확인
helm version

구성

  • cli와 쿠버네티스 클러스터에 설치되는 서버인 tiller(틸러)로 구성

chart

  • 쿠버네티스는 service, deployment, ingress 등 리소스를 생성하고 manifest 파일을 적용하는 방식으로 어플리케이션을 배포한다. 이 manifest 파일을 생성하는 템플릿을 여러 개 패키징한 것
  • helm repository 에 tgz 파일로 저장

chart 구성

chart-example
├── charts # 차트가 의존하는 차트 디렉토리
├── templates # manifest 파일 템플릿 디렉토리
│ ├── NOTES.txt # 차트 사용법 등 참조 문서 템플릿
│ ├── _helper.tpl # manifest 렌더링에 사용되는 템플릿 헬퍼
│ └── example.yaml # 각종 K8S 리소스의 manifest 템플릿
├── Chart.yaml # 차트 정보가 정의 파일
└── values.yaml # 차트 기본값 value 파일

차트 설치시 values.yaml 에 override 할 값을 정의한 yaml 파일을 만들면 된다.

repository

  • local: 헬름 클라이언트가 설치된 로컬 리포, 로컬에서 생성한 패키지가 존재
  • stable: stable charts repo, 기본값이며 helm/charts 차트 사용 가능
  • incubator: stable 조건 미달 repo
    • helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/
  • helm search 로 차트 검색 가능

명령어

init

보통은 helm init 실서버에서는 helm init --service-account tiller --node-selectors system --history-max 10 업그레이드는 helm init --upgrade

  • --service-account: 틸러가 사용할 서비스계정
  • --node-selectors: 틸러를 배포할 노드 레이블
  • --upgrade: 틸러 업그레이드
  • --history-max: 리소스 하나당 유지할 최대 히스토리 수

create

helm create 차트명

package

helm package 차트명 차트를 압축파일로 패키징

  • --version: 차트 버전 지정
    • 없을 경우 차트의 버전을 따른다.

helm search 검색어

  • -r, --regexp: 검색어를 정규표현식으로 사용
  • -l, --versions: 버전 목록도 출력

fetch

helm fetch 차트경로

  • --version: 특정 버전 지정

serve

helm serve 로컬 레포지토리로 사용할 웹 서버 시작

  • --address: 서버가 개방할 주소
    • 기본값은 127.0.0.1:8879
  • --repo-path: 차트 레포지토리가 될 로컬 디렉토리

install

helm install 차트명 차트로 애플리케이션 설치

helm install stable/redis --name my-redis

helm install stable/redis --version 3.6.0 \
--name my-redis \
--namespace gracefullight \
-f ./my-redis.yaml
  • --dry-run
  • --name: 릴리즈명
  • --namespace: 설치 대상 네임스페이스
  • -f, --values: yaml 파일 경로 (다수 가능)
  • --version: 차트 버전 지정

list

helm list helm list --namespace kube-system

  • --deleted: 삭제된 릴리즈 포함
  • --namespace: 해당 네임스페이스만 확인

get

helm get 릴리즈명 설치된 릴리스 상ㅇ세 정보를 yaml 으로 출력

  • --revision: 릴리즈 리비전 확인

delete

helm delete 릴리즈명

  • --purge: 릴리즈 삭제하고 릴리즈명 해제

쿠버네티스 오브젝트와 클래스 오브젝트 비교

· 약 2분

앞서

쿠버네티스를 이해하는 건 어렵다. DevOps 의 전반적인 플로우를 알아야 이 플로우도 이해가 가기 때문이라 생각한다. 생소한 용어들도 어렵다. 한 판을 정리 했지만 매번 참조해야되는 듯하다.

오브젝트 비교

개념JAVA 클래스쿠버네티스 오브젝트
캡슐화ClassContainer image
인스턴스ObjectContainer
재사용단위jarContainer image
컴포지션Class A Contains Class BSidecar pattern
상속Class A extends Class BA container's from parent image
배포단위jar, war...Pod
빌드 및 런타임 아이솔레이션Module, Package, ClassNamespace, Pod, Container
초기화ConsturctorInit container
초기화 후 트리거Init methodpostStart
종료 전 트리거DestroypreStop
Cleanupfinalize(), shutdown hookDefer container
비동기, 병렬 실행ThreadPoolExecutor, ForkJoinPoolJob
스케쥴링Timer, ScheduledExecutorServiceCronJob
백그라운드Daemon threadDaemonSet
설정관리System.getenv(), PropertiesConfigMap, Secret

여담

  • 개념 설정 전에 이 표를 알았더라면 훨씬 이해가 쉬웠을텐데

Github Actions로 Hexo 배포 자동화하기

· 약 2분

개념

Docker 이미지로 생성된 후에 그 위에서 돌아간다. 자세한 개념은 시간날 때 추가 예정

레파지토리 토큰 발급

여기를 참조해 레파지토리의 secret 으로 등록한다.

서브모듈

themes directory 하위의 테마들은 각각의 repo를 가지고 있다. 이 테마들을 CI 중에 가져오기 위해선 서브모듈로 등록해주고 초기화시켜줘야한다.

## 서브모듈 테마 추가
git submodule add 테마깃경로 themes/테마명

## 싱크
git submodule update --init --remote

여기서 remote 옵션을 쓰지 않을 경우 최신 마스터를 pull 하지 않는다. 서브모듈을 쓰는 이유는 내가 관리하지 않기 위함이니 꼭 추가해주자.

소스

주석 없어도 하나하나가 무슨 느낌인지는 받아들여질 것 같다.

name: Node CI

on:
push:
branches:
- master

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node: [20.x]

steps:
- uses: actions/checkout@master

- name: SETUP_NODE_${{ matrix.node }}
uses: actions/setup-node@master
with:
node-version: ${{ matrix.node }}

- name: BEFORE_INSTALL
run: npm i -g hexo workbox-cli

- name: BEFORE_SCRIPT
run: |
git config --global user.name 'gracefullight'
git config --global user.email '[email protected]'
sed -i "s/__GITHUB_TOKEN__/${{ secrets.HEXO_DEPLOY_TOKEN }}/" _config.yml

- name: THEME_INSTALL
run: |
git submodule update --init --remote --recursive

- name: NPM_INSTALL
run: npm install

- name: HEXO_CLEAN
run: hexo clean

- name: HEXO_GENERATE
run: hexo generate

- name: WORKBOX_BUILD
run: workbox injectManifest

- name: HEXO_DEPLOY
run: hexo deploy

GITHUB_TOKEN

secrets.GITHUB_TOKEN 은 예약된 토큰이다. 빌드 이미지에서 현재 repo를 접근하기 위한 토큰임을 알아두자.

결론

travis-ci 안녕

참조

puppeteer 크롤링 속도 증가시키기

· 약 1분

페이지를 가져온 뒤 css, image, font를 차단하면 더 빠른 DOM 액세스가 가능하다.

리소스 차단

// @types/puppeteer
import { launch, Browser, Request, Page } from "puppeteer";

const browser: Browser = await launch({
headless: true,
});

const page: Page = await browser.newPage();
await page.setRequestInterception(true);

page.on("request", (req: Request) => {
switch (req.resourceType()) {
case "stylesheet":
case "font":
case "image":
req.abort();
break;
default:
req.continue();
break;
}
});

await page.goto("URL");