티스토리 뷰

728x90
반응형

서론

본 포스팅에서는 Kubernetes에서 Pod를 효과적으로 구성하기 위해 Flavor를 적용하는 방법에 대해 알아보겠습니다.

Public Cloud에서도 당연히 중요하겠지만, Private Cloud에서 아키텍처를 설계하는데 있어 가장 중요한 요소 중 하나는 바로 전산자원에 대한 설계입니다.

Private Cloud는 기존 Legacy System과 마찬가지로 제한된 자원안에서 최적의 클라우드 아키텍처를 설계해야 한다는 주요 목적이 있습니다.

본문

일반적으로 Flavor라 하면 CPU, MEMORY, DISK를 의미하며 업무 패턴과 빈도, 사용률에 따라 적절한 Resource를 Deployment에 적용하고 HPA, ReplicatSet 등에 의해 Pod의 복제수를 결정하는 등 명확한 자원 설계가 이루어져야 합니다.

Kubernetes Deployment에 Flavor 적용하기

deployment.yaml 파일에 다음과 같이 정의하여 반영할 수 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wildfly-deployment
  labels:
    app: wildfly
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wildfly
  template:
    metadata:
      labels:
        app: wildfly
    spec:
      containers:
      - name: wildfly
        image: 192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest
        resources:
          requests:
            cpu: "0.5"
            memory: "1Gi"
            ephemeral-storage: "5Gi"
          limits:
            cpu: "1"
            memory: "2Gi"
            ephemeral-storage: "10Gi"
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
      nodeSelector:
        key: worker
---
apiVersion: v1
kind: Service
metadata:
  name: wildfly
spec:
  selector:
    app: wildfly
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  type: ClusterIP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: wildfly-ingress
  namespace: default
spec:
  rules:
  - host: test.nrson.co.kr
    http:
      paths:
      - backend:
          serviceName: wildfly
          servicePort: 8080
        path: /

CPU, MEMORY, DISK의 경우 각각 requests와 limits를 설정할 수 있으며, 이는 최소 요구 사항(request)과 최대 요구 사항(limits)을 의미합니다.

Replicas의 경우 Deployment.yaml 파일의 replicas에 설정할 수 있습니다.

Replica는 Pods 기동 시 복제수를 의미하며, HPA는 임계치(cpu, mem)에 의해 동적으로 Pod가 증가, 감소 하도록 구성하는 것 입니다. HPA의 경우 HorizontalPodAutoscaler kind로 추가해야 합니다.

Deployment CPU, MEMORY 적용

- cpu는 core 단위로 할당합니다. (0.5, 1 등)

- memory는 byte 단위로 할당합니다. (Ei, Pi, Ti, Gi, Mi, Ki)

cpu나 memory의 limit 값을 초과할 경우 Pod가 Restart 되므로 이를 사전에 막기 위해 Kubernetes에서는 HPA(Horizontal Pod AutoScaler)를 적용하여 특정 임계치에 도달할 경우 Pod를 증가시켜 limit에 도달하지 않도록 방지하며, 부하를 분산하는 방식으로 오토스케일 아웃을 수행합니다.

이때 Scale Out 조건으로는 Request 값을 기준으로 모든 Pod의 평균이 임계치에 도달했을 경우 Auto Scale Out이 적용됩니다.

Deployment DISK 적용

- Local Ephemeral Volume 할당하기 위해서는 ephemeral-storage를 적용합니다. ephemeral-storage는 Pod 내부에서 "/" 파티션에만 적용 가능합니다.

Local Volume은 byte 단위로 할당합니다. (Ei, Pi, Ti, Gi, Mi, Ki)

적용된 Flavor 확인

아래는 Flavor를 deployment에 반영하기 전과 후의 describe 정보입니다.

[Flavor 정보 반영 전]

[root@kubemaster ~]# kubectl describe deployment wildfly-deployment

