Kubernetes IN Docker - local clusters for testing Kubernetes

栏目: 编程工具 · 发布时间: 5年前

内容简介:Kubernetes IN Docker - local clusters for testing KubernetesKind 可以做什么?

Intro to Kind

Kubernetes IN Docker - local clusters for testing Kubernetes

Brief

Kind(Kubernetes IN Docker) 是一个用来快速创建和测试Kubernetes的工具,Kind把环境的依赖降低到了最小,仅需要机器安装了 Docker 即可。

Kind 可以做什么?

  • 快速创建一个或多个 Kubernetes 集群(几分钟)
  • 支持 ha master 部署高可用的 Kubernetes 集群
  • 支持从源码构建并部署一个 Kubernetes 集群
  • 可以快速低成本体验一个最新的 Kubernetes 集群,并支持 Kubernetes 的绝大部分功能
  • 支持本地离线运行一个多节点集群

Kind 有哪些优势?

  • 最小的安装依赖,仅需要安装 Docker 即可
  • 使用快速简单,使用 kind cli 工具即可快速创建集群
  • 使用 container 来 mock kubernetes node
  • 内部使用 kubeadm 的官方主流部署工具
  • 使用了 containerd
  • 通过了 CNCF 官方的 k8s conformance 测试

Usage

GO111MODULE="on" go get sigs.k8s.io/kind@v0.3.0 && kind create cluster

How it work

Kind 使用一个 container 来模拟一个 node,在 container 里面跑了 systemd ,并用 systemd 托管了 kubelet 以及 containerd,然后容器内部的 kubelet 把其他 Kubernetes 组件,比如 kube-apiserver,etcd,cni 等组件跑起来。 如果你想和更多Kubernetes技术专家交流,可以加我微信liyingjiese,备注『加群』。群里每周都有全球各大公司的最佳实践以及行业最新动态

可以通过配置文件的方式,来通过创建多个 container 的方式,来模拟创建多个 Node,并以这些 Node 来构建一个多节点的 Kubernetes 集群。

Kind 内部使用了 kubeadm 这个 工具 来做集群的部署,包括 ha master 的高可用集群,也是借助 kubeadm 提供的aplha特性提供的。同时,在 ha master 下,额外部署了一个 nginx 用来提供负载均衡 vip。

Build Images

Kind 的镜像分为两个,一个 Node 镜像,一个 Base 镜像。

Node 镜像

Node 镜像的构建比较复杂,目前是通过运行 Base 镜像,并在 Base 镜像内执行操作,再保存此容器内容为镜像的方式来构建的,包含的操作有:

  • 构建 Kubernetes 相关资源(比如二进制文件和镜像)
  • 运行一个用于构建的容器
  • 把构建的 Kubernetes 相关资源复制到容器里
  • 调整部分组件配置参数,以支持在容器内运行
  • 预先拉去运行环境需要的镜像
  • 通过 docker commit 方式保存当前的构建容器为 node 镜像

具体的逻辑,可以参考 node.go

Base 镜像

Base 镜像目前使用了 ubuntu:19.04 作为基础镜像,做了下面的调整:

  • 安装 systemd 相关的包,并调整一些配置以适应在容器内运行
  • 安装 Kubernetes 运行时的依赖包,比如 conntrack,socat,cni
  • 安装容器运行环境,比如 containerd,crictl
  • 配置自己的 ENTRYPOINT 脚本,以适应和调整容器内运行的问题

具体的逻辑,可以参考构建的 Dockerfile

Create Cluster

Kind 创建集群的基本过程为:

  1. 根据传入的参数,来创建 container,分为 control node 和 worker node 两种(如果是 ha master,还有一个 loadbalancer node)
  2. 如果需要,配置 loadbalancer 的配置,主要是 nginx 配置文件
  3. 生成 kubeadm 配置
  4. 对于第一个控制节点,使用 kubeadm init 初始化单节点集群
  5. 配置安装 cni 插件
  6. 配置存储(实际是安装了一个使用 hostpath 的 storageclass)
  7. 其他的控制节点,通过kubeadm join --experimental-control-plane
    的方式来扩容控制节点
  8. 通过 kubeadm join 扩容其他的工作节点
  9. 等待集群创建完成
  10. 生成访问配置,打印使用帮助具体的创建流程,可以参考代码 create.go

这里关于每个容器,是如何作为 node 跑起来的,可以简单讲解些原理:

