Opsworks agent error debugging

어느날 Prometheus alert이 와서 Portus 에 문제가 생겼음을 알렸습니다.

Prerequisite

  • AWS Opsworks chef12
  • ubuntu 16.04

디버깅

Disk Full

확인해보니 문제는

no space ….

이런 에러…

$ df -h 

로 보니 root가 disk full 입니다.

확인해보니 portus의 nginx 로그가 2GB 씩 stdout, stderr 두개….

로그 지우고 nginx 재시작으로 임시 해결..

AWS opsworks 의 agent 가 업데이트 될때 마침 디스크가 꽉 차있었나 봅니다…

용량 확보 후 재시작…

opsworks-agent-cli를 수동으로 실행해서 configure를 다시 실행시키는 것을 시도 합니다….

root@portus2:/var/lib/aws/opsworks/chef# opsworks-agent-cli run_command configure

결과는 에러…

Couldn't execute run_command: RuntimeError - Couldn't gather commands. RuntimeError - Could not parse /var/lib/aws/opsworks/chef/2018-08-28-10-28-23-01.json: JSON::ParserError - A JSON text must at least contain two octets! - /opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `initialize'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `new'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `parse'
/opt/aws/opsworks/current/lib/cli/base.rb:69:in `parse_json'
/opt/aws/opsworks/current/lib/cli/base.rb:17:in `block in gather_commands'
/opt/aws/opsworks/current/lib/cli/base.rb:16:in `each'
/opt/aws/opsworks/current/lib/cli/base.rb:16:in `gather_commands'
/opt/aws/opsworks/current/lib/cli/runner.rb:72:in `initialize'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `new'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `run'
/usr/sbin/opsworks-agent-cli:91:in `block (2 levels) in <main>'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `execute'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:296:in `block in call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:83:in `run'
/usr/sbin/opsworks-agent-cli:110:in `<main>' - /opt/aws/opsworks/current/lib/cli/base.rb:71:in `rescue in parse_json'
/opt/aws/opsworks/current/lib/cli/base.rb:69:in `parse_json'
/opt/aws/opsworks/current/lib/cli/base.rb:17:in `block in gather_commands'
/opt/aws/opsworks/current/lib/cli/base.rb:16:in `each'
/opt/aws/opsworks/current/lib/cli/base.rb:16:in `gather_commands'
/opt/aws/opsworks/current/lib/cli/runner.rb:72:in `initialize'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `new'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `run'
/usr/sbin/opsworks-agent-cli:91:in `block (2 levels) in <main>'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `execute'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:296:in `block in call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:83:in `run'
/usr/sbin/opsworks-agent-cli:110:in `<main>' - /opt/aws/opsworks/current/lib/cli/base.rb:33:in `rescue in gather_commands'
/opt/aws/opsworks/current/lib/cli/base.rb:15:in `gather_commands'
/opt/aws/opsworks/current/lib/cli/runner.rb:72:in `initialize'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `new'
/opt/aws/opsworks/current/lib/cli/runner.rb:50:in `run'
/usr/sbin/opsworks-agent-cli:91:in `block (2 levels) in <main>'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/command_support.rb:126:in `execute'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:296:in `block in call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:309:in `call_command'
/opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/gli-2.13.4/lib/gli/app_support.rb:83:in `run'
/usr/sbin/opsworks-agent-cli:110:in `<main>'

File check

파싱이 안된다고 합니다. 파일을 오픈 합니다.

$ vi /var/lib/aws/opsworks/chef/2018-08-28-10-28-23-01.json

파일이 비어있습니다… 이상합니다…

JSON 파일은 opsworks 의 리소스들의 정보가 모여있는 파일입니다. 파일 내용이 있어야하는데…. 아마도 용량문제로 파일을 쓰지 못한 듯 합니다.

/var/lib/aws/opsworks/chef 이 폴더로 들어가서 뭐하는 폴더인지 확인합니다.

Directory check

