Prometheus ๋ฐ KEDA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Kubernetes ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •

Prometheus ๋ฐ KEDA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Kubernetes ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •ํ’์„ ๋งจ by Cimuanos

ํ™•์žฅ์„ฑ์€ ํด๋ผ์šฐ๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•ต์‹ฌ ์š”๊ตฌ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. Kubernetes๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ ์ ˆํ•œ ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด ๋ณต์ œ๋ณธ ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ๋งŒํผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ReplicaSet โ€” ํ•˜์ง€๋งŒ ์ด๋Š” ์ˆ˜๋™ ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค.

Kubernetes๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž๋™์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: ๋ฐฐํฌ ๋˜๋Š” ReplicaSet) Horizon Pod Autoscaler ์‚ฌ์–‘์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์–ธ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ž๋™ ์กฐ์ •์˜ ๊ธฐ๋ณธ ๊ธฐ์ค€์€ CPU ์‚ฌ์šฉ๋Ÿ‰ ์ง€ํ‘œ(๋ฆฌ์†Œ์Šค ์ง€ํ‘œ)์ด์ง€๋งŒ ์‚ฌ์šฉ์ž ์ง€์ • ์ง€ํ‘œ์™€ ์™ธ๋ถ€ ์ œ๊ณต ์ง€ํ‘œ๋ฅผ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒ€ Mail.ru์˜ Kubernetes aaS ์™ธ๋ถ€ ์ธก์ •ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•˜์—ฌ Kubernetes ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž๋™์œผ๋กœ ํ™•์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๊ธฐ์‚ฌ๋ฅผ ๋ฒˆ์—ญํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ €์ž๋Š” Prometheus๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์ง‘๋œ HTTP ์•ก์„ธ์Šค ์š”์ฒญ ์ธก์ •ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Pod์˜ ์ˆ˜ํ‰์  Auto Scaling ๋Œ€์‹  ์˜คํ”ˆ ์†Œ์Šค Kubernetes ์—ฐ์‚ฐ์ž์ธ KEDA(Kubernetes Event Driven Auto Scaling)๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์›Œํฌ๋กœ๋“œ์— ๋Œ€ํ•œ ์›ํ™œํ•œ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •(XNUMX์—์„œ/XNUMX๊นŒ์ง€ ํฌํ•จ)์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ˜ํ‰ ํฌ๋“œ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •๊ธฐ์™€ ํ†ตํ•ฉ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ: GitHub์˜.

์‹œ์Šคํ…œ์˜ ๊ฐ„๋žตํ•œ ๊ฐœ์š”

Prometheus ๋ฐ KEDA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Kubernetes ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž๋™ ํฌ๊ธฐ ์กฐ์ •

๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋ชจ๋“  ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•œ ์„ค๋ช…์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  1. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Prometheus ํ˜•์‹์œผ๋กœ HTTP ์ ์ค‘ ํšŸ์ˆ˜ ์ธก์ •ํ•ญ๋ชฉ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  2. Prometheus๋Š” ์ด๋Ÿฌํ•œ ์ธก์ •ํ•ญ๋ชฉ์„ ์ˆ˜์ง‘ํ•˜๋„๋ก ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  3. KEDA์˜ Prometheus ์Šค์ผ€์ผ๋Ÿฌ๋Š” HTTP ์ ์ค‘ ์ˆ˜์— ๋”ฐ๋ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž๋™์œผ๋กœ ํ™•์žฅํ•˜๋„๋ก ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

KEDA์™€ ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค

Prometheus๋Š” ์˜คํ”ˆ ์†Œ์Šค ์‹œ์Šคํ…œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๊ฒฝ๊ณ  ํˆดํ‚ท์ž…๋‹ˆ๋‹ค. ํด๋ผ์šฐ๋“œ ๋„ค์ดํ‹ฐ๋ธŒ ์ปดํ“จํŒ… ์žฌ๋‹จ. ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ์ธก์ •ํ•ญ๋ชฉ์„ ์ˆ˜์ง‘ํ•˜์—ฌ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ผ ํŒŒ๋‚˜ ๋˜๋Š” Kubernetes API์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๊ธฐํƒ€ ์‹œ๊ฐํ™” ๋„๊ตฌ.

