레이블이 regexp인 게시물을 표시합니다. 모든 게시물 표시
레이블이 regexp인 게시물을 표시합니다. 모든 게시물 표시

aws eks(k8s) ingress path regex 동작 문제

# aws eks(elastic kubernetes service) 에 ingress controller 를 설치했다.
# nginx-ingress controller 는 아래 설명처럼 nginxinc 를 설치했다. 

# 참고로 nginx controller 는 크게 2종류가 있다.
# kubernetes 에서 개발한 kubernetes/ingress-nginx
# nginx 에서 개발한 nginxinc/kubernetes-ingress with NGINX
# 모두 nginx 기반으로 하고 약간의 차이가 있다.

# ingress 설정은 다음과 같이 (.*) regexp(정규식) 매칭을 사용했다.
# 정규식의 capture group-> 보통 () 로 구분되는 그룹,
# (.*) 하나만 있어 $1 (첫번째 캡쳐 그룹)을 rewrite 대상으로
# 백엔드 서비스에 넘겨주는 의도다. 
# 만약 ysoftman/(/|$)(.*) 라면
# (/|$) -> $1
# (.*) -> $2 
# 가 placeholder 가 된다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: path-ingress
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: "*.amazonaws.com"
      paths:
      - path: /ysoftman/(.*)
        backend:
          serviceName: ysoftman-service
          servicePort: 8080

# 그런데 다음과 같이 요청하면 nginx 404 응답을 준다.
# 참고로 path를 / 나 /ysoftman 처럼 고정된 경로를 주면 동작한다.
curl "https://aaa-bbb-ccc.amazonaws.com/ysoftman/abc"
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

# nginx controller pod 의 로그를 보면 다음과 같은 에러 후 404로 응답한다.
/etc/nginx/html/ysoftman/abc" failed (2: No such file or directory)

# nginxinc 문서를 보니 ingress path 에 정규식이 사용되지 않고 있고,
# path 에 정규식을 지원한다고 명시도 되어 있지 않다.
# 대신 nginxinc ingress controller는 virtualServer 라는 새로운 loadbalancer 리소스도 제공하고 여기서 정규식을 사용할 수 있다.

# 그래서 nginxinc nginx-ingress controller 은 모두 삭제
kubectl delete namespace nginx-ingress
kubectl delete clusterrole nginx-ingress
kubectl delete clusterrolebinding nginx-ingress


# kubernetes nginx-ingress controller for AWS 를 설치
# NETWORK LOAD BALANCER (NLB) 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.46.0/deploy/static/provider/aws/deploy.yaml

# 참고로 nginx controller pod 에러가 다음과 같이 발생하면 ingressclass 리소스를 삭제해야 한다.
Invalid IngressClass (Spec.Controller) value "quivr.be/ingress-nginx-controller". Should be "k8s.io/ingress-nginx"
IngressClass with name nginx is not valid for ingress-nginx (invalid Spec.Controller)

# external-ip 확인
# xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com
kubectl get svc --namespace ingress-nginx

# kubernetes ingress-nginx 는 path 에서 (.*)등의 정규식은 지원하지만
# host 명은 지원하지 않는다.
# 다음과 같이 호스명은 full hostname 으로 명시해야 하고
# path 에는 정규식을 사용할 수 있다.
  rules:
  - host: "xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com"
      paths:
      - path: /ysoftman/(.*)
        backend:
          serviceName: ysoftman-service
          servicePort: 8080

# 이제 ingress path 정규식에 맞다면 200 OK 응답을 받는다.
curl "https://xxxxx-xxxxx.elb.ap-northeast-2.amazonaws.com/ysoftman/abc"

prometheus query

# prometheus query 사용 예시
# 버전 조회
prometheus_build_info

# my_requests 메트릭 모두 조회
my_requests

# my_requests 중 abc label 값이 lemon 인 경우 조회
my_requests{abc="lemon"}

# my_requests 중 abc label 값이 lemon 이 아닌 경우 조회
my_requests{abc!="lemon"}

# my_requests 중 abc label 값이 lemon로 시작하는 경우 조회
# =~ 로 regex match 한다.
my_requests{abc=~"^lemon.*"}

