侧边栏壁纸
博主头像
问道

问道的小花园,总能给你带来惊喜

  • 累计撰写 68 篇文章
  • 累计创建 35 个标签
  • 累计收到 6 条评论

kubernetes资源对象:以练促学(一)

问道
2022-07-27 / 0 评论 / 1 点赞 / 482 阅读 / 13,788 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-07-27,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

引子

kubernetes的资源对象是kubernetes体系中的重要组成部分,简单理解就是生成的kubernetes的系统应用,用来调度、编排我们的业务应用。是我们的业务应用与kubernetes的kube-controller组件,如:apiserver、kube-controller、kube-scheduler等之间的中间层,起到承上启下的作用。

将kubernetes的资源对象简单的分类为以下几种资源对象:

类别名称
资源对象Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Ingress、Label、CustomResourceDefinition
存储对象Volume、PersistentVolume、Secret、ConfigMap
策略对象SecurityContext、ResourceQuota、LimitRange
身份对象ServiceAccount、Role、ClusterRole

学习kubernetes的资源对象对入门kubernetes是十分重要的,但kubernetes的资源对象比较多,概念繁杂,容易让人困惑。

单单从理论出发,也容易让人无法留下较深的印象,故本系列直接从各种小练习出发,以练促学,在实践中加深对kubernetes资源对象的理解。同时也在实践找那个插入响应的理论讲解,理论与实践相辅相成,相符促进。

关于kubernetes的简单入门,以及搭建一个简单的kubernetes集群,百度或者其他资讯平台都有很好的教程。关注作者,私信留言(kubernetes)直接赠送。

存储

存储
1. 创建含有初始化容器的pod,满足如下要求。
1)  pod名为pod1,镜像为nginx。
2)  创建一个名字为v1的卷,这个卷的数据不能永久存储数据。
3)  初始化容器名字为initc1,镜像使用busybox,挂载此卷v1到目录/data。
4)  在初始化容器里,创建文件/data/aa.txt。
5)  普通容器名字为c1,镜像为nginx。
6)  把卷v1挂载到/data里。
7)  当次pod运行起来之后,在pod1的c1容器里,查看是不是存在/data/aa.txt。

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0 #terminationGracePeriodSeconds 可以定义优雅关闭的宽限期,即在收到停止请求后,有多少时间来进行资源释放或者做其它操作,如果到了最大时间还没有停止,会被强制结束。默认值:30。
  volumes:
  - name: v1
    emptyDir: {}#只写一个位置对应的容器的位置,物理机上随便找一个位置,删除后物理机上的数据也会消失
  containers:
  - name: initc1
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","touch /data/aa.txt && sleep 1000"]
    volumeMounts:
    - name: v1
      mountPath: /data
  - name: c1
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: v1
      mountPath: /data
      #readOnly: false
    resources: {}#resources可以用于限制容器对资源的使用,具体设置如下
  dnsPolicy: ClusterFirst#dns策略,ClusterFirst 表示集群 DNS 优先
  restartPolicy: Always
status: {}

###############################################################
测试在pod1的c1容器里,查看是不是存在/data/aa.txt
[root@vms31 10-test]# kubectl exec -it pod1 -c c1 -- ls /data
aa.txt 

requests未设置时,默认与limits相同。
limits未设置时,默认值与集群配置相关。
可以使用requests来设置各容器需要的最小资源
limits用于限制运行时容器占用的资源,用来限制容器的最大CPU、内存的使用率。
当容器申请内存超过limits时会被终止,并根据重启策略进行重启。.
    resources:
      limits:
        cpu: "1"
        memory: 2048Mi
      requests:
        cpu: "0.6"
        memory: 1024Mi
 

2. 创建一个持久性存储,满足如下要求。
1)  持久性存储的名字为pv10。
2)  容量大小设置为2G。
3)  访问模式为ReadWriteOnce。
4)  存储类型为hostPath,对应目录/pv10。
5)  storageClassName设置为cka。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv10
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain #持久卷回收策略,Retain就是保留,还有”Recycle” 和 “Delete”
  storageClassName: cka #
  hostPath: #hostPath存储删除容器,物理机上的文件还会保存,但不会同步到重建的pod上
    path: /data 
    
