미리 AWS 환경은 세팅해둔 상태! (external alb - web(ec2) - was(ec2))

직접 apache와 tomcat을 올려보기 위한 작업을 할 것이다...

 

왜 web - was 분리 구성을 하는가?

https://hwanchang.tistory.com/5


WEB 서버 구성(Apache)

  • Apache 설치 및 시작
yum install -y httpd
systemctl start httpd
  • alb 의 target group 상태검사 경로 변경 

  • index.html 생성
cd /var/www/html
vi index.html

# index.html
<html>
<body>WEB-A 서버입니다.</body>
</html>
  • health check: alb dns 주소를 통해 확인

  • health check: curl 명령어 활용

 

WAS 서버 구성(Tomcat)

  • java 다운로드 & tomcat 다운로드

https://www.oracle.com/java/technologies/downloads/

https://tomcat.apache.org/에서 다운로드

tar xvzf <파일명>
cp -R <디렉토리명> /usr/local/src
  • tomcat, jdk 경로 설정
vi /etc/profile

# 경로 확인
source /etc/profile
echo $JAVA_HOME
echo $CATALINA_HOME

  • tomcat 서비스 등록
cd /etc/init.d
vi tomcat

# tomcat file
#!/bin/bash
# Startup script for the Tomcat Server
# chkconfig : 345 50 50
# description: Tomcat is a Web application server.
# processname : java
# directory :
CATALINA_HOME=/usr/local/src/apache-tomcat-10.1.11
export JAVA_HOME=/usr/local/src/jdk-17.0.8
export CATALINA_HOME=/usr/local/src/apache-tomcat-10.1.11
case "$1" in
start)
echo "Starting tomcat: "
$CATALINA_HOME/bin/startup.sh
;;
stop)
echo "Shutting down tomcat: "
$CATALINA_HOME/bin/shutdown.sh
;;
restart)
echo "Restarting tomcat: "
$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh
;;
*)
echo "Usage: service tomcat"
start|stop|restart
exit 1
esac
exit 0

chmod 755 tomcat
service tomcat start

  • EC2 SG에 8080 포트 오픈
  • WAS 서버 index.html 생성
cd /usr/local/src/apache-tomcat-10.1.11/webapps/ROOT
vi index.html

# index.html
<html>
<body>WAS-A 서버입니다.</body>
</html>

 

WEB 서버 - WAS 서버 연동

  • WEB 서버 내부에 httpd.conf 파일 수정
vi /etc/httpd/conf/httpd.conf

###New Configuration
<VirtualHost *:80>
    ServerName <alb-dns주소>

    ProxyPass / http://<was-ip>:8080/
    ProxyPassReverse / http://<was-ip>:8080/
</VirtualHost>

systemctl restart httpd.service
  • WAS 서버
cd /usr/local/src/tomcat/bin
./shutdown.sh
./startup.sh
  • alb dns 접속 시 WAS 화면이 뜨면 성공 

 

 

참고: https://sweetysnail1011.tistory.com/57

 

❗java 다운받을 때 프로세서 확인 꼭 하기 uname -i 명령어 활용❗

'Computer Science > DevOps' 카테고리의 다른 글

[Jenkins] 다양한 플러그인 활용  (0) 2023.07.24
[Jenkins] Jenkins Pipeline 구축  (0) 2023.07.03
[Jenkins] Jenkins 다뤄보기  (0) 2023.06.27
[OS] OS 모음집  (0) 2021.08.12
[CI/CD] Tool  (0) 2021.08.11

Slack 연결

  • 목적: ChatOps
  • slack 채널 생성(무료플랜)

  • Jenkins Plugin 설치

slack notification 플러그인 설치

  • slack 앱 추가

Jenkins CI 추가

  • Jenkins에 slack 연결

자격 증명 추가(secret text로)
slack 자격증명 확인

  • 연결 확인

저장 후 빌드 시작
알림 확인

# Jenkinsfile

