标签 Kubernetes 下的文章

了解 Kubernetes 调度器是如何发现新的吊舱并将其分配到节点。

 title=

Kubernetes 已经成为容器和容器化工作负载的标准编排引擎。它提供一个跨公有云和私有云环境的通用和开源的抽象层。

对于那些已经熟悉 Kuberbetes 及其组件的人,他们的讨论通常围绕着如何尽量发挥 Kuberbetes 的功能。但当你刚刚开始学习 Kubernetes 时,尝试在生产环境中使用前,明智的做法是从一些关于 Kubernetes 相关组件(包括 Kubernetes 调度器) 开始学习,如下抽象视图中所示:

Kubernetes 也分为控制平面和工作节点:

  1. 控制平面: 也称为主控,负责对集群做出全局决策,以及检测和响应集群事件。控制平面组件包括:
  • etcd
  • kube-apiserver
  • kube-controller-manager
  • 调度器
  1. 工作节点: 也称节点,这些节点是工作负载所在的位置。它始终和主控联系,以获取工作负载运行所需的信息,并与集群外部进行通讯和连接。工作节点组件包括:
  • kubelet
  • kube-proxy
  • CRI

我希望这个背景信息可以帮助你理解 Kubernetes 组件是如何关联在一起的。

Kubernetes 调度器是如何工作的

Kubernetes 吊舱 pod 由一个或多个容器组成组成,共享存储和网络资源。Kubernetes 调度器的任务是确保每个吊舱分配到一个节点上运行。

(LCTT 译注:容器技术领域大量使用了航海比喻,pod 一词,意为“豆荚”,在航海领域指“吊舱” —— 均指盛装多个物品的容器。常不翻译,考虑前后文,可译做“吊舱”。)

在更高层面下,Kubernetes 调度器的工作方式是这样的:

  1. 每个需要被调度的吊舱都需要加入到队列
  2. 新的吊舱被创建后,它们也会加入到队列
  3. 调度器持续地从队列中取出吊舱并对其进行调度

调度器源码scheduler.go)很大,约 9000 行,且相当复杂,但解决了重要问题:

等待/监视吊舱创建的代码

监视吊舱创建的代码始于 scheduler.go 的 8970 行,它持续等待新的吊舱:

// Run begins watching and scheduling. It waits for cache to be synced, then starts a goroutine and returns immediately.

