2022년 1월 7일 금요일

[ Python ] ModuleNotFoundError: No module named

pip install로 해당 package를 다운 받았지만 

ModuleNotFoundError 에러가 나올 때


설치한 패키지의 directory가 python실행시 포함되는지 확인

$ cat test.py
import sys
print(sys.path)

$ python test.py
['', '/usr/lib/python3.6', '/usr/lib/python3.6/plat-x86_64-linux-gnu', ...'/usr/lib/python3.6/dist-packages']


python shell에서도 확인

$ python
>>> import sys
>>> print(sys.path)
>>> ['', '/usr/lib/python3.6', '/usr/lib/python3.6/plat-x86_64-linux-gnu...


두 값을 비교하여 설치한 모듈의 directory가

포함되지 않는다면 실행할 py파일에 해당 코드 추가

sys.path.append("path")


[ Ansible ] Roles을 이용한 Playbook


[ roles init ]

roles directory 생성

$ mkdir roles
$ cd rolse

$ ansible-galaxy init common
$ tree common ├── README.md ├── defaults │   └── main.yml ├── files ├── handlers │   └── main.yml ├── meta │   └── main.yml ├── tasks │   └── main.yml ├── templates ├── tests │   ├── inventory │   └── test.yml └── vars     └── main.yml



[ roles/common/vars/main.yml ]

미리 변수를 정의하여 tasks에서 사용

name: my-host



[ roles/common/templates/host.my-host.j2 ]

tasks에서 사용할 template정의

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.1.10 main_server
192.168.1.11 storage_server



[ roles/common/tasks/main.yml ]

실제 동작하는 tasks 작성

- name: Install packages
  yum:
    name:
      - wget
      - unzip
  become: true

- name: modify hosts
  template:
    src: ../templates/hosts.{{name}}.j2
    dest: /etc/hosts
    owner: root
    group: root

 


[ common.yml ]

최초 실행 playbook 

- hosts: '{{ target }}'
  roles:
    - common


[ playbook 실행 ]

$ ansible-playbook common.yml --extra-vars "target=my-host" --user=my









[ Prometheus ] Jmx exporter Hadoop설정

[ prerequisite ]

  • hadoop설치 
  • hadoop_env.sh에 jmx port 설정
jmx설정 예시

export HADOOP_DATANODE_OPTS="-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.port=19004 
$HADOOP_DATANODE_OPTS"


jmx데이터를 바로 prometheus가 읽을 수 없으니 

jmx_exporter를 통해 jmx->metric으로 변환시켜야 한다.


[ jmx_export설치 ]

wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.16.1/jmx_prometheus_javaagent-0.16.1.jar

참조 : https://github.com/prometheus/jmx_exporter



[ hadoop-env.sh ]

각 옵션마다 jar파일을 실행하게 설정 값을 변경

예시 : -javaagent:<jmx exporter jar file path>=<port>:<configure file path>

# Name node jmx export 설정
export HDFS_NAMENODE_OPTS="
...
-javaagent:/path/jmx_prometheus_javaagent-0.16.1.jar=5566:/path/config.yml
$HDFS_NAMENODE_OPTS"

# Data node jmx export 설정
export HDFS_DATANODE_OPTS="
...
-javaagent:/path/jmx_prometheus_javaagent-0.16.1.jar=5577:/path/config.yml
$HDFS_DATANODE_OPTS"


configure file 참조: https://github.com/prometheus/jmx_exporter

---
startDelaySeconds: 0
hostPort: 127.0.0.1:1234
username: 
password: 
jmxUrl: service:jmx:rmi:///jndi/rmi://127.0.0.1:1234/jmxrmi
ssl: false
lowercaseOutputName: false
lowercaseOutputLabelNames: false
whitelistObjectNames: ["org.apache.cassandra.metrics:*"]
blacklistObjectNames: ["org.apache.cassandra.metrics:type=ColumnFamily,*"]
rules:
  - pattern: 'org.apache.cassandra.metrics<type=(\w+), name=(\w+)><>Value: (\d+)'
    name: cassandra_$1_$2
    value: $3
    valueFactor: 0.001
    labels: {}
    help: "Cassandra metric $1 $2"
    cache: false
    type: GAUGE
    attrNameSnakeCase: false



[ web에서 확인 ]

http://YourHostIp:5566



[ prometheus.yml ]

jmx exporter데이터를 http로 받을 수 있으니 prometheus가 가져올 수 있게 설정

scrape_configs:
  - job_name: "namenode"
    static_configs:
      - targets: ["namenode-ip:5566"]

  - job_name: "datanode"
    static_configs:
      - targets: ["datanode-ip:5577"]


[ prometheus web에서 확인 ]

프로메테우스 재시작 후 -> http:prometheus_host:9090 -> target메뉴 에서 

수집데이터 확인



참조 :

https://www.fatalerrors.org/a/hdfs-yarn-on-promethues-grafana-monitoring-promethues-data-source-configuration.html

https://programming.vip/docs/how-to-use-jmx_-exporter-prometheus-grafana-monitor-hadoop-cluster.html


2022년 1월 4일 화요일

[ Shell script ] 쉘 스크립트 짤 때 많이 쓰는 명령어 5가지

 

shell script 짤 때 자주 쓰는 리눅스 명령어 5가지

  • 1. 문자열을 찾을 수 있는 grep
  • 2. 파일을 찾을 수 있는 find
  • 3. 특정 문자열을 출력할 수 있는 awk
  • 4. 문자열을 바꾸는 sed
  • 5. 날짜와 시간 관련 date

1. Grep
grep [옵션] 패턴 파일

grep 'for' ./ShellScript/for.sh
    for num in 1 2 3

#-i:대소문자 무시
grep 'for' -i ./ShellScript/for.sh

#-e: 여러 개의 패턴을 사용할 경우 (or)
grep -e 'for' -e'file' ./ShellScript/for.sh
    for num in 1 2 3     for file in $HOME/*

#-f: 파일과 함께 사용 할 경우, pt.txt는 패턴이 저장되어 있음
grep -f pt.txt ./ShellScript/for.sh

#-w: 해당 라인만 결과를 출력 / -o: 해당 단어만 출력
grep -w 'for' ./ShellScript/for.sh

#-c: 검색한 패턴의 단어 갯수
grep -c 'for' ./ShellScript/for.sh     5

#-l: 패턴이 포함된 파일 목록 조회
grep -l 'for' ./ShellScript/*     ./ShellScript/arr_ex.sh     ./ShellScript/for.sh

#-H: 파일명을 앞 라인에 보여줌 / -h: 파일명을 보여주지 않음
grep -H 'file' ./ShellScript/for.sh     ./ShellScript/for.sh:for file in $HOME/*     ./ShellScript/for.sh: echo $file

#-n: 패턴이 포함된 라인 번호
grep -n 'file' ./ShellScript/for.sh     8:for file in $HOME/*     10: echo $file

#-A: 설정한 라인 수 만큼 라인 아래 출력 / -B: 설정한 라인 수 만큼 라인 위 출력 / -C: A+B
done for file in $HOME/* do echo $file


#-r: 하위 디렉토리까지 검색 / -R: 심볼릭 링크까지
grep -r 'print "$hey"' ./*

#표현식 패턴
grep "^/[[[:alnum:]]*\]" ./ShellScript/for.sh

2. Find
find [옵션] [대상 경로] [표현식]

find /etc -name chrony.conf
    /etc/chrony.conf

#-L: 심폴링 링크까지 검색 / -perm: 파일권한 검색
find -L /etc/ -perm 644 -name 'rc.*'

#-group: 그룹소유권으로 검색
find ./ -group root

#-type: 파일타입으로 검색(d:디렉토리 / f:파일)
find ./ -type d -name 'p*'

#-a: and연산자 / -o: or연산자
find ./ -size 65k -o -name 'r*'

#-fprint: 검색결과를 파일로 저장
find ./ -name 'p*' -fprint p-file.txt

3. Awk
awk [옵션] '패턴' 대상파일

#그대로 내용 출력
awk '{ print }' file-list.txt

# 1번째 4번째 컬럼만 출력
awk '{ print $1, $4 }' file-list.txt

# 포맷적용
awk '{ printf "%-5s %s\n", $3, $5 }' file-list.txt

4. Sed
sed [옵션] '명령어' 대상파일

#file-list의 root를 centos로 바꾸어서 출력 (저장x)
sed 's/root/centos/' ./file-list.txt | grep centos

#-i : 바꾼 문자를 적용한 file-list.txt.bak이란 파일을 생성
sed -i.bak 's/root/centos/' ./file-list.txt | grep root

5. Date
date [옵션] 

#현재 시간을 기준으로 어제 날짜
date -d yesterday

#현재 시간을 기준으로 다양한 표현
date -d "+10 day"
date -d "-3 week"
date -d "5 years ago"

#date 포맷
date "+%Y-%m-%d %l:%M: %p"
    2022-01-04  9:16 AM




2022년 1월 3일 월요일

[ Prometheus ] 프로메테우스 설치

 [ 아키텍처 ] 

  • 시계열 데이터를 스크래핑하고 저장하는 프로메테우스 메인 서버
  • 응용 프로그램 코드 계측을 위한 클라이언트 라이브러리
  • Short-lived Job 지원을 위한 게이트웨이
  • HAProxy, StatsD, Graphite 등과 같은 서비스를 Exporter.
  • Alter Manager
  • 다양한 지원 도구




[ 설치 ]

Download

$ wget https://github.com/prometheus/prometheus/releases/download/v2.32.1/prometheus-2.32.1.linux-amd64.tar.gz
$ tar -xvf prometheus-2.32.1.linux-amd64.tar.gz

설정파일 : prometheus.yml 

global:
  # 얼마나 자주 scrap할 건지
  scrape_interval:     15s
  # 얼마나 자주 rules을 적용할건지
  evaluation_interval: 15s

rule_files:
  # - "first.rules"
  # - "second.rules"

# Http endpoint로 데이터 노출 http://localhost:9090
# Metrics 수집시 http://localhost:9090/metrics
scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ['localhost:9090']

설정 옵션 : https://prometheus.io/docs/prometheus/latest/configuration/configuration/



실행 command

./prometheus --config.file=prometheus.yml


systemd에 service등록

/etc/systemd/system/prometheus.service

[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target

[Service]
User=prometheus
Restart=on-failure
ExecStart=/home/prometheus/prometheus \
  --config.file=/home/prometheus/prometheus.yml \

[Install]
WantedBy=multi-user.target

실행 command2

systemctl start prometheus.service


Graph : localhost:9090/graph -> 검색창에 아래 매트릭스 이름 검색

promhttp_metric_handler_requests_total


Filtering code=200

promhttp_metric_handler_requests_total{code="200"}

count metric

count(promhttp_metric_handler_requests_total)

graph interval control

rate(promhttp_metric_handler_requests_total{code="200"}[10m])

sample job monitoring
- prometheus에서 설정한 job이름으로 검색

scrape_duration_seconds{job="prometheus", instance="localhost:9090"}


[ Elasticsearch ] index template


[ Index template ] 

보통 날짜별로 elasticsearch에 index를 생성하여 사용하는데

매번 데이터가 들어올 때 마다 mapping을 통해 field type을 지정하지 않기 위해

Index template를 사용한다.


생성 예시 

* 일별로 log-20220101, log-20220101 형식으로 인덱스 생성된다.

PUT _template/log_template
{

    "order": 0,
    "index_patterns": [
        "log-20*"
    ],
    "settings": {
        "index": {
            "number_of_shards": "1",
            "number_of_replicas": "1",
        }
    },
    "mappings": {
        "properties": {
            "user_id": {
                "type": "long"
            },
            "name": {
                "type": "text"
            },
            "sale": {
                "type": "long"
            },
            "sale_date": {
                "type": "date",
                "format": "yyyy-MM-dd"
            }
        }
    }
}


생성 template확인

GET _template/log_template


Field data types :

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

[ Elasticsearch ] Reindex


1. Temp index 생성

PUT users_temp


2. Temp index에 타입 Mapping

PUT users_temp/_mapping
{
  "properties": {
    "location": {
      "type": "geo_point"
    }
  }
}


3. Re-index를 Temp index에 실행
POST _reindex
{
  "source": {
    "index": "users"
  },
  "dest": {
    "index": "users_temp"
  }
}


4. User index 삭제
DELETE /users

5. 다시 User index 생성

PUT users

6. User index mapping

PUT users/_mapping
{
  "properties": {
    "location": {
      "type": "geo_point"
    }
  }
}


7. Re-index를 User index 실행

POST _reindex
{
  "source": {
    "index": "users_temp"
  },
  "dest": {
    "index": "users"
  }
}

 8. Temp index 삭제

DELETE /users_temp