Kubernetes 几种存储方式性能对比 (转载)

Portworx阅读(159)评论(0)

原文来自:

https://blog.fleeto.us/post/kubernetes-storage-performance-comparison/

摘要

本文展示了一个简单的存储对比,使用未经性能优化的多种存储提供的存储卷进行测试和比较。

忽略 Azure 的原生 PVC 或 hostPath ,我们可以得出如下测试结果:

  • Portworx 是 AKS 上最快的容器存储。
  • Ceph 是私有云集群上最快的开源存储后端。对公有云来说,其操作太过复杂,这些多余的复杂性并没有能提供更好的测试表现。
  • OpenEBS 的概念很棒,但是其后端需要更多优化。

如果你正在运行 Kubernetes,你可能正在使用,或者准备使用动态供给的块存卷 ,而首当其冲的问题就是为集群选择合适的存储技术。这个事情并不能用一个简单的测试来做出简单的回答,告诉你目前市面上最好的技术是什么。存储技术的选择过程中,集群上运行的负载类型是一个重要的输入。对于裸金属集群来说,需要根据实际用例进行选择,并集成到自己的硬件之中。公有云中的托管 K8s,例如 AKS、EKS 或者 GKE,都具有开箱可用的块存储能力,然而这也不见得就是最好的选择。有很多因素需要考虑,比如说公有云的 StorageClass 的故障转移时间太长。例如在 一个针对 AWS EBS 的故障测试中,加载了卷的 Pod 用了超过五分钟才成功的在另一个节点上启动。Portworx 或者 OpenEBS 这样的云原生存储产品,正在尝试解决这类问题。

本文的目标是使用最常见的 Kubernetes 存储方案,进行基本的性能对比。我觉得在 Azure AKS 上使用下列后端:

  • AKS 原生 Storageclass:Azure native premium
  • 使用 cStor 后端的 OpenEBS
  • Portworx
  • Heketi 管理的 Gluster
  • Rook 管理的 Ceph

现在我们来介绍每种存储后端,并交代一下安装过程,然后进入 AKS 测试环境进行测试,最后得出结果。

存储

这一节中介绍测试中用到的存储方案,包含安装过程以及该方案的优缺点。

Azure 原生 StorageClass

我选择这一方案的动机是以此作为所有测试的基线。这个方案 应该 提供最佳性能。Azure 动态的创建托管磁盘,并把它们映射到 K8s 的虚拟机中,最终成为 Pod 的存储卷。

这个方案很方便,什么多余的步骤都不需要。创建一个新的 AKS 集群之后,就自动提供了两个预定义的 StorageClass,分别是 default 和 managed-premium ,premium 使用的是基于 SSD 的高性能低延迟磁盘。

$ kubectl get storageclasses
NAME                PROVISIONER                AGE
default(default)   kubernetes.io/azure-disk   8m
managed-premium     kubernetes.io/azure-disk   8m

$ kubectl get pvc
NAME              STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
dbench-pv-claim   Bound     pvc-e7bd34a4-1dbd-11e9-8726-ae508476e8ad   1000Gi     RWO            managed-premium   10s

$ kubectl get po
NAME           READY     STATUS              RESTARTS   AGE
dbench-w7nqf   0/1ContainerCreating029s

优点

AKS 开箱即用。

缺点

故障转移非常缓慢,有时需要十分钟以后,存储卷才能重新挂载到不同节点上的 Pod 里。

OpenEBS

对我来说 OpenEBS 是个全新事物,因此我很有兴趣做他的测试。他提出了一个新的 Container Attached Storage(容器挂载存储) 概念,这是一个基于微服务的存储控制器,以及多个基于微服务的存储副本。他和 Portworx 同样,属于云原生存储分类的成员。

它是一个完全开源的方案,目前提供两种后端——Jiva 和 cStor。我最开始选择的是 Jiva,后来切换到 cStor。cStor 有很多长处,例如他的控制器和副本被部署到单一的 OpenEBS 所在的命名空间之中,能够管理原始磁盘等。每个 K8s 卷都有自己的存储控制器,能在节点存储容量的许可范围内对存储进行扩展。

在 AKS 上运行

在 AKS 上的安装非常容易。

  1. 连接到所有 K8s 节点上,安装 iSCSI,这是因为他需要使用 iSCSI 协议在 K8s 节点之间进行 Pod 和控制器的连接。
    apt-get update
    apt install -y open-iscsi
  2. 使用一个 YAML 定义在 K8s 集群上完成部署:
    kubectl apply -f https://openebs.github.io/charts/openebs-operator-0.8.0.yaml
  3. 下一步,OpenEBS 控制器发现了节点中的所有磁盘。但是我必须手工标识出我附加的 AWS 托管磁盘。
    $ kubectl get disk
    NAME                                      AGE
    disk-184d99015253054c48c4aa3f17d137b15m
    disk-2f6bced7ba9b2be230ca5138fd0b07f15m
    disk-806d3e77dd2e38f188fdaf9c46020bdc5m
  4. 然后把这些磁盘加入 StoragePoolClaim,这个对象会在 StorageClass 中进行引用:
    ---
    apiVersion: storage.k8s.io/v1
    kind:StorageClass
    metadata:
      name: openebs-custom
      annotations:
        openebs.io/cas-type: cstor
        cas.openebs.io/config😐
          - name:StoragePoolClaim
            value:"cstor-disk"
    provisioner: openebs.io/provisioner-iscsi
    ---
    apiVersion: openebs.io/v1alpha1
    kind:StoragePoolClaim
    metadata:
      name: cstor-disk
    spec:
      name: cstor-disk
      type: disk
      maxPools:3
      poolSpec:
        poolType: striped
      disks:
        diskList:
        - disk-2f6bced7ba9b2be230ca5138fd0b07f1
        - disk-806d3e77dd2e38f188fdaf9c46020bdc
        - disk-184d99015253054c48c4aa3f17d137b1

完成这些步骤之后,就可以用 K8s 的 PVC 来动态的创建存储卷了。

优点

  • 开源
  • Maya 在资源使用的可视化方面做得非常好。可以在 K8s 中部署多个服务,方便的为集群的各方面数据设置监控和日志。对于排错工作来说,这十分重要。
  • CAS 概念:我非常欣赏这一概念,我相信这是未来的趋势。
  • OpenEBS 社区:在社区中我的任何问题都能在几分钟内得到解决。Slack 上的团队非常有帮助。

缺点

  • 不成熟:OpenEBS 还很年轻,目前还没有发布稳定版。核心团队还在进行后端的优化,未来几个月里会对性能做出很大提升。
  • Kubelet 和存储控制器之间的 iSCSI 连接是通过 K8s Service 进行的,这在 Tungsten Fabric 之类的 CNI 插件环境中可能会出问题。
  • 需要在 K8s 节点上安装额外的软件(iSCSI),这对于托管集群来说非常不便。

注:OpenEBS 团队对我的案例场景进行了调整:

https://github.com/kmova/openebs/tree/fio-perf-tests/k8s/demo/dbench

Portworx

Portworx 是另一个面向 Kubernetes 的容器原生存储方案,它专注于高度分布式的环境。这是一个主机可寻址的存储,每个卷都直接映射到挂在的主机上。他提供了基于应用 I/O 类型的自动微调能力。 官方网站 提供了更多信息。不幸的是,它也是本文中唯一的非开源产品。然而它提供了 3 节点的免费试用。

在 AKS 上运行

在 AKS 上的安装同样简单,我用了他们 网站 提供的生成器。

azure0
$ kubectl get pods -o wide -n kube-system -l name=portworx
NAME             READY     STATUS    RESTARTS   AGE       IP          NODE                       NOMINATED NODE
portworx-g9csq   1/1Running014m10.0.1.66   aks-agentpool-20273348-2<none>
portworx-nt2lq   1/1Running014m10.0.1.4    aks-agentpool-20273348-0<none>
portworx-wcjnx   1/1Running014m10.0.1.35   aks-agentpool-20273348-1<none>

为 PVC 创建一个 StorageClass,定义高优先级,以及三个副本:

root@aks-agentpool-20273348-0:~# kubectl get storageclass -o yaml portworx-sc
apiVersion: storage.k8s.io/v1
kind:StorageClass
metadata:
  creationTimestamp:2019-01-28T21:10:28Z
  name: portworx-sc
  resourceVersion:"55332"
  selfLink:/apis/storage.k8s.io/v1/storageclasses/portworx-sc
  uid:23455e40-2341-11e9-bfcb-a23b1ec87092
parameters:
  priority_io: high
  repl:"3"
provisioner: kubernetes.io/portworx-volume
reclaimPolicy:Delete
volumeBindingMode:Immediate

优点

  • 部署方便:生成器包含配置细节。
  • 不像 Ceph 和 Glusterfs 那样需要进行额外配置。
  • 云原生存储:公有云和裸金属都可以运行。
  • 存储级别感知和应用感知的 I/O 微调。

缺点

  • 闭源:商业解决方案

GlusterFS Heketi

GlusterFS 是知名的开源存储方案,是由 Redhat 提供的开源存储方案。 Heketi 是 GlusterFS 的 RESTful 卷管理界面。它提供了易用的方式为 GlusterFS 卷提供了动态供给的功能。如果没有 Heketi 的辅助,就只能手工创建 GlusterFS 卷并映射到 K8s PV 了。关于 GlusterFS 的更多信息,请阅读 官方文档 。

在 AKS 上运行

根据 Heketi 的 快速入门 文档进行部署。

  1. 参照 样例 ,创建一个包含磁盘和主机名的拓扑文件。
  2. Heketi 主要的开发和测试都在基于 RHEL 的操作系统上,我在 AKS 上使用 Ubuntu 主机时,出现了内核模块路径错误的问题,我提交了一个 PR 来修正这个问题。

    ~~~ +++ b/deploy/kube-templates/glusterfs-daemonset.yaml @@ -67,7 +67,7 @@ spec: mountPath: “/etc/ssl” readOnly: true – name: kernel-modules

    name: kernel-modules hostPath:

    mountPath: “/usr/lib/modules”

    mountPath: “/lib/modules” readOnly: true securityContext: capabilities: {} @@ -131,4 +131,4 @@ spec: path: “/etc/ssl”

    path: “/usr/lib/modules”

    path: “/lib/modules” ~~~

  3.  

    我在 AKS 环境中遇到的另一个问题是一个非空磁盘,所以我用 wipefs 为 glusterfs 进行清理。这个磁盘并未用过。

     

    $ wipefs -a /dev/sdc /dev/sdc: 8 bytes were erased at offset 0x00000218 (LVM2_member): 4c 56 4d 32 20 30 30 31

  4. 最后运行 gk-deploy -g -t topology.json ,会在每个节点上运行 Heketi 控制器管理之下的 GlusterFS Pod。
    $ kubectl get po -o wide
    NAME                     READY   STATUS    RESTARTS IP        NODE                       NOMINATED NODE
    glusterfs-fgc8f          1/1Running010.0.1.35  aks-agentpool-20273348-1
    glusterfs-g8ht6          1/1Running010.0.1.4   aks-agentpool-20273348-0
    glusterfs-wpzzp          1/1Running010.0.1.66  aks-agentpool-20273348-2
    heketi-86f98754c-n8qfb   1/1Running010.0.1.69  aks-agentpool-20273348-2

    然后我遇到了新问题。K8s 控制面无法使用 Heketi 的 restURL 。我测试了一下 kube dns 的记录,pod IP 和 svc IP 都没有生效。最后只能手工使用 Heketi CLI 来创建存储卷。 

$ export HEKETI_CLI_SERVER=http://10.0.1.69:8080
$ heketi-cli volume create --size=10--persistent-volume --persistent-volume-endpoint=heketi-storage-endpoints | kubectl create -f -
persistentvolume/glusterfs-efb3b155 created

$ kubectl get pv
NAME                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
glusterfs-efb3b155   10Gi       RWX            RetainAvailable

然后把现存 PV 映射为 PVC,加载给测试 工具 进行测试。

kind:PersistentVolumeClaim
apiVersion: v1
metadata:
  name: glusterfs-efb3b155
spec:
  accessModes:
    -ReadWriteMany
  storageClassName:""
  resources:
    requests:
      storage:10Gi
  volumeName: glusterfs-efb3b155
$ kubectl get pvc
NAME                 STATUS    VOLUME               CAPACITY   ACCESS MODES   STORAGECLASS   AGE
glusterfs-efb3b155   Bound     glusterfs-efb3b155   10Gi       RWX                           36m

Heketi 的更多输出:

$ gluster volume info vol_efb3b15529aa9aba889d7900f0ce9849

VolumeName: vol_efb3b15529aa9aba889d7900f0ce9849
Type:ReplicateVolume ID:96fde36b-e389-4dbe-887b-baae32789436
Status:StartedSnapshotCount:0Number of Bricks:1 x 3=3Transport-type: tcp
Bricks:Brick1:10.0.1.66:/var/lib/heketi/mounts/vg_5413895eade683e1ca035760c1e0ffd0/brick_cd7c419bc4f4ff38bbc100c6d7b93605/brick
Brick2:10.0.1.35:/var/lib/heketi/mounts/vg_3277c6764dbce56b5a01426088901f6d/brick_6cbd74e9bed4758110c67cfe4d4edb53/brick
Brick3:10.0.1.4:/var/lib/heketi/mounts/vg_29d6152eeafc57a707bef56f091afe44/brick_4856d63b721d794e7a4cbb4a6f048d96/brick
OptionsReconfigured:
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

$ kubectl get svc
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
heketi                     ClusterIP192.168.101.75<none>8080/TCP   5h
heketi-storage-endpoints   ClusterIP192.168.103.66<none>1/TCP      5h

$ kubectl get endpoints
NAME                       ENDPOINTS                            AGE
heketi                     10.0.1.69:80805h
heketi-storage-endpoints   10.0.1.35:1,10.0.1.4:1,10.0.1.66:15h
kubernetes                 172.31.22.152:4431d
root@aks-agentpool-20273348-0:~# kubectl get endpoints heketi-storage-endpoints -o yaml
apiVersion: v1
kind:Endpoints
metadata:
  creationTimestamp:2019-01-29T15:14:28Z
  name: heketi-storage-endpoints
  namespace:default
  resourceVersion:"142212"
  selfLink:/api/v1/namespaces/default/endpoints/heketi-storage-endpoints
  uid:91f802eb-23d8-11e9-bfcb-a23b1ec87092
subsets:- addresses:
  - ip:10.0.1.35
  - ip:10.0.1.4
  - ip:10.0.1.66
  ports:
  - port:1
    protocol: TCP

