내 생각에는 Node 장애가 발생했을 때, 빠르게 Pod가 장애가 발생한 Node에서 종료 처리되고 다른 Node로 스케쥴링되게 하려면, 300초로 설정된 값을 1초로 줄이면 되지 않을까하는 상상을 해본다.
시간 여유가 있을 때, 한번 1초로 변경하고 Node를 다운시켜서 테스트해봐야겠다.
참고: 쿠버네티스는 사용자나 컨트롤러에서 명시적으로 설정하지 않았다면, 자동으로 node.kubernetes.io/not-ready 와 node.kubernetes.io/unreachable 에 대해 tolerationSeconds=300 으로 톨러레이션을 추가한다. 자동으로 추가된 이 톨러레이션은 이러한 문제 중 하나가 감지된 후 5분 동안 파드가 노드에 바인딩된 상태를 유지함을 의미한다.
참고: Go Module과 Package를 사용하는 방법이 Go Version에 따라 다를 수 있다. 아래 예제는 Go 1.17을 이용한 예제이고, 아마 Go 1.11 이상을 사용하는 경우라면 아래 설명이 잘 맞을 것이다.
여담: 나는 본업이 Go Language를 사용해서 개발하는 개발자가 아니다보니, 2~3년에 한번 잠깐 GoLang을 이용해서 개발하려고 하면 Go Package와 Module 때문에 시간을 허비하게 된다. 그래서 오늘은 기왕 스터디한 것을 2~3년 뒤에 또 GoLang을 사용할 일이 있을 경우, 쉽게 Package와 Module 개념을 습득하기 위해 예제를 통해서 메모를 할까 한다.
Go PKG를 다루기 위해서는 크게 3가지 방식이 있다.
방식 A
$GOPATH 경로를 설정하고, 이 $GOPATH 경로 안에서만 Package를 사용하는 방법. (암묵적 Module 사용하기)
방식 B <-- 가장 많은 개발자가 선호하는 방식이 아닐까 생각한다.
Module을 명시적으로 선언(go mod init x.y.z)하고, 내가 원하는 폴더 어디에서든 Go Source Code를 작성하는 방법.
방식 C
go ven를 이용해서 현재 디렉토리 하위에서 모든 Package를 사용하는 방법.
각 Package 사용 방식에 대해서 아래에서 세부적으로 다룬다.
$GOPATH 경로를 선언하여 Package를 사용하는 방식
설명보다는 예제 코드를 보는 것이 좋을 듯~~~
$ vi ~/.bash_profile
...
export GOPATH=$(go env GOPATH)
...
$ . ~/.bash_profile
$ echo $GOPATH
/Users/sejong/go
$ cd $GOPATH
##
## 이제부터는 $GOPATH/src 디렉토리 밑에서만 코드를 작성해야 한다.
##
$ mkdir -p src/myexample
$ cd src/myexample
$ mkdir myPkgAlpha
$ cd myPkgAlpha
$ vi example.go
package myPkgAlpha
import "fmt"
# 주의: 패키지 외부에서 참조할 수 있도록 함수 이름은 대문자로 시작해야 한다.
func MyExamplePrint() {
fmt.Println("My Alpha PKG")
}
$ cd ..
$ vi main.go
package main
import (
"fmt"
"myexample/myPkgAlpha"
)
func main() {
fmt.Println("This is main package.")
myPkgAlpha.MyExamplePrint()
}
$ go mod init myexample
$ go mod tidy
$ go build
$ ./myexample
This is main package.
My Alpha PKG
$ tree
.
├── go.mod
├── main.go
├── myPkgAlpha
│ └── example.go
└── myexample
$
$GOPATH 경로가 아닌, 나만의 별도의 Project 폴더에서 Go Module 사용하는 방식
Go module을 사용하면 $GOPATH 경로가 아닌 아무 곳(디렉토리)에서 Go Source Code를 작성할 수 있는 자유가 생긴다.
긴 설명은 생략하고, 아래 예제처럼 Go Package와 Module을 사용하면 된다.
##
## 새로운 프로젝트를 위한 폴더를 만들자~
##
$ mkdir go-mod-pkg-example
$ cd go-mod-pkg-example
##
## Go Package를 만들자. (myPkgAA)
## 주의사항: package 이름과 folder 이름을 동일하게 작성해야 한다.
##
$ mkdir myPkgAA
$ cd myPkgAA
##
## 아래와 같이 myPkgAA 패키지에 대한 코드를 작성한다.
##
$ vi example.go
package myPkgAA
const (
COMPANY = "Sejong Inc"
LOCATION = "Seoul Korea"
)
##
## Package가 1개만 있으면 심심하니까, 하나 더 만들자. (mypkg_bb)
##
$ cd ..
$ mkdir mypkg_bb
$ cd mypkg_bb
##
## 아래와 같이 mypkg_bb 패키지에 대한 코드를 작성한다.
##
$ vi example.go
package mypkg_bb
import (
"fmt"
)
// NOTE: 함수 이름은 대문자로 시작해야 한다.
func DoSomething(company string, location string) {
fmt.Println("[In mypkg_bb]")
fmt.Println(" Company :", company)
fmt.Println(" Location :", location)
}
##
## 위에서 작성한 Package를 사용하는 Go Module Code를 작성하자.
##
$ go mod init myexample.cncf/sejong/myexample
$ vi main.go
// NOTE: package 이름을 main 으로 한다.
package main
// NOTE: 이 module의 이름이 "myexample.cncf/sejong/myexample" 이었기 때문에
// myPkgAA 패키지를 import하려면 아래처럼 경로를 작성해야 한다.
import (
"myexample.cncf/sejong/myexample/myPkgAA"
"myexample.cncf/sejong/myexample/mypkg_bb"
)
func main() {
mypkg_bb.DoSomething(myPkgAA.COMPANY, myPkgAA.LOCATION)
}
## 솔직히, 위 예제 패키지(로컬 패키지)만 이용하는 경우에는 아래 tidy 명령을 필요 없다.
## 그러나 main.go 파일에서 외부 pkg를 import 한 것도 포함했다면,
## 아래처럼 tidy 명령을 수행해야 한다.
$ go mod tidy
$ go build
$ ./myexample
[In mypkg_bb]
Company : Sejong Inc
Location : Seoul Korea
$ tree
.
├── go.mod
├── main.go
├── myPkgAA
│ └── example.go
├── myexample
└── mypkg_bb
└── example.go
$
Vendor 방식의 패키지 관리
vendor 디렉토리에 특정 버전의 외부 패키지들을 저장 시킨 뒤 빌드에 참여시킴으로써 버전 일관성 문제를 해결 할 수 있다.
그리고 다운로드 불가한 외부 패키지를 어떻게든 한번만 구할 수만 있다면 다운로드 불가 문제도 피할 수 있다.
Container Image처럼 내가 작성한 Go Module 소스 코드가 있는 폴더에 의존성이 있는 모든 Package를 vendor/ 폴더 디렉토리에 다운로드 받는 다는 것이 가장 큰 특징이다.