TeamCity 쿠버네티스로 이관하기

hbjs97·2024년 9월 2일

도커스웜에서 운영되던 teamcity를 쿠버네티스로 이관한 과정을 정리한다.
적절한 helm chart 가 없어 직접 배포했다.

팀시티 서버

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: teamcity-server
  namespace: teamcity
spec:
  serviceName: 'teamcity'
  replicas: 1
  selector:
    matchLabels:
      app: teamcity-server
  template:
    metadata:
      labels:
        app: teamcity-server
    spec:
      initContainers:
        - name: volume-permissions
          image: busybox
          command: ['sh', '-c', 'chown -R 1000:1000 /data/teamcity_server/datadir']
          volumeMounts:
            - name: teamcity-data
              mountPath: /data/teamcity_server/datadir
      containers:
        - name: teamcity-server
          image: jetbrains/teamcity-server:2024.07.1
          ports:
            - containerPort: 8111
          env:
            - name: TEAMCITY_SERVER_MEM_OPTS
              value: '-Xmx6g'
          resources:
            requests:
              memory: '4Gi'
              cpu: '4000m'
            limits:
              memory: '8Gi'
              cpu: '8000m'
          volumeMounts:
            - name: teamcity-data
              mountPath: /data/teamcity_server/datadir
  volumeClaimTemplates:
    - metadata:
        name: teamcity-data
      spec:
        accessModes: ['ReadWriteOnce']
        resources:
          requests:
            storage: 20Gi

서버 pod 에는 데이터베이스 외에도, 데이터베이스에 대한 연결 정보나 플러그인그 외 다른 데이터들도 저장된다. 재시작 시 다시 인스톨러를 보고싶지 않다면 위 정보를 stateful 하게 관리해야한다.

팀시티 에이전트

apiVersion: apps/v1
kind: Deployment
metadata:
  name: teamcity-agent
  namespace: teamcity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: teamcity-agent
  template:
    metadata:
      labels:
        app: teamcity-agent
    spec:
      containers:
        # agent 의 build runner 로 docker 를 사용하고있다. dind 컨테이너를 사용해 Docker 데몬을 실행하고, TeamCity 에이전트 컨테이너에서 이 데몬에 연결한다.
        - name: dind
          image: docker:20.10-dind
          securityContext:
            privileged: true
          # 기본적으로 2376 에 TLS를 사용하는 Docker 데몬이 실행되지만, TeamCity 에이전트는 TLS를 사용하지 않으므로 2375 포트를 사용하게 명시해야한다.
          command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '-H', 'unix:///var/run/docker.sock']
          env:
            - name: DOCKER_DRIVER
              value: overlay2
          volumeMounts:
            - name: dind-storage
              mountPath: /var/lib/docker
        - name: teamcity-agent
          image: jetbrains/teamcity-agent:2024.07.1
          env:
            - name: SERVER_URL
              value: 'teamcity-server.teamcity.svc.cluster.local:8111'
            - name: AGENT_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: DOCKER_HOST
              value: 'tcp://localhost:2375' # DinD 컨테이너의 Docker 데몬에 연결
          resources:
            requests:
              cpu: '2000m'
              memory: '2Gi'
            limits:
              cpu: '4000m'
              memory: '4Gi'
          volumeMounts:
            - name: dind-storage
              mountPath: /var/lib/docker
      volumes:
        - name: dind-storage
          emptyDir: {}

팀시티 Professional(무료) 라이센스 에서는 최대 3개의 agent 까지 사용할 수 있다.

jetbrains 에서 제공하는 teamcity-agent 이미지에는 docker 가 설치되어 있지 않다.
따라서 docker 를 사용해 빌드해야 하는 경우 에러가 발생하며 이를 해결하기 위해 아래 방법들을 두고 고민했다.

  1. teamcity-agent 이미지에 docker 가 설치된 커스텀 agent 이미지 사용
  2. dind 컨테이너(docker daemon) 배포하고, agent 컨테이너에서 사용

추후 팀시티 버전 업그레이드 시 커스텀 이미지를 새로 만들어야 하는데 귀찮을 것 같아 dind 컨테이너를 함께 배포하는 2번 방법을 선택했다.

위 agent yaml 에 따라 dind 컨테이너 설정을 조금 수정해서 사용해야한다.

에이전트 할당

팀시티 서버에서 에이전트는 수동으로 할당해줘야 한다.
최초 실행 시 agent pod 이 배포되어 있음에도 상단 메뉴에 Agents 0 를 확인할 수 있다.

Unauthorized agents 를 모두 수동으로 pool 에 할당해줄 수 있다.

위와같이 할당이 끝났다면 agent 가 정상적으로 작업을 수행할 수 있다.

데이터베이스 마이그레이션

기존 환경에선 RDS 를 사용하고 있었다. 하지만 해당 RDS 인스턴스의 자원이 거의 사용되지 않고 있었고, 온프레미스 환경의 쿠버네티스를 사용하고 있기 때문에 RDS → K8s 로 DB 를 이전했다.

teamcity server 에 접근하면 아래 인스톨러가 실행된다.

Restore from backup 선택 시 기존 backup 파일을 사용해 복구할 수 있다.
단, source database(RDB) 에서 target database(in K8s) 로 마이그레이션 하는 기능은 제공되지 않는다.

Administration → Backup 에서 데이터를 백업할 수 있다.

백업한 데이터를 업로드하고 Proceed 버튼을 누르면 target database 설정을 할 수 있다.

만약 지정한 데이터베이스가 비어있지 않은 경우 아래 에러와 함께 Restore 가 수행되지 않는다.

Found a TeamCity schema when expected an empty database

복구가 끝나면 서버가 재시작되고 서비스를 이용할 수 있다.

마이그레이션 없이 초기화 하려면?

인스톨러 초기 화면에서 Restore from backup 가 아니라 Proceed 로 진행할 수 있다.

데이터베이스 정보를 입력하고 진행하면

초기화 기다리고

라이센스 동의하면

관리자 계정을 생성하고 서비스를 이용할 수 있다.

0개의 댓글