在Kubernetes中集中管理具有不同架构(Intel、ARM)的节点的方法是什么?

首先

这次我们将尝试配置Kubernetes以便统一管理不同架构的节点。许多用户可能同时拥有在服务器或个人电脑上广泛使用的与Intel兼容指令集架构(以下简称amd64)的CPU,以及在树莓派等小型电脑上使用的ARM指令集架构(以下简称arm)的CPU。

迄今为止,组建集群环境(包括服务器集中管理)的经典做法是统一架构。然而,现在是物联网时代。现在越来越多的情况是,将由小型PC(如传感器等)组成的边缘计算与用于分析已收集的传感器数据的大型服务器/云计算(核心计算)合并构建成一个边缘-核心服务。换句话说,从服务角度看,边缘和核心的计算被结合起来用于执行服务的一个计算环境。此外,从管理这些计算机的管理员角度来看,即使增加了同一架构设备的数量,只要监视方式和软件更新等操作方式相同,负担并不会有太大变化。负担激增的原因是不同架构类型的设备增多。对管理员来说,针对每种不同架构类型的设备都需要使用不同的监视方式和更新操作方式就是一场噩梦。因此,管理员想要支持/管理各种设备以满足物联网的需求,但实际上却做不到,这是现实吗?

因此,本次我们将构建一个混合了不同架构的Kubernetes集群,并且旨在通过Kubernetes实现统一管理的环境。具体而言,我们将在Mac(Intel Core i7:amd64架构)虚拟机上搭建的Kubernetes Master中添加树莓派(ARMv8:arm架构)作为节点。我们将创建一个由多种架构(异构)构建的Kubernetes集群环境,而不是只有amd64(或arm)单一架构(同质化)的硬件。通过这样做,我们可以使用Kubernetes统一管理不同架构的节点。

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

设定

这次使用的设定环境是下一个环境。

    • Mac(amd64)のVirtualBox上に構築されたKubernetes Cluster

kubeadm にてセットアップ
Master, Node x 2 のKubernetes Cluster
Pod NetworkにFlannelを使用

Mac上にインストールされたkubectl

上記のKubernetes Clusterを管理

Raspberry Pi3 ModuleB+(arm)

Raspberry PI と kubeadm で自宅 Kubernetes クラスタを構築する
を参考に”kubeadmのインストール”までを実施

从下一节开始,在Mac上搭建的基于VirtualBox的amd64架构的Kubernetes集群中,添加arm架构(树莓派)的节点。

添加Raspberry Pi(arm)的Node

首先,在Raspberry Pi上添加Raspberry Pi的节点。
当使用kubeadm在Mac上设置Kubernetes主节点时,执行在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.

我们将使用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)运行。
节点k8s-node3在Raspberry Pi(arm)上运行。
仅仅通过kubeadm join命令添加节点是不会改变节点的状态为NotReady。

这是因为kube-system命名空间中的kube-proxy和kube-flannnel-ds在ARM体系结构的节点上没有运行。通过kubectl get ds命令确认,可以看到两个DaemonSet已经启动了3个,但只有amd64体系结构的节点数量(包括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文件如下。

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命令获取kube-proxy的YAML配置,并进行改良以创建上述的YAML文件。
metadata.name、metadata.labels等可以设定任意名称。
配置的关键是spec.nodeSelector。
如果节点是arm架构,则指定beta.kubernetes.io/arch: arm,以便启动此DaemonSet。
同时,指定arm架构的容器镜像。
将spec.containers.image设置为gcr.io/google_containers/kube-proxy-arm:v1.10.2。这将使arm架构的节点上运行kube-proxy-arm容器镜像。
使用kubectl命令部署所创建的kube-proxy-arm.yaml文件。

$ 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节点上有3个kube-proxy在运行,在arm节点上有1个kube-proxy在运行。

添加 kube-flannel-ds(arm)

接下来,我们将设置适用于arm处理器的kube-flannel-ds。
以下是要使用的kube-flannel-ds的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.nodeSelector中指定了beta.kubernetes.io/arch: arm。同时,还要指定容器镜像为quay.io/coreos/flannel:v0.9.1-arm。通过kubectl命令部署创建的kube-flannel-ds-arm.yaml文件。

$ 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架构上运行的。因此,在AM64架构的节点上有3个kube-flannel-ds实例,在ARM架构的节点上有1个kube-flannel-ds实例。

确定Node

在执行arm架构节点(k8s-node3)上的kube-proxy和kube-flannel-ds之后,可以使用kubectl命令来检查节点的状态。
可以看到k8s-node3的状态已更改为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集群环境。通过这个环境,管理员可以通过kubectl命令进行集中管理。Kubernetes的用户需要选择在amd64和arm架构上以什么方式运行应用程序。可以通过在nodeSelector中指定beta.kubernetes.io/arch: arm来进行选择。这样可以轻松地指定amd64和arm的环境。

另外,作为管理不同异构硬件的方法,我们也可以分别建立amd64和arm的Kubernetes集群。这种情况下,管理员需要管理多个Kubernetes集群,并需要管理多个网络、API访问点和证书等。因此,如果针对amd64和arm分别运营的服务有所不同,考虑到网络分割等因素可能是有效的选择。

另一方面,在运营涉及amd64和arm环境协同工作的服务时,本次建立的Kubernetes集群环境可能是有效的。例如,正如前面提到的,将用于IoT环境的传感器等设备在边缘设备(arm架构)上运行,然后将从传感器获取的数据在数据中心的计算机(amd64架构)上进行分析。

根据所运营的服务,如何建立和运营Kubernetes集群是一个令人头痛的问题,但至少Kubernetes可以选择任一方案,并选择与提供的服务和运营形式相匹配的环境。期待在未来的会议等活动中能够看到有趣的Kubernetes集群环境的介绍。

请提供相关信息
参考资料
参考资讯

    Raspberry PI と kubeadm で自宅 Kubernetes クラスタを構築する
广告
将在 10 秒后关闭
bannerAds