标签: Kubernetes

Kubernetes 上容器的启动顺序如何把控?

为什么要做容器启动顺序控制?我们都知道 Pod 中除了 init-container 之外,是允许添加多个容器的。类似 TektonCD 中 task 和 step 的概念就分别与 pod 和 container 对应,而 step 是按照顺序执行的。此外还有服务网格的场景,sidecar 容器需要在服务容器启动之前完成配置的加载,也需要对容器的启动顺序加以控制。否则,服务容器先启动,而 sidecar 还无法提供网络上的支持。

现实

%title插图%num

 

期望

%title插图%num

 

到了这里肯定有同学会问,spec.containers[] 是一个数组,数组是有顺序的。Kubernetes 也确实是按照顺序来创建和启动容器,但是 容器启动成功,并不表示容器可以对外提供服务。

在 Kubernetes 1.18 非正式版中曾在 Lifecycle 层面提供了对 sidecar 类型容器的 支持,但是*终该功能并没有落地[2]。

那到底该怎么做?

%title插图%num

TL;DR

笔者准备了一个简单的 go 项目[3],用于模拟 sidecar 的启动及配置加载。

克隆代码后可以通过 make build 构建出镜像,假如你是用的 minikube 进行的实验,可以通过命令 make load-2-minikube 将镜像加载到 minikube 节点中。

使用 Deployment 的方式进行部署,直接用 Pod 也可以。

  1. apiVersion: apps/v1
  2. kind:Deployment
  3. metadata:
  4. creationTimestamp:null
  5. labels:
  6. app: sample
  7. name: sample
  8. spec:
  9. replicas:1
  10. selector:
  11. matchLabels:
  12. app: sample
  13. strategy:{}
  14. template:
  15. metadata:
  16. creationTimestamp:null
  17. labels:
  18. app: sample
  19. spec:
  20. containers:
  21. image: addozhang/k8s-container-sequence-sidecar:latest
  22. name: sidecar
  23. imagePullPolicy:IfNotPresent
  24. lifecycle:
  25. postStart:
  26. exec:
  27. command:
  28. -/entrypoint
  29. wait
  30. image: busybox:latest
  31. name: app
  32. imagePullPolicy:IfNotPresent
  33. command:[“/bin/sh”,”-c”]
  34. args:[“date; echo ‘app container started’; tail -f /dev/null”]

下面的截图中,演示了在 sample 命名空间中,pod 内两个容器的执行顺序。

%title插图%num

%title插图%num

Kubernetes 源码

在 kubelet 的源码 pkg/kubelet/kuberuntime/kuberuntime_manager.go 中,#SyncPod 方法用于创建 Pod,步骤比较繁琐,直接看第 7 步:创建普通容器。

  1. // SyncPod syncs the running pod into the desired pod by executing following steps:
  2. //
  3. // 1. Compute sandbox and container changes.
  4. // 2. Kill pod sandbox if necessary.
  5. // 3. Kill any containers that should not be running.
  6. // 4. Create sandbox if necessary.
  7. // 5. Create ephemeral containers.
  8. // 6. Create init containers.
  9. // 7. Create normal containers.
  10. func (m *kubeGenericRuntimeManager)SyncPod(pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff)(result kubecontainer.PodSyncResult){
  11. // Step 7: start containers in podContainerChanges.ContainersToStart.
  12. for _, idx := range podContainerChanges.ContainersToStart{
  13. start(“container”, containerStartSpec(&pod.Spec.Containers[idx]))
  14. }
  15. return
  16. }

在 #start 方法中调用了 #startContainer 方法,该方法会启动容器,并返回容器启动的结果。注意,这里的结果还 包含了容器的 Lifecycle hooks 调用。

也就是说,假如容器的 PostStart hook 没有正确的返回,kubelet 便不会去创建下一个容器。

  1. // startContainer starts a container and returns a message indicates why it is failed on error.
  2. // It starts the container through the following steps:
  3. // * pull the image
  4. // * create the container
  5. // * start the container
  6. // * run the post start lifecycle hooks (if applicable)
  7. func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeapi.PodSandboxConfig, spec *startSpec, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, podIP string, podIPs []string)(string, error){
  8. // Step 4: execute the post start hook.
  9. if container.Lifecycle!=nil&& container.Lifecycle.PostStart!=nil{
  10. kubeContainerID := kubecontainer.ContainerID{
  11. Type: m.runtimeName,
  12. ID: containerID,
  13. }
  14. msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart)
  15. if handlerErr !=nil{
  16. m.recordContainerEvent(pod, container, kubeContainerID.ID, v1.EventTypeWarning, events.FailedPostStartHook, msg)
  17. if err := m.killContainer(pod, kubeContainerID, container.Name,“FailedPostStartHook”, reasonFailedPostStartHook,nil); err !=nil{
  18. klog.ErrorS(fmt.Errorf(“%s: %v”,ErrPostStartHook, handlerErr),“Failed to kill container”,“pod”, klog.KObj(pod),
  19. “podUID”, pod.UID,“containerName”, container.Name,“containerID”, kubeContainerID.String())
  20. }
  21. return msg, fmt.Errorf(“%s: %v”,ErrPostStartHook, handlerErr)
  22. }
  23. }
  24. return“”,nil
  25. }

%title插图%num

实现方案

%title插图%num

cmd/entrypoint/wait.go#L26[4] (这里参考了 Istio 的 pilot-agent 实现 )

在 PostStart 中持续的去检查 /ready 断点,可以 hold 住当前容器的创建流程。保证 /ready 返回 200 后,kubelet 才会去创建下一个容器。

这样就达到了前面截图中演示的效果。

  1. for time.Now().Before(timeoutAt){
  2. err = checkIfReady(client, url)
  3. if err ==nil{
  4. log.Println(“sidecar is ready”)
  5. returnnil
  6. }
  7. log.Println(“sidecar is not ready”)
  8. time.Sleep(time.Duration(periodMillis)* time.Millisecond)
  9. }
  10. return fmt.Errorf(“sidecar is not ready in %d second(s)”, timeoutSeconds)

如何轻松地将可访问LAN的Pod部署到Kubernetes集群上

想要在Kubernetes集群上部署可访问LAN的Pod来达到目的?接下来就展示一下它实际上是多么容易。

%title插图%num

Kubernetes更具挑战性的方面之一是部署到集群,同时使你可以从LAN访问已部署的应用程序和服务。在发现hostNetwork设置之前,我一直为此努力。该特定选项适用于Kubernetes Pod,并使得可以从集群外部访问已部署的Pod。

通过使用此特定设置,窗格中的应用程序能够访问托管窗格的节点上的网络接口。从理论上讲,这意味着您实际上可以从LAN访问这些Pod。

我想向你展示如何进行这项工作。这很容易。

%title插图%num

你需要做的事

完成这项工作只需一个正在运行的Kubernetes集群。该群集可以位于AWS,Google Cloud,您自己的本地硬件或任何其他主机上。如果您还没有群集,则始终可以在数据中心上部署一个群集。

一旦访问了Kubernetes集群,就可以部署一个外部环境或至少您的LAN可以访问的Pod。

%title插图%num

如何创建你的YAML文件

我们要做的*件事是创建一个非常基础的YAML文件,以演示如何使用hostNetworking设置。这个YAML会将一个influxdb pod部署到Kubernetes集群,然后我们可以从集群外部访问它。

在Kubernetes控制器上,使用以下命令创建新的YAML文件:

namo fluxdb.yml

在该新文件中,粘贴以下内容:

apiVersion: v1kind: Podmetadata: name: influxdbspec: hostNetwork: true containers:    -name: influxdb     image: influxdb

这里重要的一点是:

hostNetwork:true

上面的设置为Pod提供了对主机网络接口的必要访问权限。如果没有该设置,则Pod仍将部署,但只能从群集内访问。YAML文件使用单个容器(也称为influxdb)创建一个名为influxdb的Pod,该容器使用influxdb映像。

保存并关闭文件。

%title插图%num

如何部署吊舱

现在,我们将部署新的pod。这是通过以下命令完成的:

Kubectl create -f influxdb.yml

该Pod将部署到群集,但是完成部署将花费一点时间。

%title插图%num

如何测试外部访问

接下来,我们将测试新部署的Pod的外部访问。为此,我们必须找出Pod部署到哪个节点,这还将向我们显示该节点的IP地址。为此,发出命令:

Kubectl create pod influxdb

上面的命令将打印出有关你新部署的Pod的大量信息。我们想要的重要部分位于IPs部分。你应该看到类似以下的行:

IP:192.168.1.112

IP:行将列出已将Pod部署到的节点的IP地址。掌握了这些信息之后,您可以使用以下命令测试连接:

curl -v http:// IP:8086 / ping

其中IP是托管influxdb Pod的节点的IP地址。您收到的响应应包括HTTP / 1.1 204 No Content(图A)。

%title插图%num

恭喜,你刚刚将Pod部署到可通过LAN访问的Kubernetes集群。

是不是并不像你想象中那么难!

原文链接:

https://www.techrepublic.com/article/how-to-easily-deploy-lan-accessible-pods-to-a-kubernetes-cluster/

分布式架构的王者?Kubernetes凭什么

说起kubernetes,主要是通过动态伸缩容来解决容器扩容的问题。随着技术的不断发展,微服务对互联网架构的不断影响,微服务对运维行业的压力也造成了非常大的影响,kubernetes已经在devops领域,占据了非常重要的地位,或者毫不夸张的说,已经可以成为一个行业的标准了。

kubernetes是一个分布式架构的王者,解决了微服务的很多技术难题和运维烦恼,但是它并不是一下就进化而来,ta到底是要解决什么样的问题,适合哪些的应用场景呢?现在的kubernetes有哪些缺陷,未来的技术发展方向是哪里呢?我们更加应该关注这些,才能让我们更好的把握好趋势,体会到技术的魅力。

%title插图%num

虚拟化

在熟悉kubernets之前,我们应该先了解一下虚拟化,kubernetes本身就是一个虚拟化的产品。理解虚拟化,可以帮助我们更好的理解kubernetes是如何帮助我们解决行业痛点,为何如此的被大众如此热衷的。

1. 什么是虚拟化

在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、⽹络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使⽤户可以⽐原本的组态更好的⽅式来应⽤这些资源。这些资源的新虚拟部分是不受现有资源的架设⽅式,地域或物理组态所限制。⼀般所指的虚拟化资源包括计算能⼒和资料存储。

2. 虚拟化的分类

根据在整个系统中的位置不同,虚拟化架构分为以下几种:

  • 寄居虚拟化架构
  • 裸金属虚拟化架构
  • 操作系统虚拟化架构
  • 混合虚拟化架构

1)寄居虚拟化架构

寄居虚拟化架构指在宿主操作系统之上安装和运行虚拟化程序,依赖于宿主操作系统对设备的支持和物理资源的管理。(类似 Vmware Workstation 的程序)

%title插图%num

2)裸金属虚拟化架构

裸金属虚拟化架构指直接在硬件上面安装虚拟化软件,再在其上安装操作系统和应用,依赖虚拟层内核和服务器控制台进行管理。

%title插图%num

3)操作系统虚拟化架构

操作系统虚拟化架构在操作系统层面增加虚拟服务器功能。操作系统虚拟化架构把单个的操作系统划分为多个容器,使用容器管理器来进行管理。

宿主操作系统负责在多个虚拟服务器(即容器)之间分配硬件资源,并且让这些服务器彼此独立。

%title插图%num 4)混合虚拟化架构

混合虚拟化架构将一个内核级驱动器插入到宿主操作系统内核。这个驱动器作为虚拟硬件管理器来协调虚拟机和宿主操作系统之间的硬件访问。

%title插图%num

3. 虚拟化的特点

虚拟化具有以下特点:

  • 分区:对物理机分区,可实现在单一物理机上同时运行多个虚拟机。
  • 隔离:同一物理机上多个虚拟机相互隔离。
  • 封装:整个虚拟机执行环境封装在独立文件中。
  • 独立:虚拟机无须修改,可运行在任何物理机上。

%title插图%num

常用的虚拟化技术

1. openstack

OpenStack:开源管理项⽬ OpenStack是⼀个旨在为公共及私有云的建设与管理提供软件的开源项⽬。它不是⼀个软件,⽽是由⼏个主要的组件组合起来完成⼀些具体的⼯作。OpenStack由以下五个相对独⽴的组件构成:

  • OpenStack Compute(Nova)是⼀套控制器,⽤于虚拟机计算或使⽤群组启动虚拟机实例;
  • OpenStack镜像服务(Glance)是⼀套虚拟机镜像查找及检索系统,实现虚拟机镜像管理;
  • OpenStack对象存储(Swift)是⼀套⽤于在⼤规模可扩展系统中通过内置冗余及容错机制,以对象为单位的存储系统,类似于Amazon S3;
  • OpenStack Keystone,⽤于⽤户身份服务与资源管理以及
  • OpenStack Horizon,基于Django的仪表板接⼝,是个图形化管理前端。这个起初由美国国家航空航天局和Rackspace在2010年末合作研发的开源项⽬,在打造易于部署、功能丰富且易于扩展的云计算平台。OpenStack项⽬的⾸要任务是简化云的部署过程并为其带来良好的可扩展性,企图成为数据中⼼的操作系统,即云操作系统。

2. KVM

KVM(Kernel-based Virtual Machine)基于内核的虚拟机 KVM是集成到Linux内核的Hypervisor,是X86架构且硬件⽀持虚拟化技术(Intel VT或AMD-V)的Linux的全虚拟化解决⽅案。它是Linux的⼀个很⼩的模块,利⽤Linux做⼤量的事,如任务调度、内存管理与硬件设备交互等。KVM*⼤的好处就在于它是与Linux内核集成的,所以速度很快

3. VMWare

VMWare (Virtual Machine ware)是⼀个“虚拟PC”虚拟机管理管理软件。它的产品可以使你在⼀台机器上同时运⾏两个或更多Windows、 DOS、LINUX系统。与“多启动”系统相⽐,VMWare采⽤了完全不同的概念。多启动系统在⼀个时刻只能运⾏⼀个系统,在系统切换时需要重新启动机器。VMWare是真正“同时”运⾏,多个操作系统在主系统的平台上,就象标准Windows应⽤程序那样切换。⽽且每个操作系统你都可以进⾏虚拟的分区、配置⽽不影响真实硬盘的数据,你甚⾄可以通过⽹卡将⼏台虚拟机⽤⽹卡连接为⼀个局域⽹,*其⽅便。安装在VMware操作系统性能上⽐直接安装在硬盘上的系统低不少,因此,⽐较适合学习和测试。

%title插图%num

容器和云计算

1. 容器发展史

1)Chroot

容器技术的概念可以追溯到1979年的UNIX Chroot。这项功能将Root⽬录及其它⼦⽬录变更⾄⽂件系统内的新位置,且只接受特定进程的访问,其设计⽬的在于为每个进程提供⼀套隔离化磁盘空间。1982年其被添加⾄BSD。

chroot只是提供了对进程⽂件⽬录虚拟化的功能,不能够防⽌进程恶意访问系统。这个问题在FreeBSDGails容器技术中得以解决

2)FreeBSD Jails

FreeBSD Jails与Chroot的定位类似,不过其中包含有进程沙箱机制以对⽂件系统、⽤户及⽹络等资源进⾏隔离。通过这种⽅式,它能够为每个Jail、定制化软件安装包乃⾄配置⽅案等提供⼀个对应的IP地址。Jails技术为FreeBSD系统提供了⼀种简单的安全隔离机制。它的不⾜在于这种简单性的隔离也同时会影响Jails中应⽤访问系统资源的灵活性。

3)Solaris Zones

Solaris Zone技术为应⽤程序创建了虚拟的⼀层,让应⽤在隔离的Zone中运⾏,并实现有效的资源管理。每⼀个Zone 拥有⾃⼰的⽂件系统,进程空间,防⽕墙,⽹络配置等等。

Solaris Zone技术真正的引⼊了容器资源管理的概念。在应⽤部署的时候为Zone配置⼀定的资源,在运⾏中可以根据Zone的负载动态修改这个资源限制并且是时⽣效的,在其他Zone不需要资源的时候,资源会⾃动切换给需要的资源的Zone,这种切换是即时的不需要⼈⼯⼲预的,*⼤化资源的利⽤率,在 必要的情况下,也可以为单个Zone隔离⼀定的资源。

4)LXC

LXC指代的是Linux Containers,其功能通过Cgroups以及Linux Namespaces实现。也是第⼀套完整的Linux容器管理实现⽅案。在LXC出现之前,Linux上已经有了类似Linux-Vserver、OpenVZ和FreeVPS。虽然这些技术都已经成熟,但是这些解决⽅案还没有将它们的容器⽀持集成到主流 Linux 内核。相较于其它容器技术, LXC能够在⽆需任何额外补丁的前提下运⾏在原版Linux内核之上。⽬前LXC项⽬由Canonical有限公司负责赞助及托管

5)Docker

Docker项⽬*初是由⼀家名为DotCloud的平台即服务⼚商所打造,其后该公司更名为Docker。Docker在起步阶段使⽤LXC,⽽后利⽤⾃⼰的Libcontainer库将其替换下来。与其它容器平台不同,Docker引⼊了⼀整套与容器管理相关的⽣态系统。其中包括套⾼效的分层式容器镜像模型、⼀套全局及本地容器注册表、⼀个精简化REST API以及⼀套命令⾏界⾯等等。

与Docker具有同样⽬标功能的另外⼀种容器技术就CoreOS公司开发的Rocket. Rocket基于AppContainer规范并使其成为⼀项更为开放的标准

2. Docker容器

Docker简单高效的思想, 快速的被广大的用户所接受。

1)Docker历史

2010年,⼏个搞IT的年轻⼈在美国旧⾦⼭成⽴了⼀家名叫“dotCloud”的公司。这家公司主要提供基于PaaS的云计算技术服务。具体来说,是和LXC有关的容器技术。LXC,就是Linux容器虚拟技术(Linux container)、后来,dotCloud公司将⾃⼰的容器技术进⾏了简化和标准化,并命名为——Docker。

Docker技术诞⽣之后,并没有引起⾏业的关注。⽽dotCloud公司,作为⼀家⼩型创业企业,在激烈的竞争之下,也步履维艰。正当他们快要坚持不下去的时候,脑⼦⾥蹦出了“开源”的想法。

什么是“开源”?开源,就是开放源代码。也就是将原来内部保密的程序源代码开放给所有⼈,然后让⼤家⼀起参与进来,贡献代码和意⻅。

Open Source,开源有的软件是⼀开始就开源的。也有的软件,是混不下去,创造者⼜不想放弃,所以选择开源。⾃⼰养不活,就吃“百家饭”嘛。

2013年3⽉,dotCloud公司的创始⼈之⼀,Docker之⽗,28岁的Solomon Hykes正式决定,将Docker项⽬开源。

不“开”则已,⼀“开”惊⼈。

越来越多的IT⼯程师发现了Docker的优点,然后蜂拥⽽⾄,加⼊Docker开源社区。Docker的⼈⽓迅速攀升,速度之快,令⼈瞠⽬结⾆。开源当⽉,Docker 0.1版本发布。此后的每⼀个⽉,Docker都会发布⼀个版本。到2014年6⽉ 9⽇,Docker 1.0版本正式发布。

此时的Docker,已经成为⾏业⾥⼈⽓*⽕爆的开源技术,没有之⼀。甚⾄像Google、微软、Amazon、 VMware这样的巨头,都对它⻘睐有加,表示将全力⽀持。

Docker⽕了之后,dotCloud公司⼲脆把公司名字也改成了Docker Inc.。Docker和容器技术为什么会这么⽕爆?说⽩了,就是因为它“轻”, 简单、快速。

2)Docker的原理

容器是⼀种轻量级的虚拟化技术,因为它跟虚拟机⽐起来,它少了⼀层 hypervisor 层。

hypervisor是⼀种运⾏在物理服务器和操作系统之间的中间层软件,可以允许多个操作系统和应⽤共享⼀套基础物理硬件。可以将hypervisor看做是虚拟环境中的“元”操作系统,可以协调访问服务器上的所有物理设备和虚拟机,所以⼜称为虚拟机监视器(virtual machine monitor)。hypervisor是所有虚拟化技术的核⼼,⾮中断的支持多⼯作负载迁移是hypervisor的基本功能。当服务器启动并执⾏hypervisor时,会给每⼀台虚拟机分配适量的内存、CPU、网络和磁盘资源,并且加载所有虚拟机的客户操作系统。

对于容器来说,*重要的是怎么保证这个进程所⽤到的资源是被隔离和被限制住的,在 Linux 内核上⾯是由 cgroup 和 namespace 这两个技术来保证的。

3)NameSpace

namespace 是⽤来做资源隔离的,在Linux 内核上有七种 namespace,docker 中⽤到了前六种。第七种cgroup namespace 在 docker 本身并没有⽤到,但是在 runC 实现中实现了 cgroup namespace。


%title插图%num

容器编排技术

随着微服务技术的发展,容器也给我们带来了一些新的挑战:

  • 怎么去管理那么多的容器
  • 怎么横向扩展
  • 容器down了,怎么恢复
  • 更新容器后如何灰度发布
  • 如何监控容器
  • 新创建的容器如何加入服务
  • 数据安全问题

1. 常用的docker编排工具

1)docker-compose

Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

2)swarm

⽬前三⼤主流的容器平台Swarm,Mesos和Kubernetes具有不同的容器调度系统;Swarm的特点是直接调度Docker容器,并且提供和标准Docker API⼀致的API。

每台服务器上都装有Docker并且开启了基于HTTP的DockerAPI。这个集群中有⼀个SwarmManager的管理者,⽤来管理集群中的容器资源。管理者的管理对象不是服务器层⾯⽽是集群层⾯的,也就是说通过Manager,我们只能笼统地向集群发出指令⽽不能具体到某台具体的服务器上要⼲什么(这也是Swarm的根本所在)。⾄于具体的管理实现⽅式,Manager向外暴露了⼀个HTTP接⼝,外部⽤户通过这个HTTP接⼝来实现对集群的管理

3)Mesos

Mesos针对不同的运⾏框架采⽤相对独⽴的调度系统,其框架提供了Docker容器的原⽣⽀持。Mesos并不负责调度⽽是负责委派授权,毕竟很多框架都已经实现了复杂的调度

4)Kubernetes

Kubernetes则采⽤了Pod和Label这样的概念把容器组合成⼀个个的互相存在依赖关系的逻辑单元。Pod中可以部署容器, 目前集成的是docker容器, 如果docker哪一天不流行了,pod的存在可以轻松切换。

相关容器被组合成Pod后被共同部署和调度,形成服务(Service)。这个是Kubernetes和Swarm,Mesos的主要区别。

Kubernetes(k8s)是⾃动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展。如果你曾经⽤过Docker容器技术部署容器,那么可以将Docker看成Kubernetes内部使⽤的低级别组件。

Kubernetes不仅仅⽀持Docker,还⽀持Rocket,这是另⼀种容器技术。

使⽤Kubernetes可以:

  • ⾃动化容器的部署和复制
  • 随时扩展或收缩容器规模
  • 将容器组织成组,并且提供容器间的负载均衡
  • 很容易地升级应⽤程序容器的新版本
  • 提供容器弹性,如果容器失效就替换它

看穿这些套路,你的kubernetes会更香

1. kubernetes架构设计

要了解Kubernetes的架构, 首先要看懂它的架构图。

%title插图%num

其实Kubernetes他就是一个分布式的王者解决方案,那他本身也是一个分布式系统的,是由master和多台node节点组成,master并不处理消息, 主要负责转发消息到node节点上,node才是我们真正处理业务能力的主要节点,这个我们可以借鉴nginx的master进程与process进程之间的关系,还有jenkins的主从也是主并不处理消息,分发给从来处理的。

master接收各种api,把请求接收进来,不论你是通过kubectl还是通过http的api接口,都由master接收,并把各种消息全部存储到etcd中,然后把任务分发出去,让node小弟开始干活,这是它一贯的“地主作风”。

2. kubernetes创建pod的时序图

我们再来看看kubernetes创建pod的时序图:

%title插图%num

kubernetes所有的交互过程,其实是把所有的数据存储在etcd中。

api server在处理请求的时候,都把所有的数据记录在etcd中,流程就结束了。

定时任务Scheduler也是出发api接口,把数据写入到etcd中,它的使命也完成了。

kubelet是它的客户端命令行,也是通过api接口把数据写入到etcd。

*终pod的调用过程也是要和docker容器进行挂钩的。

%title插图%num

kubernetes的核心概念

系统地梳理kubernetes的核心概念,可以让我们更加清晰、深刻地理解它们。

1. master

kubernetes集群中有一个节点,就是master节点。master节点包含kube-controller-manager、kube-apiserver、kube-scheduler、cloud-controller-manager等组成部分。它们主要是用来派发任务的,自己并不干活。像地主老财,核心机密都掌握在自己手中。

2. Node

kubernetes集群中除了master节点,就是node节点,node节点就是那些干活的,*底层的工作者。

3. kube-apiserver

Kubernetes API Server: Kubernetes API,集群的统一入口,各组件协调者,以HTTP API提供接口服务,所有对象资源的增删改查和监听操作都交给APIServer处理后再提交给Etcd存储。

所有对于kubernetes操作的所有命令,都是从这里发出去的,这里就像是中央首长的办公室,只有他发了话,kubernetes内部才会干活儿,正常运作起来。

4. kube-scheduler

从scheduler这个单词的意思,其实我们也可以猜出来其大概意思。如果要创建一个pod,人家接收到请求以后,直接写入到etcd中了,因为是分布式的,所有人家的事情就完成了。

但是真正创建pod的事情还没有做。比如, 在yu哪个node上创建pod、不同服务的负载情况、使用情况、负载均衡的算法等。其他一些后续的工作,都听从scheduler的调度,它发挥的是统一指挥的作用,进行资源安排。

5. kube-controller-manager

controller-manager主要是用来做什么的呢?从controller这个我们可以知道, 他这个是提供接口的, 但是他还有一个manager, 那种重点其实就是在这个manager上面。

我们使用docker,肯定是希望对docker容器进行动态的扩缩容。那接下来我们需要一个接口、需要给一个容器(比如nginx容器)、需要几个备份的副本、需要对容器有一个统一的manager入口。而controller-manager发挥的就是这个作用。

但是controller-manager并不仅仅包含副本个数的manager,还包括其他很多controller。现将contoller Manager包含的controller列举如下:

  1. Replication Controller
  2. Node Controller
  3. Namespace Controller
  4. Service Controller
  5. EndPoints Controller
  6. Service Account Controller
  7. Persistent Volume Controller
  8. Daemon Set Controller
  9. Deployment Controller
  10. Job Controller
  11. Pod Autoscaler Controller

它们的主要作用是进行副本的控制,只不过我们把副本拆分出了很多的模块, 对各种副本的控制。

6. etcd

这个不用说了,就是一个KV的nosql数据库,用来存储所有kubernetes中的所有数据。

7. kubelet

在学习kubelet之前,我们先来看一张图。

%title插图%num

kubelet主要是干什么的呢?其实说白了它就是一个kubernetes封装的客户端,类似于redis的redis-client,zookeeper的zookeeper-cli,可以在服务器上直接运行一些命令,操作kubernetes。其实kubelet*终也是把命令交给“中央首长”帮公司apiserver进行畸形处理。

8. kube-proxy

kube-proxy只是存在于node节点上,主要维护网络规则和四层负载均衡的工作。本质上,kube-proxy 类似一个反向代理, 我们可以把每个节点上运行的kube-proxy 看作service的透明代理兼LB。

kube-proxy 监听 apiserver 中service 与Endpoint 的信息,配置iptables 规则,请求通过iptables 直接转发给 pod。

9. pod

Pod是*小部署单元,一个Pod由一个或多个容器组成,Pod中容器共享存储和网络,在同一台Docker主机上运行。

为什么要设计这个pod的,直接用docker不香吗?这个是kubernetes设计中比较睿智的点,docker目前是*火的容器虚拟化技术,那如果来年不火了呢,或者是换成了其他呢?kubernetes是不是就跪了……这就是设计pod的巧妙之处,可以根据不同虚拟化容器技术,进行快速切换,减少开发的成本。

%title插图%num

kubernetes核心组件原理

1. RC[控制器]

ReplicationController

用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的pod来替代,而如果发生异常,多出来的容器也会自动回收。

在新版本的kubernetes中,建议使用ReplicaSet来取代ReplicationController。

2. RS[控制器]

ReplicaSet

ReplicaSet跟Repliation Controler没有本质的不同,只是名字不一样。并且ReplicaSet支持集合式的selector,虽然ReplicaSet可以独立使用,但一般还是建议使用Deployment来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update 但Deployment支持)。

Rolling-update的滚动更新:先创建新版本的pod容器,再删除老版本的pod容器。

3. Deployment

Deployment为pod和ReplicaSet提供了一个声明式定义方法,用来替代以前的ReplicationController来方便的管理应用。

deployment不仅仅可以滚动更新,而且可以进行回滚。如果发现升级到的新版本后服务不可用,可以回滚到上一个版本。

4. HAP

HPA是Horizontal Pod AutoScale的缩写,Horizontal Pod Autoscaling 仅适用于 Deployment 和 ReplicaSet,在V1版本中仅支持根据Pod的CPU利用率扩容,在vlalpha版本中,支持根据内存和用户自定义的metric扩缩容。

5. statefullSet

StatefullSet是为了解决有状态服务的问题(对应Deployments 和 ReplicaSets 是为无状态服务而设计)。其应用场景包括:

1)稳定的持久化存储,即Pod重新调度后还是能访问的相同持久化数据,基于PVC来实现。

2)稳定的网络标志,及Pod重新调度后其 PodName 和 HostName 不变,基于Headlesss Service(即没有 Cluster IP 的 Service)来实现。

3)有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行 (即从 0 到 N-1,在下一个Pod运行之前所有之前的Pod必须都是Running 和 Ready 状态),基于 init containers 来实现。

4)有序收缩,有序删除(即从N-1 到 0)。

6. DaemonSet

DaemonSet确保全部或者一些node打上污点,pod如果不定义容忍这个污点,那么pod就不会被调度器分配到这个node。

Node上运行一个Pod的副本。当有Node加入集群时,也会为他们新增一个Pod。当有Node从集群移 除时,这些Pod也会被回收。删除DaemonSet将会删除他创建的所有Pod,使用DaemonSet 的一些典型 用法:

1)运行集群存储daemon,例如在每个Node上运行glustered,ceph。

2)在每个Node上运行日志收集Daemon,例如:fluentd、logstash。

3)在每个Node上运行监控Daemon,例如:Prometheus Node Exporter Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束 Cron Job管理基于时间Job,即:在给定时间点只运行一次,周期性地在给定时间点运行。

7. Volume

数据卷,共享pod中容器使用的数据。

8. Label

标签用于区分对象(比如Pod、Service),键/值对存在;每个对象可以有多个标签,通过标签关联对象。

Kubernetes中任意API对象都是通过Label进行标识,Label的实质是一系列的Key/Value键值对,其中key与value由用户自己指定。

Label可以附加在各种资源对象上,如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去。

Label是Replication Controller和Service运行的基础,二者通过Label来进行关联Node上运行的 Pod。

我们可以通过给指定的资源对象捆绑一个或者多个不同的Label来实现多维度的资源分组管理功能,以便于灵活方便的进行资源分配、调度、配置等管理工作。一些常用的Label如下:

1)版本标签:

“release”:”stable”,”release”:”canary”……

2)环境标签:

“environment”:”dev”,”environment”:”qa”,”environment”:”production”

3)架构标签:

“tier”:”frontend”,”tier”:”backend”,”tier”:”middleware”

4)分区标签:

“partition”:”customerA”,”partition”:”customerB”

5)质量管控标签:

“track”:”daily”,”track”:”weekly”

Label相当于我们熟悉的标签,给某个资源对象定义一个Label就相当于给它贴上了一个标签,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。

Label Selector在Kubernetes中重要使用场景如下:-> kube-Controller进程通过资源对象RC上定义Label Selector来筛选要监控的Pod副本的数量,从而实现副本数量始终符合预期设定的全自动控制流程;-> kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立起每个Service到对应Pod 的请求转发路由表,从而实现Service的智能负载均衡;-> 通过对某些Node定义特定的Label,并且在Pod定义文件中使用Nodeselector这种标签调度策略,kuber-scheduler进程可以实现Pod“定向调度”的特性。

9. service

Service是一个抽象的概念。它通过一个虚拟的IP的形式(VIPs),映射出来指定的端口,通过代理客户端发来的请求转发到后端一组Pods中的一台(也就是endpoint)。

Service定义了Pod逻辑集合和访问该集合的策略,是真实服务的抽象。Service提供了统一的服务访 问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不需要了解后台Pod是如何运行。外部系统访问Service的问题:

首先需要弄明白Kubernetes的三种IP这个问题

  1. Node IP:Node节点的IP地址
  2. Pod IP: Pod的IP地址
  3. Cluster IP:Service的IP地址

首先,Node IP是Kubernetes集群中节点的物理网卡IP地址,所有属于这个网络的服务器之间都能通过这个网络直接通信。这也表明Kubernetes集群之外的节点访问Kubernetes集群之内的某个节点或者 TCP/IP服务的时候,必须通过Node IP进行通信。

其次,Pod IP是每个Pod的IP地址,他是Docker Engine根据docker0网桥的IP地址段进行分配的,通 常是一个虚拟的二层网络。

*后,Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络。

原因有以下几点:

Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址-> Cluster IP无法被ping,他没有一个“实体网络对象”来响应-> Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并 且他们属于Kubernetes集群这样一个封闭的空间。-> Kubernetes集群之内,Node IP网、Pod IP网与Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊路由规则。

Kubernetes 诞生七年,凭什么成为主流?

引言

作为一款开源的容器编排引擎,始于2014年的Kubernetes一经推出就受到了开发者的喜爱,在此之前,从来没有人想过能有一个同时被所有云供应商支持的分布式应用。在Kubernetes里,用户可以轻松地在虚拟机及硬件上运行程序,让开发者彻底摆脱过去以主机为中心的环境。Kubernetes在市场中并不是唯一的容器管理平台,但它支持用户只需要编写一次就能在所有类型的云供应商及私有云上运行,开发人员可以快速部署、随时拓展应用程序,同时降低了硬件的使用量。

经过了七年的发展历程,Kubernetes成为继Linux、Docker后*受欢迎的第三大平台的同时,也俨然已经成为云计算领域的主流应用。

近日,CSDN采访了VMware应用现代化业务部门研发副总裁、Kubernetes创始人Craig McLuckie,VMware首席工程师、Kubernetes创始人Joe Beda,VMware中国研发技术总监、CNCF Harbor开源项目创建人张海宁,邀请他们分享了Kubernetes的发展动态以及开源项目的成功秘诀。

1

容器与虚拟机的结合是必然趋势?

Kubernetes诞生七年,你认为它成功的秘诀是什么?

Joe Beda:Kubernetes在诞生之初我们就知道它在将来会有怎样的发展潜力,应该向什么方向发展。宛如儿时玩的拼图游戏,我们不仅有完成这个拼图所需要的所有部分,而且有完整的图纸。Kubernetes和其他项目相比,*大的不同之处在于:它是在正确的时机推出正确的创新。

更重要的是,我们在创建了Kubernetes之后吸引了更多人加入其中,把Kubernetes做成了一个社区,Kubernetes今天的成功正是靠后期集体的力量携手努力做到的,正如“独行快,众行远”这句谚语一般,这才是Kubernetes成功的关键。

随着云计算技术的应用与发展,未来容器会颠覆虚拟机吗?

Joe Beda:容器和虚拟机分别满足了不同的需求,但如果把这两个技术结合在一起,通常能够带来不错的结果。

虚拟机从一开始部署的时候就能实现很高水平的隔离,而且每一个虚拟机都有自己的内核,不会出现内核共用的情况。从安全的角度来看,界定清晰的安全边界能够让用户在使用的过程中更放心。

容器与hypervisor相比,它的优势在于启动和关闭都非常快速方便,和虚拟机相比,容器是一种更加轻量级的技术,多台容器可以共享同一个内核。另外,它的一个显著特点在于容器镜像方面,我们可以把同一个容器的镜像运行到笔记本电脑或者Kubernetes集群之上,而同一个容器的镜像在不同环境当中它的工作表现是一模一样的,这样当开发者跨越不同的环境进行开发就带来了使用上的便捷。

而且我们现在也看到越来越多的用户把容器和虚拟机放在一起来运行,就像我们此前讲到的这两个技术之间具有很强的互补性,这样一种部署能够让用户把两个技术的优势都发挥出来,比方说更高的开发效率、可移植性以及安全隔离等等。

%title插图%num

VMware首席工程师

Kubernetes创始人Joe Beda

VMware有没有计划推出容器本地的虚拟化?

Joe Beda:答案是肯定的,但我们是用不同的方法来实现的。比如说我们在vSphere 7当中内置了VMware本地的PODs,也就是说通过hypervisor来支持Kubernetes Pods。另外一个技术路径就是在Kubernetes的平台之上来托管虚拟机,长期以来VMware做了大量的投入和创新来不断完善hypervisor。

2

Kubernetes未来的发展方向

传统应用是通过购买成熟解决方案的方式获得的,我们选择现代应用的过程中应该直接选择购买还是自建应用程序呢?

Joe Beda:对于任何一个企业来说,无论是选择购买还是自建应用程序都要基于具体的业务需求以及市场上的现有产品来决定。今天我们看到,有越来越多针对Kubernetes的现成软件解决方案,打造现代化的应用程序不光是一个技术上的转型,也是一种文化上的转型。开发团队和运维团队之间一定要养成互动和反馈的良好习惯,这样才能帮助企业不断推出和构建可扩展性更好和可靠性更高的现代化应用。

Kubernetes有没有考虑过取代vSphere?未来发展方向在哪里?

Joe Beda:现在说Kubernetes替代vSphere肯定是为时过早的,我们认为Kubernetes和vSphere是互补的技术,而不是互相替代的技术。*初在创建Kubernetes的时候,考虑的就是将来要让Kubernetes运行到某种底层的基础架构之上,比如Google Compute Engine。所以今天我们看到Kubernetes无论是在Google Compute Engine还是在Amazon Elastic Compute Cloud (EC2),亦或是在VMware的vSphere上,都能够运行。

Craig McLuckie:事实上Kubernetes已经成为了一种新型的基础架构及服务IaaS的平台,这样就为用户带来了很多的机会,能够对他们任意环境当中的运维和开发工作进行标准化。而且对于Kubernetes来说,我们不仅是要把Kubernetes作为一个“终点”,也可以在构建任何一个目标系统的过程当中利用Kubernetes产生更多的效益。

%title插图%num

VMware应用现代化业务部门研发副总裁

Kubernetes创始人Craig McLuckie

3

如果构建一款成功的开源项目?

VMware Habor与Kubernetes一样,都是开源成功的典范,为什么会选择开源? 

张海宁:现在开源其实是一种主流的社区协作模式,当时将项目开源其实有两个目的。一是希望能有更多的用户来使用这项技术,对此进行反馈的同时方便我们检验市场的成熟度,从而对项目不断地优化。如果是闭源的话,其实很难迅速地获得大批量的用户。第二点,做开源是不是就意味着没有商业化的潜力?答案也不一定。开源以后,其实还是可以从中获取很多的商业价值的。Harbor本身是免费的,但是产品是要有企业去支持的,这二者之间并不矛盾,反而是一个互相配合的事情。

%title插图%num

VMware中国技术研发技术总监

CNCF Harbor开源项目创建人张海宁

Habor作为首个原创于中国的CNCF毕业项目,有哪些经验可以分享?

张海宁:首先,Harbor是可信的云原生制品仓库,*早其实它叫做企业级的镜像管理仓,是由VMware中国研发中心原创的一个开源项目,与Kubernetes一样,Harbor今年也7岁了。

CNCF的开源项目其实分了很多个级别,不同的级别代表不同的用户认可度和成熟度。*开始Sandbox沙箱是入门级,中间有一个Incubation孵化级,*后是Graduation毕业级。每一个项目在不同的级别中逐渐走向成熟,毕业级的考核是相当严格的,只有认证、检查、审计等等各个环节都达到要求以后才能毕业。同时毕业也意味着得到了国际开源组织对它的认可,在后面可以投入到生产环节中。

为什么要使用 Kubernetes 准入控制器

Kubernetes 控制平面由几个组件组成。其中一个组件是 kube-apiserver,简单的 API server。它公开了一个 REST 端点,用户、集群组件以及客户端应用程序可以通过该端点与集群进行通信。总的来说,它会进行以下操作:

  1. 从客户端应用程序(如 kubectl)接收标准 HTTP 请求。
  2. 验证传入请求并应用授权策略。
  3. 在成功的身份验证中,它能根据端点对象(Pod、Deployments、Namespace 等)和 http 动作(Create、Put、Get、Delete 等)执行操作。
  4. 对 etcd 数据存储进行更改以保存数据。
  5. 操作完成,它就向客户端发送响应。

%title插图%num

请求流程

现在让我们考虑这样一种情况:在请求经过身份验证后,但在对 etcd 数据存储进行任何更改之前,我们需要拦截该请求。例如:

  1. 拦截客户端发送的请求。
  2. 解析请求并执行操作。
  3. 根据请求的结果,决定对 etcd 进行更改还是拒*对 etcd 进行更改。

Kubernetes 准入控制器就是用于这种情况的插件。在代码层面,准入控制器逻辑与 API server 逻辑解耦,这样用户就可以开发自定义拦截器(custom interceptor),无论何时对象被创建、更新或从 etcd 中删除,都可以调用该拦截器。

有了准入控制器,从任意来源到 API server 的请求流将如下所示:

%title插图%num

准入控制器阶段(来自官方文档)

官方文档地址:https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/

根据准入控制器执行的操作类型,它可以分为 3 种类型:

  • Mutating(变更)
  • Validating(验证)
  • Both(两者都有)

Mutating:这种控制器可以解析请求,并在请求向下发送之前对请求进行更改(变更请求)。

示例:AlwaysPullImages

Validating:这种控制器可以解析请求并根据特定数据进行验证。

示例:NamespaceExists

Both:这种控制器可以执行变更和验证两种操作。

示例:CertificateSigning

有关这些控制器更多信息,查看官方文档:https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do

准入控制器过程包括按顺序执行的2个阶段:

  1. Mutating(变更)阶段(先执行)
  2. Validation (验证)阶段(变更阶段后执行)

Kubernetes 集群已经在使用准入控制器来执行许多任务。

Kubernetes 附带的准入控制器列表:https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do

通过该列表,我们可以发现大多数操作,如 AlwaysPullImages、DefaultStorageClass、PodSecurityPolicy 等,实际上都是由不同的准入控制器执行的。

%title插图%num

如何启用或禁用准入控制器?

要启用准入控制器,我们必须在启动 kube-apiserver 时,将以逗号分隔的准入控制器插件名称列表传递给 --enable-ading-plugins。对于默认插件,命令如下所示:

%title插图%num

要禁用准入控制器插件,可以将插件名称列表传递给 --disable-admission-plugins。它将覆盖默认启用的插件列表。

%title插图%num

%title插图%num

默认准入控制器

  • NamespaceLifecycle
  • LimitRanger
  • ServiceAccount
  • TaintNodesByCondition
  • Priority
  • DefaultTolerationSeconds
  • DefaultStorageClass
  • StorageObjectInUseProtection
  • PersistentVolumeClaimResize
  • RuntimeClass
  • CertificateApproval
  • CertificateSigning
  • CertificateSubjectRestriction
  • DefaultIngressClass
  • MutatingAdmissionWebhook
  • ValidatingAdmissionWebhook
  • ResourceQuota

%title插图%num

为什么要使用准入控制器?

准入控制器能提供额外的安全和治理层,以帮助 Kubernetes 集群的用户使用。

执行策略:通过使用自定义准入控制器,我们可以验证请求并检查它是否包含特定的所需信息。例如,我们可以检查 Pod 是否设置了正确的标签。如果没有,那可以一起拒*该请求。某些情况下,如果请求中缺少一些字段,我们也可以更改这些字段。例如,如果 Pod 没有设置资源限制,我们可以为 Pod 添加特定的资源限制。通过这样的方式,除非明确指定,集群中的所有 Pod 都将根据我们的要求设置资源限制。Limit Range 就是这种实现。

安全性:我们可以拒*不遵循特定规范的请求。例如,没有一个 Pod 请求可以将安全网关设置为以 root 用户身份运行。

统一工作负载:通过更改请求并为用户未设置的规范设置默认值,我们可以确保集群上运行的工作负载是统一的,并遵循集群管理员定义的特定标准。这些就是我们开始使用 Kubernetes 准入控制器需要知道的所有理论。

原文链接:https://medium.com/cloudlego/kubernetes-admission-controllers-request-interceptors-47a9b12c5303

未来,边缘计算的功能支柱是 Kubernetes

在数字化转型时代,5G网络是一个飞跃。5G正在推动边缘计算的发展,而Kubernetes则是5G与边缘计算之间的粘合剂。

%title插图%num

云计算的十年

云计算之于信息技术(IT)产业,就像石油之于汽车工业一样。云让数据触手可及,彻底改变了科技领域。本世纪初,亚马逊的EC2播下了云的种子。谷歌云和微软Azure紧随其后。然而,云计算的真正增长是在2010-2012年之后才突飞猛进的。

%title插图%num

Synergy Resarch Group云供应商增长图

未来的统计和趋势:

  • 到2021年,云计算将处理90%以上的工作负载(Cisco)
  • 企业将在私有云中运行大约41%的工作负载,在公有云中运行38%(RightScale)
  • 到2021年底,75%的计算实例和云工作负载将采用SaaS(Cisco)

%title插图%num

云原生

云原生的出现是云生态系统进化发展的一个标志。云原生架构的基本特性是对基础设施的多层抽象。这意味着云原生架构师必须通过代码定义这些层。在进行编码时可以加入一些功能,*大程度地提高业务价值。云原生还能够实现基础设施的可扩展性。

云原生容器技术为云原生生态系统的未来发展做出了显著贡献。它还在实现5G架构的实时能力方面发挥着重要的作用。借助以容器为中心的Web服务,5G网络公司能够提高弹性并更快地部署。容器使部署过程变得容易,它为5G基础设施提供了强大的动力,以扩展跨云网络的数据需求。组织可以利用容器来处理数据并进行大规模计算。

