主要讲述如何在K8s中部署应用。
首先,我们在实战项目中经常会用到的一些概念
使用上一篇文章,我们重建Kind K8s环境,并部署一个可以从本地访问的简单网页,加深理解。
Workloads(工作负载)是运行在K8s上的应用,可以是单独一个组件(比如一个Job)也可以是多个组件协同运行(比如deployment,service,ingress等一起构成一个应用)。
无论是哪种形式,在K8s上负载最终都是以Pod为基本单位运行的。
Pod本身有一个生命周期,比如当一个node出现故障宕机了,则此node上运行的所有Pod会失败,这时我们需要重新在其它节点创建Pod。
一般情况下,我们不直接运行Pod,我们通过Workloads Resources来帮我们管理Pod。
每个Workloads Resources有不同的controller相对应,controller按我们的要求维护Pod的状态(比如在一个node失败后,在其它节点重建pod)。
Pod是我们在K8s中可以创建使用的最小计算单元。每个Pod可以由一个或者多个容器组成。
比如,kube-system namespace内运行的pods
K8s为每个Pod分配一个集群内部的IP和DNS。
多个容器组成的Pods中,容器之间共享Pod的存储和网络。一个Pod中的多个容器总是安排运行在相同的node上,并且同时启动或者停止。
下图展示了一个Pod中运行的两个容器
Pod中多容器的常用应用例子还有
在Pod中运行应用容器之外,再运行一个Filebeat容器,用来把应用容器产生的日志输出到ElasticSearch。
下图中,第一行backend pod 中就运行了两个容器,READY 显示2/2,代表这个pod中有两个容器在运行
我们可以使用 kubectl describe 命令,查看 backend pod中具体有哪两个容器。
从下图可以看到,其中一个是backend应用容器,还有一个是filebeat容器
kubectl describe pods/POD_NAME -n NAMESPACE_NAME
另外,在Pod中我们还可以设置init容器,init容器在其它容器(应用容器)运行之前启动运行并终止,init容器可以帮我们做一些初始化的工作。
我们通过Workloads Resources来管理Pods,K8s提供了一些定义好的Workloads Resources类型来满足不同的业务要求。
我们后面实验用的是Deployment,所以我们再多介绍一下Workloads Resources中的Deployment。
我们在Deployment中描述需要的状态,然后Deployment Controller帮我们把Pod运行在指定状态。
简单点说就是,我们在Deployment Yaml文件中定义自己的Pod(容器)模板、运行数量等,然后Deployment Controller帮我们维护这些Pod。
这时如果Pod运行所在的Node宕机了,Deployment Controller会自动帮我们把Pod运行到其它可用的Node上。
Deployment通过selector(利用labels)来选择哪些Pods归其管理。
下面就是一个Deployment Yaml文件,后面我们会用kubectl命令运行这个yaml文件,在kind K8s中部署。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
说明:
以后部署任何K8s应用,都会以这种yaml文件的形式来做部署。
当然我们也可以使用Helm来做部署,但Helm最终也是生成上面这种yaml文件来部署应用。
现在,我们观察一下Kind K8s中kube-system 空间内部署的Deployment
查看Deployment的详细信息
kubectl describe deployments/coredns -n kube-system
说明:这里可以看到selector,以及Pod模板等信息
在用Deployment管理Pod时,Deployment会帮助我们重启失败的Pod,维护Pod设定的状态。
但是重启后的Pod会分配一个新的内部IP和DNS,这就会造成一些问题。
比如,一个应用运行了两组Pod,一组做为前端,另一组做为后端。当后端的Pod重启并分配新IP之后,前端如何找到新的后端?(服务发现)
这就是Service提供的功能。
Service用来把应用运行的Pods做为网络服务暴露出来。
可以简单理解为,Pods没有固定IP,但Service有固定IP,把Pods和Service关联起来之后,我们就可以通过Service来找到需要的Pods。
与Deployment一样,Service也用yaml文件来定义,下面一个Service的例子
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
说明:
我们观察Kind K8s中kube-system 空间内部署的Service,目前这个Service的类型是Clsuter IP,只能从内部访问
K8s支持在cluster中创建virtual cluster,这些virtual cluster就叫做namespaces。
当一个K8s集群有很多用户或项目使用时,我们可以通过创建namespace来区分用户和资源。
在一个Cluster中,一个K8s对象的名称是不能重复的,但在namespace中,只要对象名称不在当前namespace中重复即可。
查看cluster中所有Namespaces
kubectl get namespaces
这里的DNS是特指K8s内部的DNS。K8s会自动为每个Pod和Service创建DNS,我们可以通过DNS或者IP来访问Pod和Service。