cf dev를 이용해 Cloud Foundry의 CFAR(Cloud Foundry Application Runtime)에 파이썬 앱을 올려보자.


환경

  • Ubuntu 18.04
  • Baremetal Server


목표

  • Cloud Foundry에서 CFAR(Cloud Foundry Application Runtime)의 기본을 실습해보기 위해 cf dev를 이용해 파이썬 어플리케이션을 올려보자.
  • 해당 포스트는 실습 위주이며 참고자료에 있는 내용을 토대로 작성하였습니다.


Cloud Foundry

Cloud Foundry

  • Cloud Foundry: Cloud Foundry Foundation에 의해서 운영되는 멀티클라우드 오픈소스 platform as a service (PaaS).
  • 많은 프로젝트들이 들어가 있으며 배포, 관리 및 앱 환경 구축에 이르기까지 다양한 서비스를 제공한다.
  • 예시) BOSH 그리고 CFAR

CFAR(Cloud Foundry Application Runtime)

  • CFAR: Cloud Foundry Application Runtime (CFAR)은 개발자가 코드에만 신경쓸 수 있게 해주는 코드 중심 플랫폼입니다. 어떤 언어나 프레임워크인지 상관없이 코드를 받아서 어떤 클라우드에서라도 실행할 수 있게 해줍니다.
  • 코드를 작성하고 설정 파일을 추가한 다음에 CFAR에 업로드하면 앱 실행환경을 만들 수 있습니다.

CF Dev

  • CF Dev: CF Dev는 개발자 컴퓨터에 하이퍼바이저와 BOSH Director를 이용해 Cloud Foundry를 사용할 수 있도록 고안된 배포판입니다.
  • CF Dev를 이용하면 개인의 컴퓨터에서 간단하게 CFAR의 기능을 이용해 앱을 구축할 수 있습니다.
  • 본 글에서는 간단한 파이썬 플라스크(Flask) 앱을 만들어볼 예정입니다.


CF Dev

CF Dev 설치

  • QEMU와 libvirt 설치
sudo apt install qemu-kvm libvirt-bin libvirt-doc -y
  • CF CLI 설치
# ...first add the Cloud Foundry Foundation public key and package repository to your system
wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add -
echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
# ...then, update your local package index, then finally install the cf CLI
sudo apt-get update -y
sudo apt-get install cf-cli -y
  • CF Dev plugin 설치
cf install-plugin -r CF-Community cfdev


CF Dev 환경 구축

  • cf dev start
cf dev start
  • 결과 화면
Downloading Resources...
Progress: |====================>| 100.0%
Setting State...

CF Dev collects anonymous usage data to help us improve your user experience. We intend to share these anonymous usage analytics with user community by publishing quarterly reports at :

https://github.com/pivotal-cf/cfdev/wiki/Telemetry

Are you ok with CF Dev periodically capturing anonymized telemetry [y/N]?> y
WARNING: CF Dev requires 8192 MB of RAM to run. This machine may not have enough free RAM.
Creating the VM...
Starting the VM...
Fetching VM Address...
Waiting for the VM...
Deploying the BOSH Director...
Deploying CF...
  Done (11m24s)

 	  ██████╗███████╗██████╗ ███████╗██╗   ██╗
 	 ██╔════╝██╔════╝██╔══██╗██╔════╝██║   ██║
 	 ██║     █████╗  ██║  ██║█████╗  ██║   ██║
 	 ██║     ██╔══╝  ██║  ██║██╔══╝  ╚██╗ ██╔╝
 	 ╚██████╗██║     ██████╔╝███████╗ ╚████╔╝
 	  ╚═════╝╚═╝     ╚═════╝ ╚══════╝  ╚═══╝
 	             is now running!

 	To begin using CF Dev, please run:
 	    cf login -a https://api.dev.cfdev.sh --skip-ssl-validation

 	Admin user => Email: admin / Password: admin
 	Regular user => Email: user / Password: pass

 	To deploy a particular service, please run:
 	    cf dev deploy-service <service-name> [Available services: mysql]