node {

  // job
  try {
    stage('build') {
      println('so far so good...')
    }
    stage('test') {
      println('A test has failed!')
      sh 'exit 1'
    }
  } catch(e) {
    // mark build as failed
    currentBuild.result = "FAILURE";

    // send slack notification
    slackSend (color: '#FF0000', message: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")

    // throw the error
    throw e;
  }
}

Sonarqube 연결

  • docker-compose 활용하여 Sonarqube 설치
mkdir jenkins 
cd jenkins
vi docker-compse.yml
  
# docker compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

docker-compse up -d
#docker-compose.yml
version: '2'
services:
  jenkins:
    image: jenkins-docker:latest
    ports:
      - "8080:8080"
      - "50000:50000"
    networks:
      - jenkins
    volumes:
      - /var/jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
  postgres:
    image: postgres:9.6
    networks:
      - jenkins
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonarpasswd
    volumes:
      - /var/postgres-data:/var/lib/postgresql/data
  sonarqube:
    image: sonarqube:lts
    ports:
      - "9000:9000"
      - "9092:9092"
    networks:
      - jenkins
    environment:
      SONARQUBE_JDBC_USERNAME: sonar
      SONARQUBE_JDBC_PASSWORD: sonarpasswd
      SONARQUBE_JDBC_URL: "jdbc:postgresql://postgres:5432/sonar"
    depends_on:
      - postgres

networks:
  jenkins:
  • 인스턴스 9000번 포트 열어주고 확인해보자 (소나큐브 설치 완료되었는지 확인)

  • Jenkins pipeline을 통해 Sonarqube 통합
  • Sonarqube Scanner for Jenkins 플러그인 설치
    • 이후 Jenkinsfile에 코드 넣어두면 된다! (sonar-scanner 부분)
node {
    def myGradleContainer = docker.image('gradle:jdk8-alpine')
    myGradleContainer.pull()

    stage('prep') {
        git url: 'https://github.com/wardviaene/gs-gradle.git'
    }

    stage('build') {
      myGradleContainer.inside("-v ${env.HOME}/.gradle:/home/gradle/.gradle") {
        sh 'cd complete && /opt/gradle/bin/gradle build'
      }
    }

    stage('sonar-scanner') {
      def sonarqubeScannerHome = tool name: 'sonar', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
      withCredentials([string(credentialsId: 'sonar', variable: 'sonarLogin')]) {
        sh "${sonarqubeScannerHome}/bin/sonar-scanner -e -Dsonar.host.url=http://sonarqube:9000 -Dsonar.login=${sonarLogin} -Dsonar.projectName=gs-gradle -Dsonar.projectVersion=${env.BUILD_NUMBER} -Dsonar.projectKey=GS -Dsonar.sources=complete/src/main/ -Dsonar.tests=complete/src/test/ -Dsonar.language=java -Dsonar.java.binaries=."
      }
    }
}

 

'Computer Science > DevOps' 카테고리의 다른 글

[AWS] WEB - WAS 구성 (Apache - Tomcat)  (0) 2023.07.27
[Jenkins] Jenkins Pipeline 구축  (0) 2023.07.03
[Jenkins] Jenkins 다뤄보기  (0) 2023.06.27
[OS] OS 모음집  (0) 2021.08.12
[CI/CD] Tool  (0) 2021.08.11

Jenkins 구축 관련해서 아래의 블로그를 참고!

https://realyun99.tistory.com/199


Jekins Pipeline

  • Jenkins를 사용하여 CD Pipeline 을 구현하고 통합하는 것을 지원하는 플러그인의 집합
  • Pipeline DSL 구문을 통해 코드로 전송 파이프라인을 모델링하기 위한 확장 가능한 자동화 서버를 갖추고 있음
  • Jenkinsfile 소스에 해당 내용을 넣고 경로를 보여주면 됨
  • Pipeline에 대한 자세한 내용은 해당 블로그를 참고하면 좋을 듯 싶다!

Jenkins Pipeline 프로젝트 생성

  • project configure

https://github.com/wardviaene/docker-demo 를 내 github으로 fork
해당 docker.build안 docker 주소 본인 환경에 맞게 변경

  • 지금 빌드 클릭

dockerhub 레포지토리에도 이미지 올라간 것을 볼 수 있음!


Docker Pipeline 프로젝트 생성

  • docker pipeline plugin 설치 후 프로젝트 생성

  • project configure

물론 해당 젠킨스 파일 또 잘 수정해야함...

  • 지금 빌드 클릭

dockerhub 에 올라옴!


위의 단계들을 진행하면서 제일 중요한건 Jenkinsfile안의 코드다! 두 프로젝트의 차이점도 Jenkinsfile 밖에 없다.

해당 파일들의 내용을 파헤쳐보자.

 

Jenkinsfile: Jenkins Pipeline ver

node {
   def commit_id
   stage('Preparation') {
     checkout scm
     sh "git rev-parse --short HEAD > .git/commit-id"                        
     commit_id = readFile('.git/commit-id').trim()
   }
   stage('test') {
     nodejs(nodeJSInstallationName: 'nodejs') {
       sh 'npm install --only=dev'
       sh 'npm test'
     }
   }
   stage('docker build/push') {
     docker.withRegistry('https://index.docker.io/v2/', 'dockerhub') {
       def app = docker.build("realyun99/docker-nodejs-demo:${commit_id}", '.').push()
     }
   }
}

Jenkinsfile.v2: Docker Pipeline ver

node {
   def commit_id
   stage('Preparation') {
     checkout scm
     sh "git rev-parse --short HEAD > .git/commit-id"
     commit_id = readFile('.git/commit-id').trim()
   }
   stage('test') {
     def myTestContainer = docker.image('node:16')
     myTestContainer.pull()
     myTestContainer.inside {
       sh 'npm install --only=dev'
       sh 'npm test'
     }
   }
   stage('test with a DB') {
     def mysql = docker.image('mysql').run("-e MYSQL_ALLOW_EMPTY_PASSWORD=yes") 
     def myTestContainer = docker.image('node:16')
     myTestContainer.pull()
     myTestContainer.inside("--link ${mysql.id}:mysql") { // using linking, mysql will be available at host: mysql, port: 3306
          sh 'npm install --only=dev' 
          sh 'npm test'                     
     }                                   
     mysql.stop()
   }                                     
   stage('docker build/push') {            
     docker.withRegistry('https://index.docker.io/v2/', 'dockerhub') {
       def app = docker.build("realyun99/docker-nodejs-demo:${commit_id}", '.').push()
     }                                     
   }                                       
}

 

  • test 단계에서 docker 이미지를 당겨와서 사용할 수 있다 → jenkins configure에서 따로 설정해줄 필요가 없다!
    • 즉 nodejs를 jenkins 컨테이너가 아닌 옆에 새 컨테이너를 생성하고 해당 커멘드들을 실행하게 된다.
    • 커멘드 실행이 끝나면 컨테이너는 폐기되고 다음 단계로 넘어간다.

 

 

❗ 원하는대로 컨테이너 생성해서 이미지 올리는 등의 코드를 작성하고 싶으면 Docker Pipeline이 유용할 듯 싶다? ❗

'Computer Science > DevOps' 카테고리의 다른 글

[AWS] WEB - WAS 구성 (Apache - Tomcat)  (0) 2023.07.27
[Jenkins] 다양한 플러그인 활용  (0) 2023.07.24
[Jenkins] Jenkins 다뤄보기  (0) 2023.06.27
[OS] OS 모음집  (0) 2021.08.12
[CI/CD] Tool  (0) 2021.08.11

Jenkins란

  • 모든 언어의 조합과 소스 코드 레포지토리에 대한 CI/CD 환경을 구축하기 위한 도구
    • 빌드: 서버에 올릴 수 있는 상태로 만드는 것
    • 배포: 서버에 올려 사용자가 사용할 수 있게 하는 것
  • 기능: 컴파일 오류 검출, 자동화 테스트 수행, 정적 코드 분석으로 인한 코딩 규약 준수 여부 체크, 성능 변화 감시 등..

 EC2에 Jenkins 설치

#!/bin/bash

# this script is only tested on ubuntu focal 20.04 (LTS)

# install docker
sudo apt-get update
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
systemctl enable docker
systemctl start docker
usermod -aG docker ubuntu

# run jenkins
mkdir -p /var/jenkins_home
chown -R 1000:1000 /var/jenkins_home/
docker run -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -d --name jenkins jenkins/jenkins:lts

# show endpoint
echo 'Jenkins installed'
echo 'You should now be able to access jenkins at: http://'$(curl -4 -s ifconfig.co)':8080'
  • http://<EC2-ip>:8080 접속해서 Jenkins 들어가면 됨...

Jenkins 프로젝트(nodejs) 빌드 테스트

  • 원하는 프로젝트 이름 설정

  • 소스코드 추가 - git 주소 적으면 됨

  • 빌드 스텝 추가

  • NodeJS 설정을 위한 Jenkins 관리 - Tools 설정

  • 빌드 환경 설정

  • 지금 빌드 클릭

[확인]


Docker로 애플리케이션 배포 

  • Jenkins Plugin: CloudBees Docker Build and Publish 설치
  • Jenkins Docker: Jenkins 컨테이너가 Docker API와 통신할 수 있는 Docker socket에 접근할 수 있게..
# Dockerfile
FROM jenkins/jenkins:lts
USER root

RUN mkdir -p /tmp/download && \
 curl -L https://download.docker.com/linux/static/stable/x86_64/docker-18.03.1-ce.tgz | tar -xz -C /tmp/download && \
 rm -rf /tmp/download/docker/dockerd && \
 mv /tmp/download/docker/docker* /usr/local/bin/ && \
 rm -rf /tmp/download && \
 groupadd -g <998> docker && \
 usermod -aG staff,docker jenkins

USER jenkins
# groupadd 의 숫자는 cat /etc/group | grep docker 로 확인
# git clone 
cd jenkins-docker
docker build -t jenkins-docker .

docker stop jenkins # 기존의 jenkins 종료
docker rm jenkins

docker run -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock --name jenkins -d jenkins-docker
docker exec -it jenkins bash
  • docker repository 생성

  • build step 추가

  • 지금 빌드 클릭

[해당 환경 테스트]

docker pull realyun99/docker-nodejs-demo
docker run -p 3000:3000 -d --name my-nodejs-app realyun99/docker-nodejs-demo
# EC2 보안그룹 포트도 열어주기!(3000)

 

'Computer Science > DevOps' 카테고리의 다른 글

[Jenkins] 다양한 플러그인 활용  (0) 2023.07.24
[Jenkins] Jenkins Pipeline 구축  (0) 2023.07.03
[OS] OS 모음집  (0) 2021.08.12
[CI/CD] Tool  (0) 2021.08.11
[CI/CD] 정의  (0) 2021.08.11

(참고: https://iot-sitewise.workshop.aws/en/introduction/what-you-are-going-to-build.html)


CloudFormation 스택 생성 (도쿄)

  • Cloud9 환경
  • SageMaker 노트북 인스턴스 등..

 

SiteWise gateway가 AWS IoT Greengrass에서 실행되고 Greengrass는 AWS IoT Core에 연결한다.

(IoT Core의 Rule Engine으로 데이터를 수집할 예정!)

→ 실습의 흐름 맛보기 랄까...

 

IoT에 대한 로깅 활성화

  • IoT 서비스가 계정의 CW에 쓸 수 있도록 허용하려면 서비스 역할이 필요하다.
    • CloudFormation 콘솔 상 IoT ServiceRoleName 출력 세션에서 역할 이름 확인 가능하다.

 

AWS IoT SiteWise 설정

  • 자신의 속성이 데이터 스트림과 일치하는 경우에만 데이터가 SiteWise로 수집된다.
  • 데이터 수집 방법
    • OPC-UA 서버에 연결하고 이러한 서버에서 데이터를 검색하는 SiteWise 게이트웨이를 통해
    • AWS IoT Core의 MQTT 항목에 메시지를 게시하고 AWS IoT 규칙을 사용하여 데이터를 AWS IoT SiteWise로
    • BatchPutAssetPropertyValue API를 사용하여 SiteWise로 직접

 

먼저 SiteWise gw를 만들자.

(Greengrass 구성 요소로 게이트웨이가 실행된다.)

(data collection pack: 데이터를 수집하고 클라우드로, data processing pack: 게이트웨이가 에지에서 데이터 처리)

진행할 실습 상에서 게이트웨이는 cloud9 환경이다.

엣지 기능에서 데이터 처리팩은 비활성화!

게시자 구성의 경우는 디폴트

승인을 누르면 설치 파일이 PC에 다운로드 된다.

다운로드된 파일을 cloud9으로 업로드 한다. (/home/ec2-user/sitewise/)

cd ~/sitewise
chmod +x sitewise-workshop-Gateway.deploy.sh
sudo ./sitewise-workshop-Gateway.deploy.sh

(Greengrass의 코어 디바이스 → 배포  → 구성 요소)

# greengrass 상태 확인
systemctl status greengrass.service

# greengrass process 실행 확인
ps aux |grep green

# 로그 파일
sudo su -
cd /greengrass/v2/logs/
  • 로그 확인
    • greengrass.log : AWS IoT Greengrass에 대한 로그
    • aws.iot.SiteWiseEdgeCollectorOpcua.log : OPC-UA 서버에서 데이터를 수집하는 SiteWise 구성 요소
    • aws.iot.SiteWiseEdgePublisher.log : 클라우드의 SiteWise 데이터 저장소로 데이터를 전송하는 SiteWise 구성 요소

 

OPC-UA 서버 시작을 해보자.

cd ~/sitewise/
./start-node-opcua.sh

 

  • OPC-UA 서버가 SiteWise 데이터 수집기(aws.iot.SiteWiseEdgeCollectorOpcua) 에서 연결을 수신했다.
  • 수집기의 경우 OPC-UA 서버에서 데이터를 검색하여 스트림에 기록한다.
  • SiteWise Publisher는 이 스트림을 읽고 데이터를 AWS cloud의 AWS IoT SiteWise로 전달한다.

현재 까지의 환경

 

 AWS IoT SiteWise 데이터 수집

  • SiteWise는 데이터를 소비하고 데이터 스트림을 자산 속성에 일치 시킨다.
    • 자산 모델 및 자산을 생성하고 데이터 스트림을 자산 속성과 연결한다.

 

먼저 AWS IoT SiteWise 데이터 스토리지를 확인해보자.

aws iotsitewise describe-storage-configuration

연결 해제된 데이터 저장소가 활성화 되면 위의 출력이 뜬다. → disassociated mode

(데이터 저장소가 설정된 모드는 데이터 스트림을 자산 속성과 연결하는 방식에 영향을 준다.)

 

데이터 수집의 경우 (실습 기준)

  • Generators 1 and 2: through a SiteWise gateway
  • Generators 3 and 4: through the SiteWise PUT API
  • Generators 7 and 8: by using AWS IoT’s rules engine

 

[자산 모델링]

SiteWise 자산을 사용해 산업 운영의 가상 표현을 생성할 수 있다.

(자산: 디바이스, 장비 또는 하나 이상의 데이터 스트림을 IoT SiteWise로 보내는 프로세스)

실습의 예로 /DayOneEnergyCorp/1/Generator/Power 의 경우 1번 발전기에서 생성된 에너지 측정값이다.

(측정값을 기반으로 메트릭 생성 가능)

 

Asset model → Asset → Asset property

 

[Generator 표현]

(실습: 각 발전기는 분당 생산된 에너지와 발전기의 내부 온도를 보고, 분당 20와트의 에너지 생산 예상)

생성기 템플릿에서 아래의 측정 및 지표 정의할 예정!

  • 측정: 생산된 분당 와트, 온도 및 rpm
  • 지표: 5분당 총 와트, 5분당 평균 온도 및 5분당 평균 rpm

 

자산 모델(Asset model)을 생성해보자.

자산의 경우 템플릿을 기반으로 생성된다.(정보의 일관성 보장)

위 이미지와 같이 모델을 생성한다. (상태가 active 될 때 까지 기다리기!)

 

자산(Asset)을 만들어 보자.

얘도 상태가 active 확인이 되어야 한다.


데이터 스트림 연결 및 알림을 구성해보자.

(자산이 생성된 뒤 SiteWise에 수집되는 데이터 스트림을 자산 속성과 연결하는 과정이 필요하다.)

SiteWise가 IoT에 데이터를 게시하도록 하려면 관련 속성에 대한 알림을 활성화 해야한다.

 

나의 경우 연결 해제 모드 인 것을 위에서 확인했다.

데이터 스트림 관리를 통해 속성을 선택해 업데이트 한다.

위와 같이 데이터 스트림이 Generator-1(자산)의 속성과 연결된 것을 확인할 수 있다.

 

자산에 들어가 Generator-1의 모든 측정 및 지표에 대한 MQTT 알림 상태를 ENABLED로 설정

 

데이터 플로우를 확인해보자.

(SiteWise 게이트웨이는 OPC-UA 서버에서 스트림을 가져와 SiteWise에 업로드해야 한다.

3개의 데이터 스트림이 자산(Generator-1)에 연결된다. 알림이 활성화되어 있기에 IoT Core에 게시된다.)

 

SiteWise는 알림의 데이터를 토픽에 게시한다.

$aws/sitewise/asset-models/+/assets/+/properties/+

아니면 자산에서 측정 및 지표에서 최신값에 값이 표시가 되어야 한다!

 

데이터 생성기를 시작하려면,

# AWS IoT Core로 수집 시작
cd ~/sitewise
./sitewise-iot-ingest.py

# AWS IoT SiteWise로 수집 시작
cd ~/sitewise
./sitewise-direct-ingest.py

(추가 자산을 만들어 더 많은 데이터를 수집하려면 Generator-2는 SiteWise gw, Genterator-3는 PUT API, Generator-7은 IoT Core Rule Engine을 통해 수집된다.)

 

대충 이런 흐름이다...(어렵다😥)

 

AWS IoT SiteWise Monitor

이제 마지막으로 모니터링을 할 수 있는 환경을 만들어보자.

자산의 데이터를 모니터링하려면 포털을 생성한 뒤 프로젝트와 대시보드를 만든다.

(AWS 계정 없이도 포털을 다른 사용자와 공유가 가능하다.)

루트 하나만 프로젝트와 연결 가능하기 때문에 계층 구조 생성이 필요

계층 구조를 위한 자산 모델 생성 가이드

더보기

CREATE POWER PLANT ASSET MODEL

  1. Name: Power Plant
  2. Attribute definitions
  3. Name: location, Default value: {"lat": "none", "lon": "none"}, Data type: String
  4. Hierarchy definitions
  5. Hierarchy name: Power_Plants-Generators-Hierarchy
  6. Hierarchy model: Generator model 262966 Doppler
  7. Metric definitions
  8. Name: power_per_plant_5m
  9. Formula: sum(Power_Plants-Generators-Hierarchy sum_watts_5m)
  10. Time interval: 5 minutes

CREATE POWER PLANT ASSET

You will now create a power plant asset and add generator assets to it. The Power Plant 1 will host generators 1 and 2.

  1. Model: Power Plant
  2. Name: Power Plant 1
  3. Wait until the Status becomes ACTIVE
  4. Edit
  5. Assets associated to this asset
  6. Add associated asset
  7. Hierarchy: Power_Plants-Generators-Hierarchy
  8. Asset: Generator-1
  9. Add associated asset
  10. Hierarchy: Power_Plants-Generators-Hierarchy
  11. Asset: Generator-2
  12. Metric: “power_per_plant_5m”: Notification status: ENABLED
  13. Save asset

Create

  • Power Plant 2 with associated asset Generator-3
  • Power Plant 3 with associated asset Generator-7

CREATE ASSET MODEL FOR ALL POWER PLANTS

  1. Name: All Power Plants
  2. Hierarchy definitions
  3. Hierarchy name: All_Power_Plants-Power_Plants-Hierarchy
  4. Hierarchy model: Power Plant
  5. Metric definitions
  6. Name: power_all_plants_5m
  7. Formula: sum(All_Power_Plants-Power_Plants-Hierarchy power_per_plant_5m)
  8. Time interval: 5 minutes

CREATE AN ASSET FROM THE ALL POWER PLANTS MODEL

When the model is in the status ACTIVE create assets based on this model. Add Power Plant assets.

  1. Model: All Power Plants
  2. Name: All Power Plants

After the asset has been created associate each Power Plant asset to All Power Plants

  1. Edit
  2. Assets associated to this asset
  3. Add associated asset
  4. Hierarchy: All_Power_Plants-Power_Plants-Hierarchy
  5. Asset: Power Plant 1
  6. Add associated asset
  7. Hierarchy: All_Power_Plants-Power_Plants-Hierarchy
  8. Asset: Power Plant 2
  9. Add associated asset
  10. Hierarchy: All_Power_Plants-Power_Plants-Hierarchy
  11. Asset: Power Plant 3
  12. “power_all_plants_5m”: Notification status: ENABLED
  13. Save asset

  

너무 길어지니까.. 모니터링을 위한 포털 생성의 경우 다음 포스팅에서 진행하도록 하자...

위의 실습을 이어서 진행할 것이다.

https://realyun99.tistory.com/192


AWS Cloud에서 component를 배포하려면 먼저 recipe 파일을 확장해 S3의 component artifact를 참조한 다음 component artifact를 S3로 업로드 해야한다.

배포가 구성되면 디바이스가 S3에서 아티팩트를 다운로드 한다.

 

버킷을 만들고 다음 명령을 사용해 버킷 이름을 검색하는 명령어를 입력한다.

EPOCH_TIME=$(date +"%s") && S3_BUCKET=ggcv2-workshop-$HOSTNAME-$EPOCH_TIME && aws s3 mb s3://$S3_BUCKET

아래 코드 중 버킷이름을 위에서 검색했던 이름으로 변경하고 json 파일을 업데이트 해준다.

{
   "RecipeFormatVersion": "2020-01-25",
   "ComponentName": "com.example.HelloWorld",
   "ComponentVersion": "1.0.0",
   "ComponentDescription": "My first AWS IoT Greengrass component.",
   "ComponentPublisher": "Amazon",
   "ComponentConfiguration": {
      "DefaultConfiguration": {
         "Message": "world"
      }
   },
"Manifests": [
      {
         "Platform": {
            "os": "linux"
         },
         "Lifecycle": {
            "Run": "python3 -u {artifacts:path}/hello_world.py '{configuration:/Message}'\n"
         },
         "Artifacts": [
            {
               "URI": "s3://[YOUR BUCKET NAME]/artifacts/com.example.HelloWorld/1.0.0/hello_world.py"
            }
         ]
      }
   ]
}

component artifact를 업로드 해준다.

aws s3 cp --recursive /home/ubuntu/environment/GreengrassCore/ s3://$S3_BUCKET/

 

IoT Greengrass의 Component에서 Component 정의를 생성하는 과정이다.

cd /home/ubuntu/environment/GreengrassCore/recipes && aws greengrassv2 create-component-version  --inline-recipe fileb://com.example.HelloWorld-1.0.0.json --region $AWS_DEFAULT_REGION

# component 목록 확인
aws greengrassv2 list-components --region $AWS_DEFAULT_REGION

 

Pub/Sub IPC

Greengrass V2는 프로세스 간 통신을 위한 IPC SDK를 제공한다.

(custom component의 각 프로세스 간 Pub/Sub 통신이 가능하다.)

  • 센서 데이터를 읽고 토픽에 계속 pub하는 component, 해당 토픽 로그를 sub하고 메시지를 수신하는 component 및 IPC를 사용하는 custom component 를 만드는 과정

 

먼저 Publisher를 만들어보자.

데이터를 토픽에 pub하기 위해 더미 센서를 생성해야한다.

mkdir -p ~/environment/GreengrassCore/artifacts/com.example.Publisher/1.0.0 && cd ~/environment/GreengrassCore/artifacts/com.example.Publisher/1.0.0
touch example_publisher.py dummy_sensor.py

 

생성된 빈 스크립트 파일을 열고 아래 언급된 파일 이름에 따라 붙여 넣는다.

# dummy_sensor.py
from random import gauss

class DummySensor(object):
    def __init__(self, mean=25, variance=1):
        self.mu = mean
        self.sigma = variance
        
    def read_value(self):
        return float("%.2f" % (gauss(1000, 20)))

if __name__ == '__main__':
    sensor = DummySensor()
    print(sensor.read_value())


# example_publisher.py
import time
import datetime
import json
import awsiot.greengrasscoreipc
from awsiot.greengrasscoreipc.model import (
    PublishToTopicRequest,
    PublishMessage,
    JsonMessage
)
from dummy_sensor import DummySensor


TIMEOUT = 10
publish_rate = 1.0

ipc_client = awsiot.greengrasscoreipc.connect()

sensor = DummySensor()

topic = "my/topic"


while True:
    message = {"timestamp": str(datetime.datetime.now()),
               "value": sensor.read_value()}
    message_json = json.dumps(message).encode('utf-8')

    request = PublishToTopicRequest()
    request.topic = topic
    publish_message = PublishMessage()
    publish_message.json_message = JsonMessage()
    publish_message.json_message.message = message
    request.publish_message = publish_message
    operation = ipc_client.new_publish_to_topic()
    operation.activate(request)
    future = operation.get_response()
    future.result(TIMEOUT)

    print("publish")
    time.sleep(1/publish_rate)

 

recipe 폴더와 빈파일 생성

touch ~/environment/GreengrassCore/recipes/com.example.Publisher-1.0.0.json

해당 빈파일에 아래 내용 붙여 넣기

{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.Publisher",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.Publisher:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Install": "pip3 install awsiotsdk numpy",
        "Run": "python3 -u {artifacts:path}/example_publisher.py"
      }
    }
  ]
}

 