###############################################################################
PersistentVolumes 可以有多种回收策略,包括 “Retain”、”Recycle” 和 “Delete”。
对于动态配置的 PersistentVolumes 来说,默认回收策略为 “Delete”。这表示当用户删除对应的 
PersistentVolumeClaim 时,动态配置的 volume 将被自动删除。如果 volume 包含重要数据时,
这种自动行为可能是不合适的。那种情况下,更适合使用 “Retain” 策略。使用 “Retain” 时,
如果用户删除 PersistentVolumeClaim,对应的 PersistentVolume 不会被删除。
相反,它将变为 Released 状态,表示所有的数据可以被手动恢复。
###############################################################################
PV是对底层网络共享存储的抽象,将共享存储定义为一种“资源”,比如Node也是容器应用可以消费的资源。
PV由管理员创建和配置,与共享存储的具体实现直接相关。

PVC则是用户对存储资源的一个“申请”,就像Pod消费Node资源一样,PVC能够消费PV资源。
PVC可以申请特定的存储空间和访问模式。

StorageClass,用于标记存储资源的特性和性能,管理员可以将存储资源定义为某种类别,
正如存储设备对于自身的配置描述(Profile)。根据StorageClass的描述可以直观的
得知各种存储资源的特性,就可以根据应用对存储资源的需求去申请存储资源了。存储卷可以按需创建。 

3. 创建pvc,满足如下要求。
1)  名字为pvc10。
2)  让此pvc和pv10进行关联。
3)  所在命名空间为default。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc10
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi #pvc的容量和pv的大小是否要求一致,我觉得是不需要的
  storageClassName: cka
 

4. 创建pod,满足如下要求。
1)  名字为pod-pvc。
2)  创建名字为v1的卷,让其使用pvc10作为后端存储。
3)  容器所使用的镜像为nginx。
4)  把卷v1挂载到/data目录。

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod-pvc
  name: pod-pvc
spec:
  nodeName: vm3
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    persistentVolumeClaim:  
      claimName: pvc10      
  containers:
  - image: nginx
    name: pod-pvc
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: v1
      mountPath: /data  
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Secret

创建含有初始化容器的pod,满足如下要求:

1.创建secret,名字为s1,键值对为name1/tom1
1)创建一个名字为nginx的pod,镜像为nginx。
2.)此pod里定义一个名字为MYENV的变量,此变量的值为s1里name1对应的值。
3)当pod运行起来之后,进入pod里查看变量MYENV的值。

[root@vms31 10-test]# kubectl create secret --help
Create a secret using specified subcommand.

Available Commands:
  docker-registry 创建一个给 Docker registry 使用的 secret
  generic         从本地 file, directory 或者 literal value 创建一个 secret
  tls             创建一个 TLS secret

Usage:
  kubectl create secret [flags] [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

[root@vms31 10-test]# kubectl create secret generic s1 --from-literal=name1=tom1 
#generic子命令可以通过本地文件、目录或者literal(键值对) 

[root@vms31 10-test]# kubectl nginx --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > test.yaml

修改生成的yaml文件

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - env:
    - name: MYENV
      valueFrom:
        secretKeyRef:
          name: s1
          key: name1
    image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

验证容器内的变量值

[root@vms31 10-test]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          2m49s
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl exec -it nginx -- bash
root@nginx:/# echo $MYENV
tom1

2.创建configmap,名字cm1,键值对为name2/tom2

1)创建一个名字为nginx2的pod,镜像为nginx。

2)此pod里把cm1挂载到/also/data目录里。

创建configmap并生成yaml文件

[root@vms31 10-test]# kubectl create cm cm1 --from-literal=name2=tom2
configmap/cm1 created
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl run nginx2 --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > test2.yaml

配置的yaml文件

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx2
  name: nginx2
spec:
  volumes:
  - name: v1
    configMap:
      name: cm1
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx2
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /also/data
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

验证pod的configmap

[root@vms31 10-test]# kubectl exec -it nginx2 -- cat /also/data/name2
tom2[root@vms31 10-test]#

deploy

1.创建一个deployment,满足如下要求:

1)名字为web1,镜像为nginx:1.9。

2)此web1要有2个副本。

3)pod的标签为app-name=web1。

deploy的yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web1
  name: web1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web1
    spec:
      containers:
      - image: nginx:1.9
        name: nginx
        resources: {}
status: {}

