Skip to content

Latest commit

 

History

History
568 lines (371 loc) · 29.4 KB

8주차 - 진행한 작업들.md

File metadata and controls

568 lines (371 loc) · 29.4 KB

Controller 구현

기존의 구현한 모든 서비스의 컨트롤러를 구현하였다.

SwaggerUI 잘 안나오는 문제

구글링을 해도 잘 안 나와서, 깃헙 이슈도 검색해보고 공식 문서도 보았지만 답을 구하기 어려웠다.

그래서 깃헙 데모 코드를 보니까, 이미지 업로드 기능이 잘 구현되어 있는 걸 확인, 코드를 뜯어봄.

동일하게 API 작성 해 보니 잘 됨.

여기까지 3시간이 걸렸음. 공식문서에서도 지원한다고 하는 정도의 내용만 있어서, 해당 내용이 추가되었으면 좋겠다고 느낌. (공식문서에 있었으면 적어도 30분이면 해결되었을 문제)

13.53. Is file upload supported ?

- The library supports the main file types: `MultipartFile`, `@RequestPart`, `FilePart`

SpringDoc 조건 확인 및 이슈화

혹시나 다른 실행 방법을 내가 못 찾고 있는건 아닌가 싶어 간단한 프로젝트를 만들고 여러 조건을 확인해 보았지만, Demo 코드와 동일한 사용법 외에는 적절한 해결 방법이 없었다.

그래서 공식문서에도 해당 내용이 추가되면 좋을 거 같아 정리해서 이슈로 개선 요청을 보내보았다. 사실 공식문서에서 기능을 잘 설명하고 않아서, 데모를 읽어야한 제대로 된 사용 방법을 찾을 수 있다.

그래서 거절될 것 같기도 한데, 일단 개인적으로 불편하다고 느껴서 요청이라도 해 보려고 한다.

Location Header에 대한 공부

이미지 업로드 API 컨트롤러 코드의 반환 결과로 ResponseEntity created(URI)을 사용하려고 했는데, URI이 필요하다고 해서 왜 필요한지 내부 구현을 살펴보았다.

살펴보니 Location Header에 해당 URI를 반환하는데, 그럼 Location Header란 무엇인가?

Location Header 201이나 3xx 대에서 사용되는 해더로, 특정 자원의 위치를 반환하기 위해 사용한다고 한다.

created(URI)의 경우는 생성된 자원의 위치를 나타내기 위해 사용한다.

그리고 Content-Location 헤더와는 다르다. 해당 해더는 콘텐츠 협상(클라이언트의 상태에 따라 다른 데이터(파일 형식, 언어)등을 제공하는 것)에서 콘텐츠 협상이 다 끝난 이후의 리소스 위치를 의미한다.

Location은 콘텐츠 협상과 무관하고, Content-Location은 콘텐츠 협상 이후의 특정 URI를 반환하기 위해 사용한다.

공식문서의 설명이 조금 애매해서 잘 이해가 가지 않았는데, 김영한 씨의 인프런 QNA에서 더 쉽게 설명해주어 이해할 수 있었다.

CD Part.1 - 이미지 빌드하고 레지스트리에 등록하기

아래 내용은 Jib 공식문서어떤 블로그 글을 주로 참고하여 구현하였다.

Jib 도입하기

Jib는 구글에서 제공하는 툴로, docker 환경을 구성할 필요 없이 OCI(컨테이너 표준)이미지를 생성할 수 있다. 스프링부트 도커 튜토리얼에서도 이야기하고 있다.

또, 효율적인 이미지 관리를 위한 Layer도 자동으로 설정해 준다.

고민 1 - 어떻게 환경변수(DB 주소 등)을 외부에서 주입받을 것인가?

jar을 사용했을 때는 별 문제 없이 바로 jar을 클라우드 스토리지에 올리고(환경변수가 포함된 빌드) 사용하면 되었음.

컨테이너는 독립된 환경이라서 서버 인스턴스의 로컬 환경이 celog(내 어플리케이션 서버가 올라간) 컨테이너에서 개입할 수 없음

또, 여러 설정을 외부에서 변경할 수 있었으면 했다. (jar 파일 실행 시 로컬의 다른 경로에서 재정의 가능하지만, 컨테이너는 그럴 수 없다.)

구상

