클라우드 아키텍처 그림 그리는 툴


https://cloudcraft.co/app



1탭은 Design으로 그림을 그린다.


공유기능은 링크와 이미지만 있다. (visio처럼 xml로 나오지는 않는다.)


<링크>

https://cloudcraft.co/view/4d5731b7-7e14-43e2-b8e5-5b329a2bd6c3?key=3m40jn0enpfd2t90


<이미지>

https://cloudcraft.co/api/blueprint/4d5731b7-7e14-43e2-b8e5-5b329a2bd6c3/png?grid=true&transparent=false&width=1280&height=720






3탭의 예산 정보도 볼 수 있다.






2탭은 Live인데, 실제 그림 그리는대로 아마존 설계를 한다.


Welcome to Cloudcraft Live

Live mode allows you to link your real AWS infrastructure with your diagrams.


이 부분이 cloudcraft 회사가 창출하는 부분이다.




Posted by 김용환 '김용환'



docker 파일에서 java docker repository를 사용하려 할 때 다음을 참조할 수 있다. 


https://github.com/docker-library/repo-info/tree/master/repos/java/remote




예를 들어 docker 파일에 아래와 같이 사용한다면.


FROM java:openjdk-8-jdk-alpine


바로 아래 url의 docker 이미지를 사용하게 된다.


https://github.com/docker-library/repo-info/blob/master/repos/java/remote/openjdk-8-jdk-alpine.md



openjdk 8 111 버전을 사용하는 버전이다.. 


Posted by 김용환 '김용환'


오픈 스택의 overcommit 정보



https://docs.openstack.org/arch-design/design-compute/design-compute-overcommit.html




오픈 스택의 가상화 서버의 overcommit 기본 값은 다음과 같이 되어 있다.  가상 서버를 사용할 때 효율을 위해서 비율이 크다.


  • CPU allocation ratio: 16:1
  • RAM allocation ratio: 1.5:1



CPU allocation ratio가 16:1이라는 의미는 스케쥴러가 물리 코어 하나 당 16개의 가상 코어를 쓸 수 있도록 할당하겠다는 의미이다. 물리 서버가 12코어가 있다면.. 스케쥴러는 192개의 가상 코어를 사용할 수 있다. 인스턴스당 4 가상 코어를 쓰겠다고 하면.. 물리 서버의 192개중 48 인스턴스를 제공한다는 의미이다.


오픈 스택 문서를 보면 설명이 잘 나와 있다. 


OR
CPU overcommit ratio (virtual cores per physical core)
PC
Number of physical cores
VC
Number of virtual cores per instance

인스턴스 개수 = (OR*PC)/VC





https://inter6.github.io/2016/04/22/nova-overcommit/ 이 분의 글이 좋아서 발췌한다.



  • (Instance Count) = (Overcommit Ratio) * (Physical Cores) / (vCores per Instance)
  • (Overcommit Ratio) = (Instance Count) / (Physical Cores) * (vCores per Instance)



만약 인텔의 Hyper-Thread 기능을 사용할 경우, Mirantis에서는 총 코어 개수를 물리 코어 x 1.3 으로 계산할 것을 가이드한다.

다음 환경에서 오버커밋 비율로 생성해낼 수 있는 인스턴스 개수는 다음과 같다.

  • 인텔 E5-2640 v3 2.6Ghz 8Core x 2way
  • Hyper-Thread 활성화
  • 인스턴스당 평균 4개의 코어를 사용
Overcommit RatioInstance CountPhysical CoresvCores per Instance
15.220.84
210.420.84
420.820.84
841.620.84
1683.220.84



Posted by 김용환 '김용환'


Dockerfile에서  USER를 nobody로 설정해서. docker container를 띄워서 톰캣이 재시작되지 않는 버그를 발견했다.


centos, mac에서는 잘 동작하는데, ubuntu에서만 동작하지 못했다.


Permission denied.. 분명 권한이 있는데로 파일 생성을 어느 path에서는 할 수 있고, 어느 path에서는 할 수 없었다.



nobody@08678a6be7c9:/usr/local/tomcat$ ls -al
total 120
drwxr-sr-x 28 nobody nogroup  4096 Apr  9 15:32 .
drwxrwsr-x 23 root   staff    4096 Apr  9 15:32 ..
-rw-r-----  1 nobody nogroup 57092 Sep 28  2017 LICENSE
-rw-r-----  1 nobody nogroup  1723 Sep 28  2017 NOTICE
-rw-r-----  1 nobody nogroup  7064 Sep 28  2017 RELEASE-NOTES
-rw-r-----  1 nobody nogroup 15946 Sep 28  2017 RUNNING.txt
drwxr-x---  2 nobody nogroup  4096 Nov  8 19:45 bin
drwx--S---  2 nobody nogroup  4096 Apr  9 15:30 conf
drwxr-x---  2 nobody nogroup  4096 Nov  8 19:45 lib
drwxr-x---  2 nobody nogroup  4096 Sep 28  2017 logs
drwxr-x---  2 nobody nogroup  4096 Nov  8 19:45 temp
drwxr-x---  9 nobody nogroup  4096 Apr  9 15:32 webapps
drwxr-x---  2 nobody nogroup  4096 Sep 28  2017 work

nobody@08678a6be7c9:/usr/local/tomcat$ touch a
nobody@08678a6be7c9:/usr/local/tomcat$ ls a
-rw-r--r--  1 nobody nogroup     0 Apr  9 16:51 a


nobody@08678a6be7c9:/usr/local/tomcat/logs$ touch a
touch: cannot touch ‘a’: Permission denied


docker info를 통해 driver를 확인했다. 

mac은 overlay2를 사용하고 있고. centos는 overlay, ubuntu는 aufs를 사용하고 있었다.


aufs 정보는 다음과 같으며 https://docs.docker.com/storage/storagedriver/aufs-driver/..


docker 공식 문서에서는 더 이상 aufs를 사용하지 않고 overlay를 사용하라고 되어 있다.

https://docs.docker.com/storage/storagedriver/overlayfs-driver/





mesos, docker 장비에서 docker 파일 드라이버를 aufs로 overlay로 변경했다. 



로컬에 저장된 기존 도커 container 모두 중단 및 docker image 삭제한다.


$ docker rm $(docker ps -qa)

$ docker images

$ docker rmi ...




시스템 설정을 변경한다.



$ sudo -i

 

$ CONFIGURATION_FILE=$(systemctl show --property=FragmentPath docker | cut -f2 -d=)

#/etc/systemd/system/docker.service


$ cp $CONFIGURATION_FILE /etc/systemd/system/docker.service

 

$ perl -pi -e 's/^(ExecStart=.+)$/$1 -s overlay/' /etc/systemd/system/docker.service



$ cat > /etc/docker/daemon.json

{

    "storage-driver": "overlay"

}


$ service mesos-slave restart #메소스 사용중이라면.. 반드시.

$ service docker restart 



그리고.  $ docker info를 실행해 docker 기본 filer driver가 overlay인지 확인한다.

docker container를 실행한 후, docker insepect $container_id로 확인해서. overlay인지 확인한다.

정상적으로 잘 동작하면 ok










Posted by 김용환 '김용환'


fluentd에서 가장 까다로운 것이 로그를 정규표현식으로 분석하는 것이다.

잘못하면 로그가 drop될 수 있기 때문에.. 신중하게 써야 하는데.


헤로쿠의 다음 url에서 fluent의 정규 표현식을 테스트해볼 수 있다. 


http://fluentular.herokuapp.com/




예를 들어 다음 로그를


"192.168.6.118 - - [25/May/2014:23:44:21 +0000]  GET /images/templates/main/favicon_16_24_32.ico HTTP/1.1 \"200\" 1811 \"-\" \"test-domain.com\" test-domain.com \"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36\" \"-\" upstream_response_time 0.028 upstream_addr 192.168.6.7:8017 msec 1401061461.752 request_time 0.028"



다음과 같은 regex로 파싱할 수 있다. 


