概要

Kafkaに魅せられて、とりあえず手元のマシンで動かしてみましょうか、、、と、インフラしか知らないSEがMacBookProを新たに購入し、Qiita等にアップされている諸先輩方の記事を参考にさせていただき、ローカルのDocker環境でKafkaを動作確認したまでの手順を、過去に7回に分け記載しました。その7回に記事についてはこちらから参照ください。
今回は、そのDocker環境で動いていたKafka検証システムの docker-compose.yml を Kubernetes環境のマニファスト(yaml形式)でどのように定義し直すのかを確認しました。

kafka-k8s-1.png

上図に従い、マニフェストを定義しています。

PodManifestProducer/Comsumerpython-iot-dev.yamlzookeeperzookeeper-v1.yamlbrokerbroker-v1.yamlksql-server/ksql-cliksql-v1.yaml

なお、Producwe/Consumer については、Docker Image 作成のため、Dockerfile も定義しています。

実行環境

macOS Big Sur 11.1
Docker version 20.10.2, build 2291f61
Python 3.8.3

Kubernetes環境

Diamanti spektra kubernetes
Harbor
windows DNS

作業のディレクトリ構成

作業のディレクトリ構成は以下となります

$ tree                
.
├── Dockerfile
├── broker-v1.yaml
├── ksql-v1.yaml
├── opt
│   ├── Consumer-v1.py
│   └── Producer-v1.py
├── python-iot-dev.yaml
├── requirements.txt
└── zookeeper-v1.yaml

Producer/Consumer の Dockerfile

Producer/Consumer で共通のDocker Image となります。
Producer/Consumerで稼働させるプログラムをコピーしておきます。

FROM python:3.8.3-slim
USER root

RUN apt-get update
RUN apt-get -y install locales && localedef -f UTF-8 -i ja_JP ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less
RUN apt-get install -y dnsutils iputils-ping net-tools procps netcat

COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install -r requirements.txt

