Fargate 에서 실행 중인 pods 를 모니터링 할 수는 있을까.
초창기에 EKS 를 fargate 로 세팅한 후에 모니터링을 위해 prometheus 까지 만들어 놓으려다가, 실패하고 이제야 설치를 해봤다. 기억으로는 아마도 fargate 때문이었다. 그때까지만 해도 대부분 문서들이 전부 EC2 기반이라 삽질 조금 하다가 깔끔하게 접었었다.
지금은 Fargate / EC2 상관없이 AWS 에서 제공하는 AMP(Amazon Managed Service for Prometheus) 를 이용하면 쉽게 연동이 가능할 것 같은데, 역시나 서울 리전은 아직 해당 서비스를 제공하지 않는다. 그리하여 짬 내서 다시 한번 시도해 보았다.
일단 나는 EC2 를 쓸 생각이 없었는데, Prometheus 는 Fargate 로 설치할 수 없다. Prometheus 의 시계열 데이터베이스가 컨테이너 재시작 중에 손실되지 않도록 영구 볼륨(Persistent Volumes) 을 사용하여 Prometheus 에 지속성을 제공해야 한다. 그러려면 우선 EKS 에서 EC2 노드 그룹 (Node Group) 을 생성해야 한다.
1. Add Node Group
노드 그룹을 생성할 때는, 노드 IAM 역할(role) 을 필요로 한다.
IAM 대시보드에서 아래 두가지 정책을 포함하는 역할(ex. EksEC2nodeGroupRole) 을 만든다.
- AmazonEKSWorkerNodePolicy
- AmazonEC2ContainerRegistryReadOnly
또한, 쿠버네티스의 서비스계정에서 IAM 역할을 사용할 수 있도록 Amazon VPC CNI plugin 을 구성한다.
# aws-node 서비스계정 생성/업데이트
$ eksctl create iamserviceaccount \
--name aws-node \
--namespace kube-system \
--cluster my-cluster \
--role-name "AmazonEKSVPCCNIRole" \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy \
--override-existing-serviceaccounts \
--approve
2023-01-31 17:42:15 [ℹ] eksctl version 0.75.0
2023-01-31 17:42:15 [ℹ] using region ap-northeast-2
2023-01-31 17:42:16 [ℹ] 1 iamserviceaccount (kube-system/aws-node) was included (based on the include/exclude rules)
2023-01-31 17:42:16 [!] metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set
2023-01-31 17:42:16 [ℹ] 1 task: {
2 sequential sub-tasks: {
create IAM role for serviceaccount "kube-system/aws-node",
create serviceaccount "kube-system/aws-node",
} }2023-01-31 17:42:16 [ℹ] building iamserviceaccount stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:42:16 [ℹ] deploying stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:42:16 [ℹ] waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:42:33 [ℹ] waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:42:49 [ℹ] waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:43:09 [ℹ] waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:43:26 [ℹ] waiting for CloudFormation stack "eksctl-my-cluster-addon-iamserviceaccount-kube-system-aws-node"
2023-01-31 17:43:26 [ℹ] serviceaccount "kube-system/aws-node" already exists
2023-01-31 17:43:26 [ℹ] updated serviceaccount "kube-system/aws-node"
role 과 serviceAccounts 설정을 마쳤으면 eks 대시보드에서 노드 그룹을 추가/확인 한다. (node 수는 1개만 설정했다. 100G)
$ kubectl get pods -w -n kube-system
NAME READY STATUS RESTARTS AGE
aws-node-q123f 1/1 Running 0 4h5m
kube-proxy-abcmh 1/1 Running 0 4h5m
...
EKS 콘솔의 추가기능에서 Amazon EBS CSI 드라이버(v1.23 버전부터 EC2 노드그룹 사용시 필요) 를 설치해야 하는데 IAM 역할을 미리 생성 해준다. (해당 권한이 올바로 설치되지 않으면 아래 storage 가 생성되지 못한다.)
$ eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve \
--role-only \
--role-name AmazonEKS_EBS_CSI_DriverRole
2. Prometheus 설치
# prometheus install
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
$ helm install prometheus prometheus-community/prometheus \
--namespace prometheus \
--set alertmanager.persistentVolume.storageClass="gp2" \
--set server.persistentVolume.storageClass="gp2"
NAME: prometheus
LAST DEPLOYED: Tue Jan 31 13:04:08 2023
NAMESPACE: prometheus
STATUS: deployed
REVISION: 1
NOTES:
The Prometheus server can be accessed via port 80 on the following DNS name from within your cluster:
prometheus-server.prometheus.svc.cluster.local
Get the Prometheus server URL by running these commands in the same shell:
export POD_NAME=$(kubectl get pods --namespace prometheus -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace prometheus port-forward $POD_NAME 9090
The Prometheus alertmanager can be accessed via port on the following DNS name from within your cluster:
prometheus-%!s(<nil>).prometheus.svc.cluster.local
Get the Alertmanager URL by running these commands in the same shell:
export POD_NAME=$(kubectl get pods --namespace prometheus -l "app=prometheus,component=" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace prometheus port-forward $POD_NAME 9093
#################################################################################
###### WARNING: Pod Security Policy has been disabled by default since #####
###### it deprecated after k8s 1.25+. use #####
###### (index .Values "prometheus-node-exporter" "rbac" #####
###### . "pspEnabled") with (index .Values #####
###### "prometheus-node-exporter" "rbac" "pspAnnotations") #####
###### in case you still need it. #####
#################################################################################
The Prometheus PushGateway can be accessed via port 9091 on the following DNS name from within your cluster:
prometheus-prometheus-pushgateway.prometheus.svc.cluster.local
Get the PushGateway URL by running these commands in the same shell:
export POD_NAME=$(kubectl get pods --namespace prometheus -l "app=prometheus-pushgateway,component=pushgateway" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace prometheus port-forward $POD_NAME 9091
For more information on running Prometheus, visit:
https://prometheus.io/
모니터링은 내부에서만 사용할 예정이라 기본사양인 gp2 EBS 볼륨을 사용했으며, alertmanager 용 2G / server 용 8G 볼륨이 생성된다.
# check prometheus pods
$ kubectl get all -n prometheus
NAME READY STATUS RESTARTS AGE
pod/prometheus-alertmanager-0 1/1 Running 0 85s
pod/prometheus-kube-state-metrics-7cdcf7cc98-m7n9q 1/1 Running 0 85s
pod/prometheus-prometheus-node-exporter-552n8 0/1 Pending 0 85s
pod/prometheus-prometheus-node-exporter-5hkjp 0/1 Pending 0 84s
pod/prometheus-prometheus-node-exporter-5k54s 0/1 Pending 0 85s
pod/prometheus-prometheus-node-exporter-77gsb 1/1 Running 0 84s
pod/prometheus-prometheus-node-exporter-9ckh5 1/1 Running 0 85s
pod/prometheus-prometheus-node-exporter-gtvht 0/1 Pending 0 85s
pod/prometheus-prometheus-node-exporter-hxkn6 0/1 Pending 0 84s
pod/prometheus-prometheus-node-exporter-rxl4b 0/1 Pending 0 85s
pod/prometheus-prometheus-node-exporter-xr468 0/1 Pending 0 85s
pod/prometheus-prometheus-node-exporter-zqxrm 0/1 Pending 0 85s
pod/prometheus-prometheus-pushgateway-9d598d466-844ct 1/1 Running 0 85s
pod/prometheus-server-6487b794-qtddq 2/2 Running 0 85s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/prometheus-alertmanager ClusterIP 172.20.40.182 <none> 9093/TCP 85s
service/prometheus-alertmanager-headless ClusterIP None <none> 9093/TCP 85s
service/prometheus-kube-state-metrics ClusterIP 172.20.106.187 <none> 8080/TCP 85s
service/prometheus-prometheus-node-exporter ClusterIP 172.20.144.95 <none> 9100/TCP 85s
service/prometheus-prometheus-pushgateway ClusterIP 172.20.17.45 <none> 9091/TCP 85s
service/prometheus-server ClusterIP 172.20.39.89 <none> 80/TCP 85s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/prometheus-prometheus-node-exporter 10 10 2 10 2 <none> 85s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/prometheus-kube-state-metrics 1/1 1 1 85s
deployment.apps/prometheus-prometheus-pushgateway 1/1 1 1 85s
deployment.apps/prometheus-server 1/1 1 1 85s
NAME DESIRED CURRENT READY AGE
replicaset.apps/prometheus-kube-state-metrics-7cdcf7cc98 1 1 1 86s
replicaset.apps/prometheus-prometheus-pushgateway-9d598d466 1 1 1 86s
replicaset.apps/prometheus-server-6487b794 1 1 1 86s
NAME READY AGE
statefulset.apps/prometheus-alertmanager 1/1 86s
만약 alertmanager 가 Pending 상태라면 prometheus uninstall 후에, 해당 EBS 볼륨(아마도 2G)도 직접 삭제하고, pvc 도 조회하여 삭제한다. (kubectl delete pvc name -n namespace)... prometheus uninstall 때 기존 alertmanager 관련 볼륨정보가 삭제되지 않는듯... 여러번 설치테스트 하다가 이것 때문에 삽질 좀 했다.
0/9 nodes are available: 1 node(s) had volume node affinity conflict, 8 node(s) had taint {eks.amazonaws.com/compute-type: fargate}, that the pod didn't tolerate.
또한 node-exporter 는 ec2 노드에서 작동하는 daemonset 으로 실행되지만 이미 생성된 fargate 노드들이 daemonset 을 지원하지 않기 때문에 fargate 에서 schedule 을 수행할 수 없다. node-exporter 의 역할은 실행중인 node에 배치되어 해당 호스트의 low-level 매트릭(vCPU, Mem, Network, Disk) 수집을 담당하는데, kube-state-metrics 가 이 메트릭을 대신 수집해 주어 node-exporter 없이도 지표 수집이 가능한 것 같아, node-exporter 를 전부 삭제했다.
# node-exporter 삭제
$ kubectl delete daemonset prometheus-prometheus-node-exporter -n prometheus
3. prometheus URL 접속 확인 (선택)
# Prometheus server URL
$ export POD_NAME=$(kubectl get pods --namespace prometheus -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}")
# 127.0.0.1:9090
$ kubectl --namespace prometheus port-forward $POD_NAME 9090
# Alertmanager URL
$ export POD_NAME=$(kubectl get pods --namespace prometheus -l "app.kubernetes.io/name=alertmanager" -o jsonpath="{.items[0].metadata.name}")
# 127.0.0.1:9093
$ kubectl --namespace prometheus port-forward $POD_NAME 9093
# PushGateway URL
$ export POD_NAME=$(kubectl get pods --namespace prometheus -l "app.kubernetes.io/name=prometheus-pushgateway" -o jsonpath="{.items[0].metadata.name}")
# 127.0.0.1:9091
$ kubectl --namespace prometheus port-forward $POD_NAME 9091
4. Grafana 설치
$ vi grafana.yaml
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus-server.prometheus.svc.cluster.local
access: proxy
isDefault: true
# grafana install
$ helm repo add grafana https://grafana.github.io/helm-charts
$ helm install grafana grafana/grafana \
--namespace prometheus \
--set persistence.storageClassName="gp2" \
--set persistence.enabled=true \
--set adminPassword='admin_password' \
--values ./grafana.yaml \
--set service.type=LoadBalancer
W0131 18:50:26.890856 44556 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0131 18:50:27.492718 44556 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME: grafana
LAST DEPLOYED: Tue Jan 31 18:50:26 2023
NAMESPACE: prometheus
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
kubectl get secret --namespace prometheus grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
2. The Grafana server can be accessed via port 80 on the following DNS name from within your cluster:
grafana.prometheus.svc.cluster.local
Get the Grafana URL to visit by running these commands in the same shell:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc --namespace prometheus -w grafana'
export SERVICE_IP=$(kubectl get svc --namespace prometheus grafana -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
http://$SERVICE_IP:80
3. Login with the password from step 1 and the username: admin
grafana 설치 확인
# Grafana URL
$ kubectl get svc --namespace prometheus grafana -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
abc29d87564994207b5dfb965886a11e-1234385928.ap-northeast-2.elb.amazonaws.com
[ dashboard id: 12006 ]
# 만약 망했으면 uninstall 하고 처음부터 다시 try...
$ helm uninstall prometheus --namespace prometheus
$ helm uninstall grafana --namespace prometheus
삭제되지 않은 볼륨들도 모두 삭제한다.
대부분의 쿠버네티스 스펙이 helm 으로 한방에 설치되니까 편하긴 한듯...
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.