k8s 入门-minikube部署应用和基本概念
这篇以部署一个nginx应用为例,介绍应用在k8s集群中的部署方式,其中穿插会介绍相关概念和组件(如service和deployment)并在使用中加深理解。
这里通过2种方式来部署nginx应用,第一种是通过命令run的方式,这种方式主要用于学习和测试,部署较为简单。第二种是通过yaml文件创建deployment的方式,这种方式可以应对更为复杂的部署场景,也是我们在实际生产和部署过程中常用的方式。
一、基本概念
这里首先先介绍下k8s中几个核心概念,也是后面的命令中会用到的:
目前K8s中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的控制器为Deployment、Job、DaemonSet和PetSet。
复制控制器(Replication Controller,RC)
RC是K8s集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。即使在指定数目为1的情况下,通过RC运行Pod也比直接运行Pod更明智,因为RC也可以发挥它高可用的能力,保证永远有1个Pod在运行。RC是K8s较早期的技术概念,只适用于长期伺服型的业务类型,比如控制小机器人提供高可用的Web服务。
副本集(Replica Set,RS)
RS是新一代RC,提供同样的高可用能力,区别主要在于RS后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment的理想状态参数使用。
部署(Deployment)
部署表示用户对K8s集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。以K8s的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理。
服务(Service)
RC、RS和Deployment只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务的问题。一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。在K8s集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。在K8s集群中微服务的负载均衡是由Kube-proxy实现的。Kube-proxy是K8s集群内部的负载均衡器。它是一个分布式代理服务器,在K8s的每个节点上都有一个;这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。与之相比,我们平时在服务器端做个反向代理做负载均衡,还要进一步解决反向代理的负载均衡和高可用问题。
简单理解就是:
(1)RC和RS是负责监控pod运行情况并保证pod数量是用户配置的数量,如果其中有pod挂掉,RC和RS控制器会自动创建新的pod,如果有大于用户配置数量的pod也会自动杀死多余的pod,保证当前运行的pod数量是正确的。RS是RC的升级版。
(2)服务sevice是负责分发用户请求到具体的pod上。因为同一个业务可能会有多个pod,即使是只有一个pod也可能会动态变化(第一条中说到的为了保证高可用pod挂掉会自动重新创建),因此实际运行业务的pod的IP会一直在变化,但是用户访问时是使用固定IP来访问应用的,这个过程中怎么把用户请求分发到对应pod上就是service做的事情。查看service时会看到2个IP,EXTERNAL-IP是对外IP,CLUSTER-IP是集群内IP。service内部会进行统筹管理最终将用户请求分发到具体pod,并通过集群内部IP(即CLUSTER-IP)与pod进行通信。
二、pod初试:部署一个nginx应用
通过run命令运行pod
$ minikube kubectl -- run nginx --image=nginx --port=80
验证pod的可用性:
$ minikube kubectl -- get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 28m 172.17.0.5 minikube <none> <none>
$ minikube ssh
$ curl 172.17.0.5
作为服务对外暴露:
$ minikube kubectl -- expose pod nginx --port=80 --target-port=80 --type=NodePort
–type解释:
后两个类型都可以把服务对外暴露,关于这两种暴露方式的差别为:
1.NodePort 服务是引导外部流量到你的服务的最原始方式。NodePort,正如这个名字所示,在所有节点(虚拟机)上开放一个特定端口,任何发送到该端口的流量都被转发到对应服务。
2.LoadBalancer 服务是暴露服务到 internet 的标准方式。在 GKE 上,这种方式会启动一个 Network Load Balancer,它将给你一个单独的 IP 地址,转发所有流量到你的服务。通过查看service详情也可以看到里面会有一个EXTERNAL-IP。
–type=ClusterIP方式下验证服务的可用性:
$ minikube kubectl -- get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22h
nginx ClusterIP 10.96.90.16 <none> 80/TCP 3s
$ minikube service nginx --url
* service default/nginx has no node port
$ minikube ssh
$ curl 10.96.90.16
–type=NodePort和方式下验证服务的可用性:
$ minikube service nginx3 --url
$ minikube kubectl -- get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
nginx3 NodePort 10.106.95.180 <none> 80:31434/TCP 4s
$ minikube ip
192.168.49.2
简写,以上是分2步创建pod和服务,可以合并使用一条命令:
$ minikube kubectl -- run nginx2 --image=nginx --port=80 --expose
service/nginx2 created
pod/nginx2 created
备注:在1.17版本以前run命令可以通过–replicas参数指定pod副本数量,–generator参数指定创建的资源的类型,资源列表如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HhuS2q28-1629709206989)(C:\Users\unicom\AppData\Roaming\Typora\typora-user-images\image-20210823142658200.png)]
但是从V1.17版本开始,这两个参数都被废弃了。官方推荐通过创建deployment的方式来创建pod。run命令只会创建pod类型的资源。因此建议使用本章第三节中的方式来部署应用。
三、deployment初试:部署一个nginx应用
1.通过stdin创建deployment
$ minikube kubectl -- create deployment nginx2 --image=nginx --replicas=2
$ minikube kubectl -- get pods
NAME READY STATUS RESTARTS AGE
nginx2-5fc4444698-2sqlv 1/1 Running 0 87s
nginx2-5fc4444698-9p472 1/1 Running 0 87s
$ minikube kubectl -- get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx2 2/2 2 2 17s
2.通过yml文件创建deployment
$ vim test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
$ kubectl apply -f test.yml
$ minikube kubectl -- get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 3m40s
$ minikube kubectl -- get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-7848d4b86f-7rpnh 1/1 Running 0 4m8s
nginx-deployment-7848d4b86f-hjff5 1/1 Running 0 4m8s
四、高可用性验证
$ minikube kubectl -- get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx2 2/2 2 2 149m
$ minikube kubectl -- get pods
NAME READY STATUS RESTARTS AGE
nginx2-5fc4444698-2sqlv 1/1 Running 0 147m
nginx2-5fc4444698-9p472 1/1 Running 0 147m
$ minikube kubectl -- delete pod nginx2-5fc4444698-9p472
pod "nginx2-5fc4444698-9p472" deleted
$ minikube kubectl -- get pods
NAME READY STATUS RESTARTS AGE
nginx2-5fc4444698-2sqlv 1/1 Running 0 147m
nginx2-5fc4444698-qbckv 1/1 Running 0 16s
|