[k6] k6-operator 설치


Kubernetes에서 서비스를 운영하기 전에는 필수적으로 거쳐야 할 단계가 성능테스트, 부하테스트라고 생각한다.

다만 성능테스트랑 부하테스트 이 둘을 제대로 해본 적이 없는 나에게는 큰 난제로 다가왔다.

일단은! 테스트 Tool을 정하는 과정에서 전통적인 JMeter는 호기심이 없었고, Python 기반인 Locust나 JS기반인 k6가 좀 끌렸다.

Locust랑 k6는 둘다 GitHub에 별도 많은 인기있는 Tool들이지만 Grafana랑 뗄레야 뗄 수 없는 관계인 나에게는 k6가 더 매력적이었다.

그렇게 k6를 정하고 설치해보기로 하였다.




k6 자체는 가벼운 툴이면서도 사용하기도 되게 쉬웠다.

가상 유저인 vu의 스레드들도 가볍고, 공식문서를 확인해보니 vu만큼 스레드를 만드는 것이 아니라 loop문을 도는 것 같다.

하나의 VM으로 테스트해도 충분할 것 같지만 새로운 기술을 참지 못하는 나로서는 k6-operator가 산뜻하게 다가왔다.

k6-operator는 흔히 k8s에서 사용하는 operator처럼 k6를 kubernetes에서 띄워주는 역할을 한다.

예를 들자면 내가 100vu로 초당 1회의 요청을 k6로 테스트한다고 가정할 시, 이를 k6-operator를 사용해서 parallelism을 4로 설정하면 k6의 test pod들이 4개가 떠서 각각 25vu로 초당 1회의 요청을 분산해서 한다.

왜 이렇게 불편하게 사용하는지에 대한 의문이 있을 수 있는데 k6-operator를 사용한다면 worker node에 pod들이 분산되게 때문에 비교적 인프라에 대한 자원을 분산할 수 있는 장점이 있다.

실제로 1개의 vm에서 k6를 실행했을 경우, 원하는 tps를 내기 위해서는 vm의 스펙을 유동적으로 조절해야했다.

그러면 k6-operator는 어떻게 설치했는지 기록해봐야겠다.




kubernetes에서 Tool을 설치하기 제일 편한 방법은 개인적으로 helm이라고 생각한다.

버전관리도 편하고, vaules.yaml으로 관리되기에 재사용성도 뛰어나다고 생각했기에 k6-operator(이하 k6)또한 helm으로 설치하였다.

아래는 values.yaml이며, 다른 설정은 크게 건드리지 않고 tolerations에 pool만 k6용으로 따로 분리하였다.

# @schema
# required: false
# type: object
# @schema
global:
# @schema
# required: false
# type: object
# @schema
# global.image — Global image configuration
image:
# @schema
# required: false
# type: string
# @schema
# global.image.registry — Global image registry to use if it needs to be overridden for some specific use cases (e.g local registries, custom images, …)
registry: “”

# @schema
# required: false
# type: array
# @schema
# global.image.pullSecrets — Optional set of global image pull secrets
pullSecrets: []

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# customAnnotations — Custom Annotations to be applied on all resources
customAnnotations: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# podAnnotations — Custom Annotations to be applied on all pods
podAnnotations: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# customLabels — Custom Label to be applied on all resources
customLabels: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# podLabels — Custom Label to be applied on all pods
podLabels: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# nodeSelector — Node Selector to be applied on all containers
nodeSelector: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# affinity — Affinity to be applied on all containers
affinity: {}

# @schema
# additionalProperties: true
# required: false
# type: array
# @schema
# tolerations — Tolerations to be applied on all containers
tolerations:
– key: “pool”
operator: “Equal”
value: “k6-node-pool”

# @schema
# required: false
# type: boolean
# @schema
# installCRDs — Installs CRDs as part of the release
installCRDs: true

# @schema
# required: false
# type: object
# @schema
# namespace — Namespace creation
namespace:
# @schema
# required: false
# type: boolean
# @schema
# namespace.create — create the namespace (default: true)
create: false

# @schema
# required: false
# type: object
# @schema
prometheus:
# @schema
# required: false
# type: boolean
# @schema
# prometheus.enabled — enables the prometheus metrics scraping (default: false)
enabled: false