docker run 시에 -e 옵션을 사용하면 가능하다고 한다. (해봐야 알 듯) -e는 환경변수를 설정하는 것으로, 해당 컨테이너 내부에 환경변수가 설정되면 스프링에서 횐경변수를 읽고 스프링 프로퍼티 값에 주입해서 사용한다. -> 하지만 이 경우, 내가 환경변수로 정의하지 않은 값을 변경할수는 없지 않나? (내가 정의하지 않은 스프링 프로퍼티 값 같은 것들)

그리고 7주차에 CI 고민하면서 Github Actions에 환경변수 저장하는 걸 해 보았으니까, 해당 코드를 기반으로 이미지를 실행할 때 비슷한 방식으로 주입해주면 될 듯

이미지 빌드 시에 ENV 옵션을 사용할 수도 있으나, 그럼 외부에서 이미지를 보고 속성 값을 파악할 수 있기 때문에 좋지 않다고 생각했다.

그리고 이미지 저장소 경로도 외부에 노출되지 않게 하고 싶은데, gradle에서 사용되는 값이라. System Properties를 사용해서 CD 스크립트에서 주입하도록 할 예정. 이것도 환경변수로 주입

./gradlew jib \
    -Djib.to.image=$이미지주소 \
	-Djib.to.auth.username=$USERNAME \
    -Djib.to.auth.password=$PASSWORD
로컬에서 jib task 실행해서 이미지 레지스트리에 등록해보기

�잘 올라감 - 자세한 사용법은 코드랑 CD 문서 참고

하고나서 컨테이너 실행해서 결과 주입 되나 확인

그래서 로컬에서 확인해보려고 하니까? 프로필 주입이 안 되네? 어차피 PROD에서만 읽으니까 profile이야 그렇다고 해도... 나머지 값은 꼭 필요한데

jdk 이미지에서 제공하는 환경변수 설정인 JAVA_TOOL_OPTIONS를 사용해 JVM의 값을 재정의 할 수 있었다. 하지만, jvmFlags ['-Dspring.profiles.active=${SPRING_ACTIVE_PROFILE}'] 처럼 gradle jib task에서 환경변수를 사용하도록 정의했지만, 잘 동작하지 않았다.
=가 누락되어 있었다. jvmFlags = ['-Dspring.profiles.active=${SPRING_ACTIVE_PROFILE}'] 라고 사용하면 잘 동작한다.

일단 이렇게 하고, 나머지 환경변수는 -e로 넣어서 잘 되는지 확인했고, 문제없이 잘 적용되었다. 다만 환경변수가 추가될 때마다 CD를 변경해야 하는게 조금 불편할 것 같다. (package를 private하게 관리하면 그냥 yml에 필요한 값을 다 때려넣거나, CSP의 키 보안관리 기능이나 spring-cloud-config 등... 더 좋은 방법은 많은데, 지금 사용하기는 무리가 있어서)

docker run -p 8080:8080 -p 3306:3306 \
           -e "npc-access-key=비밀" \
           -e "npc-bucket-name=비밀" \
           -e "npc-end-point=비밀" \
           -e "github-client-id=비밀" \
           -e "github-client-secret=비밀" \
           -e "ncp-region=kr-standard" \
           -e "redirect-uri=비밀" \
           -e "npc-secret-key=비밀" \
           -e "SPRING_ACTIVE_PROFILE=비밀" \
           -e "celog-mysql-url=jdbc:비밀" \
           -e "celog-mysql-username=비밀" \
           -e "celog-mysql-password=비밀" \
           -e "celog-jpa-ddl-auto=비밀" \
           비밀/celog-server:latest

근데 이거 문제가 3306을 이미 DB 컨테이너가 점유중임 그래서 내가 3306 연결하려고 해도 안됨, 그래서 그냥 DB 컨테이너 끄고 클라우드에서 퍼블릭으로 올리는거 읽게 할 예정

(그리고 서버 인스턴스 올릴때는 리다이렉트 주소도 변경해야 할 듯? 아 근데 그러면 음... dns가 아니라서 따로 그 뭐야 우회해서 올려야 하네)

암튼 DB 올리고 했는데, 잘 안됨

보니까 내 생각에는 네트워크가 문제임

일단 로컬 환경에서 jar로 실행하면 문제없이 클라우드 DB 접근 되는데, 컨테이너는 안됨

