kubernetes max pods

Kubernetes 공식 문서에 따르면 기본 설정으로 노드 당 최대 110개의 파드를 생성할 수 있습니다. 이는 노드에서 파드의 IP를 할당하기 위해서입니다. IP 주소 자원은 한정되어 있기 때문에, 노드당 생성할 수 있는 파드 수를 제한하여 네트워크 충돌을 방지하고 안정적인 운영을 보장하고 있습니다.

 

아래 이미지는 Kubernetes 공식 문서에서 제시하는 기본값입니다.

  • 노드는 최대 110개의 파드
  • 클러스터는 최대 5000개의 노드
  • 클러스터는 최대 150000개의 파드
  • 클러스터는 최대 300000개의 컨테이너

 

kubernetes max pods 개수 수정

kubernetes 공식 문서에서 제공하는 기본 값을 사용하는 것을 권장하지만 그래도 상황에 따라 노드의 개수는 늘리지 못하지만 최대 파드의 개수가 더 필요한 경우가 있습니다. 이번 문서에서는 최대 파드의 개수를 수정하는 방법에 대해 알아보겠습니다.

 

현재 노드의 할당할 수 있는 파드의 개수 확인

$ kubectl get nodes -o=custom-columns=NODE:.metadata.name,MAXPODS:.status.capacity.pods
NODE      MAXPODS
master    110
worker1   110
worker2   110

 

해당 worker node kubelet 수정

먼저 worker node에 접속하여 sudo 권한을 부여하고 maxPods의 내용을 추가합니다.

vi /var/lib/kubelet/config.yaml
# 아래 내용 추가
maxPods: 250

 

worker node kubelet 재시작

sudo systemctl daemon-reload
sudo systemctl restart kubelet

 

결과 확인

$ kubectl get nodes -o=custom-columns=NODE:.metadata.name,MAXPODS:.status.capacity.pods
NODE      MAXPODS
master    110
worker1   250
worker2   250

 

 

참고 문서

https://kubernetes.io/docs/setup/best-practices/cluster-large/

https://github.com/kubernetes/kubernetes/issues/23349

 

Cruise Control

Strimzi는 LinkedIn에서 개발한 Cruise Control을 지원합니다. Cruise Control은 Kafka 클러스터의 성능 모니터링, 로드 밸런싱, 스케일링 및 장애 복구 등을 자동화하는 도구로, Kafka 클러스터의 운영을 크게 단순화하고 최적화합니다. Strimzi를 사용하면 Cruise Control을 Kafka 클러스터와 쉽게 통합하여 다음과 같은 기능을 활용할 수 있습니다.

로드 밸런싱
Cruise Control은 클러스터 전체의 워크로드 분포를 지속적으로 모니터링하고, 필요에 따라 파티션을 다시 분배하여 로드 밸런싱을 수행합니다. 이를 통해 리소스 사용률을 최적화하고, 클러스터의 처리량과 성능을 극대화할 수 있습니다.

Broker 추가 및 제거
클러스터의 워크로드 요구사항이 변경될 때, Cruise Control을 사용하면 Kafka 브로커를 자동으로 추가하거나 제거할 수 있습니다.

장애 복구
브로커 장애가 발생할 경우, Cruise Control은 자동으로 장애 복구 프로세스를 수행하여, 영향을 받은 파티션을 다른 브로커로 재할당합니다. 이는 클러스터의 가용성과 내구성을 유지하는 데 중요합니다.

 

위와 같이 Cruise Control에서는 여러가지 기능을 제공하지만 이번 문서 실습에서는 Broker의 추가 및 제거에 중점으로 실습을 진행하였습니다.

Cruise Control Goal

Cruise Control은 Kafka 클러스터의 최적화와 관리를 위해 다양한 목표(Goals)를 사용합니다. 목표는 goals, default.goals, hard.goals로 구분되어 있습니다. goals에서는 default.goals에서 사용할 목표를 정의합니다. default.goals은 Cruise Control의 작업 중에 기본적으로 사용되는 목표들의 집합을 정의하며 반드시 goals에 정의된 목표만 사용할 수 있습니다. hard.goals 설정은 반드시 만족해야 하는 목표들의 집합을 정의합니다. 이 목표들은 Cruise Control이 어떤 상황에서도 위반해서는 안 되는 필수 조건으로 작용합니다.

goals, default.goals, hard.goals 기본값

# goal 기본값
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.PotentialNwOutGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.TopicReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderBytesInDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.kafkaassigner.KafkaAssignerDiskUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.kafkaassigner.KafkaAssignerEvenRackAwareGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.PreferredLeaderElectionGoal

# default.goal 기본값
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.PotentialNwOutGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuUsageDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.TopicReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderReplicaDistributionGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderBytesInDistributionGoal

# hard.goal 기본값
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuCapacityGoal

goal 목표의 의미

# 클러스터의 복제본이 랙 고장에 대해 내성을 가지도록 보장합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal

# 랙을 고려하여 파티션의 복제본이 분산되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareDistributionGoal

# 브로커 당 최소한의 토픽 리더를 유지하여 리더 분포의 균형을 맞춥니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal

# 모든 브로커가 설정된 복제본 용량을 초과하지 않도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal

# 모든 브로커의 디스크 사용량이 설정된 임계값을 넘지 않도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal

# 네트워크 입력 용량의 임계값을 넘지 않도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal

# 네트워크 출력 용량의 임계값을 넘지 않도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal

# CPU 사용량이 설정된 임계값을 넘지 않도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuCapacityGoal

# 전체 클러스터에 걸쳐 복제본이 고르게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaDistributionGoal

# 네트워크 출력 잠재력을 기준으로 최적화를 수행합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.PotentialNwOutGoal

# 디스크 사용량이 브로커 간에 균일하게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskUsageDistributionGoal

# 네트워크 입력 사용량이 브로커 간에 균일하게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundUsageDistributionGoal

# 네트워크 출력 사용량이 브로커 간에 균일하게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundUsageDistributionGoal

# CPU 사용량이 브로커 간에 균일하게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.CpuUsageDistributionGoal

# 특정 토픽의 복제본이 클러스터에 걸쳐 고르게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.TopicReplicaDistributionGoal

# 리더 복제본이 브로커 간에 고르게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderReplicaDistributionGoal

# 리더 복제본의 입력 데이터가 브로커 간에 고르게 분포되도록 합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderBytesInDistributionGoal

# Kafka Assigner 도구와 유사한 방식으로 디스크 사용량을 최적화합니다.
com.linkedin.kafka.cruisecontrol.analyzer.kafkaassigner.KafkaAssignerDiskUsageDistributionGoal

# Kafka Assigner 도구와 유사한 방식으로 랙 인식 복제본 배치를 최적화합니다.
com.linkedin.kafka.cruisecontrol.analyzer.kafkaassigner.KafkaAssignerEvenRackAwareGoal

# 리더 복제본의 선출을 최적화하여 특정 조건에서 리더의 선출을 선호합니다.
com.linkedin.kafka.cruisecontrol.analyzer.goals.PreferredLeaderElectionGoal

Strimzi를 이용한 Cruise Control 배포

Strimzi에서는 Cruise Control를 배포하는 방법으로는 별도의 리소스를 정의하는 것이 아닌 kafkas.kafka.strimzi.io 리소스에 cruiseControl: {}를 정의하면 카프카 클러스터와 함께 Deployment 형식으로 배포됩니다.

---
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: kafka
  annotations:
    strimzi.io/node-pools: enabled
spec:
  kafka:
    version: 3.6.1
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: false
    readinessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    livenessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    config:
      default.replication.factor: 2
      min.insync.replicas: 1
      inter.broker.protocol.version: "3.6"
      num.partitions: 3
    resources:
      limits:
        cpu: 1
        memory: 1Gi
      requests:
        cpu: 500m
        memory: 1Gi
    logging:
      type: inline
      loggers:
        kafka.root.logger.level: INFO
        kafka.request.logger.level: INFO
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 1Gi
      deleteClaim: true
  entityOperator:
    topicOperator: {}
    userOperator: {}
  cruiseControl:
    config:
      default.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.TopicReplicaDistributionGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderReplicaDistributionGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.LeaderBytesInDistributionGoal
      hard.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.MinTopicLeadersPerBrokerGoal

Kafka 리소스를 생성하게 되면 zookeeper, kafka와는 다르게 Cruise Control은 Deployment 리소스로 배포됩니다.

KafkaRebalance

Strimzi에서 최적화 작업을 제안하기 위해서는 KafkaRebalance라는 리소스를 생성하는 것으로 제안을 할 수 있습니다. kafkaRebalance는 Cruise Control에 의해 제안을 확인하고 해당 제안을 적용하게 됩니다. KafkaRebalance로 제안할 수 있는 종류는 다음과 같습니다.

full 기본값

Cruise Control에 정의된 goal을 기반으로 클러스터의 모든 브로커에 rebalance를 수행합니다. KafkaRebalance의 기본값으로 KafkaRebalance에 아무런 정보를 기입하지 않으면 full 모드로 동작하지만 사용자는 KafkaRebalance 리소스를 생성할 때 mode 필드를 통해 리밸런싱의 모드를 직접 지정할 수 있습니다. full 모드를 명시적으로 지정하면, Cruise Control은 클러스터 전체에 대한 종합적인 리밸런싱 작업을 수행할 수 있습니다.

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: my-rebalance
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  mode: full

 

add-brokers

