Kubernetesに触れる: データの永続化についてとKafkaクラスターのデプロイ

之前:

    • KubernetesからみたDocker

 

    • Kubernetesに触れる

 

    Kubernetesに触れる: Kubernetes内のネットワークとDNS

今回はKubernetes上のデータの永続化(Volume, PersistentVolumeClaim)について説明したあと、KafkaとZookeeperクラスターをKubernetes上にデプロイするManifestファイルを眺めながら、そこで出てくるリソースについて軽く説明する。

关于数据持久化

Kubernetes不适合的情况

いわゆる状態を持つことをKubernetesでもそのままstatefulという言葉で表現する。Kubernetesにおける”stateful”の明確な定義を私はまだ述べられないけれど、少なくともDBやKafkaのような、永続化されたデータを扱うタイプのPodのことをstatefulと呼んでいる。これはNginxがstatelessと呼ばれることと対比して考えるとわかりやすい。

Cloud Native DevOps with Kubernetesという書籍では、はっきりと「データベース(のようなstatefulなPod)をKubernetesで動かすことはお勧めしない」と記載されている。似たようなことを言う人はWeb上にも沢山見受けられる。例えば -> https://www.quora.com/Is-it-a-good-way-to-run-Kafka-on-Kubernetes

勘違いのないように述べておくと、Kubernetesでもデータの永続化をしたり、それを操作するDBをデプロイすることはできるし、さらに完全にプロダクションレベルでそれを動かすことはできる。

作为不推荐的理由之一,是因为Manifest非常技巧性并且变得复杂。引入Kubernetes的初衷之一应该是为了减少对基础架构的关注,集中精力在核心工作上。考虑到这一点,也许无法找到在Kubernetes上运行数据库需要付出巨大努力的价值。相比之下,直接在主机上运行可能更容易管理和处理故障。

Kubernetes上のアプリケーションでデータベースを使う際の代替案として挙げられているのが、クラウドプロバイダーが提供するPaaSを利用することである。

尽管有这样的背景,我们现在要看一下如何在Kubernetes上持久化数据的方法。

体积

Dockerのときと同じように、Podでもホスト上のファイルやディレクトリをマウントできる。例えば以下のようにManifestファイルを記述すればよい。

apiVersion: v1
kind: Pod
metadata:
  name: cent-hostpath
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container-1
    image: centos:7
    command: ['sleep', '3600']
    volumeMounts:
    - mountPath: "/tmp"
      name: sample-hostpath
  volumes:
    - name: sample-hostpath
      hostPath:
        path: /tmp
        type: DirectoryOrCreate

これはCentOS7のcotainerをsleep 3600コマンドを実行しているだけの無意味なものである。spec.volumeMountsのフィールドにあるところで、Container内の/tmpのディレクトリをsample-hostpathという名前のVolumeで定義されたところにマウントすることを指定している。そのあとのspec.volumesでsample-hostpathという名前で指定されたホストの領域を指定している。

尽管可以利用主机域,但这是明显的反模式,所以不会继续深入探讨。

或许以下的emptyDir可能还有其它的用途。

apiVersion: v1
kind: Pod
metadata:
  name: cent
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container-1
    image: centos:7
    command: ['sleep', '3600']
    volumeMounts:
    - mountPath: "/tmp"
      name: sample-emptydir
  - name: myapp-container-2
    image: centos:7
    command: ['sleep', '3600']
    volumeMounts:
    - mountPath: "/tmp"
      name: sample-emptydir
  volumes:
    - name: sample-emptydir
      emptyDir: {}

spec.volumesの中にemptyDirが定義された。これはPod内に作成される疑似的な”ホスト上のディレクトリ”で、Podが削除されたらこの領域も削除される。従ってデータの永続化はできない。とはいえ、上のようにPodの中に複数のContainerがある場合には、この領域を互いのContainerで共有できることにある。例えばPodの中でPub/Subを実現したい場合に、Pub用のContainerがこの領域に何かを書き込んで、Sub用のContainerがこの領域内のファイルをtailするような構成にすればそれができる。こうした使い方は有意義かもしれない。

SC, PV, PVC 可以被汉化为”SC,PV,PVC”。

