- Fargate
- nodeaffinity
- EKS
- SAA-CO2
- aws
- cloudnative
- SAA-CO3
- CKA
- DevOps
- eventbridge
- go
- Datadog
- K8S
- kubernetesadmin
- Kubernetes
- SMTP
- SPF
- Lambda
- aws ses
- DKIM
- gochannel
- λ©μΌ μΈμ¦ νλ‘ν μ½
- containerorchestration
- JVM
- Certified Solutions Architect
- kubernetesscheduling
- dMarc
- Java
- kubernetesstudyguide
- Today
- Total
DevOps Tasks
AWS Parameter Store, λλμ νλΌλ―Έν° κ΄λ¦¬ μ΄λ»κ² ν΄κ²°ν κΉ? Goμ Cobraλ‘ λ§λ CLI κ°λ°κΈ° λ³Έλ¬Έ
AWS Parameter Store, λλμ νλΌλ―Έν° κ΄λ¦¬ μ΄λ»κ² ν΄κ²°ν κΉ? Goμ Cobraλ‘ λ§λ CLI κ°λ°κΈ°
λ°λ°₯μ€ 2024. 12. 3. 15:34π λ°λ³΅ μμ μ λΉν¨μ¨μ± ν΄κ²°
`AWS Parameter Store` λ μ ν리μΌμ΄μ μ μ€μ κ°μ μμ νκ² κ΄λ¦¬ν μ μλ κ°λ ₯ν μλΉμ€μ λλ€.
κ·Έλ¬λ κ΄λ¦¬ μμ μμ ν¨μ¨μ±μ μ ν΄νλ λͺ κ°μ§ λ¬Έμ κ° μμμ΅λλ€.
μ΄λ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ CLI λꡬλ₯Ό κ°λ°νμ¬ μλνμ μ±λ₯ μ΅μ νλ₯Ό λͺ©νλ‘ μΌμμ΅λλ€.
λ°λ³΅ μμ
μ¬λ¬ νκ²½μ λμΌν μ€μ κ°μ μΆκ°νκ±°λ μ λ°μ΄νΈνλ μμ μ΄ λ²κ±°λ‘κ³ , μ΄λ₯Ό μλννμ¬ μκ°μ μ μ½νκ³ μ€μλ₯Ό μ€μ΄κ³ μ νμ΅λλ€.
λλ νλΌλ―Έν° μ²λ¦¬
λλμ νλΌλ―Έν°λ₯Ό ν¨μ¨μ μΌλ‘ μ²λ¦¬νκΈ° μν΄ `λ³λ ¬ μ²λ¦¬`λ₯Ό νμ©νμ¬ μμ μλλ₯Ό μ΅μ ννμ΅λλ€.
Rate Limit λ¬Έμ
λλ νλΌλ―Έν° μ²λ¦¬ μ€ API νΈμΆ μ νμ΄ λ°μνμ¬ μ΄λ₯Ό `μ§μ λ°±μ€ν`μ `λλ€ μ§ν°`λ‘ ν΄κ²°νμ΅λλ€.
μλ μ²λ¦¬
μ½μμμ νλΌλ―Έν°λ₯Ό κ΄λ¦¬νλ κ³Όμ μμ λ°μν μ μλ μ€μλ₯Ό λ°©μ§νκΈ° μν΄ μμ μ μλννμ΅λλ€.
CLI κ°λ°κ³Ό Cobra νλ μμν¬
μ΄ λꡬλ Go μΈμ΄μ Cobra νλ μμν¬λ₯Ό νμ©νμ¬ μ€κ³λμμ΅λλ€.
νΉν Cobraλ ν¨μ¨μ μ΄κ³ μ§κ΄μ μΈ CLI κ°λ°μ κ°λ₯νκ² νλ©°, μμ μ±κ³Ό νμ₯μ±μ λμμ μ 곡ν©λλ€.
Cobraλ λͺ
λ Ήμ΄ κΈ°λ° CLI κ°λ°μ λ¨μννλ©΄μλ κ°λ ₯ν κΈ°λ₯μ μ 곡νλ Go μΈμ΄μ νμ€ νλ μμν¬μ
λλ€.
λ€μκ³Ό κ°μ μ£Όμ μ₯μ μ΄ μμ΅λλ€
- λͺ λ Ήμ΄ κ΅¬μ‘°ν : λͺ λ Ήμ΄λ₯Ό λ 립μ μΌλ‘ ꡬννλ©°, κ³μΈ΅μ νΈλ¦¬ κ΅¬μ‘°λ‘ νμ₯ν μ μμ΄ λ³΅μ‘ν CLI μ€κ³μ μ ν©ν©λλ€.
- νλκ·Έ μ§μ : λ€μν μ΅μ νλκ·Έ(-region, -profile λ±)λ₯Ό μΆκ°ν΄ μ¬μ©μ κ²½νμ κ°μ νκ³ μ μ°μ±μ μ 곡ν©λλ€.
- μλ μμ± : Zsh, Bash, Fish λ± λ€μν μ νκ²½μμ λͺ λ Ήμ΄ μλ μμ± κΈ°λ₯μ μ 곡νμ¬ κ°λ° μμ°μ±μ λμ λλ€.
λν, Goμ κ°λ ₯ν νλ«νΌ λ
립μ±μ νμ©ν΄ λ€μν νκ²½μ λ§μΆ λ°μ΄λ리λ₯Ό μμ½κ² μμ±ν μ μμ΅λλ€.
# macOS Apple Silicon (M1/M2/M3)
GOOS=darwin GOARCH=arm64 go build -o ssm-silicon-mac
# macOS Intel
GOOS=darwin GOARCH=amd64 go build -o ssm-intel-mac
# Windows
GOOS=windows GOARCH=amd64 go build -o ssm-windows.exe
π― ν΄κ²°νκ³ μ ν μ£Όμ λ¬Έμ
λ°λ³΅ μμ μλν
for _, env := range envs {
go func(env string) {
params, err := ssmClient.GetParameters(fmt.Sprintf("%s", env))
if err == nil {
jsonutil.WriteJSON(fmt.Sprintf("%s.json", env), params, true)
}
}(env)
}
π μ¬λ¬ νκ²½μ λν΄ νλΌλ―Έν°λ₯Ό μ‘°ννκ³ μ λ‘λνλ μμ μ CLIλ‘ κ°μν.
Rate Limit λ¬Έμ μν
baseDelay := 200 * time.Millisecond
for attempt := 1; attempt <= maxRetries; attempt++ {
err := ssmClient.PutParameters(params)
if err == nil {
break
}
time.Sleep(baseDelay * time.Duration(1<<attempt) + time.Duration(rand.Int63n(int64(100*time.Millisecond))))
}
π μ§μ λ°±μ€νλ‘ μ¬μλ κ°κ²©μ 2λ°°μ© λλ¦¬κ³ , λλ€ μ§ν°λ‘ 0~100msμ 무μμ μ§μ°μ μΆκ°ν΄ νΈμΆ μΆ©λμ λ°©μ§ν©λλ€.
μμ μλμ μμ μ± ν₯μ
sem := make(chan struct{}, 5)
var wg sync.WaitGroup
for _, param := range params {
sem <- struct{}{}
wg.Add(1)
go func(param string) {
defer func() { <-sem }()
defer wg.Done()
ssmClient.PutParameter(param)
}(param)
}
wg.Wait()
π κ³ λ£¨ν΄κ³Ό μΈλ§ν¬μ΄λ₯Ό νμ©ν λμμ± μ²λ¦¬λ‘ λκ·λͺ¨ μμ μ μλ μ΅μ ν.
β‘ μ±λ₯ μ΅μ νλ₯Ό μν ν΅μ¬ λ°©λ²λ€
λ©λͺ¨λ¦¬ κ΄λ¦¬μ μ¬μ¬μ©μΌλ‘ ν¨μ¨ ν₯μ
Buffered I/O νμ©
- νμΌ μ½κΈ°μ μ°κΈ° μμ μμ `bufio.NewReader`μ `bufio.NewWriter`λ₯Ό μ¬μ©ν΄ λ©λͺ¨λ¦¬λ₯Ό ν¨μ¨μ μΌλ‘ μ¬μ©νκ³ μμ μλλ₯Ό λμμ΅λλ€.
reader := bufio.NewReader(file)
decoder := json.NewDecoder(reader)
writer := bufio.NewWriter(file)
encoder := json.NewEncoder(writer)
encoder.SetIndent("", " ")
encoder.Encode(data)
writer.Flush()
π ν° νμΌ μ²λ¦¬ μ λ©λͺ¨λ¦¬ μ¬μ©λμ μ€μ΄κ³ , λμ€ν¬ I/O μμ μκ°μ λ¨μΆ.
ꡬ쑰체μ ν¬μΈν°μ νμ©
- AWS SDK ν΄λΌμ΄μΈνΈλ₯Ό `SSMClient` ꡬ쑰체μ μΊ‘μννμ¬ λ©λͺ¨λ¦¬ μ¬μ¬μ©μ±μ λμ΄κ³ , μμ μ€ λ°λ³΅ μ΄κΈ°νλ₯Ό λ°©μ§.
type SSMClient struct {
client *ssm.Client
sts *sts.Client
}
func NewSSMClient(profile, region string) *SSMClient {
cfg, _ := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(region),
config.WithSharedConfigProfile(profile),
)
return &SSMClient{
client: ssm.NewFromConfig(cfg),
sts: sts.NewFromConfig(cfg),
}
}
π AWS ν΄λΌμ΄μΈνΈλ₯Ό λ°λ³΅ μμ±νλ λμ μ¬μ¬μ©νμ¬ μ΄κΈ°ν λΉμ© κ°μ.
λμμ± μ²λ¦¬λ‘ μμ μλ ν₯μ
κ³ λ£¨ν΄κ³Ό WaitGroup
- `AWS SSM API` νΈμΆμ κ³ λ£¨ν΄μΌλ‘ λ³λ ¬ννμ¬ μμ μλλ₯Ό μ΅μ ν.
- `sync.WaitGroup`μ νμ©ν΄ λ³λ ¬ μμ μ μλ£λ₯Ό λκΈ°ν.
var wg sync.WaitGroup
for _, param := range params {
wg.Add(1)
go func(param string) {
defer wg.Done()
}(param)
}
wg.Wait()
π μ¬λ¬ νκ²½μ νλΌλ―Έν°λ₯Ό λμμ μ‘°ννκ±°λ μ λ‘λνμ¬ μ²λ¦¬ μλ μ¦κ°.
μΈλ§ν¬μ΄λ₯Ό νμ©ν λμ μμ μ ν
- μ±λ(`chan struct{}`)μ μΈλ§ν¬μ΄λ‘ μ¬μ©ν΄ λ³λ ¬ μμ μλ₯Ό μ μ΄.
sem := make(chan struct{}, 5) // λμ μμ
5κ° μ ν
for _, param := range params {
sem <- struct{}{}
go func(param string) {
defer func() { <-sem }()
// μμ
μν
}(param)
}
π AWS Rate Limit μ΄κ³Όλ₯Ό λ°©μ§νλ©΄μλ μ΅λ λ³λ ¬ μμ μ²λ¦¬ κ°λ₯.
μ§μ λ°±μ€νμ λλ€ μ§ν°λ‘ μμ μ± ν보
- AWS Rate Limitμ λλ¬ν κ²½μ°, μ§μ λ°±μ€νμ λλ€ μ§ν°λ₯Ό μ μ©ν μ¬μλ λ‘μ§μΌλ‘ μμ μ±μ λμ.
baseDelay := 200 * time.Millisecond
attempt := 0
for {
attempt++
err := ssmClient.PutParameters(map[string]interface{}{paramPath: value}, "")
if err == nil {
break
}
backoff := baseDelay * time.Duration(1<<uint(attempt))
jitter := time.Duration(rand.Int63n(int64(100 * time.Millisecond)))
time.Sleep(backoff + jitter)
}
π AWS API νΈμΆ μ€ν¨ μ μ§μ λ°±μ€νμ λλ€ μ§ν°λ₯Ό νμ©ν΄ νΈμΆ μΆ©λμ λ°©μ§νλ©° μμ μ±κ³΅λ₯ μ λμ΄λ λ°©μμΌλ‘ ν΄κ²°.
JSON λ°μ΄ν° μ΅μ ν μ²λ¦¬
- μ€μ²©λ JSON ꡬ쑰 ννν λ° μ¬κ΅¬μ±:
- AWS SSMμ νλΌλ―Έν° νμμ λ§κ² μ€μ²©λ JSON λ°μ΄ν°λ₯Ό ννννκ±°λ λ€μ μ€μ²©λ κ΅¬μ‘°λ‘ λ³ν.
func flattenParameters(prefix string, params interface{}, flatParams map[string]interface{}) { switch paramsTyped := params.(type) { case map[string]interface{}: for key, value := range paramsTyped { fullKey := filepath.Join(prefix, key) flattenParameters(fullKey, value, flatParams) } default: flatParams[prefix] = params } }
π JSON λ°μ΄ν°μ λ³ν κ³Όμ μ μλννμ¬ κ°λ°μμ μμμ λΆλ΄ κ°μ.
CLI μ€κ³μ μ¬μ©μ κ²½ν κ°ν
- λͺ
λ Ήμ΄ μ€κ³μ νλκ·Έ κ΄λ¦¬
- Cobra νλ μμν¬λ₯Ό νμ©ν΄ μ§κ΄μ μΈ CLI λͺ λ Ήμ΄ μ€κ³.
var rootCmd = &cobra.Command{ Use: "ssm", Short: "AWS SSM Parameter Store κ΄λ¦¬ CLI", } func init() { rootCmd.AddCommand(getCmd, putCmd, completionCmd, versionCmd) }
π μ¬μ©μ μΉνμ λͺ λ Ήμ΄μ νλκ·Έλ₯Ό ν΅ν΄ CLI μ κ·Όμ± ν₯μ.
π±οΈ AWS μ½μ? κ·Έκ±° μμ§λ μ¨μ?
μ΄ CLI λꡬλ₯Ό ν΅ν΄ λ€μκ³Ό κ°μ κ²°κ³Όλ₯Ό μ»μ μ μμμ΅λλ€
β±οΈ μκ° μ μ½: λ°λ³΅ μμ μλνλ‘ μμμ μκ°μ λν μ κ°νμ΅λλ€.
π μλ μ κ·Έλ μ΄λ: λ³λ ¬ μ²λ¦¬μ λμμ± μ΅μ νλ‘ μμ ν¨μ¨μ ν¬κ² ν₯μμμΌ°μ΅λλ€.
π μμ μ± κ°ν: Rate Limit λ¬Έμ λ₯Ό μ§μ λ°±μ€νμ λλ€ μ§ν°λ‘ ν΄κ²°νλ©° μμ μ μμ μ±μ ν보νμ΅λλ€.
μ΄μ λ°λ³΅ μμ μ λΆλ΄μμ λ²μ΄λ, λ μ€μν λ¬Έμ μ μ§μ€ν μ μκ² λμμ΅λλ€.
κ·Έλ¦¬κ³ λ¬΄μ보λ€, λ§€λ² Consoleμ μ΄μ§ μμλ λλ€λ μ μ λ§ν νμλ μκ² μ£ ? π
'GO' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
AWS Lambda μ Golang base64 Encoding μ μ©νκΈ° (0) | 2024.01.11 |
---|---|
AWS Lambda μ go routine, channel μ μ©μΌλ‘ μ€ν μλ λν κ°μ (0) | 2024.01.06 |
Go λ? (0) | 2023.12.26 |