%title插图%num

来源:红帽

容器和DevOps的融合同样对于5G的发展起到了推动作用。引入这些松耦合服务将有助于5G供应商自动化应用部署,快速接收反馈,消除瓶颈,并持续改进。他们可以通过混合云按需提供资源,并进行统一管理。

电信行业已经点燃了“云原生之火”,未来十年将迅速蔓延。

%title插图%num

容器网络功能(CNF)的兴起

我们见证了容器网络功能(CNF)的兴起。CNF可以在跨多云或混合云基础设施的Kubernetes上运行。与传统上运行在VMware环境中的VNF相比,CNF是超轻量级的。CNF架构的一个关键因素是,它可以部署在裸机服务器上,从而大大降低了成本。

5G是电信领域的下一波浪潮,它有望提供具有自动化、弹性和透明的下一代服务。从需求架构来看,VNF(VMware环境)对于5G提供商而言不是理想的选择。从逻辑上讲,采用CNF是未来发展的必然选择。当然,完全抛弃VMware并非易事。因此,VNF和CNF的混合模型也是不错的选择。

%title插图%num

资料来源:Linux基金会

%title插图%num

边缘计算必须重塑方向

多个设备同时生成大量数据。让中心云来处理这些数据是一项艰巨的任务。边缘计算体系结构使基础设施靠近分布式环境中的数据设备,从而缩短了响应时间并降低了延迟。边缘计算对数据的本地处理简化了流程并降低了总成本。迄今为止,边缘计算一直是电信行业的催化剂。然而,随着5G的到来,这些界限都将被打破。

5G使宽带速度提高了10倍,并使设备密度骤降了大约100万台/平方公里。为此,5G需要超低延迟,这可以通过边缘计算支持的数字基础设施实现。

为确保5G的发展,边缘计算必须确保:

  • 更好的设备管理
  • 资源利用率高
  • 更轻量级的功能
  • 超低延迟
  • 增加安全防护,保障数据传输可靠性

%title插图%num

Kubernetes:在边缘为5G赋能

kubernetes(K8s)是一个开源的,用于管理云平台中多个主机上的容器化的应用。Kubernetes简化了跨分布式环境的底层计算,并在边缘赋予了一致性。Kubernetes通过自动化和快速部署以及更广泛的安全覆盖,帮助网络提供商*大化边缘容器的价值。用于边缘计算的Kubernetes将消除大多数劳动密集型工作负载,从而提高生产率和质量。

至少到目前为止,Kubernetes在释放5G的商业价值方面发挥着重要作用。唯一可以替代Kubernetes的是VMware,但由于空间和成本问题,目前暂时还无法做到。事实证明,Kubernetes架构可加速关键任务工作负载的自动化并降低5G部署的总体成本。

Kubernetes可以创建一个自我控制的闭环,从而确保所需数量的微服务被托管并控制在所需的级别。此外,Kubernetes的Horizontal Pod Autoscaler可以根据边缘的工作负载释放新的容器实例。

%title插图%num

KubeEdge:为Kubernetes提供优势

KubeEdge是一个基于Kubernetes的开源项目。*新版本KubeEdge v1.3对Kubernetes的功能进行了改进,可在边缘推动容器化应用程序的智能编排。KubeEdge通过对网络、应用程序、部署和元数据的基础设施支持,简化了边缘和云数据中心之间的通信。它还允许程序员创建自定义的逻辑脚本,以在资源受限的边缘设备通信。

%title插图%num

来源:Kubeedge.io

%title插图%num

未来

物联网、大数据和人工智能带来的设备激增将产生庞大的数据量。对于5G的而言,边缘计算必须处理这些复杂的工作负载并保持数据弹性。因此,Kubernetes将成为边缘计算的功能支柱,在编排容器化应用中赋予弹性。

原文链接:

https://dzone.com/articles/kubernetes-bridging-the-gap-between-5g-and-intelli

如何部署一个Kubernetes集群

在上一篇文章《Kubernetes和Docker的关系是什么?》中,和大家分享了关于Kubernetes的基本系统架构以及关于容器编排相关的概念,并总体阐述Kubernetes与Docker之间的基本关系。而要学习Kubernetes容器编排技术,首先要解决的就是学习环境问题,而由于Kubernetes本身具有一定的复杂性,且需要较大的系统资源环境,所以对于刚入门的读者来说如何快速部署一套Kubernetes学习环境就成了一件棘手的事情。

在本篇文章中,我以在Mac笔记本中安装两台Ubantu系统的方式,演示如何部署一套具备一个控制节点(Master)和一个计算节点(Worker)的Kubernetes学习集群。

%title插图%num

系统环境准备

要安装部署Kubernetes集群,首先需要准备机器,*直接的办法可以到公有云(如阿里云等)申请几台虚拟机。而如果条件允许,拿几台本地物理服务器来组建集群自然是*好不过了。但是这些机器需要满足以下几个条件:

  • 要求64位Linux操作系统,且内核版本要求3.10及以上,能满足安装Docker项目所需的要求;
  • 机器之间要保持网络互通,这是未来容器之间网络互通的前提条件;
  • 要有外网访问权限,因为部署的过程中需要拉取相应的镜像,要求能够访问到gcr.io、quay.io这两个dockerregistry,因为有小部分镜像需要从这里拉取;
  • 单机可用资源建议2核CPU、8G内存或以上,如果小一点也可以但是能调度的Pod数量就比较有限了;
  • 磁盘空间要求在30GB以上,主要用于存储Docker镜像及相关日志文件;

在本次实验中由于条件有限,我是在Mac笔记本上通过虚拟软件准备了两台虚拟机,其具体配置如下:

  • 2核CPU、2GB内存,30GB的磁盘空间;
  • Unbantu 20.04 LTS的Sever版本,其Linux内核为5.4.0;
  • 内网互通,外网访问权限不受控制;

%title插图%num

Kubeadm一键部署工具简介

作为典型的分布式系统,Kubernetes的部署一直是困扰初学者进入Kubernetes世界的一大障碍。在发布早期Kubernetes的部署主要依赖于社区维护的各种脚本,但这其中会涉及二进制编译、配置文件以及kube-apiserver授权配置文件等诸多运维工作。目前各大云服务厂商常用的Kubernetes部署方式是使用SaltStack、Ansible等运维工具自动化地执行这些繁琐的步骤,但即使这样,这个部署的过程对于初学者来说依然是非常繁琐的。

正是基于这样的痛点,在志愿者的推动下Kubernetes社区终于发起了kubeadm这一独立的一键部署工具,使用kubeadm我们可以通过几条简单的指令来快速地部署一个kubernetes集群。后面的内容,就将具体演示如何使用kubeadm来部署一个Kubernetes集群。

%title插图%num

安装Kubeadm及Docker环境

在准备的两台虚拟机中,分别安装Kubeadm部署工具及Docker环境。步骤如下:

1)、编辑操作系统安装源配置文件,添加kubernetes镜像源,命令如下:

  1. #添加Kubernetes官方镜像源apt-key
  2. root@kubenetesnode01:~#curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add –
  3. #添加Kubernetes官方镜像源地址
  4. root@kubernetesnode01:~# vim /etc/apt/sources.list
  5. #add kubernetes source
  6. deb http://apt.kubernetes.io/ kubernetes-xenial main

上述操作添加的是kubernetes的官方镜像源,如果apt.kubernetes.io因为网络原因访问不到,也可以换成国内Ubantu镜像源,如阿里云镜像源地址:

  1. #添加阿里云Kubernetes镜像源apt-key
  2. root@kubenetesnode01:~# curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add –
  3. #添加阿里云Kubernetes镜像源地址
  4. root@kubernetesnode01:~# vim /etc/apt/sources.list
  5. deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main

2)、镜像源添加后更新apt资源列表,命令如下:

  1. root@kubernetesnode01:~# apt-get update
  2. Hit:1 http://cn.archive.ubuntu.com/ubuntu focal InRelease
  3. Hit:2 http://cn.archive.ubuntu.com/ubuntu focal-updates InRelease
  4. Hit:3 http://cn.archive.ubuntu.com/ubuntu focal-backports InRelease
  5. Hit:4 http://cn.archive.ubuntu.com/ubuntu focal-security InRelease
  6. Get:5 https://packages.cloud.google.com/apt kubernetes-xenial InRelease [8,993 B]
  7. Get:6 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 Packages [37.7 kB]
  8. Fetched 46.7 kB in 7s (6,586 B/s)
  9. Reading package lists… Done

3)、完成上述2步后就可以通过apt-get命令安装kubeadm了,如下:

  1. root@kubernetesnode01:~# apt-get install -y docker.io kubeadm
  2. Reading package lists… Done
  3. Building dependency tree
  4. Reading state information… Done
  5. The following additional packages will be installed:
  6. bridge-utils cgroupfs-mount conntrack containerd cri-tools dns-root-data dnsmasq-base ebtables kubectl kubelet kubernetes-cni libidn11 pigz runc socat ubuntu-fan
  7. ….

这里直接使用Ubantu的docker.io安装源。在上述安装kubeadm的过程中,kubeadm和kubelet、kubectl、kubernetes-cni这几个kubernetes核心组件的二进制文件都会被自动安装好。

4)、Docker服务启动及限制修改

完成上述步骤侧操作后,系统中会自动安装Docker引擎,但是在具体运行kubernetes部署之前需要对Docker的配置信息进行一些调整。

首先,编辑系统/etc/default/grub文件,在配置项GRUB_CMDLINE_LINUX中添加如下参数:

  1. GRUB_CMDLINE_LINUX=” cgroup_enable=memory swapaccount=1″

完成编辑后保存执行如下命令,并重启服务器,命令如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# update-grub
  2. root@kubernetesnode01:/opt/kubernetes-config# reboot

上述修改主要解决的是可能出现的“docker警告WARNING: No swap limit support”问题。

其次,编辑创建/etc/docker/daemon.json文件,添加如下内容:

  1. {
  2.   “exec-opts”: [“native.cgroupdriver=systemd”]
  3. }

完成保存后执行重启Docker命令,如下:

root@kubernetesnode01:/opt/kubernetes-config# systemctl restart docker

此时可以查看Docker的Cgroup信息,如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# docker info | grep Cgroup
  2.  Cgroup Driver: systemd

上述修改主要解决的是“Dockercgroup driver. The recommended driver is “systemd””的问题。需要强调的是以上修改只是作者在具体安装操作是遇到的具体问题的解决整理,如在实践过程中遇到其他问题还需要自行查阅相关资料!

*后,需要注意由于kubernetes禁用虚拟内存,所以要先关闭掉swap否则就会在kubeadm初始化kubernetes的时候报错,具体如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# swapoff -a

该命令只是临时禁用swap,如要保证系统重启后仍然生效则需要“edit /etc/fstab”文件,并注释掉swap那一行。

完成以上操作后启动系统Docker服务,命令如下:

root@kubenetesnode02:~# systemctl enable docker.service

%title插图%num

部署Kubernetes的Master节点

在Kubernetes中Master节点是集群的控制节点,它是由三个紧密协作的独立组件组合而成,分别是负责API服务的kube-apiserver、负责调度的kube-scheduler以及负责容器编排的kube-controller-manager,其中整个集群的持久化数据由kube-apiserver处理后保存在Etcd中。