优点

  • 久经考验的存储方案。
  • 比 Ceph 轻量。

缺点

  • Heketi 在公有云上表现不佳。在私有云上表现良好,安装会方便一些。
  • 并非为结构化数据设计,例如 SQL 数据库。然而可以使用 GlusterFS 为 数据库 提供备份和恢复支持。

Ceph Rook

我在 OpenStack 私有云上尝试过安装和运行 Ceph。它需要为特定硬件定制参数,根据数据类型设计 pg 组、SSD 分区和 CRUSH 图等。所以第一次听说在 3 节点的 K8s 集群上运行 Ceph 的时候,我不太相信它能工作。结果 Rook 的编排工具让我印象深刻,它把所有的步骤和 K8s 的编排能力结合在一起,让安装变得非常简便。

在 AKS 上运行

Rook 的缺省安装无需任何特定步骤,如果没什么高级配置,会非常简单。

  1. 我使用的是 Ceph 快速入门指南

  2. 为 AKS 配置 FLEXVOLUME_DIR_PATH ,这是因为它需要 /etc/kubernetes/volumeplugins/ ,而不是 Ubuntu 中缺省的 /usr/libexec ,没有这个步骤,Kubelet 就 无法加载 PVC 了。

    ~~~ diff –git a/cluster/examples/kubernetes/ceph/operator.yaml b/cluster/examples/kubernetes/ceph/operator.yaml index 73cde2e..33f45c8 100755 — a/cluster/examples/kubernetes/ceph/operator.yaml +++ b/cluster/examples/kubernetes/ceph/operator.yaml @@ -431,8 +431,8 @@ spec: # – name: AGENT_MOUNT_SECURITY_MODE # value: “Any” # Set the path where the Rook agent can find the flex volumes

    • # – name: FLEXVOLUME_DIR_PATH
    • # value: “

    • – name: FLEXVOLUME_DIR_PATH
    • value: “/etc/kubernetes/volumeplugins” # Set the path where kernel modules can be found # – name: LIB_MODULES_DIR_PATH # value: “

      “ ~~~

  3. 还要在 deviceFilter 中指定要使用的设备,这里是 /dev/sdc 。

    ~~~ diff –git a/cluster/examples/kubernetes/ceph/cluster.yaml b/cluster/examples/kubernetes/ceph/cluster.yaml index 48cfeeb..0c91c48 100755 — a/cluster/examples/kubernetes/ceph/cluster.yaml +++ b/cluster/examples/kubernetes/ceph/cluster.yaml @@ -227,7 +227,7 @@ spec: storage: # cluster level storage configuration and selection useAllNodes: true useAllDevices: false

    • deviceFilter:
    • deviceFilter: “^sdc” location: config: ~~~
  4. 安装之后,创建一个 Ceph block pool,以及 StorageClass,使用如下配置。
    apiVersion: ceph.rook.io/v1
    kind:CephBlockPool
    metadata:
      name: replicapool
      namespace: rook-ceph
    spec:
      failureDomain: host
      replicated:
        size:3---
    apiVersion: storage.k8s.io/v1
    kind:StorageClass
    metadata:
       name: rook-ceph-block
    provisioner: ceph.rook.io/block
    parameters:
      blockPool: replicapool
      clusterNamespace: rook-ceph
      fstype: xfs
    reclaimPolicy:Retain
  5. 最后使用部署 工具 进行检查。

ceph status
  cluster:
    id:     bee70a10-dce1-4725-9285-b9ec5d0c3a5e
    health: HEALTH_OK

  services:
    mon:3 daemons, quorum c,b,a
    mgr: a(active)
    osd:3 osds:3 up,3in

  data:
    pools:0 pools,0 pgs
    objects:0  objects,0 B
    usage:3.0GiB used,3.0TiB/3.0TiB avail
    pgs:[root@aks-agentpool-27654233-0/]#[root@aks-agentpool-27654233-0/]#[root@aks-agentpool-27654233-0/]# ceph osd status
+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+| id |           host           |  used | avail | wr ops | wr data | rd ops | rd data |   state   |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+|0| aks-agentpool-27654233-0|1025M|1021G|0|0|0|0| exists,up ||1| aks-agentpool-27654233-1|1025M|1021G|0|0|0|0| exists,up ||2| aks-agentpool-27654233-2|1025M|1021G|0|0|0|0| exists,up |+----+--------------------------+-------+-------+--------+---------+--------+---------+-----------+

优点

  • 在大型生产环境上的健壮存储系统。
  • Rook 很好的简化了生命周期管理。

缺点

  • 复杂:更加重量级,也不太适合在公有云上运行。在私有云上的运行可能更加合适。

AKS 测试环境

我用 3 个虚拟机创建了基本的 Azure AKS 集群。为了连接到 Premium SSD 上,我只能使用 type E 以上级别的虚拟机。因此我选择了 Standard_E2s_v3 ,其上配备了 2 vCPU 以及 16GB 的内存。

在 AKS 集群所在的资源足中,可以看到所有的虚拟机、网络接口等资源。在这里创建 3 个 1TB 的 Premium SSD 存储,并手工挂载到每个虚拟机上。

这样在每个实例上,我都有 1TB 的空磁盘。Azure 的页面上,根据我们选择的虚拟机和磁盘尺寸来看,性能应该有 5000 IOPS 以及 200MB/s 的吞吐量。最后一节会显示我们的真实结果。

性能结果

注意:每种存储的结果并不能作为独立的评估结果,但是其比较情况是可以参考的。有很多种对比测试的方法,这是最简单的一种。

为了运行测试,我决定使用现成的测试工具 Dbench ,它是一个 k8s 的 YAML 文件,会使用 FIO 运行 8 个测试用例。可以在 Dockerfile 中 指定不同测试 :

  • 随机读写带宽。
  • 随机读写 IOPS。
  • 读写延迟。
  • 顺序读写。
  • 混合读写 IOPS。

所有测试的结果可以在 Github 上找到。

随机读写带宽

随机读写测试表明,GlusterFS、Ceph 以及 Portworx 的读取性能比 AWS 本地盘的 hostPath 快了几倍。读缓存是罪魁祸首。GlusterFS 和 Portworx 的写入更快,其效率直逼本地磁盘。

随机读写 IOPS

随机 IOPS 测试中,Portworx 和 Ceph 表现最好。Portworx 在写入方面获得了接近 Azure 原生 PVC 的 IOPS。

读写延迟

延迟测试的结果比较有趣,Azure 原生 PVC 比多数其它存储都差。Portworx 和 Ceph 表现最好。写入方面,GlusterFS 要优于 Ceph。OpenEBS 的延迟相对来说非常的高。

顺序读写

顺序读写的结果和前面的随机测试差不多,然而 Cpeh 在读取方面比 GlusterFS 快了一倍多。写入结果基本一致,只有 OpenEBS 表现奇差。

混合读写 IOPS

最后一个测试用例检查的是混合读写情况下的 IOPS,Portworx 和 Ceph 都给出了优于 Azure 原生 PVC 的结果。

结论

本文展示了一个简单的存储对比,使用未经性能优化的多种存储提供的存储卷进行测试和比较。建议关注本文所述方法,不建议直接采用结果进行判断。

忽略 Azure 的原生 PVC 或 hostPath ,我们可以得出如下测试结果:

  • Portworx 是 AKS 上最快的容器存储。
  • Ceph 是私有云集群上最快的开源存储后端。对公有云来说,其操作太过复杂,这些多余的复杂性并没有能提供更好的测试表现。
  • OpenEBS 的概念很棒,但是其后端需要更多优化。

调整性能数据的测试规模应该会很有意思。另外值得关注的对比就是 CPU 和内存的消耗。我会持续关注,并分享更多。

从零开始入门 K8s | 手把手带你理解 etcd

alicloudnative阅读(560)评论(0)

作者 | 曾凡松(逐灵) 阿里云容器平台高级技术专家

本文整理自《CNCF x Alibaba 云原生技术公开课》第 16 讲。

导读:etcd 是用于共享配置和服务发现的分布式、一致性的 KV 存储系统。本文从 etcd 项目发展所经历的几个重要时刻开始,为大家介绍了 etcd 的总体架构及其设计中的基本原理。希望能够帮助大家更好的理解和使用 etcd。

一、etcd 项目的发展历程

etcd 诞生于 CoreOS 公司,它最初是用于解决集群管理系统中 OS 升级的分布式并发控制以及配置文件的存储与分发等问题。基于此,etcd 被设计为提供高可用、强一致的小型 keyvalue 数据存储服务。

项目当前隶属于 CNCF 基金会,被 AWS、Google、Microsoft、Alibaba 等大型互联网公司广泛使用。

1.png

最初,在 2013 年 6 月份由 CoreOS 公司向 GitHub 中提交了第一个版本的初始代码。

到了 2014 年的 6 月,社区发生了一件事情,Kubernetes v0.4 版本发布。这里有必要介绍一下 Kubernetes 项目,它首先是一个容器管理平台,由谷歌开发并贡献给社区,因为它集齐了谷歌在容器调度以及集群管理等领域的多年经验,从诞生之初就备受瞩目。在 Kubernetes v0.4 版本中,它使用了 etcd 0.2 版本作为实验核心元数据的存储服务,自此 etcd 社区得到了飞速的发展。

很快,在 2015 年 2 月份,etcd 发布了第一个正式的稳定版本 2.0。在 2.0 版本中,etcd 重新设计了 Raft 一致性算法,并为用户提供了一个简单的树形数据视图,在 2.0 版本中 etcd 支持每秒超过 1000 次的写入性能,满足了当时绝大多数的应用场景需求。2.0 版本发布之后,经过不断的迭代与改进,其原有的数据存储方案逐渐成为了新时期的性能瓶颈,之后 etcd 启动了 v3 版本的方案设计。

2017 年 1 月份的时候,etcd 发布了 3.1 版本,v3 版本方案基本上标志着 etcd 技术上全面成熟。在 v3 版本中 etcd 提供了一套全新的 API,重新实现了更高效的一致性读取方法,并且提供了一个 gRPC 的 proxy 用于扩展 etcd 的读取性能。同时,在 v3 版本的方案中包含了大量的 GC 优化,在性能优化方面取得了长足的进步,在该版本中 etcd 可以支持每秒超过 10000 次的写入。

2018 年,CNCF 基金会下的众多项目都使用了 etcd 作为其核心的数据存储。据不完全统计,使用 etcd 的项目超过了 30 个,在同年 11 月份,etcd 项目自身也成为了 CNCF 旗下的孵化项目。进入 CNCF 基金会后,etcd 拥有了超过 400 个贡献组,其中包含了来自 AWS、Google、Alibaba 等 8 个公司的 9 个项目维护者。

2019 年,etcd 即将发布全新的 3.4 版本,该版本由 Google、Alibaba 等公司联合打造,将进一步改进 etcd 的性能及稳定性,以满足在超大型公司使用中苛刻的场景要求。

二、架构及内部机制解析

总体架构

etcd 是一个分布式的、可靠的 key-value 存储系统,它用于存储分布式系统中的关键数据,这个定义非常重要。

2.png

一个 etcd 集群,通常会由 3 个或者 5 个节点组成,多个节点之间通过 Raft 一致性算法的完成分布式一致性协同,算法会选举出一个主节点作为 leader,由 leader 负责数据的同步与数据的分发。当 leader 出现故障后系统会自动地选取另一个节点成为 leader,并重新完成数据的同步。客户端在多个节点中,仅需要选择其中的任意一个就可以完成数据的读写,内部的状态及数据协同由 etcd 自身完成。

在 etcd 整个架构中,有一个非常关键的概念叫做 quorum,quorum 的定义是 (n+1)/2,也就是说超过集群中半数节点组成的一个团体,在 3 个节点的集群中,etcd 可以容许 1 个节点故障,也就是只要有任何 2 个节点可用,etcd 就可以继续提供服务。同理,在 5 个节点的集群中,只要有任何 3 个节点可用,etcd 就可以继续提供服务,这也是 etcd 集群高可用的关键。

在允许部分节点故障之后继续提供服务,就需要解决一个非常复杂的问题:分布式一致性。在 etcd 中,该分布式一致性算法由 Raft 一致性算法完成,这个算法本身是比较复杂的有机会再详细展开,这里仅做一个简单的介绍以方便大家对其有一个基本的认知。Raft 一致性算法能够工作的一个关键点是:任意两个 quorum 的成员之间一定会有一个交集(公共成员),也就是说只要有任意一个 quorum 存活,其中一定存在某一个节点(公共成员),它包含着集群中所有的被确认提交的数据。正是基于这一原理,Raft 一致性算法设计了一套数据同步机制,在 Leader 任期切换后能够重新同步上一个 quorum 被提交的所有数据,从而保证整个集群状态向前推进的过程中保持数据的一致。

3.png

etcd 内部的机制比较复杂,但 etcd 给客户提供的接口是简单直接的。如上图所示,我们可以通过 etcd 提供的客户端去访问集群的数据,也可以直接通过 http 的方式(类似 curl 命令)直接访问 etcd。在 etcd 内部,其数据表示也是比较简单的,我们可以直接把 etcd 的数据存储理解为一个有序的 map,它存储着 key-value 数据。同时 etcd 为了方便客户端去订阅数据的变更,也支持了一个 watch 机制,通过 watch 实时地拿到 etcd 中数据的增量更新,从而实现与 etcd 中的数据同步等业务逻辑。

API 介绍

接下来我们看一下 etcd 提供的接口,这里将 etcd 的接口分为了 5 组:

4.png

  • 第一组是 Put 与 Delete。上图可以看到 put 与 delete 的操作都非常简单,只需要提供一个 key 和一个 value,就可以向集群中写入数据了,删除数据的时候只需要指定 key 即可;
  • 第二组是查询操作。etcd 支持两种类型的查询:第一种是指定单个 key 的查询,第二种是指定的一个 key 的范围;
  • 第三组是数据订阅。etcd 提供了 Watch 机制,我们可以利用 watch 实时订阅到 etcd 中增量的数据更新,watch 支持指定单个 key,也可以指定一个 key 的前缀,在实际应用场景中的通常会采用第二种形势;
  • 第四组事务操作。etcd 提供了一个简单的事务支持,用户可以通过指定一组条件满足时执行某些动作,当条件不成立的时候执行另一组操作,类似于代码中的 if else 语句,etcd 确保整个操作的原子性;
  • 第五组是 Leases 接口。Leases 接口是分布式系统中常用的一种设计模式,其用法后面会具体展开。

数据版本机制

要正确使用 etcd 的 API,必须要知道内部对应数据版本号的基本原理。

