k8s 集群中对资源管理和资源对象编排部署都可以通过声明样式(YAML)文件来解决,也就是可以把需要对资源对象操作编辑到YAML 格式文件中,我们把这种文件叫做资源清单文件,通过kubectl 命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署了。
YAML 基本语法如下:
#
表示注释,从这个字符一直到行尾,都会被解释器忽略 ---
表示新的yaml文件开始YAML 支持如下的数据结构
对象:键值对的集合,又称为映射(mapping) / 哈希(hashes) / 字典(dictionary)
# 对象类型:对象的一组键值对,使用冒号结构表示
name: Tom
age: 18
# yaml 也允许另一种写法,将所有键值对写成一个行内对象
hash: {name: Tom, age: 18}
数组
# 数组类型:一组连词线开头的行,构成一个数组
People
- Tom
- Jack
# 数组也可以采用行内表示法
People: [Tom, Jack]
YAML文件主要分为了两部分,一个是控制器 和 被控制的对象
在一个YAML文件的控制器定义中,有很多属性名称
属性名称 | 介绍 |
---|---|
apiVersion | API版本 |
kind | 资源类型 |
metadata | 资源元数据 |
spec | 资源规格 |
replicas | 副本数量 |
selector | 标签选择器 |
template | Pod模板 |
metadata | Pod元数据 |
spec | Pod规格 |
containers | 容器配置 |
一般来说,我们很少自己手写YAML文件,而是借助工具来创建
使用kubectl create命令,一般用于资源没有部署的时候,我们可以直接创建一个YAML配置文件
# 尝试运行,并不会真正的创建镜像
kubectl create deployment web --image=nginx -o yaml --dry-run
# 输出到一个文件中
kubectl create deployment web --image=nginx -o yaml --dry-run > hello.yaml
使用kubectl get命令导出yaml文件,生成一个 nginx.yaml
的配置文件
kubectl get deploy nginx -o=yaml --export > nginx.yaml
Controller是在集群上管理和运行容器的对象。Pod 和 Controller之间是通过label标签来建立关系,从而实现应用的运维,比如弹性伸缩,滚动升级等。
Deployment控制器可以部署无状态应用,管理Pod和ReplicaSet,进行部署、滚动升级、自我修复等功能。自愈:例如当容器临时挂掉后,kubelet会尝试对容器进行重启;故障转移(failover):当某个机器节点故障时,会将机器上运行的pod转移到其他机器继续运行。
直接使用deployment部署应用
kubectrl create deployment web --image=nginx
为了更好地重用和配置,所以我们都是通过YAML进行部署。首先将部署配置输出到一个文件
kubectl create deployment web --image=nginx --dry-run -o yaml > nginx.yaml
yaml配置文件 nginx.yml
,配置文件如下所示
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
name: nginx
resources: {}
status: {}
通过YAML文件创建应用“web”,并对外暴露端口
kubectl apply -f nginx.yaml
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1
其中
将上面的操作一起写入配置文件中
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1 -o yaml > web1.yaml
得到的web1.yaml如下所示
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2020-11-16T02:26:53Z"
labels:
app: web
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: "2020-11-16T02:26:53Z"
name: web2
namespace: default
resourceVersion: "113693"
selfLink: /api/v1/namespaces/default/services/web2
uid: d570437d-a6b4-4456-8dfb-950f09534516
spec:
clusterIP: 10.104.174.145
externalTrafficPolicy: Cluster
ports:
- nodePort: 32639
port: 80
protocol: TCP
targetPort: 80
selector:
app: web
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
查看对外暴露的服务
通过controller可以便捷地将应用升级到最新版本或切换回之前的某个版本
首先创建一个 1.14版本的nginx
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: {}
kubectl apply -f nginx.yaml
我们使用下面的命令,可以将nginx从 1.14 升级到 1.15
kubectl set image deployment web nginx=nginx:1.15
在我们执行完命令后,能看到升级的过程
也可以将应用进行回滚
# 查看升级状态
kubectl rollout status deployment web
# 查看历史版本
kubectl rollout history deployment web
# 回滚到上一个版本
kubectl rollout undo deployment web
# 回滚到指定版本
kubectl rollout undo deployment web --to-revision=2
但应用访问遇到瓶颈时,可以通过如下命令增加节点来缓解访问压力
kubectl scale deployment web --replicas=10
能够清晰看到,新增了10个副本
Statefulset主要是用来部署有状态应用
对于StatefulSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。适合StatefulSet的业务包括数据库服务MySQL 和 PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务
使用StatefulSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,StatefulSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。
使用 StatefulSet部署有状态应用
apiVersion: apps
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
replicas:
selector:
matchLabels:
- app: nginxj
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
然后通过查看pod,能否发现每个pod都有唯一的名称
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4Sq1jCD-1661438498263)(https://gitee.com/moxi159753/LearningNotes/raw/master/K8S/11_Kubernetes%E6%8E%A7%E5%88%B6%E5%99%A8Controller%E8%AF%A6%E8%A7%A3/images/image-20201117203217016.png)]
在deployment中是有身份的,有唯一标识,而statefulset是根据主机名 + 按照一定规则生成域名,每个pod有唯一的主机名,并且有唯一的域名
DaemonSet 即后台支撑型服务,主要是用来部署守护进程。从而保证Pod运行在所有集群节点,或者是nodeSelector选定的全部节点。典型的后台支撑型服务包括:存储、日志和监控等。在每个节点上支撑K8S集群运行的服务。
守护进程在我们每个节点上,运行的是同一个pod,新加入的节点也同样运行在同一个pod里面
apiVersion: apps/vl
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: 8 0
volumeMount s:
- name: varlog
mountPath: /tmp/log
volumes:
-name: varlog
hostPath:
path: /var/log
Job也即一次性任务,一次性执行完就结束。
Job是K8S中用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别就是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的 spec.completions 策略而不同:单Pod型任务有一个Pod成功就标志完成;定数成功行任务保证有N个任务全部成功;工作队列性任务根据应用确定的全局成功而标志成功。
apiVersion: batch/vl
# 一次性任务
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
定时任务,根据cron表达式配置的规则每隔一段时间执行一次
apiVersion: batch/vl
# 定期任务
kind: CronJob
metadata:
name: dailyJob
spec:
# 设置执行周期
schedule: "*/l * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: dailyJob
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes
restartPolicy: OnFailure
然后下面命令就是每个一段时间输出
我们首先用上述的配置文件,创建一个定时任务
kubectl apply -f cronjob.yaml
创建完成后,我们就可以通过下面命令查看定时任务
kubectl get cronjobs
在K8S集群中,Service可以将一组 Pods 抽象为一个公开的网络服务,只需要对使用者统一暴露一个服务地址,不必区分内部具体实现的pod。通过Service可以提供服务发现和负载均衡的功能。
服务发现:Pod应用将自己的地址注册到Service中,从而把请求路由到指定的节点进行处理并返回。例如当Pod对应的某个节点停止工作时,另一个节点以一个新的IP启动一个新的Pod,并向Service中注册自己的IP和端口号以替换原来的Pod,这样当请求再次到达时可以路由到新的节点。
负载均衡:当请求过多时,将请求分散到不同的节点进行处理以缓解压力。微服务的负载均衡是由kube-proxy实现的,它是一个分布式代理服务器,在K8S的每个节点上都有一个。
在访问service的时候,其实也是需要有一个ip地址,这个ip肯定不是pod的ip地址,而是 虚拟IP vip
Service常用类型有三种
通过expose
命令暴露App名为web的服务,并将服务的8000端口和pod内的80端口建立映射。如果我们没有做设置的话,默认使用的是第一种方式 ClusterIp,也就是只能在集群内部使用,可以通过--type
参数设置service类型
kubectl expose deployment web --port=8000 --target-port=80 --dry-run -o yaml > service.yaml
导出包含service的配置信息如下
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
status:
loadBalancer: {}