본문 바로가기

서버_AWS_LINUX_CICD

개발서버 구축 - 2 CI/CD Teamcity

프론트 서버, 백엔드 서버, 내개인 브런치 백엔드 서버 

등등등...

매번 clone 하고 배포하려니 여간 귀찮은 작업이 아니였다.

 

1. Shell Script 작성.

일단 급한대로 Shell Script를 작성해서 자동화를 했다.

- GitClone 에 관한 스크립트

  - 기존 프로젝트를 rm -rf 하고, 

  - 프로젝트를 clone 한다

  - 정상적으로 불러오면 docker build스크립트를 실행한다.

 

- docker build 에 관한 스크립트

  - 프로젝트 내의 Dockerfile 을 이용하여 image build하도록 한다.

 

2.CI/CD Tool Teamcity-server 구축

그래도 기왕 할거면 CI/CD를 제대로 구축해야지 싶었다.

젠킨스가 유명하긴 하지만 너무 복잡하고 어렵다는 평이 많았다.

마침 내가 떠맡은 회사 프로젝트가 있는데, 퇴사한 선임들이 Teamcity로 배포를 구축해놓고 나갔었다.

그래서 종종 오류가 생길때 몇일 밤낮을 머리를 쥐어짜며 건들여본 경험이있었는데,

차라리 이참에 제대로 Teamcity로 구축을 해보자는 생각이 들었다.

 

 

1)Teamcity-server설치

설치

docker run --name teamcity-server-instance  -v /Users/lsk/teamcity/data:/data/teamcity_server/datadir -v /Users/lsk/teamcity/logs:/opt/teamcity/logs -p 8111:8111 jetbrains/teamcity-server

오류

>>> Permission problem: TEAMCITY_DATA_PATH '/data/teamcity_server/datadir' is not a writeable directory
>>> Permission problem: TEAMCITY_LOGS '/opt/teamcity/logs' is not a writeable directory

    Looks like some mandatory directories are not writable (see above).
    TeamCity container is running under 'tcuser' (1000/1000) user.

    A quick workaround: pass '-u 0' parameter to 'docker run' command to start it under 'root' user.
    The proper fix: run 'chown -R 1000:1000' on the corresponding volume(s), this can take noticeable time.

    If the problem persists after the permission fix, please check that the corresponding volume(s)
    are not used by stale stopped Docker containers ("docker container prune" command may help).

data,logs가 root 로 되어있어 생긴문제

sudo chown -R 1000:1000 data logs

이걸로 권한 해결하기. 

근데도 안되서 폴더들을 다 지우고, 

현재 일반계정으로 디렉토리들을 다시 만들었더니 성공했다.

이 녀석들을 포함하는 teamcity 폴더까지 권한을 바꿔주니 성공했다.

 

2)teamcity-agent 설치

 

docker로 teamcity-agent도 설치 해준다.

설치할때 SERVER_URL 값을 넣어주어야 하는데, 예시에서는 host주소에 " "를 붙이도록 한다.

그런데, 이것 때문에 agent가 server주소를 제대로 인지하지 못한다.

그리고 같은 인스턴스라서 localhost라고 생각 할 수 있겠지만, 도커에서 localhost는 컨테이너 내부를 의미한다.

따라서 공인아이피, 혹은 사설아이피(192.xxx.xxx.xxx)으로 입력을 해주어야 한다.

serverUrl=\u201Chttp\://xxx.xxx.xxx.xxx\:8111\u201D

buildAgent.properties를 vi로 열어보면 "따옴표가 \u201C로 변환되어 문제를 일으켰다....

일단 url이 지저분하지 않도록 이상한 부분은 다 지워준다.

 

agent compatiable 문제

Teamcity server에서는 agent가 감지된 것이 확인되었지만, project에 incompatiable한 상태였다.

즉 agent가 project를 빌드하기에 호환이 안된다는 것이다.

메시지를 보면, docker가 존재하지 않는다는데, Teamcity-agent 컨테이너 내에 docker가 존재하지 않는다는것 같다.

Unmet requirements: 
docker.server.version exist 
docker.server.osType Contains linux

 