로그인

  • Email: user / Password: pass
cf login -a https://api.dev.cfdev.sh --skip-ssl-validation
  • 결과 화면
API endpoint: https://api.dev.cfdev.sh

Email: user

Password:
Authenticating...
OK

Targeted org cfdev-org

Targeted space cfdev-space



API endpoint:   https://api.dev.cfdev.sh (API version: 3.76.0)
User:           user
Org:            cfdev-org
Space:          cfdev-space


어플리케이션 파일 작성

  • 4개의 파일이 필요합니다.
  • 폴더 생성
mkdir flask_test_cf
cd flask_test_cf

app.py

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello_world():
    return "Hello World!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=int(os.getenv("PORT", 5001)))

Procfile

  • CFAR에서 실행할 명령어
web: python app.py

requirements.txt

  • pip freeze 명령어를 이용해서 생성 가능
pip freeze > requirements.txt
Click==7.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.11.1
MarkupSafe==1.1.1
Werkzeug==1.0.0

runtime.txt

  • 사용할 파이썬 버전 명시
python-3.6.9


작성한 파일 확인

$ ls
app.py  Procfile  requirements.txt  runtime.txt


cf push를 이용해 application 올리기

  • 프로젝트 디렉토리에서
# -m: memory size to use
# -b: buildpack option(we use python in this case)
# python-hello-world: app name, this will be subdomain name
cf push -m 128M -b python_buildpack python-hello-world
  • 결과
Pushing app python-hello-world to org cfdev-org / space cfdev-space as user...
Getting app info...
Creating app with these attributes...
+ name:         python-hello-world
  path:         /home/twpower/flask_test_cf
  buildpacks:
+   python_buildpack
+ memory:       128M
  routes:
+   python-hello-world.dev.cfdev.sh

Creating app python-hello-world...
Mapping routes...
Comparing local files to remote cache...
Packaging files to upload...
Uploading files...
 963 B / 963 B [=========================================================================] 100.00% 1s

Waiting for API to complete processing files...

