저장소 클래스를 사용하여 Kubernetes에서 Kafka를 실행하여 로컬 개발

최근 기사에서 사용Kafka(PV)과Persistent Volumes(PVC)를 사용하여 로컬 Kubernetes에서 실행Persistent Volume Claims하는 설정을 보여 드렸습니다. 이 글은 KubernetesStorage Class(SC)를 사용하는 설정을 소개하고 기본 자동 설정Rancher local-path-provisioner을 이용합니다.
이런 설정은 이전의 설정보다 간단하고 사용하는 코드도 적지만 외부화된 호스트의 데이터 경로를 소량 제어하는 동시에 일부internal knowledge of Kind를 설정해야 한다.전반적으로 말하자면, 나는 이전의 댓글보다 이런 지역의 발전 방식을 더 좋아한다.

Strimzi is an awesome simpler alternative to achieve the same, check it out. My goal with this setup here is for learning and to have a more "realistic" Kubernetes setup on local development machine so I opted to not use Strimzi or Helm charts.

I have created and tested these approaches on a Linux Development machine. It should work for Mac and Windows with some minimal adjustments also but I have never tried it.


Github repo에서 상기 두 가지 방법의 파일을 찾을 수 있고 빠른 입문을 할 수 있는 완전한 원본 코드를 얻을 수 있습니다.복제 환매 협의git clone [email protected]:mmaia/kafka-local-kubernetes.git.