func (sched *Scheduler) Run() {
        if !sched.config.WaitForCacheSync() {
                return
        }

        go wait.Until(sched.scheduleOne, 0, sched.config.StopEverything)

负责对吊舱进行排队的代码

负责对吊舱进行排队的功能是:

// queue for pods that need scheduling
        podQueue *cache.FIFO

负责对吊舱进行排队的代码始于 scheduler.go 的 7360 行。当事件处理程序触发,表明新的吊舱显示可用时,这段代码将新的吊舱加入队列中:

func (f *ConfigFactory) getNextPod() *v1.Pod {
        for {
                pod := cache.Pop(f.podQueue).(*v1.Pod)
                if f.ResponsibleForPod(pod) {
                        glog.V(4).Infof("About to try and schedule pod %v", pod.Name)
                        return pod
                }
        }
}

处理错误代码

在吊舱调度中不可避免会遇到调度错误。以下代码是处理调度程序错误的方法。它监听 podInformer 然后抛出一个错误,提示此吊舱尚未调度并被终止:

// scheduled pod cache
        podInformer.Informer().AddEventHandler(
                cache.FilteringResourceEventHandler{
                        FilterFunc: func(obj interface{}) bool {
                                switch t := obj.(type) {
                                case *v1.Pod:
                                        return assignedNonTerminatedPod(t)
                                default:
                                        runtime.HandleError(fmt.Errorf("unable to handle object in %T: %T", c, obj))
                                        return false
                                }
                        },

换句话说,Kubernetes 调度器负责如下:

  • 将新创建的吊舱调度至具有足够空间的节点上,以满足吊舱的资源需求。
  • 监听 kube-apiserver 和控制器是否创建新的吊舱,然后调度它至集群内一个可用的节点。
  • 监听未调度的吊舱,并使用 /binding 子资源 API 将吊舱绑定至节点。

例如,假设正在部署一个需要 1 GB 内存和双核 CPU 的应用。因此创建应用吊舱的节点上需有足够资源可用,然后调度器会持续运行监听是否有吊舱需要调度。

了解更多

要使 Kubernetes 集群工作,你需要使以上所有组件一起同步运行。调度器有一段复杂的的代码,但 Kubernetes 是一个很棒的软件,目前它仍是我们在讨论或采用云原生应用程序时的首选。

学习 Kubernetes 需要精力和时间,但是将其作为你的专业技能之一能为你的职业生涯带来优势和回报。有很多很好的学习资源可供使用,而且 官方文档 也很棒。如果你有兴趣了解更多,建议从以下内容开始:

你喜欢的 Kubernetes 学习方法是什么?请在评论中分享吧。


via: https://opensource.com/article/20/11/kubernetes-scheduler

作者:Mike Calizo 选题:lujun9972 译者:MZqk 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

资源配额控制应用的 CPU 或内存使用情况,防止资源被过量使用或被抢占。

 title=

当 Kubernetes 集群运行过一段时间或者在被开发者大量使用后,Kubernetes 资源(例如 CPU 和内存)的控制的问题就会显现出来。而在大多情况下只有集群出问题后,我们才会意识到资源控制的重要性。

Kubernetes 部署过程如果没有能充分考虑到将来的扩展性,资源类问题将会非常常见,此类问题与集群的管理和部署团队的经验有关。

如果不加以合理控制,一个暴力的应用或者开发者可能影响到共享该集群的所有业务,大家因此会相互埋怨、指责并保护性地抢占资源。这对于集群管理和开发人员都是非常难以处理的场景。

在 Kubernetes 环境中控制应用的计算资源使用有多种方式。大部分情况下,我们可以使用“资源控制”和“限制范围”。注意存储管理不在我们讨论范围之内,存储管理可以通过 持久卷 Persistent Volume 件,以实现针对不同的存储控制需求。

资源配额是一种控制 Kubernetes 计算资源的方法。本文告诉你如何使用该功能来管理开发人员行为并控制应用的资源使用。

什么是资源配额

简而言之,资源配额 提供了限制每个命名空间资源消耗的约束条件,它们只能在命名空间级别上应用,这意味着它们可以应用于计算资源,并限制命名空间内的对象数量。

Kubernetes资源配额通过 ResourceQuota 对象来为每个命名空间设置资源配额,对以下对象类型的 CPU 和内存进行限制:

  • 吊舱 Pod
  • 服务 Service
  • 机密信息 Secret
  • 持久卷断言 Persistent Volume Claim (PVC)
  • 配置映射 ConfigMap

Kubernetes 通过 requestlimit 两个参数对 CPU 和内存进行限制(参考 LimitRange 文档)。前者表示容器最小被保证资源,后者表示容器最大可用资源。实际上最大可用资源还受限于其它容器的实际使用情况。

下一张图片解释了配额中 requestlimit 的区别:

 title=

下面我们就通过一个例子来说明如何设置资源配额来创建约束,将应用程序限制在某些资源上,它还展示了实现资源配额以获得对 Kubernetes 的控制的有用性。

准备环境

首先你需要一个 Kubernetes 环境。以下是我使用 Kubernetes 环境:

  • Minikube v1.14.2
  • Fedora 33 操作系统
  • 互联网接入

如果你想在 Linux 机器上通过 Minikube 搭建 Kubernetes 测试环境,可以参考 Bryant Son 的《Minikube 入门》 一文。Window 或者 macOS 用户可以参考这篇文章

设置资源配额

这里我们仅展示 CPU 配额设置步骤,配置内存配额或两者的组合与之类似。

在生产环境中,CPU 是最需要被控制的资源,尤其是在多应用的场景下特别需要注意防止某些应用消耗太多 CPU 而影响到其它应用。

首先我们创建一个命名空间,在其中设置 CPU 配额:

$ kubectl create namespace quota-test
namespace/quota-test created

准备 cpu-quota.yaml 文件,内容如下:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: test-cpu-quota
spec:
  hard:
    requests.cpu: "100m"  
    limits.cpu: "200m"

应用 CPU 配额到 Kubernetes 集群:

$ kubectl apply -f cpu-qouta.yaml
resourcequota/test-cpu-quota created

使用 kubectl describe 检查配额配置情况:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    0     200m
requests.cpu  0     100m

Used resources 列中显示了当前情况,该列值会随着 吊舱 Pod 的部署而变化。

下面是我们来验证限额管理的场景。我们将在同一命名空间下部署三个不同的吊舱,为它们配置以不同的资源限制如下:

  • PodA:第一个被实例化,使用 50% 可用 CPU 资源
  • PodB:第二个被实例化,使用其余 50% 可用 CPU 资源
  • PodC:没有可用 CPU 资源,因此不会被部署

部署吊舱

PodA:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: poda
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "50m"
      limits:
        cpu: "100m"
  restartPolicy: Never
EOF

部署 PodA 后,再次查看配额描述信息中的 Used CPU 信息:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    100m  200m
requests.cpu  50m   100m

PodB:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: podb
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "50m"
      limits:
        cpu: "100m"
  restartPolicy: Never
EOF

再次查看 CPU 资源使用,此时 PodB 启动后 CPU 限制已经达到上限:

$ kubectl describe resourcequota/test-cpu-quota --namespace quota-test
Name:         test-cpu-quota
Namespace:    quota-test
Resource      Used  Hard
--------      ----  ----
limits.cpu    200m  200m
requests.cpu  100m  100m

PodC:

试着创建 PodC,此时 CPU 配额已经被 PodA 和 PodB 用尽:

$ kubectl create -n quota-test -f - << EOF
apiVersion: v1
kind: Pod
metadata:
  name: podc
spec:
  containers:
  - name: quota-test
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Pod is Running ; sleep 5000']
    resources:
      requests:
        cpu: "5m"
      limits:
        cpu: "10m"
  restartPolicy: Never
EOF

正我们期望,第三个 Pod 无法被启动,配额限制了吊舱的创建:

Error from server (Forbidden): error when creating "STDIN": pods "podc" is forbidden: exceeded quota: test-cpu-quota, requested: limits.cpu=10m,requests.cpu=5m, used: limits.cpu=200m,requests.cpu=100m, limited: limits.cpu=200m,requests.cpu=100m

如我们的例子所示,定义合理的资源配额限制开发者行为对 Kubernetes 管理十分重要。

清理

删除刚才创建的命名空间 quota-test:

$ kubectl delete -n quota-test

规划资源配额

Kubernetes 中提供多种方式来控制资源的抢占和使用,合理的规划和配置配额、限制范围和其它原生参数对保持集群的稳定性十分必要。

你应该十分谨慎地控制计算资源的资源配额,特别是关键业务的生产应用环境。

在规划资源配额时,开发人员的参与很重要,需要他们预估并给出最合理的资源使用值。


via: https://opensource.com/article/20/12/kubernetes-resource-quotas

作者:Mike Calizo 选题:lujun9972 译者:larryzju 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

设置一个本地开发环境,或者直接用这些工具尝试容器编排平台。

Kubernetes 是一个开源的容器编排平台。它由 Google 开发,为自动化部署、扩展和管理容器化应用提供了一个开源系统。虽然大多数人在云环境中运行 Kubernetes,但在本地运行 Kubernetes 集群不仅是可能的,它还至少有两个好处:

  • 在决定使用 Kubernetes 作为主要平台部署应用之前,你可以快速试用它。
  • 在将任何东西推送到公共云之前,你可以将其设置为本地开发环境,从而实现开发环境和生产环境之间的分离。

无论你的情况如何,将本地 Kubernetes 环境设置为你的开发环境都是推荐的选择,因为这种设置可以创建一个安全而敏捷的应用部署流程。

幸运的是,有多个平台可以让你尝试在本地运行 Kubernetes,它们都是开源的,并且都是 Apache 2.0 许可。

  • Minikube 的主要目标是成为本地 Kubernetes 应用开发的最佳工具,并支持所有适合的 Kubernetes 特性。
  • kind 使用 Docker 容器“节点”运行本地 Kubernetes 集群。
  • CodeReady Containers(CRC)用来管理为测试和开发目的优化的本地 OpenShift 4.x 集群。
  • Minishift 通过在虚拟机 (VM) 内运行单节点的 OpenShift 集群,帮助你在本地运行 OpenShift 3.x 集群。

Minikube

 title=

Minikube 是在本地计算机上运行 Kubernetes 环境的最知名、最流行的选择。无论你使用什么操作系统,Minikube 的文档都会为你提供一个简单的安装指南。一般来说,安装 Minikube 只需运行两条命令:

$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-PLATFORM-amd64
$ sudo install minikube-PLATFORM-amd64 /usr/local/bin/minikube

Minikube 可在 Linux、macOS 或 Windows 上快速设置本地 Kubernetes 集群,其功能如下:

  • 支持最新的 Kubernetes 版本(包括 6 个以前的小版本)
  • 跨平台(Linux、macOS、Windows)
  • 以虚拟机、容器或裸机的形式部署
  • 支持多个容器运行时(CRI-O、containerd、Docker)
  • 用于快速推送镜像的 Docker API 端点
  • 负载均衡器、文件系统挂载、FeatureGates 和其他高级功能
  • 用于轻松安装 Kubernetes 应用的附加组件

因为 Minikube 是一个开源项目,你可以对它的源代码做贡献。

kind

 title=

kind 的开发者将其描述为“一个使用 Docker 容器‘节点’运行本地 Kubernetes 集群的工具”。它是为测试 Kubernetes 而设计的,但也可能用于本地开发或持续集成。

kind 支持:

  • 多节点(包括高可用性)集群
  • 从源码构建 Kubernetes 版本
  • Make/Bash/Docker 或 Bazel,以及预发布构建
  • Linux、MacOS 和 Windows

此外,kind 是一个经过云原生计算基金会(CNCF)认证的 Kubernetes 合规安装程序。因为它是开源的,你可以在它的 GitHub 仓库中找到 kind 的源码

CodeReady Container (CRC)

 title=

如果你想在本地尝试最新版本的 OpenShift,可以尝试红帽的 CodeReady Containers (CRC)。CRC 将一个最小的 OpenShift 4.x 集群带到你的本地计算机上,为开发和测试目的提供一个最小的环境。CRC 主要针对开发者的桌面使用。

你可以在 GitHub 上找到 CodeReady Container 的源码,也是在 Apache 2.0 许可下提供的。

Minishift

 title=

Minishift 项目帮助你在本地用 OKD 在虚拟机内的单节点 OpenShift 集群运行一个版本的 OpenShift。你可以用它来尝试 OpenShift,或者在你的本地主机上为云开发。

和这个列表中的其他工具一样,Minishift 也是开源的,你可以在 GitHub 上访问它的源码

为人服务的 Kubernetes

正如你所看到的,有几种方法可以在本地环境中试用 Kubernetes。我有遗漏么?欢迎留言提问或提出建议。


via: https://opensource.com/article/20/11/run-kubernetes-locally

作者:Bryant Son 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

将 Kubernetes 与 Ansible 结合实现云端自动化。此外,还可以参照我们的 Ansible 的 k8s 模块速查表。

Ansible 是实现自动化工作的优秀工具,而 Kubernetes 则是容器编排方面的利器,要是把两者结合起来,会有怎样的效果呢?正如你所猜测的,Ansible + Kubernetes 的确可以实现容器编排自动化。

Ansible 模块

实际上,Ansible 本身只是一个用于解释 YAML 文件的框架。它真正强大之处在于它丰富的模块,所谓 模块 module ,就是在 Ansible 剧本 playbook 中让你得以通过简单配置就能调用外部应用程序的一些工具。

Ansible 中有模块可以直接操作 Kubernetes,也有对一些相关组件(例如 DockerPodman)实现操作的模块。学习使用一个新模块的过程和学习新的终端命令、API 一样,可以先从文档中了解这个模块在调用的时候需要接受哪些参数,以及这些参数在外部应用程序中产生的具体作用。

访问 Kubernetes 集群

在使用 Ansible Kubernetes 模块之前,先要有能够访问 Kubernetes 集群的权限。在没有权限的情况下,可以尝试使用一个短期在线试用账号,但我们更推荐的是按照 Kubernetes 官网上的指引,或是参考 Braynt Son 《入门 Kubernetes》的教程安装 Minikube。Minikube 提供了一个单节点 Kubernetes 实例的安装过程,你可以像使用一个完整集群一样对其进行配置和交互。

在安装 Minikube 之前,你需要确保你的环境支持虚拟化并安装 libvirt,然后对 libvirt 用户组授权:

$ sudo dnf install libvirt
$ sudo systemctl start libvirtd
$ sudo usermod --append --groups libvirt `whoami`
$ newgrp libvirt

安装 Python 模块

为了能够在 Ansible 中使用 Kubernetes 相关的模块,你需要安装以下这些 Python 模块:

$ pip3.6 install kubernetes --user
$ pip3.6 install openshift --user

启动 Kubernetes

如果你使用的是 Minikube 而不是完整的 Kubernetes 集群,请使用 minikube 命令在本地创建一个最精简化的 Kubernetes 实例:

$ minikube start --driver=kvm2 --kvm-network default

然后等待 Minikube 完成初始化,这个过程所需的时间会因实际情况而异。

获取集群信息

集群启动以后,通过 cluster-info 选项就可以获取到集群相关信息了:

$ kubectl cluster-info
Kubernetes master is running at https://192.168.39.190:8443
KubeDNS is running at https://192.168.39.190:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

使用 k8s 模块

Ansible 使用 k8s 这个模块来实现对 Kubernetes 的操作,在剧本中使用 k8s 模块就可以对 Kuvernetes 对象进行管理。这个模块描述了 kubectl 命令的最终状态,例如对于以下这个使用 kubectl 创建新的命名空间的操作:

$ kubectl create namespace my-namespace

这是一个很简单的操作,而对这个操作的最终状态用 YAML 文件来描述是这样的:

- hosts: localhost
  tasks:
    - name: create namespace
      k8s:
        name: my-namespace
        api_version: v1
        kind: Namespace
        state: present

如果你使用的是 Minikube,那么主机名(hosts)应该定义为 localhost。需要注意的是,所使用的模块也定义了可用参数的语法(例如 api_versionkind 参数)。

在运行这个剧本之前,先通过 yamllint 命令验证是否有错误:

$ yamllint example.yaml

确保没有错误之后,运行剧本:

$ ansible-playbook ./example.yaml

可以验证新的命名空间是否已经被创建出来:

$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   37h
kube-node-lease   Active   37h
kube-public       Active   37h
kube-system       Active   37h
demo              Active   11h
my-namespace      Active   3s

使用 Podman 拉取容器镜像

容器是个 Linux 系统,几乎是最小化的,可以由 Kubernetes 管理。LXC 项目和 Docker 定义了大部分的容器规范。最近加入容器工具集的是 Podman,它不需要守护进程就可以运行,为此受到了很多用户的欢迎。

通过 Podman 可以从 Docker Hub 或者 Quay.io 等存储库拉取容器镜像。这一操作对应的 Ansible 语法也很简单,只需要将存储库网站提供的镜像路径写在剧本中的相应位置就可以了:

   - name: pull an image
      podman_image:
        name: quay.io/jitesoft/nginx

使用 yamllint 验证:

$ yamllint example.yaml

运行剧本:

$ ansible-playbook ./example.yaml
[WARNING]: provided hosts list is empty, only localhost is available.
Note that the implicit localhost does not match 'all'

PLAY [localhost] ************************

TASK [Gathering Facts] ************************
ok: [localhost]

TASK [create k8s namespace] ************************
ok: [localhost]

TASK [pull an image] ************************
changed: [localhost]

PLAY RECAP ************************
localhost: ok=3 changed=1 unreachable=0 failed=0
           skipped=0 rescued=0 ignored=0

使用 Ansible 实现部署

Ansible 除了可以执行小型维护任务以外,还可以通过剧本实现其它由 kubectl 实现的功能,因为两者的 YAML 文件之间只有少量的差异。在 Kubernetes 中使用的 YAML 文件只需要稍加改动,就可以在 Ansible 剧本中使用。例如下面这个用于使用 kubectl 命令部署 Web 服务器的 YAML 文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-webserver
spec:
  selector:
    matchLabels:
      run: my-webserver
  replicas: 1
  template:
    metadata:
      labels:
        run: my-webserver
    spec:
      containers:
      - name: my-webserver
        image: nginx
        ports:
        - containerPort: 80

如果你对其中的参数比较熟悉,你只要把 YAML 文件中的大部分内容放到剧本中的 definition 部分,就可以在 Ansible 中使用了:

   - name: deploy a web server
      k8s:
        api_version: v1
        namespace: my-namespace
        definition:
          kind: Deployment
          metadata:
            labels:
              app: nginx
            name: nginx-deploy
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: nginx
            template:
              metadata:
                labels:
                  app: nginx
              spec:
                containers:
                  - name: my-webserver
                    image: quay.io/jitesoft/nginx
                    ports:
                      - containerPort: 80
                        protocol: TCP

执行完成后,使用 kubectl 命令可以看到预期中的的 部署 deployment

$ kubectl -n my-namespace get pods
NAME                      READY  STATUS
nginx-deploy-7fdc9-t9wc2  1/1    Running

在云上使用模块

随着现在越来越多的开发和部署工作往云上转移的趋势,我们必须了解如何在云上实现自动化。其中 k8spodman_image 这两个模块只是云开发中的其中一小部分。你可以在你的工作流程中寻找一些需要自动化的任务,并学习如何使用 Ansible 让你在这些任务上事半功倍。


via: https://opensource.com/article/20/9/ansible-modules-kubernetes

作者:Seth Kenlon 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

作为云原生的核心产品,Kubernetes 提供的编排和管理功能,能轻松完成大规模容器部署,但 Kubernetes 自身的复杂性也导致众多企业一直徘徊于容器服务之外。据调查,只有不足 10% 的用户表示使用 Kubernetes 时没有遇到阻碍。

在 2019 年的一个关于容器技术的一个调查数据中,有 40% 的受访者表示计划采用容器。然而,据 UCloud 产品经理张鹏波透露说,在他们接触的用户当中,曾经在两年前表示有兴趣迁移到容器的用户,两年过去了,这些用户很多依旧“计划采用”容器服务。

这让我好奇其中发生了什么。让我们一起来探寻一下其中的症结,以及是否可以将复杂的 Kubernetes变得不复杂。

Kubernetes 复杂吗?

自从 2017 年,Kubernetes 在容器编排三强争霸赛中胜出后,就成为了容器编排领域的事实标准,极大的助推了容器技术在业界的发展。作为企业级的容器服务编排系统,Kubernetes 从技术上是现在、乃至未来的主流。

容器拥有很多优点,包括不可变环境、轻量级、快速启动等优势;而容器编排系统又在此基础上更进一步,提供了更加强大的功能,包括自动部署、快速扩容、故障自愈等等。

然而,在这一系列令人神往的优势和功能背后,Kubernetes 也相应的引入了更多的复杂性。这些复杂性体现在多个方面,比如说:

  • 首先是 Kubernetes 架构,本质上,Kubernetes 是用来管理分布式系统的平台。而一说到分布式,复杂性是不可避免的,管理分布式系统的平台自然也不例外。
  • 另外是容器支持的网络,Kubernetes 支持的网络类型很多。很多用户对于 Kubernetes 的网络非常疑惑或者说很纠结,当业务要迁移到 Kubernetes 时,选择什么类型的网络是一个难以抉择的问题。特别是在业务迁移上去之后又遇到一些问题的话,排查起来会非常麻烦,这给用户带来很大负担。
  • 最后还有就是各种各样 Kubernetes 组件的配置,这些都是用户将业务迁移到 Kubernetes 的障碍。

有什么解决方案吗?

如上所述,并不是每个用户都能尝到桃子的美味的,还有很多渴望迁移到容器环境的用户被拒之门外。

在这种情况下,全球各家云服务商,都纷纷推出自己的容器编排服务,在 Kubernetes上构建了自己的 Kubernetes发行版或定制产品。

而作为中国第一家公有云科创板上市公司,UCloud 利用在 UK8S 产品的技术沉淀,推出新的容器管理服务产品 Cube:两步即可部署容器化应用;采用无服务器形态,不需要再维护底层基础设施;按秒后付费,无需预留资源;降低企业部署云原生产品的学习和技术门槛。

为什么要推出 Cube?

在容器和 Kubernetes 如火如荼发展的同时,UCloud 发现,在他们的 UK8S 上线大概两年多的时间里,之前曾经想把业务迁到 Kubernetes 的用户。在两年后的今天,他们还是说这个话,说我很想上 Kubernetes,还需要你们来做技术交流。

UCloud 产品经理张鹏波说:

这让我们一度很困惑,我们一开始也做了一些尝试,比如说做了很多线下的培训、线上的交流,尝试去推动用户把他们的业务迁移到 UK8S 里面来。但是发现这个过程非常缓慢,我们没有办法控制和推动用户的迁移流程。很多公司的业务在快速发展,运维和研发是没有办法做架构上的调整的。

发现沟通、培训这条路实际上是走不通之后的。后来我们想,能不能换一条路,能不能基于 Kubernetes提供这样一个产品:这个产品只具有 Kubernetes 好处,掩盖了 Kubernetes 的复杂性,只提供类似于自动部署、快速扩容这样的特性,而用户不需要关心底层的 Kubernetes 架构,不需要再操心 Kubernetes 的网络了,也不需要去学习 Kubernetes 的各种 API 了。

Cube 的设计思路

沿着这个思路,UCloud 形成了自己的 Cube 产品。它的设计是从以下几个方面考虑的:

首先,Kubernetes 里面哪些功能是会经常会用到的,比如 Deployment 控制多副本容器组的管理, Job 控制任务型容器组,Service 做服务发现,PVC可以用来抽象使用块存储以及文件存储。这是 Kubernetes 最核心的一些功能。UCloud 在设计 Cube 的时候,希望将这些功能全部保留。这意味着整个 Cube 是基于 Kubernetes 来实现的。把这些复杂性全部屏蔽掉,用户不需要维护 Kubernetes 集群,不需要操心 Kubernetes 网络方案,而是由 Cube 提供一个最优网络方案,把容器的网络和虚拟机的网络扁平化。

其次,把业务迁移到 Kubernetes 的时候,把单体业务变成分布式业务、微服务的时候,用户一定需要考虑容器日志的统一收集、统一管理的问题。在 Cube 里面自动完成了日志的采集工作,集成了日志管理工作。另外,对容器环境的监控也是同样的道理,统一在 Cube 中完成。

当把这些产品全部集成到 Cube 里以后,Cube 是一个什么样的产品形态呢?

首先保证 Kubernetes 最核心的功能,用户能够在 Cube 里面创建 Kubernetes 常用的对象;另外 Cube 的产品形态应该是无服务器的形式;最后,Cube 引入了轻量级的虚拟化技术,实现了容器组与容器组之间虚拟机级别的隔离,这样好处是什么呢?

我们都知道容器的运行是共享使用宿主机的内核的,存在一定的安全风险,Cube 为每一个容器组实现了一层虚拟机的封装,可以使用户安全的运行容器;同时 UCloud 容器团队针对虚拟机的启动进行了深入优化,虚拟机启动速度最快只需要 125 毫秒。

Cube 的功能亮点

快速迁移

让我们横向对比一下,用户使用 Kubernetes 和 Cube 的流程上会有哪些区别。

左边是 Kubernetes,用户要把业务迁移到 Kubernetes,大概要经过这几个步骤:

  • 第一个步骤学习 Kubernetes,不仅仅是一个人,也可能不仅仅是一个团队,这个过程可能需要三个月到一年。
  • 搭建集群,考虑集群的参数配置、集群的维护工作。
  • 然后是做业务镜像。
  • 之后还要考虑了解 Kubernetes的 API 以及 Kubernetes 应用。
  • 最后才部署应用。

从 UCloud 观察到的情况来看,如果是对 Kubernetes非常熟悉的用户,这个过程可能要一两个月;但是如果对 Kubernetes 不熟悉,需要半年乃至一年。

使用 Cube 的话,就不再需要学习复杂的 Kubernetes知识了,和创建虚拟机一样在 Cube 里面创建一个应用,全部都是图形化的方式。所以,Cube 整个流程只有两步:

  • 制作镜像。
  • 在 Cube 的界面上直接部署应用就好了。

UCloud 产品经理张鹏波说,“我们有几个用户知道了 Cube 公测,公测以后第一天进行了解,第二天就把自己部署的业务迁移到 Cube 上来了,一天的时间就可以完成业务迁移的工作。”

成本降低

另外在成本方面,我们知道 Kubernetes 是一个大型的分布式集群,除了工作节点以外,还有管理节点。管理节点只是用来管理 Kubernetes 支持的应用,这部分开销实际上从企业角度来看是浪费的。对业务没有起到正向的作用,所以 Kubernetes 成本会比较高。

而对于 Cube,因为只需要为容器实例来付费,容器用了多少资源就付多少钱,不再考虑管理节点的开销、资源预留的问题。

更多的便利性

此外,还有一些其他针对 Kubernetes 自身的一些的改进。在 Cube 整个研发过程中,引入了一些亮点。

第一个是镜像预热,我们知道容器的启动速度其实很快的,基本一秒钟就能拉起来容器实例。但是这是热启动的情况,就是说工作节点上有这个镜像时,拉起来速度是很快的。而在冷启动的情况下,如果虚拟机上没有对应的镜像时,并且镜像非常大时,这个过程就非常缓慢了。我们遇到过最大的镜像有 20G 以上,容器的启动的时间就要花费几分钟。这样,容器本来说快速启动的优势就没有了,比虚拟机还慢了。所以,UCloud 在研发 Cube 的时候,使用了镜像预热的技术,把容器镜像变成 MBD 设备,在容器启动的时候,把它纳入到启动容器的节点上去,省去了镜像拉起的时间,让容器冷启动的时间从以前需要十几分钟变成现在只要几秒钟就拉起来了。

另外,因为 Kubernetes 是由谷歌开源的一项方案,很多理念和大部分企业更加超前一点。所以,在这种设计理念下,Kubernetes 每一个容器在重启以后,容器的 IP 就会变化。而我们知道很多传统的应用设计上是依赖于固定 IP 的,IP 一旦变化整个应用就会出现一些问题。很多用户都希望让容器重启后 IP 保持不变。这对于特别是有状态的服务尤为重要。所以,在 Cube 里面使用了 UCloud 的 EIP 功能,能够让用户容器重启时其 IP 保持不变。

最后,Cube 要兼容原有的运维习惯。传统上,虚拟机和 IDC 里面的物理机在使用体验上是没有什么差别的。有些用户之前业务部署在虚拟机,经常需要在出现问题的时候,直接登录到虚拟机里面去排错,查看一些日志。所以,为了兼容用户以前使用虚拟机的习惯,在 Cube 里面的容器也提供了登录功能,让用户在业务出现问题的时候,能够登录到容器里去快速排查问题。

结语

说实话,关于 Kubernetes 和各种发行版,我们也看过和研究过不少产品了,但是更多的是叶公好龙,没有将自己的应用迁移到 Kubernetes上的想法。一方面对着 Kubernetes 的各种先进特性馋涎欲滴,另外一方面却担心没有足够的精力面对全新的技术变化带来的挑战。

不过,今天看到 UCloud 的 Cube 产品,我决定要去亲自试试这个桃子的味道了。

随着业务的现代化和规模化,Kubernetes 和其背后的云原生成为如今软件系统的唯一选择。而对于众多的开发者来说, Kubernetes 并不是一个简单的问题,使用 Kubernetes 意味着需要理解 Kubernetes 背后的众多概念,你需要理解 Kubernetes 背后复杂的一套生态。但,对于一个企业来说,业务才是核心,Kubernetes 对于企业来说,更多只是一个基础设施,这个基础设施很重要,不得不有,但又无法产生价值,企业不会投入太多精力

在这种情况下,选择使用开源社区提供的发行版和各种管理工具,就成为一个并不经济的选项。对于企业来说,找到一个可以以最低心智负担接入的 Kubernetes 服务,才是最佳选择。相比于社区的众多发行版,Amazon EKS 屏蔽了 Kubernetes 底层的基础设施的部分,将 Worker 层面的工作保留给用户,既可以给予用户一定的自由,同时又可以让用户可以无痛的从传统架构切换至云原生架构上。

对于企业而言,Amazon EKS 服务,可能是一个最佳的选择。

做一个敢于承诺 SLA 的 Kubernetes 服务

和很多 Kubernetes 服务/开源软件不同,Amazon 的 EKS 服务主打的是一个高度可用、可扩展且安全的 Kubernetes 服务,并且,EKS 承诺,为客户提供了 99.95% 的可用性,让自己的客户可以安全高效的运转业务。在众多 Kubernetes 服务中,敢于提出向企业承诺可用性保障的 Kubernetes 服务,Amazon 是其中之首。这让 Amazon EKS 脱颖而出。

EKS 工作模式

Amazon EKS 通过托管控制平面节点,尽可能的降低用户在维护整个集群的成本。在使用 Amazon EKS 后,企业只需要维护执行业务所需的 Worker 节点,就可以搞定整个集群的运转。剩下的工作,就交给 AWS 来完成。AWS 为用户提供了一个可以跨多个 AWS 可用区,可扩展且高度可用的控制平面,从而确保无论在什么情况下 Kubernetes API 和 etcd 服务都可以正常运转。从而确保业务的可用性。

不仅如此,Amazon EKS 还通过整合 AWS 的其他业务,诸如 Elastic Load BalancingAWS CloudWatch 等服务,让整个 Kubernetes 集群可以更加动态的完成业务的请求而不会崩溃。

做一个功能强大的 Kubernetes 服务

企业之所以选择 AWS ,很大程度是因为 AWS 为企业提供了足够多的能力支持和足够强大的业务范围,只要你需要,AWS 就可以为你提供相应的服务。

基于用户的需求, AWS 在标准的 Kubernetes 服务的基础之上,引入了对于 AWS 更多能力的支持,包括:

  • 基于 AWS Cloud Map 的服务发现能力
  • 基于 Amazon VPC CNI 的网络能力
  • 基于 AWS IAM 验证器的权限管理能力
  • 基于 Elastic Load Balancing 的负载均衡能力
  • 基于 AWS Fargate 的无服务器计算能力
  • 基于 AWS Outposts 的混合云部署对接能力
  • 给予 AWS CloudTrail 的日志记录能力
  • 给予 AWS CloudWatch 的云监控能力

这些能力源自底层云计算强大实力的能力,非一般的云计算服务商所能比拟的。但,对于企业来说,也正是这些能力,给了企业无限的可能,企业可以放心大胆的拓展自己的业务,而无需担心自己的业务底层出现任何问题,源自于 AWS 多年的云计算研究的底气,非一般的云计算服务商所能比拟的。

做一个开放开源的 Kubernetes 服务

Kubernetes 的强大,源自于其生态链中的各种各样的软件和服务,而一个 Kubernetes 服务想要发挥最强的性能,就离不开和社区的 Kubernetes 服务进行整合,享受到来自社区的种种新能力的接入。

和一般的 Kuberntes 服务相比, Amazon EKS 提供了和上游 Kubernetes 一致的 API,这意味着如果企业希望使用 Kubernetes 生态中的插件或工具,都可以直接无痛接入,从而享受到来自 Kubernetes 社区的赋能。

同时,Amazon EKS 和上游保持一致也使得 Amazon EKS 可以十分轻松的完成 Kubernetes 集群的升级。Amazon EKS 会自动将正在运行的集群更新到最新的 Kubernetes 版本,对于企业来说,无需任何关注,集群就已经完成了整体的升级,让企业的集群可以享受到 Kubernetes 的最新特性。

不仅如此,Amazon EKS 还积极的参与到 Kubernetes SIG 的建设中,并开源出了诸如 CDK8s、FireCracker 这样的项目,来增强 Kubernetes 社区生态,帮助整个 Kubernetes 社区成长。

做一个不仅仅是 Kubernetes 的 Kubernetes 服务

Kubernetes 是云原生的未来,但对于专心于业务的企业来说,Kubernetes 可能还是太重了。如果你使用了 Amazon EKS ,则可以有一个更加简单的方案,就是在 Amazon EKS 基础之上,运行 AWS Fargate,从而将容器使用的成本进一步降低。

从 EKS 到 Fargate,变化的是提供的服务,不变的是让企业可以更加简单、低成本、无负担的切换到更好的基础设施的心态,也正是这样的心态,让 Amazon EKS 基于 Kubernetes ,但有提供了超出 Kubernetes 的服务。

总结

当你需要一个足够好用、足够安全、足够稳定的 Kubernetes 服务时, Amazon EKS 就会成为一个不错的选择;当你希望用尽可能少的精力去维护基础设施,希望将更多的精力投放在业务的研发上时,Amazon EKS 就会成为一个值得你选择的选项。如果你想要试一试 Kubernetes ,那为什么不从 Amazon EKS 开始呢?