CKA-Kubernets(K8s) (二)

# 环境简易拓扑示意图

存储管理

创建卷

 # 用命令生产一个pod1的yaml文件

kubectl run pod1 --image=buxybox --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pod1.yaml

kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    emptyDir: {} # Not sure Physical directory
  containers:
  - image: busybox
    name: pod1
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3000"]
    volumeMounts:
    - name: v1
      mountPath: /xx  # in Docker Path /xx
      # readOnly: false    # default paramater
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

相关挂载参数介绍:

emptyDir(用于临时存储,删除pod,随即消失)     相当于 -v /xx   # 只写一个路径默认是容器里的目录,物理机随机生成

如何查看随机生产的物理路径在什么位置?

首先,在Master节点查看你pod是在哪个节点

kubectl get pods -o wide

然后,去相应的节点服务器上根据pod名字找出相应的容器名

sudo docker ps |grep "pod1"

最后,根据自己设定的挂载容器目录名找到物理路径

  sudo docker inspect c9163e85ac41 |grep "/xx"

  并且看到我们在容器里面创建的测试文件loki.txt 存在这个目录下面

Tips:但是,这样的emptyDir挂载方式,我的数据会随着pod的删除而丢失。

  

hostPath(永久性存储,使用的是本地存储,没法实现数据的同步)        相当于-v /xx:/yy   # 左边是物理机目录,右边是容器目录

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod2
  name: pod2
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    hostPath: 
      path: /home/loki/4-volume  # Physical directory
  containers:
  - image: busybox
    name: pod2
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3000"]
    volumeMounts:
    - name: v1
      mountPath: /xx  # in Docker Path /xx
      # readOnly: false    # default paramater
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 在相应节点服务器上创建了一个物理目录/home/loki/4-volume/yy并且映射到容器的/xx里面

这样就算,删掉了容器,这个目录里面的数据也是永久存储。

 

 Tips:但是,又出现一个新的问题。不同的worker节点这个目录的数据也是不一致的?

# 下面的实验环境需要一台NFS - Server 我们这里用VM4来模拟

nfs(ceph,iscsi... 共享存储)

