k8s 学习实战(一)
概述
本次专题我们将分两讲来学习 k8s 入门实战,内容分配如下
第一讲
虚拟机环境搭建
k8s 中的一些概念介绍
第二讲
实战
通过 kubeadmin 搭建 k8s 集群
不同类型的 pod 创建
实战中的坑点总结
环境搭建
本次实验环境采用 windows11 上通过 Oracle VM VirtualBox 搭建虚拟机的方式进行 k8s 的环境搭建
Oracle VM 版本 7.0
虚拟机镜像版本 CentOS-7.6-x86_64-Minimal-1810
虚拟机重点配置
master 节点资源稍微高一点,2C/4G。node 节点资源可以稍微低一点 1C/2G
网络配置
网卡一配置 NAT 网络模式,主要让虚拟机可以联网
网络二 配置 http only,并手动配置主机网络
网络设置
vim /etc/sysconfig/network-scripts/ifcfg-enp0s3
确认 ONBOOT=yes
systemctl restart network
基本概念介绍
Docker
容器技术起源于 docker
Docker 架构是一个 C/S 架构,docker Damon 负责镜像的拉去和本地存储
k8s
Kubernetes 分解出一些松耦合的对象,才能简化系统模型,减轻用户的心智负担
K8s 架构图
Kubernetes 的高明之处就在于把这些都抽象化规范化了
k8s 环境搭建(minikube)
minikube 只能够搭建 Kubernetes 环境
要操作 Kubernetes,还需要另一个专门的客户端工具“kubectl”
minikube start --kubernetes-version=v1.23.3 --image-mirror-country='cn' --force
K8S 概念脑图
K8S 集群环境搭建(kubeadmin)
我们在第二讲会介绍
Deployment
为什么会出现 deployment?
Pod 只能管理容器,不能管理自身,所以就出现了 Deployment,由它来管理 Pod
Deployment 里有三个关键字段,其中的 template 和 Job 一样,定义了要运行的 Pod 模板
replicas 字段定义了 Pod 的“期望数量”,Kubernetes 会自动维护 Pod 数量到正常水平
selector 字段定义了基于 labels 筛选 Pod 的规则,它必须与 template 里 Pod 的 labels 一致
创建 Deployment 使用命令 kubectl apply,应用的扩容、缩容使用命令 kubectl scale
Deployment 模板
也可以通过代码创建
export out="--dry-run=client -o yaml"
kubectl create deploy ngx-dep --image=nginx:alpine $out
Deamonset
DaemonSet,它会在 Kubernetes 集群的每个节点上都运行一个 Pod,就好像是 Linux 系统里的“守护进程”(Daemon)
DaemonSet 的目标是为集群里的每个节点部署唯一的 Pod,常用于监控、日志等业务
DaemonSet 的 YAML 描述与 Deployment 非常接近,只是没有 replicas 字段
污点(taint)和容忍度(toleration)
kubectl describe node #查看节点状态
kubectl taint node master node-role.kubernetes.io/master:NoSchedule- ##去除污点
kubectl taint node master node-role.kubernetes.io/master:NoSchedule ##master 节点添加污点
toleration #添加到 pod 创建的 yaml 的申明文件中
Service
Pod 的生命周期很短暂,会不停地创建销毁,所以就需要用 Service 来实现负载均衡,它由 Kubernetes 分配固定的 IP 地址,能够屏蔽后端的 Pod 变化
Service 对象使用与 Deployment、DaemonSet 相同的“selector”字段,选择要代理的后端 Pod,是松耦合关系
基于 DNS 插件,我们能够以域名的方式访问 Service,比静态 IP 地址更方便。
名字空间是 Kubernetes 用来隔离对象的一种方式,实现了逻辑上的对象分组,Service 的域名里就包含了名字空间限定。
Service 的默认类型是“ClusterIP”,只能在集群内部访问,如果改成“NodePort”,就会在节点上开启一个随机端口号,让外界也能够访问内部的服务。(nodePort 比较简单,但是也有一些弊端。但是 dashboard 的部署我就采用了 NodePort 的方式进行部署的 pod)
本质上 service 是 kube-proxy 控制的四层负载均衡,在 TCP/IP 协议栈上转发流量,运行架构
Ingress
Service 是四层负载均衡,能力有限,所以就出现了 Ingress,它基于 HTTP/HTTPS 协议定义路由规则
Ingress 只是规则的集合,自身不具备流量管理能力,需要 Ingress Controller 应用 Ingress 规则才能真正发挥作用
Ingress Class 解耦了 Ingress 和 Ingress Controller,我们应当使用 Ingress Class 来管理 Ingress 资源
最流行的 Ingress Controller 是 Nginx Ingress Controller,它基于经典反向代理软件 Nginx
docker-compose
Kubernetes 源自 Docker 又超越了 Docker,依靠着它的 master/node 架构,掌控成百上千台的计算节点,然后使用 YAML 语言定义各种 API 对象来编排调度容器,实现了对现代应用的管理
docker-compose 也使用 YAML 来描述容器,但语法语义更接近 Docker 命令行
docker-compose YAML 里的关键概念是“service”,它是一个容器化的应用
docker-compose 的命令与 Docker 类似,比较常用的有 up、ps、down,用来启动、查看和停止应用
命令行 如: docker-compose -f wp-compose.yml up -d
PersistentVolume
解决数据持久化问题
概念
PersistentVolume 简称为 PV,是 Kubernetes 对存储设备的抽象,由系统管理员维护,需要描述清楚存储设备的类型、访问模式、容量等信息
PersistentVolumeClaim 简称为 PVC,代表 Pod 向系统申请存储资源,它声明对存储的要求,Kubernetes 会查找最合适的 PV 然后绑定
StorageClass 抽象特定类型的存储系统,归类分组 PV 对象,用来简化 PV/PVC 的绑定过程
HostPath 是最简单的一种 PV,数据存储在节点本地,速度快但不能跟随 Pod 迁移
申明
PersistentVolumeClaim+NFS
在 Kubernetes 集群里,网络存储系统更适合数据持久化,NFS 是最容易使用的一种网络存储系统,要事先安装好服务端和客户端
可以编写 PV 手工定义 NFS 静态存储卷,要指定 NFS 服务器的 IP 地址和共享目录名。
使用 NFS 动态存储卷必须要部署相应的 Provisioner,在 YAML 里正确配置 NFS 服务器
动态存储卷不需要手工定义 PV,而是要定义 StorageClass,由关联的 Provisioner 自动创建 PV 完成绑定
YMAL
StatefulSet 对象管理有状态的应用
什么是有状态的应用
理论上任何应用都是有状态的
有的应用的状态信息不是很重要,即使不恢复状态也能够正常运行,这就是我们常说的“无状态应用”。“无状态应用”典型的例子就是 Nginx 这样的 Web 服务器,它只是处理 HTTP 请求,本身不生产数据(日志除外),不需要特意保存状态
因为重启而丢失了状态是绝对无法接受的,这样的应用就是“有状态应用”(redis,数据库)
StatefulSet 的 YAML 描述和 Deployment 几乎完全相同,只是多了一个关键字段 serviceName
要为 StatefulSet 里的 Pod 生成稳定的域名,需要定义 Service 对象,它的名字必须和 StatefulSet 里的 serviceName 一致
访问 StatefulSet 应该使用每个 Pod 的单独域名,形式是“Pod 名. 服务名”,不应该使用 Service 的负载均衡功能
在 StatefulSet 里可以用字段“volumeClaimTemplates”直接定义 PVC,让 Pod 实现数据持久化存储
YAML 定义
滚动更新
使用命令 kubectl scale,我们就可以轻松调整 Deployment 下属的 Pod 数量
滚动更新,使用 kubectl rollout 实现用户无感知的应用升级和降级
管理应用更新使用的命令是 kubectl rollout,子命令有 status、history、undo ,pause,resume, 等
版本回滚
kubectl rollout history deploy ${podName} #查看版本信息
kubectl rollout history deploy --revision=2 #回滚到指定的版本
Kubernetes 会记录应用的更新历史,可以使用 history --revision 查看每个版本的详细信息,也可以在每次更新时添加注解 kubernetes.io/change-cause
应用保障
创建容器有三大隔离技术:namespace、cgroup、chroot 。K8s 资源配额使用的是 cgroup 技术
probe
Pod 探测状态可以使用 Shell、TCP Socket、HTTP Get 三种方式,还可以调整探测的频率和超时时间等参数
集群可用保障
namespace
kubectl create ns test-ns #创建 namespace
kubectl get pod -n test-ns #查看某个 namespace 下的 pod
kubectl delete ns test-ns #删除指定的 namespace
名字空间是一个逻辑概念,没有实体,它的目标是为资源和对象划分出一个逻辑边界,避免冲突
ResourceQuota 对象可以为名字空间添加资源配额,限制全局的 CPU、内存和 API 对象数量
LimitRange 对象可以为容器或者 Pod 添加默认的资源配额,简化对象的创建工作
可观测性和自动扩缩容
Metrics Server 是一个 Kubernetes 插件,能够收集系统的核心资源指标,相关的命令是 kubectl top
Prometheus 是云原生监控领域的“事实标准”,用 PromQL 语言来查询数据,配合 Grafana 可以展示直观的图形界面,方便监控
HorizontalPodAutoscaler 实现了应用的自动水平伸缩功能,它从 Metrics Server 获取应用的运行指标,再实时调整 Pod 数量,可以很好地应对突发流量
prometheus 架构图
网络通信插件
Kubernetes 使用的是“IP-per-pod”网络模型,每个 Pod 都会有唯一的 IP 地址,所以简单易管理
CNI 是 Kubernetes 定义的网络插件接口标准,按照实现方式可以分成“Overlay”“Route”和“Underlay”三种,常见的 CNI 插件有 Flannel、Calico 和 Cilium
Flannel 支持 Overlay 模式,它使用了 cni0 网桥和 flannel.1 设备,本机通信直接走 cni0,跨主机通信会把原始数据包封装成 VXLAN 包再走宿主机网卡发送,有性能损失
Calico 支持 Route 模式,它不使用 cni0 网桥,而是创建路由规则,把数据包直接发送到目标网卡,所以性能高
版权声明: 本文为 InfoQ 作者【BeyondLife】的原创文章。
原文链接:【http://xie.infoq.cn/article/cba2a3eb69b1f4c0aad3648a4】。文章转载请联系作者。
评论