KEDA๋Š” ์Šค์ผ€์ผ๋Ÿฌ ๊ฐœ๋…์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” KEDA์™€ ์™ธ๋ถ€ ์‹œ์Šคํ…œ ์‚ฌ์ด์˜ ๊ฐ€๊ต ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์Šค์ผ€์ผ๋Ÿฌ ๊ตฌํ˜„์€ ๊ฐ ๋Œ€์ƒ ์‹œ์Šคํ…œ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋ฉฐ ์—ฌ๊ธฐ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ KEDA๋Š” ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™ ์Šค์ผ€์ผ๋ง์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

์Šค์ผ€์ผ๋Ÿฌ๋Š” Kafka, Redis, Prometheus์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, KEDA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Prometheus ์ธก์ •ํ•ญ๋ชฉ์„ ๊ธฐ์ค€์œผ๋กœ Kubernetes ๋ฐฐํฌ๋ฅผ ์ž๋™์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œํ—˜ ์ ์šฉ

Golang ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ HTTP๋ฅผ ํ†ตํ•œ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ๋‘ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. Prometheus Go ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ณ„์ธกํ•˜๊ณ  ์ ์ค‘ ํšŸ์ˆ˜๊ฐ€ ํฌํ•จ๋œ http_requests ์ง€ํ‘œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Prometheus ์ธก์ •ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—”๋“œํฌ์ธํŠธ๋Š” URI์— ์žˆ์Šต๋‹ˆ๋‹ค. /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ GET ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ‚ค ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค(access_count) Redis์—์„œ. ์ด๋Š” HTTP ํ•ธ๋“ค๋Ÿฌ์˜ ์ผ๋ถ€๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  Prometheus ์ธก์ •ํ•ญ๋ชฉ์„ ํ™•์ธํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ธก์ •ํ•ญ๋ชฉ ๊ฐ’์€ ๊ฐ’๊ณผ ๋™์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. access_count ๋ ˆ๋””์Šค์—์„œ.
    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋‹ค์Œ์„ ํ†ตํ•ด Kubernetes์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. Deployment. ์„œ๋น„์Šค๋„ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค ClusterIP, ์ด๋ฅผ ํ†ตํ•ด Prometheus ์„œ๋ฒ„๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธก์ •ํ•ญ๋ชฉ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐฐํฌ ๋งค๋‹ˆํŽ˜์ŠคํŠธ.

ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค ์„œ๋ฒ„

Prometheus ๋ฐฐํฌ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋Š” ๋‹ค์Œ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • ConfigMap โ€” Prometheus ๊ตฌ์„ฑ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  • Deployment โ€” Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์— Prometheus๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๊ฒฝ์šฐ
  • ClusterIP โ€” UI Prometheus์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ ์„œ๋น„์Šค
  • ClusterRole, ClusterRoleBinding ะธ ServiceAccount โ€” Kubernetes์—์„œ ์„œ๋น„์Šค ์ž๋™ ๊ฐ์ง€(์ž๋™ ๊ฒ€์ƒ‰)์šฉ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— Prometheus ์‹คํ–‰์„ ์œ„ํ•œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ.

KEDA ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค ScaledObject

์Šค์ผ€์ผ๋Ÿฌ๋Š” ์ธก์ •ํ•ญ๋ชฉ์„ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ KEDA ์‚ฌ์ด์˜ ๋ธŒ๋ฆฌ์ง€ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ScaledObject ๋ฐฐํฌ๋ฅผ ์ด๋ฒคํŠธ ์†Œ์Šค(์ด ๊ฒฝ์šฐ Prometheus)์™€ ๋™๊ธฐํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐฐํฌํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๋ฆฌ์†Œ์Šค์ž…๋‹ˆ๋‹ค.

ScaledObject ๋ฐฐํฌ ํ™•์žฅ ์ •๋ณด, ์ด๋ฒคํŠธ ์†Œ์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(์˜ˆ: ์—ฐ๊ฒฐ ๋น„๋ฐ€, ๋Œ€๊ธฐ์—ด ์ด๋ฆ„), ํด๋ง ๊ฐ„๊ฒฉ, ๋ณต๊ตฌ ๊ธฐ๊ฐ„ ๋ฐ ๊ธฐํƒ€ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋ฐฐํฌ๋ฅผ ํ™•์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ์ž๋™ ํฌ๊ธฐ ์กฐ์ • ๋ฆฌ์†Œ์Šค(HPA ์ •์˜)๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด์ผ ๋•Œ ScaledObject ์‚ญ์ œ๋˜๋ฉด ํ•ด๋‹น HPA ์ •์˜๊ฐ€ ์ง€์›Œ์ง‘๋‹ˆ๋‹ค.