# @schema
# required: false
# type: object
# @schema
authProxy:
# @schema
# required: false
# type: boolean
# @schema
# authProxy.enabled — enables the protection of /metrics endpoint. (https://github.com/brancz/kube-rbac-proxy)
enabled: false
# @schema
# required: false
# type: object
# @schema
image:
# @schema
# required: false
# type: string
# @schema
# authProxy.image.registry
registry: gcr.io
# @schema
# required: false
# type: string
# @schema
# authProxy.image.repository — rbac-proxy image repository
repository: kubebuilder/kube-rbac-proxy
# @schema
# required: false
# type: string
# @schema
# authProxy.image.tag — rbac-proxy image tag
tag: v0.15.0
# @schema
# required: false
# type: string
# @schema
# authProxy.image.pullPolicy — pull policy for the image can be Always, Never, IfNotPresent (default: IfNotPresent)
pullPolicy: IfNotPresent

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# authProxy.resources — rbac-proxy resource limitation/request
resources: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# authProxy.livenessProbe — Liveness probe in Probe format
livenessProbe: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# authProxy.readinessProbe — Readiness probe in Probe format
readinessProbe: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# authProxy.containerSecurityContext — A security context defines privileges and access control settings for the container.
containerSecurityContext: {}

# @schema
# required: false
# type: object
# @schema
# manager — controller-manager configuration
manager:
# @schema
# required: false
# type: integer
# @schema
# manager.replicas — number of controller-manager replicas (default: 1)
replicas: 1
# @schema
# required: false
# type: object
# @schema
serviceAccount:
# @schema
# required: false
# type: string
# @schema
# manager.serviceAccount.name — kubernetes service account for the k6 manager
name: k6-operator-controller
# @schema
# required: false
# type: boolean
# @schema
# manager.serviceAccount.create — create the service account (default: true)
create: true
# @schema
# required: false
# type: object
# @schema
# manager.image — controller-manager image configuration
image:
# @schema
# required: false
# type: string
# @schema
# manager.image.registry
registry: ghcr.io
# @schema
# required: false
# type: string
# @schema
# manager.image.repository — controller-manager image repository
repository: grafana/k6-operator
# @schema
# required: false
# type: string
# @schema
# manager.image.tag — controller-manager image tag
tag: controller-v0.0.18
# @schema
# required: false
# type: string
# @schema
# manager.image.pullPolicy — pull policy for the image possible values Always, Never, IfNotPresent (default: IfNotPresent)
pullPolicy: IfNotPresent

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# manager.livenessProbe — Liveness probe in Probe format
livenessProbe: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# manager.readinessProbe — Readiness probe in Probe format
readinessProbe: {}

# @schema
# required: false
# type: array
# @schema
# manager.env — List of environment variables to set in the controller
env: []

# @schema
# required: false
# type: array
# @schema
# manager.envFrom — List of sources to populate environment variables in the controller
envFrom: []

# @schema
# required: false
# type: object
# @schema
# manager.resources — controller-manager Resources definition
resources:
# @schema
# required: false
# type: object
# @schema
# manager.resources.limits — controller-manager Resources limits
limits:
# @schema
# required: false
# type: string
# @schema
# manager.resources.limits.cpu — controller-manager CPU limit (Max)
cpu: 100m
# @schema
# required: false
# type: string
# @schema
# manager.resources.limits.memory — controller-manager Memory limit (Max)
memory: 100Mi
# @schema
# required: false
# type: object
# @schema
# manager.resources.requests — controller-manager Resources requests
requests:
# @schema
# required: false
# type: string
# @schema
# manager.resources.requests.cpu — controller-manager CPU request (Min)
cpu: 100m
# @schema
# required: false
# type: string
# @schema
# manager.resources.requests.memory — controller-manager Memory request (Min)
memory: 50Mi

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# manager.containerSecurityContext — A security context defines privileges and access control settings for the container.
containerSecurityContext: {}

# @schema
# additionalProperties: true
# required: false
# type: object
# @schema
# manager.podSecurityContext — A security context defines privileges and access control settings for a pod.
podSecurityContext: {}

그 후에는 아래 명령어로 설치를 하였다.

helm -n k6 upgrade --create-namespace --install k6-operator grafana/k6-operator -f values-dev.yaml

이렇듯 helm으로 설치는 간단한데 위 처럼 upgrade 명령어로 할 때는 버전에 크게 구애 안 받는 helm만 위 명령어를 권장한다.

다음 게시글에는 k6-operator에서 부하테스트를 실행하고, prometheus에서 메트릭 보는 방법을 작성해야겠다.

Leave a Comment