可以看到通过deploy创建的pod是在deploy和pod上都能查找到的,但删除的时候是要删除deploy,删除pod会再次自动创建的

设置的标签可以看到deploy上有。pod上是没有的

2.更新此deployment,把maxSurge和maxUnavailable的值都设置为1。

服务在滚动更新时,deployment控制器的目的是:给旧版本(old_rs)副本数减少至0、给新版本(new_rs)副本数量增至期望值(replicas)。大家在使用时,通常容易忽视控制速率的特性,以下是kubernetes提供的两个参数:

  • maxUnavailable:和期望ready的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;
  • maxSurge:和期望ready的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。

通过kubectl edit deployments.apps web1来修改不太靠谱,修改原来的yaml文件再次生成,如果成功显示是deployment.apps/web1 configured,标明是修改生成的

[root@vms31 10-test]# kubectl apply -f deploy.yaml 
deployment.apps/web1 configured
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get deployments.apps 
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   2/2     2            2           18h
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web1-6f8f6976b5-t4j7l   1/1     Running   1          18h
web1-6f8f6976b5-vc8pl   1/1     Running   1          17h
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web1
  name: web1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web1
  strategy: #修改的是标红
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web1
    spec:
      containers:
      - image: nginx:1.9
        name: nginx
        resources: {}
status: {}

修改之后edit deploy发现更新策略写在下图位置

3.修改此deployment的副本数为6。

[root@vms31 10-test]# kubectl scale deployment web1 --replicas=6
deployment.apps/web1 scaled
[root@vms31 10-test]# kubectl get deployments.apps 
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   5/6     6            5           18h
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get pods
NAME                    READY   STATUS              RESTARTS   AGE
web1-6f8f6976b5-2d8r4   0/1     ContainerCreating   0          29s
web1-6f8f6976b5-bxbkj   1/1     Running             0          29s
web1-6f8f6976b5-jprw9   1/1     Running             0          29s
web1-6f8f6976b5-t4j7l   1/1     Running             1          18h
web1-6f8f6976b5-t9drk   1/1     Running             0          29s
web1-6f8f6976b5-vc8pl   1/1     Running             1          17h
 

4.更新此deployment,让其使用镜像nginx,并记录此次更新。

[root@vms31 10-test]# kubectl get deployments.apps -o wide#可以看到此时nginx版本为1.9
NAME   READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES      SELECTOR
web1   6/6     6            6           18h   nginx        nginx:1.9   app=web1
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl set image deploy web1 nginx=nginx --record#更新操作命令
deployment.apps/web1 image updated
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get deployments.apps -o wide#此时nginx版本发生了变化
NAME   READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES   SELECTOR
web1   6/6     6            6           18h   nginx        nginx    app=web1
[root@vms31 10-test]# kubectl rollout history deployment web1#可以查询到更新的版本
deployment.apps/web1 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deploy web1 nginx=nginx --record=true

kubectl rollout
对资源进行管理

可用资源包括:

deployments
daemonsets
子命令
history(查看历史版本)
pause(暂停资源)
resume(恢复暂停资源)
status(查看资源状态)
undo(回滚版本)

5.回滚此次更新 至升级之前的镜像版本nginx:1.9

[root@vms31 10-test]# kubectl get deployments.apps -o wide
NAME   READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES   SELECTOR
web1   6/6     6            6           18h   nginx        nginx    app=web1
[root@vms31 10-test]# kubectl rollout history deployment web1
deployment.apps/web1 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deploy web1 nginx=nginx --record=true

[root@vms31 10-test]# kubectl rollout undo deployment web1 --to-revision=1#把deploy回滚的命令,版本根据前面查到的
deployment.apps/web1 rolled back
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# #kubectl rollout undo deployment web1#这个命令是回滚到上一个版本 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get deployments.apps 
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   6/6     6            6           18h
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get deployments.apps -o wide#nginx版本又回到了1.9
NAME   READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES      SELECTOR
web1   6/6     6            6           18h   nginx        nginx:1.9   app=web1
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl rollout history deployment web1 
deployment.apps/web1 
REVISION  CHANGE-CAUSE
2         kubectl set image deploy web1 nginx=nginx --record=true
3         <none>

6.删除此deployment

kubectl delete deployments.apps web1 --force

Daemon Set