在vm4,上面进行vm4安装NFS-Server(下面配置仅用于实验,生产环境请勿模仿!!!

 sudo yum install -y nfs-utils

sudo systemctl start nfs-server; sudo systemctl enable nfs-server

 # 创建一个共享目录  mkdir /home/loki/ShareDir

# 编辑nfs共享存储目录  vim /etc/exports ,下入下面信息

/home/loki/ShareDir *(rw,async,no_root_squash)

 Tips:参数介绍 no_root_squash  # root 的权限不做任何的改变

# 让配置的生效 sudo exportfs -avr

Tips:参数介绍 exportfs 命令常用选项如下:

● -a 全部挂载或者全部卸载

● -r  重新挂载

● -u 卸载某一个目录

● -v 显示共享目录

  注意打开防火墙(下面的命令仅是为了实验方便,生产环境不要模仿!!!

 sudo firewall-cmd --set-default-zone=trusted

# 再worker上安装客户端

sudo yum install nfs-utils -y

# 测试一下是否能正常链接NFS  showmount -e 192.168.27.219

 # 测试挂载   

sudo mount 192.168.27.219:/home/loki/ShareDir /mnt

sudo umoun /mnt

 # yaml文件修改

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod3
  name: pod3
spec:
  nodeName: vm3
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    nfs:
      server: 192.168.27.219     # NFS Sever IP
      path: /home/loki/ShareDir  # NFS Share directory
  containers:
  - image: busybox
    name: pod3
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3000"]
    volumeMounts:
    - name: v1
      mountPath: /xx  # in Docker Path /xx
      # readOnly: false    # default paramater
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Tips: NFS,解决不同节点数据同步,但是多个项目数据安全不能保证。大家都可以往目录里面进行读写操作

持久性存储 pv

Tips: 小技巧,通过kubectl api-resource 可以查看对应名利的“缩写”形式

  # 查询此名称空间是否有pv和pvc     

  

# 需要到官方网站上download模板 

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes

 # 创建PV 的yaml文件

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  # storageClassName: slow
  nfs:
    path: /home/loki/ShareDir  # Yours NFS PATH 
    server: 192.168.27.219     # Yours NFS IP

 # 查看PV 状态  kubectl get pv

   

# 创建PVC  依然去官方网站上拿模板进行修改

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  # storageClassName: slow

 # 获取pvc信息    kubectl get pvc

 

  # 查看pvc当前状态  kubectl get pv -n defalut  看到STATUS 已经是Bound

  

 # 不能再次关联  新建另外一个PVC02的时候发现,状态已经是Pending

  

# 默认情况下 PVC和PV进行关联,主要看2个值

1. 容量大小

   pvc的大小 <= pv 的大小

注:PV的容量值如果大于PVC的话,是可以进行关联。但是PVC的值大于PV的话,则不能进行关联,出现Pending

2. accessmode相同

ReadWriteOnce   允许一次一个写

ReadOnlyMany  只允许多个写

ReadWriteMany  允许同时多个写

  

3. 让特定的PV和PVC进行关联,需要设置storageClassName (pvc 和 pv的这个值)相同的情况下会进行关联

# PV上面的设置storageClassName

  

# PVC上面的设置storageClassName

# 这次再来看结果pvc01就已经是Pending了,因为pvc02指定了storageClassName  -- loki

   

# PV和PVC创建好以后,开始进行YAML 文件设定

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod4
  name: pod4
spec:
  nodeName: vm3
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    persistentVolumeClaim:   # Options PVC
      claimName: pvc02       # pvc name
  containers:
  - image: busybox
    name: pod4
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 3000"]
    volumeMounts:
    - name: v1
      mountPath: /xx  # in Docker Path /xx
      # readOnly: false    # default paramater
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# RECLAIM POLICY 回收策略    删除pvc后

注:删除pvc之前需要先删掉对应的pod

Recycle 意思就是,当PVC被删除之后,pv会把自己存储里的数据情空,然后变成可用的

  

# 回收策略修改,PV默认有2种回收策略

Recycle --会删除数据

• 会生成一个pod回收数据
• 删除pvc之后,pv可复用
• pv状态由Released变为Available


Retain--不回收数据
• 但是删除pvc之后,pv依然不可用
• pv状态长期保持为 Released

# 修改pv的YAML文件策略修改为 Retain测试

 # 查看修改了Retain的pv,创建结果

  

# 再次删除pvc,此时数据依然保留,pv依然显示被Released(关联)状态

 # 需要重新删除pv(关联的NFS数据依然保留),让状态变成Available,再次创建pv后即可再次进行关联

注:一般pv关联的NFS不要使用相同目录,尤其注意父目录和子目录,变其中有设置为Recycle,导致的连带删除。

Tips: 此时解决了数据安全隔离的问题,但是又有一个新问题诞生,就是每次这个PV都需要管理员手动创建。如果管理员不再或者无人值守,能自动扩充吗?

动态卷供应   storageClass 简称 SC

  

#kubernetes 默认有一些自带的分配器,包括不仅限于:

kubernetes.io/aws-ebs
kubernetes.io/gce-pd
kubernetes.io/glusterfs
kubernetes.io/cinder
kubernetes.io/vsphere-volume
kubernetes.io/rbd
kubernetes.io/quobyte
kubernetes.io/azure-disk
kubernetes.io/azure-file
kubernetes.io/portworx-volume
kubernetes.io/scaleio
kubernetes.io/storageos
kubernetes.io/no-provisioner

在动态创建 pv 的时候,根据使用不同的后端存储,应该选择一个合适的分配器

# 没有的需要手动创建--分配器

利用NFS 创建动态卷供应

准备工作

1. K8s 1.20 需要手动修改一个参数

sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml

  

解决报错:  unexpected error getting claim reference: selfLink was empty, can't make reference

  1. 会导致pvc启动变成Pending

  2. 会导致external-storage里面的deployment.yaml 启动出现上面报错

 

# k8s 1.20版本需要在master上,修改一个参数

 

Cause: 参考Github 

In v1.16, we will deprecate the SelfLink field in both ObjectMeta and ListMeta objects by: documenting in field definition that it is deprecated and is going to be removed adding a release-note about field deprecation We will also introduce a feature gate to allow disabling setting SelfLink fields and opaque the logic setting it behind this feature gate.

In v1.20 (12 months and 4 release from v1.16) we will switch off the feature gate which will automatically disable setting SelfLinks. However it will still be possible to revert the behavior by changing value of a feature gate.

译文:在1.20版本中(从1.16版本到12个月的4个版本),我们将关闭会自动禁用设置SelfLinks的功能。然而,仍然有可能通过改变参数的值来恢复这种行为。

In v1.21, we will get rid of the whole code propagating those fields and fields themselves. In the meantime, we will go over places referencing that field (see below) and get rid of those too.

 修改完毕后重启kubelet,   systemctl restart kubelet

2. 创建好可以访问的NFS目录,这里就沿用上面的vm4的 NFS: /home/loki/ShareDir

3. 下载相关插件来创建nfs外部分配器

 下载所需的包

https://github.com/kubernetes-retired/external-storage.git 

 # 读安装说明README.md

/home/loki/4-volume/external-storage-master/nfs-client/README.md

$ NS=$(kubectl config get-contexts|grep -e "^*" |awk '{print $5}')
$ NAMESPACE=${NS:-default}
$ sed -i'' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/rbac.yaml ./deploy/deployment.yaml
$ kubectl create -f deploy/rbac.yaml

  

 # 执行用自己的当前的名称空间替换rbac.yamldeployment.yaml文件,然后创建rbac.yaml 

 

部署NFS分配器

vim ./deploy/deployment.yaml  修改如下内容  

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: 4-volume
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 192.168.27.219
            - name: NFS_PATH
              value: /home/loki/ShareDir
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.27.219
            path: /home/loki/ShareDir

1. 当前你自己的名称空间,如果自己分不清楚的可以用以下命令查:

kubectl config get-contexts|grep -e "^*" |awk '{print $5}'

2. 所需镜像自己提前先download下来,所有节点 pull下来我这里是用阿里镜像加速pull的

quay.io/external_storage/nfs-client-provisioner:latest

3. env里,PROVISIONER_NAME用于指定分配器的名字,这里是fuseim.pri/ifs,

NFS_SERVER和NFS_PATH分别指定这个分配器所使用的存储信息

4. 在volume里的server和path指定共享服务器和目录

# 修改配置文件后,执行命令     kubectl apply -f deployment.yaml

  

# 查看是否创建pod   kubectl get pods

   

# 在部署这个的时候俞到2个报错(遇到这2个报错是因为我下载错了版本,用了v5.5.0

报错1:     

 解决办法:修改文件    Cause: 在新版本中 Deployment 已经弃用 extensions/v1beta1 

kind: Deployment
apiVersion: extensions/v1beta1
metadata:

改为:

kind: Deployment
apiVersion: apps/v1
metadata:

报错2:

  解决办法:修改文件   Cause: 也是版本问题

spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
改为:(增加了3行内容)

spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:

  

部署storageClass

创建了nfs分配器以后.西面将开始创建一个使用这个分配器的storageClass

vim /home/loki/4-volume/external-storage-5.5.0/nfs-client/deploy/class.yaml

这里provisioner的值是fuseim.pri/ifs(默认值)是由deployment.yaml 文件里指定的分配器名字.

这个文件作用是:创建一个名字为managed-nfs-storage的storageClass.使用名字为fuseim.pri/ifs的分配器

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

开始执行   kubectl apply -f class.yaml  ,执行后查看结果 kubectl get sc

   

# 开始创建pvc文件,复制模板 cp external-storage-5.5.0/nfs-client/deploy/test-claim.yaml .

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc04
  annotations:
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

还可以写成:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc03
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi
  storageClassName: managed-nfs-storage

# 测试查看pvc状态,是否创建pvc的同时产生了pv

密码管理

在一些pod里面,是需要填写必要的用户名和密码的

# 创建一个新的名称空间  5-secpass   NS

# secret   两种方式键值对和文件    kubectl get secret 

  建议以命令行的方式来创建

# secret  第一种    kubectl create secret generic mysec1 --from-literal=name=loki --from-literal=age=16

 # 查看创建的情况   Opaque(英文意思:不透明的)

 

# 用yaml的方式查看结果

  

# 用Json方式查看

 # 通过jsonpath查看指定参数的值

  

# 查看设定的键值对,用jsonpath的方式(默认base64编码)

  

# 直接查看base64加密后的真实值

 

  

# secret  第二种 文件加密

  

   

如何使用secret

1. 卷的方式挂载secret,用于传递文件到容器

  

 # sercert 文件传递 创建到/xx 以文件的形式(如果有多个值,想要用其中一个文件)

   

#  应用场景1:  用于传递配置文件,替代模板镜像的配置文件内容

  

 

  

 

   

#  应用场景2(推荐):以变量的方式,用于保存密码

# 这样就不用把明文密码写在yaml文件,而是直接用sercert引入进来

 configmap (一般传递文件用configmap)

 

  # cm 简写= configmap    

 

  

# 创建configmap kv键值对  kubectl create cm <CM_NAME>  --from-literal=<Key>=<Value> ...

  

 # 创建configmap  文件  kubectl create cm <CM_NAME> --from-file=<FILE_PATH> ...

 # 查看设置的cm (明显发现保存的内容是明文) kubectl get <CM_NAME>  kubectl describe cm <CM_NAME>

  

# 应用场景1(推荐)通过cm把配置文件传入进去,并替换镜像默认模板配置文件  

  

 注: 当创建一个pod的时候,都检查没有问题,就是创建不成功,检查secret或者cm是否存在

# 创建过程也会卡在ContainerCreating

 # 查看kubectl  get  ev 里面明显的提示 not  found

  

 # 应用场景2: 传入变量值

  

kubectl  edit 

# 可以通过命令修改cm 配置文件    kubectl edit cm <CM_NAME> -n <NAMESPACE>

# secret 也可以类似修改方法

   

 #场景应用: 修改kube-proxy    模式iptable  ipvs,修改后删掉之前创建的pod

  

deployment   控制器

# pod只要挂掉了,就不会再次启动

# pod 不具备再生性,不健壮的

所以,需要使用控制器来管理pod

了解deployment的作用(相当于是一个机器人)

  

创建deployment

 # 推荐使用yaml的文件方式来创建deploy, 从1.18开始命令方式写的选项少于yaml文件

kubectl create deployment <DEPLOY_NAME> --image=<IMAGE_NAME> --dry-run=client -o yaml > <导出的文件>

 deploy 文件区域介绍

  #deployment 盯着pod是通过标签(matchLabels)

 # 2个标签要匹配 

deployment  

# 通过控制器模板(deployment)创建

 # deploy 基本信息查看   kubectl get deploy     kubectl get deploy -o wide

课看到默认分配了一个标签app=web1

 

  

# 修改 副本数

命令行方式

scale(伸缩)  瞬间增加副本到5个

修改方式1/3:   kubectl scale deploy <DEPLOY_NAME> --replicas=<Numbers>

EDIT方式 

# 修改方式2/3: 还可以通过edit的方式修改副本数    kubectl edit deploy  <DEPLOY_NAME>

 

YAML方式

 # 修改方式3/3: 直接修改yaml文件的方式修改副本数,修改后要生效需要重新执行 apply -f <DEPLOY_YAML>

# 水平自动伸缩    HPA

  

纵向扩展:只能增加cpu,内存,硬件相关

横向扩展:比较灵活可弹性增删节点

# 配置HPA之前准备

mtric server           # 确保安装

kubectl top nodes  # 验证

# 创建hpa

 

  不存在优先级的问题

# 查看hpa情况    kubectl get hpa

   

 # 解决当前cpu使用量为unknown(需要设置pod资源限制)

1.可以在线修改,用  kubectl edit deploy <DEPLOY_NAME>   PS:前提是你已经设置了资源限制

 

 2.修改yaml文件

   

# 创建HPA,CPU限制

 如果是设置相同的deployment就需要删除后重新输入   kubectl autoscale deployment <DEPLOY_NAME> --min=1 --max=5 --cpu-percent=60

 

# 设置了resources: 字段以后这里就不再显示unknown了

 

  

 实验阶段

 # master 上  启用svc(负债均衡器,后面会讲,这里为了实验借用一下)

# 创建一个名为svc1 的负载均衡器,对应到控制器web1 的80端口,并且外部端口随机分配

kubectl expose --namesvc1 deploy web1 --port=80 --type=NodePort

# 分配了一个集群IP(仅集群内部可以访问和绑定了一个随机外部端口32111

 

 然后分别开启hpa和pods的情况监控,watch kubectl get hpa  和 watch kubectl get pods

 

# 因为hpa发现了cpu负载变高,开始大量增加pods数量 ,按照我们刚刚设置的最多可以开5

  

 #  在vm4 使用ab工具 模拟产生请求数

首先,安装工具   yum install httpd-tools -y

 ab -t 600 -n 1000000 -c 1000 http://192.168.27.216:32111/index.html

ab命令常用参数介绍:

-t 时间

-n requests,总共发送多少个请求

-c concurrency, 并发

  

# 如果测试终止,会等待五分钟会把pods 缩小到最小值---间隔5分钟原因是防止“抖动”

 

  

deployment 健壮性测试

# 首先,查看当前pod在vm2的节点上运行

# 然后,我们去vm2服务器上进行重启 init 0,下线差不多5分钟左右会发现再vm3上面重新创建了一个pod,这个时候我们在开机vm2节点,在vm3上面的pod不会返回到vm2上面。

# kubernetes-升级镜像

 更新容器镜像版本,首先查看当前镜像版本  nginx:latest  (默认不跟版本就是latest)

更新镜像版本     kubectl set image deploy <DEPLOY_NAME> <CONTAINERS>=<IMAGES> [--record]

  

 # 更新完毕后再次查看,发现版本已经是我们设定的版本

注:如果设置了--record,就可以使用查看历史记录命令你查看操作记录

回滚操作:  kubectl rollout undo deployment <DEPLOY_NAME>

查看历史记录:  kubectl rollout history deployment <DEPLOY_NAME>

  

 # 在线修改滚动更新策略   kubectl edit deploy <DEPLOY_NAME>

 找到下面内容位置: 

 参数介绍:

 # 可以使用百分比,也可以是具体个数

maxSurge:  在升级过程中一次升级几个 

maxUnavailable:  在升级过程中,只能有1个不可用一次性删除多少个pod

实验: 比如我们修改为一次升级3个,一次性删除1个。然后多开放几个副本进行测试

 

可以通过  kubectl get rs 命令来查看副本转移过程

   

# 如果想回退到某个指定阶段的版本   kubectl rollout undo deployment <DEPLOY_NAME> --to-revision=<numbers>

其他一些控制器

# 新建一个名称空间开始这个阶段

daemonset    例如: calico和kube-proxy每个节点都有一个ds

  

创建ds

# 通过deploy的yaml文件进行修改,因为daemonset本身不存在模板

  

默认没有模板yaml,需要通过deployment模板修改4处后如下:

# 最后DS模板如下

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

 # 针对在有ssd标签上运行

# 查看创建的ds  kubectl get ds 

 # 查看创建的ds 更详细信息   kubectl describe ds

  

通过标签(label)控制pod所在的节点位置(默认,带有污点(Taints)的nodes是不会创建pod) 

 # 创建一个节点的标签     kubectl label node <NODE> <LABEL_Key=LABEL_Value>

# 查看标签命令  kubectl get  node --show-labels

   # 根据上面设置的label设定YAML文件,然后apply -f 文件,启动后会发现,打有loki标签的节点上启动了pod(此node一定不能为有Taints,不然依然不能在这个节点上启动)

 

ReplicationController(RC)

apiVersion: v1
kind: ReplicationController
metadata:
  name: web1
spec:
  replicas: 3
  selector:
    app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80

# 查看rc 情况  kubectl get rc

# 查看rc 详细情况,这里面可以看到rc创建的pod名字   kubectl describe rc

ReplicaSet(RS)

rs 控制器,看文档实验

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs1
  labels:
    test2: bbb
spec:
  replicas: 2
  selector:
    matchLabels:
      test1: aaa
  template:
    metadata:
      labels:
        test1: aaa
    spec:
      containers:
      - image: nginx
        name: nginx

# 注意这些lables,一个代表Labels,一个代表Selector

 

 # 查看rs 运行情况

# 查看rs 详细情况

# 增加RS 运行的副本数 

   

# 都是通过depoly 模板进行修改

健康性检查  (探测)

检测方式之一:  liveness probe -- command 

command  在容器里执行一个命令,检测此命令能否正常执行

# 创建新的一个NS空间, 开始进行试验  8-probe

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    test: liveness
    run: liveness-exec
  name: liveness-exec
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: busybox
    imagePullPolicy: IfNotPresent
    name: liveness-exec
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 10
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5   # 容器启动5s内不检测
      periodSeconds: 5         # 每5s检测一次
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 通过livenessProbe字段下面的command来进行检测,如果发现没有/tmp/healthy文件,则容器重启

kubectl describe pod liveness-exec    或者 kubectl get ev 来进行观察

 

  

 检测方式之二:  liveness probe -- httpGET/tcp

httpGET  

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: liveness-http
  name: liveness-http
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: liveness-http
    livenessProbe:
      failureThreshold: 3       # 当Pod启动了并且探测到失败,K8s的重试次数。存活探测情况下的放弃就意味着>重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
      httpGet:
        path: /index.html       # 这里并非指的根目录,而是 指的是nginx主目录/usr/share/nginx/html
        port: 80
      initialDelaySeconds: 10   # 容器启动10s内不检测
      periodSeconds: 10         # 每5s检测一次
      successThreshold: 1       # 检测失败后,再次检测。连续1次才被认定为成功,默认是1,对于liveness必须是
1,最小值是1.
      timeoutSeconds: 10        # 探测超时时间,默认为10秒,最小1秒
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 官网文档探测器(livenessProbe)详细介绍

# 模拟删掉主页文件

kubectl exec -it liveness-http -- rm /usr/share/nginx/html/index.html

 

  

TCPSocket

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: liveness-tcp
  name: liveness-tcp
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: liveness-tcp
    livenessProbe:
      failureThreshold: 3       # 当Pod启动了并且探测到失败,K8s的重试次数。存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
      tcpSocket:
        port: 81
      initialDelaySeconds: 10   # 容器启动10s内不检测
      periodSeconds: 10         # 每5s检测一次
      successThreshold: 1       # 检测失败后,再次检测。连续1次才被认定为成功,默认是1,对于liveness必须是1,最小值是1.
      timeoutSeconds: 10        # 探测超时时间,默认为10秒,最小1秒
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

#   这样就会自动检测端口81是否存活,如果3次都不成功就会“重启大法”

 

 livenessProbe  通过重启来解决问题

 readinessProbe  检测到问题,并不会使用“重启大法”

# readinessProbe  -- command

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: readiness-exec
  name: readiness-exec
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: busybox
    imagePullPolicy: IfNotPresent
    name: readiness-exec
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 10
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5   # 容器启动5s内不检测
      periodSeconds: 5         # 每5s检测一次
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# readinessProbe  -- http

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: readiness-http
  name: readiness-http
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: readiness-http
    readinessProbe:
      failureThreshold: 3       # 当Pod启动了并且探测到失败,K8s的重试次数。存活探测情况下的放弃就意味着
重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 10   # 容器启动10s内不检测
      periodSeconds: 10         # 每5s检测一次
      successThreshold: 1       # 检测失败后,再次检测。连续1次才被认定为成功,默认是1,对于readiness必须
是1,最小值是1.
      timeoutSeconds: 10        # 探测超时时间,默认为10秒,最小1秒
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# readinessProbe  -- Tcp

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: readiness-tcp
  name: readiness-tcp
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: readiness-tcp
    readinessProbe:
      failureThreshold: 3       # 当Pod启动了并且探测到失败,K8s的重试次数。存活探测情况下的放弃就意味着
重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1
      tcpSocket:
        port: 81
      initialDelaySeconds: 10   # 容器启动10s内不检测
      periodSeconds: 10         # 每5s检测一次
      successThreshold: 1       # 检测失败后,再次检测。连续1次才被认定为成功,默认是1,对于readiness必须
是1,最小值是1.
      timeoutSeconds: 10        # 探测超时时间,默认为10秒,最小1秒
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

文件写法和livenessProbe类似,只是关键词不一样

liveness -- 通过重启来解决问题
readiness -- 检测到问题,并不重启(svc接受的请求不在转发给此pod)

 kubectl  get ev  # 查看事件,用于排错

# 创建服务

kubectl expose --name=<SVC_NAME> deploy <DEPLOY_NAME> --port=<PORT_NUMBER> --type=NodePort

  

# svc 负载均衡 测试(每个容器的index.html首页为了方便识别,分别修改了111,222,333)

  

job

创建job   kubectl create job <JOB_NAME> --image=<IMAGE_NAME> --dry-run=client -o yaml > <YAML_NAME>

# 修改配置文件,执行一个date命令,然后休息10秒

 # 可以看到命令执行成功

 

 # 可以看到job 已经1/1 表示执行完成

  

# job 模式不允许使用Always

# 如果使用过了就出现提示,只允许使用NeverOnFailure

Never: 不重启--通过创建新的pod来解决问题

OnFailure: 如果没有完成任务,则不停的通过创建重启来完成

  

 # job常用的一些参数介绍

backoffLimit: 重试次数

completions: 至少有几次成功

parallelism: 同时一次创建几个任务

  

# 圆周率实验(一次性计算一个圆周率)

# 所需镜像   docker pull perl

# 编辑yaml文件

 

 # 执行结果,运算出圆周率后200位的值

   

cronjob   简写cj

# 类似linux命令 crontab

 # 创建cronjob的yaml文件

  # 修改yaml

 

# 可以看到cj,根据schedule每一分钟会创建一个pod,执行一次date命令

 

 kubectl get ev 里面可以查看到每分钟创建的情况

服务的配置    svc

服务的介绍

创建服务

服务的发现

服务的发布

# 首先去要创建一个deployment,
kubectl create deploy dp1 --image=nginx --dry-run=client -o yaml > dp1.yaml

 # 确认服务使用的IP地址段    kubeadm  config view

  # podsvc 所在的网段是集群内部可访问

# 实验阶段

# 创建deploy ,修改默认副本数到2

# 修改默认的副本数为3 kubectl scale deploy <DEPLOY_NAME> --replicas=<NUMBER>

# 临时修改3个pod里面nginx首页显示内容

 # 开始创建svc服务    kubectl expose --name=<SVC_NAME> deploy <DEPLOY_NAME> --port=<PORT_NUMBER> --target-port=<PORT_NUMBER>

 # svc服务的CLUSTER-IP也只是集群内部可访问的

# 找到svc selector 标签,快速定位对应的pods

  

服务发现

 服务的发现通过三种方式:

1. 直接通过clusterIP

   

2. 通过变量

 注意事项:

1)需要相同的命名空间

2)变量获取只能获取创建之前svc的变量

