LoginSignup
24
17

More than 5 years have passed since last update.

アーキテクチャ{Intel, ARM}の異なるNodeをKubernetesで一元管理する方法

Last updated at Posted at 2018-05-08

はじめに

 今回は、Kubernetesで異なるアーキテクチャのNodeを一元管理するための設定を試します。多くのユーザは、サーバやPCで多く利用されているIntel互換の命令セットのアーキテクチャ(以降amd64と略します)のCPUと、RaspberryPiなど小型PCで利用されているARMの命令セットのアーキテクチャ(以降armと略します)のCPUを持っている人が多いのではないでしょうか。
 これまで、クラスタ環境(サーバの集中管理も含む)を組むためには、アーキテクチャを統一するのがセオリーでした。しかし、時代はIoT時代。センサーなどの情報を取得する小型PCなどで構成されているEdgeコンピューティングと、集めたセンサーデータを分析する大型サーバ/クラウドコンピューティング(Coreコンピューティング)を併せて一つのEdge-Coreのサービスを構築しているケースが増えてきました。つまり、サービスの観点からみるとEdgeとCoreのコンピューティングを併せてサービスを実行するためのひとつのコンピューティング環境なのです。また、これらのコンピュータを管理する管理者視点で見ると、同じアーキテクチャの機器の台数が増えても、監視方法やソフトウェアのアップデートなどが同じやり方であれば負担はあまり変わりません。負担が激増するのは、異なるアーキテクャの種類が増えることです。アーキテクチャの種類毎に監視方法やアップデートなどのやり方が変わることは、管理者にとって悪夢でしかありません。そのため、管理者は、IoTの要望に応えるべく色々な機器をサポート/管理したいが、手が出せないと言うのが現実ではないでしょうか。
 そこで、今回は異なるアーキテクチャを混在させたKubernetes Cluserを構築し、Kubernesにて一元管理できる環境を目指します。具体的には、Mac(Intel Core i7: amd64アーキテクチャ)上のVirtualBox上に構築したKubernetesのMasterに、Raspberry Pi(ARMv8: armアーキテクチャ)をNodeとして追加します。amd64のみ(又はarmのみ)の単一なアーキテクチャ(ホモジーニアス)のハードウェアで構築されたKubernetes Clusterの環境ではなく、マルチなアーキテクチャ(ヘテロジーニアス)で構築されたKubernetes Clusterを作成します(下図参照)。これにより、アーキテクチャの異なるNodeをKubernetesで一元管理することが出来ます。

スクリーンショット 2018-05-08 15.55.41.png

設定

今回の設定で用いる環境は次の環境です。

次節より、Mac上のVirtualBoxのamd64アーキテクチャで構築されたKubernetes Clusterに、armアーキテクチャ(Raspberry Pi)のノードを追加します。

Raspberry Pi(arm)のNodeを追加

初めにRaspberry PiのNodeを追加します。
kubeadmを使いMac上にKubernetes masterをセットアップした際に、出力されたNode追加のコマンドをRaspberry Pi上で実行します。

$ sudo kubeadm join 192.168.0.23:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxxx
<snip>
[discovery] Successfully established connection with API Server "192.168.0.23:6443"

This node has joined the cluster:
* Certificate signing request was sent to master and a response
  was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.

Nodeが追加されたかどうかをkubectlコマンドにて確認します。

$ kubectl get nodes
NAME        STATUS     ROLES     AGE       VERSION
k8s         Ready      master    7d        v1.10.2
k8s-node1   Ready      <none>    7d        v1.10.2
k8s-node2   Ready      <none>    7d        v1.10.2
k8s-node3   NotReady   <none>    17s       v1.10.2

masterのk8s,k8s-node1,k8s-node2がMac上(amd64)で動いているNodeになります。
k8s-node3がRaspberry Pi(arm)で動いているNodeになります。
単にkubeadm joinコマンドでNodeを追加しただけではSTATUSはNotReadyのままとなります。

これは、kube-systemネームスペースのkube-proxyとkube-flannnel-dsがarmアーキテクチャ上のNodeで実行されていないためです。
kubectl get dsコマンドで確認すると、両DaemonSetが3つづつ起動しており、amd64アーキテクチャのNode数(Master含む)しか起動していないのがわかります。

$ kubectl get ds -n kube-system
NAME              DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
kube-flannel-ds   3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d
kube-proxy        3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d

kube-proxy(arm)を追加

armに対応したkube-proxyをセットアップします。
使用するkube-proxyのYAMLファイルを次に記します。

kube-proxy-arm.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  creationTimestamp: null
  generation: 1
  labels:
    k8s-app: kube-proxy-arm
  name: kube-proxy-arm
  selfLink: /apis/extensions/v1beta1/namespaces/kube-system/daemonsets/kube-proxy-arm
  namespace: kube-system
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kube-proxy-arm
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s-app: kube-proxy-arm
    spec:
      nodeSelector:
        beta.kubernetes.io/arch: arm
      containers:
      - command:
        - /usr/local/bin/kube-proxy
        - --kubeconfig=/var/lib/kube-proxy/kubeconfig.conf
        image: gcr.io/google_containers/kube-proxy-arm:v1.10.2
        imagePullPolicy: IfNotPresent
        name: kube-proxy-arm
        resources: {}
        securityContext:
          privileged: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/lib/kube-proxy
          name: kube-proxy
        - mountPath: /run/xtables.lock
          name: xtables-lock
        - mountPath: /lib/modules
          name: lib-modules
          readOnly: true
      dnsPolicy: ClusterFirst
      hostNetwork: true
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: kube-proxy
      serviceAccountName: kube-proxy
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/master
      - effect: NoSchedule
        key: node.cloudprovider.kubernetes.io/uninitialized
        value: "true"
      volumes:
      - configMap:
          defaultMode: 420
          name: kube-proxy
        name: kube-proxy
      - hostPath:
          path: /run/xtables.lock
          type: FileOrCreate
        name: xtables-lock
      - hostPath:
          path: /lib/modules
          type: ""
        name: lib-modules
  templateGeneration: 4
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
status:
  currentNumberScheduled: 0
  desiredNumberScheduled: 0
  numberMisscheduled: 0
  numberReady: 0

 kubectl get ds kube-proxy -n kube-system -o yamlコマンドで出力されるYAMLを改良し上記のYAMLファイルを作成します。
metadata.name,metadata.labelsなどは、任意の名前を設定します。
設定のキーポイントは、spec.nodeSelectorです。
Nodeがarmアーキテクチャの場合に、このDaemonSetが立ち上がるようにbeta.kubernetes.io/arch: armと指定します。
併せて、armアーキテクチャのコンテナイメージを指定します。
spec.containers.imagegcr.io/google_containers/kube-proxy-arm:v1.10.2を指定します。これにより、armアーキテクチャのNodeでkibe-proxy-armのコンテナイメージが実行されるようになります。
 作成したkube-proxy-arm.yamlをkubectlコマンドでデプロイします。

$ kubectl create -f kube-proxy-arm.yaml 
daemonset.extensions "kube-proxy-arm" created

$ kubectl get ds -n kube-system 
NAME              DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
kube-flannel-ds   3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d
kube-proxy        3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d
kube-proxy-arm    1         1         1         1            1           beta.kubernetes.io/arch=arm     16s

kube-proxy-armがarmアーキテクチャ上で動作しているのがわかります。これで、amd64のNodeで3つ、armのNodeで1つのkube-proxyが実行します。

kube-flannel-ds(arm)を追加

続いて、armに対応したkube-flannel-dsをセットアップします。
使用するkube-flannel-dsのYAMLファイルを次に記します。

kube-flannel-ds-arm.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-arm
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      hostNetwork: true
      nodeSelector:
        beta.kubernetes.io/arch: arm
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.9.1-arm
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conf
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.9.1-arm
        command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]
        securityContext:
          privileged: true
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg

 ここでのキーポイントもspec.template.spec.nodeSelectorbeta.kubernetes.io/arch: armを指定する点です。
併せてコンテナイメージもquay.io/coreos/flannel:v0.9.1-armを指定します。
 作成したkube-flannel-ds-arm.yamlをkubectlコマンドでデプロイします。

$ kubectl create -f kube-flannel-ds-arm.yaml 
daemonset.extensions "kube-flannel-ds-arm" created

$ kubectl get ds -n kube-system
NAME                  DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR                   AGE
kube-flannel-ds       3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d
kube-flannel-ds-arm   1         1         1         1            1           beta.kubernetes.io/arch=arm     13s
kube-proxy            3         3         3         3            3           beta.kubernetes.io/arch=amd64   7d
kube-proxy-arm        1         1         1         1            1           beta.kubernetes.io/arch=arm     11m

kube-flannel-dsがarmアーキテクチャ上で動作しているのがわかります。これで、amd64のNodeで3つ、armのNodeで1つのkube-flannel-dsが実行します。

Nodeの確認

kube-proxy,kube-flannel-dsがarmアーキテクチャのNode(k8s-node3)で実行された後、kubectlコマンドでNodeのSTATUSを確認します。
k8s-node3のSTATUSがReadyに変更され、無事に動作しているのがわかります。

$ kubectl get nodes
NAME        STATUS    ROLES     AGE       VERSION
k8s         Ready     master    7d        v1.10.2
k8s-node1   Ready     <none>    7d        v1.10.2
k8s-node2   Ready     <none>    7d        v1.10.2
k8s-node3   Ready     <none>    55m       v1.10.2

以上で構築完了です。

感想

 今回、amd64とarmアーキテクチャのヘテロジーニアスなハードウェアのKubernetes Cluster環境を構築しました。これにより、管理者はkubectlコマンドにて一元管理することが可能となります。Kubernetesの利用者は、アプリケーションをamd64, armアーキテクャの何で動作させるかを選択する必要があります。選択には、nodeSelectorbeta.kubernetes.io/arch: armを指定します。これにより、amd64, armの環境を容易に指定できます。
 また、今回とは異なるヘテロジーニアスなハードウェアの管理方法として、amd64,arm毎に別々にKubernetes Clusterを構築する方法もあるかと思います。その場合、管理者は複数のKubernetes Clusterを管理することになり、複数のネットワークやAPIのアクセスポイント、証明書などの管理が必要となります。そのため、amd64,arm毎に運用するサービスが異なる場合には、ネットワーク分割なども併せて考慮すると有効かと思います。
 一方で、amd64,arm環境が連携し動作するようなサービスを運用する場合には、今回のKubernetes Clusterの環境が有効かもしれません。例えば、文頭で述べたように、IoT環境で利用するセンサーなどをRaspberry Piといった小型PCをEdge(armアーキテクャ)で動作させ、センサーから得たデータをセンター側のコンピュータ(amd64アーキテクチャ)で分析を行うといったサービスです。
 運用するサービスにより、Kubernetes Clusterをどう構築・運用するのか悩ましいところですが、少なくともKubernetesは、どちらの選択肢を取ることも可能であり、提供するサービスと運用形態によりマッチした環境を選べます。今後カンファレンスなどで面白いKubernetes Clusterの環境が発表されることを期待します。

参考情報

24
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
17