1.创建一个daemonset,满足如下要求:

1)名字为ds-test1。
2)使用的镜像为nginx。

daemon set的yaml文件

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: ds-test1
  name: ds-test1
spec:
  selector:
    matchLabels:
      app: ds-test1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: ds-test1
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}

daemonset创建成功后查询daemonset

[root@vms31 10-test]# kubectl get daemonsets.apps -o wide
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE     CONTAINERS   IMAGES   SELECTOR
ds-test1   2         2         2       2            2           <none>          2m45s   nginx        nginx    app=ds-test1
[root@vms31 10-test]# kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
ds-test1-bzhct   1/1     Running   0          2m46s   10.244.252.17   vms33   <none>           <none>
ds-test1-zb9c8   1/1     Running   0          2m46s   10.244.29.99    vms32   <none>           <none>

2.解释,此daemonset为什么没有在master创建pod

因为master节点设置了误点(Taints)

查看所有节点是否设置了污点

kubectl describenodes |grep -E "Taints|Name"

[root@vms31 10-test]# kubectl describe nodes | grep -E "Taints|Name"#-E表示可以使用正则表达式,该表达式表示Taints或Name
Name:               vms31
Taints:             node-role.kubernetes.io/master:NoSchedule
  Namespace                   Name                             CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms32
Taints:             <none>
  Namespace                   Name                                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms33
Taints:             <none>
  Namespace                   Name                              CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE

设置和取消污点

kubectl taint node [node] key=value[effect]

其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]

NoSchedule: 一定不能被调度

PreferNoSchedule: 尽量不要调度

NoExecute: 不仅不会调度, 还会驱逐Node上已有的Pod
[root@vms31 10-test]# kubectl get nodes
NAME    STATUS   ROLES                  AGE   VERSION
vms31   Ready    control-plane,master   97d   v1.20.1
vms32   Ready    node1                  97d   v1.20.1
vms33   Ready    node2                  97d   v1.20.1
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl taint node vms32 node-role.kubernetes.io/worker1=:NoSchedule
node/vms32 tainted
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl describe nodes | grep -E "Taints|Name"
Name:               vms31
Taints:             node-role.kubernetes.io/master:NoSchedule
  Namespace                   Name                             CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms32
Taints:             node-role.kubernetes.io/worker1:NoSchedule
  Namespace                   Name                                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms33
Taints:             <none>
  Namespace                   Name                              CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  
  
删除污点
[root@vms31 10-test]# kubectl taint node vms32 node-role.kubernetes.io/worker1-
node/vms32 untainted
[root@vms31 10-test]# kubectl describe nodes | grep -E "Taints|Name"
Name:               vms31
Taints:             node-role.kubernetes.io/master:NoSchedule
  Namespace                   Name                             CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms32
Taints:             <none>
  Namespace                   Name                                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
Name:               vms33
Taints:             <none>
  Namespace                   Name                              CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
 

3.创建一个daemonset

满足如下要求:

1)名字为ds-test2。
2)使用的镜像为nginx。
3)此daemonset所创建的pod只在含有标签为disktype=ssd的worker上运行。
4.)删除这两个daemonset。

先给一个节点设置对应标签

[root@vms31 10-test]# kubectl get nodes --show-labels | grep vm32
[root@vms31 10-test]# kubectl get nodes --show-labels | grep vms32
vms32   Ready    node1                  97d   v1.20.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=vms32,kubernetes.io/os=linux,node-role.kubernetes.io/node1=

daemonset的yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: ds-test2
  name: ds-test2
spec:
  selector:
    matchLabels:
      app: ds-test2
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: ds-test2
    spec:
      nodeSelector:
        disktype: ssd
      containers:
      - image: nginx
        name: nginx
        resources: {}

运行后可以查到只在对应标签的node上运行

[root@vms31 10-test]# kubectl get daemonsets.apps 
NAME       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ds-test2   1         1         0       1            0           disktype=ssd    7s
[root@vms31 10-test]# 
[root@vms31 10-test]# 
[root@vms31 10-test]# kubectl get pods -o wide
NAME             READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
ds-test2-4zjfc   0/1     ContainerCreating   0          23s   <none>   vms32   <none>           <none>

后续继续更新有关云原生及kubernetes的干货文章,欢迎点赞关注,多多分享。

1

评论区