Search

ELK

ENV

export EKS_CLUSTER_NAME=<CLUSTER_NAME> export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) export AWS_REGION=ap-northeast-2 export ES_DOMAIN_NAME="skills-logging" export ES_VERSION="7.10" export ES_DOMAIN_USER="admin" export ES_DOMAIN_PASSWORD="$(openssl rand -base64 12)_Ek1$"
Shell
복사

OIDC

eksctl utils associate-iam-oidc-provider \ --cluster $EKS_CLUSTER_NAME \ --approve
Shell
복사

Install AWS LoadBalancer Controller

helm repo add eks https://aws.github.io/eks-charts helm repo update eks helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=$EKS_CLUSTER_NAME \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller
Shell
복사

Logstash Policy

cat << EOF > logstash-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "es:ESHttp*" ], "Resource": "arn:aws:es:${AWS_REGION}:${ACCOUNT_ID}:domain/${ES_DOMAIN_NAME}" } ] } EOF
Shell
복사

Create Policy

aws iam create-policy \ --policy-name logstash-policy \ --policy-document file://logstash-policy.json
Shell
복사

Create Namespace

kubectl create namespace logging
Shell
복사

IRSA

eksctl create iamserviceaccount \ --name logstash \ --namespace logging \ --cluster $EKS_CLUSTER_NAME \ --attach-policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/logstash-policy" \ --override-existing-serviceaccounts \ --approve
Shell
복사
kubectl -n logging describe serviceaccounts logstash
Shell
복사

es_domain.json

cat << EOF > es_domain.json { "DomainName": "${ES_DOMAIN_NAME}", "ElasticsearchVersion": "${ES_VERSION}", "ElasticsearchClusterConfig": { "InstanceType": "r5.large.elasticsearch", "InstanceCount": 1, "DedicatedMasterEnabled": false, "ZoneAwarenessEnabled": false, "WarmEnabled": false }, "EBSOptions": { "EBSEnabled": true, "VolumeType": "gp2", "VolumeSize": 100 }, "AccessPolicies": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"es:ESHttp*\",\"Resource\":\"arn:aws:es:${AWS_REGION}:${ACCOUNT_ID}:domain/${ES_DOMAIN_NAME}/*\"}]}", "SnapshotOptions": {}, "CognitoOptions": { "Enabled": false }, "EncryptionAtRestOptions": { "Enabled": true }, "NodeToNodeEncryptionOptions": { "Enabled": true }, "DomainEndpointOptions": { "EnforceHTTPS": true, "TLSSecurityPolicy": "Policy-Min-TLS-1-0-2019-07" }, "AdvancedSecurityOptions": { "Enabled": true, "InternalUserDatabaseEnabled": true, "MasterUserOptions": { "MasterUserName": "${ES_DOMAIN_USER}", "MasterUserPassword": "${ES_DOMAIN_PASSWORD}" } } } EOF
Shell
복사

Create ElasticSearch Domain

15분 정도 소요됨
aws es create-elasticsearch-domain \ --cli-input-json file://es_domain.json
Shell
복사

Get Logstash Role & ElasticSearch Endpoint

export LOGSTASH_ROLE=$(eksctl get iamserviceaccount --cluster $EKS_CLUSTER_NAME --namespace logging -o json | jq '.[].status.roleARN' -r) export ES_ENDPOINT=$(aws es describe-elasticsearch-domain --domain-name ${ES_DOMAIN_NAME} --output text --query "DomainStatus.Endpoint")
Shell
복사

Add Role for Elasticsearch Open Distro

curl -sS -u "${ES_DOMAIN_USER}:${ES_DOMAIN_PASSWORD}" \ -X PATCH \ https://${ES_ENDPOINT}/_opendistro/_security/api/rolesmapping/all_access?pretty \ -H 'Content-Type: application/json' \ -d' [ { "op": "add", "path": "/backend_roles", "value": ["'${LOGSTASH_ROLE}'"] } ] '
Shell
복사

Update Security Group Ingress & Egress (5000, 5044Port)

EKS_NODE_GROUP_SG_ID=$(aws ec2 describe-instances --filter Name=tag:Name,Values=skills-app-node --query "Reservations[1].Instances[].SecurityGroups[].GroupId" --output text) aws ec2 authorize-security-group-ingress --group-id $EKS_NODE_GROUP_SG_ID --protocol tcp --port 5044 --source-group $EKS_NODE_GROUP_SG_ID aws ec2 authorize-security-group-ingress --group-id $EKS_NODE_GROUP_SG_ID --protocol tcp --port 5000 --source-group $EKS_NODE_GROUP_SG_ID aws ec2 authorize-security-group-egress --group-id $EKS_NODE_GROUP_SG_ID --protocol tcp --port 5044 --source-group $EKS_NODE_GROUP_SG_ID aws ec2 authorize-security-group-egress --group-id $EKS_NODE_GROUP_SG_ID --protocol tcp --port 5000 --source-group $EKS_NODE_GROUP_SG_ID
Shell
복사

Create Logstash ConfigMap

cat << EOF > logstash-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: logstash-config namespace: logging data: logstash.yml: | http.host: "0.0.0.0" path.config: /usr/share/logstash/pipeline logstash.conf: | input { beats { port => 5044 } } filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } date { match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ] } } output { elasticsearch { hosts => ["https://${ES_ENDPOINT}:443"] ssl => true user => "${ES_DOMAIN_USER}" password => "${ES_DOMAIN_PASSWORD}" index => "logstash-%{+YYYY.MM.dd}" ilm_enabled => false } } EOF
Shell
복사
kubectl apply -f logstash-config.yaml
Shell
복사

Create Logstash Deployment

cat << EOF > logstash-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: logstash namespace: logging spec: replicas: 1 selector: matchLabels: app: logstash template: metadata: labels: app: logstash spec: serviceAccountName: logstash containers: - name: logstash image: docker.elastic.co/logstash/logstash:7.10.2 ports: - containerPort: 5044 volumeMounts: - name: config-volume mountPath: /usr/share/logstash/config - name: pipeline-volume mountPath: /usr/share/logstash/pipeline volumes: - name: config-volume configMap: name: logstash-config items: - key: logstash.yml path: logstash.yml - name: pipeline-volume configMap: name: logstash-config items: - key: logstash.conf path: logstash.conf --- apiVersion: v1 kind: Service metadata: name: logstash namespace: logging spec: type: ClusterIP ports: - port: 5044 targetPort: 5044 protocol: TCP selector: app: logstash EOF
Shell
복사
kubectl apply -f logstash-deployment.yaml
Shell
복사

Get Pod

kubectl -n logging get pods -o wide
Shell
복사

demo-app.yaml

cat << EOF > demo-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: demo-app namespace: logging spec: replicas: 1 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: demo-app image: nginx:latest ports: - containerPort: 80 volumeMounts: - name: nginx-logs mountPath: /var/log/nginx - name: filebeat image: docker.elastic.co/beats/filebeat:7.10.2 volumeMounts: - name: nginx-logs mountPath: /var/log/nginx - name: filebeat-config mountPath: /usr/share/filebeat/filebeat.yml subPath: filebeat.yml volumes: - name: nginx-logs emptyDir: {} - name: filebeat-config configMap: name: filebeat-config items: - key: filebeat.yml path: filebeat.yml --- apiVersion: v1 kind: Service metadata: name: demo-app namespace: logging spec: type: LoadBalancer ports: - port: 80 targetPort: 80 selector: app: demo-app --- EOF
Shell
복사
kubectl apply -f demo-app.yaml
Shell
복사

filebeat-config.yaml

cat << EOF > filebeat-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: filebeat-config namespace: logging data: filebeat.yml: | filebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log fields: app: demo-app type: nginx-access fields_under_root: true - type: log enabled: true paths: - /var/log/nginx/error.log fields: app: demo-app type: nginx-error fields_under_root: true output.logstash: hosts: ["logstash.logging.svc.cluster.local:5044"] logging.json: true logging.metrics.enabled: false --- EOF
Shell
복사
kubectl apply -f filebeat-config.yaml
Shell
복사

nginx-config.yaml

cat << EOF > nginx-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: logging data: nginx.conf: | user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } location /error { return 500; } } } EOF
Shell
복사
kubectl apply -f nginx-config.yaml
Shell
복사

Response Test

# 서비스 IP 확인 export SERVICE_IP=$(kubectl -n logging get svc demo-app -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') # 일반 접속 로그 생성 curl http://$SERVICE_IP/ # 에러 로그 생성 curl http://$SERVICE_IP/error
Shell
복사

Get URL & User & Password

echo "Kibana URL: https://${ES_ENDPOINT}/_plugin/kibana/" echo "Kibana user: ${ES_DOMAIN_USER}" echo "Kibana password: ${ES_DOMAIN_PASSWORD}"
Shell
복사
UI