add-brokers 옵션은 Kafka 클러스터에 브로커를 추가할 때 사용되며, Cruise Control을 통해 이러한 작업을 자동화하고 최적화할 수 있습니다. Kafka 클러스터의 확장 과정에서 단순히 새로운 브로커를 추가하는 것만으로는 기존에 생성된 토픽의 파티션 복제본이 자동으로 새 브로커로 재할당되지 않습니다. 이 경우, 새 브로커는 앞으로 생성될 토픽의 파티션에만 사용될 수 있습니다.

add-brokers 옵션을 사용하여 Kafka 클러스터에 새로 추가된 브로커들에게 기존 토픽의 파티션 복제본을 자동으로 할당할 수 있습니다. 이는 클러스터의 리소스 사용을 최적화하고, 전체적인 부하 분산을 개선하는 데 도움이 됩니다. add-brokers 작업을 통해 새 브로커는 기존 토픽의 파티션 복제본을 할당받게 되며, 이는 클러스터의 부하를 보다 균등하게 분산시키고, 특정 브로커에 과부하가 집중되는 것을 방지합니다. 

파티션 복제본의 재할당 과정은 클러스터의 크기와 상태, 네트워크 속도 등에 따라 시간이 다소 소요될 수 있습니다.
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: my-rebalance
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  mode: add-brokers
  brokers: [2, 3]

remove-brokers

Kafka Cluster를 축소학 위해 Broker를 제거할 때 사용됩니다. KafkaRebalance를 사용하지 않고 브로커를 제거할 경우 파티션의 메시지가 정상적으로 Replication 되지 않고 Broker가 드랍되어 메시지 손실이 발생할 수 있습니다. 이러한 문제를 방지하기 위해 remove-broker를 사용하여 파티션을 이동하고 안전하게 Broker를 제거할 수 있습니다. remove-brokers 명령을 실행할 때, 제거하려는 브로커의 ID를 지정합니다. Cruise Control은 이 정보를 바탕으로 해당 브로커에 할당된 파티션 복제본을 다른 브로커로 이동시키는 최적의 계획을 생성하고 실행합니다.

브로커를 제거하는 과정에서 파티션의 리밸런싱이 발생합니다. 이 과정은 네트워크 트래픽과 I/O 부하를 증가시킬 수 있으므로, 클러스터의 성능에 일시적인 영향을 줄 수 있습니다.
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: my-rebalance
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  mode: remove-brokers
  brokers: [2, 3]

KafkaRebalance 수락하기

KafkaRebalance 리소스를 통해 Cruise Control을 사용하여 Kafka 클러스터의 리밸런싱을 관리할 때, 작업의 상태는 여러 단계를 거칩니다. 이 과정은 사용자가 제안된 리밸런싱 계획을 검토하고 사용자가 승인하는 방식으로 리밸런싱을 수행하는 방식으로 클러스터의 변경 사항을 보다 안전하게 관리할 수 있습니다.

# 리소스 상태 확인
> kubectl get kafkarebalances.kafka.strimzi.io -n kafka
NAME           CLUSTER    PENDINGPROPOSAL  PROPOSALREADY   REBALANCING   READY   NOTREADY
my-rebalance   my-cluster                                  true

 

KafkaRebalance 리소스 상태

PENDINGPROPOSAL
KafkaRebalance 리소스가 생성된 직후, Cruise Control이 리밸런싱 작업의 계획을 작성하고 있는 단계를 나타냅니다.

PROPOSALREADY
작업 계획이 완료되었고 사용자의 검토를 기다리고 있는 상태입니다.

REBALANCING
사용자가 리밸런싱 계획을 승인한 후, Cruise Control이 실제로 리밸런싱 작업을 수행하고 있는 상태입니다.

READY
리밸런싱 작업이 성공적으로 완료되어, KafkaRebalance 리소스가 최종 상태에 도달한 것입니다.

NOTREADY
리밸런싱 작업에 문제가 발생하여 계획이 성공적으로 수행되지 않았음을 나타내는 상태입니다. 이 경우, 문제의 원인을 분석하고 해결한 후 리밸런싱을 다시 시도해야 할 수 있습니다.

 

KafkaRebalance 리소스가 정상적으로 생성되었다면 describe를 이용하여 작업의 계획을 확인할 수 있습니다.

# 작업 계획 확인
> kubectl describe kafkarebalances.kafka.strimzi.io -n kafka my-rebalance
Name:         my-rebalance
Namespace:    kafka
Labels:       strimzi.io/cluster=my-cluster
Annotations:  <none>
API Version:  kafka.strimzi.io/v1beta2
Kind:         KafkaRebalance
Metadata:
  Creation Timestamp:  2024-03-17T06:48:41Z
  Generation:          3
  Resource Version:    179034
  UID:                 00ff25be-fb27-4f99-a9bb-2722560dfddd
Spec:
  Goals:
    LeaderReplicaDistributionGoal
    TopicReplicaDistributionGoal
  Skip Hard Goal Check:  true
Status:
  Conditions:
    Last Transition Time:  2024-03-17T07:01:35.511905341Z
    Status:                True
    Type:                  ProposalReady
  Observed Generation:     3
  Optimization Result:
    After Before Load Config Map:  my-rebalance
    Data To Move MB:               0
    Excluded Brokers For Leadership:
    Excluded Brokers For Replica Move:
    Excluded Topics:
    Intra Broker Data To Move MB:         0
    Monitored Partitions Percentage:      100
    Num Intra Broker Replica Movements:   0
    Num Leader Movements:                 0
    Num Replica Movements:                0
    On Demand Balancedness Score After:   100
    On Demand Balancedness Score Before:  100
    Provision Recommendation:
    Provision Status:                     UNDECIDED
    Recent Windows:                       1
  Session Id:                             b31d2057-273f-4666-9565-51ce304e95db
Events:                                   <none>

 

작업의 계획을 확인하고 annotate 주석을 이용하여 작업을 승인합니다.

# 작업 승인
> kubectl annotate kafkarebalance -n kafka my-rebalance strimzi.io/rebalance="approve"

# 작업을 중지할 때 stop 수행
# kubectl annotate kafkarebalance -n kafka --overwrite my-rebalance strimzi.io/rebalance="stop"

# 완료된 작업을 나중에 재사용할 때 refresh 수행 후 approve
# kubectl annotate kafkarebalance -n kafka --overwrite my-rebalance strimzi.io/rebalance="refresh"
# kubectl annotate kafkarebalance -n kafka --overwrite my-rebalance strimzi.io/rebalance="approve"

 

 


Cruise Control과 KafkaRebalance 실습

지금까지 Cruise Control과 KafkaRebalance에 대해서 알아봤습니다. 이제는 Broker 추가 및 제거하는 방법으로 직접 실습을 진행하겠습니다.

 

Cluster 구성

실습 진행을 위해 테스트용 클러스터를 구축합니다. 이번 실습에서는 별다른 설정 없이 cruiseControl 기본 값 만으로 테스트를 진행하였습니다.

---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-a
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 2
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 5Gi
        deleteClaim: true
        
---
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: kafka
  annotations:
    strimzi.io/node-pools: enabled
spec:
  kafka:
    version: 3.6.1
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: false
    readinessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    livenessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    config:
      default.replication.factor: 2
      min.insync.replicas: 1
      inter.broker.protocol.version: "3.6"
      num.partitions: 3
    resources:
      limits:
        cpu: 1
        memory: 1Gi
      requests:
        cpu: 500m
        memory: 1Gi
    logging:
      type: inline
      loggers:
        kafka.root.logger.level: INFO
        kafka.request.logger.level: INFO
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 1Gi
      deleteClaim: true
  entityOperator:
    topicOperator: {}
    userOperator: {}
  cruiseControl:
    {}

 

Topic 생성

토픽 a-topic, b-topic을 생성하고 나서 토픽 파티션의 할당된 브로커를 확인하면 0, 1번 브로커에 배포된 것을 확인할 수 있습니다.

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: a-topic
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 4
  replicas: 2
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824
---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: b-topic
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 4
  replicas: 2
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824

 

kcat 파드를 이용하여 토픽 생성 결과 확인

> ❯ kubectl exec -it -n kafka kcat -- kcat -L -b my-cluster-kafka-bootstrap:9092
Metadata for all topics (from broker -1: my-cluster-kafka-bootstrap:9092/bootstrap):
 2 brokers:
  broker 0 at my-cluster-pool-a-0.my-cluster-kafka-brokers.kafka.svc:9092
  broker 1 at my-cluster-pool-a-1.my-cluster-kafka-brokers.kafka.svc:9092 (controller)
 5 topics:
  ( ... 생략 ... )
  topic "a-topic" with 4 partitions:
    partition 0, leader 0, replicas: 0,1, isrs: 0,1
    partition 1, leader 1, replicas: 1,0, isrs: 1,0
    partition 2, leader 0, replicas: 0,1, isrs: 0,1
    partition 3, leader 1, replicas: 1,0, isrs: 1,0
  topic "b-topic" with 4 partitions:
    partition 0, leader 1, replicas: 1,0, isrs: 1,0
    partition 1, leader 0, replicas: 0,1, isrs: 0,1
    partition 2, leader 1, replicas: 1,0, isrs: 1,0
    partition 3, leader 0, replicas: 0,1, isrs: 0,1

 

Broker 확장

KafkaNodePool의 개수를 증가 시켜 브로커를 추가합니다.

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-a
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 4
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 5Gi
        deleteClaim: true

 

브로커를 추가하여 파드가 생성되었지만 카프카 클러스터를 확인하면 추가된 브로커는 클러스터에 합류하지 못한 것을 알 수 있습니다.

 

kcat을 이용하여 확인하면 클러스터에 변화가 없는 것을 알 수 있습니다.