다음 명령을 실행해 component를 배포하자.

sudo /greengrass/v2/bin/greengrass-cli deployment create \
  --recipeDir ~/environment/GreengrassCore/recipes \
  --artifactDir ~/environment/GreengrassCore/artifacts \
  --merge "com.example.Publisher=1.0.0"

 

이젠 Subscriber의 차례다. 위 과정과 비슷하니 명령어와 코드만 적어 두겠다...

더보기
# 아티팩트 폴더, 빈 스크립트 파일 생성
mkdir -p ~/environment/GreengrassCore/artifacts/com.example.Subscriber/1.0.0 && cd ~/environment/GreengrassCore/artifacts/com.example.Subscriber/1.0.0
touch example_subscriber.py

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
import time
import json
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import (
    SubscribeToTopicRequest,
    SubscriptionResponseMessage
)

TIMEOUT = 10

ipc_client = awsiot.greengrasscoreipc.connect()


class StreamHandler(client.SubscribeToTopicStreamHandler):
    def __init__(self):
        super().__init__()

    def on_stream_event(self, event: SubscriptionResponseMessage) -> None:
        message_string = event.json_message.message
        with open('/tmp/Greengrass_Subscriber.log', 'a') as f:
            print(message_string, file=f)

    def on_stream_error(self, error: Exception) -> bool:
        return True

    def on_stream_closed(self) -> None:
        pass


