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.spec.replicas定义期望的Pod数量;.spec.selector是Pod选择器,圈定Deployment管理的Pod范围。所有扩容出来的Pod的Labels必须匹配该标签。 .spec.template是Pod相关的模板(k8s包含了podtemplates这种资源对象,但不能创建,只能包含在workload资源对象中),包含了: 期望Pod的metadata,其中包含了labels(和selector.matchLabels相匹配的标签) 最终创建出的Pod的spec .spec.MinReadySeconds:默认情况下Deployment会根据Pod是否ready判断其是否可用。设置了MinReadySeconds后,Deployment会等若干秒之后才认为Pod是available的; .spec.revisionHistoryLimit:除了当前版本外,还保留的历史版本数量,默认值为10个。 .spec.paused:标识Deployment只做数量维持,不做新的发布。所有对spec.template.spec的修改都不会触发新的rollout,只会把replicas同步到对应的ReplicaSet中,更新一下Deployment的status。在Debug场景下才会设置为true。 .spec.progressDeadlineSeconds:设置Deployment处于Processing状态的超时时间。超时后Deployment认为这个Pod进入failed状态。 .spec.strategy:spec.strategy.type为Recreate时,会先停掉所有旧的再起新的;为RollingUpdate(默认)时,会滚动更新,此时有两个可配置项: MaxUnavailable:滚动过程中最多有多少个Pod不可用; MaxSurge:滚动过程中最多存在多少个Pod超过预期replicas数量。 如果用户的资源足够,且更注重发布过程中的可用性,可设置MaxUnavailable较小、MaxSurge较大。 如果用户的资源比较紧张,可以设置MaxSurge较小,甚至设置为0 注意:MaxSurge和MaxUnavailable不能同时为0! 创建出一个Deployment的时候,可以通过kubectl get deployment,看到Deployment总体的状态:
$ kubectl create -f nginx-deployment.yaml $ kubectl get deployment NAME DESRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deploynment 3 3 3 3 80mDESIRED:期望的Pod数量; CURRENT:当前实际 Pod 数量; UP-TO-DATE:到达最新的期望版本的Pod数量; AVAILABLE:运行过程中可用的Pod数量。 AGE:创建的时长。 Deployment的status中描述的状态包括:Processing(扩容/发布中)、Complete(运行中)以及Failed。 Deployment相关命令: 如果在发布过程中遇到了问题,通过kubectl rollout undo命令快速回滚Deployment版本:
$ kubectl rollout undo deployment/nginx-deployment $ kubectl rollout undo deployment.v1.apps/nginx-deployment —to-revision=2--to-revision指定可以回滚到某一个具体的版本,必须先查一下版本号:
$ kubectl rollout history deployment.v1.apps/nginx-deployment查看rollout的状态
$ kubectl rollout status deployment/nginx-deployment扩容:
$ kubectl scale deployment nginx-deployment --replicas 10
Deployment Controller实现原理:
Deployment Controller关注Deployment和ReplicaSet相关的event,收到事件后会加入到队列中。 从队列中把事件取出来后,会检查paused(Deployment是否需要新的发布) ReplicaSet Controller也通过Informer机制监听ReplicaSet资源来维持应用希望的状态数量,但是只管理副本数。如果发现replicas比Pod数量大的话扩容,比实际数量小就缩容。 假如rsA的replicas从2被改到3。 首先,Reflector会watch到ReplicaSet和Pod两种资源的变化,在DeltaFIFO中塞入了对象是rsA、类型是Updated的记录。 Informer把新的ReplicaSet更新到Index中并调用Update的回调函数。 ReplicaSet Controller的Update回调函数发现ReplicaSet变化后会把nsA/rsA作为key值加入到工作队列中, ReplicaSet Controller会并发启动多个worker,以处理不同的对象实例。 worker池中一个worker从工作队列中取到了key(nsA/rsA),并从Index中取到了ReplicaSet rsA的最新数据。 worker通过比较rsA的spec和status里的数值,发现需要对它进行扩容,因此创建了一个Pod。这个Pod的Ownereference指向向了ReplicaSet rsA。 worker如果处理失败,一般会把key重新加入到工作队列中,从而方便之后进行重试。 然后Reflector watch到的Pod新增事件,在DeltaFIFO中塞入了对象是Pod、类型是Add的记录。 Informer把新的Pod更新到Index中并调用ReplicaSet Controller的Add的回调函数。 ReplicaSet Controller的Add回调函数通过检查Pod的ownerReferences找到了对应的ReplicaSet,并把nsA/rsA字符串塞入到了工作队列中。 woker在得到新的工作项后,从缓存中取到了新的ReplicaSet记录,并得到了其所有创建的Pod。因为ReplicaSet 的status不是最新的(创建的Pod总数还未更新)。因此在此时ReplicaSet更新status使得spec和status达成一致。 StatefulSet Deployment认为:它管理的所有相同版本的Pod都是一模一样的副本。也就是说,在Deployment Controller看来,所有相同版本的Pod都是完全相同的。 StatefulSet的特征:- 每个Pod会有Order序号,会按照序号来创建、删除、更新Pod;
- 通过配置一个headless Service,使每个Pod有一个唯一的网络标识(hostname)
- 通过配置PVC模板,使每个Pod有一块或者多块PV存储盘;
- 支持一定数量的灰度发布。比如某StatefulSet有3副本,可以指定只升级其中的一个或者两个到新版本。
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginxStatefulSet的.spec.serviceName需要对应Headless Service的名字 也可以随便取一个错误的名字(不会做校验)。此时不会为Pod分配唯一的hostname
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx # has to match .spec.template.metadata.labels serviceName: “nginx” replicas: 3 # by default is 1 template: metadata: labels: app: nginx # has to match .spec.selector.matchLabels spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "my-storage-class" resources: requests: storage: 1GiStatefulSet创建了三种资源:
- ControllerRevision
- PVC
- Pod
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.spec.template.spec就是pod的spec。 .spec.template.spec.restartPolicy是重启策略,可以设置Never、OnFailure、Always三种。 若要并行运行job,还需要在spec中增加两个参数: (1).spec.completions:指定本Pod队列执行次数,即该Job指定的可以运行的总次数。 (2).spec.parallelism:代表并行执行的个数,即一个管道或者缓冲器中缓冲队列的大小。 例如completions设置为8,parallelism设置成 2。即Job一定要执行8次,每次并行2个Pod,一共会执行4个批次。 .spec.backoffLimit表示一个Job到底能重试多少次。
$ kubectl get jobs Name COMPLETIONS DURATION AGE pi 1/1 71s 4m6s
COMPLETIONS:任务里有几个Pod,其中完成了多少个。
DURATION:Job里面的实际业务运行了多长时间。
AGE:这个Pod创建了多少时间。
selector: matchLabels: controller-uid: df858f2d-82cf-4726-85e9-8e7899d13d74创建的Pod会自动加上controller-uid:xxx和的标签 如果job运行失败,.status.conditions中会显示Failed的reson和message
status: conditions: - lastProbeTime: "2020-10-20T12:09:53Z" lastTransitionTime: "2020-10-20T12:09:53Z" message: Job has reached the specified backoff limit reason: BackoffLimitExceeded status: "True" type: Failed failed: 2 startTime: "2020-10-20T12:09:07Z"job的yaml文件无法看出Job创建了哪些Pod,只能通过kubectl describe job xxx看相应的Event,发现Job会创建叫job−name−{random-suffix}的Pod: CronJob CronJob主要是用来运作一些定时任务(如Jenkins构建等),和Job相比会多几个不同的字段:
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 Kubernetes cluster restartPolicy: OnFailure.spec.schedule:设置时间格式,格式和Linux的crontab一样 .spec.startingDeadlineSeconds:每次运行Job的时候最长可以等多长时间,超过时间CronJob就会停止这个 Job .spec.concurrencyPolicy:是否允许并行运行。 PS:并行运行指的是,如果Job运行的时间特别长,第二个Job需要运行的时候上一个Job还没完成,会同时运行两个Job。 .spec.successfulJobsHistoryLimit:定时Job的执行历史的存留数。 DaemonSet DaemonSet也是Kubernetes提供的一个default controller,它是一个守护进程的控制器,能帮我们做到以下几件事情: 保证集群内的每一个节点都运行一组相同的 pod 根据节点的状态保证新加入的节点自动创建对应的 pod 在移除节点的时候,能删除对应的 pod 跟踪每个 pod 的状态,当pod出现异常会及时recovery 常用于以下几点内容: 存储:需要每台节点上都运行一个类似于 Agent 的东西 日志收集:如logstash或者fluentd,需要每台节点都运行一个Agent 监控:如说Promethues 配置示例:
apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-elasticsearch namespace: kube-system labels: k8s-app: fluentd-logging spec: selector: matchLabels: name: fluentd-elasticsearch template: metadata: labels: name: fluentd-elasticsearch spec: tolerations: containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2创建的Daemonset会在每个node创建叫daemonset−name−{random-suffix}的Pod,通过matchLabel去管理对应所属的Pod
$ kubectl get ds NAME DESIRED CURRENT READY UP-TO-DATA AVAILABLE NODE ELECTION AGE fluentd-elasticsearch 4 4 4 4 4 <node> 4sDESIRED:需要的pod个数 CURRENT:当前已存在pod个数 READY:就绪的个数 UP-TO-DATA:最新创建的个数 AVAILABLE:可用pod个数 NODE ELECTION:节点选择数 DaemonSet有两种更新策略: RollingUpdate(默认):先更新第一个Pod,然后老的Pod被移除,通过健康检查之后再建第二个Pod OnDelete:模板更新后,Pod不会有任何变化。除非手动删除某一个节点上的Pod DaemonSet Controller实现原理: 大体上与Job Controller类似,不过它还会监控Node的状态,根据配置的affinity或者label去选择对应的节点后,进行Pod的创建、Pod的版本比较和升级等。 更新完了之后,它会更新整个DaemonSet的状态