3. dns

wordpress+mysql实验,先去download相关镜像

# 准备阶段(work节点镜像准备)

sudo docker pull hub.c.163.com/library/mysql:latest

sudo docker pull hub.c.163.com/library/wordpress:latest

sudo docker pull hub.c.163.com/library/centos:latest

首先,创建mysql 的 pod

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: db
  name: db
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
  containers:
  - image: hub.c.163.com/library/mysql:latest  # 这里记得替换为自己使用的image地址
    imagePullPolicy: IfNotPresent
    name: db
    resources: {}
    env:
    - name: MYSQL_ROOT_PASSWORD                 # MySQL需要的一些变量
      value: mysql_password
    - name: MYSQL_DATABASE
      value: db_name
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 使用生产的yaml文件,创建一个数据库的svc的服务

 kubectl expose --name=dbsvc pod db --port=3306

# 查看kubectl  get svc -o wide 

  

在创建wordpress pod

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: blog
  name: blog
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
  containers:
  - image: hub.c.163.com/library/wordpress:latest
    imagePullPolicy: IfNotPresent
    name: blog
    resources: {}
    env:
    - name: WORDPRESS_DB_USER
      value: db_username
    - name: WORDPRESS_DB_PASSWORD
      value: password
    - name: WORDPRESS_DB_NAME
      value: db_name
    - name: WORDPRESS_DB_HOST
      value: cluster-ip(x.x.x.x) # 这个地址来源你的db_svc
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

