⭐ 가시다(gasida) 님이 진행하는 AWS EKS Workshop 실습 스터디 게시글입니다.
이번 게시글은 Observability 에 관한 내용을 진행합니다.
사전에 필요한 내용
Domain: AWS Route 53 호스팅 사이트
#Domain 호스팅 주소 : jjongguet.com
ACM(AWS Certificate Manager)
실습 환경 배포
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/**eks-oneclick3.yaml**
# CloudFormation 스택 배포
aws cloudformation deploy --template-file **eks-oneclick3.yaml** --stack-name **myeks** --parameter-overrides KeyName=jjongkey SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 MyIamUserAccessKeyID=A6HX... MyIamUserSecretAccessKey=X3xKphNvLAbrn4l ClusterBaseName=**myeks** --region ap-northeast-2
# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name **myeks** --query 'Stacks[*].**Outputs[0]**.OutputValue' --output text
# 작업용 EC2 SSH 접속
ssh -i jjongkey.pem **root**@$(aws cloudformation describe-stacks --stack-name **myeks** --query 'Stacks[*].Outputs[0].OutputValue' --output text)
기본 설정
# default 네임스페이스 적용
kubectl ns default
# 노드 정보 확인 : t3.xlarge
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
eksctl get iamidentitymapping --cluster myeks
# 노드 IP 확인 및 PrivateIP 변수 지정
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath={.items[0].status.addresses[0].address})
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
echo "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile
echo "export N3=$N3" >> /etc/profile
echo $N1, $N2, $N3
# 노드 보안그룹 ID 확인
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query "SecurityGroups[*].[GroupId]" --output text)
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
# 워커 노드 SSH 접속
for node in $N1 $N2 $N3; do ssh -o StrictHostKeyChecking=no ec2-user@$node hostname; done
도메인 변수 설정
MyDomain=jjongguet.com
AWS LB/ExternalDNS/EBS, kube-ops-view 설치
# ExternalDNS
echo "export MyDomain=jjongguet.com" >> /etc/profile
MyDnzHostedZoneId=$(aws route53 list-hosted-zones-by-name --dns-name "${MyDomain}." --query "HostedZones[0].Id" --output text)
echo $MyDomain, $MyDnzHostedZoneId
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/aews/externaldns.yaml
MyDomain=$MyDomain MyDnzHostedZoneId=$MyDnzHostedZoneId envsubst < externaldns.yaml | kubectl apply -f -
# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{"spec":{"type":"LoadBalancer"}}'
kubectl annotate service kube-ops-view -n kube-system "external-dns.alpha.kubernetes.io/hostname=kubeopsview.$MyDomain"
echo -e "Kube Ops View URL = http://kubeopsview.$MyDomain:8080/#scale=1.5"
# AWS LB Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller
# EBS csi driver 설치 확인
eksctl get addon --cluster ${CLUSTER_NAME}
kubectl get pod -n kube-system -l 'app in (ebs-csi-controller,ebs-csi-node)'
kubectl get csinodes
# gp3 스토리지 클래스 생성
kubectl get sc
kubectl apply -f https://raw.githubusercontent.com/gasida/PKOS/main/aews/gp3-sc.yaml
kubectl get sc
- 이때 kube-ops-view 는 2가지 경로 에서 접근가능하다. 그 이유는?
- kube-ops-view 의 Service 를 ClusterIP 로 배포했었는데, 이를 LoadBalancer 로 바꿧고(patch) 따라서 a1a90df551915430ca499bee1e2f3e9a-1443098734.ap-northeast-2.elb.amazonaws.com 주소의 8080:32448/TCP 로 배포되었다.
- ELB호스트 URL 은 AWS에 의해 생성된 ELB에 직접 접근한다.
- ⇒ http://a1a90df551915430ca499bee1e2f3e9a-1443098734.ap-northeast-2.elb.amazonaws.com:8080/ 접근을 가능하게 했다.
- 어노테이션을 사용하여 external-dns.alpha.kubernetes.io/hostname 에 도메인이름을 할당함으로써, DNS레코드를 생성했다. → 이 도메인 이름을 사용하여 서비스에 접근할 수 있게 했다.⇒ http://kubeopsview.jjongguet.com:8080/ 을 호스트의 이름으로 해석해서 → ELB가 kube ops view 서비스로 요청을 전달한다.
- → 설정된 DNS 레코드를 통해 ELB의 호스트 이름으로 리다이렉트된다
- kube-ops-view 의 Service 를 ClusterIP 로 배포했었는데, 이를 LoadBalancer 로 바꿧고(patch) 따라서 a1a90df551915430ca499bee1e2f3e9a-1443098734.ap-northeast-2.elb.amazonaws.com 주소의 8080:32448/TCP 로 배포되었다.
- 여기서 AWS LB Controller 이 배포되는 형태는?
- AWS LB Controller 는 배포했을때 Deployment 로만 배포되고, Service 는 배포되지않는다. Service 가 배포되지 않고, AWS Load Balancer 가 작동하는 이유는 Controller가 모든 LB타입을 감시 → AWS콘솔에 ELB/NLB를 자동으로 프로비저닝 하기 때문이다. 여기서부터는 AWS가 담당한다. 따라서 서비스가 필요하지않다.
설치정보 확인
# 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
# eksctl 설치/업데이트 addon 확인
eksctl get addon --cluster $CLUSTER_NAME
# IRSA 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
# EC2 Instance Profile에 IAM Role 정보 확인
cat myeks.yaml | grep managedNodeGroups -A20 | yh
1. EKS CONSOLE
EKS Console 에 가보면 Cluster ARN(CERT ARN) 정보를 확인가능하다.
Cluster ARN은 AWS IAM, AWS CLI/SDK, Kubernetes Annotation, Watch and Logging 을 하는 용도로 사용한다고 한다.
2. LOGGING IN EKS
EKS Control Plane Logging
Control plane 에서 발생한 이벤트를 EKS Cloud Watch 에 로깅 설정을 할 수 있다.
로깅의 종류는 5가지이다.
- Kubernetes API server component logs (
**api**
) –kube-apiserver-<nnn...>
- Audit (
**audit**
) –kube-apiserver-audit-<nnn...>
- Authenticator (
**authenticator**
) –authenticator-<nnn...>
- Controller manager (
**controllerManager**
) –kube-controller-manager-<nnn...>
- Scheduler (
**scheduler**
) –kube-scheduler-<nnn...>
로깅 활성화, 로그 그룹으로 등록
# 모든 로깅 활성화
aws eks update-cluster-config --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
# 로그 그룹 확인
aws logs describe-log-groups | jq
EKS → 배포한 eks → 관찰성(Observerbility) → 제어 플레인 로깅(Controll Plane Logging) 에서 5가지 항목을 조회 가능하다.
CloudWatch → 로그 그룹 → 로그 이름( /aws/eks//cluster ) 에서 확인가능하다.
# 로그 tail 확인 : aws logs tail help
aws logs tail /aws/eks/$CLUSTER_NAME/cluster | more
# 신규 로그를 바로 출력
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --follow
# 필터 패턴
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --filter-pattern <필터 패턴>
# 로그 스트림이름
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --log-stream-name-prefix <로그 스트림 prefix> --follow
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --log-stream-name-prefix kube-controller-manager --follow
kubectl scale deployment -n kube-system coredns --replicas=1
kubectl scale deployment -n kube-system coredns --replicas=2
# 시간 지정: 1초(s) 1분(m) 1시간(h) 하루(d) 한주(w)
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --since 1h30m
# 짧게 출력
aws logs tail /aws/eks/$CLUSTER_NAME/cluster --since 1h30m --format short
여기서 알아두어야할 것은 ‘이렇게 로깅을 할 수 있다는 것’ 정도만 알아두면 될것같다. (이 방법은 거의 사용하지 않는것 같다)
# EKS Control Plane 로깅(CloudWatch Logs) 비활성화
eksctl utils **update-cluster-logging** --cluster $CLUSTER_NAME --region $AWS_DEFAULT_REGION **--disable-types all** --approve
# 로그 그룹 삭제
aws logs **delete-log-group** --log-group-name /aws/eks/$CLUSTER_NAME/cluster
Container(Pod) Logging
Nginx 를 프록시 서버로 배포하는것이 아닌, NGINX 를 Apache Webserver 처럼 사용하여 로깅 할 수 있다.
# NGINX 웹서버 배포
helm repo add bitnami https://charts.bitnami.com/bitnami
# 사용 리전의 인증서 ARN 확인
CERT_ARN=$(aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text)
echo $CERT_ARN
# 도메인 확인
echo $MyDomain
- 여기서 만약
CERT_ARN
이 나오지 않는다면… EKS Console 에 가보면 Cluster ARN 정보를 확인가능하다. 수동으로 등록하자.
# 파라미터 파일 생성 : 인증서 ARN 지정하지 않아도 가능! 혹시 https 리스너 설정 안 될 경우 인증서 설정 추가(주석 제거)해서 배포 할 것
cat <<EOT > nginx-values.yaml
service:
type: NodePort
networkPolicy:
enabled: false
ingress:
enabled: true
ingressClassName: alb
hostname: nginx.$MyDomain
pathType: Prefix
path: /
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
~~~~ alb.ingress.kubernetes.io/success-codes: 200-399
alb.ingress.kubernetes.io/load-balancer-name: $CLUSTER_NAME-ingress-alb
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/ssl-redirect: '443'
EOT
cat nginx-values.yaml | yh
# 배포
helm install nginx bitnami/nginx --version 15.14.0 -f nginx-values.yaml
# 확인
kubectl get ingress,deploy,svc,ep nginx
kubectl get targetgroupbindings # ALB TG 확인
# 접속 주소 확인 및 접속
echo -e "Nginx WebServer URL = https://nginx.$MyDomain"
curl -s https://nginx.$MyDomain
kubectl logs deploy/nginx -f
## 외부에서는 접속이 잘되나, myeks EC2에서 url 접속이 잘 되지 않을 경우 : 이전 aws DNS cache 영향(추정)
dig +short nginx.$MyDomain
dig +short nginx.$MyDomain @192.168.0.2
dig +short nginx.$MyDomain @1.1.1.1
dig +short nginx.$MyDomain @8.8.8.8
cat /etc/resolv.conf
sed -i "s/^nameserver 192.168.0.2/nameserver 1.1.1.1/g" /etc/resolv.conf
cat /etc/resolv.conf
dig +short nginx.$MyDomain
dig +short nginx.$MyDomain @8.8.8.8
dig +short nginx.$MyDomain @192.168.0.2
curl -s https://nginx.$MyDomain
----
# 반복 접속
while true; do curl -s https://nginx.$MyDomain -I | head -n 1; date; sleep 1; done
# (참고) 삭제 시
#helm uninstall nginx
로드밸런서에 myeks-ingress-alb 가 생성되어야함
alb → 리스너 및 규칙 → 직접확인했을때 443, 80 이 존재해야함 (중요)
이렇게 도메인주소로 연결해서 접속 가능함
4. Metrics-server
Metrics-server : kubelet 으로부터 수집한 리소스 메트릭을 수집, 집계하는 클러스터 애드온 구성요소
- cAdvisor : kubelet에 포함된 컨테이너 메트릭을 수집, 집계, 노출하는 데몬
- kubelet: 컨테이너 리소스 관리를 위한 노드 에이전트. 리소스 메트릭은 kubelet API 엔드포인트
/metrics/resource
및/stats
를 사용하여 접근 가능하다. - 요약 API:
/stats
엔드포인트를 통해 사용할 수 있는 노드 별 요약된 정보를 탐색 및 수집할 수 있도록 kubelet이 제공하는 API - metrics-server: 각 kubelet으로부터 수집한 리소스 메트릭을 수집 및 집계하는 클러스터 애드온 구성 요소. API 서버는 HPA, VPA 및
kubectl top
명령어가 사용할 수 있도록 메트릭 API를 제공한다. metrics-server는 메트릭 API에 대한 기준 구현(reference implementation) 중 하나이다. - 메트릭 API: 워크로드 오토스케일링에 사용되는 CPU 및 메모리 정보로의 접근을 지원하는 쿠버네티스 API. 이를 클러스터에서 사용하려면, 메트릭 API를 제공하는 API 확장(extension) 서버가 필요하다.
# 배포
**kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml**
# 메트릭 서버 확인 : 메트릭은 15초 간격으로 cAdvisor를 통하여 가져옴
kubectl get pod -n kube-system -l k8s-app=metrics-server
kubectl api-resources | grep metrics
kubectl get apiservices |egrep '(AVAILABLE|metrics)'
# 노드 메트릭 확인
kubectl top node
# 파드 메트릭 확인
kubectl top pod -A
kubectl top pod -n kube-system --sort-by='cpu'
kubectl top pod -n kube-system --sort-by='memory'
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl get apiservices |egrep '(AVAILABLE|metrics)'
NAME SERVICE AVAILABLE AGE
v1beta1.metrics.k8s.io kube-system/metrics-server False (MissingEndpoints) 21s
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
ip-192-168-1-42.ap-northeast-2.compute.internal 48m 1% 676Mi 4%
ip-192-168-2-100.ap-northeast-2.compute.internal 50m 1% 651Mi 4%
ip-192-168-3-167.ap-northeast-2.compute.internal 52m 1% 619Mi 4%
5. prometheus-stack
프로메테우스의 특징
- 오픈소스
- Time Series DataBase(TSDB), identified by metric name, K/V Pairs
- PromQL 로 자유로운 쿼리 가능
- 분산저장에 대한 제약없음
- HTTP를 통한 pull 방식의 데이터수집
프로메테우스의 큰 구성요소
- Prometheus Server
- Push gateway
- Alertmanager
- Prometheus Web UI
프로메테우스-스택 설치
- https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack
- 단일 헬름차트로, 모니터링에 필요한 여러 요소를 제공(Using Prometheus Operator)
# 모니터링
kubectl create ns **monitoring**
watch kubectl get pod,pvc,svc,ingress -n monitoring
# 사용 리전의 인증서 ARN 확인 : 정상 상태 확인(만료 상태면 에러 발생!)
**CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`**
echo $CERT_ARN
****# repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 파라미터 파일 생성
cat <<EOT > monitor-values.yaml
**prometheus**:
prometheusSpec:
podMonitorSelectorNilUsesHelmValues: false
serviceMonitorSelectorNilUsesHelmValues: false
retention: 5d
retentionSize: "10GiB"
**storageSpec**:
volumeClaimTemplate:
spec:
storageClassName: **gp3**
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 30Gi
ingress:
enabled: true
ingressClassName: alb
hosts:
- prometheus.$MyDomain
paths:
- /*
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/success-codes: 200-399
**alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/ssl-redirect: '443'**
**grafana**:
defaultDashboardsTimezone: Asia/Seoul
adminPassword: prom-operator
ingress:
enabled: true
ingressClassName: alb
hosts:
- grafana.$MyDomain
paths:
- /*
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]'
alb.ingress.kubernetes.io/certificate-arn: $CERT_ARN
alb.ingress.kubernetes.io/success-codes: 200-399
**alb.ingress.kubernetes.io/load-balancer-name: myeks-ingress-alb
alb.ingress.kubernetes.io/group.name: study
alb.ingress.kubernetes.io/ssl-redirect: '443'**
**persistence**:
enabled: true
type: sts
storageClassName: "gp3"
accessModes:
- ReadWriteOnce
size: 20Gi
**defaultRules:
create: false**
**kubeControllerManager:
enabled: false
kubeEtcd:
enabled: false
kubeScheduler:
enabled: false**
**alertmanager:
enabled: false**
EOT
cat monitor-values.yaml | yh
# 배포
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version **57.1.0** \
--**set** prometheus.prometheusSpec.scrapeInterval='15s' --**set** prometheus.prometheusSpec.evaluationInterval='15s' \
-f **monitor-values.yaml** --namespace monitoring
# 확인
~~## alertmanager-0 : 사전에 정의한 정책 기반(예: 노드 다운, 파드 Pending 등)으로 시스템 경고 메시지를 생성 후 경보 채널(슬랙 등)로 전송~~
## grafana : 프로메테우스는 메트릭 정보를 저장하는 용도로 사용하며, 그라파나로 시각화 처리
## prometheus-0 : 모니터링 대상이 되는 파드는 ‘exporter’라는 별도의 사이드카 형식의 파드에서 모니터링 메트릭을 노출, pull 방식으로 가져와 내부의 시계열 데이터베이스에 저장
## node-exporter : 노드익스포터는 물리 노드에 대한 자원 사용량(네트워크, 스토리지 등 전체) 정보를 메트릭 형태로 변경하여 노출
## operator : 시스템 경고 메시지 정책(prometheus rule), 애플리케이션 모니터링 대상 추가 등의 작업을 편리하게 할수 있게 CRD 지원
## kube-state-metrics : 쿠버네티스의 클러스터의 상태(kube-state)를 메트릭으로 변환하는 파드
helm list -n monitoring
kubectl get pod,svc,ingress,pvc -n monitoring
kubectl get-all -n monitoring
**kubectl get prometheus,servicemonitors -n monitoring**
~~~~**kubectl get crd | grep monitoring
kubectl df-pv**
AWS CNI Metrics 수집을 위한 사전 설정
# PodMonitor 배포
cat <<EOF | kubectl create -f -
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: aws-cni-metrics
namespace: kube-system
spec:
jobLabel: k8s-app
namespaceSelector:
matchNames:
- kube-system
podMetricsEndpoints:
- interval: 30s
path: /metrics
port: metrics
selector:
matchLabels:
k8s-app: aws-node
EOF
# PodMonitor 확인
#kubectl get podmonitor -n kube-system
kubectl get podmonitor -n kube-system aws-cni-metrics -o yaml | kubectl neat | yh
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: aws-cni-metrics
namespace: kube-system
spec:
jobLabel: k8s-app
namespaceSelector:
matchNames:
- kube-system
podMetricsEndpoints:
- interval: 30s
path: /metrics
port: metrics
selector:
matchLabels:
k8s-app: aws-node
# metrics url 접속 확인
curl -s $N1:61678/metrics | grep '^awscni'
awscni_add_ip_req_count 10
awscni_assigned_ip_addresses 8
awscni_assigned_ip_per_cidr{cidr="192.168.1.117/32"} 1
awscni_assigned_ip_per_cidr{cidr="192.168.1.131/32"} 1
awscni_assigned_ip_per_cidr{cidr="192.168.1.184/32"} 1
awscni_assigned_ip_per_cidr{cidr="192.168.1.210/32"} 0
awscni_assigned_ip_per_cidr{cidr="192.168.1.243/32"} 1
awscni_assigned_ip_per_cidr{cidr="192.168.1.247/32"} 1
awscni_assigned_ip_per_cidr{cidr="192.168.1.38/32"} 1
...
프로메테우스 기본 사용 : 모니터링그래프
- 모니터링 대상이 되는 서비스는 자체 웹 서버의 /metrics 에 다양한 메트릭 정보를 노출한다.
- 이후 프로메테우스가 해당 경로에 http get 방식으로 메트릭 정보를 가져와 TSDB로 저장한다.
# 아래 처럼 프로메테우스가 각 서비스의 9100 접속하여 메트릭 정보를 수집
kubectl get node -owide
kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus-node-exporter
# 노드의 9100번의 /metrics 접속 시 다양한 메트릭 정보를 확인할수 있음 : 마스터 이외에 워커노드도 확인 가능
ssh ec2-user@$N1 curl -s localhost:**9100**/metrics
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-192-168-1-122.ap-northeast-2.compute.internal Ready <none> 58m v1.28.5-eks-5e0fdde 192.168.1.122 43.201.54.147 Amazon Linux 2 5.10.210-201.852.amzn2.x86_64 containerd://1.7.11
ip-192-168-2-194.ap-northeast-2.compute.internal Ready <none> 58m v1.28.5-eks-5e0fdde 192.168.2.194 43.202.112.100 Amazon Linux 2 5.10.210-201.852.amzn2.x86_64 containerd://1.7.11
ip-192-168-3-47.ap-northeast-2.compute.internal Ready <none> 58m v1.28.5-eks-5e0fdde 192.168.3.47 13.125.26.188 Amazon Linux 2 5.10.210-201.852.amzn2.x86_64 containerd://1.7.11
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl get svc,ep -n monitoring kube-prometheus-stack-prometheus-node-exporter
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-prometheus-stack-prometheus-node-exporter ClusterIP 10.100.243.33 <none> 9100/TCP 11m
NAME ENDPOINTS AGE
endpoints/kube-prometheus-stack-prometheus-node-exporter 192.168.1.122:9100,192.168.2.194:9100,192.168.3.47:9100 11m
프로메테우스: ingress 도메인으로 접속
# ingress 확인
kubectl get ingress -n monitoring kube-prometheus-stack-prometheus
kubectl describe ingress -n monitoring kube-prometheus-stack-prometheus
# 프로메테우스 ingress 도메인으로 웹 접속
echo -e "Prometheus Web URL = https://prometheus.$MyDomain"
# 웹 상단 주요 메뉴 설명
1. 경고(Alert) : 사전에 정의한 시스템 경고 정책(Prometheus Rules)에 대한 상황
2. 그래프(Graph) : 프로메테우스 자체 검색 언어 PromQL을 이용하여 메트릭 정보를 조회 -> 단순한 그래프 형태 조회
3. 상태(Status) : 경고 메시지 정책(Rules), 모니터링 대상(Targets) 등 다양한 프로메테우스 설정 내역을 확인 > 버전(2.42.0)
4. 도움말(Help)
프로메테우스 설정확인: Status → Runtime & Build Information
- Storage Retention(메트릭 저장기간) 에 대한 옵션 확인가능
프로메테우스 설정확인: Status → Configuration ⇒ “node-exporter”
- job name 을 기준으로 스크래핑 하는것을 확인 가능
전체 메트릭 대상확인: Status → Target
- 해당 스택은 ‘node-exporter’, cAdvisor, Kubernetes 전반적인현황과 다양한 메트릭이 포함됨
curl -s http://192.168.1.141:10249/metrics | tail -n 5
(jjongiam@myeks:default) [root@myeks-bastion ~]# curl -s http://192.168.3.47:10249/metrics | tail -n 5
# TYPE rest_client_transport_cache_entries gauge
rest_client_transport_cache_entries 0
# HELP rest_client_transport_create_calls_total [ALPHA] Number of calls to get a new transport, partitioned by the result of the operation hit: obtained from the cache, miss: created and added to the cache, uncacheable: created and not cached
# TYPE rest_client_transport_create_calls_total counter
rest_client_transport_create_calls_total{result="miss"} 1
curl -s https://192.168.2.141/metrics | tail -n 5
#아무것도 수집되지않음.
프로메테우스 설정확인 : Status → Service Discovery : 모든 endpoint 로 도달 가능 시 자동 발견!, 도달 규칙은 설정Configuration 파일에 정의
- 메트릭을 그래프(Graph)로 조회 : Graph - 아래 PromQL 쿼리(전체 클러스터 노드의 CPU 사용량 합계)입력 후 조회 → Graph 확인
-
- 혹은 지구 아이콘(Metrics Explorer) 클릭 시 전체 메트릭 출력되며, 해당 메트릭 클릭해서 확인
1- avg(rate(node_cpu_seconds_total{mode="idle"}[1m]))
node-exporter, kube-state-metrics, kube-proxy
- 쿼리 : node-exporter
# Table 아래 쿼리 입력 후 Execute 클릭 -> Graph 확인
## 출력되는 메트릭 정보는 node-exporter 를 통해서 노드에서 수집된 정보
node_memory_Active_bytes
# 특정 노드(인스턴스) 필터링 : 아래 IP는 출력되는 자신의 인스턴스 PrivateIP 입력 후 Execute 클릭 -> Graph 확인
node_memory_Active_bytes{instance="192.168.1.122:9100"}
- 쿼리 : kube-state-metrics
# replicas's number
kube_deployment_status_replicas
kube_deployment_status_replicas_available
kube_deployment_status_replicas_available{deployment="coredns"}
# scale out
kubectl scale deployment -n kube-system coredns --replicas 3
# 확인
kube_deployment_status_replicas_available{deployment="coredns"}
- 쿼리 : kube-proxy
#
kubeproxy_sync_proxy_rules_iptables_total
kubeproxy_sync_proxy_rules_iptables_total{table="filter"}
kubeproxy_sync_proxy_rules_iptables_total{table="nat"}
kubeproxy_sync_proxy_rules_iptables_total{table="nat", instance="192.168.1.122:10249"}
애플리케이션 - NGINX 웹서버 애플리케이션 모니터링 설정 및 접속
- nginx 를 helm 설치 시 프로메테우스 익스포터 Exporter 옵션 설정 시 자동으로 nginx 를 프로메테우스 모니터링에 등록 가능!
- 프로메테우스 설정에서 nginx 모니터링 관련 내용을 서비스 모니터 CRD로 추가 가능!
- 기존 애플리케이션 파드에 프로메테우스 모니터링을 추가하려면 사이드카 방식을 사용하며 exporter 컨테이너를 추가!
- nginx 웹 서버(with helm)에 metrics 수집 설정 추가
# 모니터링
watch -d "kubectl get pod; echo; kubectl get servicemonitors -n monitoring"
기존의 nginx deployment 파일
(jjongiam@myeks:default) [root@myeks-bastion ~]# k describe deploy nginx
Name: nginx
Namespace: default
CreationTimestamp: Sun, 31 Mar 2024 05:48:19 +0900
Labels: app.kubernetes.io/instance=nginx
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=nginx
app.kubernetes.io/version=1.25.4
helm.sh/chart=nginx-15.14.0
Annotations: deployment.kubernetes.io/revision: 1
meta.helm.sh/release-name: nginx
meta.helm.sh/release-namespace: default
Selector: app.kubernetes.io/instance=nginx,app.kubernetes.io/name=nginx
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app.kubernetes.io/instance=nginx
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=nginx
app.kubernetes.io/version=1.25.4
helm.sh/chart=nginx-15.14.0
Service Account: nginx
Init Containers:
preserve-logs-symlinks:
Image: docker.io/bitnami/nginx:1.25.4-debian-12-r3
Port: <none>
Host Port: <none>
SeccompProfile: RuntimeDefault
Command:
/bin/bash
Args:
-ec
#!/bin/bash
. /opt/bitnami/scripts/libfs.sh
# We copy the logs folder because it has symlinks to stdout and stderr
if ! is_dir_empty /opt/bitnami/nginx/logs; then
cp -r /opt/bitnami/nginx/logs /emptydir/app-logs-dir
fi
Environment: <none>
Mounts:
/emptydir from empty-dir (rw)
Containers:
nginx:
Image: docker.io/bitnami/nginx:1.25.4-debian-12-r3
Port: 8080/TCP
Host Port: 0/TCP
SeccompProfile: RuntimeDefault
Liveness: tcp-socket :http delay=30s timeout=5s period=10s #success=1 #failure=6
Readiness: tcp-socket :http delay=5s timeout=3s period=5s #success=1 #failure=3
Environment:
BITNAMI_DEBUG: false
NGINX_HTTP_PORT_NUMBER: 8080
Mounts:
/opt/bitnami/nginx/conf from empty-dir (rw,path="app-conf-dir")
/opt/bitnami/nginx/logs from empty-dir (rw,path="app-logs-dir")
/opt/bitnami/nginx/tmp from empty-dir (rw,path="app-tmp-dir")
/tmp from empty-dir (rw,path="tmp-dir")
Volumes:
empty-dir:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-7f7b5d655f (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 34m deployment-controller Scaled up replica set nginx-7f7b5d655f to 1
# 파라미터 파일 생성 : 서비스 모니터 방식으로 nginx 모니터링 대상을 등록하고, export 는 9113 포트 사용
cat <<EOT > ~/nginx_metric-values.yaml
**metrics**:
enabled: true
service:
port: 9113
**serviceMonitor**:
enabled: true
namespace: monitoring
interval: 10s
EOT
# 배포
helm **upgrade** nginx bitnami/nginx **--reuse-values** -f nginx_metric-values.yaml
# 메트릭 확인 >> 프로메테우스에서 Target 확인
NGINXIP=$(kubectl get pod -l app.kubernetes.io/instance=nginx -o jsonpath={.items[0].status.podIP})
curl -s http://$NGINXIP:9113/metrics # nginx_connections_active Y 값 확인해보기
curl -s http://$NGINXIP:9113/metrics | grep ^nginx_connections_active
(jjongiam@myeks:default) [root@myeks-bastion ~]# curl -s http://$NGINXIP:9113/metrics | grep ^nginx_connections_active
nginx_connections_active 1
# nginx 파드내에 컨테이너 갯수 확인
kubectl get pod -l app.kubernetes.io/instance=nginx
kubectl describe pod -l app.kubernetes.io/instance=nginx
# 접속 주소 확인 및 접속
echo -e "Nginx WebServer URL = https://nginx.$MyDomain"
curl -s https://nginx.$MyDomain
kubectl logs deploy/nginx -f
# 반복 접속
while true; do curl -s https://nginx.$MyDomain -I | head -n 1; date; sleep 1; done
배포확인: Targets 에 nginx 생성 확인
배포확인:Configuration Job 에 nginx 생성 확인
설정이 자동으로 반영되는 원리 : 주요 config 적용 필요 시 reloader 동작!
**kubectl describe pod -n monitoring prometheus-kube-prometheus-stack-prometheus-0 | grep config-reloader**
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl describe pod -n monitoring prometheus-kube-prometheus-stack-prometheus-0 | grep config-reloader
init-config-reloader:
Image: quay.io/prometheus-operator/prometheus-config-reloader:v0.72.0
Image ID: quay.io/prometheus-operator/prometheus-config-reloader@sha256:89a6c7d3fd614ee1ed556f515f5ecf2dba50eec9af418ac8cd129d5fcd2f5c18
/bin/prometheus-config-reloader
config-reloader:
Image: quay.io/prometheus-operator/prometheus-config-reloader:v0.72.0
Image ID: quay.io/prometheus-operator/prometheus-config-reloader@sha256:89a6c7d3fd614ee1ed556f515f5ecf2dba50eec9af418ac8cd129d5fcd2f5c18
/bin/prometheus-config-reloader
Normal Pulled 45m kubelet Container image "quay.io/prometheus-operator/prometheus-config-reloader:v0.72.0" already present on machine
Normal Created 45m kubelet Created container init-config-reloader
Normal Started 45m kubelet Started container init-config-reloader
Normal Pulled 45m kubelet Container image "quay.io/prometheus-operator/prometheus-config-reloader:v0.72.0" already present on machine
Normal Created 45m kubelet Created container config-reloader
Normal Started 45m kubelet Started container config-reloader
쿼리 : 애플리케이션, Graph → nginx_ 입력 시 다양한 메트릭 추가 확인 : nginx_connections_active 등
# nginx scale out : Targets 확인
kubectl scale deployment nginx --replicas 2
# 쿼리 Table -> Graph
nginx_up
nginx_http_requests_total
nginx_connections_active
새롭게 하나 생기는것 확인
6. Grafana
그라파나: TSDB 데이터 를 시각화, 다양한 데이터 형식을 지원함(현재 실습환경에서는 prometheus 를 사용함)
- 접속 정보 확인 및 로그인 : 기본 계정 - admin / prom-operator
# 그라파나 버전 확인
kubectl exec -it -n monitoring deploy/kube-prometheus-stack-grafana -- grafana-cli --version
#grafana cli version 10.4.0
# ingress 확인
kubectl get ingress -n monitoring kube-prometheus-stack-grafana
kubectl describe ingress -n monitoring kube-prometheus-stack-grafana
# ingress 도메인으로 웹 접속 : 기본 계정 - admin / prom-operator
echo -e "Grafana Web URL = https://grafana.$MyDomain"
- Search dashboards : 대시보드 검색
- Starred : 즐겨찾기 대시보드
- Dashboards : 대시보드 전체 목록 확인
- Explore : 쿼리 언어 PromQL를 이용해 메트릭 정보를 그래프 형태로 탐색
- Alerting : 경고, 에러 발생 시 사용자에게 경고를 전달
- Connections : 설정, 예) 데이터 소스 설정 등
- Administartor : 사용자, 조직, 플러그인 등 설정
Conntecitons → Data sources → Add new data source 버튼 선택
데이터 소스 접속 확인
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
kubectl get pod netshoot-pod
# 접속 확인
**kubectl exec -it netshoot-pod -- nslookup kube-prometheus-stack-prometheus.monitoring**
kubectl exec -it netshoot-pod -- curl -s kube-prometheus-stack-prometheus.monitoring:9090/graph -v ; echo
# 삭제
**kubectl delete pod** netshoot-pod
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl exec -it netshoot-pod -- nslookup kube-prometheus-stack-prometheus.monitoring
Server: 10.100.0.10
Address: 10.100.0.10#53
Name: kube-prometheus-stack-prometheus.monitoring.svc.cluster.local
Address: 10.100.192.39
(jjongiam@myeks:default) [root@myeks-bastion ~]# kubectl exec -it netshoot-pod -- curl -s kube-prometheus-stack-prometheus.monitoring:9090/graph -v ; echo
* Host kube-prometheus-stack-prometheus.monitoring:9090 was resolved.
* IPv6: (none)
* IPv4: 10.100.192.39
* Trying 10.100.192.39:9090...
* Connected to kube-prometheus-stack-prometheus.monitoring (10.100.192.39) port 9090
> GET /graph HTTP/1.1
> Host: kube-prometheus-stack-prometheus.monitoring:9090
> User-Agent: curl/8.6.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 30 Mar 2024 21:45:00 GMT
< Content-Length: 734
< Content-Type: text/html; charset=utf-8
<
* Connection #0 to host kube-prometheus-stack-prometheus.monitoring left intact
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><script>const GLOBAL_CONSOLES_LINK="",GLOBAL_AGENT_MODE="false",GLOBAL_READY="true"</script><link rel="manifest" href="./manifest.json" crossorigin="use-credentials"/><title>Prometheus Time Series Collection and Processing Server</title><script defer="defer" src="./static/js/main.87eaac7d.js"></script><link href="./static/css/main.e075b686.css" rel="stylesheet"></head><body class="bootstrap"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
#삭제
kubectl delete pod netshoot-pod
그라파나 대시보드 사용
Data sources → Prometheus → Build a dashboard → (대시보드 번호 15757)
등장!
'외부활동' 카테고리의 다른 글
[AEWS] 2기 스터디: EKS의 인증/인가 절차1 (0) | 2024.04.11 |
---|---|
[AEWS] 2기 스터디: Autoscaling 의 다양한 방법 (0) | 2024.04.07 |
[AEWS] 2기 스터디: EKS Storage 에 대해서 (1) | 2024.03.24 |
[AEWS] 2기 스터디: AWS VPC + ALB (3) | 2024.03.17 |
[AEWS] 2기 스터디: 스터디 기본지식 + EKS내용정리 (0) | 2024.03.10 |