# [1m] : 최근 1분 동안 존재했던 값들 예를 들어 [1,2,5,10]을 취합
# 처음과 끝의 차이로 초당 평균 변화율(rate)을 계산한다.
# 처음과 시작값 외 중간의 값들은 사용되지 않기 때문에
# range vector 를 너무 크게하면 정확한 값이 도출되지 않는다.
# [1d:1h] : 최근 2일 동안 1시간 간격의 값들

# abc=lemon 요청이 1분동안 60번의 요청이 있었다면 rate 로 1tps가 된다.
rate(my_requests{abc="lemon"}[1m])

# tps 같은 변화율이 아닌 실제 카운트 값을 취할때는 increase 를 사용하면 된다.
# abc=lemon 요청이 1분동안 60번의 요청이 있었다면 increase 는 60(개)가 된다.
increase(my_requests{abc="lemon"}[1m])

# rate 로 나오는 n 개의 값을 더한다.
sum(rate(my_requests{abc="lemon"}[1m]))

# rate 로 나오는 n 개의 값 평균을 계산한다.
avg(rate(my_requests{abc="lemon"}[1m]))

# rate 로 나오는 n 개의 값중 최소값
min(rate(my_requests{abc="lemon"}[1m]))

# rate 로 나오는 n 개의 값중 최대값
max(rate(my_requests{abc="lemon"}[1m]))

# 하루 중 1분단위로 rate 합산 결과들 중 최대 값
max_over_time(sum(rate(my_requests{abc="lemon"}[1m]))[1d:1m])

# 하루 중 1분단위로 rate 합산 결과들 중 평균 값
avg_over_time(sum(rate(my_requests{abc="lemon"}[1m]))[1d:1m])

# 하루 중 1분단위로 rate 합산 결과들 중 중간 값
quantile_over_time(0.5, sum(rate(my_requests{abc="lemon"}[1m]))[1d:1m])

# pod,container 별 CPU 사용량 백분율
sum(rate(container_cpu_usage_seconds_total{name!~".*prometheus.*", image!="", container!="POD"}[5m])) by (pod, container) / 
sum(container_spec_cpu_quota{name!~".*prometheus.*", image!="", container!="POD"} / container_spec_cpu_period{name!~".*prometheus.*", image!="", container!="POD"}) by (pod, container) * 100

# worker 노드의 pod 최대 개수 파악
# on(양쪽 메트릭에 존재하는 레이블로 결과들을 구분할 수 있는 레이블)
# group_left (왼쪽 매트릭 레이블 기준으로 병합, 병합 결과에 포함할 레이블 명시할 수 있다.)
# sum (결과) by (node) 결과중 node 레이블 같은 것 까리 합치기
sum(kube_node_status_allocatable{resource="pods", unit="integer"} * on(node) group_left() kube_node_role{role="worker"}) by (node)

# worker 노드의 running pod 개수 파악
sum((kube_pod_info * on(pod, namespace) group_right(node) kube_pod_status_phase{phase="Running"}) * on (node) group_left() kube_node_role{role="worker"}) by (node)

#####

# promethus > alerts 메뉴에 등록된 rule 확인을 할 수 있다.
# 알람은 다음 3가지 상태가 있다.
- inactive: 알람 (rule)조건이 해당하지 않는 경우(정상)
- pending: 조건에 맞아서 발송 대기중, rule 명세의 for 필드에 설정된 기간동안 검사하며 이 기간 동안 조건이 해제되면 inactive, 계속 조건이 맞으면 firing 상태로 변경된다.
- firing: firing 상태가 되면 alert-manager 에게 알람 내용 전송한다.

# 자주 사용되는 prometheus alert 을 모아둔곳(왠만한건 다있음~ㅎ)

regular expression 정규표현식

