IT STUDY LOG

Sprint - 모니터링 시스템 구축 본문

devops bootcamp 4/pair/team log

Sprint - 모니터링 시스템 구축

roheerumi 2023. 6. 5. 17:00

#해결 과제

💡 Prometheus Operator가 설치된 환경에서 nginx 인그레스 컨트롤러를 설치

💡 cozserver (v2)의 디플로이먼트 및 서비스를 배포하고, 인그레스를 만들어서 nginx를 통해 서비스에 접근하도록 설정

💡 Prometheus에서 쿼리를 통해 주요 메트릭을 확인

💡 Grafana에 이미 존재하는 대시보드들을 살펴보고, 어떤 쿼리를 사용하는지 확인

 

#과제 항목별 진행 상황

✏️  helm을 이용해 nginx 인그레스 컨트롤러 설치

- nginx 인그레스 컨트롤러가 프로메테우스용 메트릭을 노출할 수 있도록 환경 설정 (참고 레퍼런스 : 레퍼런스, 레퍼런스2)

Step 1 : helm 패키지 매니저로 nginx ingress controller 설치

# nginx controller를 helm repo를 이용해 다운로드
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm repo update

# 프로메테우스 메트릭스 노출 설정 후 nginx 설치
$ helm install ingress-nginx ingress-nginx/ingress-nginx \ 
--set controller.metrics.enabled=true \
--set controller.metrics.serviceMonitor.enabled=true
NAME: ingress-nginx
LAST DEPLOYED: Fri Jun  2 17:21:12 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller'

An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: example
    namespace: foo
  spec:
    ingressClassName: nginx
    rules:
      - host: www.example.com
        http:
          paths:
            - pathType: Prefix
              backend:
                service:
                  name: exampleService
                  port:
                    number: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
      - hosts:
        - www.example.com
        secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

 

