블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

[팁] 쿠버네티스 StatefulSet에서 Headless 서비스를 이용한 Pod discovery


조대협 (http://bcho.tistory.com)


statefulset에서 데이타베이스와 같이 master,slave 구조가 있는 서비스들의 경우에는 service를 통해서 로드밸런싱을 하지 않고, service 를 통해서 로드 밸런싱을 하는 것을 잘 사용하지 않고 개별 pod의 주소를 알고 접속해야 한다. 그래서 개별 Pod의 dns 이름이나 주소를 알아야 한다.


Pod들은 DNS이름을 가질 수 는 있으나, {pod name}.{service name}.{name space}.svc.cluster.local 식으로 이름을 가지기 때문에, pod 를 DNS를 이용해서 접근하려면 service name이 있어야 한다. 그러나 statefulset에 의한 서비스들은 앞에서 언급하였듯이 쿠버네티스 service를  이용해서 로드밸런싱을 하는 것이 아니기 때문에, 로드밸런서의 역할은 필요가 없고, 논리적으로, pod들을 묶어줄 수 있는 service만 있으면 되기 때문에 headless 서비스를 활용한다. Headless 서비스를 이용하면, service 가 로드 밸런서의 역할도 하지 않고, 단일 IP도 가지지 않지만, 아래 그림처럼 nslookup을 이용해서, headless 서비스에 의해서 묶여진 Pod들의 이름도 알 수 있고




{pod name}.{service name}.{name space}.svc.cluster.local  이름으로, 각 pod 에 대한 접근 주소 역시 얻을 수 있다.




본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

도커 컨테이너 보안 취약점 스캔 도구 Anchore

조대협 (http://bcho.tistory.com)


근래에 쿠버네티스를 로컬환경에서  이것저것 테스트하다보니, 클라우드에 있는 기능 보다 오픈 소스 기능을 많이 보게 되는데, 빌드 파이프라인을 보다가 재미있는 오픈소스를 하나 찾아서 정리해놓는다.


컨테이너 이미지에 대한 보안 문제

쿠버네티스와 같은 컨테이너 오케스트레이션 솔루션에서 가장 보안 취약이 있는 곳 중의 하나는 컨테이너 이미지 인데, 도커허브와 같이 널리 알려진 컨테이너 리파지토리에 저장되서 배포되는 이미지도 보안적으로 문제가 있는 이미지가 많다. 그래서, 가급적이면 벤더들에서 보안적으로 문제가 없도록 관리하는 베이스 이미지를 사용하는 것이 좋다. (구글에서 제공하는 도커 컨테이너 베이스 이미지 https://cloud.google.com/container-registry/docs/managed-base-images)

컨테이너 이미지 스캐닝 툴 (Anchore)

다음 방법으로는 컨테이너 이미지를 구울때마다 보안적인 문제가 없는지, 알려진 보안 취약점을 스캔해서 분석하는 방법인데, 이러한 도구를 vulnerability scaning 툴이라고 한다.

이런 툴중에 Anchore 라는 툴이 있는데, 상업 버전도 있지만 오픈 소스 버전이 있어서 손쉽게 사용이 가능하다. Anchore는 보안 CVE (Common Vulnerabilities and Exposures) 목록을 기반으로 해서 스캔하는데, CVE는 미정부에서 후원하는 National Cybersecurity FFRDC 에 의해서 관리된다.  

이외에도 몇개의 보안 취약점 정보를 몇군데서 가지고 오는데 (https://anchore.freshdesk.com/support/solutions/articles/36000020579-feeds)

재미있는 것은 NPM과 루비젬에 대한 보안 취약점 피드도 가지고 온다는 점이다.

  • Linux Distributions

    • Alpine Linux

    • CentOS

    • Debian

    • Oracle Linux

    • Red Hat Enterprise Linux

    • Ubuntu

  • Software Package Repositories

    • RubyGems.org

    • NPMJS.org

  • NIST National Vulnerability Database (NVD)


간단하게 들여다 보기

설치 및 사용 방법은 공식 홈페이지를 참고하면 되고, https://anchore.freshdesk.com/support/solutions/articles/36000020729-install-with-docker-compose 에는 docker-compose를 이용해서 간단하게 설치 및 사용하는 방법이 나와 있다. 아래는 공식 홈페이지의 내용을 참고해서 설명한 내용이다.


  1. 컨테이너 이미지를 anchore에 추가한다.
    다음 예제 명령은 dokcer
    % docker-compose exec anchore-engine anchore-cli --u admin --p foobar image add docker.io/library/debian:7

  2. anchore는 등록된 이미지를 자동으로 스캔한다.
    다음 명령어를 이용하면 스캔 상태를 모니터링 할 수 있다.
    % docker-compose exec anchore-engine anchore-cli --u admin --p foobar image get docker.io/library/debian:7 | grep 'Analysis Status'

  3. 스캔이 끝나면, 발견된 보안 취약점과 상세 내용을 확인할 수 있다.
    % docker-compose exec anchore-engine anchore-cli --u admin --p foobar image vuln docker.io/library/debian:7 all
    Vulnerability ID        Package                 Severity Fix Vulnerability URL                                                 
    CVE-2005-2541           tar-1.26+dfsg-0.1+deb7u1                 Negligible None https://security-tracker.debian.org/tracker/CVE-2005-2541         
    CVE-2007-5686           login-1:4.1.5.1-1+deb7u1                 Negligible None https://security-tracker.debian.org/tracker/CVE-2007-5686         
    CVE-2007-5686           passwd-1:4.1.5.1-1+deb7u1                Negligible None https://security-tracker.debian.org/tracker/CVE-2007-5686         
    CVE-2007-6755           libssl1.0.0-1.0.1t-1+deb7u4              Negligible None https://security-tracker.debian.org/tracker/CVE-2007-6755         
    ...
    ...
    ...

여기서 CVE-XXX 식으로 나오는 것이 보안 취약점이며, 자세한 내용은 뒤에 나오는 링크에서 확인이 가능하다.

CI/CD 파이프라인 통합

실제 개발/운영 환경에서 사용하려면, 커맨드 라인 뿐만 아니라 CI/CD 빌드 파이프라인에 통합을 해야 하는데, Anchore는 젠킨스 플러그인으로 제공되서 빌드 파이프라인에 쉽게 통합이 된다.

아래와 같은 개념으로 젠킨스에서 이미지를 빌드한 후에, 쿠버네티스나 기타 컨테이너 솔루션에 배포전에 보안 취약점을 스캔할 수 있다.


<그림. Anchore를 젠킨스 빌드 파이프라인에 추가 한 그림 >

출처 : https://anchore.com/opensource/


아래는 Anchore를 젠킨스 플러그인으로 설치한후에, 컨테이너 보안 취약점을 스캔한 결과를 출력해준 화면이다.




국내에는 아직 많이 알려지지 않은것 같은데, 젠킨스와 통합해서 사용한다면 꽤나 좋은 효과를 볼 수 있지 않을까 한다.

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

minikube에서 서비스 테스트 하기

미니쿠베를 로컬환경에 설치하고 쿠버네티스 서비스를 로드 밸런서 타입으로 배포하면, External IP할당이 되지 않는다. 그래서 아래 그림과 같이 External-IP가 계속 <pending>으로 보이게 된다.


NAME         TYPE  CLUSTER-IP  EXTERNAL-IP PORT(S)          AGE

kubernetes   ClusterIP  10.96.0.1  <none> 443/TCP          7d2h

my-service   LoadBalancer  10.105.173.146  <pending> 8080:31203/TCP   4m10s


그러면 미니쿠베에서 서비스를 테스트하려면 어떻게 해야 할까? 미니쿠베는 서비스를 테스트하기 위해서 service라는 명령을 제공한다. 아래 그림과 같이 minikube service {쿠버네티스 서비스명} 을 입력하면, 로컬 브라우져에서 해당 서비스를 접속할 수 있도록 해준다.


% minikube service my-service

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

요즘 쿠버네티스를 로컬환경에서 이것 저것 테스트하고 있는데, 실행 방법은 다음과 같다.  

환경은 minikube를 인스톨하였다. (0.33.1 버전)


sudo -E minikube start --vm-driver=none --extra-config=kubelet.resolv-conf=/run/systemd/resolve/resolv.conf


쿠버네티스를 우분투에서 실행할때, 별도의 Virtual Machine 없이 실행이 가능하다. VM 없이 실행하려면 --vm-driver=none 옵션을 줘야 한다. 이때, Local DNS Pod 가 기동될때 문제가 생기는데, 이를 해결하기 위해서 --extra-config=kubelet.resolv-conf=/run/systemd/resolve/resolv.conf 옵션을 주면된다.


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

StatefulSet을 이용하여 상태가 유지되는 Pod 관리하기

조대협 (http://bcho.tistory.com)

ReplicaSet으로 Stateful Pod 관리하기

앞에서 쿠버네티스의 Pod를 관리하기 위한 여러가지 컨트롤러 (Replica Set, ReplicationController,Job 등)에 대해서 알아보았다.

이런 컨트롤러들은 상태가 유지되지 않는 애플리케이션(Stateless application)을 관리하기 위해 사용된다. Pod가 수시로 리스타트되어도 되고, Pod 내의 디스크 내용이 리스타트되어 유실되는 경우라도 문제가 없는 워크로드 형태이다. 웹서버나 웹애플리케이션 서버 (WAS)등이 그에 해당한다. 그러나 RDBMS나 NoSQL과 같은  분산 데이타 베이스등과 같이 디스크에 데이타가 유지 되어야 하는 상태가 유지되는 애플리케이션 (Stateful application)은 기존의 컨트롤러로 지원하기가 어렵다.

ReplicaSet (이하 RS)를 이용하여 데이타 베이스 Pod를 관리하게 되면 여러가지 문제가 발생한다.

Pod의 이름

RS 등, Stateless Pod를 관리하는 컨트롤러에 의해서 관리되는 Pod들의 이름은 아래 그림과 같이 그 이름이 불 규칙적으로 지정된다.



마스터/슬레이브 구조를 가지는 데이타 베이스등에서 마스터 서버의 이름을 특정 이름으로 지정할 수 가 없다.

Pod의 기동 순서

RS에 의해서 관리되는 Pod들은 기동이 될때 병렬로 동시에 기동이 된다. 그러나 데이타베이스의 경우에는 마스터 노드가 기동된 다음에, 슬레이브 노드가 순차적으로 기동되어야 하는 순차성을 가지고 있는 경우가 있다.

볼륨 마운트

Pod에 볼륨을 마운트 하려면, Pod는 PersistentVolume (이하 PV)를 PersistentVolumeClaim(이하 PVC)로 연결해서 정의해야 한다.

RS등의 컨트롤러를 사용해서 Pod를 정의하게 되면, Pod 템플릿에 의해서 PVC와 PV를 정의하게 되기 때문에, 여러개의 Pod들에 대해서 아래 그림과 같이 하나의 PVC와 PV만 정의가 된다. RS의 Pod 템플릿에 의해 정의된 Pod들은 하나의 PVC와 연결을 시도 하는데, 맨 처음 생성된 Pod가 이 PVC와 PV에 연결이 되기 때문에 뒤에 생성되는 Pod들은 PVC를 얻지 못해서 디스크를 사용할 수 없게 된다.   


아래 YAML 파일은 위의 내용을 테스트 하기 위해서 작성한 파일이다.


apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: helloweb-disk

spec:

accessModes:

  - ReadWriteOnce

resources:

  requests:

    storage: 30Gi

---

apiVersion: v1

kind: ReplicationController

metadata:

name: nginx

spec:

replicas: 3

selector:

  app: nginx

template:

  metadata:

    name: nginx

    labels:

      app: nginx

  spec:

    containers:

    - name: nginx

      image: nginx:1.7.9

      volumeMounts:

      - name: nginx-data

        mountPath: /data/redis

      ports:

      - containerPort: 8090

    volumes:

    - name: nginx-data

      persistentVolumeClaim:

        claimName: helloweb-disk



nginx Pod를 RC를 이용하여 3개를 만들도록 하고, nginx-data 라는 볼륨을 helloweb-disk라는 PVC를 이용해서 마운트 하는 YAML 설정이다. 이 설정을 실행해보면 아래 그림과 같이 nginx-2784n Pod 하나만 생성된다.




%kubectl describe pod nginx-6w9xf

명령을 이용해서 다른 Pod가 기동되지 않는 이유를 조회해보면 다음과 같은 결과를 얻을 수 있다.



내용중에 중요한 내용을 보면 다음과 같다.


“Multi-Attach error for volume "pvc-d930bfcb-2ec0-11e9-8d43-42010a920009" Volume is already used by pod(s) nginx-2784n”


앞에서 설명한 대로, 볼륨(PV)이 다른 Pod (nginx-2784n)에 의해 이미 사용되고 있기 때문에 볼륨을 사용할 수 없고, 이로 인해서, Pod 생성이 되지 않고 있는 상황이다.


RS로 이를 해결 하려면 아래 그림과 같이 Pod 마다 각각 RS을 정의하고, Pod마다 각기 다른 PVC와 PV를 바인딩하도록 설정해야 한다.



그러나 이렇게 Pod 마다 별도로 RS와 PVC,PV를 정의하는 것은 편의성 면에서 쉽지 않다.

StatefulSet

그래서 상태를 유지하는 데이타베이스와 같은 애플리케이션을 관리하기 위한 컨트롤러가 StatefulSet 컨트롤러이다. (StatefulSet은 쿠버네티스 1.9 버전 부터 정식 적용 되었다. )

StatefulSet은 앞에서 설명한 RS등의 Stateless 애플리케이션이 관리하는 컨트롤러로 할 수 없는 기능들을 제공한다. 대표적인 기능들은 다음과 같다.

Pod 이름에 대한 규칙성 부여

StatefulSet에 의해서 생성되는 Pod들의 이름은 규칙성을 띈다. 생성된 Pod들은 {Pod 이름}-{순번} 식으로 이름이 정해진다. 예를 들어 Pod 이름을 mysql 이라고 정의했으면, 이 StatefulSet에 의해 생성되는 Pod 명들은 mysql-0, mysql-1,mysql-2 … 가 된다.

배포시 순차적인 기동과 업데이트

또한 StatefulSet에 의해서 Pod가 생성될때, 동시에 모든 Pod를 생성하지 않고, 0,1,2,.. 순서대로 하나씩 Pod를 생성한다. 이러한 순차기동은 데이타베이스에서 마스터 노드가 기동된 후에, 슬레이브 노드가 기동되어야 하는 조건등에 유용하게 사용될 수 있다.

개별 Pod에 대한 디스크 볼륨 관리

RS 기반의 디스크 볼륨 관리의 문제는 하나의 컨트롤러로 여러개의 Pod에 대한 디스크를 각각 지정해서 관리할 수 없는 문제가 있었는데, StatefulSet의 경우 PVC (Persistent Volume Claim)을 템플릿 형태로 정의하여, Pod 마다 각각 PVC와 PV를 생성하여 관리할 수 있도록 한다.


그럼 StatefulSet 예제를 보자


apiVersion: apps/v1

kind: StatefulSet

metadata:

name: nginx

spec:

selector:

  matchLabels:

    app: nginx

serviceName: "nginx"

replicas: 3

template:

  metadata:

    labels:

      app: nginx

  spec:

    terminationGracePeriodSeconds: 10

    containers:

    - name: nginx

      image: k8s.gcr.io/nginx-slim:0.8

      ports:

      - containerPort: 80

        name: web

      volumeMounts:

      - name: www

        mountPath: /usr/share/nginx/html

volumeClaimTemplates:

- metadata:

    name: www

  spec:

    accessModes: [ "ReadWriteOnce" ]

    storageClassName: "standard"

    resources:

      requests:

        storage: 1Gi


RS나 RC와 크게 다른 부분은 없다. 차이점은 PVC를 volumeClaimTemplate에서 지정해서 Pod마다 PVC와 PV를 생성하도록 하는 부분이다. 위의 볼드처리한 부분


이 스크립트를 실행하면 아래와 같이 Pod가 배포 된다.



pod의 이름은 nginx-0,1,2,... 식으로 순차적으로 이름이 부여되고 부팅 순서도 0번 pod가 기동되고 나면 1번이 기동되고 다음 2번이 기동되는 식으로 순차적으로 기동된다.


template에 의해서 PVC가 생성되는데, 아래는 생성된 PVC 목록이다. 이름은 {StatefulSet}-{Pod명} 식으로 PVC가 생성이 된것을 확인할 수 있다.


그리고 마지막으로 아래는 PVC에 의해서 생성된 PV(디스크 볼륨)이다.

기동 순서의 조작

위의 예제에 보는것과 같이, StatefulSet은 Pod를 생성할때 순차적으로 기동되고, 삭제할때도 순차적으로 (2→ 1 → 0 생성과 역순으로) 삭제한다. 그런데 만약 그런 요건이 필요 없이 전체가 같이 기동되도 된다면 .spec.podManagementPolicy 를 통해서 설정할 수 있다.

.spec.podManagementPolicy 는 디폴트로 OrderedReady 설정이 되어 있고, Pod가 순차적으로 기동되도록 설정이 되어 있고, 병렬로 동시에 모든 Pod를 기동하고자 하면  Parallel 을 사용하면 된다.

아래는 위의 예제에서 podManagementPolicy를 Parallel로 바꾼 예제이다.

apiVersion: apps/v1

kind: StatefulSet

metadata:

name: nginx

spec:

selector:

  matchLabels:

    app: nginx

serviceName: "nginx"

podManagementPolicy: Parallel

replicas: 3

template:

  metadata:

    labels:

      app: nginx

  spec:

    terminationGracePeriodSeconds: 10

    containers:

:

Pod Scale out and in

지금까지 StatefulSet에 대한 개념과 간단한 사용방법에 대해서 알아보았다. 그러면, StatefulSet에 의해 관리되는 Pod가 장애로 인하거나 스케일링 (In/out)으로 인해서 Pod의 수가 늘거나 줄면 그에 연결되는 디스크 볼륨은 어떻게 될까?


예를 들어 아래 그림과 같이 Pod-1,2,3 이 기동되고 있고, 이 Pod들은 StatefulSet에 의해서 관리되고 있다고 가정하자. Pod들은 각각 디스크 볼륨 PV-1,2,3 을 마운트해서 사용하고 있다고 하자.



이때, Pod-3가 스케일인이 되서, 없어지게 되면, Pod는 없어지지면, 디스크 볼륨을 관리하기 위한 PVC-3는 유지 된다. 이는 Pod 가 비정상적으로 종료되었을때 디스크 볼륨의 내용을 유실 없이 유지할 수 있게 해주고, 오토 스케일링이나 메뉴얼로 Pod를 삭제했을때도 동일하게 디스크 볼륨의 내용을 유지하도록 해준다.



그러면 없앴던 Pod가 다시 생성되면 어떻게 될까? Pod가 다시 생성되면, Pod 순서에 맞는 번호로 다시 생성이 되고, 그 번호에 맞는 PVC 볼륨이 그대로 붙게 되서, 다시 Pod 가 생성되어도 기존의 디스크 볼륨을 그대로 유지할 수 있다.



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.


PodDisruptionBudget

조대협 (http://bcho.tistory.com)


Pod의 개수는 컨트롤러가 붙어 있을 경우에는 컨트롤러 스펙에 정의된 replica 수 만큼을 항상 유지 하도록 되어 있다. Pod의 수가 replica의 수를 유지 하지 못하고 줄어드는 경우가 있는데, 애플리케이션이 크래쉬 나거나, VM이 다운되는 등의 예상하지 못한 사고로 인한 경우가 있고, 또는 시스템 관리자가 업그레이드등의 이슈로 노드를 인위적으로 다운 시키는 것과 같이 예상 가능한 상황이 있다.

예상 가능한 상황에서 Pod가 없어지는 것을 Voluntary disruptions 라고 하고, 커널 패닉이나 VM 크래쉬같은 예기치 못한 상황에서 Pod가 없어지는 것을 Involuntary disruptions 라고 한다.


노드를 인위적으로 줄일 경우(Voluntary disruptions) 그 노드에 Pod가 여러개 돌고 있을 경우 순간적으로 Pod의 수가 줄어들 수 있다. 예를 들어 웹 서버 Pod가 노드1에 5개, 노드 2에 8개가 돌고 있을 때 노드1을 다운 시키면 순간적으로 Pod의 총 수가 8개가 된다. replica수에 의해서 복귀는 되겠지만, 성능을 유지하기 위해서 일정 수의 Pod 수를 유지해야 하거나, NoSQL 처럼 데이타 저장에 대한 안정성을 확보하기 위해서 쿼럼값만큼  최소 Pod를 유지해야 하는 경우 , 이런 노드 다운은 문제가 될 수 있다.


그래서 인위적인 노드 다운등과 같이 volutary disruption 상황에도 항상 최소한의 Pod수를 유지하도록 해주는 것이 PodDistruptionBudget (이하 PDB)이라는 기능이다.  PDB를 설정하면 관리자가 노드 업그레이드를 위해서 노드를 다운 시키거나 또는 오토스케일러에 의해서 노드가 다운될 경우, Pod수를 일정 수 를 유지하지 못하면 노드 다운이나 오토스케일러에 의한 스케일 다운등을 막고, Pod 수를 일정 수준으로 유지할 수 있을때 다시 그 동작을 하도록 한다.


예를 들어 nginx-pod가 2개가 유지되도록 PDB를 설정했다고 가정하자


node-1

node-2

node-3

nginx-pod-1

nginx-pod-2

nginx-pod-3


위와 같은 상태에서 시스템 관리자가 node-1에 대한 패치를 위해서 node-1을 다운 시키려고 node draining 명령을 실행했다고 하자. 그럼 node-1에 있는 nginx-pod-1은 다른 node로 옮겨진다.(이를 eviction이라고 한다. ) 구체적으로는 nginx-pod-1 은 terminate 되고, node-2나 node-3에 새로운 pod가 생기게 된다. 여기서는 node-2에 nginx-pod-4라는 이름으로 새로운 pod가 생성된다고 가정하자


node-1 (draining)

node-2

node-3

nginx-pod-1(terminating)

nginx-pod-2

nginx-pod-4 (starting)

nginx-pod-3


이때 마음급한 관리자가 nginx-pod-4가 기동되는 것을 기다리지 않고, node-2를 패치하기 위해서 node-3 를 다운 시키려고 draining 명령을 내렸다고 하자.

이 경우 nginx-pod-4가 아직 기동중인 상태이기 때문에, 현재 사용 가능한 pod는 nginx-pod-2 와 nginx-pod-3 2개 뿐인데, node-3를 다운 시키면 nginx-pod-2 하나 밖에 남지 않기 때문에, PDB에서 정의한 pod의 개수 2개를 충족하지 못하기 때문에, node-3에 대한 다운 작업은 블록 된다.


PDB는 YAML 파일을 이용해서 리소스로 정의될 수 있다.

PDB에서 정의 하는 방법은 minAvailable 정의할 경우 앞의 예제에서 설명한 바와 같이 최소한 유지해야 하는 Pod의 수를 정의할 수 있고 또는 maxUnavailable 을 정의해서 최대로 허용할 수 있는 Unhealthy한 Pod 의 수를 정의할 수 있다. 이 두 값은 Pod의 숫자로 정의할 수 도 있고 또는 %를 사용할 수 있다.


예를 들어

  • minAvailable 가 5이면, 최소한 5개의 Pod 는 항상 정상 상태로 유지하도록 한다.

  • minAvailable 가 10%이면,  Pod의 replica 수를 기준으로 10%의 Pod 는 항상 정상 상태로 유지하도록 한다.

  • maxUnavailable 가 1이면, 최대 한개의 Pod만 비정상 상태를 허용하도록 한다.


그러면 이렇게 정의한 값들은 어떻게 Pod에 적용할까, PDB를 만든후에, 이 PDB안에 label selector를 정의해서 PDB를 적용할 Pod를 선택할 수 있다.


완성된 예제는 다음과 같다.

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
 name: zk-pdb
spec:
 minAvailable: 2
 selector:
   matchLabels:
     app: zookeeper


< 출처 : https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget >


이 예제는 app: zookeeper라고 되어 있는 Pod 들을 최소 2개는 항상 유지할 수 있도록 하는 설정이다.

지금까지 간단하게 PDB에 대한 개념을 설명하였다. 일반적인 Stateless 애플리케이션에는 크게 문제가 없겠지만, 일정 성능 이상을 요하는 애플리케이션이나, NoSQL과 같은 일정 수의 쿼럼 유지가 필요한 애플리케이션등의 경우에는 PDB를 정의하는 것이 좋다.


참고로 현재 PDB는 베타 상태이고 정식 릴리즈 상태는 아니기 때문에, 운영 환경에는 아직 사용하지 않는 것이 좋다.

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

PodPreset


애플리케이션을 배포하는데 있어서, 애플리케이션 실행 파일과과 설정 정보를 분리해서 환경에 따라 설정 정보만 변경해서 애플리케이션을 재배포하는 방법이 가장 효율적이다.  


쿠버네티스에서는 ConfigMap을 이용하여 이러한 정보를 환경 변수로 넘기거나, 또는 파일이나 디렉토리로 마운트하는 방법을 제공해왔다. ConfigMap을 이용하는 경우 ConfigMap에서 여러 정보를 꺼내오도록 해야 한다. 또한 반복적으로 유사한 애플리케이션을 배포하고자 할때, 디스크가 필요한 경우에는 볼륨과 그 마운트에 대한 정의를 해야하기 때문에, 애플리케이션을 배포하는 Pod의 설정 파일이 다소 복잡해질 수 있다.


그래서 새롭게 소개되는 개념이 PodPreset 이다.

PodPreset에는 환경 변수 이외에도, 볼륨과 볼륨 마운트 정보를 정의할 수 있다.

이렇게 정의된 PodPreset은 label selector를 통해서 적용할 Pod를 지정할 수 있다.

label selector에 의해서 지정된 Pod는 Pod가 생성될때, PodPreset에 지정된 정보가 추가되서 Pod가 생성된다.


이해가 잘 안될 수 있는데, 예제를 살펴보는게 가장 빠르다. 예제는 쿠버네티스 공식 홈페이지에 있는 예제를 사용하였다.

https://kubernetes.io/docs/tasks/inject-data-application/podpreset/#simple-pod-spec-example



아래는 PodPreset  예제이다.

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
 name: allow-database
spec:
 selector:
   matchLabels:
     role: frontend
 env:
   - name: DB_PORT
     value: "6379"
 volumeMounts:
   - mountPath: /cache
     name: cache-volume
 volumes:
   - name: cache-volume
     emptyDir: {}


env 부분에서 DB_PORT 환경 변수에  데이타 베이스 접속 포트를 정해주었고, /cache 디록토리에 emptyDir을 마운트 하도록 하는 설정이다. 이 PodPreset을 role: frontend 인 Pod 들에 적용하도록 하였다.


아래는 Pod 정의 예제이다.


apiVersion: v1
kind: Pod
metadata:
 name: website
 labels:
   app: website
   role: frontend
spec:
 containers:
   - name: website
     image: nginx
     ports:
       - containerPort: 80

내용을 보면 알겠지만, 간단하게 nginx 웹서버를 실행하는 Pod 설정 파일이다.

그런데 이 Pod를 배포하게 되면 앞에 PodPreset에서 Selector로 role:frontend 를 적용하도록 하였기 때문에, 이 Pod에는 앞에서 정의한 PodPreset이 적용되서 실제 배포 모양은 아래와 같이 된다.


apiVersion: v1
kind: Pod
metadata:
 name: website
 labels:
   app: website
   role: frontend
 annotations:
   podpreset.admission.kubernetes.io/podpreset-allow-database: "resource version"
spec:
 containers:
   - name: website
     image: nginx
     volumeMounts:
       - mountPath: /cache
         name: cache-volume
     ports:
       - containerPort: 80
     env:
       - name: DB_PORT
         value: "6379"
 volumes:
   - name: cache-volume
     emptyDir: {}


원래 Pod 설정 파일에 있는 내용에 추가해서 env, volumeMount, volumes 부분이 PodPreset에 정의된데로 추가 적용된것을 확인할 수 있다.


Configmap이 이미 있는데, 이런게 왜 필요할까 하고 잠깐 살펴봤는데, 편하다. 쿠버네티스에서 디스크 볼륨 설정이 그다지 간략하다고 말하기가 어렵고 그래서, 개발자 입장에서 애플리케이션을 간략하게 배포하고 싶은데, 디스크에 대한 설정을 해야 하는데, 이 부분을 모두 PodPreset에서 관리자가 해줄 수 있는 구조로 빠질 수 있다. 아직 알파단계 API이기 때문에 환경 정보와 볼륨 관련 정보만 지정하는데, 정식 버전에서는 좀 더 많은 설정 정보를 제공했으면 한다.



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

Kong API gateway

아키텍쳐 | 2019.02.07 23:11 | Posted by 조대협

Kong API gateway 간단 리뷰 노트 


요즘 MSA가 다시 올라오기 시작하고 있고, Kubernetes Istio 조합으로 좋은 아키텍쳐를 많이 그려낼 수 있게 되기 시작해서, API 게이트웨이를 다시 살펴보고 있는데, 시장에 API 게이트 웨이들은 대부분 인수가 된 상황이고, Kubernetes에서는 Ambassador가 올라오고 있는데, Istio 통합이나 Kubernetes 통합 기능은 강력하지만, 아직 신생 제품이라 기능이 그리 많이 않고, 보통 오픈 소스 대세는 Kong을 많이 이야기 하길래 쭈욱 살펴봤는데, 일단 CLI 명령이 거의 없고 제대로 이해한것이 맞다면, REST CALL로 설정을 잡아야 하고, Kubenetes 에 Ingress로 올라갈 수 도 있고, Istio 통합도 로드맵에는 있지만 아직은 완성전 단계..  설치 스크립트를 따라가 보니 Cassandra나 Postgres를 뒷단에 놓는것이 아마도 로그 수집 용도인것 같은데, 가볍게 사용하기에는 설정이 너무 무겁다. 

GUI 도구로는 지원 도구인 Konga가 있기는 하지만 UI를 봤을때 너무 단순하기도 하다. 

지켜보기는 하지만, 아직은 살짝 기다려야 하는 상태가 아닌가 싶다. 


참고 https://medium.com/@tselentispanagis/managing-microservices-and-apis-with-kong-and-konga-7d14568bb59d


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.