์ •์˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ScaledObject ์ด ์˜ˆ์—์„œ๋Š” ์Šค์ผ€์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Prometheus:

apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))

๋‹ค์Œ ์‚ฌํ•ญ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

  1. ๊ทธ๋Š” ๋‹ค์Œ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. Deployment ์ด๋ฆ„์œผ๋กœ go-prom-app.
  2. ํŠธ๋ฆฌ๊ฑฐ ์œ ํ˜• - Prometheus. Prometheus ์„œ๋ฒ„ ์ฃผ์†Œ๋Š” ์ธก์ •ํ•ญ๋ชฉ ์ด๋ฆ„, ์ž„๊ณ„๊ฐ’ ๋ฐ PromQL ์ฟผ๋ฆฌ, ์ด๋Š” ์‚ฌ์šฉ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. PromQL ์ฟผ๋ฆฌ - sum(rate(http_requests[2m])).
  3. ์— ๋”ฐ๋ฅด๋ฉด pollingInterval,KEDA๋Š” XNUMX์ดˆ๋งˆ๋‹ค ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค์—๊ฒŒ ํ‘œ์ ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. (minReplicaCount), ์ตœ๋Œ€ Pod ์ˆ˜๋Š” ๋‹ค์Œ์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. maxReplicaCount (์ด ์˜ˆ์—์„œ๋Š” - XNUMX).

์„ค์น˜ ๊ฐ€๋Šฅ minReplicaCount XNUMX๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ KEDA๋Š” XNUMX๋Œ€XNUMX ๋ฐฐํฌ๋ฅผ ํ™œ์„ฑํ™”ํ•œ ๋‹ค์Œ ์ถ”๊ฐ€ ์ž๋™ ํ™•์žฅ์„ ์œ„ํ•ด HPA๋ฅผ ๊ณต๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์—ญ์ˆœ, ์ฆ‰ XNUMX์—์„œ XNUMX์œผ๋กœ ํฌ๊ธฐ ์กฐ์ •๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ˆ์—์„œ๋Š” ์ด๊ฒƒ์ด ์ฃผ๋ฌธํ˜• ์‹œ์Šคํ…œ์ด ์•„๋‹ˆ๋ผ HTTP ์„œ๋น„์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— XNUMX์„ ์„ ํƒํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์ž๋™ ํ™•์žฅ์˜ ๋งˆ๋ฒ•

์ž„๊ณ„๊ฐ’์€ ๋ฐฐํฌ๋ฅผ ํ™•์žฅํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ฆฌ๊ฑฐ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ์˜ˆ์—์„œ๋Š” PromQL ์ฟผ๋ฆฌ sum(rate (http_requests [2m])) ์ง€๋‚œ XNUMX๋ถ„ ๋™์•ˆ ์ธก์ •๋œ ์ง‘๊ณ„๋œ HTTP ์š”์ฒญ ๋น„์œจ(์ดˆ๋‹น ์š”์ฒญ ์ˆ˜)์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ž„๊ณ„๊ฐ’์ด XNUMX์ด๋ฏ€๋กœ ๊ฐ’์ด XNUMX๊ฐœ ๋ฏธ๋งŒ์ธ ๋™์•ˆ XNUMX๊ฐœ ๋ฏธ๋งŒ์ด ๋œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. sum(rate (http_requests [2m])) XNUMX๊ฐœ ๋ฏธ๋งŒ. ๊ฐ’์ด ์ฆ๊ฐ€ํ•˜๋ฉด ๋งค๋ฒˆ ํ•˜์œ„๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. sum(rate (http_requests [2m])) 12๊ฐœ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ’์ด 14~XNUMX์ด๋ฉด Pod ์ˆ˜๋Š” XNUMX๊ฐœ์ž…๋‹ˆ๋‹ค.

์ด์ œ ์„ค์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

์‚ฌ์ „ ์„ค์ •

Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์™€ ๊ตฌ์„ฑ๋œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. kubectl. ์ด ์˜ˆ์—์„œ๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. minikube, ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๊ฒƒ์„ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ค์น˜ํ•˜๋ ค๋ฉด ์ง€๋„๋ ฅ.

Mac์— ์ตœ์‹  ๋ฒ„์ „์„ ์„ค์น˜ํ•˜์„ธ์š”:

curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/

์„ธํŠธ ์ฟ  ๋ฒ ํ‹€Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์— ์•ก์„ธ์Šคํ•ฉ๋‹ˆ๋‹ค.

Mac์— ์ตœ์‹  ๋ฒ„์ „์„ ์„ค์น˜ํ•˜์„ธ์š”:

curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version

KEDA ์„ค์น˜

KEDA๋ฅผ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ทธ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ ๋ชฉ๋ก์— ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜. ์ €๋Š” ๋ชจ๋†€๋ฆฌ์‹ YAML์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml

KEDA์™€ ๊ทธ ๊ตฌ์„ฑ์š”์†Œ๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ์„ค์น˜๋ฉ๋‹ˆ๋‹ค. keda. ํ™•์ธํ•  ๋ช…๋ น:

kubectl get pods -n keda

KEDA Operator๊ฐ€ ์‹œ์ž‘๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ํ›„ ๋‹ค์Œ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. Running State. ๊ทธ ํ›„์— ๊ณ„์†ํ•˜์‹ญ์‹œ์˜ค.

Helm์„ ์‚ฌ์šฉํ•˜์—ฌ Redis ์„ค์น˜

Helm์ด ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์•ˆ๋‚ด. Mac์— ์„ค์น˜ํ•˜๋Š” ๋ช…๋ น:

brew install kubernetes-helm
helm init --history-max 200

helm init ๋กœ์ปฌ ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์„ค์น˜๋„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Tiller Kubernetes ํด๋Ÿฌ์Šคํ„ฐ์—.

kubectl get pods -n kube-system | grep tiller

Tiller ํฌ๋“œ๊ฐ€ ์‹คํ–‰ ์ค‘ ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

๋ฒˆ์—ญ๊ฐ€์˜ ์ชฝ์ง€: ์ž‘์„ฑ์ž๋Š” Tiller ์„œ๋ฒ„ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•˜๋Š” Helm@2๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ Helm@3์ด ์ ํ•ฉํ•˜๋ฏ€๋กœ ์„œ๋ฒ„ ๋ถ€๋ถ„์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Helm์„ ์„ค์น˜ํ•œ ํ›„ Redis๋ฅผ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ํ•˜๋‚˜์˜ ๋ช…๋ น์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis

Redis๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

kubectl get pods/redis-server-master-0

Redis๊ฐ€ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. Running.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ

๋ฐฐํฌ ๋ช…๋ น:

kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created

๋ชจ๋“  ๊ฒƒ์ด ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

kubectl get pods -l=app=go-prom-app

Redis๊ฐ€ ์ƒํƒœ์— ๋“ค์–ด๊ฐˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. Running.

Prometheus ์„œ๋ฒ„ ๋ฐฐํฌ

Prometheus ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Prometheus์šฉ Kubernetes ์„œ๋น„์Šค ๊ฒ€์ƒ‰. ์„œ๋น„์Šค ๋ ˆ์ด๋ธ”์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ Pod๋ฅผ ๋™์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep

๋ฐฐ์น˜ํ•˜๋‹ค, ํŒŒ๊ฒฌํ•˜๋‹ค:

kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created

๋ชจ๋“  ๊ฒƒ์ด ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

kubectl get pods -l=app=prometheus-server

ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค๊ฐ€ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์„ธ์š” Running.

์‚ฌ์šฉ kubectl port-forward Prometheus ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(๋˜๋Š” API ์„œ๋ฒ„)์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

KEDA ์ž๋™ ํ™•์žฅ ๊ตฌ์„ฑ ๋ฐฐํฌ

์ƒ์„ฑํ•˜๋Š” ๋ช…๋ น ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

KEDA ์šด์˜์ž ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"

์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ํ™•์ธํ•˜์„ธ์š”. ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. minReplicaCount 1๊ณผ ๊ฐ™์Œ:

kubectl get pods -l=app=go-prom-app

HPA ๋ฆฌ์†Œ์Šค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

kubectl get hpa

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s

์ƒํƒœ ํ™•์ธ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•ก์„ธ์Šค

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ REST ์—”๋“œํฌ์ธํŠธ์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜์„ธ์š”.

kubectl port-forward service/go-prom-app-service 8080

์ด์ œ ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Go ์•ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. http://localhost:8080. ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์„ธ์š”.

curl http://localhost:8080/test

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1

์ด ์‹œ์ ์—์„œ Redis๋„ ํ™•์ธํ•ด๋ณด์„ธ์š”. ๋‹น์‹ ์€ ๊ทธ ์—ด์‡ ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค access_count 1๋กœ ์ฆ๊ฐ€:

kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"

์ธก์ •ํ•ญ๋ชฉ ๊ฐ’์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€์ง€ ํ™•์ธํ•˜์„ธ์š”. http_requests ๋˜‘๊ฐ™๋‹ค:

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1

