사내 공용으로 구축되어 있는 Ngrinder를 Kubernetes로 이전하는 작업을 하였다. 버그인지 유저불량인지 간혹가다 컨트롤러가 멈추거나 에이전트가 정상 동작을 못하는 경우가 있었는데, 부하 테스트 용도로 사용되는 툴이므로 크리티컬 하지 않아 단순 재시작을 해줘왔다.

Kubernetes로 이전하면서 발생되는 장점은 liveness를 통해 컨트롤러가 멈추면 자동 재시작을 할 수 있다는 것이다. Daemonset으로 에이전트를 띄우면 향후에 에이전트 추가 시 자동으로 추가된 node에 배포되는 장점도 있다. Daemonset을 두 개 혹은 세 개 띄울 시에 컨트롤러에서 보여지는 에이전트 수가 배로 많아지게끔 할수도 있다.

컨트롤러 이미지는 ngrinder/controller:3.4.4, 에이전트 이미지는 ngrinder/agent:latest를 사용했다.

참고
– 이미지: https://hub.docker.com/r/ngrinder/controller/

Manifest

컨트롤러

컨트롤러의 경우 재시작 후에 데이터가 날라가지 않게 하기 위해서 raid1로 구성 하였다. 그리고 hostPath를 이용해서 컨트롤러가 띄워진 node의 /opt/ngrinder-controller에 pod의 컨트롤러 데이터를 연결하였다.

컨트롤러 용도의 node에는 컨트롤러 pod만 띄우고 에이전트 pod은 띄우지 않는게 관리상 편할 것이라고 판단되어 해당 node에 taint를 설정하고 컨트롤러 manifest에는 tolerations를 설정하였다.

굳이 loadbalancer 타입의 service를 생성해서 한 홉을 거쳐갈 필요는 없다고 생각되어, 컨트롤러 pod을 hostPort로 띄우고 해당 node를 사내 도메인에 직접 추가하였다. hostPort를 통해서 해당 node의 포트로 직접 서비스를 하려면 hostNetwork: true 설정을 꼭 해줘야 했다.

정상적으로 컨트롤러가 띄워져 있다면 /login에 요청을 했을 때 응답으로 200을 주기 때문에 해당 경로를 liveness의 판단 척도로 두었다.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: controller
  name: ngrinder-controller
spec:
  replicas: 1
  selector:
    matchLabels:
      app: controller
  template:
    metadata:
      labels:
        app: controller
    spec:
      nodeName: <컨트롤러 node 이름>
      hostNetwork: true
      tolerations:
      - key: "app"
        operator: "Equal"
        value: "controller"
        effect: "NoSchedule"
      volumes:
      - name: controller-data
        hostPath:
          path: "/opt/ngrinder-controller"
          type: DirectoryOrCreate
      containers:
      - image: ngrinder/controller:3.4.4
        name: controller
        livenessProbe:
          httpGet:
            path: /login
            port: 80
          periodSeconds: 5
          failureThreshold: 2
          initialDelaySeconds: 10
        volumeMounts:
        - mountPath: "/opt/ngrinder-controller"
          name: controller-data
        ports:
        — hostPort: 80
        — hostPort: 16001
        — hostPort: 12000
        — hostPort: 12001
        — hostPort: 12002
        — hostPort: 12003
        — hostPort: 12004
        — hostPort: 12005
        — hostPort: 12006
        — hostPort: 12007
        — hostPort: 12008
        — hostPort: 12009

에이전트

에이전트를 실행하기에 앞서 docker inspect ngrinder/agent | grep ENTRYPOINT를 보면 /scripts/run.sh를 실행하는걸 알 수 있다. 해당 스크립트를 보면 앞부분에 controller=$1가 나와있고 이것을 통해서 manifest 작성시 args로 컨트롤러 정보를 넘겨주면 간단하게 연결을 시킬 수 있다는 것을 알 수 있었다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ngrinder-agent
  labels:
    app: agent
spec:
  selector:
    matchLabels:
      app: agent
  template:
    metadata:
      labels:
        app: agent
    spec:
      containers:
      - name: agent
        image: ngrinder/agent:latest
        args: ["<컨트롤러 node 이름>"]