根据不同的角色,调用不同的函数创建节点:

[nodes.go](https://github.com/kubernetes-sigs/kind/blob/master/pkg/cluster/internal/create/nodes.go#L196)
// TODO(bentheelder): remove network in favor of []cri.PortMapping when that is in

func (d *nodeSpec) Create(clusterLabel string) (node *nodes.Node, err error) {

// create the node into a container (docker run, but it is paused, see createNode)

// TODO(bentheelder): decouple from config objects further

switch d.Role {

case constants.ExternalLoadBalancerNodeRoleValue:

node, err = nodes.CreateExternalLoadBalancerNode(d.Name, d.Image, clusterLabel, d.APIServerAddress, d.APIServerPort)

case constants.ControlPlaneNodeRoleValue:

node, err = nodes.CreateControlPlaneNode(d.Name, d.Image, clusterLabel, d.APIServerAddress, d.APIServerPort, d.ExtraMounts)

case constants.WorkerNodeRoleValue:

node, err = nodes.CreateWorkerNode(d.Name, d.Image, clusterLabel, d.ExtraMounts)

default:

return nil, errors.Errorf("unknown node role: %s", d.Role)

}

return node, err

} 

节点(容器)创建时,通过配置 --privileged,挂载 tmpfs,修改主机名等,来运行节点 create

func createNode(name, image, clusterLabel, role string, mounts []cri.Mount, extraArgs ...string) (handle *Node, err error) {

runArgs := []string{

"-d", // run the container detached

"-t", // allocate a tty for entrypoint logs

// running containers in a container requires privileged

// NOTE: we could try to replicate this with --cap-add, and use less

// privileges, but this flag also changes some mounts that are necessary

// including some ones docker would otherwise do by default.

// for now this is what we want. in the future we may revisit this.

"--privileged",

"--security-opt", "seccomp=unconfined", // also ignore seccomp

"--tmpfs", "/tmp", // various things depend on working /tmp

"--tmpfs", "/run", // systemd wants a writable /run

// some k8s things want /lib/modules

"-v", "/lib/modules:/lib/modules:ro",

"--hostname", name, // make hostname match container name

"--name", name, // ... and set the container name

// label the node with the cluster ID

"--label", clusterLabel,

// label the node with the role ID

"--label", fmt.Sprintf("%s=%s", constants.NodeRoleKey, role),

}



// pass proxy environment variables to be used by node's docker deamon

proxyDetails := getProxyDetails()

for key, val := range proxyDetails.Envs {

runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", key, val))

}



// adds node specific args

runArgs = append(runArgs, extraArgs...)



if docker.UsernsRemap() {

// We need this argument in order to make this command work

// in systems that have userns-remap enabled on the docker daemon

runArgs = append(runArgs, "--userns=host")

}



err = docker.Run(

image,

docker.WithRunArgs(runArgs...),

docker.WithMounts(mounts),

)



// we should return a handle so the caller can clean it up

handle = FromName(name)

if err != nil {

return handle, errors.Wrap(err, "docker run error")

}



return handle, nil

} 

More

Kind是一个比较简单有趣的项目,Kind的 scope 定的比较明确和具体,也定的比较小,其实借助 Kind 或者 Kind 的思想,可以做更多的事情,比如:

  • 在单节点部署自己的上层平台
  • 借助容器 mock 节点的方式,优化现有的测试方案
  • 自动化的部署测试
  • 自动化的 e2e 测试

原文链接: https://mp.weixin.qq.com/s/Vhr0ml1wI1BIoxKqKGTXRg


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

图解物联网

图解物联网

[ 日] NTT DATA集团、河村雅人、大塚纮史、小林佑辅、小山武士、宫崎智也、石黑佑树、小岛康平 / 丁 灵 / 人民邮电出版社 / 2017-4 / 59.00元

本书图例丰富,从设备、传感器及传输协议等构成IoT的技术要素讲起,逐步深入讲解如何灵活运用IoT。内容包括用于实现IoT的架构、传感器的种类及能从传感器获取的信息等,并介绍了传感设备原型设计必需的Arduino等平台及这些平台的选择方法,连接传感器的电路,传感器的数据分析,乃至IoT跟智能手机/可穿戴设备的联动等。此外,本书以作者们开发的IoT系统为例,讲述了硬件设置、无线通信及网络安全等运用Io......一起来看看 《图解物联网》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具