《每天5分钟玩转Kubernetes》
一、先把Kubernetes跑起来
1.2 创建kubernetes集群
命令 | 操作 |
---|---|
minikube start |
启动minikube |
minikube status |
查看minikube状态 |
kubectl get nodes |
查看集群节点 |
kubectl cluster-info |
查看集群信息 |
1.3 部署应用
|
|
选项 | 说明 |
---|---|
--image |
指定镜像 |
--port |
设置应用对外服务的端口 |
关键概念
概念 | 说明 | 备注 |
---|---|---|
Deployment | 可以理解为应用 | |
Pod | 一个或多个容器的集合,同一个Pod中所有容器共享IP地址和Port空间 | Kubernetes中最小的调度单元 |
|
|
修正,书籍直接创建pod,本笔记修正为创建deployment,应该使用
1
k create deployment kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --replicas=2
1.4 访问应用
默认情况下所有Pod只能在集群内部访问,需要通过Service暴露服务
|
|
使用命令kubectl get services
查看服务
名称 | 说明 |
---|---|
kubernetes | 集群的默认服务 |
kubernetes-bootcamp | 通过kubectl expose 创建的服务,8080是暴露的端口,另外一个是随机份配的 |
1.5 Scale应用
|
|
1.6 滚动更新
当前应用使用的是v1版本,现在需要更新为v2版本
|
|
回退到v1版本
|
|
二、重要概念
概念 | 说明 |
---|---|
Cluster | 是计算、存储和网络资源的集合,K8S利用这些资源云星宇各种基于容器的应用 |
Master | 是集群的大脑,负责调度应用,维护集群状态,实现集群伸缩等功能 |
Node | 职责是运行容器的应用,Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期 |
Pod | 是Kubernetes中最小的调度单元,一个Pod中可以包含一个或多个容器,Pod中的容器共享IP地址和Port空间,可以通过localhost通信 |
Controller | 通常K8S不直接创建Pod,而是通过Controller管理Pod,例如Deployment、ReplicaSet、DaemonSet、StatefulSet、Job等 |
Service | 是Pod的抽象,可以将一组Pod封装成一个Service,Service定义了外接方位一组特定Pod的方式,Service有自己的IP和端口,为Pod提供了负载均衡 |
Namespace | 将一个物理的Cluster逻辑上分为多个虚拟Cluster,可使用kubectl get namespaces 查看所有namespace |
K8S中Pod的解读
概念 | 说明 |
---|---|
目的 | K8S引入Pod的目的是为了解决容器间通信的问题 |
使用方式 | 运行单一容器(一个Pod运行 一个容器,但K8S管理的还是Pod,而不是容器) 、运行多个容器 |
放到一Pod中的容器 | 通常是紧密耦合的容器,并且需要直接共享资源,比如一个容器负责应用,另一个容器负责日志收集 |
K8S中的Controller解读
概念 | 说明 |
---|---|
Deployment | 最常见的Controller,可以管理Pod的多个副本 |
ReplicaSet | 实现了Pod的多副本管理,使用Deployment会自动创建ReplicaSet,通常不直接使用ReplicaSet |
DaemonSet | 用于每个Node最多只能运行一个Pod的场景,比如运行日志收集器 |
StatefulSet | 能够保证Pod的每个副本在整个生命周期中名称是不变的 |
Job | 用于运行一次性任务,比如批处理任务 |
三、部署K8S Cluster
3.1 安装Docker
所有节点都需要安装Docker
|
|
3.2 安装kubelet、kubeadm、kubectl
工具 | 功能 | 部署节点 |
---|---|---|
kubelet | 运行在每个Node上,负责Pod的创建、启停等功能 | 所有Node |
kubeadm | 用于初始化集群 | Master |
kubectl | 用于管理集群 | Master |
书籍资料不作为参考,请自行查找部署方案
3.3 初始化Master
3.3.1 初始化Master
|
|
参数 | 说明 |
---|---|
–apiserver-advertise-address | 指定Master的的哪个interface与Cluster的其他节点通信 |
–pod-network-cidr | 指定Pod的IP地址范围,Pod的IP地址将从这个范围中分配 |
3.3.3 安装Pod网络
要让Cluster中的Pod能够互相通信,需要安装Pod网络,Pod网络是一种特殊的网络,它为Pod提供了一个IP地址,使得Pod能够互相通信
|
|
3.3.4 添加k8s-node1和k8s-node2
|
|
token是kubeadm init生成的,可以通过
kubeadm token list
查看
四、Kubernetes架构
4.1 Master节点
包含如下组件
组件名称 | 别称 | 说明 |
---|---|---|
API Server | kube-apiserver | 提供HTTP Rest接口,是集群控制的入口,所有资源的增删改查都是通过它来完成的,它会把资源的状态保存到etcd中 |
Scheduler | kube-scheduler | 负责Pod的调度,它会根据资源的使用情况和其他约束条件将Pod调度到合适的Node上运行,调度策略是可配置的 |
Controller Manager | kube-controller-manager | 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等,它是一个Master中的Daemon,每个Daemon都是一个独立的控制器,分别负责不同的功能 |
etcd | etcd | 分布式键值存储,用于保存集群的状态,比如Pod的状态、Service的状态等,etcd是一个独立的进程,它可以单独部署,也可以和Master部署在一起 |
Pod网络 | Pod能互相通信的基础,flannel是其中一个可选方案 |
4.2 Node节点
包含如下组件
组件名称 | 说明 |
---|---|
kubelet | 当Scheduler确定在某个Node上运行Pod后,会将Pod的具体配置信息(image、volume等)发送给该节点的kubelet,kubelet负责Pod的创建、启停等操作 |
Proxy | 负责为Service提供cluster内部的服务发现和负载均衡,它会监控Service和Endpoint的变化,并根据变化更新规则,从而保证Service的访问质量 |
Pod网络 | Pod能互相通信的基础,flannel是其中一个可选方案 |
4.3 完整的架构图
几乎所有的Kubernetes组件本身也运行在Pod中,通过如下命令查看(其中kube-dns组件为Cluster提供DNS服务)
kubelet是唯一没有以容器形式运行的Kubernetes组件,它在Ubuntu中通过Systemd服务运行
|
|
4.4 用例子把它们串起来
|
|
修正,应该为
kubectl create deployment httpd-app --image=httpd --replicas=2
kubectl
→ API Server
→ Controller
→ Scheduler
→ Pod网络
→ kubelet
→ Docker
五、运行应用
5.1 Deployment
5.1.1 运行Deployment
|
|
修正,应该为
kubectl create deployment nginx-deployment --image=nginx:1.7.9 --replicas=2
|
|
kubectl创建Deployment后,会自动创建ReplicaSet,ReplicaSet会根据Deployment的配置信息创建Pod
5.1.2 命令VS配置文件
K8S支持两种创建资源的方式
命令 | 配置文件 | |
---|---|---|
使用方式 | kubectl [command] | kubectl apply -f file |
可实现范围 | 创建资源、对资源更新、查看状态 | 创建资源、对资源更新 |
载体 | 命令 | 配置文件 |
优点 | 方便快捷 | 描述最终的状态、能够重复部署、方便管理 |
缺点 | 不利于管理 | 配置文件比较繁琐 |
5.1.3 Deployment配置文件简介
|
|
字段名称 | 说明 |
---|---|
apiVersion | API版本,Deployment的API版本为apps/v1,可以通过kubectl api-versions 查看 |
kind | 资源类型,Deployment的资源类型为Deployment,可以通过kubectl api-resources 查看 |
metadata | 元数据,包含Deployment的名称、标签、注释等信息,可以通过kubectl describe deployment nginx-deployment 查看 |
spec | 规格,包含Deployment的配置信息,包括Pod的副本数、Pod的模板、Pod的配置信息等,可以通过kubectl get deployment nginx-deployment -o yaml 查看 |
replicas | Pod的副本数,可以通过kubectl scale deployment nginx-deployment --replicas=3 修改 |
template | Pod的模板,包含Pod的元数据和规格,可以通过kubectl get deployment nginx-deployment -o yaml 查看 |
metadata | Pod的元数据,包含Pod的名称、标签、注释等信息,可以通过kubectl describe pod nginx-deployment-5c7588df5b-2q9q2 查看 |
spec | Pod的规格,包含Pod的配置信息,包括容器的镜像、容器的端口、容器的命令等,可以通过kubectl get pod nginx-deployment-5c7588df5b-2q9q2 -o yaml 查看 |
执行kubectl apply -f nginx.yaml
创建Deployment; 执行kubectl delete -f nginx.yaml
删除Deployment
5.1.4 伸缩
伸缩是指在线增加或减少Pod的副本数
修改Deployment的配置文件,将replicas的值修改为3,然后执行kubectl apply -f nginx.yaml
,即可实现伸缩
默认K8S不会将Pod调度到Master节点
5.1.5 FailOver
模拟k8s-node2故障,K8S会自动调度维持总副本数
5.1.6 用Label控制Pod的位置
label是key-value对
|
|
使用label控制Pod的位置,只需要在Deployment的配置文件中添加nodeSelector字段即可,disktype=ssd表示只将Pod调度到标签中包含disktype=ssd的节点上
|
|
5.2 DaemonSet
Controller类型 | 说明 |
---|---|
Deployment | 部署的副本Pod会分布在各个Node上,每个Node都可能运行好几个副本 |
DaemonSet | 部署的副本Pod会运行在每个Node上,但每个Node只运行一个副本 |
使用DaemonSet的场景:日志收集、监控、存储、守护进程等,例如k8s中本身用DaemonSet运行的系统组件:kubectl get daemonset --namespace=kube-system
5.3 Job
容器按照持续运行的时间可分为两类:服务类容器和工作类容器。
容器类型 | 说明 | 举例 | 对应Controller类型 |
---|---|---|---|
服务类容器 | 需要一直运行 | Web应用、数据库、缓存等 | Deployment、ReplicaSet和DaemonSet |
工作类容器 | 运行一次或定时运行 | 数据处理、定时任务、批处理等 | Job |
5.3.1 Pod失败的情况
restartPolicy字段配置失败的处理策略
restartPolicy | 说明 | 失败的处理 |
---|---|---|
OnFailure | 只有在容器退出状态码非0时才重启容器,一般用于工作类容器,如数据处理、定时任务、批处理等 | 只会创建一个Pod,体现在RESTARTS上 |
Never | 无论何种原因终止,都不重启容器,一般用于一次性容器,如数据处理、定时任务、批处理等 | 会创建多个Pod,直到SUCCESS |
5.3.2 Job的并行性
通过parallelism设置运行同时运行多个Pod,如下配置为:每次运行两个pod,直到总共6个Pod成功完成
|
|
5.3.3 定时Job
默认apiServer没有开启定时任务,需要在启动apiServer时添加
--runtime-config=batch/v2alpha1=true
参数,然后重启kubelet服务systemctl restart kubelet.service
通过schedule字段设置定时任务,如下配置为:每分钟运行一次(创建一个新的Pod),直到总共6个Pod成功完成
|
|
六、通过Service访问Pod
Pod是脆弱的,但应用是健壮的。
6.1 创建Service
创建Deployment
|
|
创建Service
|
|
查看Service与Pod的对应关系:Endpoints
|
|
6.2 Cluster IP底层实现
Cluster IP是虚拟IP,不是真实存在的IP,是kube-proxy进程通过iptables实现的
6.3 DNS访问Service
除了可以通过Cluster IP访问Service,还可以通过DNS访问Service
Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>
访问Service,例如:httpd-svc.default
tips1:同一namespace可忽略namespace_name
tips2: 不同namespace可通过
<SERVICE_NAME>.<NAMESPACE_NAME>.svc.cluster.local
访问Service,例如:httpd-svc.default.svc.cluster.local
tips3: 一个yaml中可以同时定义多个资源,使用
---
分割
6.4 外网如何访问Service
Service类型
类型 | 说明 |
---|---|
ClusterIP | 默认类型,只能在集群内部访问,外部无法访问,一般用于内部服务访问 |
NodePort | 在ClusterIP的基础上,绑定每个Node的端口,外部可以通过NodeIP:NodePort访问 |
LoadBalancer | 在NodePort的基础上,通过云服务商提供的负载均衡器,外部可以通过LoadBalancer的IP访问 |
配置为NodePort类型
需要注意发布了NodePort方式的Service依然无法访问:解决Windows/Mac版Desktop Docker中自带的K8s无法访问pod ip、Mac使用minikube发布,本地访问Service失败问题解决
|
|
七、Rolling Update
7.1 实践
通过httpd:2.2.31版本升级为httpd:2.2.32版本演示k8s升级
7.2 回滚
关键操作及属性 | 说明 |
---|---|
kubectl apply | 每次更新应用,k8s都会记录下当前的配置,保存为一个revision |
Deployment配置文件的revisionHistoryLimit | 设置保存的revision数量,默认为10 |
kubectl apply * –record | 记录每次更新的操作 |
kubectl rollout history deployment | 查看Deployment的更新历史 |
kubectl rollout undo deployment | 回滚到上一个版本 |