在 k8s 上进行部署前,首先需要了解一个基本概念 Deployment
Deployment 译名为 部署。在k8s中,通过发布 Deployment,可以创建应用程序 (docker image) 的实例 (docker container),这个实例会被包含在称为 Pod 的概念中,Pod 是 k8s 中最小可管理单元。
在 k8s 集群中发布 Deployment 后,Deployment 将指示 k8s 如何创建和更新应用程序的实例,master 节点将应用程序实例调度到集群中的具体的节点上。
创建应用程序实例后,Kubernetes Deployment Controller 会持续监控这些实例。如果运行实例的 worker 节点关机或被删除,则 Kubernetes Deployment Controller 将在群集中资源最优的另一个 worker 节点上重新创建一个新的实例。这提供了一种自我修复机制来解决机器故障或维护问题。
在容器编排之前的时代,各种安装脚本通常用于启动应用程序,但是不能够使应用程序从机器故障中恢复。通过创建应用程序实例并确保它们在集群节点中的运行实例个数,Kubernetes Deployment 提供了一种完全不同的方式来管理应用程序。
使用kubectl部署
创建文件 nginx-deployment.yaml,内容如下:
apiVersion apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind Deployment #该配置的类型,我们使用的是 Deployment
metadata#译名为元数据,即 Deployment 的一些基本属性和信息
name nginx-deployment #Deployment 的名称
labels#标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app nginx #为该Deployment设置key为app,value为nginx的标签
spec#这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas 1 #使用该Deployment创建一个应用程序实例
selector#标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels#选择包含标签app:nginx的资源
app nginx
template#这是选择或创建的Pod的模板
metadata#Pod的元数据
labels#Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app nginx
spec#期望Pod实现的功能(即在pod中部署)
containers#生成container,与docker中的container是同一种
name nginx #container的名称
image nginx 1.7.9 #使用镜像nginx:1.7.9创建container,该container默认80端口可访问
应用yaml文件
kubectl apply -f nginx-deployment.yaml
查看部署结果
# 查看 Deployment
kubectl get deployments
# 查看 Pod
kubectl get pods
显示建立成功,可分别查看到一个名为 nginx-deployment 的 Deployment 和一个名为 nginx-deployment-xxxxxxx 的 Pod
查看Pods和Node
Pod
创建 Deployment 后,k8s创建了一个 Pod(容器组) 来放置应用程序实例(container 容器)。
Pod 容器组 是一个k8s中一个抽象的概念,用于存放一组 container(可包含一个或多个 container 容器,即图上正方体),以及这些 container (容器)的一些共享资源。这些资源包括:
- 共享存储,称为卷(Volumes),即图上紫色圆柱
- 网络,每个 Pod(容器组)在集群中有个唯一的 IP,pod(容器组)中的 container(容器)共享该IP地址
- container(容器)的基本信息,例如容器的镜像版本,对外暴露的端口等
pod是k8s集群上最基本的单元。当我们在k8s创建Deployment的时候,会在集群上创建包含容器的POD,而不是直接创建容器。每个Pod都与它的work节点(node)绑定,并保持在那里直到终止或者被删除。如果节点发生故障,则会在集群中的其他节点node上运行相同的pod,从同样的镜像创建container,使用同样的配置,IP地址不同,pod名字不同。
注意:
- pod是一组容器,可以包含一个或者多个应用程序,以及共享存储(卷),ip地址和有关如何运行容器的信息。
- 如果多个容器紧密耦合并且需要共享磁盘等资源,则它们应该是被部署在同一个pod中
Node
下图显示一个 Node(节点)上含有4个 Pod(容器组)
Pod总是在node上运行。node是k8s集群中的计算机,可以是虚拟机或者物理机。每个node节点上都由master管理。一个node上可以有多个pod,k8s master会根据每个node上的资源情况,自动调度pod到最佳的node上。
每个node至少运行:
- kubelet,负责master节点和worker节点之间的通信进程,管理pod和pod内运行的container容器、
- 容器运行环境,如docker负责下载镜像,创建和运行容器等。
相关故障排除
- kubectl get 显示资源列表
# kubectl get 资源类型
#获取类型为Deployment的资源列表
kubectl get deployments
#获取类型为Pod的资源列表
kubectl get pods
#获取类型为Node的资源列表
kubectl get nodes
# 查看所有名称空间的 Deployment
kubectl get deployments -A
kubectl get deployments --all-namespaces
# 查看 kube-system 名称空间的 Deployment
kubectl get deployments -n kube-system
注意,并非所有的对象都在名称空间里面
- kubctl describe 显示有关资源的详细信息
# kubectl describe 资源类型 资源名称
#查看名称为nginx-XXXXXX的Pod的信息
kubectl describe pod nginx-XXXXXX
#查看名称为nginx的Deployment的信息
kubectl describe deployment nginx
- kubectl logs 查看pod中容器的打印日志
# kubectl logs Pod名称
#查看名称为nginx-pod-XXXXXXX的Pod内的容器打印的日志
#本案例中的 nginx-pod 没有输出日志,所以您看到的结果是空的
kubectl logs -f nginx-pod-XXXXXXX
- kubectl exec 在pod中执行命令
# kubectl exec Pod名称 操作命令
# 在名称为nginx-pod-xxxxxx的Pod中运行bash
kubectl exec -it nginx-pod-xxxxxx /bin/bash
公布应用
service描述
pod有自己的生命周期,当node故障的时候,节点上运行的pod也会消失。然后deployment可以通过创建新的pod来动态将集群调整回原来的状态,以使得应用程序保持运行。
service提供了一个抽象层,它选择具备某额写特征的pod并为他们定义一个访问方式。service使用pod之间的相互依赖解耦,如一个pod访问另外一个pod需要指导对方的ip地址。一个service选定哪些pod通常由LabelSelector来决定。
创建service的时候,通过设置配置文件中的spec.type字段的值,可以以不同方式向外暴露应用程序。
- ClusterIp 默认
在集群的内部IP上公布服务,这种方式的service服务,只有在集群内部可以访问到。
- NodePort
使用nat在集群中的每个的同一个端口上公布服务。这种方式下,可以通过访问集群中任意节点+端口号的方式访问服务<NodeIP>:<NodePort>.此时ClusterIP的访问方式任然可用。
- LoadBalancer
在云环境中,创建一个集群外部的负载均衡器,并为使用该负载均衡器的IP地址作为服务的访问地址。此时ClusterIp和nodeport的访问方式任然可用。
service是一个抽象层,它通过labelselector选择一组pod,把这些pod指定端口公布到集群外部,并支持负载均衡和服务发现。
服务和标签
以下两个服务,A,和B。A将请求发送到IP为10.10.10.1的pod上,B将请求转发到IP为10.10.10.2,10.10.10.3,10.10.10.4的pod上。
service将外部请求路由到一组pod上,它提供了一个抽象层,使得k8s在不影响服务调度的情况下,动态调度容器组,例如在原有容器组失效后重新创建容器组,增加或者减少同一个Deployment对应容器组的数量等。
service使用labels,labelseletor匹配一组pod。labels是附加到k8s对象的键值对,其用途有很多种。
- 将k8s对象(node,deployment,pod,service)指派用于开发环境,测试环境或生产环境。
- 嵌入版本标签,使用标签区别不同的应用软件版本
- 使用标签对k8s对象进行分类
下图体现了labels和labelsselector之间的关联关系
- deployment B含有labelselector为app=B(此方式声明了含有app=B标签的pod与之关联
- 通过deployment B创建pod包含标签为app=B
- service B通过标签选择器app=B选择可以路由的Pod
labels可以在创建k8s对象的时候附加上去,也可以在创建之后再附加上去,任何时候都可以修改一个k8s对象的label
使用kubectl为deployment创建一个service
创建nginx的deployment中定义了labels
metadata#译名为元数据,即Deployment的一些基本属性和信息
name nginx-deployment #Deployment的名称
labels#标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组
app nginx #为该Deployment设置key为app,value为nginx的标签
##############
##创建nginx-service.yaml
vim nginx-service.yaml
#####内容如下
apiVersion v1
kind Service
metadata
name nginx-service #Service 的名称
labels#Service 自己的标签
app nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签
spec#这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
selector#标签选择器
app nginx #选择包含标签 app:nginx 的 Pod
ports
name nginx-port #端口的名字
protocol TCP #协议类型 TCP/UDP
port 80 #集群内的其他容器组可通过 80 端口访问 Service
nodePort 32600 #通过任意节点的 32600 端口访问 Service
targetPort 80 #将请求转发到匹配 Pod 的 80 端口
type NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer
执行命令并检查执行结果
kubectl apply -f nginx-service.yaml
kubectl get services -o wide
curl <任意节点的 IP>:32600
测试已经可以通过集群内部访问