首先 etcd 中有个 term 的概念,代表的是整个集群 Leader 的任期。当集群发生 Leader 切换,term 的值就会 +1。在节点故障,或者 Leader 节点网络出现问题,再或者是将整个集群停止后再次拉起,都会发生 Leader 的切换。

第二个版本号叫做 revision,revision 代表的是全局数据的版本。当数据发生变更,包括创建、修改、删除,其 revision 对应的都会 +1。特别的,在集群中跨 Leader 任期之间,revision 都会保持全局单调递增。正是 revision 的这一特性,使得集群中任意一次的修改都对应着一个唯一的 revision,因此我们可以通过 revision 来支持数据的 MVCC,也可以支持数据的 Watch。

对于每一个 KeyValue 数据节点,etcd 中都记录了三个版本:

  • 第一个版本叫做 create_revision,是 KeyValue 在创建时对应的 revision;
  • 第二个叫做 mod_revision,是其数据被操作的时候对应的 revision;
  • 第三个 version 就是一个计数器,代表了 KeyValue 被修改了多少次。

这里可以用图的方式给大家展示一下:

5.png

在同一个 Leader 任期之内,我们发现所有的修改操作,其对应的 term 值始终都等于 2,而 revision 则保持单调递增。当重启集群之后,我们会发现所有的修改操作对应的 term 值都变成了 3。在新的 Leader 任期内,所有的 term 值都等于3,且不会发生变化,而对应的 revision 值同样保持单调递增。从一个更大的维度去看,可以发现在 term=2 和 term=3 的两个 Leader 任期之间,数据对应的 revision 值依旧保持了全局单调递增。

mvcc & streaming watch

了解 etcd 的版本号控制后,接下来如何使用 etcd 多版本号来实现并发控制以及数据订阅(Watch)。

在 etcd 中支持对同一个 Key 发起多次数据修改,每次数据修改都对应一个版本号。etcd 在实现上记录了每一次修改对应的数据,也就就意味着一个 key 在 etcd 中存在多个历史版本。在查询数据的时候如果不指定版本号,etcd 会返回 Key 对应的最新版本,当然 etcd 也支持指定一个版本号来查询历史数据。

6.png

因为 etcd 将每一次修改都记录了下来,使用 watch 订阅数据时,可以支持从任意历史时刻(指定 revision)开始创建一个 watcher,在客户端与 etcd 之间建立一个数据管道,etcd 会推送从指定 revision 开始的所有数据变更。etcd 提供的 watch 机制保证,该 Key 的数据后续的被修改之后,通过这个数据管道即时的推送给客户端。

如下图所示,etcd 中所有的数据都存储在一个 b+tree 中(灰色),该 b+tree 保存在磁盘中,并通过 mmap 的方式映射到内存用来支持快速的访问。灰色的 b+tree 中维护着 revision 到 value 的映射关系,支持通过 revision 查询对应的数据。因为 revision 是单调递增的,当我们通过 watch 来订阅指定 revision 之后的数据时,仅需要订阅该 b+ tree 的数据变化即可。

7.png

在 etcd 内部还维护着另外一个 btree(蓝色),它管理着 key 到 revision 的映射关系。当客户端使用 key 查询数据时,首先需要经过蓝色的 btree 将 key 转化为对应的 revision,再通过灰色的 btree 查询到对应的数据。

细心的读者会发现,etcd 将每一次修改都记录下来会导致数据持续增长,这会带来内存及磁盘的空间消耗,同时也会影响 b+tree 的查询效率。为了解决这一问题,在 etcd 中会运行一个周期性的 Compaction 的机制来清理历史数据,将一段时间之前的同一个 Key 的多个历史版本数据清理掉。最终的结果是灰色的 b+tree 依旧保持单调递增,但可能会出现一些空洞。

mini-transactions

在理解了 mvcc 机制及 watch 机制之后,继续看 etcd 提供的 mini-transactions 机制。etcd 的 transaction 机制比较简单,基本可以理解为一段 if-else 程序,在 if 中可以提供多个操作,如下图所示:

8.png

If 里面写了两个条件,当 Value(key1) 大于 “bar” 并且 Version(key1) 的版本等于 2 的时候,执行 Then 里面指定的操作:修改 Key2 的数据为 valueX,同时删除 Key3 的数据。如果不满足条件,则执行另外一个操作:Key2 修改为 valueY。

在 etcd 内部会保证整个事务操作的原子性。也就是说 If 操作所有的比较条件,其看到的视图一定是一致的。同时它能够确保多个操作的原子性不会出现 Then 中的操作仅执行了一半的情况。

通过 etcd 提供的事务操作,我们可以在多个竞争中去保证数据读写的一致性,比如说前面已经提到过的 Kubernetes 项目,它正是利用了 etcd 的事务机制,来实现多个 KubernetesAPI server 对同样一个数据修改的一致性。

lease 的概念及用法

lease 是分布式系统中一个常见的概念,用于代表一个分布式租约。典型情况下,在分布式系统中需要去检测一个节点是否存活的时,就需要租约机制。

9.png

上图示例中的代码示例首先创建了一个 10s 的租约,如果创建租约后不做任何的操作,那么 10s 之后,这个租约就会自动过期。接着将 key1 和 key2 两个 key value 绑定到这个租约之上,这样当租约过期时 etcd 就会自动清理掉 key1 和 key2,使得节点 key1 和 key2 具备了超时自动删除的能力。

如果希望这个租约永不过期,需要周期性的调用 KeeyAlive 方法刷新租约。比如说需要检测分布式系统中一个进程是否存活,可以在进程中去创建一个租约,并在该进程中周期性的调用 KeepAlive 的方法。如果一切正常,该节点的租约会一致保持,如果这个进程挂掉了,最终这个租约就会自动过期。

在 etcd 中,允许将多个 key 关联在同一个 lease 之上,这个设计是非常巧妙的,可以大幅减少 lease 对象刷新带来的开销。试想一下,如果有大量的 key 都需要支持类似的租约机制,每一个 key 都需要独立的去刷新租约,这会给  etcd 带来非常大的压力。通过多个 key 绑定在同一个 lease 的模式,我们可以将超时间相似的 key 聚合在一起,从而大幅减小租约刷新的开销,在不失灵活性同时能够大幅提高 etcd 支持的使用规模。

三、典型的使用场景介绍

元数据存储

Kubernetes 将自身所用的状态存储在 etcd 中,其状态数据的高可用交给 etcd 来解决,Kubernetes 系统自身不需要再应对复杂的分布式系统状态处理,自身的系统架构得到了大幅的简化。

10.png

Server Discovery (Naming Service)

第二个场景是 Service Discovery,也叫做名字服务。在分布式系统中,通常会出现的一个模式就是需要多个后端(可能是成百上千个进程)来提供一组对等的服务,比如说检索服务、推荐服务。

11.png

对于这样一种后端服务,通常情况下为了简化后端服务的运维成本(节点故障时随时被替换),后端的这一进程会被类似 Kubernetes 这样的集群管理系统所调度,这样当用户(或上游服务)调用过来时,我们就需要一个服务发现机制来解决服务路由问题。这一服务发现问题可以利用 etcd 来高效解决,方式如下:

  • 在进程内部启动之后,可以将自身所在的地址注册到 etcd;
  • API 网关够通过 etcd 及时感知到后端进程的地址,当后端进程发生故障迁移时会重新注册到 etcd 中,API 网关也能够及时地感知到新的地址;
  • 利用 etcd 提供的 Lease 机制,如果提供服务的进程运行过程中出现了异常(crash),API 网关也可以摘除其流量避免调用超时。

在这一架构中,服务状态数据被 etcd 接管,API 网关本身也是无状态的,可以水平地扩展来服务更多的客户。同时得益于 etcd 的良好性能,可以支持上万个后端进程的节点,使得这一架构可以服务于大型的企业。

Distributed Coordination: leader election

在分布式系统中,有一种典型的设计模式就是 Master+Slave。通常情况下,Slave 提供了 CPU、内存、磁盘以及网络等各种资源 ,而 Master 用来调和这些节点以使其对外提供一个服务(比如分布式存储,分布式计算)。典型的分布式存储服务(HDFS)以及分布式计算服务(Hadoop)它们都是采用了类似这样的设计模式。这样的设计模式会有一个典型的问题:Master 节点的可用性。当 Master 故障以后,整个集群的服务就挂掉了,没有办法再服务用户的请求。

为了解决这个问题,典型的做法就是启动多个 Master 节点。因为 Master 节点内会包含控制逻辑,多个节点之间的状态同步是非常复杂的,这里最典型的做法就是通过选主的方式,选出其中一个节点作为主节点来提供服务,另一个节点处于等待状态。

12.png

通过 etcd 提供的机制可以很容易的实现分布式进程的选主功能,比如可以通过对同一个 key 的事务写来实现抢主的逻辑。一般而言,被选主的 Leader 会将自己的 IP 注册到 etcd 中,使得 Slave 节点能够及时获取到当前的 Leader 地址,从而使得系统按照之前单个 Master 节点的方式继续工作。当 Leader 节点发生异常之后,通过 etcd 能够选取出一个新的节点成为主节点,并且注册新的 IP 之后,Slave 又能够拉取新的主节点的 IP,继续恢复服务。

Distributed Coordination 分布式系统并发控制

在分布式系统中,当我们去执行一些任务,比如说去升级 OS、或者说升级 OS 上的软件的时候、又或者去执行一些计算任务的时候,出于对后端服务的瓶颈或者是业务稳定性的考虑,通常情况下需要控制任务的并发度。如果该任务缺少一个调和的 Master 节点,可以通过 etcd 来完成这样的分布式系统工作。

13.png

在这个模式中通过 etcd 去实现一个分布式的信号量,并且可以利用 etcd leases 机制来实现自动地剔除掉故障节点。在进程执行过程中,如果进程的运行周期比较长,我们可以将进程运行过程中的一些状态数据存储到 etcd,从而使得当进程故障之后且需要恢复到其他地方时,能够从 etcd 中去恢复一些执行状态,而不需要重新去完成整个的计算逻辑,以此来加速整个任务的执行效率。

本文总结

本文分享的主要内容就到此为止了,这里为大家简单总结一下:

  • 第一部分,为大家介绍了 etcd 项目是如何诞生的,以及在 etcd 发展过程中经历的几个重要时刻;
  • 第二部分,为大家介绍了 etcd 的架构以及其内部的基本操作接口,在理解 etcd 是如何实现高可用的基础之上,展示了 etcd 数据的一些基本操作以及其内部的实现原理;
  • 第三部分,介绍了三种典型的 etcd 使用场景,以及在对应的场景下,分布式系统的设计思路。

 阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术公众号。”

Kubernetes 时代的安全软件供应链

alicloudnative阅读(176)评论(0)

本文节选自《不一样的 双11 技术:阿里巴巴经济体云原生实践》一书。

作者
汤志敏  阿里云容器服务高级技术专家
汪圣平  阿里云云平台安全高级安全专家

导读:从 Docker image 到 Helm, 从企业内部部署到全球应用分发,作为开发者的我们如何来保障应用的交付安全。本文会从软件供应链的攻击场景开始,介绍云原生时代的应用交付标准演进和阿里云上的最佳实践。

“没有集装箱,就不会有全球化”。在软件行业里,Docker 和 Kubernetes 也扮演了类似的角色,加速了软件行业的社会化分工和交付运维的效率。2013 年, Docker 公司提出了容器应用打包规范 Docker Image,帮助开发者将应用和依赖打包到一个可移植的镜像里。2015 年,Google 将 Kubernetes 捐献给 CNCF,进一步普及了大规模容器编排调度的标准。

Kubernetes 以一种声明式的容器编排与管理体系,屏蔽了底层基础架构的差异,让软件交付变得越来越标准化。随着 K8s 为代表的云原生技术的大规模运用,越来越多的容器化应用被分发到 IDC、公共云、边缘等全球各地。

在 2019 年,阿里云容器镜像服务 ACR 的月镜像下载量超过了 3 亿次。同年 10 月,阿里云云市场的容器镜像类目发布,越来越多的企业将其软件以容器的方式进行上架和销售。11 月,天猫 双11 的所有核心系统 100% 上云,容器镜像服务 ACR 除了支持 双11 的内部镜像托管以外,也将内部的能力在云上透出,支持更多的 双11 生态公司。

接下来我们看下如何保证容器和 Kubernetes 下的软件供应链安全,并先熟悉下软件供应链的常见攻击场景。

软件供应链攻击面和典型攻击场景

软件供应链通常包括三个阶段:

  • 软件研发阶段
  • 软件交付阶段
  • 软件使用阶段

在不同阶段的攻击面如下:

1.png

历史上著名的 APPLE Xcode IDE 工具攻击就是发生在软件研发阶段的攻击,攻击者通过向 Xcode 中注入恶意后门,在非官方网站提供下载,所有使用此 Xcode 的开发者编译出来的 APP 将被感染后门。同样著名的还有美国的棱镜门事件,亦是在大量的软件中植入后门程序,进行数据获取等恶意操作。

Kubernetes 中的软件供应链攻击面也包括在以上范围之中,以软件使用阶段为例,今年 RunC 漏洞 CVE-2019-5736,漏洞本身与 RunC 的运行设计原理相关,Container 之外的动态编译 Runc 被触发运行时会引用 Conainer 内部的动态库,造成 RunC 自身被恶意注入从而运行恶意程序,攻击者只需要在一个 Container 镜像中放入恶意的动态库和恶意程序,诱发受攻击者恶意下载运行进行模糊攻击,一旦受攻击者的 Container 环境符合攻击条件,既可完成攻击。

2.png

同样的攻击面还存在于 Kubernetes 自身服务组件之中,前段时间爆出的 HTTP2 CVE-2019-9512、CVE-2019-9514 漏洞就是一个非常好的软件研发阶段脆弱性的例子,漏洞存在于 GO 语言的基础 LIB 库中,任何依赖 GO 版本(<1.2.9)所编译的 KubernetesHTTP2 服务组件都受此漏洞影响,因此当时此漏洞影响了 K8s 全系列版本,攻击者可以远程 DOS Kubernetes API Server。同时在 Kubernetes 组件的整个交付过程中也存在着攻击面,相关组件存在被恶意替换以及植入的可能性。

不同于传统的软件供应链,镜像作为统一交付的标准如在容器场景下被大规模应用,因此关注镜像的使用周期可以帮助攻击者更好的设计攻击路径。

3.png

