1. 使用kind搭建k8s集群

0. 简介

Kubernetes(简称k8s,即k和s之间有8个字母)是一个可移植的、可拓展的开源平台,使用声明式配置并依据配置信息自动执行容器化管理。

我研究生毕业的第一份工作,是在一个汽车配套软件公司从事嵌入式Linux开发,那时候的开发模式是在开发机上使用交叉编译工具链编译出可执行的程序,导到arm板上直接运行。所以从整个流程上来说,交叉编译工具链的版本、所依赖的库、以及各种依赖环境都必须copy到对应的板子上才能运行,若涉及到整个生产的流程,那就会更麻烦。后来去了一家AI企业做后端开发后,才慢慢接触到容器化部署,这就使得开发环境、测试环境和生产环境的部署变得轻松和敏捷。其实我的这种经历,也就对应了应用程序部署方式的发展趋势:

  • 传统部署:直接部署在物理机上,无法明确应用程序的边界,也很难合理地分配资源;其次是程序迁移时也很困难;
  • 虚拟化部署:应用程序被虚拟机互相隔离,限制了程序之间的非法访问;也能更好地实现规模化的部署;但是虚拟机比较重,其自身消耗的资源就比较多;
  • 容器化部署:相比于虚拟化部署,其降低了隔离层级,共享了操作系统,更加轻量。

综上,容器化是一种很好的程序部署方案,在生产环境中,我们需要管理容器化的应用程序,确保其健康运行,而k8s就是针对此类问题而提供的容器化编排解决方案,其提供的特性有服务发现负载均衡存储编排自动发布和回滚自愈以及密钥和配置管理等。

1. 学习环境搭建

1.1 k8s替代工具的选择

几乎不会有人在本地部署一个完整的k8s集群,一般会采用一些替代工具,比如kind、minikube或者k3s等,可参考Minikube vs.kind vs.k3s-我应该用哪一个?,这里我选择的是kind。

安装kind

kind的安装可以参考Installation,我是Mac系统,直接运行:

bash 复制代码
brew install kind

安装kubectl

kubectl是k8s的命令行工具,可以用来部署应用、监测和管理集群资源以及查看日志。安装参考kubectl

bash 复制代码
brew install kubectl

2. 使用kind创建集群

创建很简单,可参考Cluster,但是需要注意的是,应该是国内墙的原因,直接执行kind create cluster可能并不能拉去下镜像,即使能够访问外网,也会长时间卡在 Ensuring node image (kindest/node:v1.27.3) 这个步骤,这个时候需要手动去拉取镜像(注意要拉取具体版本,在我的环境中直接运行docker pull kindest/node也拉不到):

bash 复制代码
docker pull kindest/node:v1.27.3

简单集群

在kind的镜像拉取成功后,可以直接使用kind create cluster创建,生成的cluster名称默认为kind,可以使用kind delete cluster --name kind进行删除。

bash 复制代码
 ~  kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.27.3) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Thanks for using kind! 😊

然后执行以下指令,会发现创建了一个control-plane的节点:

bash 复制代码
 ~  kubectl config get-contexts
CURRENT   NAME              CLUSTER           AUTHINFO          NAMESPACE
*         kind-kind         kind-kind         kind-kind

 ~  kubectl get node
NAME                 STATUS   ROLES           AGE   VERSION
kind-control-plane   Ready    control-plane   75s   v1.27.3

多节点集群

一般而言,我们的k8s集群不会是只有一个节点,虽然我们使用kind在开发机上进行集群搭建,但是集群节点本质上是跑在docker上的,所以我们也可以模拟多节点集群。

首先,我们使用yaml记录搭建集群的配置:

yaml 复制代码
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  # port forward 80 on the host to 80 on this node
  extraPortMappings:
  - containerPort: 30950
    hostPort: 80
    # optional: set the bind address on the host
    # 0.0.0.0 is the current default
    listenAddress: "127.0.0.1"
    # optional: set the protocol to one of TCP, UDP, SCTP.
    # TCP is the default
    protocol: TCP
- role: worker
- role: worker
- role: worker

然后使用以下命令创建多节点集群:

bash 复制代码
 ~  kind create cluster --name multi --config ./multi-node.yaml
Creating cluster "multi" ...
 ✓ Ensuring node image (kindest/node:v1.27.3) 🖼
 ✓ Preparing nodes 📦 📦 📦 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-multi"
You can now use your cluster with:

kubectl cluster-info --context kind-multi

Thanks for using kind! 😊

然后查看容器,可以看到创建了一个控制节点,三个工作节点。

bash 复制代码
 ~  docker ps | grep multi
dc3218f93fb8   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago   Up 2 minutes                                                        multi-worker2
12dca63de042   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago   Up 2 minutes                                                        multi-worker
9895ed46d75a   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago   Up 2 minutes   127.0.0.1:57884->6443/tcp, 127.0.0.1:80->30950/tcp   multi-control-plane
2b1bfd3ccdac   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago   Up 2 minutes                                                        multi-worker3

端口映射 - type: NodePort

由于 kind 是把 node 运行在 docker 里的, 因此即使在 k8s 集群中使用 nodePort 方式将服务暴露出来,在宿主机上依旧无法访问。

因为这里暴露的 nodePort 其实是 docker 容器的端口,如果 docker 容器启动时没有将端口映射出来依旧无法访问

所以我们需要端口映射来实现服务的访问,我们先创建nodePort.yaml如下,然后执行kubectl apply -f nodePort.yaml即可创建对应的Service和Pod(这些概念后续介绍):