> kubectl exec -it -n kafka kcat -- kcat -L -b my-cluster-kafka-bootstrap:9092
Metadata for all topics (from broker -1: my-cluster-kafka-bootstrap:9092/bootstrap):
 2 brokers:
  broker 0 at my-cluster-pool-a-0.my-cluster-kafka-brokers.kafka.svc:9092
  broker 1 at my-cluster-pool-a-1.my-cluster-kafka-brokers.kafka.svc:9092 (controller)
 5 topics:
  ( ... 생략 ... )
  topic "a-topic" with 4 partitions:
    partition 0, leader 0, replicas: 0,1, isrs: 0,1
    partition 1, leader 1, replicas: 1,0, isrs: 1,0
    partition 2, leader 0, replicas: 0,1, isrs: 0,1
    partition 3, leader 1, replicas: 1,0, isrs: 1,0
  topic "b-topic" with 4 partitions:
    partition 0, leader 1, replicas: 1,0, isrs: 1,0
    partition 1, leader 0, replicas: 0,1, isrs: 0,1
    partition 2, leader 1, replicas: 1,0, isrs: 1,0
    partition 3, leader 0, replicas: 0,1, isrs: 0,1

 

KafkaRebalance add-brokers

2, 3번 브로커를 추가합니다.

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: rebalance-add
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  mode: add-brokers
  brokers: [2, 3]

 

KafkaRebalance 리소스 상태 확인

 

작업 계획 확인

 

작업 승인

 

결과 확인

> kubectl exec -it -n kafka kcat -- kcat -L -b my-cluster-kafka-bootstrap:9092
Metadata for all topics (from broker -1: my-cluster-kafka-bootstrap:9092/bootstrap):
 4 brokers:
  broker 0 at my-cluster-pool-a-0.my-cluster-kafka-brokers.kafka.svc:9092
  broker 2 at my-cluster-pool-a-2.my-cluster-kafka-brokers.kafka.svc:9092
  broker 3 at my-cluster-pool-a-3.my-cluster-kafka-brokers.kafka.svc:9092
  broker 1 at my-cluster-pool-a-1.my-cluster-kafka-brokers.kafka.svc:9092 (controller)
 5 topics:
 (... 생략 ...)
  topic "a-topic" with 4 partitions:
    partition 0, leader 3, replicas: 3,2, isrs: 2,3
    partition 1, leader 3, replicas: 3,2, isrs: 2,3
    partition 2, leader 3, replicas: 3,2, isrs: 2,3
    partition 3, leader 2, replicas: 2,3, isrs: 3,2
  topic "b-topic" with 4 partitions:
    partition 0, leader 1, replicas: 1,0, isrs: 1,0
    partition 1, leader 3, replicas: 3,2, isrs: 2,3
    partition 2, leader 3, replicas: 3,2, isrs: 2,3
    partition 3, leader 0, replicas: 0,1, isrs: 0,1

결과를 확인하면 기존 토픽의 파티션이 새롭게 추가된 브로커에도 할당된 것을 확인할 수 있습니다.

 

KafkaRebalance remove-brokers 생성

이제는 반대로 추가한 브로커를 제거하는 방법을 수행합니다.

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: rebalance-remove
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  mode: remove-brokers
  brokers: [2, 3]

 

remove-brokers 작업 수행

 

KafkaNodePool의 개수를 줄여 자원 반납

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-a
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 2
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 5Gi
        deleteClaim: true

 

참고문서

https://strimzi.io/docs/operators/latest/deploying#cruise-control-concepts-str

KafkaTopic

Strimzi를 사용하면 Kubernetes 환경에서 Kafka Topic을 쉽고 효율적으로 관리할 수 있습니다. Strimzi의 Topic Operator를 통해 Kafka Topic을 Kubernetes의 Custom Resource로 선언적으로 생성, 수정, 삭제할 수 있으며, 이는 접근 권한 문제와 같은 다양한 문제를 해결하는 데 도움이 됩니다.

KafkaTopic 생성하기

먼저 Strimzi를 이용하여 KafkaTopic을 생성하기 위해서는 Kafka Cluster가 Kubernetes 환경에 Strimzi Cluster Operator로 이미 배포되어 있어야 합니다. Strimzi를 이용한 Kafka Cluster 구축은 아래 링크를 통해 진행할 수 있습니다.

 

Strimzi를 이용한 Kafka Cluster 배포

https://stdhsw.tistory.com/entry/Strimzi-2-Cluster-Operator%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-Kafka-Cluster-%EB%B0%B0%ED%8F%AC

 

my-topic.yml 파일 작성

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 3
  replicas: 2
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824

strimzi.io/cluster 라벨을 이용하여 my-cluster 이름의 카프카 클러스터에 my-topic을 생성합니다. spec에는 토픽의 세부 사항을 정의할 수 있습니다. 여기에는 파티션의 수(partitions), 각 파티션의 복제본 수(replicas)를 설정하였으며, 토픽에 적용할 추가적인 설정은 config에 기록하여 정의할 수 있습니다.

Strimzi에서는 Topic을 생성할 때 63글자 미만이며, 소문자와 hyphen을 이용하여 토픽명을 정의하는 것을 권장하고 있습니다. (특수문자, 공백, 기호는 사용하지 마세요)

 

 

Topic 생성

kubectl apply -f my-topic.yml

kafkaTopic 리소스를 생성하게 되면 my-cluster의 카프카 클러스터로 생성된 Entity Operator의 Topic Operator가 my-cluster 카프카에 토픽을 생성합니다.

만약 KafkaTopic 리소스가 아닌 다른 방법으로 토픽을 생성되었다면 ?

Kafka Streams 또는 auto.create.topics.enable 옵션으로 생성된 토픽은 기존 토픽명에 해시값이 붙어 "my-topic---c55e57fe2546a33f9e603caf57165db4072e827e"와 같은 이름으로 KafkaTopic 리소스가 생성됩니다. 이렇게 생성된 KafkaTopic리소스로도 해당 토픽을 관리할 수 있습니다.

 

kcat으로 Topic에 메시지 전송(Producer) 및 수신(Consumer)

Kafka 토픽이 성공적으로 생성된 후, 그 토픽이 정상적으로 동작하는지 확인하기 위해 kcat (이전 명칭: kafkacat)을 사용하여 메시지를 전송하고 수신하여 정상 동작을 확인합니다.

 

kafka-kcat.yml

apiVersion: v1
kind: Pod
metadata:
  name: kcat
  namespace: kafka
spec:
  containers:
    - name: kcat
      image: edenhill/kcat:1.7.1
      command: ["tail"]
      args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0

 

kcat 파드 생성

kubectl apply -f kafka-kcat.yml

 

kcat을 이용한 메시지 전송

# kcat으로 카프카 클러스터 확인
> kubectl exec -it -n kafka kcat -- kcat -L -b my-cluster-kafka-bootstrap:9092
Metadata for all topics (from broker -1: my-cluster-kafka-bootstrap:9092/bootstrap):
 4 brokers:
  broker 0 at my-cluster-pool-a-0.my-cluster-kafka-brokers.kafka.svc:9092
  broker 2 at my-cluster-pool-b-2.my-cluster-kafka-brokers.kafka.svc:9092
  broker 3 at my-cluster-pool-b-3.my-cluster-kafka-brokers.kafka.svc:9092
  broker 1 at my-cluster-pool-a-1.my-cluster-kafka-brokers.kafka.svc:9092 (controller)
 1 topics:
  topic "my-topic" with 3 partitions:
    partition 0, leader 1, replicas: 1,0, isrs: 1,0
    partition 1, leader 0, replicas: 0,2, isrs: 0,2
    partition 2, leader 2, replicas: 2,3, isrs: 2,3

# kcat으로 메시지 전송 메시지를 전부 입력하였다면 ctrl+d로 나옵니다.
> kubectl exec -it -n kafka kcat -- kcat -P -b my-cluster-kafka-bootstrap:9092 -t my-topic -K:
> 1:a
> 2:b
> 3:c
> 1:aa
> 2:bb
> 3:cc

 

kcat을 이용한 메시지 수신

# kcat을 이용하여 메시지는 수신합니다.
> kubectl exec -it -n kafka kcat -- kcat -C -b my-cluster-kafka-bootstrap:9092 -t my-topic
b
c
bb
cc
a
aa
% Reached end of topic my-topic [1] at offset 4
% Reached end of topic my-topic [2] at offset 2
% Reached end of topic my-topic [0] at offset 0

 

참고문서

https://strimzi.io/docs/operators/latest/deploying

 

Cluster Operator를 이용한 Kafka Cluster 배포

Strimzi를 사용하여 Kafka 클러스터를 배포하는 것은 Kubernetes 환경에서 매우 간단합니다. Strimzi의 Custom Resource Definitions (CRD)인 Kafka 리소스를 활용하여 Kafka Broker와 Zookeeper 앙상블을 포함한 Kafka 클러스터를 구성할 수 있습니다.

Strimzi 설치를 진행하지 않으셨다면 아래 링크를 통해 Strimzi 설치를 먼저 진행하여 주시기 바랍니다.

https://stdhsw.tistory.com/entry/Strimzi-1-Strimzi-Cluster-Operator-%EC%84%A4%EC%B9%98-in-Kubernetes

 

Zookeeper 모드 Kafka Cluster 배포

Strimzi의 Custom Resource인 Kafka 리소스를 사용하여 간단하게 Kafka 클러스터를 배포하는 방법은 다음과 같습니다.

 

my-cluster.yml 파일 작성

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-a
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 2
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 5Gi
        deleteClaim: true
---
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-b
  namespace: kafka
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 2
  roles:
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 5Gi
        deleteClaim: true