Name:                   wildfly-deployment

Namespace:              default

CreationTimestamp:      Sat, 28 Dec 2019 20:33:06 +0900

Labels:                 app=wildfly

Annotations:            deployment.kubernetes.io/revision: 8

Selector:               app=wildfly

Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:       app=wildfly

  Annotations:  kubectl.kubernetes.io/restartedAt: 2019-12-28T06:41:28-05:00

  Containers:

   wildfly:

    Image:        192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest

    Port:         8080/TCP

    Host Port:    0/TCP

    Environment:  

    Mounts:       

  Volumes:        

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Available      True    MinimumReplicasAvailable

  Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  

NewReplicaSet:   wildfly-deployment-5fcff44ddc (1/1 replicas created)

Events:          

 

[Flavor 정보 반영 후]

[root@kubemaster ~]# kubectl describe deployment wildfly-deployment

Name:                   wildfly-deployment

Namespace:              default

CreationTimestamp:      Sat, 28 Dec 2019 20:33:06 +0900

Labels:                 app=wildfly

Annotations:            deployment.kubernetes.io/revision: 10

Selector:               app=wildfly

Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:       app=wildfly

  Annotations:  kubectl.kubernetes.io/restartedAt: 2019-12-28T08:41:36-05:00

  Containers:

   wildfly:

    Image:      192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest

    Port:       8080/TCP

    Host Port:  0/TCP

    Limits:

      cpu:                1

      ephemeral-storage:  10Gi

      memory:             2Gi

    Requests:

      cpu:                500m

      ephemeral-storage:  5Gi

      memory:             1Gi

    Environment:          

    Mounts:               

  Volumes:                

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Available      True    MinimumReplicasAvailable

  Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  

NewReplicaSet:   wildfly-deployment-c75c786dd (1/1 replicas created)

Events:

  Type    Reason             Age                 From                   Message

  ----    ------             ----                ----                   -------

  Normal  ScalingReplicaSet  63s                 deployment-controller  Scaled up replica set wildfly-deployment-68d5df85c4 to 1

  Normal  ScalingReplicaSet  62s                 deployment-controller  Scaled down replica set wildfly-deployment-68d5df85c4 to 0

  Normal  ScalingReplicaSet  62s                 deployment-controller  Scaled up replica set wildfly-deployment-c75c786dd to 1

  Normal  ScalingReplicaSet  49s (x2 over 117m)  deployment-controller  Scaled down replica set wildfly-deployment-5fcff44ddc to 0

[root@kubemaster ~]#

위와 같이 Pod별 할당 할 Resource 정보가 등록되었습니다.

또한 하단과 같이 실제 Pod에 해당 Flavor가 적용된 것을 확인할 수 있습니다.

[root@kubemaster ~]# kubectl describe pods wildfly-deployment-c75c786dd-5k6xn

Name:         wildfly-deployment-c75c786dd-5k6xn

Namespace:    default

Priority:     0

Node:         kubeworker/192.168.56.103

Start Time:   Sat, 28 Dec 2019 22:41:48 +0900

Labels:       app=wildfly

              pod-template-hash=c75c786dd

Annotations:  kubectl.kubernetes.io/restartedAt: 2019-12-28T08:41:36-05:00

Status:       Running

IP:           10.233.104.22

IPs:

  IP:           10.233.104.22

Controlled By:  ReplicaSet/wildfly-deployment-c75c786dd

Containers:

  wildfly:

    Container ID:   docker://ed559eb7ecdf77b83f367c8e851f696df8109482dd51f46a24eebdd94872d587

    Image:          192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest

    Image ID:       docker-pullable://192.168.56.100:5000/middleware/wildfly/wildfly_custom_image@sha256:

570d48c7ab7cef1fc7bce8de8c607d80ab700ab05e6087c1bc5e217821683d50

    Port:           8080/TCP

    Host Port:      0/TCP

    State:          Running

      Started:      Sat, 28 Dec 2019 22:41:50 +0900

    Ready:          True

    Restart Count:  0

    Limits:

      cpu:                1

      ephemeral-storage:  10Gi

      memory:             2Gi

    Requests:

      cpu:                500m

      ephemeral-storage:  5Gi

      memory:             1Gi

    Environment:          

    Mounts:

      /var/run/secrets/kubernetes.io/serviceaccount from default-token-v6ddt (ro)

Conditions:

  Type              Status

  Initialized       True 

  Ready             True 

  ContainersReady   True 

  PodScheduled      True 

Volumes:

  default-token-v6ddt:

    Type:        Secret (a volume populated by a Secret)

    SecretName:  default-token-v6ddt

    Optional:    false

QoS Class:       Burstable

Node-Selectors:  key=worker

Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s

                 node.kubernetes.io/unreachable:NoExecute for 300s

Events:

  Type     Reason            Age                From                 Message

  ----     ------            ----               ----                 -------

  Warning  FailedScheduling  12m (x2 over 12m)  default-scheduler    0/2 nodes are available: 1 Insufficient memory, 1 node(s) didn't match node selector.

  Normal   Scheduled         12m                default-scheduler    Successfully assigned default/

wildfly-deployment-c75c786dd-5k6xn to kubeworker

  Normal   Pulling           12m                kubelet, kubeworker  Pulling image "192.168.56.100:5000/middleware/wildfly/

wildfly_custom_image:latest"

  Normal   Pulled            12m                kubelet, kubeworker  Successfully pulled image "192.168.56.100:5000/middleware/

wildfly/wildfly_custom_image:latest"

  Normal   Created           12m                kubelet, kubeworker  Created container wildfly

  Normal   Started           12m                kubelet, kubeworker  Started container wildfly

[root@kubemaster ~]# 

다음으로 Node에 해당 Flavor가 적용된 것도 확인할 수 있습니다.

[root@kubemaster ~]# kubectl describe nodes 
Name:               kubemaster 
Roles:              master 
Labels:             beta.kubernetes.io/arch=amd64 
                    beta.kubernetes.io/os=linux 
                    kubernetes.io/arch=amd64 
                    kubernetes.io/hostname=kubemaster 
                    kubernetes.io/os=linux 
                    node-role.kubernetes.io/master= 
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock 
                    node.alpha.kubernetes.io/ttl: 0 
                    volumes.kubernetes.io/controller-managed-attach-detach: true 
CreationTimestamp:  Wed, 25 Dec 2019 22:16:49 +0900 
...

...
  Namespace                  Name                                  CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE 
  ---------                  ----                                  ------------  ----------  ---------------  -------------  --- 
  kube-system                calico-node-nzwvv                     150m (8%)     300m (16%)  64M (2%)         500M (21%)     3d 
  kube-system                coredns-58687784f9-jshnf              100m (5%)     0 (0%)      70Mi (3%)        170Mi (7%)     3d 
  kube-system                dns-autoscaler-79599df498-fvddt       20m (1%)      0 (0%)      10Mi (0%)        0 (0%)         3d 
  kube-system                kube-apiserver-kubemaster             250m (13%)    0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                kube-controller-manager-kubemaster    200m (11%)    0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                kube-proxy-dm55b                      0 (0%)        0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                kube-scheduler-kubemaster             100m (5%)     0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                nodelocaldns-kjkd9                    100m (5%)     0 (0%)      70Mi (3%)        170Mi (7%)     3d 
Allocated resources: 
  (Total limits may be over 100 percent, i.e., overcommitted.) 
  Resource           Requests        Limits 
  --------           --------        ------ 
  cpu                920m (51%)      300m (16%) 
  memory             221286400 (9%)  856515840 (36%) 
  ephemeral-storage  0 (0%)          0 (0%) 
Events:               


