30-k8s-controller-service:
Controller
1、什么是Controller
Controller是在集群上管理和运行容器的对象,Controller是实际存在的,Pod是虚拟机的
2、Pod和Controller的关系
Pod是通过Controller实现应用的运维,比如弹性伸缩,滚动升级等
Pod 和 Controller之间是通过label标签来建立关系,同时Controller又被称为控制器工作负载
3、Deployment控制器应用场景
- Deployment控制器可以部署无状态应用
- 管理Pod和ReplicaSet(副本集)
- 部署,滚动升级等功能
- 应用场景:web服务,微服务
Deployment表示用户对K8S集群的一次更新操作。Deployment是一个比RS( Replica Set, RS) 应用模型更广的 API 对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新 RS 中副本数增加到理想状态,将旧RS中的副本数减少到0的复合操作。
这样一个复合操作用一个RS是不好描述的,所以用一个更通用的Deployment来描述。以K8S的发展方向,未来对所有长期伺服型的业务的管理,都会通过Deployment来管理。
Deployment部署应用
使用Deployment部署过应用,如下代码所示
kubectrl create deployment nginx-1 --image=nginx
但是上述代码不是很好的进行复用,因为每次我们都需要重新输入代码,所以我们都是通过YAML进行配置
但是我们可以尝试使用上面的代码创建一个镜像【只是尝试,不会创建】
kubectl create deployment nginx-1 --image=nginx --dry-run -o yaml > nginx-1.yaml
然后输出一个yaml配置文件 nginx.yml
,配置文件如下所示
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-1
name: nginx-1
spec:
replicas: 1
selector:
matchLabels:
app: nginx-1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx-1
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
selector 和 label 就是我们Pod 和 Controller之间建立关系的桥梁
使用YAML创建Pod
通过刚刚的代码生成YAML文件,下面使用该配置文件快速创建Pod镜像
kubectl apply -f nginx-1.yaml
但是这个方式创建的,我们只能在集群内部进行访问,所以我们还需要对外暴露端口
kubectl expose deployment nginx-1 --port=80 --type=NodePort --target-port=80 --name=nginx-2
关于上述命令,有几个参数
- –port:就是我们内部的端口号
- –target-port:就是暴露外面访问的端口号
- –name:名称
- –type:类型
同理,一样可以导出对应的配置文件
kubectl expose deployment nginx-1 --port=80 --type=NodePort --target-port=80 --name=nginx-2 -o yaml > nginx-2.yaml
得到的nginx-2.yaml如下所示
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2022-03-20T04:55:48Z"
labels:
app: nginx-1
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:externalTrafficPolicy: {}
f:ports:
.: {}
k:{"port":80,"protocol":"TCP"}:
.: {}
f:port: {}
f:protocol: {}
f:targetPort: {}
f:selector:
.: {}
f:app: {}
f:sessionAffinity: {}
f:type: {}
manager: kubectl
operation: Update
time: "2022-03-20T04:55:48Z"
name: nginx-2
namespace: default
resourceVersion: "44172"
selfLink: /api/v1/namespaces/default/services/nginx-2
uid: 270fe009-d389-4b5c-8eca-d8d54444d6df
spec:
clusterIP: 10.109.47.165
externalTrafficPolicy: Cluster
ports:
- nodePort: 30713
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-1
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
然后访问对应的url,即可看到 nginx了 http://Nodeip:30713/
4、升级回滚
- 升级: 假设从版本为1.14 升级到 1.15 ,这就叫应用的升级【升级可以保证服务不中断】
- 回滚:从版本1.15 变成 1.14,这就叫应用的回滚
- 弹性伸缩:我们根据不同的业务场景,来改变Pod的数量对外提供服务,这就是弹性伸缩
首先我们先创建一个 1.14版本的Pod
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx:1.14
name: nginx
resources: {}
status: {}
我们先指定版本为1.14,然后开始创建我们的Pod
kubectl apply -f nginx-14-version.yaml
通过docker images,查看到1.14版本的nginx镜像
使用下面命令,可将nginx从 1.14 升级到 1.16
kubectl set image deployment web nginx=nginx:1.16
在我们执行完命令后,能看到升级的过程
- 首先是开始的nginx 1.14版本的Pod在运行,然后 1.16版本的在创建
- 然后在1.165版本创建完成后,就会暂停1.14版本
- 最后把1.14版本的Pod移除,完成我们的升级
我们在下载 1.16版本,容器就处于ContainerCreating状态,然后下载完成后,就用 1.16版本去替换1.14版本了,这么做的好处就是:升级可以保证服务不中断
我们到我们的hadoop103节点上,查看我们的 docker images;
查看升级状态
下面可以,查看升级状态
kubectl rollout status deployment web
查看历史版本
我们还可以查看历史版本
kubectl rollout history deployment web
应用回滚
我们可以使用下面命令,完成回滚操作,也就是回滚到上一个版本
kubectl rollout undo deployment web
然后我们就可以查看状态
kubectl rollout status deployment web
同时我们还可以回滚到指定版本
kubectl rollout undo deployment web --to-revision=2
5、弹性伸缩
弹性伸缩,也就是我们通过命令一下创建多个副本
kubectl scale deployment web --replicas=10
能够清晰看到,我们一下创建了10个副本
删除之前的pod,学习测试使用
[root@hadoop102 k8s-yaml]# kubectl get deployment
[root@hadoop102 k8s-yaml]# kubectl delete deployment nginx
Service
定义一组pod的访问规则,前面我们了解到 Deployment 只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务的问题。一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。
要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的后端服务实例。在K8S集群中,客户端需要访问的服务就是Service对象。每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。
在K8S集群中,微服务的负载均衡是由kube-proxy实现的。kube-proxy是k8s集群内部的负载均衡器。它是一个分布式代理服务器,在K8S的每个节点上都有一个;这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的kube-proxy就越多,高可用节点也随之增多。与之相比,我们平时在服务器端使用反向代理作负载均衡,还要进一步解决反向代理的高可用问题。
1、Service存在的意义
1.1防止Pod失联【服务发现】
因为Pod每次创建都对应一个IP地址,而这个IP地址是短暂的,每次随着Pod的更新都会变化,假设当我们的前端页面有多个Pod时候,同时后端也多个Pod,这个时候,他们之间的相互访问,就需要通过注册中心,拿到Pod的IP地址,然后去访问对应的Pod
1.2定义Pod访问策略【负载均衡】
页面前端的Pod访问到后端的Pod,中间会通过Service一层,而Service在这里还能做负载均衡,负载均衡的策略有很多种实现策略,例如:随机,轮询,响应比
2、Pod和Service的关系
这里Pod 和 Service 之间还是根据 label 和 selector 建立关联的 【和Controller一样】
3、Service常用类型
kubectl expose --help
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEJUtdZz-1670132544045)(png/image-20220320135016511.png)]
Service常用类型有三种
- ClusterIp:集群内部访问
- NodePort:对外访问应用使用
- LoadBalancer:对外访问应用使用,公有云
例:
我们可以导出一个文件 包含service的配置信息
[root@hadoop102 k8s-yaml]# kubectl apply -f nginx-14-version.yaml
[root@hadoop102 k8s-yaml]# kubectl get pod
[root@hadoop102 k8s-yaml]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
web 1/1 1 1 52s
[root@hadoop102 k8s-yaml]# kubectl expose deployment web --port=80 --target-port=80 --dry-run -o yaml > service.yaml
service.yaml 如下所示
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
status:
loadBalancer: {}
如果我们没有做设置的话,默认使用的是第一种方式 ClusterIp,也就是只能在集群内部使用,我们可以添加一个type字段,用来设置我们的service类型
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}
修改完命令后,我们使用创建一个pod
kubectl apply -f service.yaml
然后能够看到,已经成功修改为 NodePort类型了,最后剩下的一种方式就是LoadBalanced:对外访问应用使用公有云
node一般是在内网进行部署,而外网一般是不能访问到的,那么如何访问的呢?
- 找到一台可以通过外网访问机器,安装nginx,反向代理
- 手动把可以访问的节点添加到nginx中
如果我们使用LoadBalancer,就会有负载均衡的控制器,类似于nginx的功能,就不需要自己添加到nginx上
Controller详解
1、有状态无状态
Statefulset
Statefulset主要是用来部署有状态应用,对于StatefulSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。
无状态应用
我们原来使用 deployment,部署的都是无状态的应用,那什么是无状态应用?
- 认为Pod都是一样的
- 没有顺序要求
- 不考虑应用在哪个node上运行
- 能够进行随意伸缩和扩展
有状态应用
上述的因素都需要考虑到
- 让每个Pod独立的,保持Pod启动顺序和唯一性
- 唯一的网络标识符,持久存储
- 有序,比如mysql中的主从
2、StatefulSet部署有状态应用
无头service, ClusterIp:none。这里就需要使用 StatefulSet部署有状态应用
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
然后通过查看pod,能否发现每个pod都有唯一的名称
然后我们在查看service,发现是无头的service
kubectl get svc
这里有状态的约定,肯定不是简简单单通过名称来进行约定,而是更加复杂的操作
- deployment:是有身份的,有唯一标识
- statefulset:根据主机名 + 按照一定规则生成域名
每个pod有唯一的主机名,并且有唯一的域名
- 格式:主机名称.service名称.名称空间.svc.cluster.local
- 举例:nginx-statefulset-0.default.svc.cluster.local
删除:kubectl delete svc nginx
3、DaemonSet
DaemonSet 即后台支撑型服务,主要是用来部署守护进程
长期伺服型和批处理型的核心在业务应用,可能有些节点运行多个同类业务的Pod,有些节点上又没有这类的Pod运行;而后台支撑型服务的核心关注点在K8S集群中的节点(物理机或虚拟机),要保证每个节点上都有一个此类Pod运行。节点可能是所有集群节点,也可能是通过 nodeSelector选定的一些特定节点。典型的后台支撑型服务包括:存储、日志和监控等。在每个节点上支撑K8S集群运行的服务。
守护进程在我们每个节点上,运行的是同一个pod,新加入的节点也同样运行在同一个pod里面
举例:在每个node节点安装数据采集工具
vim filebeat.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-test
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: logs
image: nginx
ports:
- containerPort: 80
volumeMounts:
-name: varlog
mountPath: /tmp/log
volumes:
- name: varlog
hostPath:
path: /var/log
kubectl get pod
进入某个 Pod里面,进入
kubectl exec -it ds-test-cbk6v bash
通过该命令后,我们就能看到我们内部收集的日志信息了
Job和CronJob
一次性任务 和 定时任务
- 一次性任务:一次性执行完就结束
- 定时任务:周期性执行
Job是K8S中用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别就是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的 spec.completions 策略而不同:单Pod型任务有一个Pod成功就标志完成;定数成功行任务保证有N个任务全部成功;工作队列性任务根据应用确定的全局成功而标志成功。
1、Job一次性任务测试
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
使用下面命令,能够看到目前已经存在的Job
kubectl get jobs
在计算完成后,通过命令查看,能够发现该任务已经完成
我们可以通过查看日志,查看到一次性任务的结果
kubectl logs pi-qpqff
kubectl delete -f job.yaml
2、CronJob定时任务测试
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob #定时任务
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the k8s cluster
restartPolicy: OnFailure
创建一个定时任务
kubectl apply -f cronjob.yaml
kubectl get pods
创建完成后,我们就可以通过下面命令查看定时任务:kubectl get cronjobs
我们可以通过日志进行查看:kubectl logs hello-1599100140-name…
然后每次执行,就会多出一个 pod
删除svc 和 statefulset
使用下面命令,可以删除我们添加的svc 和 statefulset
kubectl delete svc web
kubectl delete statefulset --all
Replication Controller
Replication Controller 简称 RC,是K8S中的复制控制器。RC是K8S集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。
即使在指定数目为1的情况下,通过RC运行Pod也比直接运行Pod更明智,因为RC也可以发挥它高可用的能力,保证永远有一个Pod在运行。RC是K8S中较早期的技术概念,只适用于长期伺服型的业务类型,比如控制Pod提供高可用的Web服务。
Replica Set
Replica Set 检查 RS,也就是副本集。RS是新一代的RC,提供同样高可用能力,区别主要在于RS后来居上,能够支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment的理想状态参数来使用
学习路径:https://space.bilibili.com/302417610/,如有侵权,请联系q进行删除:3623472230