---
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: kafka
  annotations:
    strimzi.io/node-pools: enabled
spec:
  kafka:
    version: 3.6.1
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: false
    readinessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    livenessProbe:
      initialDelaySeconds: 15
      timeoutSeconds: 5
    config:
      default.replication.factor: 2
      min.insync.replicas: 1
      inter.broker.protocol.version: "3.6"
      num.partitions: 3
    resources:
      limits:
        cpu: 1
        memory: 1Gi
      requests:
        cpu: 500m
        memory: 1Gi
    logging:
      type: inline
      loggers:
        kafka.root.logger.level: INFO
        kafka.request.logger.level: INFO
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 1Gi
      deleteClaim: true
  entityOperator:
    topicOperator: {}
    userOperator: {}

KafkaNodePool은 카프카 브로커의 특성을 정의하고 해당 특성을 카프카 클러스터에 브로커로 등록해 주는 역할을 수행합니다. KafkaNodePool을 이용하여 브로커 노드 관리를 효율적으로 수행할 수 있습니다. 카프카 브로커는 KafkaNodePool 마다 2개씩 구성하여 총 4대의 브로커로 구성되었으며, Zookeeper는 3대로 구성하였습니다.

 

Kafka 리소스 생성

kubectl apply -f my-cluster.yml

 

kafka 리소스를 생성하였다면 StrimziPodSet리소스가 생성됩니다. 기존에는 StatefulSet을 통하여 파드가 관리되었지만 현재는 Strimzi에서 정의한 StrimziPodSet으로 파드가 관리됩니다. 위와 같이 카프카 클러스터를 구축하였다면 다음과 같이 StrimziPodSet이 생성된 것을 확인할 수 있습니다.

 

그리고 my-cluster 카프카 설정으로 Deployment 워크로드로 EntityOperator가 생성됩니다. EntityOperator는 TopicOperator와 UserOperator로 구성되며 Topic과 User를 생성 및 관리하는 역할을 수행합니다. 하나의 카프카 클러스터에 최대 하나의 EntityOperator가 생성될 수 있습니다.

StrimziPodSet과 EntityOperator가 모두 정상적으로 배포가 되었고 이를 통해 다음과 같이 파드가 생성된 것을 확인할 수 있습니다.

KRAFT 모드는 현재

이글을 작성하고 다음날... Strimzi에서 Kraft모드 사용 정식 버전이 나왔습니다. Strimzi 버전 0.40.0으로 Upgrade를 진행하시면 정식 Kraft 모드로 카프카 클러스터 배포를 진행하실 수 있습니다.

 

kraft-cluster.yml

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: dual-role
  namespace: kafka
  labels:
    strimzi.io/cluster: kraft-cluster
spec:
  replicas: 4
  roles:
    - controller
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 10Gi
        deleteClaim: false
---

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: kraft-cluster
  namespace: kafka
  annotations:
    strimzi.io/node-pools: enabled
    strimzi.io/kraft: enabled
spec:
  kafka:
    version: 3.6.1
    metadataVersion: 3.6-IV2
    replicas: 3
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: false
    config:
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
      default.replication.factor: 3
      min.insync.replicas: 2
    resources:
      limits:
        cpu: 1
        memory: 1Gi
      requests:
        cpu: 500m
        memory: 1Gi
    storage:
      type: jbod
      volumes:
        - id: 0
          type: persistent-claim
          size: 5Gi
          deleteClaim: false
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 1Gi
      deleteClaim: false
  entityOperator:
    userOperator: {}

 

KafkaNodePool은 Strimzi Kafka Operator에서 제공하는 리소스 중 하나로, Kafka 브로커의 구성 및 성질을 정의하는 리소스입니다. KRaft 모드(즉, Zookeeper 없이 Kafka를 운영하는 모드)에서 KafkaNodePool을 사용하면 브로커의 역할을 보다 세밀하게 설정할 수 있습니다. KRaft 모드에서 브로커는 다음과 같은 역할을 가질 수 있습니다.

  • Controller: Kafka 클러스터 내에서 메타데이터를 관리하는 중앙 제어 노드의 역할을 합니다. 컨트롤러는 클러스터의 전반적인 상태를 관리하고, 토픽 생성, 삭제, 파티션 리밸런싱과 같은 작업을 총괄합니다. KRaft 모드에서는 단일 컨트롤러 또는 컨트롤러 세트가 이러한 역할을 담당합니다.
  • Broker: 실제 메시지를 저장하고 클라이언트 요청을 처리하는 노드의 역할을 합니다. 브로커는 프로듀서로부터 메시지를 받아 저장하고, 컨슈머의 요청에 따라 메시지를 제공합니다.
  • Controller와 Broker 모두: 하나의 노드가 컨트롤러 역할과 브로커 역할을 동시에 수행할 수도 있습니다. 이 경우, 노드는 메타데이터 관리와 메시지 저장 및 처리의 책임을 모두 갖게 됩니다.

KafkaNodePool 리소스를 사용하여 각 브로커 노드의 역할을 구성함으로써, Kafka 클러스터의 성능과 안정성을 최적화하고, 특정 운영 요구사항에 맞춰 클러스터를 조정할 수 있습니다.

 

YAML파일을 보시면 zookeeper가 선언된 것을 확인할 수 있는데 아직까지 Strimzi 0.40.0 버전에서는 Kafka CRD에 zookeeper가 반듯이 선언되도록 정의가 되어 있어 zookeeper를 선언해야 되지만 실제로 zookeeper가 배포되지는 않습니다.

 

참고문서

https://strimzi.io/docs/operators/latest/deploying

 

Strimzi 란

Strimzi는 Apache Kafka 및 기타 Apache Kafka 생태계 프로젝트를 Kubernetes 및 Red Hat OpenShift와 같은 컨테이너 오케스트레이션 플랫폼에서 쉽게 배포, 관리 및 운영할 수 있도록 도와주는 오픈 소스 프로젝트입니다. Strimzi를 통하여 Kafka를 Kubernetes에 배포하면 Kafka 클러스터를 쉽게 확장하고 Kafka 클러스터를 쉽게 백업하고 Kafka 클러스터를 쉽게 업그레이드할 수 있습니다. 또한 Strimzi는 Prometheus, Grafana 등과 같은 모니터링 도구와 통합되어 Kafka 클러스터의 상태와 성능을 지속적으로 모니터링할 수 있도록 하며, Kafka 클러스터를 쉽게 재구성하고 Kafka 클러스터를 쉽게 보안할 수 있습니다.

또한, Strimzi는 Zookeeper, Kafka Connect, Kafka MirrorMaker, Kafka Bridge, Kafka Exporter, Cruise Control, Strimzi UI와 같은 Kafka 생태계 프로젝트를 Kubernetes에 통합 배포할 수 있도록 지원합니다. 이는 Kafka 기반 애플리케이션과 시스템을 효율적으로 구축, 확장 및 관리하는 데 큰 도움이 됩니다. 이번 실습을 통하여 Kubernetes 환경에서 Strimzi Cluster Operator 배포와 각 리소스의 기능에 대하여 알아보겠습니다.

 

Strimzi 동작 방식

이미지 출처 : https://strimzi.io/docs/operators/latest/overview#kafka-components_str

 

Strimzi 설치

Kubernetes 환경에 Strimzi를 설치하는 방법은 대표적으로 3가지 방법이 있습니다. YAML을 통한 설치 방법, OperatorHub을 이용한 설치 방법, Helm을 이용한 설치방법이 있습니다. 이번 문서에서는 YAML 방식과, Helm 방식에 대하여 정리하였습니다. 둘 중 하나의 방법을 선택하여 진행하여 주시기 바랍니다.

YAML 설치 방법

Strimzi 클러스터를 Kubernetes 환경에 배포하는 과정에서는 기본적인 Kubernetes 명령어와 개념에 대한 이해가 필요합니다. YAML을 이용하여 배포를 진행할 때는 Kubernets 명령어 습득 만으로도 Strimzi 클러스터를 배포할 수 있는 이점이 있지만 다수의 설정이나 복잡한 구성을 변경하고자 할 때 번거롭고 오류가 발생할 수 있는 불편함이 있습니다.

 

GitHub에서 양식 가져오기

`https://github.com/strimzi/strimzi-kafka-operator` GitHub주소를 가져와 해당 디렉토리로 이동하여 다음 명령어를 통하여 간편하게 Strimzi Cluster Operator를 배포할 수 있습니다.

kubectl apply -f install/cluster-operator -n 네임스페이스

 

Helm을 이용한 설치 방법

Helm을 사용하여 Strimzi Kafka 클러스터를 Kubernetes 환경에 배포하는 방법은 Kubernetes 명령어뿐만 아니라 Helm의 기본 사용법에 대한 이해도 필요하게 합니다. 이러한 접근 방식은 초기 학습해야 되는 단점이 있을 수 있지만, Helm의 기본 사용법을 숙지하면 Helm은 Kubernetes 애플리케이션의 패키지 관리자 역할을 수행하여 다양한 설정을 values.yaml 파일을 통해 간단하게 수정할 수 있으며, 업그레이드, 롤백, 삭제 등의 작업을 간단한 명령어로 수행할 수 있습니다. 뿐만 아니라 values.yaml 파일을 공유함으로써 협업하는 팀원들에게 현재의 설정 값을 간편하게 공유할 수 있습니다.

 

values.yml 설정 변경

Kubernets Cluster내에 모든 Namespace에 접근할 수 있도록 설정을 변경합니다.

watchAnyNamespace: true

 

Helm을 이용한 Strimzi 설치

# helm repo 추가
helm repo add strimzi https://strimzi.io/charts