Step 2 : 프로메테우스 웹 UI (http://localhost:9090)에서 ingress-nginx-controller가 Target으로 설정되었는지 확인

- 사전에 kubectl 명령어를 통해 port-forward 필요

# 프로메테우스 노출
$ kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090

# 그라파나 노출
$ kubectl --namespace monitoring port-forward svc/grafana 3000

 

✏️  인그레스 생성

Step 0 : 아키텍처

출처 : 코드스테이츠 데브옵스 부트캠프 과정

 

Step 1 : 디플로이먼트, 서비스 배포 후 ingress 생성

(1) 디플로이먼트, 서비스, 인그레스 yaml 파일 작성

# deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cozserver
  namespace: default
  labels:
    app: cozserver
spec:
  selector:
    matchLabels:
      app: cozserver
  replicas: 3
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: cozserver
    spec:
      containers:
      - name:  nodejs
        image:  sebcontents/cozserver:2.0
# service.yaml

apiVersion: v1
kind: Service
metadata:
  name: cozserver
  namespace: default
spec:
  selector:
    app: cozserver
  type: ClusterIP # NOT LoadBalancer
  ports:
  - name: cozserver
    protocol: TCP
    port: 8055
    targetPort: 8080
# ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cozserver
  annotations:
    kubernetes.io/ingress.class: "nginx" # ingress class를 명시해주어야 함
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: localhost # nginx ingress controller에서 인그레스 리소스를 정의할 때 이 host필드는 필수
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: cozserver
            port:
              number: 8055

(2)  디플로이먼트, 서비스, 인그레스 배포

# 디플로이먼트 배포
$ kubectl apply -f cozserver-deployment-v2.yaml --record
deployment.apps/cozserver created

# 서비스 배포
$ kubectl apply -f cozserver-service.yaml               
service/cozserver created

# 인그레스 배포
$ kubectl apply -f cozserver-ingress.yaml 
ingress.networking.k8s.io/cozserver created

 

Step 2 : 포트포워딩을 통해 호스트 PC에서 인그레스에 접근 허용

$ sudo kubectl port-forward service/ingress-nginx-controller 80 &

 

Step 3 : 해당 네임스페이스의 클러스터에 실행된 디플로이먼트, 서비스, 인그레스 확인

$ kubectl get all,ingresses --namespace="default"                
NAME                                           READY   STATUS    RESTARTS   AGE
pod/cozserver-7dcc7c99b7-ffpc9                 1/1     Running   0          18m
pod/cozserver-7dcc7c99b7-l9622                 1/1     Running   0          18m
pod/cozserver-7dcc7c99b7-sbwwx                 1/1     Running   0          18m
pod/ingress-nginx-controller-5988bbb6b-r2v56   1/1     Running   0          22m

NAME                                         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/cozserver                            ClusterIP      10.105.185.120   <none>        8055/TCP                     17m
service/ingress-nginx-controller             LoadBalancer   10.100.241.249   <pending>     80:32213/TCP,443:31440/TCP   22m
service/ingress-nginx-controller-admission   ClusterIP      10.101.10.117    <none>        443/TCP                      22m
service/ingress-nginx-controller-metrics     ClusterIP      10.96.128.235    <none>        10254/TCP                    22m
service/kubernetes                           ClusterIP      10.96.0.1        <none>        443/TCP                      32m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cozserver                  3/3     3            3           18m
deployment.apps/ingress-nginx-controller   1/1     1            1           22m

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/cozserver-7dcc7c99b7                 3         3         3       18m
replicaset.apps/ingress-nginx-controller-5988bbb6b   1         1         1       22m

NAME                                  CLASS    HOSTS       ADDRESS   PORTS   AGE
ingress.networking.k8s.io/cozserver   <none>   localhost             80      10m
  sprint-k8s-rollout-reference $ git:(reference) $ Handling connection for 80

 

✏️  인그레스 접속 로그가 찍히는지 프로메테우스를 통해 확인

Step 1 : http://localhost로 접속해 인그레스를 통해 cozserver에 접속

Step 2 : 프로메테우스 웹 UI Graph 에서 각종 쿼리 수행 (SRE의 네 가지의 황금 시그널을 보기 위해 필요한 메트릭 조회)

(1) nginx_ingress_controller_requests : 트래픽, 오류 확인

우측 10은 접속 횟수를 의미

(2) nginx_ingress_controller_request_duration_seconds_count : 대기 시간

(3) nginx_ingress_controller_request_duration_seconds_bucket : 대기 시간

(4) node_cpu_seconds_total : 포화 수준

Step 3 : 프로메테우스가 지원하는 PromQL을 통해 다음과 같이 복잡한 지표를 표현 가능

(1) 1시간 동안 인그레스 컨트롤러를 통해 들어온 요청의 누적 비율

sum(rate(
  nginx_ingress_controller_requests[1h]
)) 
by (ingress)

(2) 1시간 동안 모든 요청 중 400번대 에러의 비율

sum(rate(
  nginx_ingress_controller_requests{
    status=~"4.."
  }[1h]
))
by (ingress) /
sum(rate(
  nginx_ingress_controller_requests[1h]
))
by (ingress)

 

✏️ Grafana의 대시보드 살펴보기

Step 1 : grafana의 대시보드에서 쿼리 수행

Step 2 :  커뮤니티에서 만들어놓은 대시보드를 Import 해보기

(0) grafana dash 보드 import하는 방법

- 대시보드에서 new > import 

- json 파일을 업로드하거나, grafana.com의 dashboard id를 입력하거나, 직접 json을 입력해 dashboard 로드

- data source로 프로메테우스를 선택 후 import

(1) NGINX Ingress controller

(2) 쿠버네티스 올인원 모니터링 대시보드

 

#TROUBLE SHOOTING LOG

📝 문제 1 : nginx 404 not found

  • 원인 : ingress class name을 명시적으로 지정해주지 않아 발생한 문제
  • 해결 방안 : ingress.yaml 파일에 ingress-controller pod의 class name과 동일한 ingress class name을 명시
$ kubectl describe pod ingress-nginx-controller-5988bbb6b-r2v56

Name:             ingress-nginx-controller-5988bbb6b-r2v56
Namespace:        default
# ... 중략 ... #
Containers:
  controller:
    Container ID:  docker://bb3d562c924cb3b9570cb7de4dd1fd6d401d2e1ea3ac53b3c6c3a71ac40beb1c
    Image:         registry.k8s.io/ingress-nginx/controller:v1.8.0@sha256:744ae2afd433a395eeb13dc03d3313facba92e96ad71d9feaafc85925493fee3
    Image ID:      docker-pullable://registry.k8s.io/ingress-nginx/controller@sha256:744ae2afd433a395eeb13dc03d3313facba92e96ad71d9feaafc85925493fee3
    Ports:         80/TCP, 443/TCP, 10254/TCP, 8443/TCP
    Host Ports:    0/TCP, 0/TCP, 0/TCP, 0/TCP
    Args:
      /nginx-ingress-controller
      --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
      --election-id=ingress-nginx-leader
      --controller-class=k8s.io/ingress-nginx
      --ingress-class=nginx # ingress-class명
      --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
      --validating-webhook=:8443
      --validating-webhook-certificate=/usr/local/certificates/cert
      --validating-webhook-key=/usr/local/certificates/key
# ... 하략 ... #
# ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cozserver
  annotations:
    kubernetes.io/ingress.class: "nginx" # ingress class를 명시
# ... 하략 ...#
  • 참고
    • 쿠버네티스 1.18에 IngressClass 리소스 및 ingressClassName 필드가 추가되기 전에 인그레스 클래스는 인그레스에서 kubernetes.io/ingress.class 어노테이션으로 지정되었으나 앞으로 사라질 어노테이션임
    • kubernetes.io/ingress.class 어노테이션은 일반적으로 인그레스를 구현해야 하는 인그레스 컨트롤러의 이름을 참조하는 데 사용됨
    • 인그레스의 최신 ingressClassName 필드는 kubernetes.io/ingress.class 어노테이션을 대체하나 완전 동등한 것은 아님
    • ingressClassName 필드는 인그레스 컨트롤러의 이름을 포함하는 추가 인그레스 구성이 포함된 인그레스 클래스 리소스를 참조
    • ingressClassName을 생략하려면, 기본 인그레스 클래스가 정의되어 있어야 함(즉, 기본 인그레스 클래스가 정의되어있지 않으면 생략 불가능)

 

#References

https://prometheus.io/

 

Prometheus - Monitoring system & time series database

An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.

prometheus.io

https://grafana.com/

 

Grafana: The open observability platform | Grafana Labs

Your observability stack Operational dashboards for your data here, there, or anywhere

grafana.com

https://stackoverflow.com/questions/70434928/nginx-controller-returns-404-not-found-on-path-and-default-backend

 

Nginx Controller Returns 404 Not Found On Path and Default Backend

I have created a kubernetes cluster using Vagrant. I created a Nginx pod and a Cluster IP service for it. I can curl both the pod and the service getting a successful result. I have now installed an

stackoverflow.com

https://kubernetes.io/ko/docs/concepts/services-networking/ingress/#default-ingress-class

 

인그레스(Ingress)

기능 상태: Kubernetes v1.19 [stable] 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공

kubernetes.io

https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressBackend

https://prometheus.io/docs/visualization/grafana/

 

Grafana | Prometheus

An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.

prometheus.io

https://grafana.com/docs/grafana/latest/dashboards/manage-dashboards/

 

Manage dashboards | Grafana documentation

 

grafana.com

https://grafana.com/grafana/dashboards/9614-nginx-ingress-controller/

 

NGINX Ingress controller | Grafana Labs

Edit Delete Confirm Cancel

grafana.com

 

Comments