云原生基本概念:
在容器化时代,虽然Docker已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理、资源调度、文件管理等等。
不过目前也涌现了很多解决方案,比如 Mesos、Swarm、Kubernetes 等等,其中谷歌开源的 Kubernetes就是其中的王者!
它是基于容器的集群编排引擎,具备扩展集群、滚动升级回滚、弹性伸缩、自动治愈、服务发现等多种特性能力。
1. K8s集群架构及核心概念
1.1 K8S 架构图
K8S功能
(1)自动装箱
基于容器对应用运行环境的资源配置要求自动部署应用容器
(2)自我修复(自愈能力)
当容器失败时,会对容器进行重启
当所部署的 Node 节点有问题时,会对容器进行重新部署和重新调度
当容器未通过监控检查时,会关闭此容器直到容器正常运行时,才会对外提供服务
(3)水平扩展
通过简单的命令、用户 UI 界面或基于 CPU 等资源使用情况,对应用容器进行规模
扩大或规模剪裁
(4)服务发现
用户不需使用额外的服务发现机制,就能够基于 Kubernetes 自身能力实现服务
发现和负载均衡
(5)滚动更新
可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新
(6)版本回退
可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退
(7)密钥和配置管理
在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。
(8)存储编排
自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要
存储系统可以来自于本地目录、网络存储(NFS、Gluster、Ceph 等)、公共云存储服务
(9)批处理
提供一次性任务,定时任务;满足批量数据处理和分析的场景
1.2 K8S组件
1.2.1 api service
所有服务访问统一入口。对外暴露K8S的api接口,是外界进行资源操作的唯一入口,并提供认证、授权、访问、控制、API注册和发现等机制。
1.2.2 controller manager
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等,他们是处理集群中常规任务的后台线程。
1.2.3 scheduler
负责资源的调度,按照预定的调度策略将Pod调度到响应的机器上;就是监视新创建的Pod,如果没有分配节点,就选择一个节点供他们运行,这就是Pod的调度。
1.2.4 etcd
一个可信赖的分布式键值存储服务,能够为整个分布式集群存储一些关键数据,协助分布式集群运转。储K8S集群所有重要信息(持久化)。v2版本是基于内存的存储,v3开始才是序列化到介质。新版K8S(v1.11以上)已经改用v3版本的etcd。
1.2.5 kubelet
直接跟容器引擎交互实现容器的生命周期管理。
1.2.6 kube-proxy
负责写入规则至iptables、ipvs实现服务映射访问。其中scheduler和controller-manager两个组件是有leader选举的,这个选举机制是K8S对于这两个组件的高可用保障。Api server是可以水平扩展的。
1.2.7 其他重要插件:
coredns:可以为集群中的SVC创建一个域名IP的对应关系解析
dashboard:给 K8S 集群提供一个 B/S 结构访问体系
ingress controller:官方只能实现四层代理,INGRESS 可以实现七层代理
federation:提供一个可以跨集群中心多K8S统一管理功能
prometheus :提供K8S集群的监控能力
elk:提供 K8S 集群日志统一分析介入平台
1.3 K8S资源
K8S中的所有内容都抽象为资源,资源实例化后叫做对象。
在K8S中,一般使用yaml格式的文件来创建符合我们预期的Pod(容器组),这种yaml文件一般被称为资源清单。
K8S中的资源可分为三种:
1.3.1 名称空间级资源
通过:kubectl api-resources --namespaced=true 查看全部。K8S是有空间概念的,以下资源是归属于某个空间的(没有指定就是默认空间default)。
同时也可以根据功能分为以下几种:1.3.1.1工作负载型
Pod、ReplicaSet(ReplicationController在v1.11版本废弃)、Deployment、StatefulSet、DaemonSet、Job、CronJob
1.3.1.2服务发现及负载均衡型
Service、Ingress等
1.3.1.3配置与存储型
Volume、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
1.3.1.4特殊类型的存储卷
ConfigMap(当做配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
1.3.2 集群级资源
通过:kubectl api-resources --namespaced=false 查看全部。
Namespace、Node、Role、ClusterRole、RoleBinding、ClusterRoleBinding
1.3.3 元数据型资源
HPA、PodTemplate、LimitRange
1.3.4资源清单常用字段:
yaml文件是K8S资源声明表达的格式。各种资源通用的常用字段如下:
字段 | 属性 | 描述 |
---|---|---|
apiVersion | String | 这里是指K8S API的版本,目前基本是V1,可以通过kubect1api-versions命令查询 |
kind | String | 资源的类型和角色,比如: Pod、ReplicaSet、Deployment等 |
metadata | Object | 元数据对象,固定值就写metadata |
-name | String | 元数据对象的名字,自定义编写 |
-namespace | String | 元数据对象的命名空间,自定义编写 |
Spec | Object | 详细定义对象,固定值就写Spec |
-containers | List | 这里是Spec对象的容器列表定义,是个列表 |
--name | String | 定义容器的名字 |
--image | String | 用到镜像名称 |
--imagePullPolicy | String | 定义镜像拉取策略,有Always(每次都拉取最新镜像)Never(仅使用本地镜像)、lfNotPresent(本地不存在才拉取在线镜像)三个值可选。默认Always |
--command | List | 指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令 |
--args | List | 指定容器启动命令参数,因为是数组可以指定多个 |
--workingDir | String | 指定容器的工作目录 |
volumeMounts | List | 指定容器内部的存储卷配置 |
---name | String | 指定可以被挂载的存储卷的名称 |
---mountPath | String | 指定可以被容器挂载的存储卷的路径 |
---readOnly | String | 设置存储卷的读写模式,true或false,默认false |
--ports | List | 指定容器需要用到的端口列表 |
---name | String | 指定端口名称 |
---containerPort | String | 指定容器需要监听的端口号 |
---hostPort | String | 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,会冲突) |
---protocol | String | 指定端口协议,支持TCP和UDP,默认TCP |
--env | List | 指定容器运行前需要设置的环境变量列表 |
---name | String | 指定环境变量名称 |
---value | String | 指定环境变量值 |
--resources | Object | 指定资源限制和资源请求的值 (这里开始就是设置容器的资源上限) |
---limits | Object | 指定设置容器运行时资源的运行上限 |
----cpu | String | 指定CPU的限制,单位为core数,将用于docker run --cpu-shares参数 |
----memory | String | 指定Memory内存的限制,单位为MIB,GiB |
---requests | Object | 指定容器启动和调度时的限制设置 |
---cpu | String | CPU请求,单位为core数,容器启动时初始化可用数量 |
----memory | String | 内存请求,单位为MiB,GiB,容器启动时初始化可用数量 |
-restartPolicy | String | 定义Pod的重启策略,可选值为Always (Pod一旦终止运行无论如何终止,kubectl服务都将重启它)、OnFailure (只有Pod以非非0退出码终止时才会重启)、Never (Pod终止后kubectl将退出码报告给master,不会重启Pod),默认值为Always |
1.4 工作负载
1.4.1 Node
K8s中节点(node)指的是一个工作机器,曾经叫做minion。不同的集群中,节点可能是虚拟机,也可能是物理机。每个节点都由master组件管理,并包含了运行Pod(容器组)所需的服务。这些服务包括:容器引擎、kubelet、kube-proxy。
kubectl get nodes -o wide 查看所有节点的列表。
kubectl describe node 查看节点状态以及节点的其他详细信息。
输出的节点状态包括以下信息:
Addersses
包括内外部IP、hostname等信息。
Conditions
描述了节点的硬盘、内存、进程数等压力状态。
Capacity and Allocatable
描述节点上的可用资源如CPU、内存、该节点可调度的最大pod数等情况。
Info
描述了节点的基本信息,如Linux内核版本、Kubernetes版本、Docker版本、操作系统名称等。
1.5 节点管理
与Pod和Service不一样,节点并不是由Kubernetes创建的,节点由云供应商创建。向Kubernetes中创建节点时,仅仅是创建了一个描述该节点的API对象。节点API对象创建成功后,Kubernetes将检查该节点是否有效。
例如,假设创建如下节点信息:
kind: Node
apiVersion: v1
metadata:
name:"10.0.0.10"
labels:
name:"first-node"
对应的效果为:
Kubernetes在APIServer上创建一个节点API对象(节点的描述),并且基于metadata.name字段对节点进行健康检查。如果节点有效,则可以向该节点调度Pod;否则,该节点API对象将被忽略,直到节点变为有效状态。
1.6 节点控制器(Node Controller)
这是一个负责管理节点的Kubernetes master组件。在节点的生命周期中,节点控制器起到了许多作用:
- 在注册节点时为节点分配CIDR地址块。
- 通过云供应商(cloud-controller-manager)接口,检查节点列表中每一个节点对象对应的虚拟机是否可用。在云环境中,只要节点状态异常,节点控制器检查其虚拟机在云供应商的状态,如果虚拟机不可用,自动将节点对象从APIServer中删除。
- 监控节点的健康状况。当节点变得不可触达时(例如,由于节点已停机,节点控制器不再收到来自节点的心跳新号),节点控制器将节点API对象的NodeStatusCondition取值从NodeReady更新为Unknown;然后在等待pod-eviction-timeout时间后,将节点上的所有Pod从节点驱逐。
1.6.1节点自注册(Self-Registration)
如果Kubelet的启动参数--register-node为true(默认为true),kubelet会尝试将自己注册到APIServer。
Kubelet自行注册时,将使用以下选项:
--kubeconfig:向apiserver进行认证时所用身份信息的路径
--cloud-provider:向云供应商读取节点自身元数据
--register-node:自动向API Server祖册节点
--register-with-taints:注册节点时,为节点添加污点(逗号分隔,格式为=:)
--node-ip:节点的IP地址
--node-labels:注册节点时,为节点添加标签
--node-status-update-frequency:向master节点发送心跳信息的时间间隔
对应的效果为:
如果 Node authorization mode (opens new window)和 NodeRestriction admission plugin (opens new window)被启用,kubelet 只拥有创建/修改其自身所对应的节点 API 对象的权限。
1.7 Pod
- Pod(容器组)是 Kubernetes 中最小的可部署单元。
- 一个 Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络 IP 地址、以及一些确定容器该如何运行的选项。
- Pod 容器组代表了 Kubernetes 中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。
- 一个Pod是容器环境下的“逻辑主机”,它可能包含一个或者多个紧密相连的应用,这些应用可能是在同一个物理主机或虚拟机上。
- Pod 的context可以理解成多个linux命名空间的联合:
PID 命名空间
同一个Pod中应用可以看到其它进程。
网络 命名空间
同一个Pod的中的应用对相同的IP地址和端口有权限。
IPC 命名空间
同一个Pod中的应用可以通过VPC或者POSIX进行通信。
UTS 命名空间
同一个Pod中的应用共享一个主机名称。
注:同一个Pod中的应用可以共享磁盘,磁盘是Pod级的,应用可以通过文件系统调用。
1.7.1 Pod创建流程
注:
- 用户提交创建Pod的请求,可以通过API Server的REST API ,也可用Kubectl命令行工具,支持Json和Yaml两种格式。
- API Server 处理用户请求,存储Pod数据到Etcd。
- Schedule通过和 API Server的watch机制,查看到新的Pod,尝试为Pod绑定Node。调度器用一组规则过滤掉不符合要求的主机,比如Pod指定了所需要的资源,那么就要过滤掉资源不够的主机,对上一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略进行调度;选择打分最高的主机,进行binding操作,结果存储到Etcd中。
- kubelet根据调度结果执行Pod创建操作。绑定成功后,会启动container。Scheduler会调用API Server的API在Etcd中创建一个bound pod对象,描述在一个工作节点上绑定运行的所有Pod信息。运行在每个工作节点上的kubelet也会定期与Etcd同步bound pod信息。
1.7.2 Pod的定义
可以通过kubectl explain pod 查看pod yaml定义的顶级属性,然后通过类似 kubectl explain pod.{顶级属性}查看二级属性的细节定义。
下面给出一个pod资源定义的样例,对pod的描述有一个初步了解。
#与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
apiVersion: v1
#该配置的类型,我们使用的是Pod
kind: Pod
#译名为元数据,即 Pod 的一些基本属性和信息
metadata:
#Pod 的名称
name: nginx-pod
#标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
labels:
#为该Deployment设置key为app,value为nginx的标签
app: nginx
#期望Pod实现的功能(即在pod中部署)
spec:
#生成container,与docker中的container是同一种
containers:
#container的名称
- name: nginx
#使用镜像nginx:1.7.9创建container,该container默认80端口可访问
image: nginx:1.7.9
保存为nginx-pod.yaml文件,通过kubectl apply -f nginx-pod.yaml启动pod。通过kubectl get pods -o wide查看pod的启动情况。
2. 服务发现、负载均衡、网络
Kubernetes 中 Service 是一个 API 对象,通过 kubectl + YAML 定义一个 Service,可以将符合 Service 指定条件的 Pod ,作为可通过网络访问的服务提供给服务调用者。
Service 是 Kubernetes 中的一种服务发现机制:
Pod 有自己的 IP 地址
Service 被赋予一个唯一的 dns name
Service 通过 label selector 选定一组 Pod
Service 实现负载均衡,可将请求均衡分发到选定这一组 Pod 中例如,假设您有一组 Pod:
每个 Pod 都监听 9376 TCP 端口
每个 Pod 都有标签 app=MyApp下面文件可用来创建一个 Service(名字为 my-service):
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
对应的效果为:
Service 从自己的 IP 地址和 port 端口接收请求,并将请求映射到符合条件的 Pod 的 targetPort。
为了方便,默认 targetPort 的取值 与 port 字段相同
- Kubernetes 将为该 Service 分配一个 IP 地址(ClusterIP 或 集群内 IP),供 Service Proxy 使用
- Kubernetes 将不断扫描符合该 selector 的 Pod,并将最新的结果更新到与 Service 同名 my-service 的 Endpoint 对象中
2.1 服务代理
Kubernetes 集群中的每个节点都运行了一个 kube-proxy。
负责为 Service(ExternalName 类型的除外)提供虚拟 IP 访问。
Kubernetes 支持三种 proxy mode(代理模式),他们的版本兼容性如下:
代理模式 | K8S版本 | 是否默认 |
---|---|---|
User space proxy mode | v1.0 + | |
lptables proxy mode | v1.1 + | 默认 |
lpvs proxy mode | v1.8 + |
2.1.1 User space 代理模式
kube-proxy 监听 kubernetes master以获得添加和移除 Service / Endpoint 的事件
kube-proxy 在其所在的节点(每个节点都有 kube-proxy)上为每一个 Service 打开一个随机端口
kube-proxy 安装 iptables 规则,将发送到该 Service 的 ClusterIP(虚拟 IP)/ Port 的请求重定向到该随机端口
任何发送到该随机端口的请求将被代理转发到该 Service 的后端 Pod 上(kube-proxy 从 Endpoint 信息中获得可用 Pod)
kube-proxy 在决定将请求转发到后端哪一个 Pod 时,默认使用 round-robin(轮询)算法,并会考虑到 Service 中的 SessionAffinity 的设定
2.1.2 Iptables 代理模式--默认模式
kube-proxy 监听 kubernetes master 以获得添加和移除 Service / Endpoint 的事件
kube-proxy 在其所在的节点(每个节点都有 kube-proxy)上为每一个 Service 安装 iptable 规则
iptables 将发送到 Service 的 ClusterIP / Port 的请求重定向到 Service 的后端 Pod 上
对于 Service 中的每一个 Endpoint,kube-proxy 安装一个 iptable 规则。默认情况下,kube-proxy 随机选择一个 Service 的后端 Pod
iptables proxy mode 的优点:
- 更低的系统开销
- 在 linux netfilter 处理请求,无需在 userspace 和 kernel space 之间切换
- 更稳定
与 user space mode 的差异:
- 使用 iptables mode 时 如果第一个 Pod 没有响应,则创建连接失败
- 使用 user space mode 时如果第一个 Pod 没有响应,kube-proxy 会自动尝试连接另外一个后端 Pod您可以配置 Pod 就绪检查(readiness probe)确保后端 Pod 正常工作。
- 在 iptables 模式下 kube-proxy 将只使用健康的后端 Pod,从而避免了 kube-proxy 将请求转发到已经存在问题的 Pod 上。
IPVS 代理模式
kube-proxy 监听 kubernetes master 以获得添加和移除 Service / Endpoint 的事件
kube-proxy 根据监听到的事件,调用 netlink 接口,创建 IPVS 规则;并且将 Service/Endpoint 的变化同步到 IPVS 规则中
当访问一个 Service 时,IPVS 将请求重定向到后端 Pod
IPVS proxy mode 基于 netfilter 的 hook 功能,与 iptables 代理模式相似,但是 IPVS 代理模式使用 hash table 作为底层的数据结构,并在 kernel space 运作。
这就意味着:
IPVS 代理模式可以比 iptables 代理模式有更低的网络延迟,在同步代理规则时,也有更高的效率
与 user space 代理模式 / iptables 代理模式相比,IPVS 模式可以支持更大的网络流量IPVS 提供更多的负载均衡选项:
rr: round-robin lc: least connection (最小打开的连接数) dh: destination hashing sh: source hashing sed: shortest expected delay nq: never queue
在所有的代理模式中,发送到 Service 的 IP:Port 的请求,将被转发到一个合适的后端 Pod,而无需调用者知道任何关于 Kubernetes/Service/Pods 的细节。
2.2服务发现--DNS
安装了K8s插件-- DNS 服务,Core DNS (opens new window)。Kubernetes 集群中就会运行一组 DNS Pod,配置了对应的 Service,并由 kubelete 将 DNS Service 的 IP 地址配置到节点上的容器中以便解析 DNS names。CoreDNS 监听 Kubernetes API 上创建和删除 Service 的事件,并为每一个 Service 创建一条 DNS 记录。集群中所有的 Pod 都可以使用 DNS Name 解析到 Service 的 IP 地址。
例如:
名称空间 my-ns 中的 Service my-service,将对应一条 DNS 记录 my-service.my-ns。
名称空间 my-ns 中的Pod可以直接 nslookup my-service (my-service.my-ns 也可以)。
其他名称空间的 Pod 必须使用 my-service.my-ns。my-service 和 my-service.my-ns 都将被解析到 Service 的 Cluster IP。
2.2.1Service 类型
Kubernetes 中可以通过不同方式发布 Service,通过 ServiceType 字段指定。
ServiceType 可选值 | 描述 | 是否默认 |
---|---|---|
ClusterIP | 通过集群内部的一个Cluster IP 地址暴露 Service,只在集群内部可以访问。 | 默认值。 |
NodePort | 通过每一个节点上的静态端口(NodePort)暴露 Service,同时自动创建 ClusterIP 类型的访问方式。 在集群内部通过(ClusterIP):(Port) 访问, 在集群外部通过 (NodeIP):(NodePort) 访问。 |
|
LoadBalancer | 通过云服务供应商(AWS、Azure、GCE 等)的负载均衡器在集群外部暴露 Service,同时自动创建 NodePort 和 ClusterIP 类型的访问方式。LoadBalancer是将.spec.type 字段设置为 LoadBalancer,Kubernetes 将为该Service 自动创建一个负载均衡器。 负载均衡器的创建操作异步完成,您可能要稍等片刻才能真正完成创建,负载均衡器的信息将被回写到 Service 的.status.loadBalancer 字段。 在集群内部通过 (ClusterIP):(Port) 访问 在集群外部通过 (NodeIP):(NodePort) 访问 在集群外部通过 (LoadBalancerIP):(Port) 访问。 |
|
ExternalName | 将 Service 映射到 externalName 指定的地址(例如:foo.bar.example.com),返回值是一个 CNAME 记录。不使用任何代理机制。ExternalName 类型的 Service 映射到一个外部的 DNS name,而不是一个 pod label selector。可通过 spec.externalName 字段指定外部 DNS name。 | |
External IP | 如果有外部 IP 路由到 Kubernetes 集群的一个或多个节点,Kubernetes Service 可以通过这些 externalIPs 进行访问。externalIP 需要由集群管理员在 Kubernetes 之外配置。在 Service 的定义中, externalIPs 可以和任何类型的 .spec.type 一通使用。 |
2.2.2Ingress
Ingress 是 Kubernetes 的一种 API 对象,将集群内部的 Service 通过 HTTP/HTTPS 方式暴露到集群外部,并通过规则定义 HTTP/HTTPS 的路由。
Ingress 具备如下特性:
- 集群外部可访问的 URL.
- 负载均衡。
- SSL Termination.
- 按域名路由(name-based virtual hosting).
Ingress 的例子如下所示:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: # Ingress 的名字,仅用于标识 name: my-ingress-for-nginx spec: # Ingress 中定义 L7 路由规则 rules: # 根据 virtual hostname 进行路由(请使用您自己的域名) - host: demo.my-company.com http: # 按路径进行路由 paths: - path: / backend: # 指定后端的 Service 为之前创建的 nginx-service serviceName: nginx-service servicePort: 80
描述:
Ingress Controller 通常是部署在集群中的一个 Deployment,并且通过 NodePort Service 暴露自己的端口,使得用户可以在集群外通过其 NodePort 访问到 Ingress Controller。
假设该端口为32351,并且 demo.my-company.com 这个域名被解析到集群中某一个节点的 IP(或者被配置到浏览器所在机器的 hosts 文件),则当用户在浏览器中输入地址 http://demo.my-company.com:32351 时:请求被转发到集群某节点的32351节点端口。根据 Service 的定义,请求被转发到 Ingress Controller 的 Web 端口。Ingress Controller 根据请求域名 demo.my-company.com 以及请求路径,匹配到 Ingress 定义中该请求应该被路由到 nginx-service的80端口。Ingress Controller 执行 L7 路由转发,将请求发送到 nginx-service 的80端口。
2.3 K8s网络
容器网络
容器网络是容器选择连接到其他容器、主机和外部网络(如Internet)的机制。
CNI意为容器网络接口,它是一种标准的设计,为了让用户在容器创建或销毁时都能够更容易地配置容器网络。目前最流行的CNI插件是Flannel。Flannel插件既可以确保满足Kubernetes的网络要求,又能为Kubernetes集群管理员提供他们所需的某些特定的网络功能。容器的Runtime提供了各种网络模式,每种模式都会产生不同的体验。
例如,Docker默认情况下可以为容器配置以下网络:
none
将容器添加到一个容器专门的网络堆栈中,没有对外连接。
host
将容器添加到主机的网络堆栈中,没有隔离。
default bridge
默认网络模式。每个容器可以通过IP地址相互连接。
自定义网桥
用户定义的网桥,具有更多的灵活性、隔离性和其他便利功能。
Docker还可以让用户通过其他驱动程序和插件,来配置更高级的网络(包括多主机覆盖网络)。
3. 各大发行版本K8S(教程)对比:
K0S
K0S 可以认为是一个下游的 Kubernetes 发行版,与原生 Kubernetes 相比,k0s 并未阉割大量 Kubernetes 功能;k0s 主要阉割部分基本上只有树内 Cloud provider,其他的都与原生 Kubernetes 相同。
MicroK8S (教程-教程2)
是目前最小、最快与Kubernetes全面兼容的集群系统,它不需要VirtualBox。主要用于工作站和小型团队,但是目前镜像并没有与snap打包在一起,还在gcr.io上,国内下载上还是有问题。MicroK8S适合离线开发、原型开发和测试,尤其是运行VM作为小、便宜、可靠的K8S用于CI/CD。支持arm架构,也适合开发 IoT 应用,通过 MicroK8S 部署应用到小型Linux设备上。
Kind
Kind 是另一个 Kubernetes SIG 项目,但与 Minikube 相比有很大不同。顾名思义,它将集群移动到 Docker 容器中。与生成 VM 相比,这导致启动速度明显加快。
创建集群与 minikube 的方法非常相似。执行kind create cluster,然后你就可以开始了。通过使用不同的名称(--name) kind,您可以并行创建多个实例。
K3S (教程-未验证)
K3S是一个轻量级的Kubernetes环境,是Kubernetes的官方发行版。由Rancher Labs开发,它以小于40MB的二进制文件形式提供。由于重量轻,它有望用于边缘计算,物联网和CI等应用。
而之所以称为 k3s 是因为相对 k8s 裁剪了如下5个部分:
- 过时的功能和非默认功能
- Alpha 功能
- 内置的云提供商插件
- 内置的存储驱动
- Docker
K3D
k3d 是一个开源实用的应用程序,旨在轻松地在 docker 容器中运行高度可用的轻量级 k3s 集群。
使用 k3d,您可以轻松创建单节点和多节点 k3s 集群,以在 Kubernetes 上进行无缝本地开发和测试。通过在 Kubernetes 中运行,k3d 还可以帮助您轻松扩展和缩减工作负载。
k3d 是 k3s 的包装器,顾名思义就是 docker 上的 k3s。
Minikube (教程-未验证)
Minikube是一个 Kubernetes SIG 项目,已经启动三年多了。它采用生成虚拟机的方法,该虚拟机本质上是一个单节点 K8s 集群。由于支持大量管理程序,它可以在所有主要操作系统上使用。这也允许您并行创建多个实例。
从用户的角度来看,minikube 是一个非常适合初学者的工具。您使用启动集群命令 minikube start,等待几分钟,您kubectl就可以开始了。要指定 Kubernetes 版本,您可以使用该--kubernetes-version标志。可在此处找到受支持版本的列表。默认情况下,Minikube 创建一个单节点集群,但您可以在启动时使用--nodes 标志设置更多节点。
Minikube 的主要优点是它非常轻便,并且非常易于安装和使用。
Minikube 的主要缺点是它仅为测试而设计。它不是运行生产级集群的实用解决方案
功能对比
K0s | MicroK8s | Kind | K3S + K3D | Minikube | |
---|---|---|---|---|---|
管理节点创建/删除 | ✗ | ✗ | ✓ | ✓ | ✓ |
节点管理系统 | ✗ | ✗ | docker | docker | virtualbox, vmwarefusion, kvm2, vmware, none, docker, podman, ssh |
容器运行时 | containerd | containerd | containerd, CRI-O | CRI-O | Docker, CRI-O, containerd |
默认 CNI | Calico | Calico | kindnet | Flannel | bridge |
挂载主机操作系统的文件系统 | HostPath | HostPath | HostPath + docker mount | HostPath + docker mount | HostPath + … (depends on the virtualization system) |
插件 | ✗ | ✓ | ✗ | ✗ | ✓ |
非特权用户创建群集的能力 | ✗ | ✗ | ✓ | ✓ | ✓ |
Vanilla Kubernetes | ✓ | ✓ | ✓ | ✗ | ✓ |
3.1安装示例
kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具,这个工具
能通过两条指令完成一个 kubernetes 集群的部署:
第一、创建一个 Master 节点 kubeadm init
第二, 将 Node 节点加入到当前集群中 $ kubeadm join <Master节点的IP和端口>
3.1.1 准备内容
-3台虚拟机 11, 12, 13
安装CentOS7系统
- 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像
- 禁止 swap 分区
搭建参考这里:https://blog.csdn.net/BogerPeng/article/details/124908685
3.1.2 三台服务器系统初始化
- 1). 关闭防火墙:
firewall-cmd --state #查看防火墙状态
systemctl stop firewalld
systemctl disable firewalld
为什么关闭防火墙,请参考:https://www.q578.com/s-5-2615546-0/
- 2). 关闭 selinux:
[root@sharplee ~]# sestatus
SELinux status: disabled
# 永久
sed -i 's/enforcing/disabled/' /etc/selinux/config
# 临时
setenforce 0
- 3). 关闭 swap - K8S的要求
#(1)临时关闭swap分区, 重启失效;
swapoff -a
#(2)永久关闭swap分区
sed -ri 's/.*swap.*/#&/' /etc/fstab
#(3)输入命令 free -mh 查看一下分区的状态:
[root@k8shost admin]# sed -ri 's/.*swap.*/#&/' /etc/fstab
[root@k8shost admin]# sudo reboot
[root@k8shost admin]# free -mh
total used free shared buff/cache available
Mem: 1.8G 777M 331M 35M 710M 859M
Swap: 0B 0B 0B
- 4). 主机名:
$ hostnamectl set-hostname <hostname>
## 11 机器
hostnamectl set-hostname k8smaster
## 12 机器
hostnamectl set-hostname k8snode1
## 13 机器
hostnamectl set-hostname k8snode2
- 5). 添加 hosts
cat > /etc/hosts << EOF
192.168.137.11 k8smaster
192.168.137.12 k8snode1
192.168.137.13 k8snode2
EOF
- 6). br_netfilter模块加载
# 查看
lsmod |grep br_netfilter
#临时添加
modprobe br_netfilter
#永久添加
----------------------------------------------------------------
cat > /etc/rc.sysinit << EOF
#!/bin/bash
for file in /etc/sysconfig/modules/*.modules ; do
[ -x $file ] && $file
done
EOF
cat > /etc/sysconfig/modules/br_netfilter.modules << EOF
modprobe br_netfilter
EOF
chmod 755 /etc/sysconfig/modules/br_netfilter.modules
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
----------------------------------------------------------------
# 生效
sysctl --system
# 测试重启设置是否有效
firewall-cmd --state
sestatus
free -mh
ifconfig
cat /etc/hosts
lsmod |grep br_netfilter
sysctl -p /etc/sysctl.d/k8s.conf
- 7). 时间同步:
yum install ntpdate -y
timedatectl set-timezone Asia/Shanghai
ntpdate time.windows.com
- 8). 安装 snap
yum install epel-release -y
yum install yum-plugin-copr -y
yum copr enable ngompa/snapcore-el7 -y
yum install snapd -y
systemctl enable --now snapd.socket
ln -s /var/lib/snapd/snap /snap
- 9). 系统环境变量修改/etc/environment
cat > /etc/environment << EOF
LANG=zh_CN.UTF-8
LC_ALL=zh_CN.UTF-8
EOF
- 10).设置环境变量 + 系统代理
否则会报错 -bash: microk8s.kubectl: command not found
vi /etc/profile
export PATH=$PATH:/snap/bin
export proxy=192.168.137.1:7890
export http_proxy=$proxy
export https_proxy=$proxy
export ftp_proxy=$proxy
export no_proxy="localhost, 127.0.0.1, ::1"
source /etc/profile
env | grep pro/path
- 可选1). 免密登录
只在master执行
ssh-keygen -t rsa
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.137.12
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.137.13
ssh 192.168.137.12
ssh k8snode2
- 可选2). 修改固定ip
vi /etc/sysconfig/network-scripts/ifcfg-eth0
systemctl restart network
ping 192.168.137.11
3.1.4 Microk8s 安装
# 查看 microk8s 信息
sudo snap info microk8s
# 安装
sudo snap install microk8s --classic --channel=1.26/edge
sudo snap install microk8s --classic --channel latest/edge/test-containerd
#卸载
sudo snap remove microk8s
#彻底清除
sudo snap remove microk8s --purge
#重命名
sudo snap alias microk8s.kubectl kubectl
sudo snap alias microk8s.ctr ctr
##俩不常用的
sudo snap alias microk8s.helm helm
sudo snap alias microk8s.helm3 helm3
#常用命令
snap restart microk8s
microk8s version
microk8s inspect
microk8s stop
microk8s start
microk8s config:显示 kubernetes 配置文件
microk8s istioctl:与 istio 服务交互;需要启用 istio 插件
microk8s reset:将基础架构重置为干净状态
#检测服务状态
microk8s status --wait-ready
microk8s status
#附加插件
microk8s enable dashboard ingress dns
#去除插件
microk8s disable dashboard ingress dns
#添加节点
microk8s add-node
kubectl get all
kubectl get nodes
#查看状态
kubectl get pods --all-namespaces
#查看详情
kubectl describe pod --all-namespaces
kubectl describe node k8smaster
#查看一个pod具体信息
kubectl describe pod -n kube-system kubernetes-XXXXXX
#使用本地映射访问 dashboard
#找到pod名
kubectl get pods --all-namespaces | grep dashboard
#查看pod的开放端口, 一般是8443
kubectl describe --namespace kube-system pod/kubernetes-dashboard-6fd7f9c494-dgxlj
#将pod的开放端口映射到本地,这个转发命令行不能关闭
kubectl port-forward --namespace=kube-system --address=0.0.0.0 pod/kubernetes-dashboard-XXXXX 8443:8443
#使用token访问
kubectl get secrets --all-namespaces | grep dashboard-token
#查看镜像
ctr images ls
#镜像下载失败处理
1.
ctr image pull k8s.gcr.io/pause:3.1
ctr image pull k8s.gcr.io/metrics-server/metrics-server:v0.5.2
1.1证书无效
https://github.com/canonical/microk8s/issues/1046
1.2其他版本未测试
ctr image pull k8s.gcr.io/pause:3.7
ctr image pull registry.k8s.io/pause:3.7
microk8s refresh-certs
kubectl describe pod --all-namespaces| grep "Pulling image"
snap restart microk8s
https://github.com/canonical/microk8s/issues
2.
https://blog.csdn.net/gchan/article/details/120865800
sudo snap install docker
sudo curl -L "https://raw.githubusercontent.com/OpsDocker/pullk8s/main/pullk8s.sh" -o /usr/local/bin/pullk8s
sudo chmod +x /usr/local/bin/pullk8s
pullk8s check --microk8s
pullk8s pull k8s.gcr.io/pause:3.7 --microk8s
3.
https://microk8s.io/docs/registry-private#configure-registry-mirrors-7
在特定情况下(例如地理限制、网络防火墙),某些映像注册表可能不可用。例如,对于中国大陆用户不可用,而是使用 例如的镜像。k8s.gcr.ioregistry.cn-hangzhou.aliyuncs.com/google_containers 要为 配置注册表镜像并将其指向 ,需要进行以下配置:k8s.gcr.ioregistry.cn-hangzhou.aliyuncs.com/google_containers
# create a directory with the registry name
sudo mkdir -p /var/snap/microk8s/current/args/certs.d/registry.k8s.io
# create the hosts.toml file pointing to the mirror
echo '
server = "registry.k8s.io"
[host."https://registry.aliyuncs.com/v2/google_containers"]
capabilities = ["pull", "resolve"]
override_path = true
' | sudo tee -a /var/snap/microk8s/current/args/certs.d/registry.k8s.io/hosts.toml
参考:
[1]学习K8S,读完这篇就够了! - https://www.bilibili.com/read/cv18627327
[2]Minikube vs. kind vs. k3s vs k3d vs MicroK8s - https://blog.csdn.net/xixihahalelehehe/article/details/128953310
[3]最小化K8S环境部署之MicroK8S - https://blog.51cto.com/kaliarch/4910030
[4]轻量级 Kubernetes K3S初探 - https://www.infoq.cn/article/0c7viUfLrxOZeh7qlRBT
[5]轻量级 K8S 环境、本地 K8S 环境Minikube - https://blog.csdn.net/crazymakercircle/article/details/128800909
[6]用于本地实验的小型 Kubernetes:k0s、MicroK8s、kind、k3s 和 Minikube - https://zhuanlan.zhihu.com/p/594206344
[7]K8S 学习笔记一 基础概念和环境搭建 - https://blog.csdn.net/BogerPeng/article/details/124892243
[8]MicroK8s 安装 - https://www.likecs.com/show-307304024.html
[9]MicroK8s 安装 - https://soulteary.com/2022/10/15/lightweight-and-highly-available-k8s-cluster-construction-solution-microk8s.html