参考文档:使用K3s快速搭建集群 · 语雀
前提:提前准备好vmware并安装centos系统 并下载好k3s相关资源 下载需要网络环境支持
下载安装脚本
install.sh
:https://get.k3s.io/下载
k3s
二进制文件:k3s下载k3s必要的image:离线安装需要的image文件
这些文件都可以在github仓库中获取:GitHub - k3s-io/k3s: Lightweight Kubernetes
目录
Deployment(部署)与ReplicaSet(副本集)
使用K3S搭建k8s集群(虚拟机方式)
K3s 是一个轻量级的、完全兼容的 Kubernetes 发行版本。非常适合初学者。
K3s将所有 Kubernetes 控制平面组件都封装在单个二进制文件和进程中,文件大小<100M,占用资源更小,且包含了kubernetes运行所需要的部分外部依赖和本地存储提供程序。
K3s提供了离线安装包,安装起来非常方便,可以避免安装过程中遇到各种网络资源访问问题。
K3s特别适用于边缘计算、物联网、嵌入式和ARM移动端场景。
提示:
K3s完全兼容kubernetes,二者的操作是一样的,使用k3s完全满足我们学习kubernetes的要求,课程的最后,我们再使用kubeadm安装一个完整的集群。
1.准备工作
在一台虚拟机上执行如下命令:
- 关闭防火墙
- 设置selinux(需要联网)
systemctl disable firewalld --nowyum install -y container-selinux selinux-policy-base yum install -y https://rpm.rancher.io/k3s/latest/common/centos/7/noarch/k3s-selinux-0.2-1.el7_8.noarch.rpm
2.下载安装包
下载安装脚本install.sh
:https://get.k3s.io/
下载k3s
二进制文件:k3s
下载必要的image:离线安装需要的image文件
这些文件都可以在github仓库中获取:GitHub - k3s-io/k3s: Lightweight Kubernetes
3.执行安装脚本
1.将k3s
二进制文件移动到/usr/local/bin
目录,并添加执行权限
mv k3s /usr/local/bin chmod +x /usr/local/bin/k3s
2.将镜像移动到/var/lib/rancher/k3s/agent/images/
目录(无需解压)
mkdir -p /var/lib/rancher/k3s/agent/images/ cp ./k3s-airgap-images-amd64.tar.gz /var/lib/rancher/k3s/agent/images/
此时将这台虚拟机复制两台出来作为worker节点
依次在每台虚拟机使用 hostnamectl set-hostname k8s-master, hostnamectl set-hostname k8s-worker1, hostnamectl set-hostname k8s-worker2 设置hostname
- 在
k8s-master
节点执行:
#修改权限
chmod +x install.sh
#离线安装
INSTALL_K3S_SKIP_DOWNLOAD=true ./install.sh
#安装完成后,查看节点状态
kubectl get node #等待一会执行这条命令会看到
#NAME STATUS ROLES AGE VERSION
#k8s-master Ready control-plane,master 17s v1.25.0+k3s1 说明master安装正确
#查看集群token
cat /var/lib/rancher/k3s/server/node-token
#K10c4b79481685b50e4bca2513078f4e83b62d1d0b5f133a8a668b65c8f9249c53e::server:bf7b63be7f3471838cbafa12c1a1964d #生成的token为集群的token 复制你自己的token出来下面要用
- 在
k8s-worker1
和k8s-worker2
节点执行
chmod +x install.sh INSTALL_K3S_SKIP_DOWNLOAD=true \ K3S_URL=https://192.168.56.109:6443 \#记得改成自己的ip 端口不用改 K3S_TOKEN=K1012bdc3ffe7a5d89ecb125e56c38f9fe84a9f9aed6db605f7698fa744f2f2f12f::server:fdf33f4921dd607cadf2ae3c8eaf6ad9 \#这个token也改成自己的 ./install.sh#此时再去master节点虚拟机执行kubectl get node等待一会执行这条命令会看到
NAME STATUS ROLES AGE VERSION
k8s-worker1 Ready <none> 15m v1.25.0+k3s1
k8s-worker2 Ready <none> 15m v1.25.0+k3s1
k8s-master Ready control-plane,master 19m v1.25.0+k3s1也可使用 watch -n 1 kubectl get node 每隔一秒动态查看集群状态
都为ready状态 集群安装成功!
排查错误
如果安装或启动不成功,可能有以下几个原因:
- 时间不统一
IP
有冲突,请为每个主机分配不同的IP- 主机名(hostname)重复,请为每个主机设置不同的主机名
- 网卡的MAC有冲突,复制虚拟机时,请为所有网卡重新生产MAC地址
4.设置镜像加速地址
由于kubernetes从V1.24
版本开始默认使用containerd
,需要修改containerd
的配置文件,才能让Pod的镜像使用镜像加速器。
配置文件路径一般为/etc/containerd/config.toml
,详见阿里云镜像加速。
在K3s中配置镜像仓库
K3s 会自动生成containerd的配置文件/var/lib/rancher/k3s/agent/etc/containerd/config.toml,不要直接修改这个文件,k3s重启后修改会丢失。
为了简化配置,K3s 通过/etc/rancher/k3s/registries.yaml文件来配置镜像仓库,K3s会在启动时检查这个文件是否存在。
我们需要在每个节点上新建/etc/rancher/k3s/registries.yaml文件,
cd /etc/rancher/k3s
vi registries.yaml
配置内容如下:
mirrors:
docker.io:
endpoint:
- "https://fsp2sfpr.mirror.aliyuncs.com/"
重启每个节点
systemctl restart k3s #master systemctl restart k3s-agent #worker
查看配置是否生效。
cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml
k8s概念
Pod
1.Pod(容器集)
Pod 是包含一个或多个容器的容器组,是 Kubernetes 中创建和管理的最小对象。
Pod 有以下特点:
- Pod是kubernetes中最小的调度单位(原子单元),Kubernetes直接管理Pod而不是容器。
- 同一个Pod中的容器总是会被自动安排到集群中的同一节点(物理机或虚拟机)上,并且一起调度。
- Pod可以理解为运行特定应用的“逻辑主机”,这些容器共享存储、网络和配置声明(如资源限制)。
- 每个 Pod 有唯一的 IP 地址。 IP地址分配给Pod,在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,Pod 内的容器可以使用
localhost
互相通信。
例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 "边车 (sidercar)" 容器负责从远端更新这些文件,如下图所示:
例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 "边车 (sidercar)" 容器负责从远端更新这些文件,如下图所示:
2.创建和管理Pod
# 创建pod
kubectl run mynginx --image=nginx
# 查看Pod
kubectl get pod
# 查看pod描述
kubectl describe pod mynginx
# 查看Pod的运行日志
kubectl logs mynginx
# 显示pod的IP和运行节点信息
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 10.42.1.3
#在容器中执行
kubectl exec mynginx -it -- /bin/bash
kubectl get po --watch
# -it 交互模式
# --rm 退出后删除容器,多用于执行一次性任务或使用客户端
kubectl run mynginx --image=nginx -it --rm -- /bin/bash
# 删除
kubectl delete pod mynginx
# 强制删除
kubectl delete pod mynginx --force
3.容器与镜像
容器运行时接口(CRI)
Kubelet运行在每个节点(Node)上,用于管理和维护Pod和容器的状态。
容器运行时接口(CRI)是kubelet 和容器运行时之间通信的主要协议。它将 Kubelet 与容器运行时解耦,理论上,实现了CRI接口的容器引擎,都可以作为kubernetes的容器运行时。
Docker没有实现(CRI)接口,Kubernetes使用dockershim来兼容docker。
自V1.24版本起,Dockershim 已从 Kubernetes 项目中移除。
crictl是一个兼容CRI的容器运行时命令,他的用法跟docker命令一样,可以用来检查和调试底层的运行时容器。
#拉取镜像
crictl pull mysql:5.7-debian
#查看镜像
crictl images
在一些局域网环境下,我们没法通过互联网拉取镜像,可以手动的导出、导入镜像。
crictl命令没有导出、导入镜像的功能。
需要使用ctr命令导出、导入镜像,它是containerd的命令行接口。
●从docker导出镜像再导入到containerd中
# 将docker镜像拉取本地
docker pull alpine:3.16
# 导出为tar包
docker save alpine:3.16 > alpine.tar
# 导入tar包 kubernetes使用的镜像都在k8s.io命名空间中-n指定命名空间 --platform指定平台
ctr -n k8s.io images import alpine.tar --platform linux/amd64
●从containerd导出、导入镜像
#导出镜像
ctr -n k8s.io images export mysql.tar docker.io/library/mysql:5.7-debian \
--platform linux/amd64
#导入镜像
ctr -n k8s.io images import mysql.tar
Deployment(部署)与ReplicaSet(副本集)
Deployment是对ReplicaSet和Pod更高级的抽象。
它使Pod拥有多副本,自愈,扩缩容、滚动升级等能力。
ReplicaSet(副本集)是一个Pod的集合。
它可以设置运行Pod的数量,确保任何时间都有指定数量的 Pod 副本在运行。
通常我们不直接使用ReplicaSet,而是在Deployment中声明。
#创建deployment,部署3个运行nginx的Pod
kubectl create deployment nginx-deployment --image=nginx:1.22 --replicas=3
#查看deployment
kubectl get deploy
#查看replicaSet
kubectl get rs
#删除deployment
kubectl delete deploy nginx-deployment
1.缩放
●手动缩放
#将副本数量调整为5
kubectl scale deployment/nginx-deployment --replicas=5
kubectl get deploy
●自动缩放
自动缩放通过增加和减少副本的数量,以保持所有 Pod 的平均 CPU 利用率不超过 75%。
自动伸缩需要声明Pod的资源限制,同时使用 Metrics Server 服务(K3s默认已安装)。
本例仅用来说明kubectl autoscale命令的使用,完整示例参考:HPA演示
#自动缩放
kubectl autoscale deployment/nginx-auto --min=3 --max=10 --cpu-percent=75
#查看自动缩放
kubectl get hpa
#删除自动缩放
kubectl delete hpa nginx-deployment
2.滚动更新 更新镜像版本和回滚版本
更新
#查看版本和Pod
kubectl get deployment/nginx-deployment -owide
kubectl get pods
#更新容器镜像
kubectl set image deployment/nginx-deployment nginx=nginx:1.23
#滚动更新 回滚
kubectl rollout status deployment/nginx-deployment
#查看过程
kubectl get rs --watch
版本回滚
#查看历史版本
kubectl rollout history deployment/nginx-deployment
#查看指定版本的信息
kubectl rollout history deployment/nginx-deployment --revision=2
#回滚到历史版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
Service(服务)
Service将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。
Service为一组 Pod 提供相同的 DNS 名,并且在它们之间进行负载均衡。
Kubernetes 为 Pod 提供分配了IP 地址,但IP地址可能会发生变化。
集群内的容器可以通过service名称访问服务,而不需要担心Pod的IP发生变化。
Kubernetes Service 定义了这样一种抽象:
逻辑上的一组可以互相替换的 Pod,通常称为微服务。
Service 对应的 Pod 集合通常是通过选择算符来确定的。
举个例子,在一个Service中运行了3个nginx的副本。这些副本是可互换的,我们不需要关心它们调用了哪个nginx,也不需要关注 Pod的运行状态,只需要调用这个服务就可以了。
1.创建Service对象
ServiceType 取值
●ClusterIP:将服务公开在集群内部。kubernetes会给服务分配一个集群内部的 IP,集群内的所有主机都可以通过这个Cluster-IP访问服务。集群内部的Pod可以通过service名称访问服务。
●NodePort:通过每个节点的主机IP 和静态端口(NodePort)暴露服务。 集群的外部主机可以使用节点IP和NodePort访问服务。
●ExternalName:将集群外部的网络引入集群内部。
●LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。
# port是service访问端口,target-port是Pod端口
# 二者通常是一样的
kubectl expose deployment/nginx-deployment \
--name=nginx-service --type=ClusterIP --port=80 --target-port=80
# 随机产生主机端口
kubectl expose deployment/nginx-deployment \
--name=nginx-service2 --type=NodePort --port=8080 --target-port=80
2.访问Service
外部主机访问:192.168.56.109:32296。
1.NodePort端口是随机的,范围为:30000-32767。
2.集群中每一个主机节点的NodePort端口都可以访问。
3.如果需要指定端口,不想随机产生,需要使用配置文件来声明。
#集群内访问
curl 10.43.65.187:80
#容器内访问
kubectl run nginx-test --image=nginx:1.22 -it --rm -- sh
#
curl nginx-service:80
Namespace(命名空间)
命名空间(Namespace)是一种资源隔离机制,将同一集群中的资源划分为相互隔离的组。
命名空间可以在多个用户之间划分集群资源(通过资源配额)。
●例如我们可以设置开发、测试、生产等多个命名空间。
同一命名空间内的资源名称要唯一,但跨命名空间时没有这个要求。
命名空间作用域仅针对带有名字空间的对象,例如 Deployment、Service 等。
这种作用域对集群访问的对象不适用,例如 StorageClass、Node、PersistentVolume 等。
Kubernetes 会创建四个初始命名空间:
●default 默认的命名空间,不可删除,未指定命名空间的对象都会被分配到default中。
●kube-system Kubernetes 系统对象(控制平面和Node组件)所使用的命名空间。
●kube-public 自动创建的公共命名空间,所有用户(包括未经过身份验证的用户)都可以读取它。通常我们约定,将整个集群中公用的可见和可读的资源放在这个空间中。
●kube-node-lease 租约(Lease)对象使用的命名空间。每个节点都有一个关联的 lease 对象,lease 是一种轻量级资源。lease对象通过发送心跳,检测集群中的每个节点是否发生故障。
使用kubectl get lease -A查看lease对象
使用多个命名空间
●命名空间是在多个用户之间划分集群资源的一种方法(通过资源配额)。
○例如我们可以设置开发、测试、生产等多个命名空间。
●不必使用多个命名空间来分隔轻微不同的资源。
○例如同一软件的不同版本: 应该使用标签 来区分同一命名空间中的不同资源。
●命名空间适用于跨多个团队或项目的场景。
○对于只有几到几十个用户的集群,可以不用创建命名空间。
●命名空间不能相互嵌套,每个 Kubernetes 资源只能在一个命名空间中。
1.管理命名空间
#创建命名空间
kubectl create namespace dev
#查看命名空间
kubectl get ns
#在命名空间内运行Pod
kubectl run nginx --image=nginx --namespace=dev
kubectl run my-nginx --image=nginx -n=dev
#查看指定命名空间内的Pod 不加-n参数 查看的是默认命名空间
kubectl get pods -n=dev
#查看命名空间内所有对象
kubectl get all
# 删除命名空间会删除命名空间下的所有内容 可能删除失败 需手动删除ns下的对象再进行删除
kubectl delete ns dev
2.切换当前命名空间
#查看当前上下文
kubectl config current-context
#设置默认命名空间 将dev设为当前命名空间,后续所有操作都在此命名空间下执行。
kubectl config set-context $(kubectl config current-context) --namespace=dev
声明式对象配置(要看得懂)
云原生的代表技术包括:
- 容器
- 声明式API
- 不可变基础设施
- 微服务
- 服务网格
管理对象
- 命令行指令
例如,使用kubectl
命令来创建和管理 Kubernetes 对象。
命令行就好比口头传达,简单、快速、高效。
但它功能有限,不适合复杂场景,操作不容易追溯,多用于开发和调试。
- 声明式配置
kubernetes使用yaml文件来描述 Kubernetes 对象。
声明式配置就好比申请表,学习难度大且配置麻烦。
好处是操作留痕,适合操作复杂的对象,多用于生产。
1. 常用命令缩写
名称 | 缩写 | Kind |
namespaces | ns | Namespace |
nodes | no | Node |
pods | po | Pod |
services | svc | Service |
deployments | deploy | Deployment |
replicasets | rs | ReplicaSet |
statefulsets | sts | StatefulSet |
#使用缩写
kubectl create deploy my-deploy --image=nginx:1.22 --replicas=3
kubectl get po
2.YAML规范
- 缩进代表上下级关系
- 缩进时不允许使用Tab键,只允许使用空格,通常缩进2个空格
:
键值对,后面必须有空格-
列表,后面必须有空格[ ]
数组#
注释|
多行文本块---
表示文档的开始,多用于分割多个资源对象group: name: group-1 members: - name: "Jack Ma" UID: 10001 - name: "Lei Jun" UID: 10002 words: ["I don't care money","R U OK"] # comments text: | line new line 3rd line
可以使用vscode安装yaml插件 使用ssh连接虚拟机 将yaml文件标准化
3.配置对象
在创建的 Kubernetes 对象所对应的 yaml文件中,需要配置的字段如下:
●apiVersion - Kubernetes API 的版本
●kind - 对象类别,例如Pod、Deployment、Service、ReplicaSet等
●metadata - 描述对象的元数据,包括一个 name 字符串、UID 和可选的 namespace
●spec - 对象的配置
掌握程度:
- 不要求自己会写 能排错 会修改 能看懂 找模版
使用yaml定义一个Pod
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
使用yaml文件管理对象
#创建对象
kubectl apply -f my-pod.yaml
#编辑对象
kubectl edit nginx
#删除对象
kubectl delete -f my-pod.yaml
3.标签
标签(Labels) 是附加到对象(比如 Pod)上的键值对,用于补充对象的描述信息。
标签使用户能够以松散的方式管理对象映射,而无需客户端存储这些映射。
由于一个集群中可能管理成千上万个容器,我们可以使用标签高效的进行选择和操作容器集合。
键的格式:
- 前缀(可选)/名称(必须)。
效名称和值:
- 必须为 63 个字符或更少(可以为空)
- 如果不为空,必须以字母数字字符([a-z0-9A-Z])开头和结尾
- 包含破折号
-
、下划线_
、点.
和字母或数字
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels: #定义Pod标签
environment: test
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
# 查看pod会显示标签
kubectl get pod --show-labels
# 查看pod并且过滤 env=test app=nginx的才会显示 都满足才显示
kubectl get pod -l environment=test,app=nginx
4.选择器
标签选择器 可以识别一组对象。标签不支持唯一性。
标签选择器最常见的用法是为Service选择一组Pod作为后端。
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector: #与Pod的标签一致
environment: test
app: nginx
ports:
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
目前支持两种类型的选择运算:基于等值的和基于集合的。
多个选择条件使用逗号分隔,相当于And(&&)运算。
等值选择
selector:
matchLabels: # component=redis && version=7.0
component: redis
version: 7.0
基于集合
selector:
matchExpressions: # tier in (cache, backend) && environment not in (dev, prod)
- {key: tier, operator: In, values: [cache, backend]}
- {key: environment, operator: NotIn, values: [dev, prod]}