WORKDIR /opt/app
COPY ./opt/*.py /opt/app/.

マニフェスト

zookeeper、broker、 ksql-server/ksql-cli、Producer/Comsumer の4つに分けて定義しました。

### Producer/Comsumer ###
apiVersion: apps/v1
kind: Deployment
metadata:
  name: iot
  namespace: spektra-demo-tenant01-project-nw-kafka
  labels:
    app: iot
spec:
  replicas: 2
  selector:
    matchLabels:
      app: iot
  template:
    metadata:
      namespace: spektra-demo-tenant01-project-nw-kafka
      labels:
        app: iot
    spec:
      containers:
      - name: iot-dev
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
        image: harbor.nwdiamanti.local/nw-kafka/python-iot:1.0.0
        tty: true
      dnsConfig:
        options:
        - name: ndots
          value: "1"
      imagePullSecrets:
      - name: harbor
### zookeeper ###
apiVersion: v1
kind: Service
metadata:
  name: kafka-zookeeper
  namespace: spektra-demo-tenant01-project-nw-kafka
spec:
  ports:
  - port: 32181
    protocol: TCP
    targetPort: 32181
  selector:
    app: kafka-zookeeper
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-zookeeper
  namespace: spektra-demo-tenant01-project-nw-kafka
  labels:
    app: kafka-zookeeper
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka-zookeeper
  template:
    metadata:
      namespace: spektra-demo-tenant01-project-nw-kafka
      labels:
        app: kafka-zookeeper
    spec:
      containers:
      - name: zookeeper
        image: confluentinc/cp-zookeeper:5.5.1
        imagePullPolicy: Always
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
        env:
        - name: ZOOKEEPER_CLIENT_PORT
          value: "32181"
        - name: ZOOKEEPER_TICK_TIME
          value: "2000"
        ports:
        - containerPort: 32181
          protocol: TCP
      dnsConfig:
        options:
        - name: ndots
          value: "1"
### broker ###
apiVersion: v1
kind: Service
metadata:
  name: kafka-broker
  namespace: spektra-demo-tenant01-project-nw-kafka
spec:
  ports:
  - port: 29092
    protocol: TCP
    targetPort: 29092
  selector:
    app: kafka-broker
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-broker
  namespace: spektra-demo-tenant01-project-nw-kafka
  labels:
    app: kafka-broker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka-broker
  template:
    metadata:
      namespace: spektra-demo-tenant01-project-nw-kafka
      labels:
        app: kafka-broker
    spec:
      containers:
      - name: broker
        image: confluentinc/cp-kafka:5.5.1
        imagePullPolicy: Always
        resources:
          limits:
            cpu: 1000m
            memory: 2Gi
        env:
        - name: KAFKA_BROKER_ID
          value: "1"
        - name: KAFKA_ZOOKEEPER_CONNECT
          value: kafka-zookeeper:32181
        - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
          value: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
        - name: KAFKA_ADVERTISED_LISTENERS
          value: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
        - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR
          value: "1"
        - name: CONFLUENT_SUPPORT_METRICS_ENABLE
          value: "false"
        ports:
        - containerPort: 9092
          protocol: TCP
        - containerPort: 29092
          protocol: TCP
      dnsConfig:
        options:
        - name: ndots
          value: "1"
### ksql-server ###
apiVersion: v1
kind: Service
metadata:
  name: kafka-ksql-server
  namespace: spektra-demo-tenant01-project-nw-kafka
spec:
  ports:
  - port: 8088
    protocol: TCP
    targetPort: 8088
  selector:
    app: kafka-ksql-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-ksql-server
  namespace: spektra-demo-tenant01-project-nw-kafka
  labels:
    app: kafka-ksql-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka-ksql-server
  template:
    metadata:
      namespace: spektra-demo-tenant01-project-nw-kafka
      labels:
        app: kafka-ksql-server
    spec:
      containers:
      - name: ksql-server
        image: confluentinc/cp-ksql-server:5.4.3
        imagePullPolicy: Always
        resources:
          limits:
            cpu: 2000m
            memory: 2Gi
        env:
        - name: KSQL_CONFIG_DIR
          value: /etc/ksql
        - name: KSQL_LOG4J_OPTS
          value: -Dlog4j.configuration=file:/etc/ksql/log4j-rolling.properties
        - name: KSQL_BOOTSTRAP_SERVERS
          value: kafka-broker:29092
        - name: KSQL_HOST_NAME
          value: ksql-server
        - name: KSQL_APPLICATION_ID
          value: IoT-K8S-1
        - name: KSQL_LISTENERS
          value: http://0.0.0.0:8088
        - name: KSQL_CACHE_MAX_BYTES_BUFFERING
          value: "0"
        - name: KSQL_AUTO_OFFSET_RESET
          value: earliest
        ports:
        - containerPort: 8088
          protocol: TCP
      dnsConfig:
        options:
        - name: ndots
          value: "1"
---
### ksql-cli ###
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-ksql-cli
  namespace: spektra-demo-tenant01-project-nw-kafka
  labels:
    app: kafka-ksql-cli
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka-ksql-cli
  template:
    metadata:
      namespace: spektra-demo-tenant01-project-nw-kafka
      labels:
        app: kafka-ksql-cli
    spec:
      containers:
      - name: ksql-cli
        image: confluentinc/cp-ksql-cli:5.4.3
        imagePullPolicy: Always
        resources:
          limits:
            cpu: 1000m
            memory: 512Mi
        tty: true
      dnsConfig:
        options:
        - name: ndots
          value: "1"

Docker環境下での Dockerfile と docker-compose.yml の過去情報

Producer/Comsumer の Dockerfile と docker-compose.yaml についてはこちらを参照ください。
zookeeper と broker と ksql-server/ksql-cli の docker-compose.yaml についてはこちらを参照ください。

Harbor へ Producer/Comsumer の Docker Image の Push

Docker Image を作成し、コンテナレジストリ(Harbor)に Push します。

$ docker image build -t python-iot:3.8.3-slim .
$ docker image ls                            
REPOSITORY        TAG            IMAGE ID       CREATED          SIZE
python-iot        3.8.3-slim     5966a0f42ed5   29 minutes ago   331MB

$ docker tag python-iot:3.8.3-slim harbor.nwdiamanti.local/nw-kafka/python-iot:1.0.0
$ docker login harbor.nwdiamanti.local
$ docker push harbor.nwdiamanti.local/nw-kafka/python-iot:1.0.0

各Pod の作成

4つのマニフェストから各種Podの起動と確認

$ kubectl apply -f python-iot-dev.yaml 
deployment.apps/iot created

$ kubectl apply -f zookeeper-v1.yaml 
 service/kafka-zookeeper created
 deployment.apps/kafka-zookeeper created

$ kubectl apply -f broker-v1.yaml 
 service/kafka-broker created
 deployment.apps/kafka-broker created

$ kubectl apply -f ksql-v1.yaml 
  service/kafka-ksql-server created
  deployment.apps/kafka-ksql-server created
  deployment.apps/kafka-ksql-cli created

$ kubectl get pod -n spektra-demo-tenant01-project-nw-kafka -o wide
   NAME                                READY   STATUS    RESTARTS   AGE
   iot-b948b544-82nhj                  1/1     Running   0          12h   <--- Producer使用
   iot-b948b544-whkbn                  1/1     Running   0          12h   <--- Consumer使用
   kafka-broker-f79866747-vp6tc        1/1     Running   0          12h
   kafka-ksql-cli-64565d78db-fx6xz     1/1     Running   0          12h
   kafka-ksql-server-f8766c6f5-mtgqz   1/1     Running   0          12h
   kafka-zookeeper-6bf5c4c6bf-88zrz    1/1     Running   0          12h

実行結果

もちろん、これ と同じ結果となりました。

最後に

アプリ屋さんが、kubectl等のコマンドを叩き、Kubernetes環境下でのコンテナプログラムの動きまでを体感しましたが、やはり、アプリ屋が本業に注力するためには、CI/CDの仕組の導入が必要だと痛感した。

参考情報

以下の情報を参考にさせていただきました。感謝申し上げます。
Kubernetes まとめ
Kubernetes のServiceについてまとめてみた
コンテナリポジトリ Harbor in kubernetes の検証
Kubernetes :kubectl コマンド一覧
Kubernetes のポッドが起動しない原因と対策
Kubernetes 1.10 Cluster内DNSの挙動確認

广告
将在 10 秒后关闭
bannerAds