攻击者可以在镜像生命周期的任何一个阶段对镜像进行污染,包括对构建文件的篡改、对构建平台的后门植入、对传输过程中的劫持替换和修改、对镜像仓库的攻击以替换镜像文件、对镜像运行下载和升级的劫持攻击等。

整个攻击过程可以借助云化场景中相关的各种依赖,如 Kubernetes 组件漏洞、仓库的漏洞,甚至基础设施底层漏洞。对于防御者来说,对于镜像的整个生命周期的安全保障,是容器场景中攻击防范的重中之重。

云原生时代的应用交付标准演进(从 Image 到 Artifacts)

在云原生时代之前,应用交付的方式比较多样化,比如脚本、RPM 等等。而在云原生时代,为了屏蔽异构环境的差异,提供统一的部署抽象,大家对应用交付标准的统一也迫切起来。

Helm

Helm 是 Kubernetes 的包管理工具,它提出了 Chart 这个概念。

  • 一个 Chart 描述了一个部署应用的多个 Kubernetes 资源的 YAML 文件,包括文档、配置项、版本等信息;
  • 提供 Chart 级别的版本管理、升级和回滚能力。

CNAB

CNAB 是 Docker 和微软在 2018 年底联合推出平台无关的 Cloud Native Application Bundle 规范。相比于 Helm,有额外几个定义:

  • 在 thick 模式时,CNAB 的 bundle 可以包含依赖的镜像二进制,从而不需要额外去镜像仓库下载,作为一个整体打包;
  • CNAB 定义了扩展的安全标准,定义了 bundle 的签名(基于 TUF )和来源证明(基于 In-Toto)描述;
  • CNAB 的部署是平台无关性,可以部署在 K8s 之上,也可以通过 terraform 等方式来部署。

CNAB 的这些特性,可以在可信软件分发商与消费者之间进行跨平台(包括云和本地 PC)的应用打包和分发。

4.png

OCI Artifacts

2019 年 9 月,开放容器标准组织(OCI)在 OCI 分发标准之上,为了支持更多的分发格式,推出了 OCI Artifacts 项目来定义云原生制品(Cloud Native Artifacts)的规范。我们可以通过扩展 media-type 来定义一种新的 Artifacts 规范,并通过标准的镜像仓库来统一管理。

Kubernetes 时代的安全软件供应链

在之前章节也提到过,相对于传统软件的安全软件供应链管理,容器和 Kubernetes 的引入使得:

  • 发布和迭代更加频繁,容器的易变性也使得安全风险稍纵即逝;
  • 更多的不可控三方依赖,一旦一个底层基础镜像有了安全漏洞,会向病毒一样传递到上层;
  • 更大范围的全球快速分发,在分发过程中的攻击也会使得在末端执行的时造成大规模安全风险。

在传统的软件安全和安全准则之上,我们可以结合一些最佳实践,沉淀一个新的端到端安全软件供应链:

5.png

我们来看一些和安全软件供应链相关的社区技术进展:

Grafeas

2017 年 10 月,Google 联合 JFrog、IBM 等公司推出了 Grafeas。Grafeas(希腊语中的”scribe”)旨在定义统一的方式来审核和管理现代软件供应链,提供云原生制品的元数据管理能力。可以使用 Grafeas API 来存储,查询和检索有关各种软件组件的综合元数据,包括合规和风险状态。

6.png

In-toto

In-toto 提供了一个框架或策略引擎来保护软件供应链的完整性

通过验证链中的每个任务是否按计划执行(仅由授权人员执行)以及产品在运输过程中未被篡改来做到这一点。In-toto 要求项目所有者创建布局 (Layout)。布局列出了软件供应链的步骤 (Step) 顺序,以及授权执行这些步骤的工作人员。当工作人员执行跨步操作时,将收集有关所使用的命令和相关文件的信息,并将其存储在链接 (Link) 元数据文件中。通过在完整的供应链中定义每个 Step,并对 Step 进行验证,可以充分完整的完整整个供应链的安全。

Kritis

为强化 Kubernetes 的安全性,Google 引入了二进制授权 (Binary Authorization),确保使用者只能将受信任的工作负责部署到 Kubernetes 中。二进制授权可以基于 Kubernetes 的 Admission Controller 来插入部署准入检测,让只有授权后的镜像在环境中运作。

下图为一个策略示例:

7.png

同时对于在安全软件供应链中占比很大的第三方软件,需要有完善的基线机制和模糊安全测试机制来保障分发过程中的安全风险,避免带已知漏洞上线,阿里云正在与社区积极贡献帮助演进一些开源的工具链。

关于基础镜像优化、安全扫描、数字签名等领域也有非常多的工具和开源产品,在此不一一介绍。

云端的安全软件供应链最佳安全实践

在阿里云上,我们可以便捷地基于容器服务 ACK、容器镜像服务 ACR、云安全中心打造一个完整的安全软件供应链。

安全软件供应链全链路以云原生应用托管为始,以云原生应用分发为终,全链路可观测、可追踪、可自主设置。可以帮助安全需求高、业务多地域大规模部署的企业级客户,实现一次应用变更,全球化多场景自动交付,极大提升云原生应用交付的效率及安全性。

8.png

在云原生应用的安全托管阶段,容器镜像服务 ACR 支持容器镜像、Helm Chart 等云原生资产的直接上传托管;也支持从源代码(Github、Bitbucket、阿里云 Code、GitLab 来源)智能构建成容器镜像。在安全软件供应用链中,支持自动静态安全扫描并自定义配置安全阻断策略。一旦识别到静态应用中存在高危漏洞后,可自动阻断后续部署链路,通知客户失败的事件及相关漏洞报告。客户可基于漏洞报告中的修复建议,一键更新优化构建成新的镜像版本,再次触发自动安全扫描。

  • 在云原生应用的分发阶段,当安全漏洞扫描完成且应用无漏洞,应用将被自动同步分发至全球多地域。

由于使用了基于分层的调度、公网链路优化以及免公网入口开启的优化,云原生应用的全球同步效率,相比本地下载后再上传提升了 7 倍。云原生应用同步到全球多地域后,可以自动触发多场景的应用重新部署,支持在 ACK、ASK、ACK@Edge 集群中应用自动更新。针对集群内大规模节点分发场景,可以实现基于镜像快照的秒级分发,支持 3 秒 500 Pod 的镜像获取,实现业务在弹性场景下的极速更新。

  • 在云原生应用运行阶段,可实现基于云安全中心的应用运行时威胁检测与阻断,实时保障每个应用 Pod 的安全运行。

云安全中心基于云原生的部署能力,实现威胁的数据自动化采集、识别、分析、响应、处置和统一的安全管控。利用多日志关联和上下文分析方案,实时检测命令执行、代码执行、SQL 注入、数据泄露等风险,覆盖业务漏洞入侵场景。结合 K8s 日志和云平台操作日志实时进行行为审计和风险识别,实现容器服务和编排平台存在的容器逃逸、AK 泄露、未授权访问风险。

总结

随着云原生的不断发展,云原生应用也会在安全、交付、全球分发等领域持续演进。我们可以预见一个新的时代:越来越多的大型软件以积木的方式由全球开发者独立开发而最终合并组装。

点击下载《不一样的 双11 技术:阿里巴巴经济体云原生实践》

ban.jpg

 

本书亮点

  • 双11 超大规模 K8s 集群实践中,遇到的问题及解决方法详述
  • 云原生化最佳组合:Kubernetes+容器+神龙,实现核心系统 100% 上云的技术细节
  • 双 11 Service Mesh 超大规模落地解决方案

阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术公众号。”

通用电气GE微服务实践:在容器中部署有状态应用

Portworx阅读(441)评论(0)

 

通用电气GE

 

通用电气GE,创立于1892年,是世界上最大的技术和服务跨国公司。自托马斯·爱迪生创建通用电气公司以来,业务遍及世界上100多个国家,拥有员工315,000人。

 

GE在航空,电力,运输,能源等行业具备丰富的产品线和运营经验。同时GE也通过数字化的方式帮助客户进行产品的运维,数据分析和改进。GE为此建立了自己的物联网数字化平台。

 

GE采用微服务架构并通过容器来运行有状态应用。为此,需要建立CSI(Container Storage Interface),GE尝试了一些办法,但是从使用上来说并不成熟,无法给平台的用户和合作伙伴,提供简单易操作的容器存储和数据管理方法。需要有一个能够同时运行无状态应用和有状态应用的基础层。

 

最终,GE选择了与Portworx携手,来建立CSI对容器存储和数据进行有效管理。

 

Portworx建立了物理存储之上的软件定义的存储抽象层,用户不需要思考具体在使用那种物理存储,也不需要知道承载应用的是哪朵公有云或者私有云。

在没有这样一个抽象层之前,用户需要手动的把物理存储卷来分配到某个容器上。传统的存储,都是通过虚拟机和操作系统来驱动存储的,对于容器来说则很不适用。因为容器通常被编排程序Orchestrator排程在多节点的环境下来运行。应用程序也不都是在单一的容器内运行。比如Cassandra, 通常是部署在一系列的容器上。一个Cassandra集群可能会有3个、10个、15个Cassandra容器,被部署在15个不同的虚拟机上,甚至可能在不同的物理数据中心里。所以当我们尝试把某个卷添加到这样一个分布式系统里的时候,就会出现非常多的问题。这些问题需要运维工程师花大量的时间来做调整,让卷与这样的分布式系统产生映射。假如说一个5节点的Cassandra集群,这些节点都运行在哪些虚拟机上呢?又是在哪个存储上呢?于是我们不得不把应用跟虚拟机对应起来,因为我们在使用虚拟机对应的存储资源。如果虚拟机停机了,我们就不得不去手动寻找相对应的存储,然后把它和新的虚拟机对应起来。这跟云原生的思想和容器排程器Orchestrator的定位并不对路。同时新的问题又会产生,如何在这样的分布式系统里为存储设定密码?如何做快照?这些问题都将留给我们的用户,这就更有问题了。

 

作为GE,我们并不想把这样的复杂的基础架构爬坑工作留给用户。

 

Portworx本身是一种基于容器的超融合架构,将计算资源与存储有机结合在一起。同时Portworx与K8S的调度软件scheduler无缝集成。

 

像数据库这样的有状态型容器化应用需要在分布式节点上的永久数据。Portworx使用有状态的Stateful Fabric来管理数据卷,即container-SLA-aware,来做到这一点。复制卷数据确保其状态,同时满足容器化应用的性能和可用性。更重要的是,Portworx可在每个容器级别中管理其快照、克隆副本和复制操作,使DevOps能够单独管理微服务,而不是像LUNs那用做传统存储系统的绑定组。使用Portworx管理有状态容器Stateful Containers很方便,每个容器级别的数据的可用性和管理也很简单,且高度自动化。

 

如果需要部署一个Cassandra集群,而又并不想让所有的节点在同一个环网上,在同一个Availability Zone或者Failure domain,Portworx可以帮助用户更好的来架构这些分布式的应用。另外通常我们希望物理资源能够有80%以上的利用率。我们需要让不同的应用在同一个硬件内共存,而不产生IO的冲突。Portworx并不是直接把存储或者物理的LUNs跟应用连接起来,我们提供一个虚拟的存储卷层来避免IO的冲突,并实现容器的加密或者是快照。尤其是当一个容器宕机,然后又从另外一个位置恢复后,我们就能够快速找到原来的存储,并且在新的容器中恢复。同时Portworx的安全与合规管理功能,帮助GE满足公司内部对于平台架构的安全合规要求,也满足了用户和客户的存储加密,存储快照这样的需求。

Service Mesh 是新瓶装旧酒吗?

alicloudnative阅读(285)评论(0)

本文节选自《不一样的 双11 技术:阿里巴巴经济体云原生实践》一书。

作者 | 李云(花名:至简) 阿里云高级技术专家

导读:在即将过去的 2019 年,Service Mesh 开源产品的成熟度虽在全球范围内没有发生质的变化,但在国内仍出现了一些值得特别关注的事件。比如:阿里巴巴在 双11 的部分电商核心应用上落地了完整的 Service Mesh 解决方案,借助 双11 的严苛业务场景完成了规模化落地前的初步技术验证。本文作者将结合自己在阿里巴巴落地实践 Service Mesh 过程中的观察与思考,来和大家进行分享。

Service Mesh 是新瓶装旧酒吗?

新技术出现时所主张的价值一定会引发相应的探讨,Service Mesh 也不例外。

以往,怀疑 Service Mesh 价值的观点主要有两大类。

  • 第一类是应用的数量并没有达到一定的规模,在 Service Mesh 增加运维和部署复杂度的情形下,认为所带来的成本和复杂度高于所获得的收益。

从根本上来看,这一类并非真正怀疑 Service Mesh 的价值,而是主张在 Service Mesh 还没有完全成熟和普及的情形下,在未来合适的时机再考虑采纳。当然,我在与外部客户交流时也碰到一些特例,他们即便在应用数很少的情形下,仍希望通过 Service
Mesh 去解决非 Java 编程语言(比方说 Go)的分布式链路追踪等服务治理问题,虽说这些能力在 Java 领域有相对成熟的解决方案,但在非 Java 领域确实偏少,所以很自然地想到了采用 Service Mesh。

  • 第二类怀疑 Service Mesh 价值的,是应用的数量具有相当的规模且对分布式应用的规模问题也有很好的认知,但由于在发展的过程中已经积累了与 Service Mesh 能力相当的那些(非体系化的)技术,造成初识 Service Mesh 时有“老酒换新瓶”的感觉而不认可其价值。阿里巴巴过去也曾属于这一阵营。

阿里巴巴在分布式应用的开发和治理方面的整体解决方案的探索有超过十年的历程,且探索过程持续地通过 双11 这样的严苛场景做检验和孵化,采用单一的 Java 语言打造了一整套的技术。即便如此,应对分布式应用的规模问题依然不轻松,体现于因为缺乏顶层设计而面临体系性不足,加之对技术产品自身的用户体验缺乏重视,最终导致运维成本和技术门槛都偏高。在面临这些阵痛之际,云原生的概念逐渐清晰地浮出了水面。

云原生主张技术产品在最为严苛的场景下仍能提供一定质量的服务而体现良好弹性,同时也强调技术产品本身应当具有良好的易用性,以及将来为企业需要多云和混合云的 IT 基础设施提供支撑(即:帮助实现分布式应用的可移植性)。

云原生的概念不仅很好地契合了阿里巴巴集团在技术发展上亟待解决的阵痛,也迎合了阿里巴巴将云计算作为集团战略、让云计算普惠社会的初衷。在这一背景下,阿里巴巴做出了全面云原生化的决定,Service Mesh 作为云原生概念中的关键技术之一,当然也包含在其中。