yaml 复制代码
kind: Pod
apiVersion: v1
metadata:
  name: foo
  labels:
    app: foo
spec:
  containers:
  - name: foo
    image: hashicorp/http-echo:latest
    args:
    - "-text=foo"
---
apiVersion: v1
kind: Service
metadata:
  name: foo
spec:
  type: NodePort
  ports:
  - name: http
    nodePort: 30950
    port: 5678 # image默认输出5678
  selector:
    app: foo

然后等待节点运行后,执行以下命令,即可实现服务的基本访问。

bash 复制代码
 ~  curl 127.0.0.1:80
foo

端口映射 - type: LoadBalancer

其实我们也可以通过负载均衡的服务,首先创建loadBalancer.yaml

yaml 复制代码
kind: Pod
apiVersion: v1
metadata:
  name: foo
  labels:
    app: foo
spec:
  containers:
  - name: foo
    image: hashicorp/http-echo:latest
    args:
    - "-text=foo"
---
kind: Pod
apiVersion: v1
metadata:
  name: bar
  labels:
    app: foo
spec:
  containers:
  - name: bar
    image: hashicorp/http-echo:latest
    args:
    - "-text=bar"
---
apiVersion: v1
kind: Service
metadata:
  name: foo
spec:
  type: LoadBalancer
  ports:
  - name: http
    nodePort: 30950
    port: 5678 # image默认输出5678
  selector:
    app: foo

然后部署Pod和Service:

bash 复制代码
~  kubectl apply -f loadBalancer.yaml
pod/foo created
pod/bar created
service/foo created

~  kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP           NODE            NOMINATED NODE   READINESS GATES
bar    1/1     Running   0          5s    10.244.1.3   multi-worker2   <none>           <none>
foo    1/1     Running   0          5s    10.244.3.4   multi-worker3   <none>           <none>

~  kubectl get svc -o wide
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE   SELECTOR
foo          LoadBalancer   10.96.180.193   <pending>     5678:30950/TCP   36s   app=foo
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          29m   <none>

然后验证:

bash 复制代码
~  for _ in {1..10}; do
  curl localhost:80
done
foo
foo
bar
foo
bar
bar
bar
foo
foo
foo

很神奇的是我这里操作没有按照kind LoadBalancer中介绍的需要先安装MetalLB

HA 集群

有时候,我们也可以创建出多个control-plane的集群,可以认为是HA的(但是在我们的环境当然是假的HA),其创建脚本如下:

yaml 复制代码
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker

执行kind create cluster --name ha --config ./ha.yaml,值得注意的是,其还会生成一个名为ha-external-load-balancer的负载均衡器:

bash 复制代码
 ~  docker ps | grep ha
8589a7ac8dba   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes                                                         ha-worker
bf21f798101e   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes    127.0.0.1:59785->6443/tcp                            ha-control-plane3
b5cc29441183   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes                                                         ha-worker2
f8cd63326cc2   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes    127.0.0.1:59786->6443/tcp                            ha-control-plane
839aa0b6e287   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes    127.0.0.1:59787->6443/tcp                            ha-control-plane2
a172a98e244f   kindest/node:v1.27.3                 "/usr/local/bin/entr..."   2 minutes ago    Up 2 minutes                                                         ha-worker3
f68e5c42edac   kindest/haproxy:v20230606-42a2262b   "haproxy -W -db -f /..."   2 minutes ago    Up 2 minutes    127.0.0.1:59788->6443/tcp                            ha-external-load-balancer

这个负载均衡器我的理解如下,在这里感谢Kubernetes教程(十五)---使用 kind 在本地快速部署一个 k8s集群,以下结论也是和他的讨论中得出的,毕竟我花了一天的时间去搜索怎么配置这个ha-external-load-balancer,以求其达到对服务负载均衡的效果,但是很大可能应该是想错了。

  1. ha-external-load-balancer是针对于control-plane节点的HA,指的是所有kubectl指令会先打到这个HAProxy,然后再分发到各个control-plane节点;
  2. 如果要做自定义服务的负载均衡,还是要根据service自带的LoadBalancer来做;

3. 参考文献

kind

Kubernetes教程(十五)---使用 kind 在本地快速部署一个 k8s集群

相关推荐
运维-大白同学2 小时前
2025最全面开源devops运维平台功能介绍
linux·运维·kubernetes·开源·运维开发·devops
敲上瘾9 小时前
【探索实战】:Kurator分布式统一应用分发平台的全面解析与实践指南
分布式·容器·kubernetes·serverless
Connie145120 小时前
记一次K8s故障告警排查(Grafna告警排查)
云原生·容器·kubernetes·grafana
谷隐凡二1 天前
Kubernetes主从架构简单解析:基于Python的模拟实现
python·架构·kubernetes
陈陈CHENCHEN1 天前
SuperMap iManager for K8s 离线环境镜像仓库 Containerd 部署
kubernetes
会飞的小蛮猪1 天前
Ubuntu24.04 基于Containerd部署K8s1.34(私服部署)
docker·云原生·kubernetes
间彧2 天前
Kubernetes滚动发布详解
kubernetes
间彧2 天前
在实际生产环境中,Kubernetes声明式API如何实现蓝绿部署、金丝雀发布等高级部署策略?
kubernetes
间彧2 天前
Kubernetes声明式API相比传统命令式API在故障恢复场景下的具体优势有哪些?
kubernetes·github
间彧2 天前
为什么说Kubernetes的API设计是其成功的关键因素之一?
kubernetes