^(?<remote_addr>[^ ]*) - (?<remote_user>[^ ]*) \[(?<time>[^\]]*)\]\s+(?<request_type>[^ ]*) (?<request_url>[^ ]*) (?<request_http_protocol>[^ ]*) "(?<status>[^"]*)" (?<body_bytes_sent>[^ ]*) "(?<http_referer>[^"]*)" "(?<http_host>[^"]*)" (?<host>[^ ]*) "(?<http_user_agent>[^"]*)" "(?<http_x_forwarded_for>[^"]*)" upstream_response_time (?<upstream_response_time>[^ ]*) upstream_addr (?<upstream_addr>[^ ]*) msec (?<msec request_time>[^ ]*) request_time (?<request_time>[^ ]*)



url은 get으로 볼 수 있다.


http://fluentular.herokuapp.com/parse?regexp=%5E%28%3F%3Cremote_addr%3E%5B%5E+%5D*%29+-+%28%3F%3Cremote_user%3E%5B%5E+%5D*%29+%5C%5B%28%3F%3Ctime%3E%5B%5E%5C%5D%5D*%29%5C%5D%5Cs%2B%28%3F%3Crequest_type%3E%5B%5E+%5D*%29+%28%3F%3Crequest_url%3E%5B%5E+%5D*%29+%28%3F%3Crequest_http_protocol%3E%5B%5E+%5D*%29+%22%28%3F%3Cstatus%3E%5B%5E%22%5D*%29%22+%28%3F%3Cbody_bytes_sent%3E%5B%5E+%5D*%29+%22%28%3F%3Chttp_referer%3E%5B%5E%22%5D*%29%22+%22%28%3F%3Chttp_host%3E%5B%5E%22%5D*%29%22+%28%3F%3Chost%3E%5B%5E+%5D*%29+%22%28%3F%3Chttp_user_agent%3E%5B%5E%22%5D*%29%22+%22%28%3F%3Chttp_x_forwarded_for%3E%5B%5E%22%5D*%29%22+upstream_response_time+%28%3F%3Cupstream_response_time%3E%5B%5E+%5D*%29+upstream_addr+%28%3F%3Cupstream_addr%3E%5B%5E+%5D*%29+msec+%28%3F%3Cmsec+request_time%3E%5B%5E+%5D*%29+request_time+%28%3F%3Crequest_time%3E%5B%5E+%5D*%29&input=%22192.168.6.118+-+-+%5B25%2FMay%2F2014%3A23%3A44%3A21+%2B0000%5D++GET+%2Fimages%2Ftemplates%2Fmain%2Ffavicon_16_24_32.ico+HTTP%2F1.1+%5C%22200%5C%22+1811+%5C%22-%5C%22+%5C%22test-domain.com%5C%22+test-domain.com+%5C%22Mozilla%2F5.0+%28Windows+NT+6.3%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F35.0.1916.114+Safari%2F537.36%5C%22+%5C%22-%5C%22+upstream_response_time+0.028+upstream_addr+192.168.6.7%3A8017+msec+1401061461.752+request_time+0.028%22&time_format=






<source> 
  type tail 
  path /var/log/foo/bar.log 
  pos_file /var/log/td-agent/foo-bar.log.pos 
  tag foo.bar 
  format /^(?<remote_addr>[^ ]*) - (?<remote_user>[^ ]*) \[(?<time>[^\]]*)\]\s+(?<request_type>[^ ]*) (?<request_url>[^ ]*) (?<request_http_protocol>[^ ]*) "(?<status>[^"]*)" (?<body_bytes_sent>[^ ]*) "(?<http_referer>[^"]*)" "(?<http_host>[^"]*)" (?<host>[^ ]*) "(?<http_user_agent>[^"]*)" "(?<http_x_forwarded_for>[^"]*)" upstream_response_time (?<upstream_response_time>[^ ]*) upstream_addr (?<upstream_addr>[^ ]*) msec (?<msec request_time>[^ ]*) request_time (?<request_time>[^ ]*)/ 
</source>



