지난 Cloud wave 프로젝트 때 경험하지 못한 K8S 환경에서 Monitoring 구축을 진행해보았다.
UI 중심으로 빠른 시각화를 경험하고 싶고 또 리소스가 부족한 로컬 클러스터인 것을 감안하여 ELK를 사용하지 않고 Grafana와 Prometheus를 사용한 메트릭 기반의 Monitoring을 구축하였다.
하지만 Log 기반의 Monitoring 또한 확인하고 싶었기에 리소스 측면에서 그나마 나은 Loki를 사용해 보았지만 그럼에도 리소스가 부족해 Pending되는 Pod들이 많았기에 Grafana와 Prometheus만을 사용해서 Monitoring 환경을 구성해보았다.
Prometheus
Prometheus는 시계열 데이터(Metric)를 수집, 저장, 쿼리 및 경고를 생성하는 오픈 소스 모니터링 및 알림 시스템이다.
2012년 SoundCloud에서 개발되었고, 현재 CNCF(Cloud Native Computing Foundation)의 프로젝트로 관리되고 있다. Docker 환경에서도 사용되지만 Kubernetes와 같은 클라우드 네이티브 환경에서 특히 자주 사용된다.
특징
1. 시계열 데이터 (Metric) 수집
데이터를 metric name과 label(key-value)의 조합으로 저장하고, 고유 식별자(time series)와 타임스탬프가 포함된 값으로 구성한다.
2. Pull 방식의 데이터 수집
Prometheus는 모니터링 대상(exporter)으로부터 데이터를 Pull 방식으로 가져온다.
HTTP 기반의 /metrics 엔드포인트를 통해 데이터를 수집한다.
3. 다양한 Exporter 제공
기본 시스템 메트릭 수집용 Node Exporter.
애플리케이션 메트릭을 제공하는 Custom Exporter.
데이터베이스(MySQL, PostgreSQL 등), 메시지 브로커(RabbitMQ, Kafka) 등 다양한 서드파티 서비스에 대한 Exporter가 제공된다.
해당 Exporter들은 클러스터의 Node, Container, Pod들의 상세한 메트릭을 수집하고 서버로 제공한다.
4. PromQL (Prometheus Query Language)
수집한 시계열 데이터를 분석하고 시각화할 수 있는 강력한 쿼리 언어를 제공한다.
이 쿼리 언어는 Prometheus UI, Grafana 대시보드에서 다양한 함수와 연산자와 함께 사용되어 시계열 데이터를 시각화한다.
5. 알림 기능 제공
Alertmanager와 통합되어 경고를 관리한다. 특정 조건이 되었을 떄 Slack, Email, PagerDuty 등 다양한 채널로 알림을 전송할 수 있다.
구축
1. helm을 통해 Prometheus와 grafana을 설치할 예정이기에 homebrew를 통해 먼저 helm을 설치한다.
이전 프로젝트에서 팀원이 구축한 모니터링을 통해 멀티 리전을 테스트 해본 경험은 있지만, 직접 구축을 하진 않았었기에 이번에 직접 구축해볼 수 있어서 기쁘다.
오픈소스인 Prometheus와 Grafana는 오픈소스로서 다양한 커뮤니티가 활성화 되어있고 자료들도 많아 다양한 문제 해결을 위한 솔루션과 지식을 쉽게 얻을 수 있었다.
또 사용자가 자유롭게 커스터마이징을 하여 본인의 환경에 맞게 원하는 정보를 시각화 할 수 있고 또 그것을 기반으로 알림을 받는다면 큰 장점이 될 것이라 생각했다.
Prometheus와 Grafana에 대해 깊이 학습한 후 사용하지 않고 이미 완성되어있는 대쉬보드 템플릿을 사용하였기에 구축한 것을 확인하는 과정에서 끝났지만, Prometheus의 PromQL을 학습하여 익숙해진다면 여러 메트릭을 직접 수집하고 대시보드 또한 직접 커스터마이징 할 수 있을 것이라 생각한다.
NodePort를 32000으로 서비스를 생성한다. http://<<worker - node ip>:32000 으로 접속할 수 있다. jnlport는 Cloud 설정을 하기 위해 열어둔다.
(설정만 할 뿐 실제로 사용하지는 않기 때문에 따라하지 않으셔도 됩니다.)
Jenkins 설정
생성 확인 및 로그인
k logs {jenkins pod} -n jenkins를 통해 초기 비밀번호를 얻을 수 있다.
다음과 같은 log에 비밀번호가 적혀있고 직접 exec를 통해 들어간 뒤 cat /var/jenkins_home/secrets/initialAdminPassword를 통하여서도 확인할 수 있다.
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
dab6423296a64832a422e252107711ca
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
*************************************************************
*************************************************************
작성자 분꼐서 상당히 자세하게 적어주셨기에 해당 부분을 그대로 따라갔고 변경한 부분만 적도록 하겠다.
Webhook을 하기 위해선 공인 ip가 필요하나 제목에서부터 알 수 있듯이 로컬에서 K8S를 실행하였기 때문에 모든 Node들이 사설 ip일 수 밖에 없다. polling 방식으로도 jenkins를 사용할 수 있겠으나 그러기엔 아쉬워 Ngrok을 통해 공인 IP를 발급받고 Webhook 설정을 해주었다.
sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet
6. kubeadm init
kubernetes에서 pod-network-cidr default 값이 10.244.0.0/16이기에 추가적인 설정을 피하려면 default 값을 사용해준다.
ip address값은 ip add 명령어를 통해 확인할 수 있으며 동일한 과정을 따라왔다면 enp0s8이 해당 값이 되겠다.
kubectl get node, po, ns 어떤 명령으로도 정상 동작을 확인할 수 있다.
kdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
sudo kubeadm join 172.30.1.96:6443 --token udr7l0.hu1o5801ove1jnns \
--discovery-token-ca-cert-hash sha256:d0f0941ac6c28bbf051d552358d8260b7ed1f7c0a2dceb48f2ec80f31799a26e
정상적으로 init이 성공하였다면 위와 같이 결과가 나올텐데 'sudo kubeadm join {controlplane ip}:6443 -token {token} --discovery-token-ca-cert-hash sha256:{hash} ' 해당 내용을 기록해두었다가 후에 worker node에서 join할 때 사용해야 한다.