# 同样的创建blog的svc服务(为了方便测试,这里使用了一个参数--type=NodePort把端口映射到物理机随机端口上

kubectl expose --name=blogsvc pod blog --port=80 --type=NodePort

# 记住这个端口,找一台机器访问物理机这个端口进行wordpress初始化

  # 访问,集群的物理IP+NodePort端口,看到如下界面

# 填上基本信息,只要没有出现让你填写数据库相关信息,表示通过cluster-ip方式成功。

# 变量的方式

跟着,我们创建一个临时pod,查看env(当前的pod,会记录之前创建好的svc的信息)

kubectl run c1 --rm -it --image=busybox --image-pull-policy=IfNotPresent -- sh

记录方式:

大写的服务名_SERVICE_HOST=  那个服务的IP

大写的服务名_SERVICE_PORT= 那个服务的端口

Note:这个pod里,它只记录那些在这个pod创建之前的svc的信息,当前创建的是不会记录的

  

# 这个pod里再次创建(删除blog 的pod,我们修改为这个变量值,再次创建)

 # 缺点:必须在同一个命名空间,需要注意创建顺序

 # DNS的方式  

# 系统里面默认的kube-system 里面存在一个kube-dns的服务

 # 查看这个svc里面跑了2个pod,这个2个pod的作用就是做名称解析

 

 # 开始测试,创建一个新的pod名叫 demo1,并为它创建一个svc,修改index.html内容为“Loki in here!”

# 发现访问的svc的名称,也可以直接访问到 

 原理解析: 当我们每创建一个svc的时候,这个svc就会向kube-system这个ns去注册,服务名 -- IP

# 创建的一个nginx pod   <----相同的命名空间

# 在不同的命名空间需要加上命名空间名

 

# 相同命名空间,直接用变量名(DNS),如果不同命名空间还需要加上 空间名     服务名.NameSpace名

 

服务的发布

原文地址:https://www.cnblogs.com/Cong0ks/p/14531370.html