$ ll
root@portus2:/var/lib/aws/opsworks/chef# ll
total 2168
drwxr-xr-x 2 aws  aws    4096 Aug 29 11:28 ./
drwxr-x--- 6 aws  aws    4096 Aug 29 11:21 ../
-rw-r--r-- 1 aws  aws       0 May 10 03:44 2018-05-08-10-10-48-01.log.gz
-rw-r--r-- 1 aws  aws  102226 Jul 17 09:55 2018-07-17-09-55-08-01.log
-rw-r--r-- 1 aws  aws       0 Aug 28 10:24 2018-08-28-10-24-52-01.json
-rw-r--r-- 1 aws  aws       0 Aug 28 10:28 2018-08-28-10-28-23-01.json
-rw-r--r-- 1 aws  aws       0 Aug 28 16:20 2018-08-28-16-20-30-01.json
-rw-r--r-- 1 aws  aws  157625 Aug 28 16:31 2018-08-28-16-31-31-01.json
-rw-r--r-- 1 root root 105741 Aug 28 16:31 2018-08-28-16-31-31-01.log
-rw-r--r-- 1 aws  aws  157559 Aug 29 05:55. 2018-08-29-05-55-37-01.json
-rw-r--r-- 1 root root 102946 Aug 29 05:55 2018-08-29-05-55-37-01.log
-rw-r--r-- 1 aws  aws  157560 Aug 29 06:14 2018-08-29-06-14-17-01.json
-rw-r--r-- 1 root root 103341 Aug 29 06:14 2018-08-29-06-14-17-01.log
-rw-r--r-- 1 aws  aws  149311 Aug 29 11:04 2018-08-29-11-04-15-01.json
-rw-r--r-- 1 root root  98073 Aug 29 11:04 2018-08-29-11-04-15-01.log
-rw-r--r-- 1 aws  aws  157559 Aug 29 11:07 2018-08-29-11-07-52-01.json
-rw-r--r-- 1 root root 103340 Aug 29 11:07 2018-08-29-11-07-52-01.log
-rw-r--r-- 1 aws  aws  157558 Aug 29 11:11 2018-08-29-11-11-30-01.json
-rw-r--r-- 1 root root 103651 Aug 29 11:11 2018-08-29-11-11-30-01.log
-rw-r--r-- 1 aws  aws  157656 Aug 29 11:21 2018-08-29-11-21-38-01.json
-rw-r--r-- 1 root root 103648 Aug 29 11:21 2018-08-29-11-21-38-01.log
-rw-r--r-- 1 aws  aws  157670 Aug 29 11:24 2018-08-29-11-24-45-01.json
-rw-r--r-- 1 root root 100655 Aug 29 11:24 2018-08-29-11-24-45-01.log

빈 파일이 몇개 있습니다..

Removing empty files

뭔지 모르겠지만 비어서 parsing error 가 나는 듯 합니다.
과감히 빈 파일을 지워줍니다.

$> rm 2018-08-28-10-24-52-01.json

그리고 다시 위의 명령을 실행합니다.

뭔가 바뀔까요?