要部署Master节点可以直接通过kubeadm进行一键部署,但这里我们希望能够部署一个相对完整的Kubernetes集群,可以通过配置文件来开启一些实验性的功能。具体在系统中新建/opt/kubernetes-config/目录,并创建一个给kubeadm用的YAML文件(kubeadm.yaml),具体内容如下:

  1. apiVersion: kubeadm.k8s.io/v1beta2
  2. kind: ClusterConfiguration
  3. controllerManager:
  4.  extraArgs:
  5.      horizontal-pod-autoscaler-userestclients: “true
  6.      horizontalpodautoscalersyncperiod: “10s
  7.      nodemonitorgraceperiod: “10s
  8. apiServer:
  9.   extraArgs:
  10.      runtimeconfig: “api/all=true
  11. kubernetesVersion: “v1.18.1″

在上述yaml配置文件中“horizontal-pod-autoscaler-use-rest-clients: “true””这个配置,表示将来部署的kuber-controller-manager能够使用自定义资源(CustomMetrics)进行自动水平扩展,感兴趣的读者可以自行查阅相关资料!而“v1.18.1”就是要kubeadm帮我们部署的Kubernetes版本号。

需要注意的是,如果执行过程中由于国内网络限制问题导致无法下载相应的Docker镜像,可以根据报错信息在国内网站(如阿里云)上找到相关镜像,然后再将这些镜像重新tag之后再进行安装。具体如下:

  1. #从阿里云Docker仓库拉取Kubernetes组件镜像
  2. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver-amd64:v1.18.1
  3. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager-amd64:v1.18.1
  4. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler-amd64:v1.18.1
  5. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64:v1.18.1
  6. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64:3.4.3-0
  7. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2
  8. docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.6.7

下载完成后再将这些Docker镜像重新tag下,具体命令如下:

  1. #重新tag镜像
  2. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2
  3. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.6.7 k8s.gcr.io/coredns:1.6.7
  4. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64:3.4.3-0 k8s.gcr.io/etcd:3.4.3-0
  5. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler-amd64:v1.18.1 k8s.gcr.io/kube-scheduler:v1.18.1
  6. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager-amd64:v1.18.1 k8s.gcr.io/kube-controller-manager:v1.18.1
  7. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver-amd64:v1.18.1 k8s.gcr.io/kube-apiserver:v1.18.1
  8. docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64:v1.18.1 k8s.gcr.io/kube-proxy:v1.18.1

此时通过Docker命令就可以查看到这些Docker镜像信息了,命令如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# docker images
  2. REPOSITORY                                                                          TAG                 IMAGE ID            CREATED             SIZE
  3. k8s.gcr.io/kube-proxy                                                               v1.18.1             4e68534e24f6        2 months ago        117MB
  4. registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64                v1.18.1             4e68534e24f6        2 months ago        117MB
  5. k8s.gcr.io/kube-controller-manager                                                  v1.18.1             d1ccdd18e6ed        2 months ago        162MB
  6. registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager-amd64   v1.18.1             d1ccdd18e6ed        2 months ago        162MB
  7. k8s.gcr.io/kube-apiserver                                                           v1.18.1             a595af0107f9        2 months ago        173MB
  8. registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver-amd64            v1.18.1             a595af0107f9        2 months ago        173MB
  9. k8s.gcr.io/kube-scheduler                                                           v1.18.1             6c9320041a7b        2 months ago        95.3MB
  10. registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler-amd64            v1.18.1             6c9320041a7b        2 months ago        95.3MB
  11. k8s.gcr.io/pause                                                                    3.2                 80d28bedfe5d        4 months ago        683kB
  12. registry.cn-hangzhou.aliyuncs.com/google_containers/pause                           3.2                 80d28bedfe5d        4 months ago        683kB
  13. k8s.gcr.io/coredns                                                                  1.6.7               67da37a9a360        4 months ago        43.8MB
  14. registry.cn-hangzhou.aliyuncs.com/google_containers/coredns                         1.6.7               67da37a9a360        4 months ago        43.8MB
  15. k8s.gcr.io/etcd                                                                     3.4.3-0             303ce5db0e90        8 months ago        288MB
  16. registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64                      3.4.3-0             303ce5db0e90        8 months ago        288MB

解决镜像拉取问题后再次执行kubeadm部署命令就可以完成Kubernetes Master控制节点的部署了,具体命令及执行结果如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubeadm init –config kubeadm.yaml –v=5
  2. Your Kubernetes control-plane has initialized successfully!
  3. To start using your cluster, you need to run the following as a regular user:
  4.   mkdir -p $HOME/.kube
  5.   sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  6.   sudo chown $(id -u):$(id -g) $HOME/.kube/config
  7. You should now deploy a pod network to the cluster.
  8. Run “kubectl apply -f [podnetwork].yaml” with one of the options listed at:
  9.   https://kubernetes.io/docs/concepts/cluster-administration/addons/
  10. Then you can join any number of worker nodes by running the following on each as root:
  11. kubeadm join 10.211.55.6:6443 –token jfulwi.so2rj5lukgsej2o6 \
  12.     –discovery-token-ca-cert-hash sha256:d895d512f0df6cb7f010204193a9b240e8a394606090608daee11b988fc7fea6

从上面部署执行结果中可以看到,部署成功后kubeadm会生成如下指令:

  1. kubeadm join 10.211.55.6:6443 –token d35pz0.f50zacvbdarqn2vi \
  2.     –discovery-token-ca-cert-hash sha256:58958a3bf4ccf4a4c19b0d1e934e77bf5b5561988c2274364aaadc9b1747141d

这个kubeadm join命令就是用来给该Master节点添加更多Worker(工作节点)的命令,后面具体部署Worker节点的时候将会使用到它。此外,kubeadm还会提示我们*次使用Kubernetes集群所需要配置的命令:

  1. mkdir -p $HOME/.kube
  2. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  3. sudo chown $(id -u):$(id -g) $HOME/.kube/config

而需要这些配置命令的原因在于Kubernetes集群默认是需要加密方式访问的,所以这几条命令就是将刚才部署生成的Kubernetes集群的安全配置文件保存到当前用户的.kube目录,之后kubectl会默认使用该目录下的授权信息访问Kubernetes集群。如果不这么做的化,那么每次通过集群就都需要设置“export KUBE CONFIG 环境变量”来告诉kubectl这个安全文件的位置。

执行完上述命令后,现在我们就可以使用kubectlget命令来查看当前Kubernetes集群节点的状态了,执行效果如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubectl get nodes
  2. NAME               STATUS     ROLES    AGE   VERSION
  3. kubernetesnode01   NotReady   master   35m   v1.18.4

在以上命令输出的结果中可以看到Master节点的状态为“NotReady”,为了查找具体原因可以通过“kuberctl describe”命令来查看下该节点(Node)对象的详细信息,命令如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubectl describe node kubernetesnode01

该命令可以非常详细地获取节点对象的状态、事件等详情,这种方式也是调试Kubernetes集群时*重要的排查手段。根据显示的如下信息:

  1. Conditions
  2. Ready False… KubeletNotReady runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

可以看到节点处于“NodeNotReady”的原因在于尚未部署任何网络插件,为了进一步验证着一点还可以通过kubectl检查这个节点上各个Kubernetes系统Pod的状态,命令及执行效果如下:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubectl get pods -n kube-system
  2. NAME                                       READY   STATUS    RESTARTS   AGE
  3. coredns-66bff467f8-l4wt6                   0/1     Pending   0          64m
  4. coredns-66bff467f8-rcqx6                   0/1     Pending   0          64m
  5. etcd-kubernetesnode01                      1/1     Running   0          64m
  6. kube-apiserver-kubernetesnode01            1/1     Running   0          64m
  7. kube-controller-manager-kubernetesnode01   1/1     Running   0          64m
  8. kube-proxy-wjct7                           1/1     Running   0          64m
  9. kube-scheduler-kubernetesnode01            1/1     Running   0          64m

命令中“kube-system”表示的是Kubernetes项目预留的系统Pod空间(Namespace),需要注意它并不是Linux Namespace,而是Kuebernetes划分的不同工作空间单位。回到命令输出结果,可以看到coredns等依赖于网络的Pod都处于Pending(调度失败)的状态,这样说明了该Master节点的网络尚未部署就绪。

%title插图%num

部署Kubernetes网络插件

前面部署Master节点中由于没有部署网络插件,所以节点状态显示“NodeNotReady”状态。接下来的内容我们就来具体部署下网络插件。在Kubernetes“一切皆容器”的设计理念指导下,网络插件也会以独立Pod的方式运行在系统中,所以部署起来也很简单只需要执行“kubectl apply”指令即可,例如以Weave网络插件为例:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d ‘\n’)
  2. serviceaccount/weave-net created
  3. clusterrole.rbac.authorization.k8s.io/weave-net created
  4. clusterrolebinding.rbac.authorization.k8s.io/weave-net created
  5. role.rbac.authorization.k8s.io/weave-net created
  6. rolebinding.rbac.authorization.k8s.io/weave-net created
  7. daemonset.apps/weave-net created

部署完成后通过“kubectl get”命令重新检查Pod的状态:

  1. root@kubernetesnode01:/opt/kubernetes-config# kubectl get pods -n kube-system
  2. NAME                                       READY   STATUS    RESTARTS   AGE
  3. coredns-66bff467f8-l4wt6                   1/1     Running   0          116m
  4. coredns-66bff467f8-rcqx6                   1/1     Running   0          116m
  5. etcd-kubernetesnode01                      1/1     Running   0          116m
  6. kube-apiserver-kubernetesnode01            1/1     Running   0          116m
  7. kube-controller-manager-kubernetesnode01   1/1     Running   0          116m
  8. kube-proxy-wjct7                           1/1     Running   0          116m
  9. kube-scheduler-kubernetesnode01            1/1     Running   0          116m
  10. weave-net-746qj

可以看到,此时所有的系统Pod都成功启动了,而刚才部署的Weave网络插件则在kube-system下面新建了一个名叫“weave-net-746qj”的Pod,而这个Pod就是容器网络插件在每个节点上的控制组件。

到这里,Kubernetes的Master节点就部署完成了,如果你只需要一个单节点的Kubernetes,那么现在就可以使用了。但是在默认情况下,Kubernetes的Master节点是不能运行用户Pod的,需要通过额外的操作进行调整,感兴趣的朋友可以自己查阅下其他资料。

%title插图%num

部署Kubernetes的Worker节点

为了构建一个完整的Kubernetes集群,这里还需要继续介绍如何部署Worker节点。实际上Kubernetes的Worker节点和Master节点几乎是相同的,它们都运行着一个kubelet组件,主要的区别在于“kubeadm init”的过程中,kubelet启动后,Master节点还会自动启动kube-apiserver、kube-scheduler及kube-controller-manager这三个系统Pod。

在具体部署之前与Master节点一样,也需要在所有Worker节点上执行前面“安装kubeadm及Decker环境”小节中的所有步骤。之后在Worker节点执行部署Master节点时生成的“kubeadm join”指令即可,具体如下:

  1. root@kubenetesnode02:~# kubeadm join 10.211.55.6:6443 –token jfulwi.so2rj5lukgsej2o6     –discovery-token-ca-cert-hash sha256:d895d512f0df6cb7f010204193a9b240e8a394606090608daee11b988fc7fea6 –v=5
  2. This node has joined the cluster:
  3. * Certificate signing request was sent to apiserver and a response was received.
  4. * The Kubelet was informed of the new secure connection details.
  5. Run ‘kubectl get nodes’ on the control-plane to see this node join the cluster.

完成集群加入后为了便于在Worker节点执行kubectl相关命令,需要进行如下配置:

  1. #创建配置目录
  2. root@kubenetesnode02:~# mkdir -p $HOME/.kube
  3. #将Master节点中$/HOME/.kube/目录中的config文件拷贝至Worker节点对应目录
  4. root@kubenetesnode02:~# scp root@10.211.55.6:$HOME/.kube/config $HOME/.kube/
  5. #权限配置
  6. root@kubenetesnode02:~# sudo chown $(id -u):$(id -g) $HOME/.kube/config

之后可以在Worker或Master节点执行节点状态查看命令“kubectl get nodes”,具体如下:

  1. root@kubernetesnode02:~# kubectl get nodes
  2. NAME               STATUS     ROLES    AGE   VERSION
  3. kubenetesnode02    NotReady   <none>   33m   v1.18.4
  4. kubernetesnode01   Ready      master   29h   v1.18.4

通过节点状态显示此时Work节点还处于NotReady状态,具体查看节点描述信息如下:

  1. root@kubernetesnode02:~# kubectl describe node kubenetesnode02
  2. Conditions:
  3. Ready False … KubeletNotReady runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

根据描述信息,发现Worker节点NotReady的原因也在于网络插件没有部署,继续执行“部署Kubernetes网络插件”小节中的步骤即可。但是要注意部署网络插件时会同时部署kube-proxy,其中会涉及从k8s.gcr.io仓库获取镜像的动作,如果无法访问外网可能会导致网络部署异常,这里可以参考前面安装Master节点时的做法,通过国内镜像仓库下载后通过tag的方式进行标记,具体如下:

  1. root@kubenetesnode02:~# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64:v1.18.1
  2. root@kubenetesnode02:~# docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64:v1.18.1 k8s.gcr.io/kube-proxy:v1.18.1

如若一切正常,则继续查看节点状态,命令如下:

  1. root@kubenetesnode02:~# kubectl get node
  2. NAME               STATUS   ROLES    AGE     VERSION
  3. kubenetesnode02    Ready    <none>   7h52m   v1.18.4
  4. kubernetesnode01   Ready    master   37h     v1.18.4

可以看到此时Worker节点的状态已经变成“Ready”,不过细心的读者可能会发现Worker节点的ROLES并不像Master节点那样显示“master”而是显示了<none>,这是因为新安装的Kubernetes环境Node节点有时候会丢失ROLES信息,遇到这种情况可以手工进行添加,具体命令如下:

  1. root@kubenetesnode02:~# kubectl label node kubenetesnode02 node-role.kubernetes.io/worker=worker

再次运行节点状态命令就能看到正常的显示了,命令效果如下:

  1. root@kubenetesnode02:~# kubectl get node
  2. NAME               STATUS   ROLES    AGE   VERSION
  3. kubenetesnode02    Ready    worker   8h    v1.18.4
  4. kubernetesnode01   Ready    master   37h   v1.18.4

到这里就部署完成了具有一个Master节点和一个Worker节点的Kubernetes集群了,作为实验环境它已经具备了基本的Kubernetes集群功能。

%title插图%num

部署Dashboard可视化插件

在Kubernetes社区中,有一个很受欢迎的Dashboard项目,它可以给用户一个可视化的Web界面来查看当前集群中的各种信息。该插件也是以容器化方式进行部署,操作也非常简单,具体可在Master、Worker节点或其他能够安全访问Kubernetes集群的Node上进行部署,命令如下:

  1. root@kubenetesnode02:~# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml

部署完成后就可以查看Dashboard对应的Pod运行状态,执行效果如下:

  1. root@kubenetesnode02:~# kubectl get pods -n kubernetes-dashboard
  2. NAME                                         READY   STATUS    RESTARTS   AGE
  3. dashboard-metrics-scraper-6b4884c9d5-xfb8b   1/1     Running   0          12h
  4. kubernetes-dashboard-7f99b75bf4-9lxk8        1/1     Running   0          12h

除此之外还可以查看Dashboard的服务(Service)信息,命令如下:

  1. root@kubenetesnode02:~# kubectl get svc -n kubernetes-dashboard
  2. NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
  3. dashboard-metrics-scraper   ClusterIP   10.97.69.158    <none>        8000/TCP   13h
  4. kubernetes-dashboard        ClusterIP   10.111.30.214   <none>        443/TCP    13h

需要注意的是,由于Dashboard是一个Web服务,从安全角度出发Dashboard默认只能通过Proxy的方式在本地访问。具体方式为在本地机器安装kubectl管理工具,并将Master节点$HOME/.kube/目录中的config文件拷贝至本地主机相同目录,之后运行“kubectl proxy”命令,如下:

  1. qiaodeMacBook-Pro-2:.kube qiaojiang$ kubectl proxy
  2. Starting to serve on 127.0.0.1:8001

本地proxy代理启动后,访问Kubernetes Dashboard地址,具体如下:

  1. http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

如果访问正常,就会看到相应的界面。

Kubernetes 也有局限性吗?

2014 年发布的 Kubernetes 在今天俨然已成为容器编排领域的事实标准,相信谈到 Kubernetes 的开发者都会一再复述上述现象。如下图所示,今天的大多数个人或者团队都会选择 Kubernetes 管理容器,而也有 75% 的人会在生产环境中使用 Kubernetes。

%title插图%num图 1 – Kubernetes 容器编排[^1]

在这种全民学习和使用 Kubernetes 的大背景下,我们也应该非常清晰地知道 Kubernetes 有哪些局限性。虽然 Kubernetes 能够解决容器编排领域的大多数问题,但是仍然有一些场景是它很难处理、甚至无法处理的,只有对这些潜在的风险有清晰的认识,才能更好地驾驭这项技术,这篇文章将从集群管理和应用场景两个部分谈谈 Kubernetes 社区目前的发展和一些局限性。

%title插图%num

集群管理

集群是一组能够在一起协同工作的计算机,我们可以将集群中的所有计算机看成一个整体,所有资源调度系统都是以集群为维度进行管理的,集群中的所有机器构成了资源池,这个巨大的资源池会为待运行的容器提供资源执行计算任务,这里简单谈一谈 Kubernetes 集群管理面对的几个复杂问题。

%title插图%num

水平扩展性

集群大小是我们在评估资源管理系统时需要关注的重要指标之一,然而 Kubernetes 能够管理的集群规模远远小于业界的其他资源管理系统。集群大小为什么重要呢,我们先来看另一个同样重要的指标 — 资源利用率,很多工程师可能没有在公有云平台上申请过资源,这些资源都相当昂贵,在 AWS 上申请一个与主机差不多配置的虚拟机实例(8 CPU、16 GB)每个月大概需要 150 美金,约为 1000 人民币[^2]。

%title插图%num

图 2 – AWS EC2 价格

大多数的集群都会使用 48 CPU 或者 64 CPU 的物理机或者虚拟机作为集群中的节点,如果我们的集群中需要包含 5,000 个节点,那么这些节点每个月大概要 8,000,000 美元,约为 50,000,000 人民币,在这样的集群中提升 1% 的资源利用率就相当于每个月节省了 500,000 的成本。

多数在线任务的资源利用率都很低,更大的集群意味着能够运行更多的工作负载,而多种高峰和低谷期不同的负载部署在一起可以实现超售,这样能够显著地提高集群的资源利用率,如果单个集群的节点数足够多,我们在部署不同类型的任务时会有更合理的组合,可以完美错开不同服务的高峰期。

Kubernetes 社区对外宣传的是单个集群*多支持 5,000 节点,Pod 总数不超过 150,000,容器总数不超过 300,000 以及单节点 Pod 数量不超过 100 个[^3],与几万节点的 Apache Mesos 集群、50,000 节点的微软 YARN 集群[^4]相比,Kubernetes 的集群规模整整差了一个数量级。虽然阿里云的工程师也通过优化 Kubernetes 的各个组件实现了 5 位数的集群规模,但是与其他的资源管理方式相比却有比较大的差距[^5]。

%title插图%num

图 3 – Apache Mesos 与 Hadoop YARN

需要注意的是 Kubernetes 社区虽然对外宣称单集群可以支持 5,000 节点,同时社区也有各种各样的集成测试保证每个改动都不会影响它的伸缩性[^6],但是 Kubernetes 真的非常复杂,我们没有办法保证你使用的每个功能在扩容的过程中都不出问题。而在生产环境中,我们甚至可能在集群扩容到 1000 ~ 1500 节点时遇到瓶颈。

每个稍具规模的大公司都想要实现更大规模的 Kubernetes 集群,但是这不是一个改几行代码就能解决的简单问题,它可能需要我们限制 Kubernetes 中一些功能的使用,在扩容的过程中,etcd、API 服务器、调度器以及控制器都有可能出现问题。社区中已经有一些开发者注意到了其中的一些问题,例如在节点上增加缓存降低 API 服务器的负载[^7],但是要推动类似的改变还是很困难的,有志之士可以尝试在社区推动类似的项目。

%title插图%num

多集群管理

单个集群的容量再大也无法解决企业面对的问题,哪怕有一天 Kubernetes 集群可以达到 50,000 节点的规模,我们仍然需要管理多个集群,多集群管理也是 Kubernetes 社区目前正在探索的方向,社区中的多集群兴趣小组(SIG Multi-Cluster)目前就在完成相关的工作[^8]。在作者看来,Kubernetes 的多集群会带来资源不平衡、跨集群访问困难以及提高运维和管理成本三大问题,我们在这里谈一谈目前在开源社区和业界几种可供参考和选择的解决方案。

%title插图%num

kubefed

首先要介绍的是 kubefed,该项目是 Kubernetes 社区给出的解决方案,它同时提供了跨集群的资源和网络管理的功能,社区的多集群兴趣小组(SIG Multi-Cluster)负责了该项目的开发工作:

%title插图%num

图 4 – Kubernetes 联邦

kubefed 通过一个中心化的联邦控制面板管理多集群中的元数据,上层的控制面板会为管理器群中的资源创建对应的联邦对象,例如:FederatedDeployment:

  1. kind: FederatedDeployment
  2. spec:
  3.   …
  4.   overrides:
  5.   # Apply overrides to cluster1
  6.     – clusterName: cluster1
  7.       clusterOverrides:
  8.         # Set the replicas field to 5
  9.         – path: “/spec/replicas”
  10.           value: 5
  11.         # Set the image of the first container
  12.         – path: “/spec/template/spec/containers/0/image”
  13.           value: “nginx:1.17.0-alpine”
  14.         # Ensure the annotation “foo: bar” exists
  15.         – path: “/metadata/annotations”
  16.           op: “add”
  17.           value:
  18.             foo: bar
  19.         # Ensure an annotation with key “foo” does not exist
  20.         – path: “/metadata/annotations/foo”
  21.           op: “remove”
  22.         # Adds an argument `-q` at index 0 of the args list
  23.         # this will obviously shift the existing arguments, if any
  24.         – path: “/spec/template/spec/containers/0/args/0”
  25.           op: “add”
  26.           value: “-q”

上层的控制面板会根据联邦对象 FederatedDeployment 的规格文件生成对应的 Deployment 并推送到下层的集群,下层集群可以正常根据 Deployment 中的定义创建特定数量的副本。

%title插图%num

图 5 – 从联邦对象到普通对象

FederatedDeployment 只是一种*简单的分发策略,在生产环境中我们希望通过联邦的集群实现容灾等复杂功能,这时可以利用 ReplicaSchedulingPreference 在不同集群中实现更加智能的分发策略:

  1. apiVersion: scheduling.kubefed.io/v1alpha1
  2. kind: ReplicaSchedulingPreference
  3. metadata:
  4.   name: test-deployment
  5.   namespacetestns
  6. spec:
  7.   targetKindFederatedDeployment
  8.   totalReplicas: 9
  9.   clusters:
  10.     A:
  11.       minReplicas: 4
  12.       maxReplicas: 6
  13.       weight: 1
  14.     B:
  15.       minReplicas: 4
  16.       maxReplicas: 8
  17.       weight: 2

上述调度的策略可以实现工作负载在不同集群之间的权重,在集群资源不足甚至出现问题时将实例迁移到其他集群,这样既能够提高服务部署的灵活性和可用性,基础架构工程师也可以更好地平衡多个集群的负载。