Name:               kubeworker 
Roles:               
Labels:             beta.kubernetes.io/arch=amd64 
                    beta.kubernetes.io/os=linux 
                    key=worker 
                    kubernetes.io/arch=amd64 
                    kubernetes.io/hostname=kubeworker 
                    kubernetes.io/os=linux 
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock 
                    node.alpha.kubernetes.io/ttl: 0 
                    volumes.kubernetes.io/controller-managed-attach-detach: true 
CreationTimestamp:  Wed, 25 Dec 2019 22:17:47 +0900 
...

...
  Namespace                  Name                                         CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE 
  ---------                  ----                                         ------------  ----------  ---------------  -------------  --- 
  default                    wildfly-deployment-c75c786dd-5k6xn           500m (26%)    1 (52%)     1Gi (68%)        2Gi (137%)     15m 
  ingress-nginx              nginx-ingress-controller-6fbff54876-lsd4l    0 (0%)        0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                calico-kube-controllers-584dcf688b-qj7vb     30m (1%)      100m (5%)   64M (4%)         256M (16%)     3d 
  kube-system                calico-node-q254k                            150m (7%)     300m (15%)  64M (4%)         500M (31%)     3d 
  kube-system                coredns-58687784f9-z9gdk                     100m (5%)     0 (0%)      70Mi (4%)        170Mi (11%)    3d 
  kube-system                kube-proxy-l9zzx                             0 (0%)        0 (0%)      0 (0%)           0 (0%)         3d 
  kube-system                kubernetes-dashboard-556b9ff8f8-pkxw7        50m (2%)      100m (5%)   64M (4%)         256M (16%)     3d 
  kube-system                nginx-proxy-kubeworker                       25m (1%)      0 (0%)      32M (2%)         0 (0%)         3d 
  kube-system                nodelocaldns-j64jh                           100m (5%)     0 (0%)      70Mi (4%)        170Mi (11%)    3d 
Allocated resources: 
  (Total limits may be over 100 percent, i.e., overcommitted.) 
  Resource           Requests         Limits 
  --------           --------         ------ 
  cpu                955m (50%)       1500m (78%) 
  memory             1410686Ki (92%)  3515999488 (224%) 
  ephemeral-storage  5Gi (11%)        10Gi (23%) 
Events:               
[root@kubemaster ~]# 

Flavor 실시간 사용률 확인

다음으로 Flavor에 대한 요약 정보를 확인해 보겠습니다.

먼저 현재 Pod의 CPU, MEMORY 사용률입니다. (kubectl top pods)

[root@kubemaster ~]# kubectl top pods

NAME                                                                   CPU(cores)   MEMORY(bytes)   

wildfly-deployment-c75c786dd-5k6xn              15m                     254Mi

[root@kubemaster ~]#

할당된 Pod의 Resource 중 현재 사용률을 확인할 수 있습니다. -w 옵션으로 retry 할 수 있습니다.

다음으로 현재 Node의 CPU, MEMORY 사용률입니다. (kubectl top nodes)

[root@master1 ~]# kubectl top nodes

NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   

kubemaster     1265m            2%               7713Mi                   12%       

kubeworker     623m              1%               2661Mi                   1%             

[root@master1 ~]#

HPA(Horizontal Pod Autoscaler) 구성

다음으로 HPA 구성 방법입니다.

apiVersion: autoscaling/v2beta2

kind: HorizontalPodAutoscaler

metadata:

  name: wildfly-hpa  

spec:

  scaleTargetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: wildfly-deployment

  minReplicas: 2

  maxReplicas: 4

  metrics:

  - type: Resource

    resource:

      name: cpu

      target:

        type: Utilization

        averageUtilization: 80

wildfly-deployment에 대한 Replica를 min 2 ~ max 4로 설정하여 동적으로 관리합니다. 이는 CPU 사용률을 기반으로 Pods를 관리하며, Pod들의 CPU 사용률이 평균 80%를 넘어설 경우 Pod를 증가시키도록 구성합니다.