๋ถ€ํ•˜ ์ƒ์„ฑ

์šฐ๋ฆฌ๋Š” ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค ์•ˆ๋…• โ€” ๋ถ€ํ•˜ ์ƒ์„ฑ์„ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ:

curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey

๋‹ค์Œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. Linux ๋˜๋Š” Windows.

์‹คํ–‰ํ•˜์„ธ์š”:

./hey http://localhost:8080/test

๊ธฐ๋ณธ์ ์œผ๋กœ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” 200๊ฐœ์˜ ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. Prometheus ์ธก์ •ํ•ญ๋ชฉ๊ณผ Redis๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201

PromQL ์ฟผ๋ฆฌ์—์„œ ๋ฐ˜ํ™˜๋œ ์‹ค์ œ ์ง€ํ‘œ ๊ฐ’์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}

์ด ๊ฒฝ์šฐ ์‹ค์ œ ๊ฒฐ๊ณผ๋Š” 1,686057971014493 ํ•„๋“œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. value. ์šฐ๋ฆฌ๊ฐ€ ์„ค์ •ํ•œ ์ž„๊ณ„๊ฐ’์€ 3์ด๋ฏ€๋กœ ์ด๋Š” ํ™•์žฅ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋” ๋งŽ์€ ๋ถ€ํ•˜!

์ƒˆ ํ„ฐ๋ฏธ๋„์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ Pod ์ˆ˜๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค.

kubectl get pods -l=app=go-prom-app -w

๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ€ํ•˜๋ฅผ ๋Š˜๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

./hey -n 2000 http://localhost:8080/test

์ž ์‹œ ํ›„ HPA๊ฐ€ ๋ฐฐํฌ๋ฅผ ํ™•์žฅํ•˜๊ณ  ์ƒˆ ํฌ๋“œ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. HPA๋ฅผ ํ™•์ธํ•˜์—ฌ ๋‹ค์Œ ์‚ฌํ•ญ์„ ํ™•์ธํ•˜์„ธ์š”.

kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s

๋กœ๋“œ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์œผ๋ฉด ํ•˜๋‚˜์˜ Pod๋งŒ ์‹คํ–‰๋˜๋Š” ์ง€์ ๊นŒ์ง€ ๋ฐฐํฌ๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ์‹ค์ œ ์ธก์ •ํ•ญ๋ชฉ(PromQL ์ฟผ๋ฆฌ์—์„œ ๋ฐ˜ํ™˜๋จ)์„ ํ™•์ธํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'

์ฒญ์†Œ

//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server

๊ฒฐ๋ก 

KEDA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์™ธ๋ถ€ ์ง€ํ‘œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Kubernetes ๋ฐฐํฌ๋ฅผ ์ž๋™์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(XNUMX๋ถ€ํ„ฐ). ์˜ˆ๋ฅผ ๋“ค์–ด Prometheus ์ง€ํ‘œ, Redis์˜ ๋Œ€๊ธฐ์—ด ๊ธธ์ด, Kafka ์ฃผ์ œ์˜ ์†Œ๋น„์ž ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

KEDA๋Š” ์™ธ๋ถ€ ์†Œ์Šค์™€ ํ†ตํ•ฉ๋˜๋ฉฐ Metrics Server๋ฅผ ํ†ตํ•ด ์ˆ˜ํ‰ํ˜• ํฌ๋“œ ์ž๋™ ์Šค์ผ€์ผ๋Ÿฌ(Horizontal Pod Autoscaler)์— ํ•ด๋‹น ๋ฉ”ํŠธ๋ฆญ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ–‰์šด์„ ๋น•๋‹ˆ๋‹ค!

๊ทธ ๋ฐ–์— ์ฝ์„ ๋‚ด์šฉ:

  1. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์ปจํ…Œ์ด๋„ˆ ๋ฐ Kubernetes๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ๋ฐ ๋ชจ๋ฒ” ์‚ฌ๋ก€.
  2. Kubernetes๋ฅผ ์œ„ํ•œ 90๊ฐœ ์ด์ƒ์˜ ์œ ์šฉํ•œ ๋„๊ตฌ: ๋ฐฐํฌ, ๊ด€๋ฆฌ, ๋ชจ๋‹ˆํ„ฐ๋ง, ๋ณด์•ˆ ๋“ฑ.
  3. Telegram์˜ Kubernetes ์ฃผ๋ณ€ ์ฑ„๋„.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€