# helm으로 Strimzi 설치 진행
helm upgrade --install -n kafka --create-namespace strimzi-kafka-operator strimzi/strimzi-kafka-operator --version 0.40.0 -f values.yml

 

정상 동작 확인

위와 같이 둘중 하나의 방식으로 Strimzi를 정상적으로 설치되었다면 Kubernetes 클러스터에 CRD(CustomResourceDefinitions)가 정의되고 Strimzi Cluster Operator가 배포된 것을 확인할 수 있습니다.

 

Strimzi CRD 확인

❯ kubectl api-resources  | grep strimzi
strimzipodsets             sps        core.strimzi.io/v1beta2         true       StrimziPodSet
kafkabridges               kb         kafka.strimzi.io/v1beta2        true       KafkaBridge
kafkaconnectors            kctr       kafka.strimzi.io/v1beta2        true       KafkaConnector
kafkaconnects              kc         kafka.strimzi.io/v1beta2        true       KafkaConnect
kafkamirrormaker2s         kmm2       kafka.strimzi.io/v1beta2        true       KafkaMirrorMaker2
kafkamirrormakers          kmm        kafka.strimzi.io/v1beta2        true       KafkaMirrorMaker
kafkanodepools             knp        kafka.strimzi.io/v1beta2        true       KafkaNodePool
kafkarebalances            kr         kafka.strimzi.io/v1beta2        true       KafkaRebalance
kafkas                     k          kafka.strimzi.io/v1beta2        true       Kafka
kafkatopics                kt         kafka.strimzi.io/v1beta2        true       KafkaTopic
kafkausers                 ku         kafka.strimzi.io/v1beta2        true       KafkaUser

 

Strimzi Operator 확인

❯ k get po -n kafka | grep strimzi
strimzi-cluster-operator-95d88f6b5-mmc7q    1/1     Running   1 (30m ago)   70m

 

Strimzi Cluster Operator

Strimzi Cluster Operator는 Kubernetes 환경에서 Strimzi CRD(CustomResourceDefinitions) 관련 리소스를 관리하는 역할을 수행합니다. 주요 기능으로는 Kafka Cluster 배포 및 관리, 구성 관리, 스케일링, 업데이트 및 업그레이드, 모니터링 및 로깅, 보안 관리, 복구, 토픽 생성 관리 및 사용자 생성 관리, 그리고 커넥터 생성 관리를  포함됩니다. 이를 통해 Kafka 클러스터의 성능, 보안, 효율성을 향상하며 Kubernetes 환경에서의 관리를 용이하게 합니다.

Strimzi 공식 문서에서는 Kubernetes 클러스터에 하나의 Cluster Operator만 배포하는 것을 권장하는데, 이는 여러 Operator가 동일한 리소스를 관리하려고 할 때 발생할 수 있는 충돌과 관련된 문제를 방지하기 위함입니다. Cluster Operator는 Strimzi에서 생성된 Custom Resource Definitions(CRD)에 대한 감시로 리소스 관리 및 조정 작업을 수행합니다. Cluster Operator가 동일한 CRD 인스턴스를 관리하려고 하면 예상치 못한 동작이나 데이터 불일치가 발생할 수 있습니다.

 

Strimzi Cluster 구조

Kubernetes Cluster 내에서 단 하나의 Strimzi Cluster Operator만 존재하며 이 Operator를 통해 Kubernetes Cluster 내에서 여러 개의 Kafka Cluster를 구축하고 관리할 수 있습니다.

 

Strimzi CustomResource

Strimzi를 설치하면, Kafka 클러스터 및 관련 리소스를 Kubernetes에서 관리할 수 있도록 여러 CRD(CustomResourceDefinitions) 를 생성합니다. 각 CRD는 Kafka 생태계의 특정 구성 요소를 나타내며, Strimzi Cluster Operator를 통해 관리됩니다. 주요 CRD와 그 기능은 다음과 같습니다

  • kafka : Kafka 클러스터의 생성, 구성, 관리를 위한 리소스를 정의합니다. 사용자는 이 리소스를 사용하여 Kafka 브로커, ZooKeeper 앙상블, Entity Operator를 포함한 전체 Kafka 클러스터를 정의하고 배포할 수 있습니다.
  • KafkaTopic : Kafka 클러스터 내의 개별 토픽을 관리하기 위해 사용됩니다. 이를 통해 토픽의 생성, 삭제, 구성 변경 등을 Kubernetes 네이티브 방식으로 수행할 수 있습니다.
  • KafkaUser : Kafka 클러스터의 사용자와 인증 정보를 관리합니다. 이 리소스를 사용하여 사용자 인증서 및 액세스 권한을 설정하고 관리할 수 있습니다.
  • KafkaConnect : Kafka Connect 클러스터를 배포하고 관리하는 CRD입니다. 데이터 소스와 싱크를 Kafka 토픽과 연결하는 커넥터를 배포 및 관리할 수 있습니다.
  • KafkaConnectors : Kafka Connect 클러스터 내에서 실행되는 개별 커넥터를 정의하고 관리합니다.
  • KafkaBridge : Kafka 클러스터에 접근할 수 있는 REST 인터페이스를 제공하는 Kafka Bridge 인스턴스를 배포 및 관리합니다. 이는 외부 애플리케이션이 Kafka 클러스터와 통신할 수 있게 해 줍니다.
  • KafkaMirrorMaker : 토픽의 데이터를 미러링 하는 데 사용되지만 현재는 사용하지 않습니다.
  • KafkaMirrorMaker2 : KafkaMirrorMaker의 더 발전된 버전으로, 더 복잡한 미러링 및 리패키징 요구사항을 지원합니다. 이를 통해 다양한 클러스터 간에 토픽, 메시지, 파티션 등을 더 효율적으로 미러링 할 수 있습니다.
  • KafkaRebalance : Kafka 클러스터 내에서 파티션의 리밸런싱을 관리하는 CRD입니다. 클러스터의 부하 분산 및 성능 최적화를 위한 자동 리밸런싱 작업을 지원합니다.
  • StrimziPodSet : 기존에는 StatefulSet을 이용하여 Kafka Broker가 관리되었지만 현재는 StatefulSet 대신 StrimziPodSet을 이용하여 관리됩니다. Kafka리소스로 생성된 Kafka Broker, Zookeeper 모두 StrimziPodSet으로 관리됩니다.
  • KafkaNodePool : 각 특성에 맞는 Kafka Broker의 특성과 Storage를 관리합니다.

참고문서

https://strimzi.io/docs/operators/latest/deploying

 

Deploying and Upgrading (0.40.0)

Configure and manage a Strimzi deployment to your precise needs using Strimzi custom resources. Strimzi provides example custom resources with each release, allowing you to configure and create instances of supported Kafka components. Fine-tune your deploy

strimzi.io

 

Service Discovery

Service Discovery는 동적으로 변화하는 환경에서 수집 대상을 자동으로 찾아내고 관리하는 기술로, 사용자가 수동으로 각각의 서비스를 추적하고 업데이트하는 번거로움을 해소해 줍니다. 이 기술은 특히 클라우드 환경에서 매우 유용하며, AWS, Azure, GCP와 같은 주요 Public Cloud 제공 업체들과 Kubernetes, 호스트, HTTP 서비스 등 다양한 환경에서의 Service Discovery를 지원합니다. Prometheus는 이러한 동적 환경에 탁월하게 대응할 수 있도록 Service Discovery 기능을 제공하고 있습니다. 본 문서에서는 Prometheus의 구성 파일을 통해 Service Discovery를 어떻게 정의하는지, 그리고 Prometheus가 이 설정을 바탕으로 어떻게 자동으로 수집 대상을 식별하고 선정하는지에 대한 방법에 대하여 기록하였습니다. 이를 통해 사용자는 Prometheus를 사용하여 보다 효율적으로 자원을 모니터링 할 수 있는 방법을 이해하는데 많은 도움이 되었으면 합니다.

 

Kubernetes Service Discovery

동적인 환경에서 서비스들이 어떻게 변화하는지를 실시간으로 파악하고 관리하는 것은 매우 복잡하고 어려운 일입니다. 이러한 문제를 해결하기 위해 Prometheus에서는 다양한 Service Discovery 메커니즘을 제공하고 있으며, 그 중에서도 특히 Kubernetes 환경에 최적화된 Kubernetes Service Discovery를 예시로 들어 Prometheus의 Service Discovery 작동 원리를 상세하게 설명해 보고자 합니다. 이 예제를 통해 설명드리는 것은 Kubernetes 환경에서의 Service Discovery 방식이지만, 이와 유사한 원리로 다양한 환경에서 Prometheus가 어떻게 서비스를 자동으로 감지하고 모니터링 대상으로 추가하는지에 대한 이해를 돕기 위함입니다. 따라서 이 예제를 통해 Kubernetes Service Discovery의 구체적인 작동 방식을 파악하시면, Prometheus가 지원하는 다른 환경들에서의 Service Discovery 작동 방식도 보다 쉽게 이해하고 적용하실 수 있습니다. 이번 문서의 내용은 Prometheus의 설치 과정이나 초기 설정 방법 등 기초적인 내용보다는, Prometheus가 어떻게 동적인 서비스 환경에서 모니터링 대상을 자동으로 발견하고 관리하는지에 대한 동작 원리와 방식에 초점을 맞추어 정리하였습니다.

 

Service Discovery 설정 파일 작성