# regexp
/ 정규식 패턴 시작과 끝
^ 문자열의 시작, ^a 는 a로 시작하는
$ 문자열의 끝, a$ a로 끝나는
? 앞문자가 0번 또는 1번 발생 {0,1} 과 같다.
* 앞문자가 0번 이상 발생 {0,} 과 같다.
+ 앞문자가 1번 이상 발생 {1,} 과 같다.
. 어떤 문자도 일치
| 선택, a|b 는 a 또는 b
() 하위식(subexpression), 괄호 안의 내용을 하나의 그룹으로, 그룹마다 왼쪽부터 $1 $2 ... $괄호개수 로 사용된다.
(?:) 그룹으로 처리되지 않도록 한다.[] 안의 문자 한개 선택, a[bcd]a 는 aba, aca, ada 가 된다.
[a-z] a부터z 중 문자 하나, a, b .. z 가 된다.
[^] 제외(부정), [^ab]z는 az, bz 를 제외한 cz, dz, Az, Bz, ... Zz 등이 된다.
a{2} a 가 2번 반복
a{1,5} a 가 1번 이상 5번 이하 반복
a{1,} a 가 1번 이상 반복
\특수문자 특수문자 자체
\0 null\n 줄바꿈\r 캐리지 리턴
\d 숫자
\D 숫자가 아닌
\s 공백
\S 공백이 아닌
\t 탭
\v 버티컬 탭
\w 워드 [A-Za-z0-9_] 와 같다.\W 워드가 아닌 [^A-Za-z0-9_] 와 같다.
\< 단어의 시작
\> 단어의 끝

# /패턴/ 뒤에 명시
g 전체대상
i 대소문자 무시
m 멀티라인
x 공백문자 무시

# matched text$1 $2 ... $n 으로 정규식과 일치하는 n 개의 값을 지칭한다.

# nginx flag
~ 는 case-sensitive(대소문자 구별) 정규식
~* 는 case-insensitive(대소문자 구별안함) 정규식
!~ 는 case-sensitive(대소문자 구별) 정규식 negative(not)
!~* 는 case-insensitive(대소문자 구별안함) 정규식 negative(not)
@ 는 location 블럭이름 정의

# glob 표현(패턴) 정규식은 아니고, 유닉스에서 파일 집합을 표현하는데 쓰인다.
* 는 어떤 문자든 0번 이상 매칭
? 는 어떤 문자든 1번 매칭

# 참고
# 정규식 테스트 https://regexr.com/

맥 다수의 파일명 변경하기

# rename 설치(맥의 경우)
# sudo  brew install rename

# 현재 디렉토리내의 모든.txt 확장자 파일을 .log 로 바꾸기(정규 표현식 사용하는 경우)
rename 's/\.txt/\.log/' *.txt

# test 로 시작 하는 모든 디렉토리,파일 test 부분 -> ysoftman 로 바꾸기
rename 's/^test/ysoftman/' *

Django 사용하기

# 파이썬용 Django(장고) 웹 프레임쿼를 사용하여 빠르게 MVC 패턴의 웹서버를 만들 수 있다.
# 장고 설치(pip 환경이 셋팅되어 있어야 함)
# 참고로 설치가 완료 되면 윈도우 python3 기준 C:\Python34\Scripts\django-admin.py 를 사용한다.
pip install django

# 프로젝트 생성
# 현재 위치에 프로젝트명(ysoftman_web)의 디렉토리와 .py 파일들이 생성된다.
django-amdin.py startproejct ysoftman_web

# 요청 처리 로직 만들기
vi ysoftman_web/ysoftman_test.py

from django.http import HttpResponse
from django.shortcuts import render

def ysoftman_test(request):
    return HttpResponse("ysoftman django test")

def ysoftman_test2(request):
    # html 로 응답
    return render(request, './teamweb/templates/mainview.html', {})

# /teamweb/templates/mainview.html 만들기(templates디렉토리 생성해서 구분하자)
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>ysoftman</title>
     테스트입니다.
</head>
<body>
</body>
</html>

# 처리할 요청과 이를 처리할 로직(함수) 연결
vi ysoftman_web/urls.py

from ysoftman_web.ysoftman_test import ysoftman_test
# url 은 r(정규표현식)를 사용한다.
# \d --> 숫자
# ^ --> 문자열 시작
# $ --> 문자열 끝
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)), # admin 으로 시작하는 url
    url(r'^ysoftman_test/', ysoftman_test) # ysoftman_test 로 시작하는 url
    url(r'^$', ysoftman_test2), # / 인 경우
]

# 웹 서버 실행하기(서버 종료는 ctrl + break)
cd ysoftman_web
python manage.py runserver

# 접속 확인(디폴트 설정)
http://127.0.0.1:8000/admin

# ysoftman_test 테스트 코드 확인
http://127.0.0.1:8000/
http://127.0.0.1:8000/ysoftman_test