Posted by 김용환 '김용환'

[fluentd] format json

Cloud 2018.04.10 18:20


아파치나 nginx로그를 fluentd로 전달하고 싶을 때 regex를 사용하는 것보다 format json을 사용하는 것이 좋다.


https://docs.fluentd.org/v0.12/articles/recipe-json-to-elasticsearch



<source>
  @type tail
  path /var/log/httpd-access.log #...or where you placed your Apache access log
  pos_file /var/log/td-agent/httpd-access.log.pos # This is where you record file position
  tag foobar.json #fluentd tag!
  format json # one JSON per line
  time_key time_field # optional; default = time
</source>


Posted by 김용환 '김용환'



openstack4j를 활용해 keystone 인증은 

http://www.openstack4j.com/learn/getting-started



openstack4j의 keystone 인증 방식(v2.0) 관련 예제는 다음과 같다. 



import org.openstack4j.api.OSClient.{OSClientV2, OSClientV3}

import org.openstack4j.core.transport.Config

import org.openstack4j.model.common.Identifier

import org.openstack4j.openstack.OSFactory



      val os: OSClientV2 = OSFactory.builderV2()

        .endpoint("https://internal.k8s.openstack.google.io:5000/v2.0")

        .credentials("sam","password")

        .tenantName("admin")

        .authenticate()


      println(os.getAccess.getToken)

      

     

결과



KeystoneToken{id=3a735957bd0c45d3b64242e0edd150cb, created=Wed Feb 07 20:51:37 KST 2018, expires=Thu Feb 08 11:51:37 KST 2018, tenant=KeystoneTenant{id=ae17dbd7165142808e074579360a8b9c, name=admin, description=NULL, enabled=true}}




v3 인증 방식(https://github.com/ContainX/openstack4j)을 사용하려면 여러 방식이 있다.

sing Identity V3 authentication you basically have 4 options:

(1) authenticate with project-scope

OSClientV3 os = OSFactory.builderV3()
                .endpoint("http://<fqdn>:5000/v3")
                .credentials("admin", "secret", Identifier.byId("user domain id"))
                .scopeToProject(Identifier.byId("project id"))
                .authenticate());

(2) authenticate with domain-scope

OSClientV3 os = OSFactory.builderV3()
                .endpoint("http://<fqdn>:5000/v3")
                .credentials("admin", "secret", Identifier.byId("user domain id"))
                .scopeToDomain(Identifier.byId("domain id"))
                .authenticate());

(3) authenticate unscoped

OSClientV3 os = OSFactory.builderV3()
                .endpoint("http://<fqdn>:5000/v3")
                .credentials("user id", "secret")
                .authenticate();

(4) authenticate with a token

OSClientV3 os = OSFactory.builderV3()
                .endpoint("http://<fqdn>:5000/v3")
                .token("token id")
                .scopeToProject(Identifier.byId("project id"))
                .authenticate());

실제로 아래와 같이 테스트해보면 안되기도 한다.


      val domainid = Identifier.byName("Default")


      val os: OSClientV3 = OSFactory.builderV3()

        .endpoint("https://internal.k8s.openstack.google.io:5000/v3")

        .credentials("sam","password",domainid)

        .scopeToDomain(domainid)

        .authenticate()


      OSFactory.enableHttpLoggingFilter(true)


      println(os.getToken)



인증만 할꺼라 json으로 파싱해서 보내는것이 나은 듯 하다.. ㄷ ㄷ 


예제의 도메인을 그대로 참조해서 

https://internal.k8s.openstack.google.io:5000/v3/auth/tokens 엔드 포인트에 다음 json을 body로 보낸다.


import play.api.libs.json._
val json: JsValue = Json.parse(s"""
{
"auth" : {
"identity": {
"methods": [ "password" ],
"password": {
"user": {
"name": "${userId}",
"domain": { "name" : "Default" },
"password": "${password}"
}
}
}
}
}
"""
)


post 결과는 다음과 같다. 