Service Mesh 给阿里巴巴带来的价值

Service Mesh 所带来的第一个变化体现于:服务治理手段从过去的框架思维向平台思维转变。

这种转变并非后者否定前者,而是前后者相结合去更好地发挥各自的优势。两种思维的最大区别在于,平台思维不仅能实现应用与技术基础设施更好的解耦,也能通过平台的聚集效应让体系化的顶层设计有生发之地。

框架思维向平台思维转变在执行上集中体现于“轻量化”和“下沉”两个动作。

  • 轻量化是指将那些易变的功能从框架的 SDK 中移出,结果是使用了 SDK 的应用变得更轻,免除了因易变功能持续升级所带来的低效;也彻底让应用的开发者无需关心这些功能,让他们能更好地聚焦于业务逻辑本身;
  • 从框架中移出的功能放到了 Service Mesh 的 Sidecar 中实现了功能下沉。

Service Mesh 作为平台性技术,将由云厂商去运维和提供相应的产品,通过开源所构建的全球事实标准一旦被所有云厂商采纳并实现产品化输出,那时应用的可移植性问题就能水到渠成地解决。

功能下沉在阿里巴巴落地 Service Mesh 的过程中也看到了相应的价值。阿里巴巴的电商核心应用基本上都是用 Java 构建的,在 Mesh 化之前,RPC 的服务发现与路由是在 SDK 中完成的,为了保证 双11 这样的流量洪峰场景下的消费者用户体验,会通过预案对服务地址的变更推送做降级,避免因为频繁推送而造成应用进程出现 Full GC。Mesh 化之后,SDK 的那些功能被放到了 Sidecar(开发语言是 C++)这一独立进程中,这使得 Java 应用进程完全不会出现类似场景下的 Full GC 问题。

软件设计的质量主要体现在“概念”和“关系”两个词上。

同样功能的一个系统,不同的概念塑造与切分将产生完全不同的设计成果,甚至影响到最终软件产品的工程质量与效率。当概念确定后,关系也随之确立,而关系的质量水平体现在解耦的程度上。Service Mesh 使得应用与技术基础设施之间的关系变得更松且稳定,通过流量无损的热升级方案,使得应用与技术基础设施的演进变得独立,从而加速各自的演进效率。软件不成熟、不完善并不可怕,可怕的是演进起来太慢、包袱太重。

阿里巴巴在落地 Service Mesh 的过程中,体会到了松耦合所带来的巨大工程价值。当应用被 Mesh 化后,接下来的技术基础设施的升级对之就透明了,之前因为升级工作所需的人力配合问题可以通过技术产品化的手段完全释放。另外,以往应用进程中包含了业务逻辑和基础技术的功能,不容易讲清楚各自对计算资源的消耗,Service Mesh 通过独立进程的方式让这一问题得以更好地隔离而实现量化,有了量化结果才能更好地对技术做优化。

Service Mesh 所带来的第二个变化在于:技术平台的建设从面向单一编程语言向面向多编程语言转变。

对于初创或小规模企业来说,业务应用的开发采用单一的编程语言具有明显优势,体现于因为个体掌握的技术栈相同而能带来良好的协作效率,但当企业的发展进入了多元化、跨领域、规模更大的更高阶段时,多编程语言的诉求就随之产生,对于阿里巴巴这样的云厂商来说更是如此(所提供的云产品不可能过度约束客户所使用的编程语言)。多编程语言诉求的背后是每种编程语言都有自己的优势和适用范围,需要发挥各自的优势去加速探索与创新。

从技术层面,这一转变意味着:

  • 第一,技术平台的能力需要尽可能地服务化,避免因为服务化不彻底而需要引入 SDK,进而带来多编程语言问题(即因为没有相应编程语言的 SDK 而无法使用该编程语言);
  • 第二,在无法规避 SDK 的情形下,让 SDK 变得足够的轻且功能稳定,降低平台化和多编程语言化的工程成本,支持多编程语言 SDK 最好的手段是采用 IDL。

从组织层面,这一转变意味着平台技术团队的人员技能需要多编程语言化。一个只有单一编程语言的团队是很难做好面向多编程语言的技术平台的,不只是因为视角单一,还因为无法“吃自己的狗食”而对多编程语言问题有切肤之痛。

Service Mesh 带来的发展机遇

在这两个变化之下,我们来聊一聊 Service Mesh 所带来的发展机遇。

  • 首先,Service Mesh 创造了一次以开发者为中心去打造面向未来的分布式应用开发平台的机会。

在 Service Mesh 出现之前,各种分布式服务治理技术产品的发展,缺乏强有力的抓手去横向拉通做体系化设计和完成能力复用,因而难免出现概念抽象不一致和重新造轮子的局面,最终每个技术产品有自己的一套概念和独立的运维控制台。当多个运维控制台交到开发者手上时,他们需要做大量的学习,去理解每个运维控制台的概念以及它们之间的关系,背后所带来的困难和低效是很容易被人忽视的。

本质上,Service Mesh 的出现是解决微服务软件架构之下那些藏在应用与应用之间的复杂度的。它的出现使得所有的分布式应用的治理问题被放到了一起去考虑。换句话说,因为 Service Mesh 的出现,我们有机会就分布式应用的治理做一次全局的设计,也有机会将各种技术产品整合到一起而避免重复建设的问题。

未来的分布式应用开发平台一定是基于 Service Mesh 这一基础技术的。为此,需要借这个契机从易用性的角度重新梳理应给开发者塑造的心智。易用性心智的确立,将使得开发者能在一个运维控制台上做最少的操作,通过为他们屏蔽背后的技术实现细节,而减轻他们在使用时的脑力负担,以及降低操作失误带来安全生产事故的可能性。

理论上,没有 Service Mesh 之前这些工作也能做,但因为没有具体的横向技术做抓手而无法落地。

  • 其次,Service Mesh 给其他技术产品创造了重新思考云原生时代的发展机会。

有了 Service Mesh 后,以前很多独立的技术产品(比如,服务注册中心、消息系统、配置中心)将变成 BaaS(Backend as a Service)服务,由 Service Mesh 的 Sidecar 负责与它们对接,应用对这些服务的访问通过 Sidecar 去完成,甚至有些 BaaS 服务被 Sidecar 终结而完全对应用无感。

这些变化并非弱化了那些 BaaS 服务的重要性。相反,因为其重要性而需要与 Service Mesh 做更好的整合去为应用提供服务,与此同时探索做一定的能力增强。比方说,Service Mesh 所支持的应用版本发布的灰度功能(包括蓝绿发布、金丝雀发布、A/B 测试),并非每一个 BaaS 服务在 Mesh 化后就能很好地支持这一功能,而是需要做相应的技术改造才行。请注意,这里主要讲的是应用的灰度能力,而非 BaaS 服务自身的灰度能力。当然,并不妨碍探索通过 Service Mesh 让 BaaS 服务自身的灰度工作变得简单且低风险。

未来很多技术产品的竞争优势将体现于它能否与 Service Mesh 形成无缝整合。

无缝整合的核心驱动力,源于用户对技术产品的易用性和应用可移植性的需要。基于这一认识,阿里巴巴正在将 RocketMQ/MetaQ 消息系统的客户端中的重逻辑剥离到 Envoy 这一 Sidecar 中(思路依然是“下沉”),同时基于 Service Mesh 所提供的能力做一定的技术改造,以便 RocketMQ/MetaQ 能很好地支撑应用的灰度发布。类似这样的思考与行动,相信未来会在更多的技术产品上出现。

  • 再次,Service Mesh 给技术基础设施如何与业务基础技术更好地协同提供了一次探索机会。

每一种业务(比如电商)都会构建基于所在领域的基础技术,这类技术我们称之为业务基础技术。当阿里巴巴希望将某一业务的基础技术搬到外部去服务客户时,面临业务基础技术如何通过服务化去满足客户已选择的、与业务基础技术不同的编程语言的问题,否则会出现基于 Java 构建的业务基础技术很难与 Go 所编写的应用协同。

在 Service Mesh 致力于解决服务化问题的过程中,能否通过一定的技术手段,让业务基础技术的能力通过插件的形式“长”在 Service Mesh 之上是一个很值得探索的点。当业务基础技术以插件的形式存在时,业务基础技术无需以独立的进程存在而取得更好的性能,且这一机制也能被不同的业务复用。阿里巴巴的 Service
Mesh 技术方案所采用的 Sidecar 开源软件 Envoy 正在积极地探索通过 Wasm 技术去实现流量处理的插件机制,将该机制进一步演变成为业务基础技术插件机制是值得探索的内容。

下图示例说明了业务基础技术的插件机制。

图中两个彩色分别代表了不同的业务(比如一个代表电商,另一个代表物流),两个业务的基础技术并非开发了两个独立的应用(进程)然后做发布和运维管理,而是基于 Wasm 所支持的编程语言实现了业务技术插件,这一点可以理解为用多编程语言的方式解决业务服务化问题,而非强制要求采用与 Sidecar 一样的编程语言。插件通过 Service Mesh 的运维平台进行管理,包含安装、灰度、升级、监控等能力。

至简.png

由于插件是“长”在 Service Mesh 之上的,插件化的过程就是业务技术服务化的过程。

另外,Service Mesh 需要提供一种选择能力,让业务的应用开发者或运维者选择自己的机器上需要哪些插件(可以理解为插件市场)。另一个值得关注的点是:插件的运维和管理能力以及一定的质量保证手段由 Service Mesh 平台提供,但运维、管理和质量保证的责任由各插件的提供者承担。这种划分将有效地杜绝所有插件的质量由 Service Mesh 平台去承担而带来的低效,分而治之仍是改善很多工程效率的良方。

  • 最后,Service Mesh 给探索面向未来的异地多活、应用永远在线的整体技术解决方案打开了一扇大门。

服务之间的互联互通,服务流量的控制、观测和安全加固是微服务软件架构下所要解决的关键问题,这些问题与规模化下的服务可用性和安全性紧密相关。未来,通过 Service Mesh 的流量控制能力能做很多改善应用发布和运维效率的文章,那时才能真正看到一个灵动、称手的云平台。

Service Mesh 的“三位一体”发展思路

阿里巴巴作为云计算技术的供应商,在探索 Service Mesh 技术的道路上,不只是考虑如何让云原生技术红利在阿里巴巴内部兑现,同时还思考着如何将技术红利带给更多的阿里云客户。基于此,阿里巴巴就 Service Mesh 的整体发展思路遵循“三位一体”,即阿里巴巴内部、阿里云上的相应商业产品和开源软件将采用同一套代码。

就我们与阿里云客户交流的经验来看,他们乐于尽最大可能采用非云厂商所特有的技术方案,以免被技术锁定而在未来的发展上出现掣肘。另外,他们只有采纳开源的事实标准软件才有可能达成企业的多云和混合云战略。基于客户的这一诉求,我们在 Service Mesh 的技术发展上特别重视参与开源事实标准的共建。在 Istio 和 Envoy 两个开源项目上,我们都会致力于将内部所做的那些优化反哺给开源社区。

未来,我们将在 Service Mesh 领域坚定而扎实地探索,也一定会将探索成果和思考持续地分享给大家。

点击下载《不一样的 双11 技术:阿里巴巴经济体云原生实践》

ban.jpg

本书亮点

  • 双11 超大规模 K8s 集群实践中,遇到的问题及解决方法详述
  • 云原生化最佳组合:Kubernetes+容器+神龙,实现核心系统 100% 上云的技术细节
  • 双 11 Service Mesh 超大规模落地解决方案

阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术公众号。”

如何跨不同版本K8S,为有状态工作负载做蓝绿部署

Portworx阅读(444)评论(0)

容器的生态正在爆发!不仅仅应用层在快速变化,还有用于管理应用程序的平台:Kubernetes,也在快速变化。这就为Ops团队带来了一个必须要解决的难题。IT团队如何才能保证一款应用程序能够在各种不同版本的Kubernetes上都能良好运行呢?

PX-Motion演示:如何跨不同版本Kubernetes,为有状态的工作负载做蓝绿部署

蓝-绿部署是一种专门用于解决这一问题的技术,并能够降低生产环境部署的过程中的停机或错误风险。在蓝绿部署场景下,用户需要构建两个完全相同的生产环境(分别称为蓝与绿),这两个环境之间仅在需要部署的新的变更方面存在差异。每一次仅激活一个环境,两个环境之间的数据传输也是部署过程的一部分。该技术对于不含任何数据的无状态应用非常有效,但对于数据库这类有状态应用则存在一定的困难,因为用户不得不保留两份生产数据副本。这种情况下可能会需要使用Postgres、MySQL以及其他数据库备份和恢复脚本,或定制化操作手册或自动脚本等将数据从一个数据源人工移动到另一个数据源,这个过程将会非常复杂并且会耗费大量的时间。

Portworx采用PX-Motion解决了有状态应用程序的蓝绿部署过程中的数据管理问题。PX-Motion使IT团队能够很方便地在各种环境之间进行数据和应用配置的迁移,极大地简化了有状态应用的蓝绿部署。

本篇博文将对PX-Motion的功能与能力进行探讨。具体地说,笔者将展示如何对两个不同版本的Kubernetes上运行的有状态LAMP堆栈进行蓝绿部署。

总结来说,我们会:

1.   将两个Kubernetes集群(分别称为来源集群和目标集群)配对,从而使数据、配置和Pods能够这两个集群之间进行转移,这是蓝绿部署的一部分。

2.   使用Kubernetes将一个LAMP堆栈部署到来源集群上,并验证应用程序能够运行。

3.   使用PX-Motion可以将Kubernetes的部署、加密文件、副本集、服务、持久卷、持久卷连接以及数据等,从来源集群迁移到目标集群上进行测试和验证。在迁移完成之后,所有的Pods都能够在来源集群上继续运行。现在我们已经有了两个集群在运行,分别是蓝色和绿色。

4.   使用Kubernetes验证我们的应用以及自身数据是否正在目标集群上正常运行。

5.   在新集群上的部署验证完成之后,我们就可以更新我们的负载平衡设置,从而使所有的流量指向新集群。此时蓝绿部署就完成了。

我们开始吧!

安装PX-Motion

前提条件