Prometheus에서 scrape_configs 설정을 통해 Kubernetes 상의 특정 노드에서 실행 중인 exporter의 메트릭을 수집하는 과정은 매우 세밀하고 구체적인 접근이 필요합니다. 이러한 설정에서 scrape_configs의 선언 순서는 타겟을 효과적으로 식별하고 분류하는 데 있어 핵심적인 역할을 합니다. Prometheus는 이 설정들을 선언된 순서대로 처리하게 되므로, 가능한 한 빠르게 대상을 좁혀나갈 수 있도록 최적화된 조건을 선두에 배치하는 것이 중요합니다. 이렇게 함으로써, Prometheus는 불필요한 탐색을 줄이고, 보다 효율적으로 메트릭을 수집할 수 있는 대상을 신속하게 파악할 수 있습니다. (참고 : Kubernetes Service Discovery는 node, pod, service, endpoints, endpointslice의 리소스를 통하여 수집 대상을 정의할 수 있습니다.)

 

이 예제는 Prometheus의 구성에서 특히 Kubernetes 환경 내의 특정 노드에서 실행되고 있는 nginx-exporter라는 이름의 워크로드로부터 메트릭을 수집하는 방법니다. 이 과정에서 kubernetes_sd_configs 설정에서 role을 pod로 지정함으로써, Prometheus가 Kubernetes의 파드 단위에서 동작하는 서비스를 대상으로 메트릭 수집을 수행하도록 설정하였습니다.

  1. 해당 파드가 worker1이라는 노드에 동작한다면 Keep 합니다.
  2. worker1에 동작하는 파드의 워크로드가 nginx-exporter라면 Keep 합니다.
  3. 파드의 9113이라는 Container port가 있으면 Keep 합니다.

이러한 단계별 접근 방식은 Prometheus가 Kubernetes 환경 내에서 메트릭을 수집할 때 필요한 정확성과 효율성을 보장합니다. 이 과정을 통해 Prometheus는 불필요한 데이터 수집을 최소화하고, 관련된 메트릭만을 효과적으로 수집하며, 시스템의 부하를 줄이는 동시에 모니터링의 정확성을 높일 수 있습니다.

scrape_configs:
  - job_name: 'my-metrics'
    kubernetes_sd_configs:
      - role: pod  # 파드 레벨에서 메트릭 수집

    relabel_configs:
      # 동작중인 노드이름이 'worker1'인 파드만 수집 설정
      - source_labels: [__meta_kubernetes_pod_node_name]
        action: keep
        regex: worker1

      # 워크로드 이름이 'nginx-exporter'인 파드만 수집 설정
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: nginx-exporter

      # 컨테이너 포트가 9113 파드만 수집
      - source_labels: [__meta_kubernetes_pod_container_port_number]
        action: keep
        regex: '(.*)9113'

 

Service Discovery 동작 방식

Prometheus의 Service Discovery 메커니즘은 크게 Discovery Manager와 Scrape Manager 두 가지 핵심 구성 요소의 동작에 의해 구현됩니다. 이 Manager는 Prometheus가 동적 환경에서 서비스를 발견하고, 해당 서비스로부터 메트릭을 수집하는 작업을 수행합니다.

 

Discovery Manager 동작

Discovery Manager는 사용자가 정의한 Service Discovery 설정에 따라 각각의 서비스 발견 메커니즘을 실행하고, 이러한 메커니즘을 통해 발견된 리소스의 변화를 지속적으로 감지합니다. 이렇게 발견된 리소스에 필요한 메타데이터를 Label로 할당하는 작업을 수행합니다. 이 메타데이터는 주로 리소스를 식별하고 분류하는 데 사용되는 라벨 형태로 제공되며, Prometheus가 메트릭을 수집할 때 리소스를 구분하고 필터링하는 데 필수적입니다. 예를 들어, Kubernetes 환경에서 Discovery Manager는 각 파드, 서비스, 노드 등의 Kubernetes 리소스에 대한 정보를 수집하고, 이러한 리소스에 적절한 라벨을 할당하여 Scrape Manager가 이들을 구분할 수 있도록 합니다. Discovery Manager의 이름만 봤을 때는 위에서 선언한 scrape_configs를 통하여 필터링까지 수행하는 것 같지만 실제로 Discovery Manager에서는 필터링을 수행하지 않고 변경된 리소스만 감지하는 역할만 수행합니다.

 

소스 코드 위치

https://github.com/prometheus/prometheus/tree/main/discovery

 

Scrape Manager 동작

Discovery Manager가 발견한 리소스 정보는 일종의 중간 저장소 또는 메시지 큐인 Channel을 통해 Scrape Manager에 전달됩니다. Scrape Manager는 scrape_configs에 정의된 설정을 기반으로 실제 메트릭 수집 대상을 선별하고 필터링하는 중요한 작업을 수행합니다. scrape_configs 설정에는 수집할 대상의 종류, 주소, 포트, 경로 등이 명시되어 있으며, Scrape Manager는 이 정보를 사용하여 Prometheus가 어떤 서비스로부터 메트릭을 수집할지를 결정합니다. 또한, 이 과정에서 특정 조건에 맞는 리소스에 대해서만 메트릭을 수집하도록 필터링하여 Prometheus가 설정된 간격에 따라 각 수집 대상으로부터 메트릭을 수집합니다.

 

소스 코드 위치

https://github.com/prometheus/prometheus/tree/main/scrape

대상을 필터링하는 소스코드 위치

https://github.com/prometheus/prometheus/blob/main/model/relabel/relabel.go

 

Service Discovery 동작 순서

위에서 선언한 scrape_configs를 기반으로 동작하는 방식은 다음과 같습니다.

Discovery Manager는 kubernetes_sd_configs 설정을 통해 Kubernetes 환경과의 통신을 위한 Kubernetes 클라이언트를 초기화합니다. 이 클라이언트는 Kubernetes API Server에 Request를 통하여, 설정된 role에 따라 특정 Kubernetes 리소스(예를 들어, Pod)의 변화를 실시간으로 감지할 수 있는 Watcher(Informer)를 생성합니다. 이러한 방식으로 Prometheus는 Kubernetes 클러스터 내의 Pod 리소스의 생성, 업데이트, 삭제 등의 이벤트를 지속적으로 모니터링할 수 있게 됩니다.

 

Discovery Manager가 Kubernetes API 서버로부터 받아온 Pod 정보에는 다양한 메타데이터가 포함되어 있으며, 이 중에서 특히 중요한 정보는 라벨 형태로 Prometheus에 전달됩니다. 예를 들어, __meta_kubernetes_namespace, __meta_kubernetes_pod_name, __meta_kubernetes_pod_container_name과 같은 라벨은 각 Pod의 메타데이터의 값을 Label에 추가합니다. 이러한 Label들은 메트릭 데이터에 포함되어 Prometheus 사용자가 보다 상세한 쿼리와 분석을 수행할 수 있도록 합니다.

 

이렇게 Discovery Manager에 의해 수집되고 라벨이 할당된 리소스 정보는 Channel을 통해 Scrape Manager로 전달됩니다. Scrape Manager는 이 정보를 받아 relabel_configs 설정에 정의된 규칙을 적용하여 실제 메트릭을 수집할 대상을 최종적으로 결정합니다. relabel_configs에서는 수집할 대상의 라벨을 재정의하거나, 특정 조건에 부합하는 리소스만을 필터링하여 수집 대상으로 선정하는 작업을 수행합니다. 이 과정을 통해 Prometheus는 사용자가 정의한 규칙에 따라 필요한 리소스로부터만 메트릭을 수집하게 되며, 이는 Prometheus의 수집 효율성을 극대화하고 불필요한 데이터 수집을 최소화하는 데 중요한 역할을 합니다.

 

마지막으로, Scrape Manager는 scrape_configs에 정의된 간격에 따라, 선별된 대상으로부터 메트릭을 수집합니다. 이때 각 메트릭에는 Discovery Manager로부터 할당받은 라벨 정보가 포함되어 있으며, relabel_configs에 정의된 순서대로 수집할 대상과 수집하지 않을 대상을 분리 또는 라벨 재정의하는 작업을 수행합니다. 이렇게 분리된 수집 대상에게 사용자가 정의한 일정 간격으로 메트릭을 수집합니다.

 

 

참조

https://prometheus.io/docs/prometheus/latest/configuration/configuration/

 

Configuration | Prometheus

An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.

prometheus.io

 

 

'Prometheus' 카테고리의 다른 글

Prometheus exporter의 구조와 개인 exporter 만들기  (0) 2023.11.04
Prometheus 윈도우10에 설치  (0) 2021.06.13

kubernetes 환경에서 elasticsearch를 설치하는 방법을 정리하였습니다. 비록 테스트 환경이지만 실제 운영환경처럼 구성하기 위해 3대의 마스터 노드와 2대의 데이터 노드로 구성하였습니다(현업에서 직접 사용할 경우 보다 더 여유 있는 구성을 추천드립니다) 3대의 마스터 노드 중 실제로 마스터의 역할을 수행하는 것은 1대이며 나머지 2대의 마스터 노드는 현재 마스터 노드의 문제가 발생할 경우 마스터로 승격할 수 있도록 Standby 형식으로 구성하였습니다.

 

1. Helm chart 다운로드

저는 kubernets 환경에서 elasticsearch를 설치하기 위해 helm을 사용하였습니다. 아래 링크의 helm으로 구성하였습니다.
https://artifacthub.io/packages/helm/elastic/elasticsearch

 

elasticsearch 8.5.1 · elastic/elastic

Official Elastic helm chart for Elasticsearch

artifacthub.io

 

helm 명령어를 통하여 repo를 추가하고 다운로드합니다.

# helm repo 추가
$ helm repo add elastic https://helm.elastic.co