topic = "my/topic"

request = SubscribeToTopicRequest()
request.topic = topic
handler = StreamHandler()
operation = ipc_client.new_subscribe_to_topic(handler)
future = operation.activate(request)
while True:
    time.sleep(1)

operation.close()

# 레시피 폴더와 빈파일 생성
touch ~/environment/GreengrassCore/recipes/com.example.Subscriber-1.0.0.json 

{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.Subscriber",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.Subscriber:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Install": "pip3 install awsiotsdk",
        "Run": "python3 -u {artifacts:path}/example_subscriber.py"
      }
    }
  ]
}

# 구성요소 배포
sudo /greengrass/v2/bin/greengrass-cli deployment create \
  --recipeDir ~/environment/GreengrassCore/recipes \
  --artifactDir ~/environment/GreengrassCore/artifacts \
  --merge "com.example.Subscriber=1.0.0"

받은 메시지가 계속 표시되면 성공한 것!

tail -f /tmp/Greengrass_Subscriber.log

 

Local MQTT Broker

여기까지는 Greengrass 디바이스가 데이터 공급자 역할을 할 수 있도록 허용하는 로컬 Pub/Sub 개념이였다.

그러나 데이터 공급자가 Greengrass 장치 외부에 있는 경우 MQTT 형식으로 게시 대상을 도입할 수 있다.

