用kind搭建k8s集群环境

Posted by 梁远鹏 on 2023-03-12 | 阅读 |,阅读约 6 分钟

TOC

前言

由于各类基于 kubernetes 的云原生实验或测试的前提都是需要一个 kubernetes 环境,而在写博客时总是需要提及使用 Kind 来搭建 kubernetes 环境. 因此这里单独写一篇文章来介绍如何用 Kind 来部署 kubernetes,同时提供各种不同 kubernetes 环境的 Kind 配置文件供你使用.

相关文章推荐阅读

值得先说的经验

端口映射

一个很值得注意的踩坑点: Kind 通过 NodePort 暴露端口号时一定要注意有两个地方需要处理:

  • Kind 对应 docker 容器暴露端口号
  • 正常的服务 NodePort 暴露端口号

坑点主要是第一点时常会忘记,导致访问不了.

更多的 Kind 版本

Kind 目前不保证对每一个 kubernetes 版本都构建一个对应的 node 镜像,目前我提供了一些 Kind 官方没有的镜像,例如 beta 版本或 RC 版本的 kubernetes.如: ghcr.io/liangyuanpeng/kindest/node:v1.28.0-rc.0, 不仅仅是已发布的镜像,有时我还会基于 kubernetes master 分支进行构建Kind 的镜像,用于测试某一个功能或 PR,如果你也有需要为一个特定版本打包一个对应的 Kind 镜像,可以在我的博客留言,有时间的话我可以帮忙处理:)

如果你发现你需要的某个版本的镜像 Kind 官方没有提供可以在本博客:用kind搭建k8s集群环境底部添加评论,我会考虑进行打包.

有一些镜像版本 Kind 不会进行构建,但你可能可以在我的镜像列表中找到它: https://github.com/liangyuanpeng/kubernetes/pkgs/container/kindest%2Fnode

使用

基本上,即使你没有使用过 Kind 也不是问题,因为基于 Kind 来搭建 kubernetes 就是一条命令的事,需要使用到 Kind 命令,因此你需要下载 Kind 命令行工具.

官方的 Kind 命令下载地址可以在Kind发布地址找到,而我提供了一个另一个地址来下载 Kind 命令行,在下载 Github 上文件速度慢的时候可以用这个地址:

https://res.cloudinary.com/lyp/raw/upload/v1678598428/lan/kind/kind

版本是 v0.17.0

对应的Github文件下载地址是:

https://github.com/kubernetes-sigs/kind/releases/download/v0.17.0/kind-linux-amd64

上述文件架构是 Linux amd64 的,其他架构文件可以自行在上述提供的 Github 发布地址上找到.

使用默认的节点镜像以及默认的集群测试环境名称:

kind create --config kind.yaml

使用特定节点镜像搭建的测试环境:

kind create --config kind.yaml --image kindest/node:v1.26.0

添加--name参数为你的 Kind kubernetes 集群命名:

kind create --config kind.yaml --image kindest/node:v1.26.0 --name mykind

祝你云原生之旅愉快! :)

各类环境的配置文件

由于 Kind 的配置文件也是区分版本的,因此将这个版本放到文件下载路径中,方便明白配置文件的适用范围.

其中大部分都配置了基于lank8s.cn服务来拉取gcr.ioregistry.lank8s.cn的容器镜像,因此你可以愉快的 Tekton、Knative 等云原生技术,而不需要考虑被墙的镜像的问题了.

相关配置如下:

containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
    endpoint = ["https://gcr.lank8s.cn"]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
    endpoint = ["https://registry.lank8s.cn"]  

注意: 新版本的 Containerd 发生了变更,旧版本的配置将会被淘汰. 新版本的配置需要在 /etc/containerd/certs.d 目录(默认)下为每一个镜像仓库新建一个对应的 hosts.toml 文件来进行镜像仓库的配置. 例如 registry.k8s.io 的镜像配置,需要创建一个这样的文件:/etc/containerd/certs.d/registry.k8s.io/hosts.toml 文件内容如下:

server = "https://registry.k8s.io"

[host."https://registry.lank8s.cn"]
  capabilities = ["pull","resolve"]
[host."https://registry99.lank8s.cn"]
  capabilities = ["pull","resolve"]

其中镜像地址可以配置多个.

具体参考官方文档: https://github.com/containerd/containerd/blob/main/docs/hosts.md#cri