container 내부에 들어가보았는데, docker 자체는 존재했으나 실행이 안된다.

dockerd를 이용해서 실행하려고 해도 실행이 안된다.

그런데 어차피 docker안에서 docker를 실행하는것은 권장되지 않는 Docker in Docker 방식이다.

 

공식문서를 다시 찾아보니, agent컨테이너를 빌드할때, 호스트 docker를 연결을 해줘야 한다는 것이였다.

docker run -d -e SERVER_URL=xxx.xxx.xxx.xxx:8111  \
	--name agent1 \
    -u 0 \
    -v /home/teamcity_agent:/data/teamcity_agent/conf \
    -v /var/run/docker.sock:/var/run/docker.sock  \
    -v /opt/buildagent/work:/opt/buildagent/work \
    -v /opt/buildagent/temp:/opt/buildagent/temp \
    -v /opt/buildagent/tools:/opt/buildagent/tools \
    -v /opt/buildagent/plugins:/opt/buildagent/plugins \
    -v /opt/buildagent/system:/opt/buildagent/system \
    jetbrains/teamcity-agent

여기에서 -v /var/run/docker.sock:/var/run/docker.sock 부분이 외부도커를 내부도커에 연동해서, 컨테이너 내에서 호스트 도커를 자신의 도커처럼 이용하는 것이다.

 

이것이 되니까 compatiable 해졌다.

 

다시 정리하면, agent가 compatiable 의 여부는 

해당 프로젝트의 'BuildStep을 실행하는데 필요한 어플리케이션들의 스펙'이 'agent가 보유한 실행 어플리케이션의 스펙'과 일치하는지 여부이다.

해당 프로젝트의 BuildStep에서는 docker를 이용한 빌드 과정이 있었는데, agent는 docker가 없는(꺼져있는) 상태였기 때문에 호환이 안된 것이다.

 

이걸로 node관련한 프로젝트는 빌드 성공했다.

 

JAVA JDK Version 문제

백엔드 서버는 Java17버전의 springboot 프로젝트이다.

gradle로 buildstep을 설정하여 진행을 시켜보았는데 오류가 뜬다....

  org.gradle.internal.component.NoMatchingConfigurationSelectionException: No matching variant of org.springframework.boot:spring-boot-gradle-plugin:3.0.5 was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '7.6.1' but:
    - Variant 'apiElements' capability org.springframework.boot:spring-boot-gradle-plugin:3.0.5 declares a library, packaged as a jar, and its dependencies declared externally:
        - Incompatible because this component declares an API of a component compatible with Java 17 and the consumer needed a runtime of a component compatible with Java 11

 

해당 프로젝트는 17버전인데, 빌드를 진행하는 Java 즉, 로컬 Java는 11버전이라는 것이다.

그런데 이 Java는 Teamcity Agent 설치시 자동설치되는 것이다...

알고보니 최근까지도 Agent가 11버전까지만 지원하는 것에 대한 불만이 좀 있는것 같다....

 

다행이도 17버전을 추가 설치 할 수 있었다.

https://teamcity-support.jetbrains.com/hc/en-us/community/posts/9089101362322

 

여기 조언대로 17버전을 추가로 설치하고 container를 restart 했더니 teamcity-server에서도 해당 17버전을 감지했다.

 

 

build step을 gradle로 했다면, 이렇게 JDK를 지정할수도 있고,

CLI로 할 경우라면

./gradlew clean -Dorg.gradle.java.home=/usr/lib/jvm/java-17-amazon-corretto
./gradlew build -Dorg.gradle.java.home=/usr/lib/jvm/java-17-amazon-corretto

이렇게 Dorg.gradle.java.home 을 강제로 입력해주면 된다.

 

 

이로써 node 프로젝트, Spring프로젝트 모두 agent의 로컬에서 작업은 성공했고,

 

이후 결과물을 container로 띄울지, scp로 다른곳에 보내서 실행시킬지는 내맘이다.

'서버_AWS_LINUX_CICD' 카테고리의 다른 글

개발서버 구축 - 1  (0) 2023.04.25
환경변수와 bin(binary)  (0) 2022.12.23