(Greengrass 장치를 로컬 MQTT 게이트웨이로 바꾸는 브릿지)

MQTT 브로커 구성 요소 배포를 진행하면 된다..

(배포 → 개정)

위의 구성요소 구성을 클릭한 뒤 아래의 코드를 넣어주면 된다.

# Auth
{
  "deviceGroups": {
    "formatVersion": "2021-03-05",
    "definitions": {
      "MyDeviceGroup": {
        "selectionRule": "thingName: MyClientDevice* OR thingName: MyOtherClientDevice*",
        "policyName": "MyClientDevicePolicy"
      }
    },
    "policies": {
      "MyClientDevicePolicy": {
        "AllowAll": {
          "statementDescription": "Allow client devices.",
          "operations": [
            "mqtt:connect",
            "mqtt:publish",
            "mqtt:subscribe"
          ],
          "resources": [
            "*"
          ]
        }
      }
    }
  }
}

# Bridge
{
   "mqttTopicMapping": {
     "HelloWorldIotCoreMapping": {
       "topic": "clients/+/hello/world",
       "source": "LocalMqtt",
       "target": "IotCore"
     }
   }
 }

이 실습에선 Mosquitto 클라이언트를 사용해 장치를 시뮬레이션 할 예정이다.

인증 구성 요소는 AWS IoT Core에서 AWS IoT 사물로 등록되고 사물과 연결된 동일한 인증서를 제공하는 디바이스를 지원한다.

 