사전 요구 사항, 설치:

  • Docker
  • Kubectl
  • Kind
  • 스토리지 클래스를 사용하여 설정


    위의 재구매 계약을 체결한 경우 여기에 표시된 설정은 storage-class-setup 폴더 아래에 있습니다.이 폴더에서 여러 개의 Kubernetes 성명 파일을 찾을 수 있습니다. 모든 파일을 하나의 단독 파일로 통합할 수도 있고, 세 개의 대시 --- 를 포함하는 줄로 구분할 수도 있습니다. 이 파일을 통합하는 것을 좋아하면 터미널을 열고, 메모리 클래스 설정 폴더에서 실행될 수도 있습니다. for each in ./kafka-k8s/*; do cat $each; echo "---"; done > local-kafka-combined.yaml 모든 파일을 local kafka combined라는 파일로 통합할 수 있습니다.아마르.

    The main thing to notice in this setup below compared to the previous one is that you don't have any PV or PVC configuration files this time because we're leveraging the default Rancher local-path-provisioner provided by Kind automatically through it's default Storage class.


    이 예에서 모든 종류를 현시적으로 구분하기 위해서, 이것은 매우 편리하기 때문에,kubectl을 직접 실행할 수 있고, 디렉터리를 가리킬 수 있기 때문에, 아래의 '실행하기' 부분에서 말한 바와 같이.kind-config.yaml - 이 파일은 IDE나 명령줄에서 개발할 때 프로그램을 연결하고 Kubernetes에서 실행되는 Kafka와 모드 등록표 포트를 로컬 컴퓨터 호스트에 공개하도록 Kind를 설정합니다.kind-config.yaml - 이 파일은 IDE나 명령줄에서 개발할 때 프로그램을 연결하고 Kubernetes에서 실행되는 kafka와 구조 등록표 포트를 로컬 호스트에 공개하도록 Kind를 설정합니다. 또한 Rancher storage provisioner의 기본 경로를 Kind 용기에서 로컬 호스트로 비추기도 합니다.
    apiVersion: kind.x-k8s.io/v1alpha4
    kind: Cluster
    nodes:
      - role: control-plane
      - role: worker
        extraPortMappings:
          - containerPort: 30092 # internal kafka nodeport
            hostPort: 9092 # port exposed on "host" machine for kafka
          - containerPort: 30081 # internal schema-registry nodeport
            hostPort: 8081 # port exposed on "host" machine for schema-registry
        extraMounts:
          - hostPath: ./tmp
            containerPath: /var/local-path-provisioner
            readOnly: false
            selinuxRelabel: false
            propagation: Bidirectional
    
    kafka-network-np.yaml - 프로그램이 사용하는 내부 Kubernetes 네트워크를 설정합니다.
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: kafka-network
    spec:
      ingress:
        - from:
            - podSelector:
                matchLabels:
                  network/kafka-network: "true"
      podSelector:
        matchLabels:
          network/kafka-network: "true"
    
    kafka-service.yaml - 이 파일은 내부 용기와 공개 포트 사이의 매핑을 정의하고 defaul은 Kubernetes에서 NodePorts라고 하며 nodeports는 범위30000 to 32767에 사용할 수 있습니다.
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        service: kafka
      name: kafka
    spec:
      selector:
        service: kafka
      ports:
        - name: internal
          port: 29092
          targetPort: 29092
        - name: external
          port: 30092
          targetPort: 9092
          nodePort: 30092
      type: NodePort
    
    kafka-ss.yaml - 이것은 카프카가 이 설정에서 정의한 것으로 이번에는 Stateful Set를 사용합니다.
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      labels:
        service: kafka
      name: kafka
    spec:
      serviceName: kafka
      replicas: 1
      selector:
        matchLabels:
          service: kafka
      template:
        metadata:
          labels:
            network/kafka-network: "true"
            service: kafka
        spec:
          enableServiceLinks: false
          containers:
          - name: kafka
            imagePullPolicy: IfNotPresent
            image: confluentinc/cp-kafka:7.0.1
            ports:
              - containerPort: 29092
              - containerPort: 9092
            env:
              - name: CONFLUENT_SUPPORT_CUSTOMER_ID
                value: "anonymous"
              - name: KAFKA_ADVERTISED_LISTENERS
                value: "INTERNAL://kafka:29092,LISTENER_EXTERNAL://kafka:9092"
              - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE
                value: "true"
              - name: KAFKA_BROKER_ID
                value: "1"
              - name: KAFKA_DEFAULT_REPLICATION_FACTOR
                value: "1"
              - name: KAFKA_INTER_BROKER_LISTENER_NAME
                value: "INTERNAL"
              - name: KAFKA_LISTENERS
                value: "INTERNAL://:29092,LISTENER_EXTERNAL://:9092"
              - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
                value: "INTERNAL:PLAINTEXT,LISTENER_EXTERNAL:PLAINTEXT"
              - name: KAFKA_NUM_PARTITIONS
                value: "1"
              - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR
                value: "1"
              - name: KAFKA_LOG_CLEANUP_POLICY
                value: "compact"
              - name: KAFKA_ZOOKEEPER_CONNECT
                value: "zookeeper:2181"
            resources: {}
            volumeMounts:
              - mountPath: /var/lib/kafka/data
                name: kafka-data
          hostname: kafka
          restartPolicy: Always
      volumeClaimTemplates:
        - metadata:
            name: kafka-data
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 1Gi
    
    나머지 파일은 schema registry와zookeeper에 제출된 성명성 Kubernetes 프로필입니다.schema-registry-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        service: schema-registry
      name: schema-registry
    spec:
      replicas: 1
      selector:
        matchLabels:
          service: schema-registry
      strategy: {}
      template:
        metadata:
          labels:
            network/kafka-network: "true"
            service: schema-registry
        spec:
          enableServiceLinks: false
          containers:
            - env:
                - name: SCHEMA_REGISTRY_HOST_NAME
                  value: "schema-registry"
                - name: SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS
                  value: "kafka:29092"
                - name: SCHEMA_REGISTRY_LISTENERS
                  value: "http://0.0.0.0:30081"
              image: confluentinc/cp-schema-registry:7.0.1
              name: schema-registry
              ports:
                - containerPort: 30081
              resources: {}
          hostname: schema-registry
          restartPolicy: Always
    
    
    schema-registry-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        service: schema-registry
      name: schema-registry
    spec:
      ports:
        - port: 30081
          name: outport
          targetPort: 30081
          nodePort: 30081
      type: NodePort
      selector:
        service: schema-registry
    
    zookeeper-service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        service: zookeeper
      name: zookeeper
    spec:
      ports:
        - name: "2181"
          port: 2181
          targetPort: 2181
      selector:
        service: zookeeper
    
    zookeeper-ss.yaml - 이번의 주요 차이점은 상태 집합의 사용이다.
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      labels:
        service: zookeeper
      name: zookeeper
    spec:
      serviceName: zookeeper
      replicas: 1
      selector:
        matchLabels:
          service: zookeeper
      template:
        metadata:
          labels:
            network/kafka-network: "true"
            service: zookeeper
        spec:
          enableServiceLinks: false
          containers:
            - name: zookeeper
              imagePullPolicy: IfNotPresent
              image: confluentinc/cp-zookeeper:7.0.1
              ports:
                - containerPort: 2181
              env:
                - name: ZOOKEEPER_CLIENT_PORT
                  value: "2181"
                - name: ZOOKEEPER_DATA_DIR
                  value: "/var/lib/zookeeper/data"
                - name: ZOOKEEPER_LOG_DIR
                  value: "/var/lib/zookeeper/log"
                - name: ZOOKEEPER_SERVER_ID
                  value: "1"
              resources: {}
              volumeMounts:
                - mountPath: /var/lib/zookeeper/data
                  name: zookeeper-data
                - mountPath: /var/lib/zookeeper/log
                  name: zookeeper-log
          hostname: zookeeper
          restartPolicy: Always
      volumeClaimTemplates:
        - metadata:
            name: zookeeper-data
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 250Mi
        - metadata:
            name: zookeeper-log
          spec:
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 250Mi
    
    

    그것을 운행하다

  • 메모리 클래스 설정 폴더의 터미널과 cd를 엽니다.
  • 'tmp'라는 폴더를 만듭니다. 이 폴더에 저장은 기본 종류의 저장소에서 자동으로 설정됩니다.
    수업
  • 실행 종류 지정 설정: kind create cluster --config=kind-config.yml.쿠베르네트스의 향연이 열릴 것이다
    비행기를 조종하다.
  • 카프카드kubectl apply -f kafka-k8s에kubernetes 설정 실행
  • 완성 후kubernetes 대상을 정지: kubectl delete -f kafka-k8s, 필요하면kind 그룹을 정지합니다
    호스트의 스토리지도 제거됩니다kind delete cluster.
  • After running the kubectl apply command(step 4 above) check your local tmp folder where you will find the automated storage mapped to your local host disk, notice that those folders will be deleted when you shutdown the Kind cluster but they will persist over pod restarts of Kafka and zookeeper.


    카프카드 클라이언트 연결


    내가 이 부분을 추가하기로 결정한 것은 개발자들이 그들의 Kafka 클라이언트를 IDE나 로컬 개발 기기에서 docker, docker compose,kubernetes에서 실행하는 로컬 Kafka로 연결하기 어려운 것을 자주 보았기 때문이다. 주로 클라이언트가 실행할 때 오류가 발생하여 호스트 Kafka를 찾을 수 없기 때문이다.
    이 문제를 해결할 수 있는 많은 방법이 있는데, 나는 여기서 몇 가지 방법을 설명할 것이다.
  • 가장 간단한 방법은 카프카와 schema registry를 호스트의/etc/hosts 파일에 추가하는 것이다. 이렇게 하면 프록시 설정LISTENER_EXTERNAL://kafka:9092이 카프카 클라이언트에게 알릴 때 클라이언트는kafkalocalhost로 해석하여 정상적으로 작업을 할 수 있다.일부 구성에서는 schema-registry를 사용하여 동일한 작업을 수행할 수 있습니다.어떤 사람들은 이렇게 하는 것을 좋아하지 않기 때문에 선택이 있다.
  • compose 파일이나kubernetes kafka 프로필의 프로필을 LISTENER_EXTERNAL://localhost:9092로 변경합니다. 따라서 현재 로컬 클라이언트에서 kafka broker address를localhost:9092로 지정합니다. 클라이언트가 에이전트에서 받은 방송 주소와 일치하기 때문입니다.이렇게 하는 것은 docker compose나kubernetes 네트워크에 있는 용기로 프로그램을 포장해서 로컬로 실행하기로 결정하면 호출이 실패합니다.localhost가 나중에 프로그램 용기/pod를 가리키기 때문에kafka가 아니라 프로그램 용기/pod를 가리키기 때문입니다.
  • Kubernetes를 사용할 때 유사한 Telepresence 도구를 사용하여 Kubernetes 포트를 노출하고 연결합니다.
  • docker compose를 사용할 때, nicely in this article에서 말한 바와 같이 docker 내부 주소를 사용할 수 있습니다.
  • 너는 이 책Confluent blog post에서 왜 이런 상황이 발생했는지에 대한 상세한 설명을 찾을 수 있다.
    이렇게, 완성, 당신은 실용적인 로컬 카프카 +
    Kubernetes에서 실행되는 모드 등록표는 개발자 기기나 IDE에서 실행되는 프로그램을 통해 접근할 수 있습니다.
    사진 작성자Fotis FotopoulosUnsplash

    좋은 웹페이지 즐겨찾기