如果你正在尝试PX-Migration,请确认已经满足所有的前提条件(https://docs.portworx.com/cloud-references/migration/migration-stork/#overview)。

配对Kubernetes集群为数据迁移做准备

从来源集群(Kubernetes 1.10.3)向目标集群(Kubernetes 1.12.0)进行工作载荷迁移之前,我们需要将这两个集群配对起来。配对的概念相当于将手机和蓝牙播放器进行配对,使两种不同的设备结合起来工作。

集群配对首先要做的是对目标集群进行配置。首先,建立对于pxctl (“pixie-cuttle”)的访问,即Portworx CLI。下面将介绍如何在可被kubectl访问的工作站上使用pxctl。

$ kubectl config  use-context <destination-cluster>
$ PX_POD_DEST_CLUSTER=$(kubectl get pods --context
   <DESTINATION_CLUSTER_CONTEXT> -l name=portworx -n kube-system 
   -o jsonpath='{.items[0].metadata.name}')
$ alias pxctl_dst="kubectl exec $PX_POD_DEST_CLUSTER \
   --context <DESTINATION_CLUSTER_CONTEXT>
   -n kube-system /opt/pwx/bin/pxctl"

下一步,对目标集群对象存储进行设置,使其准备好与来源集群进行配对。我们需要在目标集群上设置一个对象存储端点,作为数据在迁移过程中进行分级的位置。

$ pxctl_dst -- volume create --size 100 objectstore
$ pxctl_dst -- objectstore create -v objectstore
$ pxctl_dst -- cluster token show
Token is <UUID>

下一步,创建一个集群配对YAML配置文档,从而对应到来源Kubernetes集群上。这个clusterpair.yaml(https://docs.portworx.com/cloud-references/migration/migration-stork/#overview)文档将包含如何与目标集群调度程序和Portworx存储进行验证的信息。运行如下命令并编辑YAML文档即可建立配对:

$ storkctl generate clusterpair --context <destination-cluster> > clusterpair.yaml

1.   说明:你可以用你自己的名称替换“metadata.name”。

2.   说明:在如下示例中,options.token可以使用通过上述“cluster tokenshow”命令生成的令牌。

3.   说明:在如下示例中,对于options.ip,将需要负载均衡器或Portworx节点的IP或者DNS,这样我们才能够访问9001和9010端口。

下一步,使用kubectl,将这个集群配对应用到来源集群上。

$ kubectl config use-context <source-cluster>
$ kubectl create -f clusterpair.yaml

在这种架构下,集群配对通过互联网(VPC至VPC)进行连接。这就需要确保我们的目标存储能够良好地与来源集群连接。 请参照如下说明。(https://docs.portworx.com/cloud-references/migration/)

1.   说明:这些步骤均是暂用措施,后续新版本的发布后将由自动化过程取代。

2.   说明:   云到云、本地环境到云、云到本地环境,都需要类似的步骤。

如果所有步骤均操作成功,则请使用storkctl列出集群配对,程序将显示存储调度程序Ready状态。如果显示Error,则请使用kubectl describe clusterpair,以获取更多信息。

$ storkctl get clusterpair
NAME      STORAGE-STATUS   SCHEDULER-STATUS   CREATED
green     Ready            Ready              19 Nov 18 11:43 EST
$ kubectl describe clusterpair new-cluster | grep paired
  Normal  Ready   2m    stork  Storage successfully paired
  Normal  Ready   2m    stork  Scheduler successfully paired

pxctl也可以用于列出集群配对。

$ pxctl_src cluster pair list
CLUSTER-ID  NAME               ENDPOINT                      CREDENTIAL-ID
c604c669    px-cluster-testing http://portworx-api.com:9001  a821b2e2-788f

我们的集群现在已经配对成功了。

在Kubernetes 1.12.0上测试工作负载

目前Kubernetes 1.10.3来源集群已经和1.12.0目标集群完成了配对,我们可以将运行的工作负载、配置以及数据从一个集群迁移到另一个集群上,来测试目标集群1.12.0Kubernetes上的应用程序是否能够正常运行。在迁移过程中及完成后,所有的Pods都将继续在来源集群上运行。我们现在有了两个集群,即蓝色和绿色,只在其运行的Kubernetes版本上存在差异。

$ kubectl config  use-context <1.10.3 source cluster context>

如果想要检查当前使用的Kubernetes版本,请运行kubectl version命令。这个命令能够输出当前的客户端和服务器版本。如下所示,服务器版本为1.10.3。

$ kubectl version --short | awk -Fv '/Server Version: / {print "Kubernetes Version: " $3}'
Kubernetes Version: 1.10.3-eks

在1.10.3上部署应用程序

在迁移工作负载时,我们需要一个来源集群上已经存在的工作负载。在演示中,我们将使用Heptio的示例LAMP堆栈在来源集群上创建一个LAMP堆栈(http://docs.heptio.com/content/tutorials/lamp.html),从而在MySQL卷上使用Portworx。这个堆栈包含了一个存储分类,包括Portworx、加密文件、HPH网页前端,以及一个具备Porworx卷副本的mySQL数据库。

$ kubectl create ns lamp   
                                                                                              
$ kubectl create -f . -n lamp
job.batch "mysql-data-loader-with-timeout" created
storageclass.storage.k8s.io "portworx-sc-repl3" created
persistentvolumeclaim "database" created
deployment.extensions "mysql" created
service "mysql" created
deployment.extensions "php-dbconnect" created
service "web" created
secret "mysql-credentials" created

使用kubectl对Pods进行检索,确保其处于Running状态下。

$ kubectl get po -n lamp
NAME                                   READY     STATUS    RESTARTS   AGE
mysql-6f95f464b8-2sq4v                 1/1       Running   0          1m
mysql-data-loader-with-timeout-f2nwg   1/1       Running   0          1m
php-dbconnect-6599c648-8wnvf           1/1       Running   0          1m
php-dbconnect-6599c648-ckjqb           1/1       Running   0          1m
php-dbconnect-6599c648-qv2dj           1/1       Running   0          1m

提取Web服务。记录服务的CLUSTER-IP和EXTERNAL-IP。迁移完成后,这两个数据将会因为处于新的集群上而发生变化。

$ kubectl get svc web -n lamp -o wide
NAME      TYPE           CLUSTER-IP       EXTERNAL-IP             PORT(S)      AGE   SELECTOR
web       LoadBalancer   172.20.219.134   abe7c37c.amazonaws.com  80:31958/TCP 15m   app=php-dbconnect

访问端点或使用curl确认WordPress已安装、运行正常且已连接至MySQL。

MySQL连接

$ curl -s abe7c37c.amazonaws.com/mysql-connect.php | jq
{
  "outcome": true
}

验证是否也为MySQL容器创建了PVC。如下我们将看到PVC、数据库,各有三个副本用于部署。这个卷是MySQL的ReadWriteOnce卷块。

$ kubectl get pvc -n lamp
NAME       STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS        AGE
database   Bound     pvc-c572277d-ec15-11e8-9f4d-12563b3068d4   2Gi        RWO            portworx-sc-repl3   28m

卷信息也可以使用pxctl进行展示。Volume list命令的输出如下。

$ pxctl_src -- volume list
ID                 NAME                                      SIZE  HA STATUS                       
618216855805459265 pvc-c572277d-ec15-11e8-9f4d-12563b3068d4  2 GiB 3  attached on 10.0.3.145

将应用程序迁移至Kubernetes 1.12.0

对本地kubectl客户端进行配置,使其使用正在运行1.12.0的目标集群。

$ kubectl config use-context <1.12.0 destination cluster context>

运行kubectl Version命令,这个命令将输出当前的客户端和服务器版本,如下看到运行的1.12.0。

$ kubectl version --short | awk -Fv '/Server Version: / {print "Kubernetes Version: " $3}'
Kubernetes Version: 1.12.0

验证LAMP堆栈Pods是否正在运行中。如下所示,该集群的Namespace没有资源,即表示迁移还未发生。

$ kubectl get po
No resources found.

下一步,使用Stork客户端storkctl,创建一次迁移,将LAMP堆栈资源和卷从1.10.3集群迁移到1.12.0集群上。向storkctl create migration的命令的输入包括clusterPairnamespaces以及可选的includeResourcesstartApplications,从而将相关资源纳入并在迁移完成后启动应用程序。该命令的更多信息请点击这里(https://docs.portworx.com/cloud-references/migration/migration-stork/)。

$ storkctl --context <source-cluster-context> \
   create migration test-app-on-1-12 \
   --clusterPair green \
   --namespaces lamp \
   --includeResources \
   --startApplications
Migration test-app-on-1-12 created successfully

迁移创建后,使用storkctl获取迁移状态。

$  storkctl --context <source-cluster-context> get migration
NAME               CLUSTERPAIR   STAGE     STATUS       VOLUMES   RESOURCES   CREATED
test-app-on-1-12   green         Volumes   InProgress   0/1       0/7         19 Nov 18 13:47 EST

pxctl也可以用于查看迁移状态。卷将显示出与迁移有关的STAGESTATUS

$ pxctl_src cloudmigrate status

CLUSTER UUID: 33293033-063c-4512-8394-d85d834b3716
TASK-ID            VOLUME-ID               VOLUME-NAME                               STAGE     STATUS     
85d3-lamp-database 618216855805459265      pvc-c572277d-ec15-11e8-9f4d-12563b3068d4  Done      Initialized

完成后,迁移将显示STAGE → Final和 STATUS → Successful

$ storkctl --context  <source-cluster-context> get migration

NAME               CLUSTERPAIR   STAGE     STATUS       VOLUMES   RESOURCES   CREATED
test-app-on-1-12   green         Final     Successful   1/1       7/7         19 Nov 18 13:47 EST

现在从目标集群中获得Pods。如下所示,PHP与MySQL现在都在目的集群上运行。

$ kubectl get po -n lamp
NAME                            READY     STATUS    RESTARTS   AGE
mysql-66d895ff69-z49jl          1/1       Running   0          11m
php-dbconnect-f756c7854-2fc2l   1/1       Running   0          11m
php-dbconnect-f756c7854-c48x8   1/1       Running   0          11m
php-dbconnect-f756c7854-h8tgh   1/1       Running   0          11m

注意CLUSTER-IPEXTERNAL-IP现在已经发生了变化。这表示服务现在在新的Kubernetes 1.12集群上运行,并且因此包含了与此前不同的子网。

$  kubectl get svc web -n lamp -o wide
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP            PORT(S)       AGE  SELECTOR
web       LoadBalancer   10.100.0.195   aacdee.amazonaws.com   80:31958/TCP  12m  app=php-dbconnect

如果网站能够在1.12.0集群上被访问、运行正常并且数据已经正确迁移到了1.12.0集群,则将会返回相同的输出内容。

Web网页前端

MySQL连接

$ curl -s http://aacdee.amazonaws.com//mysql-connect.php | jq
{
  "outcome": true
}

如下我们可以看到来源(下)和目标(上)集群上,kubectl get po -n lamp的输出。注意Pods的AGE,目的集群(上)中有最近迁移进来的LAMP堆栈。

两个集群在迁移后运行的是相同的程序和数据。

回顾整个过程:

1.   第一步,1.10.3 EKS集群与1.12.0集群配对。

2.   LAMP堆栈(Linux, Apache, MySQL, PHP)部署到1.10.3集群上。

3.   使用PX-Motion将Kubernetes部署、加密文件、副本集、服务、持久卷、持久卷连接,以及LAMP堆栈数据迁移到1.12.0集群上。

4.   应用程序在1.12.0集群上被访问,并验证其是否正确运行。

持久卷和连接都使用PX-Motion(https://docs.portworx.com/cloud-references/migration)在各个集群之间进行迁移,Kubernetes资源和副本都使用Portworx Stork在目标集群上进行启动。

现在我们拥有了两个完全可运行的Kubernetes集群和两个环境,即蓝色和绿色部署环境。在实际操作中,你需要在绿色集群上进行所有测试,从而确保应用程序不会在新的集群上发生预期之外的问题。确认测试完成之后,将负载均衡从蓝色集群切换至新的绿色集群,此时部署就完成了!

结论

PX-Motion具有将Portworx卷和Kubernetes资源在集群之间进行迁移的能力。上述样例就是使用PX-Motion帮助团队实现蓝绿部署的过程:对其工作负载和数据在新版本的Kubernetes上进行测试,并帮助团队在新的绿色集群上运行应用程序。在不同版本的Kubernetes上进行真实负载和数据测试,使得运营团队能够在发布新版本的Kubernetes之前获得充足的信心。蓝绿部署并不是PX-Motion唯一的功能,请查看我们其他的PX-Motion博文了解更多。

K8S数据迁移方法

Portworx阅读(717)评论(0)

Kubernetes改变了我们所有人对计算平台的看法。我们同样也需要改变现代应用程序存储数据的方式。企业越来越多地依赖数字服务来接触客户,传统企业正在Kubernetes上重新部署它们的IT应用和服务。容器的可移植性和Kubernetes自动化的好处意味着在整个IT开发/测试和生产生命周期中我们可以更快、更可靠地交付应用程序。与此同时,企业必须认识到多云部署不仅仅是一种供应策略,而且还是一种对客户最合理的应用程序交付方式。

传统的存储行业还没有做好足够的工作来解决K8S的问题:容器可移植性、K8S自动化和多云交付。Portworx企业版首先为K8S中大数据量的工作负载提供无缝的高可用性,无论这些工作负载是在本地系统还是在公共云中运行,都将提供无缝的高可用性。通过Portworx,开发团队可以获得集成调度程序、完整的数据生命周期管理,以及核心生产功能,如BYOK加密和云备份。

通过与那些已经把应用部署在主要的公有云平台或自有硬件平台上的优秀客户合作,Portworx已经掌握了完整的数据可迁移性、操作自动化、以及将含有大量数据的应用交付到多云部署中的真正能力。

可迁移性和易操作性

通过控制与K8S的集成方式,PX-Motion为大量数据型工作负载带来了充分的可迁移性。现在,类似Kubernetes为无状态工作负载带来的方便一样,我们在有状态工作负载上为客户的数据库、分析堆栈、机器学习和其他类型的应用提供数据服务。只需一个命令,PX-Motion就可以跨集群和跨云移动K8S应用程序、Kubernetes配置和Portworx数据卷。
PX-Motion的功能有:
  • 扩展容量:将较低优先级的应用程序转移到次要集群,为关键集群释放容量。
  • 蓝绿部署:通过应用程序和数据来测试新版本的Kubernetes和Portworx。这一方法同云原生应用程序团队使用蓝绿部署法相同——现在你也可以将它用于您的容器基础架构。
  • 清洁安装:从Kubernetes到Portworx的每一个基础架构安装都是全新安装,而不是就地升级。无论是本地部署还是在公有云中,全新安装提供了一种更稳定的基础架构。
  • Dev/test:以自动化的方式将工作负荷从dev升级到分段集群。因此,它消除了人工准备数据的过程(这些步骤会影响测试准确性)。
  • 迁移:将应用程序和数据从本地部署集群迁移到AWS、谷歌、Azure、IBM或其他地方的云托管Kubernetes集群。同时反过来也支持。
  • 维护:它可在几分钟内迁移整个集群的应用程序和数据,以方便执行硬件的维护服务。

PX-Motion支持跨集群和云迁移,而PX-Central提供了必要的可视性操作界面来管理和控制数据的迁移。管理员和应用程序团队可以在每个应用程序级别上可视化的调度、控制正在进行的迁移的应用状态。

不仅如此,PX-Central还从根本上简化了对量数据工作负荷的管理。通过使用PX-Central,客户可以跨越多个集群或云,来管理、监视和元数据服务。

PX-Central的主要功能有:

  • 多集群管理GUI:为您的所有容器数据需求(包括跟踪容量、配置和监视)提供统一的管理界面。
  • 集中配置和调度:简单设置即可完成关键数据保护机制,包括使用PX-企业版 CloudSnap™完成快照和云中备份。
  • 内置元数据服务:在使用PX-企业版时,消除了客户自己处理etcd服务的繁琐,并使集群更加易于管理。
  • 主动监控:已经为跟踪和分析指标、警报和异常进行了配置,让团队在规模化配置上更有效地操作。

点击鼠标即可完成的K8S企业级备份: PX-Backup & PX-Autopilot

Portworx阅读(1097)评论(0)

Portworx,容器存储与数据管理专业解决方案提供商,对其行业领先的容器原生存储解决方案Portworx Enterprise进行了更新,使其企业用户能够在Kubernetes上对关键应用程序进行扩展、备份和恢复。PX-Backup和PX-Autopilot均用于实现存储容量管理。Portworx通过PX-Backup进入企业级备份市场,使企业用户能够方便而安全地对其所有的Kubernetes应用备份进行云原生方式的管理。PX-Backup在容器领域内的独特性在于它支持使用单个命令进行单个Pod、多个Pod以及整个Kubernetes NameSpace的备份,即便企业使用的是Microsoft Azure、AWS或谷歌存储。
此外,用于进行存储容量管理的PX-Autopilot还使企业能够采用智能化的方式管理存储,仅在需要时扩充容量,从而削减50%的云端存储成本,消除长期以来的云端存储在配置时即收费,而非使用时才收费的问题。
在企业认识到云原生技术对于其数字化转型的巨大作用之后,容器技术被更加广泛的使用。Gartner预测认为,到2022年,超过20%的企业存储容量都将用于支持容器工作负载,而这一数字现在还未达到1%。这样一来,企业就需要容器原生存储平台来解决Kubernetes上运行容器应用中的各种问题。此次更新奠定了Portworx的行业领先地位:唯一的容器原生存储与数据管理全面能力供应商:为Kubernetes上运行的容器应用程序提供快速、可扩展的容器存储,自动化容量管理,备份与恢复,容灾,多云迁移,以及数据安全服务
“企业的数字化转型是由容器和Kubernetes等技术不断推动的。这些技术能够帮助团队快速向用户和客户提供更好的服务,”Portworx首席技术官Gou Rao说,“利用这些新功能,我们正在不断努力实现全栈支持,使用户能够在Kubernetes上运行含有大量数据的应用程序,从而帮助企业实现其转型目标,同时节省成本并满足合规要求。”
PX-Backup

今年早些时候Portworx发布了PX-DR,行业内第一款针对Kubernetes应用的容灾恢复服务。虽然并不是每一个应用程序都需要容灾恢复(DR),但基于市场调查机构451 Research的研究表明,即便对于非关键应用和数据,53%的公司都设定了24小时内恢复数据的RPO目标,因此数据备份对于所有企业的应用程序至关重要。为解决这个问题,Portworx发布了PX-Backup,这是一款针对Kubernetes应用程序的点击式备份与恢复服务。在得到了PX-Backup的扩充之后,Portworx Enterprise的企业用户已经能够对Kubernetes上运行的所有含有大量数据的应用程序进行管理、保障以及备份。
PX-Backup能够捕捉应用程序数据、配置以及Kubernetes对象并将其作为一个单元,使用户能够将关键性的数据存储在任意的S3-兼容的对象存储器中。备份完成后,Kubernetes应用程序就可以通过重新运行Kubernetes部署文件的方式进行恢复和重新部署。此外,PX-Backup还能够对备份中的大量数据进行捕捉,使企业能够回答备份负责人、备份内容、备份时间、备份地点、备份时长等规定与管理方面的重要问题。
其他功能还包括:
  • 这是首次,正在使用云端存储的企业,虽然尚未使用Portworx Enterprise,也可以使用这款为Kubernetes应用程序打造的备份服务PX-Backup。比如企业正在使用类似Microsoft Azure      Managed Disks、Amazon Web Services EBS以及 Google Persistent Disks。
  • Portworx的备份服务甚至可以为Cassandra、Kafka、Elasticsearch以及MongoDB等多节点分布式数据库进行备份,而其他备份服务方式,要达到这样的目标,则需要面临数据损坏的风险
  • 备份的数据可以发送至任何S3-兼容的对象存储器,使备份能够在单独的云或数据中心进行存储和恢复,也可以进行跨云和数据中心的存储和恢复。
PX-Autopilot 实现存储容量管理

Kubernetes能够实现应用程序部署的自动化,但企业也必须能够使其下层基础架构实现自动化,才能确保有足够的计算力和存储来扩展应用。虽然企业在云端获得了按使用量付费的模式,但实际上,企业都是通过过度部署存储空间的方式(通常超出2-3倍),来应对难以衡量Kubernetes上运行的数据服务的存储容量的问题。这意味着他们要为未被使用的存储付费。PX-Autopilot使企业能够通过自动检测存储容量,并在需要的时候才扩充容量的方式节省空间,降低存储费用。PX-Autopilot能够按用户定义的规则,对单个容器的容量或整个存储集群的容量进行扩充。如果不使用PX-Autopilot,则在通常客户使用的企业环境下,采用多步操作过程扩充存储空间将需要花费平台管理员将近20小时的时间。

汉莎航空使用portworx在容器集群架构和DevOps下进行数据管理

Portworx阅读(1125)评论(0)

德国汉莎航空股份公司(Deutsche Lufthansa AG),世界上第五大航空公司。汉莎航空下属的IT公司-汉莎系统公司(Lufthansa Systems),它支撑了汉莎所有线路,百万乘客,从机上到机下,从起飞到降落的所有信息化系统的建设和运营。
汉莎系统开发的机上娱乐系统采用了容器技术作为底层技术支撑。对系统的扩展性,稳定性、模块化、用户友好度,要求非常之高。微服务和容器技术逐渐成为汉莎系统产品开发的底层支撑,并应用DevOps的方式来进行开发和管理。但在这个过程中,汉莎遇到了重要的挑战,就是如何在系统灵活、易用、快速的前提下,保持数据的永久性。

汉莎发现并使用了Portworx来解决问题

我们来看看汉莎系统软件架构师麦克·威廉姆斯(Michael Wilmes)怎么评价Portworx:
 “Portworx与我们的IT系统是一个完美的结合,它对于传统的、云原生、第三方应用,非常便捷和易用。”我们的BoardConnecd系统,采用了微服务架构,运行Docker Swarm环境,和Consul-backed Service Discovery。我们采用了云上的对象存储功能与BoardConnecd系统进行数据交换,,同时我们运维大量的Block存储的服务。

以BoardConnect系统为基础的机上娱乐系统(CMS),采用的是传统的数据管理方式,数据被存储到硬盘和数据库里。当IT希望在项目上自动开启CMS的instance的时候,或者需要管理客户生产环境的每个CMS Instance的时候,就产生了对Docker 调度的强烈需要。

容器能够帮助我们提高开发速度,同时,能够帮我们更好的调节各个应用的部署和管理。以及同时保持容器的数据永久性和灵活性。使用Portworx,我们可以在几分钟内部署完整的CMS系统,并且不需要手动的干预。而之前我们需要几个小时。在生产系统中,Portworx可以帮助我们在不同的Cluster中移动CMS环境,并且同步移动数据。

不论是云环境还是硬件环境,Portworx都有工具能够帮助我们快速部署,这个实在太有价值了。Portworx帮助我们在更多的应用中使用Docker,同时更好的对应用进行生命周期管理。在我们的应用中,容器的Dev&Ops带来了易用性和快捷,就产生进一步的用传统方式管理存储的需要。但这种方式并不简单。某些服务需要基于Block服务的高I/O。而另一些服务,比如CMS和数据库,本身并不支持云存储。而Portworx解决了这样的问题

Operations也有基于Docker的挑战:通过先部署的Host Mounts,再部署Docker命名的卷,我们就能够快速进行开发,但是这些容器就会被绑定到某个具体的Docker host上,而数据被延迟到了下一个host中。这就产生了很大的问题,正常的容器可以在cluster上自动漂移,而需要数据永久性的容器就需要很多的手工动作来完成

一些通常的容器永久性解决方案,主要是建立存储应用和Docker的连接。但是这样的方式产生了1)对于某个存储和云服务的依赖性 2)存储的类型也受限。这样的解决方案无法真正满足需求。而Portworx的方案,则能够很好的解决这些问题。

部署Portworx相对简单,有很好的文档支持。Portworx让我们的Docker变得与Cluster无关,也与底层的软件堆栈无关,我们可以基于不同的云服务提供商和数据中心来进行Docker一致性的管理。同时可以把不同种类的容器用同样的方式来处理,包括云原生微服务,传统的CMS系统,和数据库。Portworx帮助我们同时对CMS,数据库,和文件系统进行自动部署和管理。当Portworx在Docker Cluster上安装完成后,管理容器变得非常简单,可以通过图形化界面,也可以通过命令行的方式,升级也很直接,存储系统可以用JSON来直接调用。

 

Portworx演示:在K8S集群间迁移有状态的应用和数据

Portworx阅读(647)评论(0)

越来越多的企业选择Kubernetes作为基础架构,它能够帮助我们缩短软件项目上市时间、降低基础架构成本、并提高软件质量。由于Kubernetes比较新,因此IT团队都在学习如何在生产环境中,在Kubernetes上对应用程序进行运行和维护。本文将探讨,当在需要额外的计算能力时,将Kubernetes应用程序迁移至另一个新的集群。
 
Portworx演示视频:https://v.qq.com/x/page/u3014njr3a5.html
需要对当前的Kubernetes集群进行扩充的一些原因
1.某个集群的资源即将被全部占用,你需要将工作负载迁移到新的具有更多的计算资源的地方。
2.你希望使用的服务在另一个区域或云中,但想要使用这些服务,你需要转移应用程序和数据。
3.硬件到期,需要升级硬件到下一代,而新硬件的计算的规格、要求以及内存容量都已经发生了变化,这就导致了迁移的必要性。
4.集群资源受限并且进行扩展instance的成本越来越高,因此你需要采用新的集群架构,这样的集群需要使用网络附加的块存储而非本地磁盘,这样才能够将存储独立于计算进行扩展。
5.开发人员希望将工作负载转移到一个具有不同的硬件、网络、操作系统或其他配置的集群进行测试或分级。
上述所列原因并不详尽,但也说明在许多条件下扩充Kubernetes环境和将工作负载从一个集群迁移到另一个集群是有必要的。这个问题在涉及无状态应用时较为简单,但对于有状态的服务,如数据库、队列、关键存储、大数据以及机器学习应用时等时,你就必须将数据转移到新的、扩容的环境中去,然后应用程序设计才能加速运行。
解决数据移动性问题:PX-Enterprise™新功能
PX-Motion不仅具有对数据进行跨环境转移的能力,它还能够对应用程序配置以及相关的有状态的资源,如PV(永久卷)等进行转移,使得操作团队能够非常方便地将一个卷、一个Kubernetes名字空间、或整个Kubernetes集群在环境之间进行转移,即便其中存在永久数据。
本文将对PX-Motion的功能与能力进行探讨。同时,我们将演示如何将一个Kubernetes命名空间以及其中运行的所有应用程序转移到一个具有资源拓展能力的新的Kubernetes集群上。在这个演示中,集群1表示资源已经过度利用的、不灵活的,已经无法满足我们不断增长的应用程序需求的集群。集群2表示一个更加灵活且可扩展的集群,我们将把工作负载转移到这个集群2上。
除了在集群之间进行整个Kubernetes命名空间的转移之外,我们还将展示如何将配置在集群1中使用本地存储的应用程序,迁移到使用网络附加的块存储的集群2中。
通过这种方式,你将看到我们需要转移真正的数据,而不是通过管理块设备映射这种小伎俩来实现的。
总的来说,在将一个有状态的Kubernetes应用程序转移到另一个集群时,你需要:
  1. 将这两个集群进行配对,从而指定一个目标集群和一个目的集群;
  2. 使用PX-Motion开始迁移,其中包括移动数据卷和配置;

数据和配置迁移完成后,Kubernetes会自动将应用程序部署到新的环境中。

我们开始吧!

配置与设置

在展示中,我们使用google Kubernetes Engine (GKE)作为Kubernetes集群,但你也可以在任意的Kubernetes集群中进行如下的操作。使用Portworx installer online spec generator获得的DaemonSet Spec, 将Portworx安装到各个集群上。逐步完成安装,Portworx安装过程在此不作赘述,可以查看portworx.com上的文档了解如何在Kubernetes上安装Portworx 。环境架构示意图如下。注意集群1和集群2的如下方面:

Cluster Name Machine Type Storage Type
Cluster 1 (Source) n1-standard-2 local-ssd
Cluster 2 (Destination) n1-standard-8 provisioned PDs

在这种情况下,第一个集群(集群1)资源面临限制,操作团队希望从本地SSD转移到更大instance的自动配置的永久磁盘(PD)中。

为什么?本地SSD在处理特定工作负载时较为有效,但其自身也存在着局限性,这也是我们在这里讨论将应用程序从一个命名空间转移到另一个命名空间的原因所在。依照谷歌的描述,本地SSD的限制包括:

  • “由于本地SSD是以物理方式附加到节点的虚拟机instance上的,其中存储的所有数据都只存在于这个节点上。而由于数据是本地存储的,因此你的应用必须要能够面对数据不可用的情况。”
  • 存储在SSD的数据是短期性的向本地SSD写入内容的Pod会在被调度离开这一节点时失去对磁盘中存储的数据进行访问的能力。”     此外,如果节点被撤销、升级或维修,则数据就会被擦除。
  • “我们并不能向现有的节点池添加本地SSD。

Portworx能够克服对上述部分限制,因为它能够将数据复制到集群中的其他提供高可用的主机上。但如果我们希望在不对计算按比例进行扩展的情况下,不断向我们的集群添加额外的存储,那么使用本地存储仍旧会存在一定的限制。上文所述的GKE上的第二个集群使用Portworx Disk Template,从而自动允许Portworx从Google云对磁盘进行管理,这比本地磁盘更加灵活一些。

第二个集群提前运行,现在使用的是自动配置的PD,可以进行工作负载的迁移。

大量应用程序的运行需要更多的计算能力

源集群如下。它是由单个命名空间(NameSpace)内运行的大量应用构成的:Cassandra, Postgres,WordPress和MySQL。所有的这些应用程序都会在集群中产生非常高的负载。如下是demo命名空间内运行的应用。注意,在单个Kubernetes集群上运行多个命名空间是可行且常见的。在演示中,我们只移动一个命名空间,让剩余的其他命名空间继续运行,不做变动。

$ kubectlconfig  use-context <source-cluster>

$ kubectlget po -n demo

NAME                                READY     STATUS    RESTARTS   AGE

cassandra-1-0                       1/1       Running  0          17m

cassandra-1-1                       1/1       Running  0          16m

cassandra-1-2                       1/1      Running   0          14m

cassandra-2-0                       1/1       Running  0          17m

cassandra-2-1                       1/1       Running  0          16m

cassandra-2-2                       1/1       Running  0          14m

mysql-1-7f58cf8c7c-srnth            1/1       Running  0          2m

mysql-2-8498757465-gqs5h            1/1       Running  0          2m

postgres-2-68c5d6b845-c4gbw         1/1       Running  0          26m

postgres-77bf94ccb5-hs7dh           1/1       Running  0          26m

wordpress-mysql-2-5fdffbdbb4-dpqm9  1/1       Running  0          17m

在某一个时间点上,当添加了更多的应用程序,如MySQL数据库时,这个集群就会遭遇其内存限制并出现“OutOfmemory”等错误,见如下。为解决这个问题,我们将demo这个命名空间迁移到一个新的集群上,从而为demo这个命名空间增添新的可用资源。

$ kubectlget po -n demo

NAME                                READY     STATUS       RESTARTS   AGE

cassandra-1-0                       1/1      Running       0         16m

cassandra-1-1                       1/1      Running       0         14m

cassandra-1-2                      1/1      Running       0         13m

cassandra-2-0                       1/1      Running       0         16m

cassandra-2-1                       1/1      Running       0         14m

cassandra-2-2                       1/1      Running      0          13m

mysql-1-7f58cf8c7c-srnth            1/1      Running      0          1m

mysql-2-8498757465-gqs5h            1/1      Running      0          25s

mysql-3-859c5dc68f-2gcdj            0/1       OutOfmemory  0          10s

mysql-3-859c5dc68f-4wzmd            0/1       OutOfmemory  0          9s

mysql-3-859c5dc68f-57npr            0/1       OutOfmemory  0          11s

mysql-3-859c5dc68f-6t8fn            0/1       Terminating  0          16s

mysql-3-859c5dc68f-7hcf6            0/1       OutOfmemory  0          6s

mysql-3-859c5dc68f-7zbkh            0/1       OutOfmemory  0          5s

mysql-3-859c5dc68f-8s5k6            0/1       OutOfmemory  0          9s

mysql-3-859c5dc68f-d49nv            0/1       OutOfmemory  0          10s

mysql-3-859c5dc68f-dbtd7            0/1       OutOfmemory  0          15s

mysql-3-859c5dc68f-hwhxw            0/1       OutOfmemory  0          19s

mysql-3-859c5dc68f-rc8tg            0/1       OutOfmemory  0          12s

mysql-3-859c5dc68f-vnp9x            0/1       OutOfmemory  0          18s

mysql-3-859c5dc68f-xhgbx            0/1       OutOfmemory  0          12s

mysql-3-859c5dc68f-zj945            0/1       OutOfmemory  0          14s

postgres-2-68c5d6b845-c4gbw         1/1      Running      0          24m

postgres-77bf94ccb5-hs7dh           1/1      Running      0          24m

wordpress-mysql-2-5fdffbdbb4-dpqm9  1/1      Running      0          16m

除PX-Motion之外,最新发布的PX-Enterprise也包含了PX-Central™,这是一个用于监视、数据分析和管理的界面,能够对Grafana、Prometheus和Alertmanager进行配置。这些仪表板会对卷、集群、etcd以及其他内容进行监控。在本文所讨论的情况下,查看集群级仪表盘,就能够了解资源方面的问题。

 

如下所示的PX-Central截屏展示了该集群正在使用的内存和CPU的情况。该集群的高CPU和内存占用率为扩展带来了问题,并且由于集群存在过载问题,很有可能导致上文所述的“OutOfMemory(内存不足)”的问题。

使用PX-Motion迁移一个Kubernetes命名空间,包括其数据。

既然已经找到了问题,现在我们来使用PX-Motion将数据迁移到新的集群上。首先,我们将两个GKE集群配对起来,实现源集群和目标集群之间的迁移连接。集群的配对和蓝牙播放器与手机的配对类似。配对过程是为了将两个不同的设备连接起来。

前提条件

如果你正在尝试PX-Migration,请确认已经满足所有的前提条件。

为了将工作负载从集群1迁移到集群2,我们需要对PX-Motion进行配置。首先要做的是配置目标集群。为实现这一点,首先建立对于pxctl (“pixie-cuttle”)的访问,即Portworx CLI。如下是pxctl在具有kubectl访问的情况下在工作站的运作情况。

$ kubectl config use-context <destination-cluster>

$PX_POD_DEST_CLUSTER=$(kubectl get pods –context

<DESTINATION_CLUSTER_CONTEXT> -lname=portworx -n kube-system

-o jsonpath='{.items[0].metadata.name}’)

$ aliaspxctl_dst=”kubectl exec $PX_POD_DEST_CLUSTER

–context <DESTINATION_CLUSTER_CONTEXT>\

-n kube-system /opt/pwx/bin/pxctl”

下一步,对目标集群进行设置使其准备好与来源集群进行配对。目标集群应当首先运行Portworx objectstore。我们需要在目标集群上设置一个对象存储端点,为数据在迁移过程中进行分级的位置。然后,为来源集群创建一个token在配对过程中使用。

$pxctl_dst — volume create –size 100 objectstore

$ pxctl_dst– objectstore create -v objectstore

$pxctl_dst — cluster token show

Token is<UUID>

现在可以创建一个集群配对YAML配置文档,从而应用到来源Kubernetes集群中去。这个clusterpair.yaml文档将包含如何与目标集群调度程序和Portworx存储进行验证的信息。运行如下命令并编辑YAML文档即可建立集群配对:

$ storkctlgenerate clusterpair –context <destination-cluster> > clusterpair.yaml

1.   说明:你可以用你自己的名称替换“metadata.name”。

2.   说明:在如下示例中,options.token可以使用通过上述“cluster token show”命令生成的令牌。

3.   说明:在如下示例中,对于options.ip,将需要一个可访问的负载均衡或Portworx节点的IP或DNS,来访问9001和9010端口。

在使用GKE时,在应用到集群之前,我们需要向Stork添加许可。Strok是由PX-Enterprise使用的Kubernetes的OSS智能调度程序扩展和迁移工具,同时我们还需要知道如何对新集群进行验证,从而对应用程序进行迁移。首先,使用谷歌云指令生成服务账户。然后,对Stork部署和验证进行编辑,从而确保其能够访问目标集群。指令请见如下。

下一步,应用这个集群并使用kubectl与来源集群进行配对。

$ kubectl config use-context <source-cluster>

$ kubectlcreate -f clusterpair.yaml

应用完成后,使用已经设置的storkctl检查集群配对的状态。

$ storkctlget clusterpair

kubectl和pxctl也可以对集群配对进行查看。

$ kubectldescribe clusterpair new-cluster | grep paired

Normal Ready   2m    stork  Storage successfully paired

Normal Ready   2m    stork  Scheduler successfullypaired

$ pxctlcluster pair list

CLUSTER-ID NAME         ENDPOINT                 CREDENTIAL-ID

c604c669   px-cluster-2  http://35.185.59.99:9001  a821b2e2-788f

开始迁移

下一步,有两种方式开始迁移动作:通过storkctl生成迁移 CLI,或参考对迁移进行描述的spec文件。我们使用第二种方法,请见如下,对演示资源和卷进行迁移。

apiVersion:stork.libopenstorage.org/v1alpha1

kind: Migration

metadata:

name: demo-ns-migration

spec:

clusterPair: new-cluster

includeResources: true

startApplications: true

namespaces:

– demo

依照上述spec文档使用kubectl创建迁移。

kubectlcreate -f migration.yaml

检查迁移状态。成功的迁移分为如下步骤:卷→应用程序→完成

$ storkctlget migration

NAME               CLUSTERPAIR   STAGE      STATUS       VOLUMES  RESOURCES   CREATED

demo-ns-migration  new-cluster   Volumes     InProgress  2/12     0/37        08 Nov 18 15:14 EST

 

$ storkctlget migration

NAME               CLUSTERPAIR   STAGE      STATUS       VOLUMES   RESOURCES  CREATED

demo-ns-migration  new-cluster   Application InProgress  12/12     30/37       08 Nov18 15:25 EST

 

$ storkctlget migration

NAME               CLUSTERPAIR   STAGE      STATUS       VOLUMES  RESOURCES   CREATED

demo-ns-migration  new-cluster   Final      Successful   12/12    37/37       08 Nov 18 15:27 EST

为了解哪些资源,如卷、PVC、状态集、复制集处于“进行中”或“已完成”状态,可以使用“kubectldescribe”命令。

$ kubectldescribe migration demo-ns-migration

迁移的状态也可以使用来源Portworx集群的pxctl进行查看。

$ pxctl –cloudmigrate status

 

CLUSTERUUID: c604c669-c935-4ca4-a0bc-550b236b2d7b

 

TASK-ID                                              VOLUME-ID              VOLUME-NAME                               STAGE  STATUS

6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-0    673298860130267347     pvc-2c2604f4-e381-11e8-a985-42010a8e0017  Done   Complete

6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-1    782119893844254444     pvc-7ef22f64-e382-11e8-a985-42010a8e0017  Done   Complete

6cb407e0-e38e-demo-cassandra-data-1-cassandra-1-2    486611245472798631     pvc-b8af3c05-e382-11e8-a985-42010a8e0017  Done   Complete

这样根据集群迁移资源的状态显示,迁移完成了,如下图示展示的就是进行的过程。来自集群1的命名空间、应用、配置以及数据等都迁移到集群2。

随后,查看目标集群以确保应用确实已经完成迁移并且能够良好运行,因为我们使用的是“startApplications: true”属性。

$ kubectl config  use-context<destination cluster>

$  kubectl get po -n demo

NAME                                READY     STATUS    RESTARTS   AGE

cassandra-1-0                       1/1       Running  0          7m

cassandra-1-1                       1/1      Running   0          5m

cassandra-1-2                       1/1       Running  0          4m

cassandra-2-0                       1/1       Running  0          7m

cassandra-2-1                       1/1       Running  0          5m

cassandra-2-2                       1/1       Running  0          4m

mysql-1-7f58cf8c7c-gs8p4            1/1       Running  0          7m

mysql-2-8498757465-4gkr2            1/1       Running  0          7m

postgres-2-68c5d6b845-cs9zb         1/1       Running  0          7m

postgres-77bf94ccb5-njhx4           1/1       Running  0          7m

wordpress-mysql-2-5fdffbdbb4-ppgsl  1/1       Running   0         7m

完美! 所有的程序都在运行中! 现在我们返回PX-CentralGrafana仪表板就可以看到集群上使用的内存和CPU都变少了。该截屏显示的是工作负载迁移后的工作节点的CPU和内存使用情况。

这正是我们希望达到的效果。如下是GKE仪表板上显示的集群1和集群2之间可用CPU和内存的量,因此上述结果是有效的。

现在我们拥有了额外的计算力,我们就可以创建额外的MySQL数据库了。这个数据库将在新集群上拥有足够的资源进行运行。

$ kubectlcreate -f specs-common/mysql-3.yaml

storageclass.storage.k8s.io”mysql-tester-class-3″ created

persistentvolumeclaim”mysql-data-3″ created

deployment.extensions”mysql-3″ created

$ kubectlget po -n demo

NAME                                READY     STATUS    RESTARTS   AGE

cassandra-1-0                       1/1      Running   0          22m

cassandra-1-1                       1/1       Running  0          20m

cassandra-1-2                       1/1       Running  0          18m

cassandra-2-0                       1/1       Running  0          22m

cassandra-2-1                       1/1       Running  0          20m

cassandra-2-2                       1/1       Running  0          18m

mysql-1-7f58cf8c7c-gs8p4            1/1       Running  0          22

mysql-2-8498757465-4gkr2            1/1       Running  0          22m

mysql-3-859c5dc68f-6mcc5            1/1       Running  0          12s

postgres-2-68c5d6b845-cs9zb         1/1       Running  0          22m

postgres-77bf94ccb5-njhx4           1/1       Running  0          22m

wordpress-mysql-2-5fdffbdbb4-ppgsl  1/1       Running  0          22m

 

成功!

集群扩增的益处是显而易见的。用户和操作员可以将旧的命名空间或应用从来源集群上删除,也可以直接将整个集群删除掉,从而回收这些资源。新的集群使用的是自动配置PD而非本地SSD,因此其存储与计算能力都能够依照IT团队的需求进行扩展。

 

结论

PX-Motion具有着将Portworx卷和Kubernetes资源在集群之间进行迁移的能力。上述案例就利用了PX-Motion这一功能,使得团队能够对Kubernetes环境实现无缝扩增。在Kubernetes上的环境之间对命名空间、卷或整个应用程序进行迁移就变得轻而易举了。扩增并不是PX-Motion唯一的功能,请查看我们其他的PX-Motion系列文章了解更多信息。

K8s项目最高技术委员会新增4人,2人来自红帽

中文社区阅读(1094)评论(0)

Kubernetes社区最近一次的技术委员会票选结果出炉,这次选出了4名新的委员,Christoph Blecker和Derek Carr来自红帽,K8s大规模部署产品提供商Loodse也有一人入选,另外还有一位Paris Pittman则来自Google。他们四人任期2年,将与现有3名委员共同主导K8s的未来发展战略方向。现有3人,其中2人来自VMware,1人来自Google。这意味着,本次K8s技术委员会中,Google、红帽和VMware的人数相同,将成为三巨头主导发展K8s的局势。