Auth component 구성을 보면 이름이 MyClientDevice 로 시작하는 장치를 허용하고 있다.

cloud9 에 아래의 내용을 입력하자.

cd ~/environment
mkdir -p devices
cd devices
THING_NAME=MyClientDevice1
aws iot create-thing --thing-name $THING_NAME
CERTIFICATE_ARN=$(aws iot create-keys-and-certificate --private-key-out $THING_NAME.key --certificate-pem-out $THING_NAME.crt --query "certificateArn" --out text --set-as-active)
aws iot attach-thing-principal --thing-name $THING_NAME --principal $CERTIFICATE_ARN

cd ~/environment
mkdir -p devices
cd devices
THING_NAME=MyOtherClientDevice1
aws iot create-thing --thing-name $THING_NAME
CERTIFICATE_ARN=$(aws iot create-keys-and-certificate --private-key-out $THING_NAME.key --certificate-pem-out $THING_NAME.crt --query "certificateArn" --out text --set-as-active)
aws iot attach-thing-principal --thing-name $THING_NAME --principal $CERTIFICATE_ARN

 

MQTT를 통한 기기 통신 테스트를 해보면,

동일한 터미널에서 Mosquitto 클라이언트를 설치한다.

sudo apt install mosquitto-clients

 

다음으로 로컬 브로커 서버 인증서엥 서명하는 CA 인증서를 검색

