上一章,说了k8s的搭建,。搭建的流程在这---> 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 节点上重新创建一个新的实例。这提供了一种自我修复机制来解决机器故障或维护问题。
下边进入正文,开始部署第一个应用程序

Deployment 处于 master 节点上,通过发布 Deployment,master 节点会选择合适的 worker 节点创建 Container,Container 会被包含在 Pod里,一个pod理论上可以包容无限的Container,但是不建议这么做。
部署nginx的deployment:
我们使用kubectl来进行部署。
首先创建 yaml文件:
apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本kind: Deployment #该配置的类型,我们使用的是 Deploymentmetadata: #译名为元数据,即 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: nginxtemplate: #这是选择或创建的Pod的模板metadata: #Pod的元数据labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Podapp: nginxspec: #期望Pod实现的功能(即在pod中部署)containers: #生成container,与docker中的container是同一种- name: nginx #container的名称image: nginx:1.18.1 #使用镜像nginx:1.18.1创建container,该container默认80端口可访问
应用 YAML 文件
两种方式都可以使用。
kubectl apply -f nginx-deployment.yamlkubctl creat -f nginx-deployment.yaml
查看部署结果:# 查看 Deployment
kubectl get deployments# 查看 Podkubectl get pods# 如果想查看x详细信息 加个参数 -o widekubectl get deployments -o wide# pod查看同理kubectl get pods -o wide
可分别查看到一个名为 nginx-deployment 的 Deployment 和一个名为 nginx-deployment-xxxxxxx 的 Pod
至此你已经成功在k8s上部署了一个实例的nginx应用程序。
那Deployment(部署)、Pod(容器组) 和 Node(节点) 他们之间是什么关系呢?
什么是POD呢?

Pod 容器组 是一个k8s中一个抽象的概念,用于存放一组 container(可包含一个或多个 container 容器,即图上正方体),以及这些 container (容器)的一些共享资源。这些资源包括:
共享存储,称为卷(Volumes),即图上紫色圆柱
网络,每个 Pod(容器组)在集群中有个唯一的 IP,pod(容器组)中的 container(容器)共享该IP地址
container(容器)的基本信息,例如容器的镜像版本,对外暴露的端口等
例如,Pod可能既包含带有Node.js应用程序的 container 容器,也包含另一个非 Node.js 的 container 容器,用于提供 Node.js webserver 要发布的数据。Pod中的容器共享 IP 地址和端口空间(同一 Pod 中的不同 container 端口不能相互冲突),始终位于同一位置并共同调度,并在同一节点上的共享上下文中运行。(同一个Pod内的容器可以使用 localhost + 端口号互相访问)。
Pod(容器组)是 k8s 集群上的最基本的单元。当我们在 k8s 上创建 Deployment 时,会在集群上创建包含容器的 Pod (而不是直接创建容器)。每个Pod都与运行它的 worker 节点(Node)绑定,并保持在那里直到终止或被删除。如果节点(Node)发生故障,则会在群集中的其他可用节点(Node)上运行相同的 Pod(从同样的镜像创建 Container,使用同样的配置,IP 地址不同,Pod 名字不同)。
TIP
重要:
Pod 是一组容器(可包含一个或多个应用程序容器),以及共享存储(卷 Volumes)、IP 地址和有关如何运行容器的信息。
如果多个容器紧密耦合并且需要共享磁盘等资源,则他们应该被部署在同一个Pod(容器组)中。
那什么是node节点呢
一个node节点上4个pod