[root@kubemaster ~]# kubectl get hpa

NAME                  REFERENCE                                   TARGETS   MINPODS   MAXPODS   REPLICAS   AGE

wildfly-hpa            Deployment/wildfly-deployment       1%/80%             2                    4                     2            5s

[root@kubemaster ~]#

위 내용은 wildfly-hpa가 반영된 정보입니다. TARGETS는 CPU 사용률을 의미하며, 80%를 넘어설 경우 MINPODS에서 MAXPODS로 증가됩니다. REPLICAS는 현재 PODS의 수를 의미합니다.

 

# 80%의 기준은 CPU Request / Limit이 다를 경우 Request의 평균이 80%를 넘어설 경우를 의미함

모든 Pod의 사용률 평균이 80%를 넘어서야 증가함 (하나의 Pod가 넘어설 경우를 의미하지 않음)

[root@kubemaster deployment]# kubectl get pods

NAME                                 READY   STATUS    RESTARTS   AGE

wildfly-deployment-c75c786dd-5k6xn   1/1     Running   1          3d21h

wildfly-deployment-c75c786dd-nzq8p   1/1      Running   0          8m37s

[root@kubemaster deployment]# kubectl describe deployment wildfly-deployment

Name:                   wildfly-deployment

Namespace:              default

CreationTimestamp:      Sat, 28 Dec 2019 20:33:06 +0900

Labels:                 app=wildfly

Annotations:            deployment.kubernetes.io/revision: 10

Selector:               app=wildfly

Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:       app=wildfly

  Annotations:  kubectl.kubernetes.io/restartedAt: 2019-12-28T08:41:36-05:00

  Containers:

   wildfly:

    Image:      192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest

    Port:       8080/TCP

    Host Port:  0/TCP

    Limits:

      cpu:                1

      ephemeral-storage:  10Gi

      memory:             2Gi

    Requests:

      cpu:                500m

      ephemeral-storage:  5Gi

      memory:             1Gi

    Environment:          

    Mounts:               

  Volumes:                

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Progressing    True    NewReplicaSetAvailable

  Available      False   MinimumReplicasUnavailable

OldReplicaSets:  

NewReplicaSet:   wildfly-deployment-c75c786dd (2/2 replicas created)

Events:

  Type    Reason             Age    From                   Message

  ----    ------             ----   ----                   -------

  Normal  ScalingReplicaSet  8m43s  deployment-controller  Scaled up replica set wildfly-deployment-c75c786dd to 2

[root@kubemaster deployment]#

위와 같이 반영 정보를 확인할 수 있습니다.

결론

Private Cloud를 실제로 구축하면서 수많은 회의와 검토를 진행했지만, 전산자원은 사실 마지막에 마지막까지도 변경되고 변경되었던것 같습니다.

Legacy 환경과는 다르게 노드 별 분리된 전산자원이 아닌 노드를 공유하는 컨테이너들이 서로 중복되어 기동되어 많은 서비스들에 대한 총합과 분배를 고려해야 하며, 클라우드 환경이 안정성을 높여준다고는 하지만, SPOF(Single Point Of Failure)가 늘어나는 감도 없지않아 있고(Container를 기동하는 노드를 함께 사용하고, msa의 많은 echo system 요소들, Disk의 공유, Logging I/O, Network Traffic 등), 기존보다 고려해야 할 포인트가 늘어나고 Hop의 증가로 인한 성능 이슈 역시 고려해야하고, 구축하는 입장에서는 고려사항이 곱절이상 늘어난 느낌입니다.

물론 성공한 설계와 이행이 뒷바침된 클라우드 환경은 우리가 생각한 만큼 강력한 힘을 보여줄 것입니다.

 

#참고

Google Cloud Kubernetes Best Practise Resource Request and Limits

728x90
반응형