首先,在使用Kubernetes进行数据持久化时,假设数据存储位置在Kubernetes集群的外部。Pod会通过网络访问该存储位置。

データを永続化したい場合は、StorageClass(SC), PersistentVolumeClaim(PVC)と呼ばれる概念を知る必要がある。(今回はDynamic Provisioningを扱う。PersistentVolumeを手動で定義する方法は扱わないので、この2つの概念しか説明しない)

存储类

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: managed-premium-retain
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Retain
parameters:
  storageaccounttype: Premium_LRS
  kind: Managed
    • クラウドプロバイダーが提供するディスク(例えばAzureであればAzure File)をKubernetesで扱うための設定。

 

    • この例ではmanaged-premium-retainというStorageClassリソース名で「AzureのPremium_LRSというタイプのディスク(SSDのやつ)を」を宣言している。

 

    クラウドプロバイダー別にパラメータが変わる。Kubernetes公式ドキュメントには利用できるprovisionerが一覧となっている => https://kubernetes.io/docs/concepts/storage/storage-classes/

持久存储卷索求

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: azure-managed-disk
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: managed-premium-retain
  resources:
    requests:
      storage: 5Gi
    • 使用するディスクのサイズや、アクセスモード(リードオンリーや色々なPodから書き込みもできるかどうか)といったことを定義するもの。

 

    この例ではazure-managed-diskというPersistentVolumeClaimリソース名で「managed-premium-retainというディスクを使って、一つのPodからしかアクセスできず(ReadWriteOnce)、サイズは5Gi使う」ということを宣言している。

要真正地使用这个,

只需将上述定义的persistentVolumeClaim指定在spec.volumes中的Pod定义中。

kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: nginx:1.15.5
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi
    volumeMounts:
    - mountPath: "/mnt/azure"
      name: volume
  volumes:
    - name: volume
      persistentVolumeClaim:
        claimName: azure-managed-disk

如果总结以上内容的话

PodはPersistentVolumeClaimを指定する。

PersistentVolumeClaimはStorageClassを指定する。

这意味着从Pod无法知道使用了哪个实际的磁盘。这里实现了Pod与实际磁盘的松耦合关系。

またStatefulSetならば、Podの定義と同じファイルにPersistentVolumeClaimを記述できる。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cent
spec:
  selector:
    matchLabels:
      app: cent
  replicas: 3
  template:
    metadata:
      labels:
        app: cent
    spec:
      containers:
      - name: cent
        image: centos:7
        command: ['sleep', '3600']
        volumeMounts:
        - name: instatefulset
          mountPath: /tmp
  volumeClaimTemplates:
  - metadata:
      name: instatefulset
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-premium-retain"
      resources:
        requests:
          storage: 1Gi

部署Kafka和Zookeeper集群。

上記を踏まえてKafkaとZookeeperのクラスターをデプロイするyamlを眺める。

动物园管理员:https://github.com/kubernetes/contrib/blob/6530ce7c043610a18bdcfbfccda0984d3b068659/statefulsets/zookeeper/zookeeper.yaml

Kafka:https://github.com/kubernetes/contrib/blob/6a70f578cb71d04992ecc0543aef291b30614d00/statefulsets/kafka/kafka.yaml 改写成中文的版本:Kafka:https://github.com/kubernetes/contrib/blob/6a70f578cb71d04992ecc0543aef291b30614d00/statefulsets/kafka/kafka.yaml

这是一个相当庞大的宣言。以下内容得到关注:

    • ClusterIPをつけない、HeadlessなServiceを作る。ホストに対して直接名前でアクセスできるように。前回のCNAME云々の話を参照

 

    • StatefulSetとしてPodをデプロイしている。

 

    • 例えばNodeのメンテナンスなどであるNodeからZookeeperを退避させないときに、動いているZookeeperの数を少なくとも2つは保っておくことを定義する -> PodDisruptionbudget

同じNodeにZookeeperが立ってはならない -> podAntiAffinity

Podが正常に動いているかの確認 -> readinessProbeとlivvenessProbe

zookeeperのmyidやkafkaのbeokerIdを、Podのhostnameから動的につけられるようにしている。
データの永続化

广告
将在 10 秒后关闭
bannerAds