Staging app and tracing logs...
   Downloading python_buildpack...
   Downloaded python_buildpack (5M)
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 creating container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 successfully created container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Downloading app package...
   Downloaded app package (963B)
   -----> Python Buildpack version 1.6.36
   -----> Supplying Python
   -----> Installing python 3.6.9
          Download [https://buildpacks.cloudfoundry.org/dependencies/python/python-3.6.9-linux-x64-cflinuxfs3-f30bc832.tgz]
   -----> Installing pip-pop 0.1.3
          Download [https://buildpacks.cloudfoundry.org/dependencies/manual-binaries/pip-pop/pip-pop-0.1.3-fc106ef6.tar.gz]
   -----> Running Pip Install
          Collecting Click==7.0 (from -r /tmp/app/requirements.txt (line 1))
            Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
          Collecting Flask==1.1.1 (from -r /tmp/app/requirements.txt (line 2))
            Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
          Collecting itsdangerous==1.1.0 (from -r /tmp/app/requirements.txt (line 3))
            Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
          Collecting Jinja2==2.11.1 (from -r /tmp/app/requirements.txt (line 4))
            Downloading https://files.pythonhosted.org/packages/27/24/4f35961e5c669e96f6559760042a55b9bcfcdb82b9bdb3c8753dbe042e35/Jinja2-2.11.1-py2.py3-none-any.whl (126kB)
          Collecting MarkupSafe==1.1.1 (from -r /tmp/app/requirements.txt (line 5))
            Downloading https://files.pythonhosted.org/packages/b2/5f/23e0023be6bb885d00ffbefad2942bc51a620328ee910f64abe5a8d18dd1/MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl
          Collecting Werkzeug==1.0.0 (from -r /tmp/app/requirements.txt (line 6))
            Downloading https://files.pythonhosted.org/packages/ba/a5/d6f8a6e71f15364d35678a4ec8a0186f980b3bd2545f40ad51dd26a87fb1/Werkzeug-1.0.0-py2.py3-none-any.whl (298kB)
          Installing collected packages: Click, Werkzeug, itsdangerous, MarkupSafe, Jinja2, Flask
            The script flask is installed in '/tmp/contents020609285/deps/0/python/bin' which is not on PATH.
            Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
          Successfully installed Click-7.0 Flask-1.1.1 Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.0 itsdangerous-1.1.0
          You are using pip version 18.1, however version 20.0.2 is available.
          You should consider upgrading via the 'pip install --upgrade pip' command.
   Exit status 0
   Uploading droplet, build artifacts cache...
   Uploading droplet...
   Uploading build artifacts cache...
   Uploaded build artifacts cache (48.9M)
   Uploaded droplet (49.7M)
   Uploading complete
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 stopping instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 destroying container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6

Waiting for app to start...
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 successfully destroyed container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6

name:              python-hello-world
requested state:   started
routes:            python-hello-world.dev.cfdev.sh
last uploaded:     Mon 10 Feb 14:37:53 KST 2020
stack:             cflinuxfs3
buildpacks:        python

type:            web
instances:       1/1
memory usage:    128M
start command:   python app.py
     state     since                  cpu    memory           disk           details
#0   running   2020-02-10T05:35:17Z   0.0%   118.4K of 128M   177.7M of 1G


응답 확인

$ curl http://python-hello-world.dev.cfdev.sh
Hello World!


CF Dev 삭제

  • cf dev 중지
cf dev stop
  • cfdev plugin 삭제
cf uninstall-plugin cfdev
  • 디렉토리 삭제
rm -rf ~/.cfdev


이슈

  • 가상머신 환경에서 실행하면 virbr0가 활성화되지 않는 이슈가 있다.


참고자료

Upload python application to Cloud Foundry’s CFAR(Cloud Foundry Application Runtime) by using cf dev


Environment and Prerequisite

  • Ubuntu 18.04
  • Baremetal Server


Goal

  • Upload python application to Cloud Foundry’s CFAR(Cloud Foundry Application Runtime) by using cf dev for practice.
  • This post is focus on practice and content is base on Reference


Cloud Foundry

Cloud Foundry

  • Cloud Foundry: Cloud Foundry is an open source, multi-cloud application platform as a service (PaaS) governed by the Cloud Foundry Foundation
  • It has many various projects like for deploying, managing and setting application environment.
  • Ex) BOSH and CFAR

CFAR(Cloud Foundry Application Runtime)

  • CFAR: Cloud Foundry Application Runtime (CFAR) is a code-centric platform that simplifies the lives of developers. It takes your code, written in any language or framework, and runs it on any cloud.
  • Just write codes and upload it to CFAR then application environment will be set.

CF Dev

  • CF Dev: CF Dev is a distribution of Cloud Foundry designed to run on a developer’s laptop or workstation using native hypervisors and a fully functional BOSH Director.
  • By using CF Dev, you can build app runtime environment easily on CFAR.
  • On this post, python flask application will be set up.


CF Dev

Install CF Dev

  • Install QEMU and libvirt
sudo apt install qemu-kvm libvirt-bin libvirt-doc -y
  • Install CF CLI
# ...first add the Cloud Foundry Foundation public key and package repository to your system
wget -q -O - https://packages.cloudfoundry.org/debian/cli.cloudfoundry.org.key | sudo apt-key add -
echo "deb https://packages.cloudfoundry.org/debian stable main" | sudo tee /etc/apt/sources.list.d/cloudfoundry-cli.list
# ...then, update your local package index, then finally install the cf CLI
sudo apt-get update -y
sudo apt-get install cf-cli -y
  • Install CF Dev plugin
cf install-plugin -r CF-Community cfdev


Make CF Dev environment

  • cf dev start
cf dev start
  • Result
Downloading Resources...
Progress: |====================>| 100.0%
Setting State...

CF Dev collects anonymous usage data to help us improve your user experience. We intend to share these anonymous usage analytics with user community by publishing quarterly reports at :

https://github.com/pivotal-cf/cfdev/wiki/Telemetry

Are you ok with CF Dev periodically capturing anonymized telemetry [y/N]?> y
WARNING: CF Dev requires 8192 MB of RAM to run. This machine may not have enough free RAM.
Creating the VM...
Starting the VM...
Fetching VM Address...
Waiting for the VM...
Deploying the BOSH Director...
Deploying CF...
  Done (11m24s)

 	  ██████╗███████╗██████╗ ███████╗██╗   ██╗
 	 ██╔════╝██╔════╝██╔══██╗██╔════╝██║   ██║
 	 ██║     █████╗  ██║  ██║█████╗  ██║   ██║
 	 ██║     ██╔══╝  ██║  ██║██╔══╝  ╚██╗ ██╔╝
 	 ╚██████╗██║     ██████╔╝███████╗ ╚████╔╝
 	  ╚═════╝╚═╝     ╚═════╝ ╚══════╝  ╚═══╝
 	             is now running!

 	To begin using CF Dev, please run:
 	    cf login -a https://api.dev.cfdev.sh --skip-ssl-validation

 	Admin user => Email: admin / Password: admin
 	Regular user => Email: user / Password: pass

 	To deploy a particular service, please run:
 	    cf dev deploy-service <service-name> [Available services: mysql]


Login

  • Email: user / Password: pass
cf login -a https://api.dev.cfdev.sh --skip-ssl-validation
  • Result
API endpoint: https://api.dev.cfdev.sh

Email: user

Password:
Authenticating...
OK

Targeted org cfdev-org

Targeted space cfdev-space



API endpoint:   https://api.dev.cfdev.sh (API version: 3.76.0)
User:           user
Org:            cfdev-org
Space:          cfdev-space


Make app files

  • Four files are needed.
  • Make directory
mkdir flask_test_cf
cd flask_test_cf

app.py

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello_world():
    return "Hello World!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=int(os.getenv("PORT", 5001)))

Procfile

  • Command to run in CFAR
web: python app.py

requirements.txt

  • It can be generated by using pip freeze command
pip freeze >  requirements.txt
Click==7.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.11.1
MarkupSafe==1.1.1
Werkzeug==1.0.0

runtime.txt

  • Write python version
python-3.6.9


Check files

$ ls
app.py  Procfile  requirements.txt  runtime.txt


Upload app using cf push

  • In project directory
# -m: memory size to use
# -b: buildpack option(we use python in this case)
# python-hello-world: app name, this will be subdomain name
cf push -m 128M -b python_buildpack python-hello-world
  • Result
Pushing app python-hello-world to org cfdev-org / space cfdev-space as user...
Getting app info...
Creating app with these attributes...
+ name:         python-hello-world
  path:         /home/twpower/flask_test_cf
  buildpacks:
+   python_buildpack
+ memory:       128M
  routes:
+   python-hello-world.dev.cfdev.sh

Creating app python-hello-world...
Mapping routes...
Comparing local files to remote cache...
Packaging files to upload...
Uploading files...
 963 B / 963 B [=========================================================================] 100.00% 1s

Waiting for API to complete processing files...

Staging app and tracing logs...
   Downloading python_buildpack...
   Downloaded python_buildpack (5M)
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 creating container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 successfully created container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Downloading app package...
   Downloaded app package (963B)
   -----> Python Buildpack version 1.6.36
   -----> Supplying Python
   -----> Installing python 3.6.9
          Download [https://buildpacks.cloudfoundry.org/dependencies/python/python-3.6.9-linux-x64-cflinuxfs3-f30bc832.tgz]
   -----> Installing pip-pop 0.1.3
          Download [https://buildpacks.cloudfoundry.org/dependencies/manual-binaries/pip-pop/pip-pop-0.1.3-fc106ef6.tar.gz]
   -----> Running Pip Install
          Collecting Click==7.0 (from -r /tmp/app/requirements.txt (line 1))
            Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)
          Collecting Flask==1.1.1 (from -r /tmp/app/requirements.txt (line 2))
            Downloading https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl (94kB)
          Collecting itsdangerous==1.1.0 (from -r /tmp/app/requirements.txt (line 3))
            Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
          Collecting Jinja2==2.11.1 (from -r /tmp/app/requirements.txt (line 4))
            Downloading https://files.pythonhosted.org/packages/27/24/4f35961e5c669e96f6559760042a55b9bcfcdb82b9bdb3c8753dbe042e35/Jinja2-2.11.1-py2.py3-none-any.whl (126kB)
          Collecting MarkupSafe==1.1.1 (from -r /tmp/app/requirements.txt (line 5))
            Downloading https://files.pythonhosted.org/packages/b2/5f/23e0023be6bb885d00ffbefad2942bc51a620328ee910f64abe5a8d18dd1/MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl
          Collecting Werkzeug==1.0.0 (from -r /tmp/app/requirements.txt (line 6))
            Downloading https://files.pythonhosted.org/packages/ba/a5/d6f8a6e71f15364d35678a4ec8a0186f980b3bd2545f40ad51dd26a87fb1/Werkzeug-1.0.0-py2.py3-none-any.whl (298kB)
          Installing collected packages: Click, Werkzeug, itsdangerous, MarkupSafe, Jinja2, Flask
            The script flask is installed in '/tmp/contents020609285/deps/0/python/bin' which is not on PATH.
            Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
          Successfully installed Click-7.0 Flask-1.1.1 Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.0 itsdangerous-1.1.0
          You are using pip version 18.1, however version 20.0.2 is available.
          You should consider upgrading via the 'pip install --upgrade pip' command.
   Exit status 0
   Uploading droplet, build artifacts cache...
   Uploading droplet...
   Uploading build artifacts cache...
   Uploaded build artifacts cache (48.9M)
   Uploaded droplet (49.7M)
   Uploading complete
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 stopping instance 6616abe5-490e-4854-9ee6-8485ad258dd6
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 destroying container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6

Waiting for app to start...
   Cell 19330b69-fa32-43e6-9884-9e89fcbbbc40 successfully destroyed container for instance 6616abe5-490e-4854-9ee6-8485ad258dd6

name:              python-hello-world
requested state:   started
routes:            python-hello-world.dev.cfdev.sh
last uploaded:     Mon 10 Feb 14:37:53 KST 2020
stack:             cflinuxfs3
buildpacks:        python

type:            web
instances:       1/1
memory usage:    128M
start command:   python app.py
     state     since                  cpu    memory           disk           details
#0   running   2020-02-10T05:35:17Z   0.0%   118.4K of 128M   177.7M of 1G


Check response

$ curl http://python-hello-world.dev.cfdev.sh
Hello World


Delete CF Dev

  • Stop cf dev
cf dev stop
  • Delete cfdev plugin
cf uninstall-plugin cfdev
  • Delete directory
rm -rf ~/.cfdev


Issue

  • virbr0 is not up in virtual machine environment.


Reference

5초마다 실행되는 systemd 서비스를 timer를 이용해 만들어보자.


환경

  • Ubuntu 18.04


목표

  • systemd의 서비스를 특정 날짜에 혹은 반복적으로 crontab처럼 사용하고 싶을때 사용하는 timer의 예제를 직접 작성해본다.
  • systemd의 timer는 OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec=와 같은 옵션과 OnCalendar=를 사용하는데 아래 예제에서는 OnCalendar=를 사용합니다.


systemd service and timer

systemd

  • systemd: Wikipedia에 따르면 init 시스템을 대신해 사용자 공간을 부트스트래핑하고 최종적으로 모든 프로세스들을 관리하는 시스템이라고 한다.

service

  • service: systemd에 있는 unit으로 systemd에 의해 관리되는 프로세스에 대해 기술한 파일이며 이를 통해 어떤 서비스나 프로그램이 실행된다.

timer

  • timer: systemd에 있는 unit으로 특정 시간이나 이벤트에 따라 사용할 service를 위해 사용한다.


systemd service timer 파일 예제

만들어야할 파일

  • 사용할 service 파일과 이벤트를 등록할 timer가 필요하다.
  • timer로 돌리려는 service는 파일명이 둘이 같아야합니다!
  • 예제에서 이름은 각각 on-calendar.service 그리고 on-calendar.timer입니다.


on-calendar.service

[Unit]
Description=Test for OnCalendar timer

[Service]
Type=oneshot
ExecStart=/usr/bin/test_on_calendar.sh

[Install]
WantedBy=multi-user.target
  • Description: 이 서비스 파일에 대한 설명입니다.
  • Type: 실행할 서비스의 타입에 대한부분으로 simple, oneshot 그리고 forking과 같은 다양한 타입이 있지만 여기서는 oneshot으로 했습니다. oneshot는 한번 사용하고 끝낼 서비스에 주로 사용되며 서비스의 프로세스가 끝날때까지 기다립니다. 해당 옵션을 사용하면 사용할때 activating으로 바뀌고 다 끝나면 inactive가 됩니다.
  • ExecStart: 해당 서비스가 실행할 파일의 절대경로를 넣어주시면 됩니다.
  • WantedBy: Unit이 어떻게 활성화(enable)될 것인지에 대한 부분이며 systemctl enable 명령어를 사용하면 해당 부분의 target에 명시된 대로 /etc/systemd/system 아래 .wants에 들어가게 됩니다. 부팅시 속한 .wants에 따라서 실행되게 됩니다.

/usr/bin/test_on_calendar.sh

  • 사용할 실행 스크립트입니다.
#!/bin/bash

date >> /tmp/OnCalendarLog.txt
  • 실행 권한을 줍니다.
chmod a+x /usr/bin/test_on_calendar.sh


on-calendar.timer

[Unit]
Description=Test for OnCalendar timer

[Timer]
OnCalendar=*-*-* *:*:0/5
AccuracySec=1s

[Install]
WantedBy=timers.target
  • Description: 이 타이머에 대한 설명입니다.
  • OnCalendar: 언제 혹은 어느 주기에 서비스를 실행할지에 대한 옵션입니다. 형식은 년-월-일 시:분:초로 나타냅니다. 만약 n초마다 서비스를 실행하고 싶으면 위의 예제처럼 *-*-* *:*:0/n으로 해주면 되며 시나 분도 똑같습니다. 해당 옵션을 다양하게 사용가능합니다.
  • AccuracySec: 타이머를 돌릴때 확인하는 주기를 의미합니다. 기본값은 1분이며 1분마다 확인하여 이벤트가 발생할 시간이 맞다면 서비스를 실행합니다. 만약 초단위로 실행을 하고 싶으면 위의 예제처럼 AccuracySec=1s를 추가해야합니다.
  • WantedBy: Unit이 어떻게 활성화(enable)될 것인지에 대한 부분이며 systemctl enable 명령어를 사용하면 해당 부분의 target에 명시된 대로 /etc/systemd/system 아래 .wants에 들어가게 됩니다. 부팅시 속한 .wants에 따라서 실행되게 됩니다.


systemd service timer 사용 예제

부팅 후에도 사용할 수 있게 enable

$ systemctl enable on-calendar.timer

systemd timer 시작

$ systemctl restart on-calendar.timer

timer 등록 확인

$ systemctl list-timers
NEXT                         LEFT          LAST                         PASSED       UNIT                         ACTIVATES
Sun 2020-02-09 00:02:35 KST  1s left       Sun 2020-02-09 00:02:30 KST  2s ago       on-calendar.timer            on-calendar.service

예제 파일 결과

$ cat /tmp/OnCalendarLog.txt
Sun Feb  9 00:02:10 KST 2020
Sun Feb  9 00:02:15 KST 2020
Sun Feb  9 00:02:20 KST 2020
Sun Feb  9 00:02:25 KST 2020
Sun Feb  9 00:02:30 KST 2020


참고자료

Make systemd service which runs every 5 seconds by using timer.


Environment and Prerequisite

  • Ubuntu 18.04


Goal

  • Create timer example which is for using systemd service in specific date, time or event.
  • systemd timer have options like OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec=, OnUnitInactiveSec= and OnCalendar=. This post example use OnCalendar=


systemd service and timer

systemd

  • systemd: According to Wikipedia, systemd is a software suite that provides an array of system components for Linux operating systems.

service

  • service: A unit configuration file whose name ends in “.service” encodes information about a process controlled and supervised by systemd.

timer

  • timer: A unit configuration file in systemd which is for using service in specific date, time or event.


systemd service timer file example

Necessary files

  • We need service and timer file.
  • service which is run by timer should have same file name with that timer
  • In this example, each name is on-calendar.service and on-calendar.timer


on-calendar.service

[Unit]
Description=Test for OnCalendar timer

[Service]
Type=oneshot
ExecStart=/usr/bin/test_on_calendar.sh

[Install]
WantedBy=multi-user.target
  • Description: Description of this file
  • Type: It is type of service which can has simple, oneshot, forking or etc. This example use oneshot. oneshot is used for short-lived and one-off tasks because it blocks on operation and wait process to be finished. When option is oneshot, then its service state will be activating while running and will be changed to inactive after it.
  • ExecStart: Give absolute path of running file or program.
  • WantedBy: It is for specifying how a unit should be enabled. By using systemctl enable command its symbolic link is added to .wants directory under /etc/systemd/system depending on its specified target. It will be run after booting depends on its .wants

/usr/bin/test_on_calendar.sh

  • Script for running.
#!/bin/bash

date >> /tmp/OnCalendarLog.txt
  • Give execution permission
chmod a+x /usr/bin/test_on_calendar.sh


on-calendar.timer

[Unit]
Description=Test for OnCalendar timer

[Timer]
OnCalendar=*-*-* *:*:0/5
AccuracySec=1s

[Install]
WantedBy=timers.target
  • Description: Description of this file
  • OnCalendar: This options specifies when to run or how frequently run. Its format is YEAR-MONTH-DAY HOUR:MINUTE:SECOND. If you like to run service in every n seconds, just make it to *-*-* *:*:0/n. It is also same in hour or minute. It can be used in many various ways.
  • AccuracySec: This unit is used to set the level of accuracy with which the timer should be adhered to. Its default value is 1 minute. So if you want to run timer in second, you need to set AccuracySec=1s like above example.
  • WantedBy: It is for specifying how a unit should be enabled. By using systemctl enable command its symbolic link is added to .wants directory under /etc/systemd/system depending on its specified target. It will be run after booting depends on its .wants


systemd service timer usage example

Make it to enable

$ systemctl enable on-calendar.timer

systemd timer start

$ systemctl restart on-calendar.timer

timer list check

$ systemctl list-timers
NEXT                         LEFT          LAST                         PASSED       UNIT                         ACTIVATES
Sun 2020-02-09 00:02:35 KST  1s left       Sun 2020-02-09 00:02:30 KST  2s ago       on-calendar.timer            on-calendar.service

Example result

$ cat /tmp/OnCalendarLog.txt
Sun Feb  9 00:02:10 KST 2020
Sun Feb  9 00:02:15 KST 2020
Sun Feb  9 00:02:20 KST 2020
Sun Feb  9 00:02:25 KST 2020
Sun Feb  9 00:02:30 KST 2020


Reference

AWS CLI를 통해서 EC2 인스턴스를 생성, 나열 그리고 삭제를 해보자.


환경

  • Ubuntu 18.04
  • AWS CLI
  • Bash shell(/bin/bash)


과정

  1. AWS CLI 설치
  2. 기본 환경 설정(구성 및 자격 증명 설정)
  3. EC2 인스턴스 생성, 나열 그리고 삭제


AWS CLI 설치

패키지 업데이트 및 업그레이드

sudo apt-get update -y && sudo apt-get upgrade -y

pip3을 설치

sudo apt-get install python3-pip

AWS CLI 설치

  • aws 명령어를 인식하지 못하면 로그아웃하고 다시 로그인한다.
pip3 install awscli --upgrade --user

AWS CLI 버전 확인

$ aws --version
aws-cli/1.16.310 Python/3.6.9 Linux/4.15.0-72-generic botocore/1.13.46


기본 환경 설정(구성 및 자격 증명 설정)

사전 점검 사항

aws configure

$ aws configure
AWS Access Key ID [None]: [YOUR KEY]
AWS Secret Access Key [None]: [YOUR KEY]
Default region name [None]: ap-northeast-2
Default output format [None]: json

~/.aws/credentials 설정 확인

$ cat ~/.aws/credentials
[default]
aws_access_key_id = [YOUR KEY]
aws_secret_access_key = [YOUR KEY]

~/.aws/config 설정 확인

$ cat ~/.aws/config
[default]
region = ap-northeast-2
output = json


EC2 인스턴스 생성, 나열 그리고 삭제

사전 점검 사항

  • 만들어진 EC2 보안 그룹이 있다고 가정
  • 보안 그룹은 AWS에서 만들 수 있으며 테스트를 위해 만든 보안 그룹의 인바운드는 SSH 포트만 열고 아웃바운드는 모두 열어놓았다.

키 페어 생성

  • 아래 명령어로 만들어진 키 페어는 따로 보관
  • 기존에 있는 키 페어를 사용해도 무관하다. 단, 공개키는 AWS에 저장되어 있고 개인키는 보관하고 있어야 한다.
aws ec2 create-key-pair --key-name TestKeyPair --query 'KeyMaterial' --output text > TestKeyPair.pem

EC2 인스턴스 생성

  • --image-id: 인스턴스에 사용할 이미지 ID
  • ami-082bdb3b2d54d5a19: Ubuntu Server 16.04 LTS (HVM), SSD Volume Type
  • --count: 생성할 인스턴스의 수
  • --key-name: 사용할 키 페어의 키
  • TestKeyPair: 위에서 만든 키 페어
  • --security-group-ids: 보안그룹 ID
aws ec2 run-instances --image-id ami-082bdb3b2d54d5a19 --count 1 --instance-type t2.micro --key-name TestKeyPair --security-group-ids [YOUR SECURITY GROUP ID]

EC2 인스턴스 나열

  • --filters: 인스턴스들을 불러올 때 사용할 필터로 예제에서는 instance-typet2.micro인 인스턴스들만 가져옴
  • --query: 인스턴스들을 불러와서 보여줄때 사용할 수 있는 옵션으로 예제에서는 인스턴스들의 ID만 나열하도록함
aws ec2 describe-instances --filters "Name=instance-type,Values=t2.micro" --query "Reservations[].Instances[].InstanceId"

EC2 인스턴스 연결

  • 키 파일 권한 설정
chmod 400 TestKeyPair.pem
  • ssh를 이용해 인스턴스에 접속
ssh -i "TestKeyPair.pem" [USER NAME]@[PUBLIC IP or PUBLIC AWS DNS]

EC2 인스턴스 삭제

  • --instance-ids: 인스턴스 ID를 이용해 삭제
aws ec2 terminate-instances --instance-ids [YOUR INSTANCE ID]


참고자료