(클라이언트가 브로커 엔드포인트를 확인하는데 사용됨)

cd ~/environment/devices
sudo cp /greengrass/v2/work/aws.greengrass.clientdevices.Auth/ca.pem .
sudo chmod 444 ca.pem

 

토픽 Subscribe를 해보자.

cd ~/environment/devices
mosquitto_sub -h localhost -p 8883 -q 0 -t clients/+/hello/world --cafile ca.pem --cert MyOtherClientDevice1.crt --key MyOtherClientDevice1.key -i MyOtherClientDevice1

 

메시지 publish (새 터미널 열고)

cd ~/environment/devices
mosquitto_pub -h localhost -p 8883 -q 0 -t clients/test/hello/world --cafile ca.pem --cert MyClientDevice1.crt --key MyClientDevice1.key -m "{\"message\": \""$2" @ "$(date +"%m-%d-%Y-%H-%M-%s")"\"}" -i MyClientDevice1

mosquitto_sub 명령을 실행하는 터미널에 메시지가 표시되어야 한다.

 

'Cloud > AWS' 카테고리의 다른 글

[AWS] Amazon OpenSearch Service 사용해보기  (0) 2023.08.23
[AWS] AWS IoT SiteWise 실습  (0) 2023.01.27
[AWS] AWS IoT Greengrass V2 실습  (0) 2023.01.26
[AWS] Firebase를 AWS Amplify로  (0) 2023.01.04
[AWS] re:Invent 2022 정리  (0) 2022.12.19

+ Recent posts