{  

   "token":{  

      "issued_at":"2018-02-07T20:42:58.000000Z",

      "audit_ids":[  

         "111123132"

      ],

      "methods":[  

         "password"

      ],

      "expires_at":"2018-02-08T20:42:58.000000Z",

      "user":{  

         "domain":{  

            "id":"default",

            "name":"Default"

         },

         "id":"1a1a1aasfdadf",

         "name":"sam"

      }

   }

}







Posted by 김용환 '김용환'


k8s의 로그 수집 툴은 fluentd 이다. 


https://github.com/GoogleCloudPlatform/k8s-stackdriver/tree/master/fluentd-gcp-image

Posted by 김용환 '김용환'




https://gravitational.com/blog/running-postgresql-on-kubernetes/

postgres를 그냥 k8s에서 운영했다가 데이터 손실되었다고 한다.

stateful(https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) 써서 HA를 유지하는 것이 좋다는 얘기가 있다. 


stateful은 중요하다.



Using StatefulSets

StatefulSets are valuable for applications that require one or more of the following.

  • Stable, unique network identifiers.
  • Stable, persistent storage.
  • Ordered, graceful deployment and scaling.
  • Ordered, graceful deletion and termination.
  • Ordered, automated rolling updates.

In the above, stable is synonymous with persistence across Pod (re)scheduling. If an application doesn’t require any stable identifiers or ordered deployment, deletion, or scaling, you should deploy your application with a controller that provides a set of stateless replicas. Controllers such as Deployment or ReplicaSet may be better suited to your stateless needs.

Limitations

  • StatefulSet was a beta resource prior to 1.9 and not available in any Kubernetes release prior to 1.5.
  • As with all alpha/beta resources, you can disable StatefulSet through the --runtime-config option passed to the apiserver.
  • The storage for a given Pod must either be provisioned by a PersistentVolume Provisioner based on the requested storage class, or pre-provisioned by an admin.
  • Deleting and/or scaling a StatefulSet down will not delete the volumes associated with the StatefulSet. This is done to ensure data safety, which is generally more valuable than an automatic purge of all related StatefulSet resources.
  • StatefulSets currently require a Headless Service to be responsible for the network identity of the Pods. You are responsible for creating this Service.





Posted by 김용환 '김용환'

fluent에는 fluent-plugin-forest(https://github.com/tagomoris/fluent-plugin-forest)라는 플러그인이 있다.


fluent 설정에 자주 보이는 편한 플러그인으로.. 


의미는 패턴화, 또는 그룹핑을 가능케 하는 표현식으로 보면 좋을 것 같다. 







특정 태그 명으로 반복되는 경우


<match service.blog>
  @type file
  time_slice_format %Y%m%d%H
  compress gz
  path /var/log/blog.*.log
</match>
<match service.portal>
  @type file
  time_slice_format %Y%m%d%H
  compress gz
  path /var/log/portal.*.log
</match>



아래와 같이 forest와 template을 같이 사용해 패턴화할 수 있다. 


<match service.*>
  @type forest
  subtype file
  remove_prefix service
  <template>
    time_slice_format %Y%m%d%H
    compress gz
    path /var/log/${tag}.*.log
  </template>
</match>





아래와 같은 패턴으로 로그가 들어오면..


아래와 같이 패턴화할 수 있다. 


<match bar.id.*>

    @type copy 

    <store> 

         type forest 

         subtype file_alternative 

         <template> 

             path /var/tmp/${tag_parts[2]}/rawdata.csv

         </template>

    </store>

</match>



참조 : https://qiita.com/yococo/items/8fa81747310e0a61808e




'Cloud' 카테고리의 다른 글

[k8s] 쿠버네티스의 로그 수집 툴  (0) 2018.02.06
[k8s] postgresql 운영 - stateful (펌질)  (0) 2018.01.25
[fluentd]의 fluent-plugin-forest(forest)  (0) 2018.01.22
[fluentd] filter/record에 예약어 존재  (0) 2017.12.18
NIFI의 provenance 의 drop event  (0) 2017.12.12
NIFI 팁  (0) 2017.12.08
Posted by 김용환 '김용환'