对应到 Kind 上的使用的话则是需要挂载对应的 hosts 文件到对应上游仓库所在目录位置,而 Kind 的配置如下:

apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry]
    config_path = ""  

需要在 containerdConfigPatches 中添加上 config_path 的配置,如果有自定义的位置则修改为自己对应的位置即可.

默认带有 lank8s.cn 服务

https://liangyuanpeng.com/files/kind/v1alpha4/kind.yaml

将event存储到单独的etcd服务

虽然使用 Kind 时只有一个 Etcd,但是不妨碍了解一下这个参数是如何使用的,或者你可以将参数值指向一个外部 Etcd,作为实际效果验证。

kind.yaml

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
  - |-
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
      endpoint = ["https://gcr.lank8s.cn"]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
      endpoint = ["https://registry.lank8s.cn"]    
nodes:
- role: control-plane
  image: kindest/node:v1.26.0
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    apiServer:
      extraArgs:
        etcd-servers-overrides: /events#https://127.0.0.1:2379    

Xline

CNCF sandbox 项目 Xline 是一个基于 Curp 协议的,用于管理元数据的分布式 KV 存储.设计兼容 Etcd API,因此可以用于替代 Etcd.目前项目处于早期阶段,欢迎你在实验环境当中用上 Xline,当你遇到一些 Xline 相关问题时,那么我会恭喜你,获得一次参与 Xline 项目开源贡献的机会了!

下面是一个将 kubernetes 中的 event 资源存储到 Xline 当中,而其他资源依然是存储在默认的 kubeadm 部署的 Etcd 当中.

xline1.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: xline1
  namespace: kube-system
spec:
  containers:
    - name: xline
      image: datenlord/xline:v0.4.1
      imagePullPolicy: IfNotPresent
      env:
      - name: RUST_LOG
        value: debug
      command:
        - /bin/sh
        - -c
        - xline --name node1 --members node1=172.18.0.2:7379,node2=172.18.0.2:8379,node3=172.18.0.2:9379 --data-dir /tmp/xline --storage-engine rocksdb
  hostNetwork: true
status: {}

xline2.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: xline2
  namespace: kube-system
spec:
  containers:
    - name: xline
      image: datenlord/xline:v0.4.1
      imagePullPolicy: IfNotPresent
      env:
      - name: RUST_LOG
        value: debug
      command:
        - /bin/sh
        - -c
        - xline --name node2 --members node1=172.18.0.2:7379,node2=172.18.0.2:8379,node3=172.18.0.2:9379 --data-dir /tmp/xline --storage-engine rocksdb
  hostNetwork: true
status: {}

xline3.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: xline3
  namespace: kube-system
spec:
  containers:
    - name: xline
      image: datenlord/xline:v0.4.1
      imagePullPolicy: IfNotPresent
      env:
      - name: RUST_LOG
        value: debug
      command:
        - /bin/sh
        - -c
        - xline --name node3 --members node1=172.18.0.2:7379,node2=172.18.0.2:8379,node3=172.18.0.2:9379 --data-dir /tmp/xline --storage-engine rocksdb
  hostNetwork: true
status: {}

kind.yaml

apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
name: test
networking:
  apiServerPort: 9443
nodes:
- role: control-plane
  image: kindest/node:v1.26.0
  extraMounts:
    - hostPath: /{yourself}/xline1.yaml
      containerPath: /etc/kubernetes/manifests/xline1.yaml
    - hostPath: /{yourself}/xline2.yaml
      containerPath: /etc/kubernetes/manifests/xline2.yaml
    - hostPath: /{yourself}/xline3.yaml
      containerPath: /etc/kubernetes/manifests/xline3.yaml
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    apiServer:
      extraArgs:
        etcd-servers-overrides: /events#http://172.18.0.2:7379;http://172.18.0.2:8379;http://172.18.0.2:9379    

基于flannel CNI的kubernetes

https://liangyuanpeng.com/files/kind/v1alpha4/kind_flannel.yaml

默认情况下 Kind 使用的 CNI 是,因此如果你需要使用 flannel CNI 的话,需要禁止默认的 CNI 并且部署 flannel.

lan@lan:~$ k get po -A
NAMESPACE            NAME                                            READY   STATUS    RESTARTS   AGE
kube-system          coredns-787d4945fb-d84n2                        0/1     Pending   0          34s
kube-system          coredns-787d4945fb-zpvlf                        0/1     Pending   0          34s
kube-system          etcd-flannel-control-plane                      1/1     Running   0          47s
...

可以看到 coredns 是没启动起来的,原因是缺少了 CNI 组件.因此首选需要下载 flannel cni 需要的组件,然后部署 flannel.

下载 cni

https://liangyuanpeng.com/files/scripts/install-cni.sh

可以使用这个文件下载 CNI 二进制内容,

部署flannel

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

回来吧kubernetes!

现在再查看一下所有 pod 的情况,会看到 Flannel 的 pod 正在拉取镜像启动,再过一会所有的 pod 都会启动起来了,当然也包括 Coredns 的 pod,这时候就可以正常食用你的 kubernetes 测试环境了!

k8s 1.26 CEL准入校验功能

https://liangyuanpeng.com/files/kind/v1alpha4/kind_flannel.yaml

多节点

https://liangyuanpeng.com/files/kind/v1alpha4/kind_mult.yaml

K8S kube-apiserver 端口映射

默认情况下使用 Kind 搭建的 kubernetes 环境只能在本机使用,这个配置文件映射了 kube-apiserver 端口,因此可以在机器A用 Kind 搭建环境,在机器B访问 Kind 的 K8S.

https://liangyuanpeng.com/files/kind/v1alpha4/kind_port.yaml

没有lank8s.cn服务

https://liangyuanpeng.com/files/kind/v1alpha4/kind_nolank8s.yaml

基于 Kind 搭建的 K8S 为 kube-apiserver 配置 SAN IP

kind.yaml

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
    endpoint = ["https://gcr.lank8s.cn"]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
    endpoint = ["https://k8s.lank8s.cn"]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
    endpoint = ["https://registry.lank8s.cn"]  
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    apiServer:
      certSANs:
        - "192.168.3.87"
        - "192.168.3.152"    

定制化 Kind 节点容器镜像

默认情况下 Kind 包含的是 kubeadm config list 所对应的容器镜像,而如果想要将自己应用的容器镜像也内置到 Kind 的节点镜像里面的话目前 Kind 是没有官方支持的,但可以用下面两种方法达到目的:

  1. 修改源码,将自己的容器镜像加入到 kind build node-image 的逻辑当中.

我在之前就做过这样的事情,让我的自定义 Kindest/node 镜像可以内置 Envoy 和 Xline 的容器镜像.但当 Kind 发布新版本的时候总是需要 rebase 一下,以此来让新发布的 Kind 也包含自己新增的这部分逻辑.

  1. 基于 kindest/node 镜像来制作 Dockerfile,放入自己的容器镜像.

例如

FROM kindest/node:v1.29.2
COPY xline.tar /xline.tar

我也做过这样的尝试,但是当我想将这个镜像导入到 containerd 的时候发现会失败,没有权限. (已经成功制作,见下方)

然后我能想到的另一个思路是在这个容器内启动多一个容器镜像仓库,例如 distribution,然后将自己的应用容器镜像放入到这个容器镜像仓库里面,并且将这个容器镜像仓库应用后台启动.当实际需要的时候就填写 localhost:5000/xline:v0.5.0,这样的特殊地址来使用,缺点是需要多启动一个应用.

这种方法的另一个注意事项是如果要考虑到多节点的情况的话就有些复杂了.

最理想的当然是 Kind 官方支持在构建自定义的节点镜像时可以提供方式来导入自己的自定义应用镜像,但 Kind 项目的使命就是为了作为 kubernetes CI 存在的,因此维护者希望保持这个项目的简洁性,以致于Feature 2160 add images subcommand这个PR一直没有合并.

目前使用下面的 Dockerfile 成功基于 Kind 的镜像制作了带应用镜像的容器镜像.

FROM kindest/node:v1.29.2

RUN mkdir /tmp/kind
COPY xline.tar /tmp/kind/
RUN ( containerd -l warning & ) && ctr -n k8s.io images import --no-unpack /tmp/kind/*.tar
RUN rm /tmp/kind/*.tar

目前已经将这部分提交到 Xline 仓库的 CI 中, 见 https://github.com/xline-kv/Xline/pull/696/files#diff-4e1e5819d750fc60652b63bacccd9aefa2fd311104d8c24387ad558268429bd4

微信公众号

扫描下面的二维码关注我们的微信公众号,第一时间查看最新内容。同时也可以关注我的Github,看看我都在了解什么技术,在页面底部可以找到我的Github。

wechat-qrcode