# helm 파일 다운로드
$ helm pull elastic/elasticsearch
$ ls -al
drwxr-xr-x@  6 hsw  staff    192  6 25 09:45 .
drwxr-xr-x@  9 hsw  staff    288  6 25 09:44 ..
-rw-r--r--@  1 hsw  staff  28898  6 25 09:45 elasticsearch-8.5.1.tgz

# helm 압축 출기
$ tar -zxvf elasticsearch-8.5.1.tgz
$ ls -al
drwxr-xr-x@  6 hsw  staff    192  6 25 09:45 .
drwxr-xr-x@  9 hsw  staff    288  6 25 09:44 ..
drwxr-xr-x@ 12 hsw  staff    384  6 25 10:26 elasticsearch
-rw-r--r--@  1 hsw  staff  28898  6 25 09:45 elasticsearch-8.5.1.tgz

 

2. values.yaml 수정

elasticsearch 디렉토리로 이동하여 values 값을 설정합니다. 저의 경우 values.yaml 파일을 직접적으로 수정하는 것보다는 새로운 yaml을 구성하여 values.yaml 파일을 override 하여 사용하는 것을 선호하기 때문에 마스터 노드와 데이터 노드 별로 설정파일을 구성하여 작업하였습니다.

master.yaml 파일 구성

마스터 노드는 3대로 구성되어 있고 클러스터 유지를 위해 CPU는 4 코어, Memory는 16GB로 여유 있게 구성하였습니다. 그리고 Lucene의 메모리 사용을 위해 16GB의 절반인 8GB만 JVM옵션으로 설정을 하였습니다.

tolerations, nodeAffinity의 경우 사용자 환경에 맞게 설정하여 사용해 주세요 사용법은 링크를 달아놨습니다.
tolerations : https://kubernetes.io/ko/docs/concepts/scheduling-eviction/taint-and-toleration/
nodeAffinity : https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/

##################################
# cluster info
createCert: false
clusterName: "elasticsearch"
nodeGroup: "master"
replicas: 3
imageTag: "7.10.2"

roles:
- master

##################################
# nodeAffinity
tolerations:
- key: "develop/elasticsearch-master"
  operator: "Exists"

nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
  nodeSelectorTerms:
    - matchExpressions:
      - key: develop/group
        operator: In
        values:
        - elasticsearch-master

##################################
# cluster config
# 테스트 환경이라 보안 설정을 끔
esConfig:
  elasticsearch.yml: |
    xpack.security.enabled: false

# AWS S3 스냅샷 테스트를 위한 설정
esJvmOptions:
  jvm.options: |
    -Des.allow_insecure_settings=true

##################################
# resources
esJavaOpts: "-Xmx8g -Xms8g"

resources:
  requests:
    cpu: 4
    memory: "16Gi"
  limits:
    cpu: 4
    memory: "16Gi"

volumeClaimTemplate:
  resources:
    requests:
      storage: 10Gi
  storageClassName: openebs

##################################
# service
protocol: http
service:
  type: NodePort
  nodePort: "30090"

data.yaml 파일 구성

데이터 노드의 경우 마스터 노드보다 더 많은 요청을 처리하고 데이터 관리를 수행하기 때문에 마스터 노드보다 더 여유 있는 스펙으로 리소스를 구성하였습니다. 데이터 노드 또한 마스터 노드처럼 사용자의 환경에 맞는 값으로 구성해 주세요

##################################
# cluster info
createCert: false
clusterName: "elasticsearch"
nodeGroup: "data"
replicas: 2
imageTag: "7.10.2"

roles:
- data
- ingest

##################################
# nodeAffinity
tolerations:
- key: "develop/elasticsearch-data"
  operator: "Exists"

nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
  nodeSelectorTerms:
    - matchExpressions:
      - key: develop/group
        operator: In
        values:
        - elasticsearch-data

##################################
# cluster config
# 테스트 환경이라 보안 설정을 끔
esConfig:
  elasticsearch.yml: |
    xpack.security.enabled: false

# AWS S3 스냅샷 테스트를 위한 설정
esJvmOptions:
  jvm.options: |
    -Des.allow_insecure_settings=true

##################################
# resources
esJavaOpts: "-Xmx16g -Xms16g"

resources:
  requests:
    cpu: 8
    memory: "32Gi"
  limits:
    cpu: 8
    memory: "32Gi"

volumeClaimTemplate:
  resources:
    requests:
      storage: 200Gi
  storageClassName: openebs

##################################
# service
# UI 사용을 위해 NodePort로 설정
protocol: http
service:
  type: NodePort
  nodePort: "30091"

Makefile 구성

저는 지속적으로 지웠다 설치했다는 반복 하는데 편리하기 위해 Makefile을 구성하였습니다.

PREFIX := es
TIMEOUT := 1200s
NAMESPACE := elasticsearch

install:
helm upgrade --wait --timeout=$(TIMEOUT) --install -n $(NAMESPACE) --create-namespace --values override-master.yaml $(PREFIX)-master .
helm upgrade --wait --timeout=$(TIMEOUT) --install -n $(NAMESPACE) --create-namespace --values override-data.yaml $(PREFIX)-data .

purge:
helm del $(PREFIX)-master -n $(NAMESPACE)
helm del $(PREFIX)-data -n $(NAMESPACE)

 

3. 설치 진행

Makefile을 이용하여 설치를 진행합니다.

# elasticsearch 설치
$ make install

 

설치 작업이 완료 되면 Elasticsearch는 다음과 같이 구성됩니다.

pod/elasticsearch-data-0             1/1     Running     0       1d
pod/elasticsearch-data-1             1/1     Running     0       1d
pod/elasticsearch-master-0           1/1     Running     0       1d
pod/elasticsearch-master-1           1/1     Running     0       1d
pod/elasticsearch-master-2           1/1     Running     0       1d

service/elasticsearch-data               NodePort    10.233.47.200  <none>   9200:30091/TCP,9300:31095/TCP   1d
service/elasticsearch-data-headless      ClusterIP   None           <none>   9200/TCP,9300/TCP               1d
service/elasticsearch-master             NodePort    10.233.56.28   <none>   9200:30090/TCP,9300:32277/TCP   1d
service/elasticsearch-master-headless    ClusterIP   None           <none>   9200/TCP,9300/TCP               1d

statefulset.apps/elasticsearch-data         2/2     1d
statefulset.apps/elasticsearch-master       3/3     1d

 

4. Elasticsearch 삭제

테스트가 끝나고 elasticsearch를 지우기 위해서는 다음과 같이 진행하면 됩니다.

# Elasticsearch 제거
$ make purge

 

본 문서는 2023년 7월에 작성된 문서입니다.

Helm은 Kubernetes 애플리케이션을 배포, 관리 및 업데이트하기 위한 패키지 관리 도구입니다. Helm은 Kubernetes 클러스터에서 애플리케이션을 쉽게 설치하고 관리하기 위한 기능을 제공합니다. Helm은 "차트"라고 하는 패키지 형식을 사용하여 Kubernetes 애플리케이션을 정의합니다. 차트는 Kubernetes 리소스 (파드, 서비스, 볼륨 등)를 정의하는 템플릿 파일과 해당 애플리케이션을 배포하고 구성하는 데 필요한 매개변수 및 값들을 포함합니다. 이러한 차트를 사용하여 애플리케이션을 쉽게 배포하고 업데이트할 수 있습니다.

helm 설치

아래 링크를 통하여 helm 설치를 진행하여 줍니다.

https://helm.sh/docs/intro/install/

 

Installing Helm

Learn how to install and get running with Helm.

helm.sh

helm repository

helm으로 설치를 진행하기 위해서는 chart를 가지고 있는 repository를 등록하여 사용해야 합니다.

# 설치하는데 필요한 chart를 가져오는 repository를 등록합니다.
helm repo add 레포지토리명 레포지토리주소

# 등록한 repository에서 설치할 수 있는 목록을 출력합니다.
helm search 레포지토리명

# 등록한 repository를 최신으로 update합니다.
helm repo update

helm install

앞에서 repo를 등록하였다면 이제는 등록된 repo를 이용하여 kubernets에 설치 작업을 진행할 수 있습니다.

helm install -n 네임스페이스 --create-namespace 앱이름 레포지토리명/설치할앱

helm upgrade

기존에 설치했던 설정값이 변경되었을 경우 helm upgrade를 통하여 변경된 내용을 적용할 수 있습니다.

helm upgrade -n 네임스페이스 앱이름 레포지토리명/설치할앱

helm delete

더 이상 배포한 앱을 사용하지 않는다면 helm delete를 통해 자원을 반납할 수 있습니다.

helm delete -n 네임스페이스 앱이름

 

[실습] helm을 이용하여 kubernetes에 nginx 설치하기

이번에 실습 예시로 helm을 이용하여 kubernets 환경에 nginx를 기본 값으로 설치하는 방법에 대해서 알아보겠습니다. helm의 repository는 ArtifactHub에서 검색할 수 있습니다. 

https://artifacthub.io/

 

Artifact Hub

Find, install and publish Kubernetes packages

artifacthub.io

 

ArtifactHub에서 nginx를 검색하면 다음과 같이 나오는데요 여기서 중요하게 봐야 되는 것 3가지가 있습니다.

먼저 어느 단체에서 만들었는지 그리고 Star를 몇개 받았는지 마지막으로 인증된 helm chart인지를 확인하여 사용자에게 가장 합리적인 것을 선택하여 줍니다.

 

페이지로 들어오면 다음과 같은 화면이 나옵니다. 이 페이지에서 helm chart에 대한 상세한 설명이 나오니 정확한 정보를 확인하기 위해서는 해당 페이지를 참고하는 것을 추천드립니다.