我们可以认为 kubefed 的主要作用是将多个松散的集群组成强耦合的联邦集群,并提供更加高级的网络和部署功能,这样我们可以更容易地解决集群之间资源不平衡和连通性的一些问题,然而该项目的关注点不包含集群生命周期的管理。

%title插图%num

集群接口

Cluster API 也是 Kubernetes 社区中与多集群管理相关的项目,该项目由集群生命周期小组(SIG Cluster-Lifecycle)负责开发,其主要目标是通过声明式的 API 简化多集群的准备、更新和运维工作,你在该项目的 设计提案 中能够找到它的职责范围[^9]。

%title插图%num

图 6 – Cluster API 概念

在该项目中*重要的资源就是 Machine,它表示一个 Kubernetes 集群中的节点。当该资源被创建时,特定提供商的控制器会根据机器的定义初始化并将新的节点注册到集群中,在该资源被更新或者删除时,也会执行操作达到用户的状态。

这种策略与阿里的多集群管理的方式有一些相似,它们都使用声明式的 API 定义机器和集群的状态,然后使用 Kubernetes 原生的 Operator 模型在更高一层的集群中管理下层集群,这能够*大降低集群的运维成本并提高集群的运行效率[^10],不过类似的项目都没有考虑跨集群的资源管理和网络管理。

%title插图%num

应用场景

我们在这一节将谈谈 Kubernetes 中一些有趣的应用场景,其中包括应用分发方式的现状、批处理调度任务以及硬多租户在集群中的支持,这些是社区中比较关注的问题,也是 Kubernetes 目前的盲点。

应用分发

Kubernetes 主项目提供了几种部署应用的*基本方式,分别是 Deployment、StatefulSet 和 DaemonSet,这些资源分别适用于无状态服务、有状态服务和节点上的守护进程,这些资源能够提供*基本的策略,但是它们无法处理更加复杂的应用。

%title插图%num

图 7 – Kubernetes 应用管理

随着 CRD 的引入,目前社区的应用管理小组(SIG Apps)基本不会向 Kubernetes 主仓库引入较大的改动,大多数的改动都是在现有资源上进行的修补,很多常见的场景,例如只运行一次的 DaemonSet[^11] 以及金丝雀和蓝绿部署等功能,现在的资源也存在很多问题,例如 StatefulSet 在初始化容器中卡住无法回滚和更新[^12]。

我们可以理解社区不想在 Kubernetes 中维护更多的基本资源,通过几个基本的资源可以覆盖 90% 的场景,剩下的各种复杂场景可以让其他社区通过 CRD 的方式实现。不过作者认为如果社区能够在上游实现更多高质量的组件,这对于整个生态都是很有价值并且很重要的工作,需要注意的是假如各位读者想要在 Kubernetes 项目中成为贡献者,SIG Apps 可能不是一个很好的选择。

批处理调度

机器学习、批处理任务和流式任务等工作负载的运行从 Kubernetes 诞生*天起到今天都不是它的强项,大多数的公司都会使用 Kubernetes 运行在线服务处理用户请求,用 Yarn 管理的集群运行批处理的负载。

%title插图%num

hadoop-yarn

图 8 – Hadoop Yarn

在线任务和离线任务往往是两种截然不同的作业,大多数的在线任务都是无状态的服务,它们可以在不同机器上进行迁移,彼此很难有*强的依赖关系;但是很多离线任务的拓扑结构都很复杂,有些任务需要多个作业一同执行,而有些任务需要按照依赖关系先后执行,这种复杂的调度场景在 Kubernetes 中比较难以处理。

在 Kubernetes 调度器引入调度框架之前,所有的 Pod 在调度器看来是没有任何关联的,不过有了调度框架,我们可以在调度系统中实现更加复杂的调度策略,例如保证一组 Pod 同时调度的 PodGroup[^13],这对于 Spark 和 TensorFlow 任务非常有用。

  1. # PodGroup CRD spec
  2. apiVersion: scheduling.sigs.k8s.io/v1alpha1
  3. kind: PodGroup
  4. metadata:
  5.   name: nginx
  6. spec:
  7.   scheduleTimeoutSeconds: 10
  8.   minMember: 3
  9. # Add a label `pod-group.scheduling.sigs.k8s.io` to mark the pod belongs to a group
  10. labels:
  11.   pod-group.scheduling.sigs.k8s.io: nginx

Volcano 也是在 Kubernetes 上构建的批处理任务管理系统[^14],它能够处理机器学习、深度学习以及其他大数据应用,可以支持包括 TensorFlow、Spark、PyTorch 和 MPI 在内的多个框架。

%title插图%num

图 9 – Volcano

虽然 Kubernetes 能够运行一些批处理任务,但是距离在这个领域上取代 Yarn 等老牌资源管理系统上还有非常大的差距,相信在较长的一段时间内,大多数公司都会同时维护 Kubernetes 和 Yarn 两种技术栈,分别管理和运行不同类型的工作负载。

硬多租户

多租户是指同一个软件实例可以为不同的用户组提供服务,Kubernetes 的多租户是指多个用户或者用户组使用同一个 Kubernetes 集群,今天的 Kubernetes 还很难做到硬多租户支持,也就是同一个集群的多个租户不会相互影响,也感知不到彼此的存在。

硬多租户在 Kubernetes 中是一个很重要、也很困难的课题,合租公寓就是一个典型的多租户场景,多个租客共享房屋内的基础设施,硬多租户要求多个访客之间不会相互影响,你可以想象这有多么困难,Kubernetes 社区甚至有一个工作小组专门讨论和研究相关的问题[^15],然而虽然感兴趣的工程师很多,但是成果却非常有限。

%title插图%num

图 10 – 多租户

尽管 Kubernetes 使用命名空间来划分虚拟机群,然而这也很难实现真正的多租户。多租户的支持到底有哪些作用呢,这里简单列几个多租户带来的好处:

  • Kubernetes 带来的额外部署成本对于小集群来说非常高昂,稳定的 Kubernetes 集群一般都需要至少三个运行 etcd 的主节点,如果大多数的集群都是小集群,这些额外的机器会带来很高的额外开销;
  • Kubernetes 中运行的容器可能需要共享物理机和虚拟机,一些开发者可能在公司内部遇到过自己的服务被其他业务影响,因为主机上容器可能隔离了 CPU 和内存资源,但是没有隔离 I/O、网络 和 CPU 缓存等资源,这些资源的隔离是相对困难的;

如果 Kubernetes 能够实现硬多租户,这不仅对云服务商和小集群的使用者来说都是个福音,它还能够隔离不同容器之间的影响并防止潜在安全问题的发生,不过这在现阶段还是比较难实现的。

%title插图%num

总结

每个技术都有自己的生命周期,越底层的技术生命周期会越长,而越上层的技术生命周期也就越短,虽然 Kubernetes 是当今容器界的扛把子,但是未来的事情没有人可以说的准。我们要时刻清楚手中工具的优点和缺点,花一些时间学习 Kubernetes 中设计的精髓,不过如果在未来的某一天 Kubernetes 也成为了过去,我们也应该感到喜悦,因为会有更好的工具取代它。

[^1]: Kubernetes and Container Security and Adoption Trends https://www.stackrox.com/kubernetes-adoption-security-and-market-share-for-containers/

[^2]: AWS Pricing Calculator https://calculator.aws/#/createCalculator/EC2

[^3]: Considerations for large clusters https://kubernetes.io/docs/setup/best-practices/cluster-large/

[^4]: How Microsoft drives exabyte analytics on the world’s largest YARN cluster https://azure.microsoft.com/en-us/blog/how-microsoft-drives-exabyte-analytics-on-the-world-s-largest-yarn-cluster/

[^5]: 备战双 11!蚂蚁金服万级规模 K8s 集群管理系统如何设计?https://www.sofastack.tech/blog/ant-financial-managing-large-scale-kubernetes-clusters/

[^6]: sig-scalability-kubemark dashboard https://testgrid.k8s.io/sig-scalability-kubemark#kubemark-5000

[^7]: Node-local API cache #84248 https://github.com/kubernetes/kubernetes/issues/84248

[^8]: Multicluster Special Interest Group https://github.com/kubernetes/community/tree/master/sig-multicluster

[^9]: Cluster API Scope and Objectives https://github.com/kubernetes-sigs/cluster-api/blob/master/docs/scope-and-objectives.md

[^10]: Demystifying Kubernetes as a service – How Alibaba cloud manages 10,000s of Kubernetes clusters https://www.cncf.io/blog/2019/12/12/demystifying-kubernetes-as-a-service-how-does-alibaba-cloud-manage-10000s-of-kubernetes-clusters/

[^11]: Run job on each node once to help with setup #64623 https://github.com/kubernetes/kubernetes/issues/64623

[^12]: StatefulSet does not upgrade to a newer version of manifests #78007 https://github.com/kubernetes/kubernetes/issues/78007

[^13]: Coscheduling based on PodGroup CRD https://github.com/kubernetes-sigs/scheduler-plugins/tree/master/kep/42-podgroup-coscheduling

[^14]: Volcano · A Kubernetes Native Batch System https://github.com/volcano-sh/volcano

[^15]: Kubernetes Working Group for Multi-Tenancy https://github.com/kubernetes-sigs/multi-tenancy

云计算开发技术有哪些 Kubernetes是怎么回事

云计算开发技术有哪些?Kubernetes是怎么回事?提及云计算,*大多数人的反应是这样的:它是一门新兴技术,是互联网发展的未来趋势,云计算核心技术比较多,学习不易。不过如果你真的想要学好云计算,也是有其规律可循的,从基础到进阶、由简单到复杂,不断的学习加练习,你就可以学好它。接下来就给大家简单讲解一下Kubernetes。

%title插图%num

Kubernetes,简称K8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署、规划、更新、维护的一种机制。

Kubernetes不仅仅支持Docker,还支持Rocket,这是另一种容器技术。

使用Kubernetes可以:自动化容器的部署和复制;随时扩展或收缩容器规模;将容器组织成组,并且提供容器间的负载均衡;很容易地升级应用程序容器的新版本;提供容器弹性,如果容器失效就替换它等等。

Kubernetes核心概念知识介绍

Pod-容器组

Pod是Kubernetes的基本操作单元,指定多个有关联容器(有调用关系依赖)构成一个Pod。Pod包含的容器运行在同一个Minion上(Worker Node),Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统。

Deployment-部署

Deployment是*近几个版本才有的,部署表示用户对K8s集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以创建、更新一个新的服务,或者滚动升级一个服务。

Job-任务

Job是K8s用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出,成功完成的标志根据不同的spec.completions策略而不同。

DaemonSet-后台支撑服务集

长期伺服型和批处理型服务的核心在业务应用,后台支持服务的核心关注点是K8s集群中的节点(物理机或虚拟机),节点可能是所有集群节点也可能是通过nodeSelector选定的一些特定节点。典型的后台支持型服务包括、存储、日志和监控每个节点上支持K8s集群运行的服务。

PetSet-有状态服务集

K8s在1.3版本里发布了Alpha版的PetSet功能,RC和RS主要是控制提供无状态服务,其所控制的Pod的名字是随机设置的。PetSet中Pod的名字作用用于关联与该Pod对应的状态。

Replication Controller-复制控制器

RC是K8s集群中*早的保证Pod高可用的API对象,通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。通过RC运行Pod比直接运行Pod更明智,RC会保证Pod的数量。

Replica Set-副本集

RS是新一代的RC,提供同样的高可用能力,RS 能支持更多种类的匹配模式。副本集一般不单独使用,而是作为Deployment的状态参数使用。

Service-服务

RC、RS和Deployment只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务,稳定地提供服务需要服务发现和负载均衡能力。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速