해당 컨테이너 inspect 확인하니까 아래처럼 나옴

		"ExposedPorts": {},
	...

중요한건 포트가 없다는거. -p 설정이 잘 되지 않았음을 알 수 있음

�딱 생각나는게, jib에서 port 설정 값이 있었던거 같은데?

찾아보니까 posts 옵션이 있고, 이게 도커파일의 EXPOSE와 동일한 역할, 즉, -p 만으로는 해결할 수 없었던 문제...

EXPOSE에서 노출할 거라고 미리 정의를 해야 -p로 해당 부분 실행이 가능한 것임...

도커를 잘 모르니까 이런 일이.....

근데 그런데도 실행 안됨

Access denied for user '이름'@'ip주소' (using password: YES)

이 발생하는데, 클라우드 DB 로그에도 남는걸 보면 인터넷 요청은 가는거 같은데....

뭐가 문제일까?

inspect로 컨테이너 정보를 읽어서 알게 되었음 비밀번호가 짤렸다. 비밀번호에 $ 기호가 들어가는데, 이게 환경변수로 판정된 것....

"Env": [
	...
	"celog-mysql-password=4aff5", // 원래는 4aff5$a6v이다.

진짜 비밀번호 문제였음

저거 계속 신경쓰는게 오히려 리소스 낭비같아서, 비번을 변경함. 그리고 그건 특문 없이 랜덤으로 길게 만들었음

그 이후 DB 연결을 됨

그리고 발생한 또 다른 문제

rg.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'imageUploadServiceImpl' defined in file [/app/classes/dev/sijunyang/celog/surpport/ncp/ImageUploadServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 's3Template' defined in class path resource [io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.class]: Unsatisfied dependency expressed through method 's3Template' parameter 3: Error creating bean with name 's3Presigner' defined in class path resource [io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.class]: Failed to instantiate [software.amazon.awssdk.services.s3.presigner.S3Presigner]: Factory method 's3Presigner' threw exception with message: Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@51a8aed8: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@2d6abfc7: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@39d62e47: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@92fa950: Unable to contact EC2 metadata service.]

로그를 보면 S3AutoConfiguration에서 여러 빈들을 생성할 수 없어서 문제가 발생하였다.

로컬에서는 문제가 없었는데, 아마 이전에 AWS 서비스를 연습하거나 사용하면서 뭔가 로컬 환경변수 같은게 적용되지 않았을까?

-> 이것도 어떻게 보면 도커의 장점이라고 해야 하나. 내 로컬이 아니라 다른 팀원의 로컬이였으면 해당 문제가 발생했을 수도 있었겠는데, 독립적인 환경의 실행?

또 로그를 보면 S3Properties라고 프로퍼티 값을 읽어서 가져오는데 나는 독자적인 ncp프로퍼티를 만들어서 사용해서 이런 문제가 발생한 것 같다.

S3Properties를 설정해주기로 함

API 받기, 사용자 저장까지 잘 되는 모습을 확인하였음

이제 인스턴스 실행하고 직접 CD 돌려보면서 시나리오 만들고, 환경변수 값 조정해서 인스턴스로 올리기만 하면 됨...

    name: auto deploy
    
    on:
      push:
        branches:
          - dev
    
    jobs:
      push_to_registry:
        name: Push to ncp container registry
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v3
          - name: Set up Docker Buildx
            uses: docker/setup-buildx-action@v2
          - name: Login to NCP Container Registry
            uses: docker/login-action@v2
            with:
              registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
              username: ${{ secrets.NCP_ACCESS_KEY }}
              password: ${{ secrets.NCP_SECRET_KEY }}
          - name: build and push
            uses: docker/build-push-action@v3
            with:
              context: .
              file: ./Dockerfile
              push: true
              tags: ${{ secrets.NCP_CONTAINER_REGISTRY }}/tag-name:latest
                        cache-from: type=registry,ref=${{ secrets.NCP_CONTAINER_REGISTRY }}/prv-frontend:latest
              cache-to: type=inline
              secrets: |
                GIT_AUTH_TOKEN=${{ secrets.GIT_TOKEN }}
    
      pull_from_registry:
        name: Connect server ssh and pull from container registry
        needs: push_to_registry
        runs-on: ubuntu-latest
        steps:
          - name: connect ssh
            uses: appleboy/ssh-action@master
            with:
              host: ${{ secrets.DEV_HOST }}
              username: ${{ secrets.DEV_USERNAME }}
              password: ${{ secrets.DEV_PASSWORD }}
              port: ${{ secrets.DEV_PORT }}
              script: |
                docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/tag-name
                docker stop $(docker ps -a -q)
                docker rm $(docker ps -a -q)
                docker run -d -p 3000:80 --env-file ${{ secrets.ENV_FILENAME_FRONTEND }} ${{ secrets.NCP_CONTAINER_REGISTRY }}/tag-name
                docker image prune -f

근데 나도 그냥 ENV 파일 만들어서 저거처럼 넣음 될듯?

그리고 그... 나머지 뭐냐? HOST나 그런건 걍 직접 만들자... 몇 개 안되고 안늘어날 거니까

ssh -i celog-server-key.pem -p22 [email protected]
pw: F7D8hL-q9+r

PROD용

npc-access-key=비밀
npc-bucket-name=비밀
... 이런 식으로 여러개

로컬용

docker run -p 8080:8080 -p 3306:3306 --env-file celog-env-vars.env celog.kr.ncr.ntruss.com/celog-server:latest

CD 스크립트 작성하기

일단 코드로 작성했고, 그건 코드 링크 걸어주면 되니까...

글고 깃헙 시크릿 키도 필요한거 다 걸었음

근데 서버 사양이 낮아서 그런가 shh로 접속하고 이미지 업로드하는데 2분 30초 넘게 걸려서 중지.

서버 이미지 만들어서 스팩 올리고(프리티어 사양은 스케일업이 안됨) 다시 만듦

그러니까 잘 됨

http://118.67.132.194:8080/로 접속해보면 잘 뜸

http://118.67.132.194:8080/swagger-ui/index.html는 API 명세 사이트...

http://118.67.132.194:8080/oauth2/authorization/github에서 로그인

도메인 없이 OAuth 리다이렉트 문제

OAuth2 리다이렉트 과정에서 주소를 지정해줘야 하는데, OAuth2는 IP로 리다이렉트 할 수 없다.

다만 지금 서비스에서 도메인까지 구매하고 사용할 이유가 있나? 싶어서 우회 방법을 찾아보았다.

스택오버플로우 글에서 nip.io를 ip 뒤에 붙여서 간편하게 ip를 도메인처럼 사용할 수 있다고 한다.

깃허브 OAuth2 설정에 NCP 서버의 외부 IP에 nip.io를 붙여 새로운 OAuth2 어플리케이션을 등록(github은 Authorization callback URL을 하나만 제공한다.)

다음은 내가 github OAuth2 서비스를 적용할 때 사용한 설정값이다.

Applicaiton name: �celog-prod
Heompage URL: http://118.67.132.194.nip.io:8080
Authorization callback URL: http://118.67.132.194.nip.io:8080/login/oauth2/code/github

Spring Actuator 적용하기

CD를 구현하려고 하는데, 아직 컨트롤러 객체를 구현하지 않아서...

HeathCheck API도 사용할 겸 생각보다 미리 Spring Actuator를 구현하기로 하였다.

이전에 프로젝트에서도 Spring Actuator를 구현해 보아서 별 어려움은 없었다.

이전에는 보안과 관련된 기능이기 때문에 안전하게, 잘 사용하기 위해서 여러 기술 블로그를 보았고, 큰 도움이 되었다.

다음과 같은 방식으로 logger 설정 가능

curl -X POST http://118.67.132.194:8080/actuator/loggers/org.springframework.security -H "Content-Type: application/json" -d '{"configuredLevel":"DEBUG"}'

도커 컨테이너 로그 보는법

백그라운드에서 실행하면 로그를 확인하기 어렵다.

그냥 로컬 환경이였으면 파일로 출력해서 볼 수도 있겠지만, 컨테이너 환경이라 찾아보기 어려워 확인해보았다.

참고

docker inspect 컨테이너명 | grep LogPath

하면, 해당 파일의 경로가 나온다.

컨테이너 로그는 계속 쌓이는거라 필요에 따라 자유롭게 확인할 수 있다.

tail -f 로그이름 << 실시간으로 확인하기

less -r 로그이름 << 페이징 기능 + 실시간 확인 가능 - q로 종료

CD이후 Oauth 에러

로컬에선 문제 없는데, 서버에서는 문제가 발생한다.

/login/oauth2/code/github까지는 잘 들어오다가. OAuth2LoginAuthenticationFilter에서 OAuth2AuthenticationException: [authorization_request_not_found]가 발생한다.

이전에도 발생했던 경험이 있는거 같은데...

서버에서 설정을 잘 못해주어서 발생한 문제였다. 그 떄는 환경변수 속성을 하나 누락해서 그랬던거 같은데, 이번에는 세션과 관련된 문제이지 않나 싶다.

아마 nip.io를 사용해서 발생한 문제로 보이는데,

OAuth2 로그인 주소를 nip.io를 적용하니까 성공했다. http://118.67.132.194.nip.io:8080/oauth2/authorization/github

nip.io 없이는 다음과 같이 세션을 가져올 수 없다는 에러가 발생했지만, {"log":"2024-04-26T10:36:43.745Z TRACE 1 --- [nio-8080-exec-8] w.c.HttpSessionSecurityContextRepository : Did not find SecurityContext in HttpSession A9BE3E3917059816D856E5A2BC070BF8 using the SPRING_SECURITY_CONTEXT session attribute\n","stream":"stdout","time":"2024-04-26T10:36:43.745414228Z"}

이후에 nip.io를 적용하고 나서는 세션을 잘 인식한다. {"log":"2024-04-26T10:39:03.360Z DEBUG 1 --- [nio-8080-exec-5] .s.ChangeSessionIdAuthenticationStrategy : Changed session id from A9BE3E3917059816D856E5A2BC070BF8\n","stream":"stdout","time":"2024-04-26T10:39:03.361232164Z"}

아마 요청 주소와 반환 주소가 달라서 이런 문제가 발생한게 아닌가 싶다.

Pinpoint Cloud 사용하기

참고:

구상

아래는 깃헙 이슈에 적은 글 복붙한거

성능 테스트 시 서버 상태를 확인하기 위한 Pinpoint 도입하기

NCP의 Pinpoint Cloud를 사용한다. 따라서 Pinpoint controller랑 web, hbase 부분은 이미 구현되어 있고,  
agent만 적용해주면 된다.

도커로 이미지를 빌드하는 현재 상황 상 agent jar 파일을 도커 이미지에 포함시키게 할 계획이다.

외부에서 주입할 수 있는 방식이 유연성은 높을수도 있을 것 같은데, 구현 편의성이랑 외부 주입 파일이 실행에 영향을 줄 수 있는게 관리 면에서 좋을 것 같지는 않다.

환경변수 속성과 달리 agent는 별도의 프로그램이니까 보안이나 의존성 면에서도 도커 이미지 내부적으로 agent를 가지고 있는게 나을 것 같다.

아니면 별도의 이미지로 만들어서 합치는 방법도 가능해 보이는데, 그건 너무 번거로울 것 같아 제외하였다.

스프링부트 서버 이미지에 Pinpoint agent 등록하기

공식문서의 설명을 보면, jib.extraDirectories를 사용해서 필요한 외부 파일을 가져와서 등록할 수 있음.

하지만 이건 디렉토리 자체를 등록하게 된다. 이 경우 agent의 라이센스 key 값을 주입해줄 수 없다.

이 문제를 해결하기 위해 gradle의 doFirstdoLast를 사용해서 키 값을 작성하고, 해당 파일을 jib task가 실행될 때 복사해서 이미지에 올라가도록 구현하였다.

근데 이러면 보안 상 별로인거 같은데, 컨테이너 이미지에 라이센스가 포함되니까... 차라리 실행될 때 특정 스크립트가 실행되게 하는게 더 좋지 않나?

project.tasks.getByName('jib').doFirst {  
    def licence = project.hasProperty('ncp-pinpoint-licence') ? project.property('ncp-pinpoint-licence') : null  
  
    if (licence == null || licence.isEmpty()) {  
        throw new GradleException("ncp-pinpoint-licence value is not provided. Please specify the value using -Pncp-pinpoint-licence=<ncp-pinpoint-licence-value>")  
    }  
    def licenceFile = file('ncp-pinpoint-agent/ncp-pinpoint-licence.txt')  
    licenceFile.write(licence)  
  
    println "ncp-pinpoint-licence write successfully"  
}

project.tasks.getByName('jib').doLast {  
    def licenceFile = file('ncp-pinpoint-agent/ncp-pinpoint-licence.txt')  
    licenceFile.write("")  
    println "ncp-pinpoint-licence removed successfully"  
}

이미지를 다운받는데 특정 권한이 필요하다면 안전하다고 볼 수도 있겠으나, 좋은 방법은 아닌 것 같다.
대신 최소한 github repo에 보안 상 중요한 key 값이 노출되는 건 보호해줄수 있긴 하지만...

다만 지금 이런 문제로 너무 오래 고민하는 건 좋지 않다고 생각해서 이 정도로 마무리하기로 했다.

후기

다만 프로젝트 github repository에 많은 jar 파일들이 올라가게 되었다. 또 프로젝트가 이어진다면 버전관리도 본인이 직접 해야한다.

이런 점으로 보았을 떄, 좋은 선택은 아니라고 생각된다.

원인을 생각해보면,
docker에 대한 이해도가 부족하지만 섯불리 도입해서 일수도 있고,
조금 더 나은 방법을 여러가지 고민해보지 못한 게 조금 아쉽다. 문제를 분석하고 생각할 시간을 많이 가지지 못해서 그런 것 같은데, 다음에는 조금 더 나은 방법을 생각해보는게 좋겠다.

문제 발생

실행이 되었지만, api 요청을 인식하지 못한다. 하지만 나머지 JVM 관련 옵션은 잘 읽고 있는 모습을 볼 수 있다.

혹시 포트 문제인가 싶어서 확인해보기로 했다. (AWS X-RAY를 사용할떄는 일부 포트를 열어줘야 했던 것으로 기억한다.)

NCP 문서에도 포트와 관련된 설정이 필요하다는 내용이 없어서 추가적으로 구글링해보니 다음과 같은 블로그를 확인할 수 있었다.

https://javapp.tistory.com/319

*(중요)배포 서버에 root 가 아닌 배포 사용자로 접속후 설치 진행해야됨 (이것때매 삽질,, 나중에 agent가 jar파일을 root로 설치되면 인식하지를 못함)

라고 한다. 현재 root 사용자로 접근해서 CD를 수행하는 상황이므로 파일을 변경해보기로 했다.

NCP Server에 사용자 추가

https://uroa.tistory.com/100 << 해당 블로그를 참고

> adduser "사용자 이름"
이후 pw 입력 ("비밀번호" - 관리자와 동일함)

> sudo visudo
�로 권한 설정 파일 들어가서
root와 동일한 권한 부여
"사용자 이름" ALL=(ALL) ALL << 이렇게 적음

이후 위 블로그에서는 따로 pem key를 복사해서 적용하지만
ncp는 그런 과정 없이도 인증 시 pem key를 입력해야 함.
이게 왜 그런지는 모르겠음
이제 다음처럼 사용해서 접근 가능
ssh -i celog-server-key.pem -p22 "사용자 이름"@118.67.132.194
pw: "비밀번호"

그리고 github actions에 사용하는 secrets 값도 수정

권한문제로 인한 CD 실패

https://github.com/f-lab-edu/celog/actions/runs/8858890705/job/24328066678?pr=58

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock 문제 발생

새로 추가한 사용자가 도커를 사용할 권한이 부족해서 발생한 문제로, 권한을 부여해 주었다.

다음 을 참고함.

https://github.com/f-lab-edu/celog/actions/runs/8858890705/job/24328118457 이후 actions가 통과하면서 권한 문제는 해결하였다.

그러나 아직도 요청을 인식하지 못하는 문제가 발생한다.

아마 위에서 root와 동일한 권한 부여한 게 문제인가 싶어 해당 권한을 제거하고, 다시 시도해보기로 했다.

(이런 다시 시도하는 과정은 변경 이후 터미널을 종료하고 실행되었다.)

로그 확인 및 버전 업그레이드

pinpoint-apm/pinpoint#9599

로그를 확인해보니 javax와 관련된 파일을 잘 불러오지 못하는 것 같았다.

구글링 해보니 해당 깃허브와 비슷한 문제였다.

spring boot 3 버전의 지원하지 않는 버전인 것 같은데

지금 사용하고 있는 버전이 NCP Pinpoint Cloud 페이지에서 제공하는 버전이라. 혹시 이후 버전을 사용하면 문제가 발생하지 않을까 싶어 기본 제공된 버전을 사용하고 있었다.

다만 이런 문제가 발생했기 때문에 버전을 올려서 실행해보기로 하였다.

릴리즈 노트를 확인하고 최신 버전을 설치하였다.

port 문제

이후 실행이 되지 않아 log를 확인해 보니 port 관련 문제가 발생한 것으로 보인다.

Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: /127.0.0.1:9991

또 기존에 나오지 않았던 로그가 나오는 걸로 보아 시작 자체는 되는 것 같다. (아니였다. ncp cloud에서 제공하는 버전이 pinpoint.banner.mode를 설정하지 않아서 나오지 않았던 것이였다.)

{"log":"        88888888ba   88  888b      88  88888888ba     ,ad8888ba,    88  888b      88  888888888888\n","stream":"stdout","time":"2024-04-27T10:33:18.653787131Z"}
{"log":"        88      ,8P  88  88 `8b    88  88      ,8P  d8'        `8b  88  88 `8b    88       88\n","stream":"stdout","time":"2024-04-27T10:33:18.653796794Z"}
{"log":"        88aaaaaa8P'  88  88  `8b   88  88aaaaaa8P'  88    da    88  88  88  `8b   88       88\n","stream":"stdout","time":"2024-04-27T10:33:18.653796849Z"}
{"log":"        88           88  88    `8b 88  88           Y8,        ,8P  88  88    `8b 88       88\n","stream":"stdout","time":"2024-04-27T10:33:18.653990635Z"}
{"log":"        88           88  88      `888  88             `\"Y8888Y\"'    88  88      `888       88\n","stream":"stdout","time":"2024-04-27T10:33:18.653997846Z"}

구글링을 하고, 공식문서를 찾아 읽어보니 agent 측에서 정보를 보낼 때 특정 port를 사용한다고 한다. 기본 값이 999x 를 사용하는 것 같아서, 해당 부분 포트를 열고, 도커에서 외부로 보낼 수 있도록 변경하였다.

그리고 ip 값이 127.0.0.1로 되어있는데, 나는 이전 버전을 사용할 때, 이런 값을 적용한 적이 없었다.

그래서 NCP Pinpoint에서 다운받았던 Agent의 설정 값 pinpoint-root.config를 확인해보니 주소가 collect.pinpoint.ncloud.com로 설정되어 있을 뿐만 아니라

많은 여러 설정들이 추가로 지원되고 있었다.

그래서 새로운 버전을 적용한다고 잘 될 것 같지는 않다.

아니면 pinpoint의 상태 값을 직접 확인해보고 알맞게 바꿀 수 있어야 할 것 같은데, 해당 문제에 투자하기에는 시간낭비라는 생각이 들었다.

우선 port를 열고 ip를 적용해 본 이후에도 실행이 되지 않았다. (이유는 정확히 모르겠지만 동일한 Connection refused: /127.0.0.1:9991가 발생한다.)

그래서 더 이상 진행이 불가능하다고 판단해 NCP에 문의를 남기고 다른 작업을 진행하기로 했다.

[문의 결과] pinpoint cloud는 springboot 3.x 버전을 지원하지 않는다.

문의에 대한 답장이 왔는데, 최소한 지금 당장 지원할 계획이 없다고 한다.

pinpoint를 사용하려면 직접 환경을 구성해서 만들어야 할 것 같다.

Log 남기기

예외 발생 시 Log를 남기는 걸 까먹어서 내부 로직 판단이 어려웠다.

HTTP 요청을 로깅하는 필터를 만들고, ContentCachingRequestWrapper, ContentCachingResponseWrapper를 사용해서 구현할 예정.

나머지 부분에는 lombok의 slf4j를 사용해서 로깅을 남길 계획이다.

이전에 팀 프로젝트를 진행할 때 알게 되었던 것. 동료의 구현을 보고 알게 되었는데, 서블릿 요청/응답은 변조를 막기 위해서 도중에 접근할 수 없다고 한다. 그래서 Wapper를 사용해야 한다.

참고