[우아한테크코스] 5월 2일 TIL

2 minute read

[infra] logging

  1. file-appender.xml 설정
    ``` <?xml version=”1.0” encoding=”UTF-8”?>
${home}file.log ${home}file-%d{yyyyMMdd}-%i.log 15MB utf8 %d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger - %m%n
2. logback.xml 설정  

<?xml version=”1.0” encoding=”UTF-8”?>

3. console-appender.xml 설정  

<?xml version=”1.0” encoding=”UTF-8”?>

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
4. json-appender.xml  

<?xml version=”1.0” encoding=”UTF-8”?>

${home}json.log ${home}json-%d{yyyyMMdd}-%i.log 15MB true true yyyy-MM-dd HH:mm:ss.SSS timestamp thread message exception context
5. logger 코드  
```java
@RestController
@RequestMapping
public class LogBackApiController {
    private static final Logger log = LoggerFactory.getLogger("console");
    private static final Logger fileLogger = LoggerFactory.getLogger("file");
    private static final Logger json = LoggerFactory.getLogger("json");


    @GetMapping("/level")
    public String index() {
        log.trace("A TRACE Message");
        log.debug("A DEBUG Message");
        log.info("An INFO Message : {}", LocalDateTime.now());
        log.warn("A WARN Message");
        log.error("An ERROR Message");


        return "로그 레벨 확인 페이지입니다.";
    }

    @GetMapping("/file")
    public String logbackTest() {
        log.info("콘솔 로깅 입니다.");
        fileLogger.info("파일 로깅 입니다.");
        return "file.log 로깅 파일을 확인해주세요.";
    }

    @GetMapping("/json")
    public String jsonTest() {
        json.info("{}, {}, {}",
            kv("orderNo", 1L),
            kv("memberNo", 2L),
            kv("deviceId", 3L)
        );
        return "json.log 로깅 파일을 확인해주세요.";
    }
}
  1. nginx 사용
    • ngingx
      http 서버의 역할: 정보를 웹 브라우저에 전송하는 역할
      리버스 프록시 역할: 가짜 서버에 클라이언트가 요청하면 프록시 서버가 reverse 서버로부터 데이터 가져오는 역할
    • 호스트와 도커 경로 마운트: docker run -d -p 80:80 -v /var/log/nginx:/var/log/nginx nextstep/reverse-proxy
    • 도커 상태 확인(cAdvisor 설치):
      docker run \
      --volume=/:/rootfs:ro \
      --volume=/var/run:/var/run:ro \
      --volume=/sys:/sys:ro \
      --volume=/var/lib/docker/:/var/lib/docker:ro \
      --volume=/dev/disk/:/dev/disk:ro \
      --publish=8080:8080 \
      --detach=true \
      --name=cadvisor \
      google/cadvisor:latest
      

      public주소:8080을 통해서 cAdvisor를 실행해 돌고 있는 도커 컨테이너를 확인할 수 있다. 뿐만 아니라 돌고 있는 컨테이너의 memory, cpu를 볼 수도 있다.

[infra] CloudWatch 사용

  • aws CloudWatch란
    실시간으로 실행 중인 애플리케이션을 모니터링하는 것으로 리소스 및 애플리케이션에 대해 측정할 수 있는 변수인 지표를 수집하고 추적할 수 있다.
    지표를 감시하다가 임계값을 위반하면 경고를 보낼 수도 있다.
  • AWS Identity and Access Management(IAM)
    리소스에 대한 접근을 안전하게 제어할 수 있는 웹서비스

  • EC2에 IAM role 설정
    인스턴스 작업 > 보안 > IAM 역할 수정: ec2-cloudwatch-api 선택

  • cloudwatch logs agent 설치
    curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O
    sudo python ./awslogs-agent-setup.py --region ap-northeast-2
    이후 스텝에 따라 필요한 입력 진행 (log_group_name에 식별자 설정하는게 좋음)

  • 로그 수집
    vi /var/awslogs/etc/awslogs.conf로 확인/수정
    sudo service awslogs restart로 설정 적용

  • Metric 수집
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
    sudo dpkg -i -E ./amazon-cloudwatch-agent.deb
    안되면 sudo
    아래 기본설정 설정
    # /opt/aws/amazon-cloudwatch-agent/bin/config.json
    {
          "agent": {
                  "metrics_collection_interval": 60,
                  "run_as_user": "root"
          },
          "metrics": {
                  "metrics_collected": {
                          "disk": {
                                  "measurement": [
                                          "used_percent",
                                          "used",
                                          "total"
                                  ],
                                  "metrics_collection_interval": 60,
                                  "resources": [
                                          "*"
                                  ]
                          },
                          "mem": {
                                  "measurement": [
                                          "mem_used_percent",
                                          "mem_total",
                                          "mem_used"
                                  ],
                                  "metrics_collection_interval": 60
                          }
                  }
          }
    }
    

    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json: 설정
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status: 설정확인

cloudwatch에 대시보드에 내 인스턴스 id 입력해 위젯 생성 진행

[infra] 각 프로젝트 spring actuator metric 수집

  • spring boot actuator?
    애플리케이션 모니터링하고 관리할 수 있는 데이터 제공하는 것
    커스텀 데이터 만드는 과정이 아래에 있다.

build.gradle 의존성에 추가

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.cloud:spring-cloud-starter-aws:2.2.1.RELEASE")
    implementation("io.micrometer:micrometer-registry-cloudwatch")
}    

application.propertices에 추가

cloud.aws.stack.auto=false  # 로컬에서 실행시 AWS stack autoconfiguration 수행과정에서 발생하는 에러 방지
cloud.aws.region.static=ap-northeast-2
management.metrics.export.cloudwatch.namespace=  # 해당 namespace로 Cloudwatch 메트릭을 조회 가능
management.metrics.export.cloudwatch.batch-size=20
management.endpoints.web.exposure.include=*

[network] 문제

  • cpu 사용률 100%를 파악하는 이유?
    cpu 사용률이 100%에 도달하면 인스턴스의 컴퓨팅 용량이 부족해 커널을 실행할 수 없게 된다.

  • 메모리가 고갈되면 발생하는 일?
    메모리가 부족하면 커널이 실행되지 않고 메모리 확보를 위해 다른 프로세스가 종료된다.

  • 디스크가 꽉차면?
    부팅하는동안 인스턴스가 멈춘다.
    복구 인스턴스를 사용하면 파일 시스템의 공간을 확보할 수 있다.
    하지만 이 과정에서 인스턴스에 저장된 데이터가 손실될 수 있으니 주의해야 한다.

aws 장애 참고

  • reverse proxy 두는 이유?
    클라이언트가 직접 app 서버에 요청하면 프로세스 1개가 응답 대기 상태가 되어야만 하는데 클라이언트가 가짜 서버에 요청하고 리버스 프록시가 데이터를 가져오는 역할을 하면 별도의 대기 상태 없이 요청을 배분해서 받을 수 있다.
    nginx 참고