Skip to main content

Command Palette

Search for a command to run...

使用 Kind 构建离线集群安装包

Updated
3 min read

Kind(Kubernetes in Docker) 是一个 Kubernetes 孵化项目,它使用 Docker 为节点进行 Kubernetes 的快速部署,可以方便的搭建 Kubernetes 集群,虽然简单,但也是通过 Kubernetes 一致性认证的安装器,因此用来做测试还是比较可靠的。

按照社区的一贯德行,安装过程虽然只要有个 Docker 就可以了,但是对网络有严重的依赖。在 Workshop 之类的场合,会受到很大限制。这种情况下,有一个离线包就会非常方便了。

获取安装文件

本文会从一个新安装的 CentOS Mini 服务器为例,逐个步骤展示构建离线 Kind 安装包的过程。最后再安装一个

这里假设这个服务器有“优秀”的互联网连接。

Docker 离线包

首先我们要为 Docker 的离线安装准备好 RPM 包,新建一个目录 rpms,用来下载安装包:

$ yum install --downloadonly --downloaddir=./rpms \
    yum-utils device-mapper-persistent-data lvm2

执行完毕之后,会在 rpms 目录中找到 Docker 的依赖包,接下来获取 Docker 的 RPM。

$ yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
$ yum --downloadonly --downloaddir=./rpms \
    install docker-ce docker-ce-cli containerd.io

如此就获得了 Docker 自身以及所有的依赖 RPM 包。可以使用 rpm 直接安装。并启动 Docker 服务。

Kubeadm 和 Kubectl

根据官方文档

$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

$ yum install --downloadonly --downloaddir=./rpms \
kubectl kubeadm --disableexcludes=kubernetes

这里做了一点修改:不再安装 kubelet,也不启动服务,仅用于获取安装包。

获取镜像

使用 rpm 安装 kubeadm,开始获取安装所需的所有镜像:

$ kubeadm config images list --kubernetes-version=v1.15.3
k8s.gcr.io/kube-apiserver:v1.15.3
k8s.gcr.io/kube-controller-manager:v1.15.3
k8s.gcr.io/kube-scheduler:v1.15.3
k8s.gcr.io/kube-proxy:v1.15.3
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1

拿到列表了就可以逐个拉取处理镜像,这里给个小脚本:

#!/bin/sh
for image in `kubeadm config images list --kubernetes-version=$1`
do
  image_name=`echo ${image} | sed "s/k8s.gcr.io.//g"`
  docker pull "${image}"
  docker tag "${image}" "${image_name}"
  file_name="${image_name}.tgz"
  docker save "${image_name}" | gzip > "${file_name}"
  docker rmi "${image}"
  docker rmi "${image_name}"
done

这样我们就有了所有 Kubeadm 所需的镜像。另外我们还需要两个辅助镜像:kindest/node:v1.15.3 以及 registry:2.7.1

CFSSL 和 Kind

$ wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-linux-amd6
$ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
$ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64

这样我们已经获得了所有安装所需的文件。可以进入离线步骤了。

安装

RPM 安装

把前面获得的 Kubectl 安装起来。

签发证书

使用 CFSSL 生成证书,首先生成 CA。

ca-csr.json

{
    "CN": "Kubernetes CA",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "ca": {
       "expiry": "87600h"
    }
}

cfssl gencert -initca ca-csr.json | cfssljson -bare ca 生成 CA 证书。

把证书加入信任列表:

$ update-ca-trust enable
$ cp ca.pem /etc/pki/ca-trust/source/anchors/
$ update-ca-trust extract

更新之后,需要重启 Docker 服务,让 Docker 也信任这一 CA。

然后是生成镜像库所需的服务器证书:

config.json

{
    "signing": {
        "default": {
            "expiry": "87600h"
        },
        "profiles": {
            "server": {
                "expiry": "87600h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            },
            "user": {
                "expiry": "87600h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "client auth"
                ]
            }
        }
    }
}

server.json

{
    "CN": "Registry",
    "hosts": [
      "127.0.0.1","10.211.55.10"
    ]
}

接下来签发证书:

$ cfssl gencert -ca ca.pem -ca-key ca-key.pem -config=config.json \
     -profile=server server.json | cfssljson -bare registry

这里的 IP 地址要跟本地地址对应。

启动镜像库

使用 docker load -i,载入了 registry 镜像,把仓库运行起来:

#!/bin/sh
docker run -d \
   --name="registry2" \
   -v "$(pwd)/storage":/var/lib/registry \
   -p 5000:5000 \
  -v "$(pwd)/certs":/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.pem \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry-key.pem \
   --restart=always \
   registry:2.7.1

如此就在 5000 端口启动了一个镜像库。

推送镜像到私库

把前面的所有镜像都载入 Docker,Tag 之后推入私库,最后在私库里就有了一系列的镜像,例如 10.211.55.10:5000/pause:3.1

安装集群

为了能够使用私库的镜像,要对 Kind 进行一点配置:

kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
kubeadmConfigPatches:
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: ClusterConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: 10.211.55.10:5000
  nodeRegistration:
    kubeletExtraArgs:
      pod-infra-container-image: 10.211.55.10:5000/pause:3.1
- |
  apiVersion: kubeadm.k8s.io/v1beta2
  kind: InitConfiguration
  metadata:
    name: config
  networking:
    serviceSubnet: 10.0.0.0/16
  imageRepository: 10.211.55.10:5000
nodes:
- role: control-plane
$ kind create cluster --image kindest/node:v1.15.3
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.15.3) 🖼
 ✓ Preparing nodes 📦
 ✓ Creating kubeadm config 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Cluster creation complete. You can now use the cluster with:

export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"

如此这般,Kind 集群就启动了。我们可以测试一下:

$ export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
$ kubectl get pods --all-namespaces
NAMESPACE     NAME                                         READY   STATUS    RESTARTS   AGE
kube-system   coredns-5c98db65d4-lkg92                     1/1     Running   0          72m
kube-system   coredns-5c98db65d4-rhv7g                     1/1     Running   0          72m
kube-system   etcd-kind-control-plane                      1/1     Running   0          71m
kube-system   kindnet-892gh                                1/1     Running   1          72m
kube-system   kube-apiserver-kind-control-plane            1/1     Running   0          71m
kube-system   kube-controller-manager-kind-control-plane   1/1     Running   0          71m
kube-system   kube-proxy-nd4ml                             1/1     Running   0          72m
kube-system   kube-scheduler-kind-control-plane            1/1     Running   0          71m

离线环境下部署镜像

Kind 提供了一个 load 命令,可以把镜像载入所有“节点”,例如:

$ kind load docker-image 10.211.55.10:5000/registry:2.7.1
$ kubectl run registry --image=10.211.55.10:5000/registry:2.7.1 --replicas=2
$ kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/registry created
$ kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
registry-6b7648c4f4-g8zxr   1/1     Running   0          24s

后记

很明显,这些步骤是可以自动化的,只需要分发一个安装包,就能够很方便的快速部署、删除一整套的 Kubernetes,可以用随需部署的方式完成环境的搭建和删除。

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts