1. 기본 환경 배포
이번 실습은 IAM 사용자 계정을 통해 관리 콘솔에 접근하고 액세스 키를 활용해 awscli 도구를 사용합니다.
해당 작업을 수행하지 않았다면 아래 토글을 확장해 작업을 선행하고 본격적인 실습에 들어갑니다.
IAM 사용자 생성 및 액세스 키 생성
1.1. Terraform을 통한 기본 인프라 배포
Terraform을 통한 기본 인프라 배포에 앞서 SSH 키 페어, IAM User Access Key ID, IAM User Secret Access Key를 미리 확인하고 메모해 둡니다.
Terraform으로 기본 인프라 배포
cd cnaee_class_tf/ch3
Bash
복사
# 실습 디렉터리 경로 진입
export TF_VAR_KeyName=[각자 ssh keypair]
export TF_VAR_MyIamUserAccessKeyID=[각자 iam 사용자의 access key id]
export TF_VAR_MyIamUserSecretAccessKey=[각자 iam 사용자의 secret access key]
export TF_VAR_SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32
Bash
복사
# Terraform 환경 변수 저장
terraform init
terraform plan
Bash
복사
# Terraform 배포
nohup sh -c "terraform apply -auto-approve" > create.log 2>&1 &
Bash
복사
Note:
nohup으로 백그라운드로 실행하도록 변경했습니다.
Terraform 배포가 완료되면 정상적으로 자원 생성이 되었는지 확인을 합니다.(cat create.log)
Terraform을 통한 기본 인프라 배포가 완료되면 관리 콘솔에서 생성된 인프라들을 확인합니다.
Note:
AWS 관리 콘솔에 로그인 할 땐 IAM 사용자 계정으로 진행합니다.
1.2. 기본 정보 확인 및 설정
Terraform 배포가 완료 후 출력되는 Output 정보에서 bastion_host_ip의 퍼블릭 IP를 확인합니다.
해당 IP로 EKS 관리용 인스턴스(myeks-bastion-EC2)에 SSH로 접속하고 아래 명령어를 통해 정보를 확인합니다.
Note:
myeks-bastion-EC2의 OS 변경으로 SSH 접근에 대한 계정을 ubuntu로 지정합니다.
(ssh -i ~/.ssh/XXXX.pem ubuntu@X.X.X.X)
기본 설정 및 확인
aws eks update-kubeconfig \
--region $AWS_DEFAULT_REGION \
--name $CLUSTER_NAME
Shell
복사
# EKS 클러스터 인증 정보 업데이트
kubens default
Bash
복사
# kubens default 설정
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PublicSubnet1,$PublicSubnet2,$PublicSubnet3
echo $PrivateSubnet1,$PrivateSubnet2,$PrivateSubnet3
Bash
복사
# 변수 호출 종합
eksctl get cluster
Bash
복사
# eksctl을 통한 eks cluster 정보 확인
eksctl get nodegroup \
--cluster $CLUSTER_NAME \
--name ${CLUSTER_NAME}-node-group
Bash
복사
# eksctl을 통한 노드 그룹 정보 확인
kubectl get node -owide
Bash
복사
# kubectl을 통한 노드 정보 확인
PublicN1=$(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})
PublicN2=$(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})
PublicN3=$(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 PublicN1=$PublicN1" >> /etc/profile
echo "export PublicN2=$PublicN2" >> /etc/profile
echo "export PublicN3=$PublicN3" >> /etc/profile
echo $PublicN1, $PublicN2, $PublicN3
Bash
복사
# 노드 IP 변수 선언
for node in $PublicN1 $PublicN2 $PublicN3; \
do \
ssh -i ~/.ssh/kp_node.pem -o StrictHostKeyChecking=no ec2-user@$node hostname; \
done
Bash
복사
# 노드에 ssh 접근 확인
2. Observability Backends 설치
LGTM Observability Full Stack 환경 구성을 위한 Backend System을 설치합니다.
•
[Metrics] - Grafana Mimir
•
[Logs] - Grafana Loki
•
[Traces] - Grafana Tempo
사전 준비
export CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo "export CERT_ARN=$CERT_ARN" >> /etc/profile; echo $CERT_ARN
export NICKNAME=[각자의 닉네임]
echo "export NICKNAME=$NICKNAME" >> /etc/profile; echo $NICKNAME
export OIDC_ARN=$(aws iam list-open-id-connect-providers --query 'OpenIDConnectProviderList[*].Arn' --output text)
echo "export OIDC_ARN=$OIDC_ARN" >> /etc/profile; echo $OIDC_ARN
export OIDC_URL=${OIDC_ARN#*oidc-provider/}
echo "export OIDC_URL=$OIDC_URL" >> /etc/profile; echo $OIDC_URL
Bash
복사
# 변수 선언
만약 인증서가 없을 경우..
cat <<EOT | kubectl apply -f -
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: gp3
allowVolumeExpansion: true
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
type: gp3
allowAutoIOPSPerGBIncrease: 'true'
encrypted: 'true'
EOT
Bash
복사
# gp3 storage class 생성
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
Bash
복사
# helm repo - grafana 추가
kubectl create ns monitoring
kubectl create ns logging
kubectl create ns tracing
kubectl create ns grafana
Bash
복사
# namespace 생성
Values 파일 다운로드
wget https://github.com/cloudneta/cnaeelab/raw/master/_data/values.zip
unzip values.zip; rm values.zip
cd values
tree
Bash
복사
# values 파일 다운로드 및 경로 진입 후 tree 명령
2.1. Grafana Mimir 설치 및 확인
Grafana Mimir 모니터링
watch kubectl get pod,pv,pvc,cm -n monitoring
Bash
복사
# [모니터링1] monitoring 네임스페이스 - pod, pv, pvc, configmap 모니터링
while true; do aws ec2 describe-volumes \
--filters Name=tag:ebs.csi.aws.com/cluster,Values=true \
--query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" \
--output text; date; sleep 1; done
Bash
복사
# [모니터링2] 동적 프로비저닝으로 생성되는 EBS 볼륨 확인
Mimir용 S3 Bucket 생성
mkdir ~/irsa; cd ~/irsa
Bash
복사
# irsa 설정 파일 경로 생성 및 진입
aws s3api create-bucket \
--bucket mimir-${NICKNAME} \
--region $AWS_DEFAULT_REGION \
--create-bucket-configuration LocationConstraint=$AWS_DEFAULT_REGION
aws s3 ls
Bash
복사
# mimir용 s3 bucket 생성 및 확인
export MIMIR_BUCKET_NAME="mimir-${NICKNAME}"
echo "export MIMIR_BUCKET_NAME=$MIMIR_BUCKET_NAME" >> /etc/profile; echo $MIMIR_BUCKET_NAME
Bash
복사
# s3 bucket 이름 변수 저장
Mimir - S3 IAM Policy 생성
cat >grafana-mimir-s3-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "MimirStorage",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::${MIMIR_BUCKET_NAME}",
"arn:aws:s3:::${MIMIR_BUCKET_NAME}/*"
]
}
]
}
EOF
cat grafana-mimir-s3-policy.json
Bash
복사
# grafana-mimir-s3-poilcy.json 파일 생성
aws iam create-policy \
--policy-name aws-mimir-s3 \
--policy-document file://grafana-mimir-s3-policy.json
Bash
복사
# aws-mimir-s3 IAM Policy 생성
Mimir - S3 IAM Role 생성
cat >trust-rs-mimir.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${OIDC_ARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_URL}:sub": "system:serviceaccount:monitoring:mimir",
"${OIDC_URL}:aud": "sts.amazonaws.com"
}
}
}
]
}
EOF
cat trust-rs-mimir.json
Bash
복사
# Mimir IAM Role Trust rs 생성
aws iam create-role \
--role-name AWS-Mimir-Role \
--assume-role-policy-document file://trust-rs-mimir.json
Bash
복사
# AWS-Mimir-Role 생성
aws iam attach-role-policy \
--role-name AWS-Mimir-Role \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-mimir-s3
Bash
복사
# IAM Policy와 IAM Role 연결
export MIMIR_ROLE_ARN=arn:aws:iam::${ACCOUNT_ID}:role/AWS-Mimir-Role
echo "export MIMIR_ROLE_ARN=$MIMIR_ROLE_ARN" >> /etc/profile; echo $MIMIR_ROLE_ARN
Bash
복사
# Mimir IAM Role ARN 변수 선언
Mimir 설치
export | grep MIMIR
Bash
복사
# MIMIR 변수 출력
cd ~/values; envsubst < mimir-temp-values.yaml > mimir-values.yaml
cat mimir-values.yaml | yh
Bash
복사
# mimir-values.yaml 확인
helm install mimir grafana/mimir-distributed \
-n monitoring \
-f mimir-values.yaml \
--version 5.4.0
Bash
복사
# mimir-values 파일을 활용해서 Mimir를 helm chart로 설치
2.2. Grafana Loki 설치 및 확인
Grafana Loki 모니터링
watch kubectl get pod,pv,pvc -n logging
Bash
복사
# [모니터링1] logging 네임스페이스 - pod, pv, pvc 모니터링
Loki용 S3 Bucket 생성
cd ~/irsa
Bash
복사
# irsa 경로 이동
aws s3api create-bucket \
--bucket loki-${NICKNAME} \
--region $AWS_DEFAULT_REGION \
--create-bucket-configuration LocationConstraint=$AWS_DEFAULT_REGION
aws s3 ls
Bash
복사
# loki용 s3 bucket 생성
export LOKI_BUCKET_NAME="loki-${NICKNAME}"
echo "export LOKI_BUCKET_NAME=$LOKI_BUCKET_NAME" >> /etc/profile; echo $LOKI_BUCKET_NAME
Bash
복사
# s3 bucket 이름 변수 저장
Loki - S3 IAM Policy 생성
cat >grafana-loki-s3-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LokiStorage",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::${LOKI_BUCKET_NAME}",
"arn:aws:s3:::${LOKI_BUCKET_NAME}/*"
]
}
]
}
EOF
cat grafana-loki-s3-policy.json
Bash
복사
# grafana-loki-s3-poilcy.json 파일 생성
aws iam create-policy \
--policy-name aws-loki-s3 \
--policy-document file://grafana-loki-s3-policy.json
Bash
복사
# aws-loki-s3 IAM Policy 생성
Loki - S3 IAM Role 생성
# Loki IAM Role Trust rs 생성
cat >trust-rs-loki.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${OIDC_ARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_URL}:sub": "system:serviceaccount:logging:loki",
"${OIDC_URL}:aud": "sts.amazonaws.com"
}
}
},
{
"Effect": "Allow",
"Principal": {
"Federated": "${OIDC_ARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_URL}:sub": "system:serviceaccount:logging:loki-compactor",
"${OIDC_URL}:aud": "sts.amazonaws.com"
}
}
}
]
}
EOF
cat trust-rs-loki.json
Bash
복사
aws iam create-role \
--role-name AWS-Loki-Role \
--assume-role-policy-document file://trust-rs-loki.json
Bash
복사
# AWS-Loki-Role 생성
aws iam attach-role-policy \
--role-name AWS-Loki-Role \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-loki-s3
Bash
복사
# IAM Policy와 IAM Role 연결
export LOKI_ROLE_ARN=arn:aws:iam::${ACCOUNT_ID}:role/AWS-Loki-Role
echo "export LOKI_ROLE_ARN=$LOKI_ROLE_ARN" >> /etc/profile; echo $LOKI_ROLE_ARN
Bash
복사
# Loki IAM Role ARN 변수 선언
Loki 설치
export | grep LOKI
Bash
복사
# LOKI 변수 출력
cd ~/values; envsubst < loki-temp-values.yaml > loki-values.yaml
cat loki-values.yaml | yh
Bash
복사
# loki-values.yaml 파일 확인
helm install loki grafana/loki-distributed \
-n logging \
-f loki-values.yaml \
--version 0.79.1
Bash
복사
# loki-values 파일을 활용해서 loki를 helm chart로 설치
2.3. Grafana Tempo 설치 및 확인
Grafana Tempo 모니터링
watch kubectl get pod,pv,pvc -n tracing
Bash
복사
# [모니터링1] tracing 네임스페이스 - pod, pv, pvc 모니터링
Tempo용 S3 Bucket 생성
cd ~/irsa
Bash
복사
# irsa 경로 이동
aws s3api create-bucket \
--bucket tempo-${NICKNAME} \
--region $AWS_DEFAULT_REGION \
--create-bucket-configuration LocationConstraint=$AWS_DEFAULT_REGION
aws s3 ls
Bash
복사
# tempo용 s3 bucket 생성
export TEMPO_BUCKET_NAME="tempo-${NICKNAME}"
echo "export TEMPO_BUCKET_NAME=$TEMPO_BUCKET_NAME" >> /etc/profile; echo $TEMPO_BUCKET_NAME
Bash
복사
# s3 bucket 이름 변수 저장
Tempo - S3 IAM Policy 생성
cat >grafana-tempo-s3-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TempoStorage",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::${TEMPO_BUCKET_NAME}",
"arn:aws:s3:::${TEMPO_BUCKET_NAME}/*"
]
}
]
}
EOF
cat grafana-tempo-s3-policy.json
Bash
복사
# grafana-tempo-s3-poilcy.json 파일 생성
aws iam create-policy \
--policy-name aws-tempo-s3 \
--policy-document file://grafana-tempo-s3-policy.json
Bash
복사
# aws-tempo-s3 IAM Policy 생성
Tempo - S3 IAM Role 생성
cat >trust-rs-tempo.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${OIDC_ARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_URL}:sub": "system:serviceaccount:tracing:tempo",
"${OIDC_URL}:aud": "sts.amazonaws.com"
}
}
}
]
}
EOF
cat trust-rs-tempo.json
Bash
복사
# Tempo IAM Role Trust rs 생성
aws iam create-role \
--role-name AWS-Tempo-Role \
--assume-role-policy-document file://trust-rs-tempo.json
Bash
복사
# AWS-Tempo-Role 생성
aws iam attach-role-policy \
--role-name AWS-Tempo-Role \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-tempo-s3
Bash
복사
# IAM Policy와 IAM Role 연결
export TEMPO_ROLE_ARN=arn:aws:iam::${ACCOUNT_ID}:role/AWS-Tempo-Role
echo "export TEMPO_ROLE_ARN=$TEMPO_ROLE_ARN" >> /etc/profile; echo $TEMPO_ROLE_ARN
Bash
복사
# Tempo IAM Role ARN 변수 선언
IAM Policy와 Role 확인
aws iam list-policies \
--query 'Policies[?contains(PolicyName, `mimir`) || contains(PolicyName, `loki`) || contains(PolicyName, `tempo`)].PolicyName' \
--output text
Bash
복사
# Mimir, Loki, Tempo - S3 IAM Policy 확인
aws iam list-roles \
--query 'Roles[?contains(RoleName, `Mimir`) || contains(RoleName, `Loki`) || contains(RoleName, `Tempo`)].RoleName' \
--output text
Bash
복사
# Mimir, Loki, Tempo - S3 IAM Role 확인
Tempo 설치
export | grep TEMPO
Bash
복사
# TEMPO 변수 출력
cd ~/values; envsubst < tempo-temp-values.yaml > tempo-values.yaml
cat tempo-values.yaml | yh
Bash
복사
# tempo-values.yaml 파일 확인
helm install tempo grafana/tempo-distributed \
-n tracing \
-f tempo-values.yaml \
--version 1.15.2
Bash
복사
# tempo-values 파일을 활용해서 tempo를 helm chart로 설치
Observability Backend 설치 확인
for ns in monitoring logging tracing; do helm list -n $ns; done
Bash
복사
# helm chart로 설치한 Obervability Backend 시스템 확인
3. OpenTelemetry Operator & Collector 설치
OpenTelemetry Operator를 통해 OpenTelemetry CRD를 생성해서 OTel Collector, OTel Auto-Instrumentation을 설치할 수 있습니다.
3.1. OpenTelemetry Operator 설치
cert-manager 설치 및 확인
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update
Bash
복사
# helm repo 추가
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version 1.15.1 \
--set crds.enabled=true
Bash
복사
# cert-manager 설치
kubectl get pod -n cert-manager
Bash
복사
# cert-manager 생성 확인
kubectl get crd | grep cert-manager
Bash
복사
# cert-manager crd 확인
OpenTelemetry Operator 설치 및 확인
watch kubectl get all -n otel
Bash
복사
# [모니터링1] otel 네임스페이스
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
Bash
복사
# helm repo 추가
helm install opentelemetry-operator open-telemetry/opentelemetry-operator \
--version 0.82.0 \
--namespace otel \
--create-namespace \
--set "manager.collectorImage.repository=otel/opentelemetry-collector-k8s"
Bash
복사
# otel-operator 설치
kubectl get crd | grep open
Bash
복사
# otel-operator crd 설치 확인
3.2. OpenTelemetry Collector 생성
OpenTelemetry Collector 생성
cd ~/values; cat otelcol-values.yaml | yh
Bash
복사
# otelcol-values.yaml 확인
helm install opentelemetry open-telemetry/opentelemetry-collector \
-n otel \
-f otelcol-values.yaml \
--version 0.81.0
Bash
복사
# Otel Collector 설치
4. Observability Visualization 설치
Observability Visualization 도구로 Grafana를 설치하고 결과를 확인합니다.
4.1. Grafana 설치
Grafana 모니터링
watch kubectl get pod,svc,ep,ingress,pv,pvc -n grafana
Bash
복사
# [모니터링1] grafana 네임스페이스 - pod, svc, ep, ingress, pv, pvc 모니터링
while true; do aws ec2 describe-volumes \
--filters Name=tag:ebs.csi.aws.com/cluster,Values=true \
--query "Volumes[].{VolumeId: VolumeId, VolumeType: VolumeType, InstanceId: Attachments[0].InstanceId, State: Attachments[0].State}" \
--output text; date; sleep 1; done
Bash
복사
# [모니터링2] 동적 프로비저닝으로 생성되는 EBS 볼륨 확인
Grafana 설치
export MyDomain=[각자 도메인 네임]
echo "export MyDomain=$MyDomain" >> /etc/profile; echo $MyDomain
Bash
복사
# MyDomain 변수 선언
cd ~/values; envsubst < grafana-temp-values.yaml > grafana-values.yaml
cat grafana-values.yaml | yh
Bash
복사
# grafana-values.yaml 확인
helm install grafana grafana/grafana \
-n grafana \
-f grafana-values.yaml \
--version 8.3.6
Bash
복사
# grafana-values 파일을 활용해서 grafana를 helm chart로 설치
while true; do \
aws elbv2 describe-load-balancers \
--query 'LoadBalancers[*].[LoadBalancerName,State.Code]' \
--output table; \
done
Bash
복사
# elb 생성 확인 (Ctrl + Z로 중지)
Note:
https://grafana.${MyDomain}/grafana로 접속합니다. (id: admin, pw: qwer1234)
5. LGTM Observability 검증
5.1. [Metrics] Grafana Mimir 확인
Grafana Data Source 설정
Data Source 지정 [Connections → Data Sources → Add data source → Prometheus]
•
Name: Mimir
•
Connection - Prometheus server URL
http://mimir-nginx.monitoring/prometheus
Bash
복사
•
Save & Test
이미지 빌드
Test Pod 생성
cd; cat >test-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: python-metric-test
labels:
app: python-metric
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '5000'
spec:
containers:
- name: python-app
image: ongja/my-flask-app:latest
ports:
- containerPort: 5000
EOF
Bash
복사
# test-pod.yaml 생성
kubectl apply -f test-pod.yaml
Bash
복사
# test pod 배포
kubectl exec -it python-metric-test \
-- /bin/sh -c "apt-get update && apt-get install -y stress && stress --cpu 4 --timeout 300"
Bash
복사
# test pod에 cpu 부하
Grafana에서 Mimir 정보 확인
Grafana 웹 페이지에서 Explorer 메뉴로 진입합니다.
•
Outline: Mimir
•
Builder → Code
•
Last 15 minutes
•
Run Query
container_cpu_usage_seconds_total{pod="python-metric-test"}
Bash
복사
# [Query] 대상 파드의 누적 CPU 사용
(sum(rate(container_cpu_usage_seconds_total{namespace="default", pod="python-metric-test"}[5m])) / sum(rate(container_cpu_usage_seconds_total[5m]))) * 100
Bash
복사
# [Query] 대상 파드의 CPU 사용량이 전체 CPU에 차지하는 비율
5.2. [Logs] Grafana Loki 확인
Grafana Data Source 설정
Data Source 지정 [Connections → Data Sources → Add data source → Loki]
•
Name: Loki
•
Connection - Loki server URL
http://loki-loki-distributed-gateway.logging
Bash
복사
•
Save & Test
Grafana에서 Loki 정보 확인
Grafana 웹 페이지에서 Explorer 메뉴로 진입합니다.
•
Outline: Loki
•
Builder → Code
•
Last 5 minutes
•
Run Query
{k8s_pod_name="python-metric-test"}
Bash
복사
# [Query] 대상 파드의 모든 로그 정보 확인
파드 로그 정보 확인
cat ~/values/otelcol-values.yaml | grep -A 1 "filelog:"
Bash
복사
# otel collector 설정 정보 필터링
for node in $PublicN1 $PublicN2 $PublicN3; do
ssh -i ~/.ssh/kp_node.pem ec2-user@$node "sudo sh -c 'ls /var/log/pods/default*/python-app/'"
done
Bash
복사
# 노드에 구성된 파드의 로그 파일 확인
for node in $PublicN1 $PublicN2 $PublicN3; do
ssh -i ~/.ssh/kp_node.pem ec2-user@$node "sudo sh -c 'cat /var/log/pods/default*/python-app/0.log'"
done
Bash
복사
# 노드에 구성된 파드의 로그 파일 내용 확인
5.3. [Traces] Grafana Tempo 확인
Grafana Data Source 설정
Data Source 지정 [Connections → Data Sources → Add data source → Tempo]
•
Name: Tempo
•
Connection - Tempo server URL
http://tempo-query-frontend-discovery.tracing:3100
Bash
복사
•
Save & Test
1.
수동 계측
이미지 빌드
Trace 수동 계측
cat << EOF > 1_deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-app
spec:
replicas: 1
selector:
matchLabels:
app: python-app
template:
metadata:
labels:
app: python-app
spec:
containers:
- name: python-app
image: ongja/inst-1:latest
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: python-app-service
spec:
selector:
app: python-app
ports:
- protocol: TCP
port: 80
targetPort: 5000
EOF
Bash
복사
# 1_deploy.yaml 생성
kubectl apply -f 1_deploy.yaml
kubectl get pod,svc
Bash
복사
# 배포 및 확인
kubectl run curl \
--image=appropriate/curl \
--restart=Never \
--rm -it -- sh
Bash
복사
# 테스트 파드에 접근해서 확인
curl http://python-app-service.default.svc.cluster.local
Bash
복사
2.
프로그래밍 계측
이미지 빌드
Trace 프로그래밍 계측
cat << EOF > app-1.yaml
apiVersion: v1
kind: Service
metadata:
name: app-1
spec:
selector:
app: app-1
ports:
- protocol: TCP
port: 80
targetPort: 5000
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-1
spec:
replicas: 1
selector:
matchLabels:
app: app-1
template:
metadata:
labels:
app: app-1
spec:
containers:
- name: app-1
image: ongja/tempo-app-1:latest
command: ["/bin/sh"]
args:
- "-c"
- |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://tempo-distributor-discovery.tracing:4318/v1/traces opentelemetry-instrument python app-1.py
ports:
- containerPort: 5000
name: http
env:
- name: SERVICE_B_HOST
value: "app-2"
- name: SERVICE_B_PORT
value: "80"
- name: PORT
value: "5000"
- name: OTEL_SERVICE_NAME
value: "app-1"
- name: OTEL_TRACES_EXPORTER
value: "console,otlp"
- name: OTEL_EXPORTER_OTLP_TRACES_HEADERS
value: "api-key=key,other-config-value=value"
- name: OTEL_TRACES_SAMPLER_ARG
value: "1"
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: "http/protobuf"
- name: OTEL_METRICS_EXPORTER
value: "none"
EOF
Bash
복사
# app-1.yaml 생성
cat << EOF > app-2.yaml
apiVersion: v1
kind: Service
metadata:
name: app-2
spec:
selector:
app: app-2
ports:
- protocol: TCP
port: 80
targetPort: 5001
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-2
spec:
replicas: 1
selector:
matchLabels:
app: app-2
template:
metadata:
labels:
app: app-2
spec:
containers:
- name: app-2
image: ongja/tempo-app-2:latest
command: ["/bin/sh"]
args:
- "-c"
- |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://tempo-distributor-discovery.tracing:4318/v1/traces opentelemetry-instrument python app-2.py
ports:
- containerPort: 5001
name: http
env:
- name: PORT
value: "5001"
- name: SERVICE_C_HOST
value: "app-3"
- name: SERVICE_C_PORT
value: "80"
- name: OTEL_SERVICE_NAME
value: "app-2"
- name: OTEL_TRACES_SAMPLER_ARG
value: "100"
- name: OTEL_TRACES_EXPORTER
value: "console,otlp"
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: "http/protobuf"
- name: OTEL_METRICS_EXPORTER
value: "none"
EOF
Bash
복사
# app-2.yaml 생성
cat << EOF > app-3.yaml
apiVersion: v1
kind: Service
metadata:
name: app-3
spec:
selector:
app: app-3
ports:
- protocol: TCP
port: 80
targetPort: 5002
name: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-3
spec:
replicas: 1
selector:
matchLabels:
app: app-3
template:
metadata:
labels:
app: app-3
spec:
containers:
- name: app-3
image: ongja/tempo-app-3:latest
command: ["/bin/sh"]
args:
- "-c"
- |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://tempo-distributor-discovery.tracing:4318/v1/traces opentelemetry-instrument python app-3.py
ports:
- containerPort: 5002
name: http
env:
- name: PORT
value: "5002"
- name: OTEL_SERVICE_NAME
value: "app-3"
- name: OTEL_EXPORTER_OTLP_TRACES_HEADERS
value: "api-key=key,other-config-value=value"
- name: OTEL_TRACES_SAMPLER_ARG
value: "100"
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: "http/protobuf"
- name: OTEL_METRICS_EXPORTER
value: "none"
- name: OTEL_TRACES_EXPORTER
value: "console,otlp"
EOF
Bash
복사
# app-3.yaml 생성
kubectl create ns tempo-test
kubectl apply -f app-1.yaml -n tempo-test
kubectl apply -f app-2.yaml -n tempo-test
kubectl apply -f app-3.yaml -n tempo-test
kubectl get pod,svc -n tempo-test
Bash
복사
# 배포 및 확인
kubectl run -n tempo-test curl \
--image=appropriate/curl \
--restart=Never \
--rm -it -- sh
Bash
복사
# 테스트 파드에 접근해서 확인
curl http://app-1
Bash
복사
curl http://app-1/error
Bash
복사
curl http://app-2
Bash
복사
curl http://app-2/error
Bash
복사
curl http://app-3
Bash
복사
curl http://app-3/error
Bash
복사
3.
자동 계측
Trace 자동 계측 - auto-instrumentation 생성
cat >auto-instrumentation.yaml <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: otel-instrumentation
spec:
exporter:
endpoint: http://opentelemetry-opentelemetry-collector.otel.svc.cluster.local:4317
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "1"
nodejs:
env:
- name: OTEL_EXPORTER_OTLP_TRACES_PROTOCOL
value: "grpc"
- name: OTEL_EXPORTER_OTLP_METRICS_PROTOCOL
value: "grpc"
- name: OTEL_NODE_DISABLED_INSTRUMENTATIONS
value: "fs"
EOF
Bash
복사
# auto-instrumentation.yaml 생성
kubectl apply -f auto-instrumentation.yaml
kubectl get instrumentations.opentelemetry.io
Bash
복사
# auto-instrumentation 배포 및 확인
Trace 자동 계측 - java 환경 테스트
cat >spring-java.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-app
spec:
selector:
matchLabels:
app: java-app
replicas: 1
template:
metadata:
labels:
app: java-app
annotations:
sidecar.opentelemetry.io/inject: "true"
instrumentation.opentelemetry.io/inject-java: "true"
spec:
containers:
- name: app
image: springio/gs-spring-boot-docker
---
apiVersion: v1
kind: Service
metadata:
name: java-app-service
spec:
type: NodePort
selector:
app: java-app
ports:
- protocol: TCP
port: 8080
targetPort: 8080
EOF
Bash
복사
# spring-java.yaml 생성
kubectl apply -f spring-java.yaml
Bash
복사
# spring-java.yaml 배포
kubectl run curl \
--image=appropriate/curl \
--restart=Never \
--rm -it -- sh
Bash
복사
# 테스트 파드에 접근해서 확인
curl http://java-app-service:8080
Bash
복사
Trace 자동 계측 - nodejs 환경 테스트
cat >nodejs-test.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodejs-express
spec:
replicas: 1
selector:
matchLabels:
app: nodejs-express
template:
metadata:
labels:
app: nodejs-express
annotations:
instrumentation.opentelemetry.io/inject-nodejs: "true"
spec:
containers:
- name: nodejs-express
image: bitnami/node:14
command: ["sh", "-c"]
args: ["npm install express && node -e \"const express = require('express'); const app = express(); app.get('/', (req, res) => res.send('Hello World!')); app.listen(8080);\""]
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: nodejs-express-service
spec:
type: NodePort
selector:
app: nodejs-express
ports:
- protocol: TCP
port: 80
targetPort: 8080
EOF
Bash
복사
# nodejs-test.yaml 생성
kubectl apply -f nodejs-test.yaml
Bash
복사
# nodejs-test.yaml 배포
kubectl run curl \
--image=appropriate/curl \
--restart=Never \
--rm -it -- sh
Bash
복사
# 테스트 파드에 접근해서 확인
curl http://nodejs-express-service
Bash
복사
6. 실습 환경 삭제
실습 환경 삭제와 Terraform 삭제 작업을 진행합니다.
6.1. 실습 자원 삭제
실습 애플리케이션 삭제
cd ~
kubectl delete -f nodejs-test.yaml
kubectl delete -f spring-java.yaml
kubectl delete -f 1_deploy.yaml
kubectl delete -f test-pod.yaml
kubectl delete -f app-1.yaml -n tempo-test
kubectl delete -f app-2.yaml -n tempo-test
kubectl delete -f app-3.yaml -n tempo-test
Bash
복사
# 실습 애플리케이션 삭제
helm과 pvc 삭제
helm uninstall grafana -n grafana
helm uninstall opentelemetry -n otel
helm uninstall opentelemetry-operator -n otel
helm uninstall cert-manager -n cert-manager
Bash
복사
# helm과 pvc 삭제
helm uninstall tempo -n tracing
kubectl delete pvc --all -n tracing
Bash
복사
helm uninstall loki -n logging
kubectl delete pvc --all -n logging
Bash
복사
helm uninstall mimir -n monitoring
kubectl delete pvc --all -n monitoring
Bash
복사
Observability Backend - S3 IAM Policy와 Role 삭제
aws iam detach-role-policy --role-name AWS-Loki-Role --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-loki-s3
aws iam detach-role-policy --role-name AWS-Mimir-Role --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-mimir-s3
aws iam detach-role-policy --role-name AWS-Tempo-Role --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-tempo-s3
aws iam delete-policy --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-loki-s3
aws iam delete-policy --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-mimir-s3
aws iam delete-policy --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/aws-tempo-s3
aws iam delete-role --role-name AWS-Loki-Role
aws iam delete-role --role-name AWS-Mimir-Role
aws iam delete-role --role-name AWS-Tempo-Role
Bash
복사
# IAM Policy와 Role 삭제
S3 Bucket 삭제
aws s3 rm s3://$MIMIR_BUCKET_NAME --recursive
aws s3 rm s3://$LOKI_BUCKET_NAME --recursive
aws s3 rm s3://$TEMPO_BUCKET_NAME --recursive
aws s3api delete-bucket --bucket $MIMIR_BUCKET_NAME --region $AWS_DEFAULT_REGION
aws s3api delete-bucket --bucket $LOKI_BUCKET_NAME --region $AWS_DEFAULT_REGION
aws s3api delete-bucket --bucket $TEMPO_BUCKET_NAME --region $AWS_DEFAULT_REGION
aws s3 ls
Bash
복사
# s3 bucket 삭제 및 확인
6.2. Terraform 삭제
Terraform 자원 삭제
nohup sh -c "terraform destroy -auto-approve" > delete.log 2>&1 &
Bash
복사
# terraform 자원 삭제
Warning:
nohup으로 백그라운드로 실행하도록 변경했습니다.
Terraform 삭제가 완료되면 정상적으로 자원 삭제 되었는지 확인을 합니다.(cat delete.log)
여기까지 3장의 첫 번째 실습인 “LGTM Observability Full Stack 구성하기” 실습을 마칩니다.
수고하셨습니다 :)