openstack ansible 모듈로 인스턴스를 생성해봤다.



서버와 vm 이름을 정의한 inventories 디렉토리의 ci 파일은 다음과 같다. 


[ci]


ci-master ansible_connection=ssh ansible_user=www  vm_name1=mytest-centos-vm1 vm_name2=mytest-centos-vm2 image=google-centos7 ansible_python_interpreter=/usr/bin/python





playbooks/proejct/ci.yml 파일은 다음과 같다. 2대의 vm을 생성한다. 


- name: CI 테스트

  hosts: ci

  environment:  "{{proxy_env}}"



  roles:

  - { role: create_vm, vm_name: "{{ hostvars['ci-master'].vm_name1 }}", image: "{{ hostvars['ci-master'].image }}" }

  - { role: create_vm, vm_name: "{{ hostvars['ci-master'].vm_name2 }}", image: "{{ hostvars['ci-master'].image }}" }



vm을 생성하는 roles/create_vm/task/main.yml 파일은 다음과 같다.


os_server 태스크를 사용한다 (https://docs.ansible.com/ansible/latest/modules/os_server_module.html  참고 )

---

- name: openstacksdk 라이브러리를 설티한다

  pip:

    name: openstacksdk

  sudo: yes


- name: 인스턴스를 생성한다

  os_server:

    state: present

    auth:

      auth_url: https://google-openstack-api.google.io:5000/v2.0/

      username: openstack

      password: xxxxx

      project_name: mytest

    name: "{{ vm_name }}"

    region_name: "az1"

    verify: false

    image: "{{ image }}"

#    key_name: openstack 키페어를 생성해서 추가해야 함

    availability_zone: Dev_Zone

    timeout: 200

    flavor: m1.large

    auto_ip: no

    security_groups: default

  register: instance

  

  

vm을 삭제하는 roles/delete_vm/task/main.yml 이다. 


---

- name: Delete an instance

  os_server:

    state: absent

    auth:

      auth_url: https://google-openstack-api.google.io:5000/v2.0/

      username: openstack

      password: xxxxx

      project_name: mytest

    name: "{{ vm_name }}"

    region_name: "az1"

    verify: false

    availability_zone: Dev_Zone

    timeout: 200

    flavor: m1.large

    auto_ip: no

    security_groups: default

  register: instance


Posted by '김용환'
,


python3 설치 여부 확인


$ yum search python3

설치할 만만하게 없다면 ius를 추가한다.


$ yum install -y https://centos7.iuscommunity.org/ius-release.rpm


Loaded plugins: fastestmirror


Cannot open: https://centos7.iuscommunity.org/ius-release.rpm. Skipping.


Error: Nothing to do


이럴 때는 rpm을 다운로드하고 바로 설치한다.


$ wget https://centos7.iuscommunity.org/ius-release.rpm --no-check-certificate


$ yum install -y ius-release.rpm


$ sudo yum install -y python36u python36u-libs python36u-devel python36u-pip


$ python3.6 -V

Python 3.6.4




python3로 실행될 수 있도록 링크를 변경한다. 


$ ls -l /bin/python*

lrwxrwxrwx. 1 root root     7  7월  3  2018 /bin/python -> python2

lrwxrwxrwx. 1 root root    14  7월  3  2018 /bin/python-config -> python2-config

lrwxrwxrwx. 1 root root     9  7월  3  2018 /bin/python2 -> python2.7

lrwxrwxrwx. 1 root root    16  7월  3  2018 /bin/python2-config -> python2.7-config

-rwxr-xr-x. 1 root root  7216  4월 11  2018 /bin/python2.7

-rwxr-xr-x. 1 root root  1835  4월 11  2018 /bin/python2.7-config

-rwxr-xr-x  2 root root 11384  5월  3 05:43 /bin/python3.6

lrwxrwxrwx  1 root root    26  7월 23 18:46 /bin/python3.6-config -> /usr/bin/python3.6m-config

-rwxr-xr-x  2 root root 11384  5월  3 05:43 /bin/python3.6m

-rwxr-xr-x  1 root root   173  5월  3 05:42 /bin/python3.6m-config

-rwxr-xr-x  1 root root  3435  5월  3 05:40 /bin/python3.6m-x86_64-config



$ sudo unlink /bin/python

$ sudo ln -s /bin/python3.6 /bin/python3

$ sudo ln -s /bin/python3.6 /bin/python

$ sudo ln -s /bin/pip3.6 /bin/pip

$ ls -l /bin/python*

lrwxrwxrwx  1 root root    14  7월 23 18:47 /bin/python -> /bin/python3.6

lrwxrwxrwx. 1 root root    14  7월  3  2018 /bin/python-config -> python2-config

lrwxrwxrwx. 1 root root     9  7월  3  2018 /bin/python2 -> python2.7

lrwxrwxrwx. 1 root root    16  7월  3  2018 /bin/python2-config -> python2.7-config

-rwxr-xr-x. 1 root root  7216  4월 11  2018 /bin/python2.7

-rwxr-xr-x. 1 root root  1835  4월 11  2018 /bin/python2.7-config

lrwxrwxrwx  1 root root    14  7월 23 18:47 /bin/python3 -> /bin/python3.6

-rwxr-xr-x  2 root root 11384  5월  3 05:43 /bin/python3.6

lrwxrwxrwx  1 root root    26  7월 23 18:46 /bin/python3.6-config -> /usr/bin/python3.6m-config

-rwxr-xr-x  2 root root 11384  5월  3 05:43 /bin/python3.6m

-rwxr-xr-x  1 root root   173  5월  3 05:42 /bin/python3.6m-config

-rwxr-xr-x  1 root root  3435  5월  3 05:40 /bin/python3.6m-x86_64-config



pip3를 설치한다.


$ wget https://bootstrap.pypa.io/get-pip.py


$ sudo -E python get-pip.py


$pip3 -V

pip 19.2 from /usr/lib/python3.6/site-packages/pip (python 3.6)





Posted by '김용환'
,


springboot에 swagger2를 적용하는 예제를 하나 만들었다.

https://github.com/knight76/springboot2-swagger2




* 버전

SpringBoot 2.1 

Swagger2 2.92 

Gradle 




Swagger Config 파일은 다음과 같다. 

@Configuration
@EnableSwagger2
public class SwaggerConfig {
	@Bean
	public Docket api(){
		return new Docket(DocumentationType.SWAGGER_2)
				.groupName("API")
				.select()
				.apis(and(RequestHandlerSelectors.basePackage("com.example.controller")))
				//.apis(RequestHandlerSelectors.any())
				.paths(PathSelectors.any())
		        .build()
				.apiInfo(apiEndPointsInfo());
	}

	public ApiInfo apiEndPointsInfo() {
		return new ApiInfoBuilder().title("Spring Boot REST API with Swagger2")
		                           .description("Language Management REST API")
		                           .contact(new Contact("knight76", "http://knight76.tistory.com", "knight76@gmail.com"))
		                           .license("Apache 2.0")
		                           .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
		                           .version("0.0.1-SNAPSHOT")
		                           .build();
	}
}




RestController의 (Get|Post|..)Mapping 앞에 붙이는 ApiOperation, ApiResponse를 참고한다.

	@ApiOperation(value = "View available cities", response = List.class)
	@ApiResponses(value = {
			@ApiResponse(code = 200, message = "Successfully retrieved list"),
			@ApiResponse(code = 401, message = "You are not authorized to view the resource"),
			@ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
			@ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
	})
	@GetMapping(value = "/cities")
	public List<City> getCities() {
		List<City> cities = cityService.findAll();
		return cities;
	}



중요한 부분은 warning 안보기 위한 gradle 설정이다. 


ext { swagger2Version = '2.9.2' oldSwagger2Version = '1.5.21' } ..

// not showing WARN i.s.m.p.AbstractSerializableParameter : Illegal DefaultValue -1 for parameter type integer // java.lang.NumberFormatException: For input string: "" implementation("io.springfox:springfox-swagger2:${swagger2Version}") { exclude group: 'io.swagger',module: 'swagger-annotations' exclude group: 'io.swagger',module: 'swagger-models' } implementation "io.swagger:swagger-annotations:${oldSwagger2Version}" implementation "io.swagger:swagger-models:${oldSwagger2Version}"


Posted by '김용환'
,



Intellij에서 lombok 셋팅은 귀찮은데, 

ntellij lombok 셋팅을 잘 설명한 블로그이다 짱!!!

http://blog.egstep.com/java/2018/01/12/intellij-lombok/



Posted by '김용환'
,


swagger2의 마지막 버전은 2.9.2로서, 최신 릴리즈로서 2018년에 릴리즈되었다. 더 이상 릴리즈는 없다. 


개발하다가 이런 에러를 만났는데..


NumberFormatException when ApiModelProperty not set [example] value

java.lang.NumberFormatException: For input string: ""



이 에러에 대한 해결책으로 github에서 제시하고 있다.

https://github.com/springfox/springfox/issues/2265#issuecomment-413286451



springfox 이슈는 아니고, 내부 라이브러리 이슈라 하는데. 

swagger2는 더이상 개발되고 있지 않다. 



그래서 아래와 같이 변경하면 에러는 발생하지 않는다. 

implementation("io.springfox:springfox-swagger2:${swagger2Version}") {
exclude group: 'io.swagger',module: 'swagger-annotations'
exclude group: 'io.swagger',module: 'swagger-models'
}
implementation "io.swagger:swagger-annotations:${oldSwagger2Version}"
implementation "io.swagger:swagger-models:${oldSwagger2Version}"
implementation "io.springfox:springfox-swagger-ui:${swagger2Version}"



Posted by '김용환'
,


도커 볼륨은 삭제하지 않는 한 계속 남아 있다. (정책상)



$ docker volume ls

DRIVER              VOLUME NAME

local               2a8456e072898c7c432c22278fda48424bd84ca5b721b63bc1c0afde3b9a65a8

local               4ec5997dc682da659e4579a271ea16cbf69feb19f13977d13dd70aa9d912c500

local               8f824c7f439708f695515bfc1998041ea660fd58825bed09d3a9b1ec5366a182

local               034ed523e602bd1158f0527278f60caf9dbaa14dbb299bd31e2e3e464ac06dd0


로컬 같은 경우는 한 번에 정리할 수 있는 prune  커맨드가 존재한다. 


$ docker volume prune




따라서 정리해서 삭제할 수 있다.


$ docker volume inspect 2a8456e072898c7c432c22278fda48424bd84ca5b721b63bc1c0afde3b9a65a8

[

    {

        "CreatedAt": "2019-07-18T05:23:17Z",

        "Driver": "local",

        "Labels": null,

        "Mountpoint": "/var/lib/docker/volumes/2a8456e072898c7c432c22278fda48424bd84ca5b721b63bc1c0afde3b9a65a8/_data",

        "Name": "2a8456e072898c7c432c22278fda48424bd84ca5b721b63bc1c0afde3b9a65a8",

        "Options": null,

        "Scope": "local"

    }

]


Posted by '김용환'
,


새로운 spring boot 프로젝트를 생성했을 때, 잘 데몬이 뜨는 것 같은데, 추가한 controller를 호출할 수 없다면 아마도 설정 문제일 것이다.


@SpringBootApplication을 선언한 클래스가 전체 소스를 포함하는 패키지 루트에 존재하는지 확인한다.


종종 나는 @SpringBootApplication을 선언한 클래스를 따로 두는 경향이 있는데, 이럴 때는 component scan을 사용해야 한다.


@ComponentScan("com.example.demo.controller")



아니면, RequestMapping이 빠졌는지 확인한다. 

Posted by '김용환'
,






개발자와 아키텍트, 데브옵스, 관리자를 위한 마이크로서비스 완벽 가이드!

1부에서 마이크로서비스라는 용어를 정의하고, 마이크로서비스 아키텍처는 마이크로(micro) 아키텍처와 매크로(macro) 아키텍처라는 두개의 레벨로 구성돼 있음을 설명한다. 레거시 시스템을 마이크로서비스로 마이그레이션하는 방법을 설명한다. 2부에서는 마이크로서비스를 구축할 수 있는 스택을 설명한다. 마이크로서비스를 구현할 때 사용할 수 있는 기술, 도커, 프론트 엔드의 통합, ESI, 비동기 및 통신, 아파치 카프카, Atom, 넷플릭스 스택, 컨설(Consul)과 아파치 httpd 서버, 쿠버네티스, PaaS를 클라우드 파운드리를 설명한다. 3부에서는 마이크로서비스를 지탱할 수 있는 운영을 설명한다. 많은 마이크로서비스를 안전하게 운영할 수 있는 운영의 기본 원칙과 마이크로서비스 운영이 어려운 이유를 설명한다. 모니터링 및 프로메테우스(Prometheus), 로그 데이터 분석을 위한 일래스틱 스택, 마이크로서비스 간의 호출을 추적하는 집킨(Zipkin)을 사용한다. 서비스 메시 기술인 이스티오(Istio)를 설명한다. 마지막에 마이크로서비스의 전망을 살펴본다. 예시는 스프링 부트와 스프링 클라우드, 도커를 기반으로 설명한다.



역자 : 김용환

알티캐스트, 네이버, 라인, SK Planet을 거쳐 현재 카카오에서 개발자로 일하고 있다. 이제 마흔네 살의 평범한 개발자로 다양한 도전에서 에너지를 얻으며, 개발과 실무 경험을 블로그(http://knight76.tistory.com)에 기록하고 있다. 

정보통신산업진흥원(NIPA) 산하의 소프트웨어공학포털에 개발 관련 내용을 공유했고, 여러 콘퍼런스와 세미나에서 그동안 쌓은 개발 지식을 발표하고 있다. 스스로에게는 물론 누군가에게 도움이 될 수 있다는 생각으로 번역을 시작했는데, 어느덧 15번째 책이다.


작가의 말

마이크로서비스(Microservice)는 최근 가장 중요한 소프트웨어 아키텍처 트렌드 중 하나다. 이미 지금까지 나온 마이크로서비스를 설명한 책이나 문서가 많이 있음에도 나는 마이크로서비스와 관련된 책을 출간했다. 왜 마이크로서비스에 관한 책이 필요할까? 

특정 아키텍처를 정의하는 것, 해당 아키텍처를 구현하는 것은 각기 다른 일이다. 이 책은 마이크로서비스 구현을 위한 기술을 제시하고 관련된 장점과 단점을 강조한다. 

이 책은 전체 마이크로서비스 시스템 기술에 대해 특별히 집중한다. 각 마이크로서비스는 서로 다른 기술을 사용해 구현될 수 있다. 그래서 개별 마이크로서비스에서 프레임워크를 선택하는 기술적인 결정은 전체 시스템 레벨의 결정만큼 중요하지 않다. 개별 마이크로서비스의 경우 프레임워크에 대한 결정을 쉽게 수정할 수 있다. 그러나 전체 시스템에 적용한 기술은 변경하기가 어렵다. 

이 책은 다른 마이크로서비스 책과 비교했을 때 주로 기술에 대해 이야기하며, 마이크로서비스에 대한 아키텍처와 왜 마이크로서비스가 사용되는지를 간단히 설명한다. 

각 레시피에는 구체적인 기술을 기반으로 하는 실행 가능한 예시가 있다. 예시는 개별적으로 실행할 수 있다. 예시는 다른 예시에 종속적이지 않아서, 업무와 관련 없는 예시는 건너 뛰고 각자에게 유용한 레시피를 볼 수 있도록 구성했다. 

이런 방법을 사용해서 관련 기술에 대한 개요를 얻을 수 있는 쉬운 접근 방법을 독자에게 제공하고 각자에게 적합한 기술 스택을 선택할 수 있게 했다. 책에서 제공하는 링크를 통해 관련 기술에 대한 깊이 있는 지식을 얻을 수 있다.




드뎌 번역하지 1년 만에 책이 나왔다.

2018년에 1판 번역을 진행/완료했는데, 올해 갑자기 2판이 나와 새로 업데이트 하니라 고생했다.

그래도 저자가 의도하는 바를 여러 날을 고민하기도 했고 상당히 놀랄 정도로 인사이트(Insight)가 있었다. 그 부분을 잘 보여주기 위해 많이 의역했다. 아마도 내가 번역한 책 중에 가장 많이 의역을 진행한 것 같다.(독일분이니 충분히 이해할 수 있다)

수 많은 개발 프로젝트가 산으로 가는 것은 코드, 정책, 문화가 균형있게 가기보다는 누군가의 탁월한 능력으로 한쪽으로 쏠리기 때문이다. 

이 책을 볼 때 코드, 정책, 문화 이렇게 3가지 관점으로 보면 좋을 것 같다. 고민하고 고생한 만큼 많은 도움이 되면 좋겠다.









Posted by '김용환'
,


Elasticsearch 를 인덱스, 데이터를 볼 수 있는 플로그인으로서 head보다 편하다..


https://github.com/appbaseio/dejavu




Posted by '김용환'
,


comm 커맨드를 실행하여 두 파일의 내용을 비교한다. 


$ cat > file.txt

1

2

$ cat > file2.txt


2


-1 매개 변수는 비교해서 첫번째 파일에만 있는 것은 출력하지 않는다. 

$ comm -1 file1.txt file2.txt


2


-2 매개 변수는 비교해서 두번째 파일에만 있는 것은 출력하지 않는다. 

$ comm -2 file1.txt file2.txt

1

2



-3 매개 변수는 비교해서 모두 존재하는 라인은 출력하지 않는다. 



$ comm -3 file1.txt file2.txt


1



comm 커맨드의 -3 매개 변수를 이용한 활용예시


$ comm -3 <(docker ps -a -q --filter=status=exited | sort)  <(docker ps -a -q --filter=exited=0 | sort) |  xargs --no-run-if-empty docker inspect 




Posted by '김용환'
,