이제 Kubernetes 환경에 nginx를 설치하기 위해서는 INSTALL 버튼을 클릭하여 줍니다.

 

화면에 출력된 명령어를 입력하게 되면 자신의 환경에 nginx가 설치됩니다.

결과 확인

$ kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-6ff77558fc-qzgw5   1/1     Running   0          15s

설치 내역 삭제하기

helm delete my-nginx

 

 

 

본 문서는 2023년 6월에 작성된 문서입니다. 시간이 지나면 현재 시험 방식과 많이 다를 수 있습니다.


저는 회사에서 2년 넘게 Kubernetes를 사용을 하여 Kubernetes에 익숙한 상태였고 이왕 Kubernetes를 사용할 줄 알게 된 거 이 기회에 CKA를 취득하는 게 좋을 것 같아 시험을 보게 되었습니다. CKA 준비 기간은 2 ~ 3주 정도 걸렸으며 모든 부분을 공부한 것이 아닌 부족한 부분만 골라 보면서 공부를 하였습니다.

결제는 어떻게?

https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/

 

Certified Kubernetes Administrator (CKA) Exam | Linux Foundation

Training in skills, knowledge, and competency to perform the responsibilities of Kubernetes administrators.

training.linuxfoundation.org

결제 진행 방식은 위 링크를 통해 Linux Foundation에 로그인 후 결제를 진행하면 됩니다. 여기서 약간의 팁은 CKA는 자주 할인을 진행하는데 적게는 15%에서 많게는 40%까지 할인을 받을 수 있습니다. 저 같은 경우 40% 해택을 받아 321,256원으로 결제할 수 있었습니다. 여기서 환율이 적용되기 때문에 환율이 좋을 때 구매를 진행하시면 같은 40% 할인이어도 실제 구매한 가격이 다를 수 있습니다.
할인 코드 확인 방법은 https://training.linuxfoundation.org/blog/ Linux Foudation 블로그에 게시물로 업로드가 되는데 그때 코드를 받아 결제를 진행하시면 됩니다.

CKA 공부 방법

저는 회사에서 Kubernetes를 2년 이상 사용하였습니다. 회사에서 사용하였을 때는 "마사야 야오야마"가 지은 "쿠버네티스 완벽 가이드"라는 책으로 공부를 하였고 CKA 준비를 하기 위해서는 Udemy에 "Mumshad Mannambeth"의 "Certified Kubernetes Administrator (CKA) with Practice Tests" 강의를 들었습니다. 저는 어느 정도 Kubernetes를 사용하여 부족한 부분만 골라서 강의를 들었습니다. 여기서 제공하는 실습문제가 실제로 많이 도움이 되었기 때문에 실습문제는 반드시 풀어보는 게 좋습니다. 이 강의 또한 할인을 자주 하기 때문에 관심등록을 통해 할인한다는 알림을 받게 되면 그때 구입하는 것을 추천드립니다. 원래 가격은 99,000원이지만 할인을 받게 되면 15,000에서 20,000원에 결제할 수 있습니다.

https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/

Killer.sh 후기

CKA 시험을 결제하게 되면 Killer.sh라는 실제 시험 환경과 아주 비슷한 환경을 제공해 줍니다. 세션을 시작하면 36시간 동안 지속적으로 비슷한 시험 환경에서 예상문제를 풀 수 있는 세션을 2개 줍니다. 1개의 세션은 36시간 동안 접속할 수 있기 때문에 주말에 문제를 여러 번 풀어보면 많은 도움이 됩니다. 세션은 2개 주지만 2개의 세션 모두 시험문제가 동일하니 굳이 2개의 세션을 사용하지 않으셔도 됩니다. 참고로 Killer.sh는 실제 CKA 시험 문제보다 어려운 문제가 나오니 여기서 좋은 못한 점수를 받았다고 낙심하지 마세요. 그리고 Killer.sh는 문제와 풀이 과정까지 전부 PDF로 제공하여 부족한 부분을 공부하는데 좋습니다.

CKA 당일!!!

PSI 브라우저 설치

시험 날짜를 정하고 나면 이메일로 PSI 브라우저를 설치할 수 있는 링크를 보내줍니다. PSI 브라우저는 시험 보기 30분 전에 설치할 수 있으며 설치가 완료되고 PSI를 구동하면 PSI와 동시에 동작할 수 없는 프로세서를 죽이고 시험에 입장을 하게 됩니다. 이때 PSI와 같이 동작할 수 없는 프로그램은 대표적으로 크롬입니다. 참고로 PSI에서 버튼을 누르면 PSI가 알아서 프로그램을 죽이니 미리 프로그램을 종료하지 않으셔도 됩니다. 

준비물

폐쇄된 공간(집보다는 주말에 회사에 출근하여 폐쇄된 회의실에서 시험을 보는 것을 추천), 여권, 웹캠(노트북 가능), 최소 15인치 이상의 화면(듀얼모니터 불가능)

감독관과의 소통

PSI 브라우저 설치가 모두 정상적으로 끝나면 감독관과 채팅을 하게 되는데.. 영어를 잘 모르는 저의 입장에서는 모든 시험 통틀어서 가장 힘든 순간이었습니다. 먼저 여권으로 신원을 확인하고 노트북에 달린 웹캠으로 시험 보는 공간을 감독관에게 확인시켜주어야 합니다. 그리고 감독관이 주변에 어떠한 물건을 치우라고 하면 바로바로 치워주면 시험을 시작하게 됩니다. 저는 감독관과 채팅을 시작하자마자 "I am not good english"라고 알려주었더니 제가 영어를 못 알아듣는 거 같으니 감독관 단어 하나씩 채팅에 쳐서 알려주는 친절함을 보여주었습니다. 그러니 영어를 잘 모르더라도 너무 두려워하지 않으셔도 됩니다.

실제 시험 환경

시험장에 들어가면 아래 이미지와 같은 환경에서 시험을 보게 됩니다. 우측 상단에는 응시자(본인)의 얼굴이 나오는데 화면에 반드시 얼굴이 벗어나면 안 됩니다. 얼굴이 화면에 벗어나게 되면 채팅창으로 감독관이 카메라에 얼굴이 나와야 된다는 메시지를 보냅니다. 그리고 가장 중요한 팁은 바로 복사 붙여 넣기인데요 저는 윈도우 노트북으로 시험을 진행하였는데 터미널과 파이어폭스, 메모장의 복붙 단축키가 다릅니다.
터미널 : ctrl + shift + c(복사), ctrl + shift + v(붙여 넣기)
파이어폭스, 메모장 : ctrl + c(복사), ctrl + v(붙여 넣기)
파이어폭스 Kubernets document에서 yaml을 복사할 때는 ctrl + c로 복사하여 터미널에서는 ctrl + shift + v로 붙여 넣어야 합니다.

참고로 문제의 언어를 선택할 수 있는데 영어, 중국어, 일본어만 제공하고 있습니다.
그리고 정말 인터넷이 아주 느리니 무조건 유선으로 시험 보는 것을 추천드리고 생각보다 PSI 브라우저가 매우 무겁습니다. 그렇기 때문에 어느 정도 성능이 좋은 컴퓨터로 시험을 보는 것을 추천드립니다.

CKA 문제 유형

문제는 15 ~ 20개 정도 나오고 2시간 동안 풀 수 있습니다. 저의 경우 17문제 나왔고 문제의 유형은 아래 리스트처럼 나왔습니다.

  • pod 생성
  • 멀티 컨테이너 pod 생성
  • 사이드카 컨테이너 pod 생성
  • deploy, statefulset, daemonset 등 생성
  • service expose
  • pv, pvc 생성 후 마운트
  • ingress, networkpolicy
  • rbac
  • etcd 백업
  • version upgrade
  • Troubleshooting

CKA Tip

  1. kubectl 자동완성은 기본적으로 적용되어 있습니다.
  2. alias k="kubectl"은 기본적으로 적용되어 있습니다.
  3. etcdctl 이 이미 설치되어 있습니다.
  4. export do="--dry-run=client -o yaml"를 미리 정의해 두면 dry-run을 수행할 때 조금은 더 빠르게 작업할 수 있습니다.
  5. kubectl create --help를 통해 create로 생성할 수 있는 리소스는 create로 생성하고 create로 생성할 수 없는 리소스는 kubernetes document에서 복사하는 게 빠릅니다. (예시로 pv, pvc는 빨리 document에서 복사해 오자)
  6. PSI 브라우저 바탕화면에서 우클릭하여 메모장을 생성 후 사용할 수 있습니다.
  7. 파이어폭스에서 ctrl + f로 검색을 하고 아래에 search highlight 체크박스 선택을 통해 검색을 강조하여 볼 수 있습니다.
  8. 파이어폭스에서 실수로 ctrl + shift + c를 누르면.. 개발자 모드가 나오는데 인터넷이 매우 느려 개발자 모드를 끄는데도 5 ~ 10초 정도 소요됩니다.
  9. 내 얼굴이 나오는 상단 메뉴를 접어 화면을 조금 더 크게 사용할 수 있다.

외우면 좋은 거

  1. etcd 백업 방법
  2. manifest위치 (/etc/kubernetes/manifests)
  3. PKI 위치 (/etc/kubernetes/pki/)
  4. 파드 DNS 확인 (kubectl exec -it 파드명 -- cat /etc/resolv.conf)
  5. kubelet 로그 확인 (journalctl -u kubelet)

CKA 시험 결과

2023년 6월 6일 시험을 봤고 6월 7일에 시험 결과가 나왔고 결과는 한 번에 합격할 수 있었습니다.!!!
CKA에 도전하는 분들 모두 응원합니다.

 

+ Recent posts