root@portus2:/var/lib/aws/opsworks/chef# opsworks-agent-cli run_command configure
Couldn't execute run_command: RuntimeError - Couldn't gather commands. RuntimeError - Could not parse /var/lib/aws/opsworks/chef/2018-08-28-10-28-23-01.json: JSON::ParserError - A JSON text must at least contain two octets! - /opt/aws/opsworks/current/vendor/bundle/ruby/2.2.0/gems/json-1.8.3/lib/json/common.rb:155:in `initialize'
...

그 뒤의 파일을 읽기 시도하다가 에러가 다시 발생했습니다.
이제 이상한 json 파일들을 전부 지워줍시다.

그리고 다시 agent 를 실행하면 정상동작하는 것을 볼 수 있습니다.

[2018-08-29T11:50:10+00:00] INFO: Processing directory[/etc/logrotate.d] action create (/var/chef/runs/5f5d34e2-e02f-4871-98b9-c842712610de/local-mode-cache/cache/cookbooks/logrotate/resources/app.rb line 60)
[2018-08-29T11:50:10+00:00] INFO: Processing template[/etc/logrotate.d/nginx] action create (/var/chef/runs/5f5d34e2-e02f-4871-98b9-c842712610de/local-mode-cache/cache/cookbooks/logrotate/resources/app.rb line 67)
[2018-08-29T11:50:10+00:00] INFO: HTTP Request Returned 404 Not Found: Object not found: chefzero://localhost:8889/nodes/portus2
[2018-08-29T11:50:10+00:00] INFO: Chef Run complete in 0.286619869 seconds
[2018-08-29T11:50:10+00:00] INFO: Running report handlers
[2018-08-29T11:50:10+00:00] INFO: Report handlers complete
[2018-08-29 11:50:10]  INFO [opsworks-agent(16252)]: Finished Chef run with exitcode 0

chef12 opsworks 실행

Chef-client 를 수동으로 실행하려면 아래와 같은 명령을 사용하면 가능합니다.

opsworks-agent-cli 실행 시 확인 가능

  1. 첫번째 chef-client 실행
# RUBYOPT="-E utf-8" /opt/aws/opsworks/current/bin/chef-client -j /var/lib/aws/opsworks/chef/2018-08-30-05-10-55-01.json -c /var/lib/aws/opsworks/client.internal.rb -o aws_opsworks_agent 2>&1
  1. 두번째 chef-client 실행
# RUBYOPT="-E utf-8" /opt/chef/bin/chef-client -j /var/chef/runs/fd1800b7-5b1e-4ec8-b7dd-3579f6c568c3/attribs.json -c /var/chef/runs/fd1800b7-5b1e-4ec8-b7dd-3579f6c568c3/client.rb  2>&1

위의 attribs.json 파일을 살펴보니…

{
  "region_project": "TEST",
  "region": "TEST01",
  ...
  ...
  "run_list": [
    "recipe[logrotate::nginx]"
  ]
}

run_list 로 제가 OpsWorks Stack 에서 execute_recipes 한 내용이 기록되어 있습니다.
logrotate 레시피를 추가해줬죠…

attribs.json 파일에 현재 실행할 명령들이 들어가는 구조로 보입니다.
필요하다면 run_list 에 명령을 변경해서 실행한다면 가능할 듯….

이상 opsworks-agent-cli 관련 디버깅 경험 이슈였습니다.

Rails spec + sidekiq 설정

Rails spec + sidekiq 설정

Rails 에서 rspecsidekiq를 사용 하는 중에 local machine 에서는 별 문제가 없었는데, Drone · Continuous Deliver에서 test 기능을 사용하는 중에 문제가 생겼습니다.

문제점

drone 에서 rspec 실행시 error 발생

`localhost:6379` connection error

해결

찾아보니 rspec 실행시 sidekiq에서 redis 접속을 시도하는 문제였습니다.

참고: Testing · mperham/sidekiq Wiki · GitHub

위 내용을 참고해서 rspec/rails_helper.rb 에 아래 두줄을 추가했습니다.

require 'sidekiq/testing'
Sidekiq::Testing.fake!

이제 정상적으로 rspecdrone 에서 동작하는 것을 확인 할 수 있습니다.

Font awesome 아이콘 정렬 문제

Font awesome 아이콘 정렬 문제

상황

현재 Bootstrap 4 를 사용해서 프로젝트를 진행 중입니다.
bootstrap 4는 버전이 beta 상태로 있지만 어차피 나중엔 쓸테니까 처음으로 시작하는 프로젝트는 모두 bootstrap 4 로 작성 중 입니다.

Bootstrap 4 에는 기존에 있던 Glyphicons 가 사라졌습니다.

링크 참조 Migrating to v4 · Bootstrap

그래서 기존 Glyphicons 를 사용하지 않고 아이콘 버튼을 만들기 위해 font awesome 을 사용하게 되었습니다.

GitHub – Justineo/vue-awesome: Awesome SVG icon component for Vue.js, built-in with Font Awesome icons.

설치하면 font-awesome 이 내장되어 있습니다.

글 작성일 현재 README 문구를 보면 버전을 확인 할 수 있습니다.

Vue-Awesome is built upon Font Awesome v4.5.0 and depends on Vue.js v2.0.1+.

문제점

Vue-awesome code using Pug

icon(name='archive')
span Zones

Font-awesome 에 있는 아이콘과 link를 생성해보면 아래 이미지와 같은 align 관련 문제점을 확인 할 수 있습니다.

http://blog.uniqbuild.co.kr/wp-content/uploads/2017/09/picture-bootstrap-noalign.png

해결

Icon inside bootstrap button · Issue #52 · Justineo/vue-awesome · GitHub
여기에서 보이는 것처럼 css 를 추가해 줍니다.

저는 .btn class 는 사용하지 않으므로 제외 했습니다.

.fa-icon {
    vertical-align: middle;
    margin-right: 0.5rem;
}

입력 후, 화면을 확인하시면 아래와 같이 아이콘이 정렬된 모습을 확인 할 수 있습니다.

http://blog.uniqbuild.co.kr/wp-content/uploads/2017/09/picture-bootstrap-align.png

Rails 5 lib folder 로딩이 안되는 문제

Rails 5 ‘lib’ folder autoload failure

Rails 5 에서 lib 폴더를 autoload path에 포함시키고 싶은데 아래 코드가 제대로 동작을 하지 않았습니다.

config.autoload_paths << Rails.root.join('lib')

첫 번째 방법

찾아보니 스택오버플로우에 아래와 같은 정보가 있습니다.

autoload – Rails 5: Load lib files in production – Stack Overflow

코드를 보면 initializer를 이용해서 rb 파일들을 읽어오도록 구현되어 있습니다.

이런식으로 원하는 코드들만 가져와도 될 듯합니다. 스타도 많이 받았습니다. ㅎㅎㅎㅎ

두번째 방법

Rails falls back on non-thread-safe autoloading even when eager_load is true · Issue #13142 · rails/rails · GitHub

위의 글을 보면 이 아저씨가 해결한 방법은 autoload 를 사용하지 않고 eager_load 를 사용하라고 합니다.

config/environments/production.rb 의 내용을 봅니다.

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

eager_load 가 기본 설정입니다.

config/application.rb 하단에 아래 내용을 추가합니다.

config.eager_load_paths << Rails.root.join('lib')

문제 없이 잘 동작합니다.

한글 깨지는 UTF8 문서에 BOM 추가

Add UTF-8 BOM

가끔 UTF-8문서에 한글이 들어가 있을 경우에 파일을 열면 한글이 깨져서 나올때가 있다.

이는 한글이 들어있는 UTF8로 인코딩된 파일에 BOM이 없어서 UTF8로 읽어야하는지를 몰라서 발생하는 현상이다. BOM이라는 놈이 직접 넣어주기엔 매번 귀찮다.

그래서 이렇게 웹에서 자바스크립트로 BOM을 넣어주도록 했다.

텍스트 파일에 간단히 BOM을 넣어주고 싶을 경우 이용하자.

 

Select a text file: