赞
踩
- 背景:我们可以直接管理集群中所有的Pod吗?
- 如果这样做,以下的问题有什么方式来解决?
- 1)如何保证集群内可用Pod的数量
- 2)如何为所有的Pod更新镜像版本
- 3)更新的过程中,如何保证服务的可用性
- 4)更新的过程中,发现问题如何快速回滚
- Deploymet:管理部署发布的控制器,能够帮我们做什么?
- 1)定义一组pod的期望数量,controller会维持Pod数量与期望数量一致
- 2)配置Pod发布方式,controller会按照给定策略更新Pod,保证更新过程中不可用的pod数量在限定范围内
- 3)如果发布有问题,支持“一键”回滚
- 1、Deployment语法
- [root@master1 yaml]# cat deployment.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: nginx
- name: nginx-deployment
- spec:
- replicas: 3 #期望副本数量
- selector:
- matchLabels:
- app: nginx
- template: #pod模板
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/nginx:v1
- name: nginx
- ports:
- - containerPort: 80
-
- 2、创建pod
- [root@master1 yaml]# kubectl apply -f deployment.yaml
- deployment.apps/nginx-deployment created
- [root@master1 yaml]# kubectl get deployment
- NAME READY UP-TO-DATE AVAILABLE AGE
- nginx-deployment 3/3 3 3 57s
-
- DESIRED: 期望pod数量(replicas)
- CURRENT:当前实际的pod数量
- UP-TO-DATE: 当达到期望版本的pod数量
- AVAILABLE:运行中并可用的pod数量
- AGE: deployment创建的时长
-
- [root@master1 yaml]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- nginx-deployment-675d5d8757 3 3 3 64s
-
- [root@master1 yaml]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- nginx-deployment-675d5d8757-9jlkg 1/1 Running 0 68s
- nginx-deployment-675d5d8757-jxfwt 1/1 Running 0 68s
- nginx-deployment-675d5d8757-w982m 1/1 Running 0 68s
- pod名字格式: ${deployment-name}-${template-hash}-${random-suffix}
-
- 3、更新镜像
- [root@master1 yaml]# kubectl set image deployment/nginx-deployment nginx=reg.mt.com:5000/nginx:v2
- deployment.extensions/nginx-deployment image updated
- [root@master1 yaml]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- nginx-deployment-54ccbb99b8 3 3 2 5s
- nginx-deployment-675d5d8757 1 1 1 10m
- [root@master1 yaml]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- nginx-deployment-54ccbb99b8 3 3 3 18s #nginx:v2的 replicaset
- nginx-deployment-675d5d8757 0 0 0 10m #nginx:v1的 pod逐渐为0
- [root@master1 yaml]# kubectl set image deployment/nginx-deployment nginx=reg.mt.com:5000/nginx:latest #最后一个参数nginx为容器名称,一个pod内有多个容器,需要指定容器名
- [root@master1 yaml]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- nginx-deployment-54ccbb99b8 3 3 3 69s
- nginx-deployment-675d5d8757 0 0 0 11m
- nginx-deployment-697b6ffb7f 1 1 0 2s #nginx:latest的pod 为逐渐为3
-
- [root@master1 yaml]# kubectl get deployment -o yaml
- --
- spec:
- progressDeadlineSeconds: 600
- replicas: 3
- revisionHistoryLimit: 10 #保留历史版本个数
- --
- [root@master1 yaml]#
-
- 4、回滚到上一个版本,当前为nginx:latest回滚到nginx:v2,如果执行两次就回滚到nginx:latest
- [root@master1 yaml]# kubectl get replicaset -o wide
- NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
- nginx-deployment-54ccbb99b8 0 0 0 14m nginx reg.mt.com:5000/nginx:v2 app=nginx,pod-template-hash=54ccbb99b8
- nginx-deployment-675d5d8757 0 0 0 24m nginx reg.mt.com:5000/nginx:v1 app=nginx,pod-template-hash=675d5d8757
- nginx-deployment-697b6ffb7f 3 3 3 12m nginx reg.mt.com:5000/nginx:latest app=nginx,pod-template-hash=697b6ffb7f
- [root@master1 yaml]# kubectl rollout undo deployment/nginx-deployment
- deployment.extensions/nginx-deployment rolled back
- [root@master1 yaml]# kubectl get replicaset -o wide
- NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
- nginx-deployment-54ccbb99b8 3 3 3 14m nginx reg.mt.com:5000/nginx:v2 app=nginx,pod-template-hash=54ccbb99b8
- nginx-deployment-675d5d8757 0 0 0 24m nginx reg.mt.com:5000/nginx:v1 app=nginx,pod-template-hash=675d5d8757
- nginx-deployment-697b6ffb7f 0 0 0 13m nginx reg.mt.com:5000/nginx:latest app=nginx,pod-template-hash=697b6ffb7f
- [root@master1 yaml]#
-
- 5、回滚到特定版本
- [root@master1 yaml]# kubectl rollout history deployment/nginx-deployment
- deployment.extensions/nginx-deployment
- REVISION CHANGE-CAUSE
- 1 <none>
- 4 <none>
- 5 <none>
- [root@master1 yaml]# kubectl rollout undo deployment/nginx-deployment --to-revision=1
- deployment.extensions/nginx-deployment rolled back
- [root@master1 yaml]# kubectl get replicaset -o wide
- NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
- nginx-deployment-54ccbb99b8 0 0 0 24m nginx reg.mt.com:5000/nginx:v2 app=nginx,pod-template-hash=54ccbb99b8
- nginx-deployment-675d5d8757 3 3 3 34m nginx reg.mt.com:5000/nginx:v1 app=nginx,pod-template-hash=675d5d8757
- nginx-deployment-697b6ffb7f 0 0 0 23m nginx reg.mt.com:5000/nginx:latest app=nginx,pod-template-hash=697b6ffb7f
- [root@master1 yaml]#
6、版本
在需要更复杂的或者更精确的历史版本管理方案的时候,建议使用helm进行版本管理
管理模式:
Deployment controller做了一些更复杂的操作,比如版本管理;把pod数量的维持工作交给replicaset controller操作。
Deployment的副本数由ReplicaSet管理,修改Deployment replicas之后,controller会把replicas同步到当前版本的Replicaset中,由Replicaset执行扩容/缩容。
回滚的过程,其实是Deployment controller重新调整下属的Replicaset的replicas数量,最终使旧版本的ReplicaSet重新扩出所有的Pod。重新创建出符合旧版本template的pod
- MinReadySeconds:判断Pod available的最小ready时间。ready的pod不一定是available
- revisionHistoryLimit:保留历史revision(ReplicaSet)的数量,默认值10
- paused:标识deployment只做数量维持、不做新的发布;在debug上可能会用到
- progressDeadlineSeconds:判断Deployment status condition为failed的最大时间
-
- 升级策略字段解析:
- MaxUnavailable:滚动过程中最多有多少个Pod不可用
- MaxSurege:滚动过程中最多存在多少个Pod超过期望replicas数量
-
- 当资源比较充足的时候,可以设置MaxUnavailable较小,而MaxSurege较大。在资源紧张的时候,可以设置MaxSurege为0.但是注意MaxSurege和MaxUnavailable不同同时为0
- 首先我们来看一下 Job 的需求来源。我们知道 K8s 里面,最小的调度单元是 Pod,我们可以直接通过 Pod 来运行任务进程。这样做将会产生以下几种问题:
-
- 1)我们如何保证 Pod 内进程正确的结束?
- 2)如何保证进程运行失败后重试?
- 3)如何管理多个任务,且任务之间有依赖关系?
- 4)如何并行地运行任务,并管理任务的队列大小?
Kubernetes 的 Job 为我们提供了什么功能:
- [root@master1 yaml]# cat job.yaml
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: my-job
- spec:
- template:
- spec:
- containers:
- - image: reg.mt.com:5000/centos:v1
- name: my-job
- resources: {}
- restartPolicy: Never #重启策略
- backoffLimit: 4 #重试次数限制
- [root@master1 yaml]# kubectl get job
- NAME COMPLETIONS DURATION AGE
- my-job 1/1 3s 3s
- COMPLETIONS: 完成pod数量
- DURATION: Job实际业务运行时长
- AGE: job创建的时长
-
- [root@master1 yaml]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- my-job-tzccn 0/1 Completed 0 2m21s
-
-
- [root@master1 yaml]# cat job2.yaml
- apiVersion: batch/v1
- kind: Job
- metadata:
- name: my-job
- spec:
- completions: 8
- parallelism: 2
- template:
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- name: my-job
- command: ["/bin/sh"]
- args: ["-c","sleep 30;date"]
- restartPolicy: OnFailure
- backoffLimit: 4
-
- parallelism #代表并行执行个数,这里的2代表并行执行的pod数量,也就是说会有2个pod并行运行
- completions #代表本pod队列执行次数,这里8代表这个任务将被执行8次
- [root@master1 yaml]# cat cron.yaml
- apiVersion: batch/v1beta1
- kind: CronJob
- metadata:
- name: hello
- spec:
- schedule: "*/1 * * * *"
- jobTemplate:
- spec:
- parallelism: 2
- completions: 8
- template:
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- name: hello
- args:
- - /bin/sh
- - -c
- - date;sleep 10;echo Hello from MT
- resources: {}
- restartPolicy: OnFailure
- startingDeadlineSeconds: 10
- concurrencyPolicy: Allow
- successfulJobsHistoryLimit: 3
-
- 参数说明:
- backoffLimit: 4 #重试次数限制
- startingDeadlineSeconds: 10 #job最长启动时间
- concurrencyPolicy: Allow #是否允许并行运行,并行,如果是false就会等待上一个job执行完毕后才会进行下一个pod
- successfulJobHistoryLimit: 3 #允许留存历史job个数
-
-
- [root@master1 yaml]# kubectl get jobs -w #每2个pod并行运行,共8个pod
- hello-1611469980 0/8 0s
- hello-1611469980 0/8 0s 0s
-
- hello-1611469980 1/8 11s 11s
- hello-1611469980 2/8 11s 11s
-
- hello-1611469980 3/8 22s 22s
- hello-1611469980 4/8 22s 22s
-
- hello-1611469980 5/8 33s 33s
- hello-1611469980 6/8 34s 34s
-
- hello-1611469980 7/8 44s 44s
- hello-1611469980 8/8 45s 45s
管理模式:
Job Controller 主要去创建相对应的 pod,然后 Job Controller 会去跟踪 Job 的状态,及时地根据我们提交的一些配置重试或者继续创建。同时我们刚刚也提到,每个 pod 会有它对应的 label,来跟踪它所属的 Job Controller,并且还去配置并行的创建, 并行或者串行地去创建 pod。
Job控制器:
Job controller会去watch apiserver,存放到queue中;我们通过yaml 提交job会经过apiserver到etcd中
job controller 检查是否有当前运行的pod,如果没有scale up创建出来。如果有的话或者大于并行度的话进行scale down
同时要去检查它是否是并行的 job,或者是串行的 job,根据设置的配置并行度、串行度,及时地把 pod 的数量给创建出来。最后,它会把 job 的整个的状态更新到 API Server 里面去
- 背景:同样的问题:如果我们没有 DaemonSet 会怎么样?下面有几个需求:
- 首先如果希望每个节点都运行同样一个 pod 怎么办?
- 如果新节点加入集群的时候,想要立刻感知到它,然后去部署一个 pod,帮助我们初始化一些东西,这个需求如何做?
- 如果有节点退出的时候,希望对应的 pod 会被删除掉,应该怎么操作?
- 如果 pod 状态异常的时候,我们需要及时地监控这个节点异常,然后做一些监控或者汇报的一些动作,那么这些东西运用什么控制器来做?
- DaemonSet 也是 Kubernetes 提供的一个 default controller,它实际是做一个守护进程的控制器,它能帮我们做到以下几件事情:
- 首先能保证集群内的每一个节点都运行一组相同的 pod;
- 同时还能根据节点的状态保证新加入的节点自动创建对应的 pod;
- 在移除节点的时候,能删除对应的 pod;
- 而且它会跟踪每个 pod 的状态,当这个 pod 出现异常、Crash 掉了,会及时地去 recovery 这个状态。
适用场景:
- #1、创建daemonset
- [root@master1 yaml]# cat ds.yaml
- apiVersion: extensions/v1beta1
- kind: DaemonSet
- metadata:
- name: ds
- spec:
- selector:
- matchLabels:
- app: centos-ds
- template:
- metadata:
- labels:
- app: centos-ds
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- imagePullPolicy: Always
- name: my-centos
- command: ["/usr/bin/tail","-f","/etc/hosts"]
- restartPolicy: Always
- updateStrategy:
- type: RollingUpdate
- rollingUpdate:
- maxUnavailable: 1
-
- RollingUpdate: 滚动更新
- OnDelete:只有在删除的时候才有
- [root@master1 yaml]# kubectl get ds
- NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
- ds 3 3 3 3 3 <none> 88s
- [root@master1 yaml]#
- DESIRED:需要的pod个数
- CURRENT:当前的pod个数
- READY:就绪的个数
- UP-TO-DATE:最新创建的个数
- AVAILABLE:可用pod个数
- NODE SELECTOR:节点选择器标签
-
- #2、指定node创建daemonset
- [root@master1 yaml]# kubectl label nodes/master3 ds=true #为master3添加标签
- [root@master1 yaml]# cat ds.yaml
- apiVersion: extensions/v1beta1
- kind: DaemonSet
- metadata:
- name: ds
- spec:
- selector:
- matchLabels:
- app: centos-ds
- template:
- metadata:
- labels:
- app: centos-ds
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- imagePullPolicy: Always
- name: my-centos
- command: ["/usr/bin/tail","-f","/etc/hosts"]
- restartPolicy: Always
- nodeSelector:
- ds: "true"
- updateStrategy:
- type: RollingUpdate
- rollingUpdate:
- maxUnavailable: 1
- [root@master1 yaml]#
- [root@master1 yaml]# kubectl get ds
- NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
- ds 1 1 1 1 1 ds=true 13m
DaemonSet 还是一个 controller,真正的业务单元也是 Pod,DaemonSet 其实和 Job controller 特别相似,它也是通过 controller 去 watch API Server 的状态,然后及时地添加 pod。唯一不同的是,它会监控节点的状态,节点新加入或者消失的时候会在节点上创建对应的 pod,然后同时根据你配置的一些 affinity 或者 label 去选择对应的节点。
当有 node 状态节点发生变化时,它会通过一个内存消息队列发进来,然后DaemonSet controller 会去 watch 这个状态,看一下各个节点上是都有对应的 Pod,如果没有的话就去创建。当然它会去做一个对比,如果有的话,它会比较一下版本,然后根据更新策略,决定如何更新pod,Ondelete 删除 pod 的时候也会去做 check 它做一遍检查,是否去更新,或者去创建对应的 pod。
- 背景:用一个容器镜像来启动一个 container。要启动这个容器,其实有很多需要配套的问题待解决:
-
-
- 1)比如说一些可变的配置。因为我们不可能把一些可变的配置写到镜像里面,当这个配置需要变化的时候,可能需要我们重新编译一次镜像,这个肯定是不能接受的;
- 2)一些敏感信息的存储和使用。比如说应用需要使用一些密码,或者用一些 token;
- 3)我们容器要访问集群自身。比如我要访问 kube-apiserver,那么本身就有一个身份认证的问题;
- 4)容器在节点上运行之后,它的资源需求;
- 5)容器在节点上,它们是共享内核的,那么它的一个安全管控怎么办?
- 6)容器启动之前的一个前置条件检验。比如说,一个容器启动之前,我可能要确认一下 DNS 服务是不是好用?又或者确认一下网络是不是联通的?那么这些其实就是一些前置的校验。
可变配置:ConfigMap
敏感信息:Secret
身份认证:ServiceAccount
资源配置:Spec.Containers[].Resources.limit/requests
安全管控:Spec.Containers[].SecurityContext
前置校验:Spec.InitContainers
主要管理容器运行所需的配置文件,环境变量,命令行参数等可变配置。用于解耦容器镜像和可变配置,从而保障工作负载(pod)的可移植性。
创建命令:
- kubectl create configmap [NAME] [DATA] //DATA可以是指定文件或者目录,或者键值对
- kubectl create configmap kube-flannel-cfg --from-file=${filename} -n kube-system
- kubectl create configmap special-config --from-literal=special.how=very --from-literal=sepcial.type=charm -n kube-system
使用configmap:
Configmap主要被Pod使用,一般用于挂载Pod用的配置文件,环境变量,命令行参数等
Configmap使用注意点:
示例:
- 使用configmap为pod指定hosts文件
- [root@master1 yaml]# kubectl create configmap host-cm --from-file=/etc/hosts --dry-run -o yaml
- apiVersion: v1
- data:
- hosts: |
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.153.132 master1 etcd1
- 192.168.153.133 master2 etcd2
- 192.168.153.134 master3 etcd3
- 192.168.153.132 reg.mt.com
- kind: ConfigMap
- metadata:
- creationTimestamp: null
- name: host-cm
-
-
- # 文件和deployment合并
- [root@master1 yaml]# cat deployment.yaml
- ---
- apiVersion: v1
- data:
- hosts: |
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.153.132 master1 etcd1
- 192.168.153.133 master2 etcd2
- 192.168.153.134 master3 etcd3
- 192.168.153.132 reg.mt.com
- kind: ConfigMap
- metadata:
- creationTimestamp: null
- name: hostcm
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: nginx
- name: nginx-deployment
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- name: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: hosts
- mountPath: /etc/hosts
- subPath: hosts
- command: ["/usr/bin/tail","-f","/etc/hosts"]
- volumes:
- - name: hosts
- configMap:
- name: hostcm
-
- subPath 说明:在configMap.data中可以定义多个内容,本文中hosts只是其中一个,一个configmap 的data中定义多个key:value,使用subPath引用。这里不加subPath会出现pod起不来的情况
-
- 注意:此时更新configmap,pod不会更新自己的hosts
secret用来存储集群中存储密码,token等敏感信息用的资源对象。其中的敏感数据采用base64编码保存。
secret的类型:
Secret可以是用户自
己建立,也可以是Secrete系统自动创建:
- #创建docker-registry
- kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email
- [--docker-server=string] [--from-literal=key1=value1] [--dry-run] [options]
-
- #从文件创建
- kubectl create secret generic my-secret --from-file=path/to/bar
- kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-file=ssh-publickey=path/to/id_rsa.pub #ssh-privatekey 为指定key名
- kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
- kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-literal=passphrase=topsecret
- kubectl create secret generic my-secret --from-env-file=path/to/bar.env
-
- #创建证书secret
- kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key
使用:
使用私有镜像库:
私有镜像库的信息可以通过Secret(kubernetes.io/dockerconfigjson)存储在集群中,Pod如果需要使用私有镜像仓库,可以通过如下两种方式来配置:
注意事项:
- # 1、docker daemon配置调整
- [root@master1 yaml]# cat /etc/docker/daemon.json
- {
- "graph": "/data/docker",
- "storage-driver": "overlay2",
- "insecure-registries": [
- "reg.mt.com:5000",
- "reg2.mt.com:5000"
- ],
- "registry-mirrors": [
- "http://hub-mirror.c.163.com",
- "https://docker.mirrors.ustc.edu.cn"
- ],
- "exec-opts": ["native.cgroupdriver=systemd"],
- "live-restore": true
- }
-
- 修改后注意重启docker daemon,所有pod都要操作
-
- # 2、安装registry
- echo '192.168.153.133 reg2.mt.com' >> /etc/hosts #追加hosts,所有node操作
- [root@master2 ~]# yum install httpd-tools docker-distribution -y #133节点操作
- [root@master2 ~]# htpasswd -Bbn admin 123456 > /usr/local/passwd
- 参考:https://docs.docker.com/registry/configuration/#htpasswd
- [root@master1 yaml]# cat /etc/docker-distribution/registry/config.yml
- version: 0.1
- log:
- fields:
- service: registry
- storage:
- cache:
- layerinfo: inmemory
- filesystem:
- rootdirectory: /var/lib/registry
- http:
- addr: 192.168.153.132:5000
- [root@master2 ~]# systemctl start docker-distribution
- [root@master2 ~]# docker tag reg.mt.com:5000/nginx:latest reg2.mt.com:5000/nginx:latest
- [root@master2 ~]# docker login reg2.mt.com:5000
- Username: admin
- Password:
- WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
- Configure a credential helper to remove this warning. See
- https://docs.docker.com/engine/reference/commandline/login/
-
- Login Succeeded
- [root@master2 ~]# docker push reg2.mt.com:5000/nginx:latest #可以推送成功
-
- # 3、测试pod
- [root@master1 ~]# kubectl create secret docker-registry reg2 --docker-username=admin --docker-password=123456 --docker-server=http://reg2.mt.com:5000 #注意--server一定要指定,域名和ip是不同的
- [root@master1 yaml]# cat a.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nginx-ds
- annotations:
- environment: "product"
- projectName: "hello world"
- labels:
- dp: nginx
- spec:
- replicas: 3
- selector:
- matchLabels:
- app: nginx-ds
- template:
- metadata:
- labels:
- app: nginx-ds
- spec:
- containers:
- - name: my-nginx
- image: reg2.mt.com:5000/nginx:latest
- ports:
- - containerPort: 80
- imagePullSecrets:
- - name: reg2
-
SA主要用于解决Pod在集群中的身份认证问题,其中认证使用的授权信息,则利用前面讲到Secret(type=kubernetes.io/serviec-account-token)进行管理:
serviceaccount:
secret: "secret由serviceaccount controller自动创建"
Pod中的应用访问它所属的k8s集群:
容器资源配置管理:
1、支持资源类型:
2、配置方法:资源配置分为Request/limit 两种
3、Pod 服务质量Qos配置:
依据容器对CPU,Memory资源的request/limit需求,Pod服务质量分类:
举例:当节点上Memroy资源不足时,将依据BestEffort、Burstable、Guaranteed的优先顺序驱逐pod
主要用于限制容器的行为,从而保障系统和其他容器的安全:
SecurityContext 主要分为三个级别:
权限和访问控制设置项,现在一共列有七项(这个数量后续可能会变化):
权限和访问控制设置项:
示例:
- [root@master1 yaml]# cat deployment.yaml
- ---
- apiVersion: v1
- data:
- hosts: |
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.153.132 master1 etcd1
- 192.168.153.133 master2 etcd2
- 192.168.153.134 master3 etcd3
- 192.168.153.132 reg.mt.com
- kind: ConfigMap
- metadata:
- creationTimestamp: null
- name: hostcm
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: nginx
- name: nginx-deployment
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- name: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: hosts
- mountPath: /etc/hosts
- subPath: hosts
- command: ["/usr/bin/tail","-f","/etc/hosts"]
- securityContext:
- allowPrivilegeEscalation: false
- volumes:
- - name: hosts
- configMap:
- name: hostcm
- securityContext:
- runAsUser: 1001
- runAsGroup: 1001
- [root@master1 yaml]#
-
- securityContext.runAsUser: podpod内进程属主
- securityContext.runAsGroup: pod内进程属组
- containers.securityContext 为container级别
- spec.securityContext为pod级别
接下来看一下 InitContainer,首先介绍 InitContainer 和普通 container 的区别,有以下三点内容:
举例说明: flannel/kube-flannel.yml at master · flannel-io/flannel · GitHub
InitContainer 其实主要为普通 container 服务,比如说它可以为普通 container 启动之前做一个初始化,或者为它准备一些配置文件, 配置文件可能是一些变化的东西。再比如做一些前置条件的校验,如网络是否联通。
引言:
Kubernetes volume分类:
1、为何要引进PV概念?
有了PV,为何又设计了PVC?
1、PV产生方式1-静态产生方式-(static Volume Provisioning)
静态 Provisioning:由集群管理员事先去规划这个集群中的用户会怎样使用存储,它会先预分配一些存储,也就是预先创建一些 PV;然后用户在提交自己的存储需求(也就是 PVC)的时候,K8s 内部相关组件会帮助它把 PVC 和 PV 做绑定;之后用户再通过 pod 去使用存储的时候,就可以通过 PVC 找到相应的 PV,它就可以使用了。
不足之处:cluster admin需要提前规划和预测存储需求,而User的需求是多样化的,很容易导致User提交的PVC找不到合适的PV。举一个最简单的例子:如果用户需要的是 20G,然而集群管理员在分配的时候可能有 80G 、100G 的,但没有 20G 的,这样就很难满足用户的真实需求,也会造成资源浪费。有没有更好的方式呢?
更好的方式:Cluster admin只创建不同类型存储的模板,User在PVC中指定使用哪种存储模板以及自己需要的大小、访问方式等参数,然后k8s自动生成相应的PV对象
2、PV产生方式2-动态生产方式-(Dynamic Volume Provisoning)
这里的StorageClass就是前文所说的创建PV的模板,它包含了创建某种具体类型PV所需的参数信息,user无需关心这些PV的细节。而k8s则会结合PVC和SC两者的信息动态创建PV对象。
地址:Storage Classes | Kubernetes
- [root@master1 yaml]# cat pv.yaml
- ---
- apiVersion: v1
- data:
- hosts: |
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 192.168.153.132 master1 etcd1
- 192.168.153.133 master2 etcd2
- 192.168.153.134 master3 etcd3
- 192.168.153.132 reg.mt.com
- kind: ConfigMap
- metadata:
- creationTimestamp: null
- name: hostcm
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- app: nginx
- name: nginx-deployment
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/centos:latest
- name: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: hosts
- mountPath: /etc/hosts
- subPath: hosts
- - name: hostpath
- mountPath: /opt
- subPath: hostpath1
- - name: cache-volume
- mountPath: /data
- readOnly: true
- command: ["/usr/bin/tail","-f","/etc/hosts"]
- volumes:
- - name: hosts
- configMap:
- name: hostcm
- - name: cache-volume
- emptyDir: {}
- - name: hostpath
- hostPath:
- path: /tmp/data
- type: DirectoryOrCreate
-
- 说明:
- .spec.volumes.emptyDir{}对应宿主机上 ${kubelet-workdir}/pods/${pod-uid}/volumes/kubernetes.io~empty-dir/cache-volume
- .spec.volumes.hostPath在pod删除后,依然存在
- .spec.volumes 声明pod的volumes信息
- .spec.containers.volumeMounts声明container如何使用pod的volumes
- 多个container共享同一个volume时,可以通过.spec.containers.volumesMounts.subPath隔离不同容器在同一个volume上数据存储的路径
以使用阿里云文件系统NAS为例:
cluster admin:
1.通过阿里云文件存储控制台,创建NAS文件系统和添加挂载点
2.创建PV对象,将NAS文件系统大小,挂载点,以及PV的access mode,reclaim policy等信息添加到PV对象中
User:
1.创建pvc对象,声明存储需求
2.创建应用pod并通过在.spec.volumes中通过pvc声明volume,通过.spec.containers.volumeMounts声明conainer挂载使用该volume
系统管理员预先创建PV:
static volume provisioning实验:使用aliyunnas存储:
(csi-nasplugin是为了在k8s中使用阿里云NAS所需的插件,csi-disk是为了在k8s中使用阿里云云盘所需要的插件)
在两个pod内执行:findmnt 会发现/data/的挂载源一样,手动删除pvc后,pv是依旧存在的,状态是release状态
PV的一些重要字段:
用户在提交 PVC 的时候,最重要的两个字段 —— Capacity 和 AccessModes。在提交 PVC 后,k8s 集群中的相关组件是如何去找到合适的 PV 呢?首先它是通过为 PV 建立的 AccessModes 索引找到所有能够满足用户的 PVC 里面的 AccessModes 要求的 PV list,然后根据PVC的 Capacity,StorageClassName, Label Selector 进一步筛选 PV,如果满足条件的 PV 有多个,选择 PV 的 size 最小的,accessmodes 列表最短的 PV,也即最小适合原则。
ReclaimPolicy:这个就是刚才提到的,用户在 PV 的 PVC 在删除之后,我的 PV 应该做如何处理?常见的有三种方式。
StorageClassName:StorageClassName 动态 Provisioning 时必须指定的一个字段,就是说我们要指定到底用哪一个模板文件来生成 PV ;
NodeAffinity:就是说我创建出来的 PV,它能被哪些 node 去挂载使用,其实是有限制的。然后通过 NodeAffinity 来声明对node的限制,这样其实对使用该PV的pod调度也有限制,就是说 pod 必须要调度到这些能访问 PV 的 node 上,才能使用这块 PV,这个字段在我们下一讲讲解存储拓扑调度时在细说。
Dynamic volume provisioning实验:使用aliyun云盘
PV创建请求提交后处于pending状态,创建完成后处于available状态,被k8s相关组件bound后(找到相应的pv)这个时候PV和PVC就结合在一起了,此时两者都是bound状态。当用户使用完PVC,将其删除后,这个PV就处于release状态。之后它应该是被删除还是被保留呢?这个就依赖ReclaimPolicy。
说明:到达released状态的pv无法根据recliaim policy回到available状态再次bound新的PVC。此时,如果想复用原来PV对应的存储中的数据,只有两种方式:
pv&pvc内部处理流程:
csi 是什么?csi 的全称是 container storage interface,它是K8s社区后面对存储插件实现(out of tree)的官方推荐方式。
csi 的实现大体可以分为两部分:
用户提交 yaml 之后,k8s内部的处理流程: 用户在提交 PVC yaml 的时候,首先会在集群中生成一个 PVC 对象,然后 PVC 对象会被 csi-provisioner controller watch到,csi-provisioner 会结合 PVC 对象以及 PVC 对象中声明的 storageClass,通过 GRPC 调用 csi-controller-server,然后,到云存储服务这边去创建真正的存储,并最终创建出来 PV 对象。最后,由集群中的 PV controller 将 PVC 和 PV 对象做 bound 之后,这个 PV 就可以被使用了。
用户在提交 pod 之后,首先会被调度器调度选中某一个合适的node,之后该 node 上面的 kubelet 在创建 pod 流程中会通过首先 csi-node-server 将我们之前创建的 PV 挂载到我们 pod 可以使用的路径,然后 kubelet 开始 create && start pod 中的所有 container。
主要分为三个阶段:
总的来说,有三个阶段:第一个 create 阶段,主要是创建存储;第二个 attach 阶段,就是将那块存储挂载到 node 上面(通常为将存储load到node的/dev下面);第三个 mount 阶段,将对应的存储进一步挂载到 pod 可以使用的路径。这就是我们的 PVC、PV、已经通过CSI实现的卷从创建到使用的完整流程。
- 存储快照产生背景:
- 1、如何保证重要数据在误操作之后可以快速恢复,以提高数据容错率
- 2、如何能够快速进行复制,迁移重要数据的动作?如进行环境复制与数据开发等
-
- Kubernetes CSI Snapshotter controller正式为了解决这些问题而设计的
存储快照的设计是仿照PV&PVC的设计思想。当用户需要存储快照的功能时,可以通过 VolumeSnapshot 对象来声明,并指定相应的 VolumeSnapshotClass 对象,之后由集群中的相关组件动态生成存储快照以及存储快照对应的对象 VolumeSnapshotContent。
PVC对象(PersistentVolumeChain)借助于扩展字段 .spec.dataSource指定为VolumeSnapshot对象,这样PVC提交之后,会由集群中的相关组件找到dataSource所指定的存储快照数据,然后新创建对应的存储以及pv对象,将存储快照数据恢复到新的pv中,这样数据就恢复回来了
1、定义:
Topology:这里所说的拓扑是 K8s 集群中为管理的 nodes 划分的一种“位置”关系,并通过在 node 的 labels 信息里面填写某一个 node 属于某一个拓扑。常见的Node labels 有三种:
也可以定义一个字符串来表示一个拓扑域,这个 key 所对应的值其实就是拓扑域下不同的拓扑位置。
例如:可以用 rack,也就是机房中的机架这个纬度来做一个拓扑域。这样就可以将不同机架 (rack) 上面的机器标记为不同的拓扑位置,也就是说可以将不同机架上机器的位置关系通过 rack 这个纬度来标识。属于 rack1 上的机器,node label 中都添加 rack 的标识,它的 value 就标识成 rack1,即 rack=rack1;另外一组机架上的机器可以标识为 rack=rack2,这样就可以通过机架的纬度就来区分来 K8s 中的 node 所处的位置。
2、产生背景:
kubernetes中通过PV&PVC体系将存储和计算分离,即使用不同的Controllers管理存储资源和计算资源。但如果创建的PV有访问“位置”(.spec.nodeAffinity)的限制,也就是只有在特定的一些Nodes才能访问PV。原有的创建Pod的流程与创建PV的流程分离,就无法保证新创建的Pod被调度到可以访问PV的Nodes上,最终导致Pod无法正常运行起来,如:
场景1:pod要访问本机的磁盘,用来提高io性能(SSD),但是如果pod创建在了Node1,但是PV创建在了Node2上就不会达到性能提高的目的
场景2:不同可用区,PV创建在了其他的zone
3、存储拓扑调度
1)本质问题:PV在Binding或者Dynamic Provisoning时,并不知道使用它的Pod会被调用到哪些Node上,但PV本身的访问对Node的“位置”(拓扑)有限制。
2)流程改进:
Binding/Dynamic Provisoning PV的操作Delay到Pod调度结果确定之后做,好处:
3)Kubernetes组件改进:
- Local PV 大部分使用的时候都是通过静态创建的方式,也就是要先去声明 PV 对象,既然 Local PV 只能是本地访问,就需要在 PV 对象中通过 nodeAffinity 来限制我这个 PV 只能在单 node 上访问,也就是给这个 PV 加上拓扑限制。如上图拓扑的 key 用 kubernetes.io/hostname 来做标记,也就是只能在 node1 访问。如果想用这个 PV,你的 pod 必须要调度到 node1 上。
-
- 既然是静态创建 PV 的方式,这里为什么还需要 storageClassname 呢?因为在 Local PV 中,如果要想让它正常工作,需要用到延迟绑定特性才行,当用户在写完 PVC 提交之后,即使集群中有相关的 PV 能跟它匹配,它也暂时不能做匹配,也就是说 PV controller 不能马上去做 binding,这个时候你就要通过一种手段来告诉 PV controller,什么情况下是不能立即做 binding。这里的 storageClass 就是为了起到这个作用,我们可以看到 storageClass 对象里的 provisioner 指定的是 **no-provisioner**,其实就是相当于告诉 K8s 它不会去动态创建 PV,它主要用到 storageclass 的 VolumeBindingMode 字段,叫 WaitForFirstConsumer,可以先简单地认为它是延迟绑定。
-
- 当用户开始提交 PVC 的时候,pv controller 在看到这个 pvc 的时候,它会找到相应的 storageClass,发现这个 BindingMode 是延迟绑定,它就不会做任何事情。
-
- 在调度的时候,当pod恰好调度在符合 pv nodeaffinity 的 node 的上面后,这个 pod 里面所使用的 PVC 才会真正地与 PV 做绑定,这样就保证我 pod 调度到这台 node 上之后,这个 PVC 才与这个 PV 绑定,最终保证的是创建出来的 pod 能访问这块 Local PV
- 动态就是指动态创建PV 有拓扑位置的限制,那怎么去指定?
-
- 首先在 storageclass 还是需要指定 BindingMode,就是 WaitForFirstConsumer,就是延迟绑定。
- 其次就是 allowedTopologies,限制就在这个地方。上图中可以看到拓扑限制是可用区的级别,这里其实有两层意思:
- 1、第一层意思就是说我在动态创建 PV 的时候,创建出来的 PV 必须是在这个可用区可以访问的;
- 2、第二层含义是因为声明的是延迟绑定,那调度器在发现使用它的 PVC 正好对应的是该 storageclass 的时候,调度 pod 就要选择位于该可用区的 nodes。
-
- 用户在写 PVC 文件的时候,写法是跟以前的写法是一样的,主要是在 storageclass 中要做一些拓扑限制。
步骤:1、创建storageclass ;2、创建pvc ;3、创建pod 绑定;
pvc创建后处于 pending 状态,在pod绑定时候的时候才会。限定node所在的可用区
首先先解释一下 csi 部分。K8s 中对存储的扩展功能都是推荐通过csi out-of-tree 的方式来实现的。
csi 实现存储扩展主要包含两部分:
两部分部件通过 unix domain socket 通信连接到一起。有这两部分,才能形成一个真正的存储扩展功能。
当用户提交 VolumeSnapshot 对象之后,会被 csi-snapshottor controller watch 到。之后它会通过 GPPC 调用到 csi-plugin,csi-plugin 通过 OpenAPI 来真正实现存储快照的动作,等存储快照已经生成之后,会返回到 csi-snapshottor controller 中,csi-snapshottor controller 会将存储快照生成的相关信息放到 VolumeSnapshotContent 对象中并将用户提交的 VolumeSnapshot 做 bound。这个 bound 其实就有点类似 PV 和 PVC 的 bound 一样。
有了存储快照,如何去使用存储快照恢复之前的数据呢?通过声明一个新的 PVC 对象,并且指定他的 dataSource 为 Snapshot 对象,当提交 PVC 的时候会被 csi-provisioner watch 到,之后会通过 GRPC 去创建存储(create volume)。这里创建存储跟之前讲解的 csi-provisioner 有一个不太一样的地方,就是它里面还指定了 Snapshot 的 ID,当去云厂商创建存储时,需要多做一步操作,即将之前的快照数据恢复到新创建的存储中。之后流程返回到csi-provisioner,它会将新创建的存储的相关信息写到一个新的 PV 对象中,新的 PV 对象被 PV controller watch 到它会将用户提交的 PVC 与 PV 做一个 bound,之后 pod 就可以通过 PVC 来使用Restore 出来的数据了。
经过这上面步骤之后,就找到了所有即满足 pod 计算资源需求又满足 pod 存储资源需求的所有 nodes。
第三个步骤就是调度器内部做的一个优化(node筛选出来之后)
**第四个步骤 ** binding/dynamic create PV
需求来源:当我们迁移应用到kubernetes后,要如何保障应用健康稳定?
当应用的Pod已经运行起来,如何让kubernetes检查应用的状态,判断是否准备好对外提供服务?
Readiness Probe:判断pod是否处于就绪状态,pod处于就绪状态的时候才会对外提供服务。当pod状态不在Readness的时候则进行流量摘除
Liveiess Probe:判断pod是否需要被重新拉起,如果配置的策略为restartAlways的时候,那么此时这个pod将被重新拉起
应用健康状态-使用方式:
其他参数:
initialDelaySeconds:pod 启动延迟多久进行一次检查,比如说现在有一个 Java 的应用,它启动的时间可能会比较长,因为涉及到 jvm 的启动,包括 Java 自身 jar 的加载;
periodSeconds:检测的时间间隔,正常默认的这个值是 10 秒;
timeoutSeconds:它表示的是检测的超时时间,当超时时间之内没有检测成功,那它会认为是失败的一个状态;
successThreshold:当 pod 从探测失败到再一次判断探测成功,所需要的阈值次数,默认情况下是 1 次,表示原本是失败的,那接下来探测这一次成功了,就会认为这个 pod 是处在一个探针状态正常的一个状态;
failureThreshold:探测失败的重试次数,默认值是 3,表示的是当从一个健康的状态连续探测 3 次失败,那此时会判断当前这个pod的状态处在一个失败的状态。
小结:
- [root@master1 yaml]# cat pod2.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- creationTimestamp: null
- name: nginx
- labels:
- app: nginx
- namespace: default
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/nginx:latest
- name: nginx2
- resources: {}
- ports:
- - containerPort: 80
- livenessProbe:
- tcpSocket:
- port: 80
- initialDelaySeconds: 10
- periodSeconds: 3
- readinessProbe:
- successThreshold: 1
- periodSeconds: 5
- httpGet:
- path: /
- port: 80
- timeoutSeconds: 5
- initialDelaySeconds: 10
执行Kubectl describe pods/${pod名称}输出:
Pod状态为Pending,可能会转换到running/Unknown/FAILED/SUCCEED。container(nginx)状态为Waiting,conditions为k8s中很多小的状态,而这个状态的聚合会变成上层的status; K8s 里面这个状态机制之间这个状态转换会产生相应的事件,而这个事件又通过类似像 normal 或者是 warning 的方式进行暴露。开发者可以通过类似像通过这个事件的机制,可以通过上层 condition Status 相应的一系列的这个字段来判断当前这个应用的具体的状态以及进行一系列的诊断。
k8s pod状态机:
Value | Description |
---|---|
Pending | The Pod has been accepted by the Kubernetes cluster, but one or more of the containers has not been set up and made ready to run. This includes time a Pod spends waiting to be scheduled as well as the time spent downloading container images over the network. |
Running | The Pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting. |
Succeeded | All containers in the Pod have terminated in success, and will not be restarted. |
Failed | All containers in the Pod have terminated, and at least one container has terminated in failure. That is, the container either exited with non-zero status or was terminated by the system. |
Unknown | For some reason the state of the Pod could not be obtained. This phase typically occurs due to an error in communicating with the node where the Pod should be running. |
kubectl apply -f --validate -f pod2.yaml --dry-run
当前 yaml 是否是正常的,如果 yaml 没有问题,那么接下来可能要诊断配置的端口是否是正常的,以及 Liveness 或 Readiness 是否已经配置正确。分为Pod远程调试和Service远程调试:
进入Pod: kubectl exec -it ${pod-name} /bin/bash
进入Pod内的container: kubectl exec -it ${pod-name} -c ${container-name} /bin/bash
- # 1、port-forward调试
- [root@master1 yaml]# cat pod2.yaml
- apiVersion: "v1"
- kind: "Service"
- metadata:
- name: "nginx-svc"
- namespace: "default"
- labels:
- app: nginx-svc
- spec:
- ports:
- - name: "port-80"
- port: 8080
- targetPort: 80
- selector:
- app: nginx
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- creationTimestamp: null
- name: nginx
- labels:
- app: nginx
- namespace: default
- spec:
- replicas: 1
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - image: reg.mt.com:5000/nginx:latest
- name: nginx2
- resources: {}
- ports:
- - containerPort: 80
- livenessProbe:
- tcpSocket:
- port: 80
- initialDelaySeconds: 10
- periodSeconds: 3
- readinessProbe:
- successThreshold: 1
- periodSeconds: 5
- httpGet:
- path: /
- port: 80
- timeoutSeconds: 5
- initialDelaySeconds: 10
- [root@master1 yaml]# kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-74895b888f-246f6 1/1 Running 0 48s 172.7.25.2 master3 <none> <none>
- [root@master1 yaml]# kubectl get svc/nginx-svc -o wide
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
- nginx-svc ClusterIP 192.168.0.16 <none> 8080/TCP 53s app=nginx
-
- 用法示例:
- 1) kubectl port-forward deployment/mydeployment 5000 6000
- # Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the deployment
-
- 2)kubectl port-forward pod/mypod 8888:5000
- # Listen on port 8888 locally, forwarding to 5000 in the pod
-
- 3)kubectl port-forward --address localhost,10.19.21.23 pod/mypod 8888:5000
- # Listen on port 8888 on localhost and selected IP, forwarding to 5000 in the pod
- 不添加 --address 参数,则监听本机
- [root@master1 yaml]# kubectl port-forward --address 192.168.153.132 svc/nginx-svc 2222:8080
- Forwarding from 192.168.153.132:2222 -> 80
- Handling connection for 2222 # 每执行一个请求,输出一行
- . . .
kubectl-debug #docker和containerd不会在镜像中携带很多的调试工具,底层的容器 runtime 比较常见的就是类似像 docker 或者是 containerd,不论是 docker 还是 containerd,它们使用的一个机制都是基于 Linux namespace 的一个方式进行虚拟化和隔离的。通常情况下 ,并不会在镜像里面带特别多的调试工具,类似像 netstat telnet 等等这些 ,因为这个会造成应用整体非常冗余。那么如果想要调试的时候该怎么做呢?其实这个时候就可以依赖类似于像 kubectl-debug 这样一个工具。kubectl-debug 这个工具是依赖于 Linux namespace 的方式来去做的,它可以 datash 一个 Linux namespace 到一个额外的 container,然后在这个 container 里面执行任何的 debug 动作,其实和直接去 debug 这个 Linux namespace 是一致的。
- 包含:kubectl-debug命令行,debug-agent部署在k8s的node上,用于启动关联排错工具集
- # 1、安装kube-debug
- export PLUGIN_VERSION=0.1.1
- wget https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_linux_amd64.tar.gz
- tar -zxvf kubectl-debug.tar.gz
- mv kubectl-debug /usr/local/bin/
-
- # 2、 安装debu-agent
- # https://raw.githubusercontent.com/aylei/kubectl-debug/master/scripts/agent_daemonset.yml
- [root@master1 yaml]# cat agent_daemonset.yaml
- apiVersion: extensions/v1beta1
- kind: DaemonSet
- metadata:
- labels:
- app: debug-agent
- name: debug-agent
- spec:
- selector:
- matchLabels:
- app: debug-agent
- template:
- metadata:
- labels:
- app: debug-agent
- spec:
- hostPID: true
- tolerations:
- - key: node-role.kubernetes.io/master
- effect: NoSchedule
- containers:
- - name: debug-agent
- image: reg.mt.com:5000/debug-agent:latest
- imagePullPolicy: Always
- securityContext:
- privileged: true
- livenessProbe:
- failureThreshold: 3
- httpGet:
- path: /healthz
- port: 10027
- scheme: HTTP
- initialDelaySeconds: 10
- periodSeconds: 10
- successThreshold: 1
- timeoutSeconds: 1
- ports:
- - containerPort: 10027
- hostPort: 10027
- name: http
- protocol: TCP
- volumeMounts:
- - name: cgroup
- mountPath: /sys/fs/cgroup
- - name: lxcfs
- mountPath: /var/lib/lxc
- mountPropagation: Bidirectional
- - name: docker
- mountPath: "/var/run/docker.sock"
- - name: runcontainerd
- mountPath: "/run/containerd"
- - name: runrunc
- mountPath: "/run/runc"
- - name: vardata
- mountPath: "/var/data"
- # hostNetwork: true
- volumes:
- - name: cgroup
- hostPath:
- path: /sys/fs/cgroup
- - name: lxcfs
- hostPath:
- path: /var/lib/lxc
- type: DirectoryOrCreate
- - name: docker
- hostPath:
- path: /var/run/docker.sock
- # containerd client will need to access /var/data, /run/containerd and /run/runc
- - name: vardata
- hostPath:
- path: /var/data
- - name: runcontainerd
- hostPath:
- path: /run/containerd
- - name: runrunc
- hostPath:
- path: /run/runc
- updateStrategy:
- rollingUpdate:
- maxUnavailable: 5
- type: RollingUpdate
-
- # 3、agentless模式,没有安装debug-agent(daemonset)
- [root@master1 src]# kubectl debug --image=reg.mt.com:5000/debug-agent:latest nginx-74895b888f-rj6qb --agentless=true /bin/sh
-
- # 4、agent模式
- 使用步骤2的daemonset安装,kubectl debug $pod 即可。在 ~/.kube/debug-config 可以配置一些默认的参数。官方示例如下:
- # debug agent listening port(outside container)
- # default to 10027
- agentPort: 10027
-
- # whether using agentless mode
- # default to true
- agentless: true
- # namespace of debug-agent pod, used in agentless mode
- # default to 'default'
- agentPodNamespace: default
- # prefix of debug-agent pod, used in agentless mode
- # default to 'debug-agent-pod'
- agentPodNamePrefix: debug-agent-pod
- # image of debug-agent pod, used in agentless mode
- # default to 'aylei/debug-agent:latest'
- agentImage: aylei/debug-agent:latest
-
- # daemonset name of the debug-agent, used in port-forward
- # default to 'debug-agent'
- debugAgentDaemonset: debug-agent
- # daemonset namespace of the debug-agent, used in port-forwad
- # default to 'default'
- debugAgentNamespace: kube-system
- # whether using port-forward when connecting debug-agent
- # default true
- portForward: true
- # image of the debug container
- # default as showed
- image: nicolaka/netshoot:latest
- # start command of the debug container
- # default ['bash']
- command:
- - '/bin/bash'
- - '-l'
- # private docker registry auth kuberntes secret
- # default registrySecretName is kubectl-debug-registry-secret
- # default registrySecretNamespace is default
- registrySecretName: my-debug-secret
- registrySecretNamespace: debug
- # in agentless mode, you can set the agent pod's resource limits/requests:
- # default is not set
- agentCpuRequests: ""
- agentCpuLimits: ""
- agentMemoryRequests: ""
- agentMemoryLimits: ""
- # in fork mode, if you want the copied pod retains the labels of the original pod, you can change this params
- # format is []string
- # If not set, this parameter is empty by default (Means that any labels of the original pod are not retained, and the labels of the copied pods are empty.)
- forkPodRetainLabels: []
- # You can disable SSL certificate check when communicating with image registry by
- # setting registrySkipTLSVerify to true.
- registrySkipTLSVerify: false
- # You can set the log level with the verbosity setting
- verbosity : 0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。