Pod(容器组)总是在 Node(节点) 上运行。Node(节点)是 kubernetes 集群中的计算机,可以是虚拟机或物理机。每个 Node(节点)都由 master 管理。一个 Node(节点)可以有多个Pod(容器组),kubernetes master 会根据每个 Node(节点)上可用资源的情况,自动调度 Pod(容器组)到最佳的 Node(节点)上。
每个 Kubernetes Node(节点)至少运行:
Kubelet,负责 master 节点和 worker 节点之间通信的进程;管理 Pod(容器组)和 Pod(容器组)内运行的 Container(容器)。
容器运行环境(如Docker)负责下载镜像、创建和运行容器等。
我们使用了 kubectl 命令行界面部署了 nginx 并且查看了 Deployment 和 Pod。kubectl 还有如下四个常用命令,在我们排查问题时可以提供帮助:
# kubectl get 资源类型#获取类型为Deployment的资源列表kubectl get deployments#获取类型为Pod的资源列表kubectl get pods#获取类型为Node的资源列表kubectl get nodes
名称空间(namespace)
在命令后增加 -A 或 --all-namespaces 可查看所有 名称空间中 的对象,使用参数 -n 可查看指定名称空间的对象,例如
# 查看所有名称空间的 Deploymentkubectl get deployments -Akubectl get deployments --all-namespaces# 查看 kube-system 名称空间的 Deploymentkubectl get deployments -n kube-system
kubectl describe - 显示有关资源的详细信息
# kubectl describe 资源类型 资源名称#查看名称为nginx-XXXXXX的Pod的信息kubectl describe pod nginx-XXXXXX#查看名称为nginx的Deployment的信息kubectl describe deployment nginx
kubectl logs - 查看pod中的容器的打印日志(和命令docker logs 类似)
# kubectl logs Pod名称#查看名称为nginx-pod-XXXXXXX的Pod内的容器打印的日志#本案例中的 nginx-pod 没有输出日志,所以您看到的结果是空的kubectl logs -f nginx-pod-XXXXXXX
kubectl exec - 在pod中的容器环境内执行命令(和命令docker exec 类似)
# kubectl exec Pod名称 操作命令# 在名称为nginx-pod-xxxxxx的Pod中运行bashkubectl exec -it nginx-pod-xxxxxx /bin/bash
TIP:
Worker节点是k8s中的工作计算机,可能是VM或物理计算机,具体取决于群集。多个Pod可以在一个节点上运行。
那么该如何访问我们部署的应用呢?
k8s提供了Service(服务)来暴露应用服务程序,使我们能否进行访问。
那什么是kubernetes Service呢?
事实上,Pod(容器组)有自己的 生命周期 (opens new window)。当 worker node(节点)故障时,节点上运行的 Pod(容器组)也会消失。然后,Deployment (opens new window)可以通过创建新的 Pod(容器组)来动态地将群集调整回原来的状态,以使应用程序保持运行。
举个例子,假设有一个图像处理后端程序,具有 3 个运行时副本。这 3 个副本是可以替换的(无状态应用),即使 Pod(容器组)消失并被重新创建,或者副本数由 3 增加到 5,前端系统也无需关注后端副本的变化。由于 Kubernetes 集群中每个 Pod(容器组)都有一个唯一的 IP 地址(即使是同一个 Node 上的不同 Pod),我们需要一种机制,为前端系统屏蔽后端系统的 Pod(容器组)在销毁、创建过程中所带来的 IP 地址的变化。
Kubernetes 中的 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 的访问方式仍然可用
TIPService是一个抽象层,它通过 LabelSelector 选择了一组 Pod(容器组),把这些 Pod 的指定端口公布到到集群外部,并支持负载均衡和服务发现。公布 Pod 的端口以使其可访问在多个 Pod 间实现负载均衡使用 Label 和 LabelSelector
下图中有两个服务Service A(黄色虚线)和Service B(蓝色虚线) Service A 将请求转发到 IP 为 10.10.10.1 的Pod上, Service B 将请求转发到 IP 为 10.10.10.2、10.10.10.3、10.10.10.4 的Pod上。

Service 将外部请求路由到一组 Pod 中,它提供了一个抽象层,使得 Kubernetes 可以在不影响服务调用者的情况下,动态调度容器组(在容器组失效后重新创建容器组,增加或者减少同一个 Deployment 对应容器组的数量等)。
Service使用 Labels、LabelSelector(标签和选择器) (opens new window)匹配一组 Pod。Labels(标签)是附加到 Kubernetes 对象的键/值对,其用途有多种:
将 Kubernetes 对象(Node、Deployment、Pod、Service等)指派用于开发环境、测试环境或生产环境
嵌入版本标签,使用标签区别不同应用软件版本
使用标签对 Kubernetes 对象进行分类
下图体现了 Labels(标签)和 LabelSelector(标签选择器)之间的关联关系
Deployment B 含有 LabelSelector 为 app=B 通过此方式声明含有 app=B 标签的 Pod 与之关联
通过 Deployment B 创建的 Pod 包含标签为 app=B
Service B 通过标签选择器 app=B 选择可以路由的 Pod

Labels(标签)可以在创建 Kubernetes 对象时附加上去,也可以在创建之后再附加上去。任何时候都可以修改一个 Kubernetes 对象的 Labels(标签)
下边为我们的nginx Deployment 创建一个Service
创建nginx的Deployment中定义了Labels,如下:metadata: #译名为元数据,即Deployment的一些基本属性和信息name: nginx-deployment #Deployment的名称labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组app: nginx #为该Deployment设置key为app,value为nginx的标签
创建文件 nginx-service.yaml
cat nginx-service.yamlapiVersion: v1kind: Servicemetadata:name: nginx-service #Service 的名称labels: #Service 自己的标签app: nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签spec: #这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问selector: #标签选择器app: nginx #选择包含标签 app:nginx 的 Podports:- name: nginx-port #端口的名字protocol: TCP #协议类型 TCP/UDPport: 80 #集群内的其他容器组可通过 80 端口访问 ServicenodePort: 32600 #通过任意节点的 32600 端口访问 ServicetargetPort: 80 #将请求转发到匹配 Pod 的 80 端口type: NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer
执行命令:
kubectl apply -f nginx-service.yaml
检查执行结果
kubectl get services -o wide
可查看到名称为 nginx-service 的服务。
访问服务
curl <任意节点的 IP>:32600
或者直接在浏览器中打开,可以查看到nginx的界面

到目前为止,我们已经成功部署好项目,并能够对其进行访问,




