Kubernetes 容器编排(2)

可视化部署

官方Dashboard

部署Dashboard

# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml
# kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
# 注意将 type: ClusterIP 改为 type: NodePort

# kubectl get svc -A |grep kubernetes-dashboard
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.107.179.10   <none>        8000/TCP                 38s
kubernetes-dashboard   kubernetes-dashboard        NodePort    10.110.18.72    <none>        443:32231/TCP            38s

 创建访问账号

#创建访问账号,准备一个yaml文件; vi dash.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
# kubectl apply -f dash.yaml

 获取访问令牌

#获取访问令牌
# kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
eyJhbGciOiJSUzI1NiIsImtpZCI6ImhRa2Q3UDFGempzb3VneVdUS0R0dk50SHlwUHExc0tuT21SOTdWQkczaG8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXBmbGxyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJlNDk0MTFhYS0zOTVhLTRkYzUtYmZmYS04MDZiODE3M2VmZWEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.k3Gd9vRF6gP3Zxy89x14y4I2RCGn232bGLo9A5iEmeMl6BRPdJXZPbwy9fm3OT6ZjVc7LHiRgArczjZuCU3Sis4tIA_24A55h74WQE_JTeiZ5XnSGRknYQRHFSqyBrTaTxgDJb-O-DHol8GQLQjr6gIPzppHc-RhWhUFFNnPVP1nr2MLFBkvIT_qAcbHP6McFf2N6IsYwVFuvyIO77qWcmyFlgSr8a3A0INEJYB2bFPRL82rNc41c0TsUwOguQbJYrDA9lBqVpSff_7Uk_-7ycabZclbZX1HPz2-F59LQW7NWQy7biZw5b25AZaXAG3kL3SDuRRBoMNS92MmDFsVyA

浏览器访问

任意节点ip+端口[上面查看到为32231]
url https://192.168.246.216:32231/
使用token登录

 kuboard 部署

[root@kube-master ~]# kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml[root@kube-master ~]# kubectl get pod -n kuboard
NAME                               READY   STATUS    RESTARTS         AGE
kuboard-agent-2-5c54dcb98f-4vqvc   1/1     Running   24 (7m50s ago)   16d
kuboard-agent-747b97fdb7-j42wr     1/1     Running   24 (7m34s ago)   16d
kuboard-etcd-ccdxk                 1/1     Running   16 (8m58s ago)   16d
kuboard-etcd-k586q                 1/1     Running   16 (8m53s ago)   16d
kuboard-questdb-bd65d6b96-rgx4x    1/1     Running   10 (8m53s ago)   16d
kuboard-v3-5fc46b5557-zwnsf        1/1     Running   12 (8m53s ago)   16d[root@kube-master ~]# kubectl get svc -n kuboard
NAME         TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                                        AGE
kuboard-v3   NodePort   10.96.25.125   <none>        80:30080/TCP,10081:30081/TCP,10081:30081/UDP   16d

kubesphere 部署

官方文档:

在 Kubernetes 上最小化安装 KubeSphere

 

# 运行安装
[root@kube-master ~]# kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.0/kubesphere-installer.yaml
[root@kube-master ~]# kubectl apply -f https://github.com/kubesphere/ks-installer/releases/download/v3.4.0/cluster-configuration.yaml

# 查看日志
[root@kube-master ~]# kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f

#卸载kubesphere

[root@kube-master ~]# curl https://raw.githubusercontent.com/kubesphere/ks-installer/release-3.4/scripts/kubesphere-delete.sh | sh

 rainbond 部署

[Rainbond](https://www.rainbond.com/)

[root@kube-master ~]# curl -o install.sh https://get.rainbond.com && bash ./install.sh
RO
[root@kube-master ~]# helm repo add rainbond https://openchart.goodrain.com/goodrain/rainbond
[root@kube-master ~]# helm repo update
[root@kube-master ~]# kubectl create namespace rbd-system

 卸载

如果是基于helm创建的rainbond
[root@kube-master ~]# helm uninstall rainbond -n rbd-system
如果是基于官方脚本创建的rainbond
# Delete PVC
[root@kube-master ~]# kubectl get pvc -n rbd-system | grep -v NAME | awk '{print $1}' | xargs kubectl delete pvc -n rbd-system
# Delete PV
[root@kube-master ~]# kubectl get pv | grep rbd-system | grep -v NAME | awk '{print $1}' | xargs kubectl delete pv
# Delete CRD
[root@kube-master ~]# kubectl delete crd componentdefinitions.rainbond.io \
helmapps.rainbond.io \
rainbondclusters.rainbond.io \
rainbondpackages.rainbond.io \
rainbondvolumes.rainbond.io \
rbdcomponents.rainbond.io \
servicemonitors.monitoring.coreos.com \
thirdcomponents.rainbond.io \
rbdabilities.rainbond.io \
rbdplugins.rainbond.io \
servicemeshclasses.rainbond.io \
servicemeshes.rainbond.io \
-n rbd-system
# Delete NAMESPACE
[root@kube-master ~]# kubectl delete ns rbd-system

集群常用指令

基础控制指令

# 查看对应资源: 状态
$ kubectl get <SOURCE_NAME> -n <NAMESPACE> -o wide
kubectl get nodes -n kuboard -o wide
# 查看对应资源: 事件信息
$ kubectl describe <SOURCE_NAME> <SOURCE_NAME_RANDOM_ID> -n <NAMESPACE>
kubectl describe pods kube-apiserver-kube-master -n kube-system
# 查看pod资源: 日志
$ kubectl logs -f <SOURCE_NAME_RANDOM_ID> [CONTINER_NAME] -n <NAMESPACE>
kubectl logs -f kube-apiserver-kube-master -n kube-system
# 创建资源: 根据资源清单
$ kubectl apply[or create] -f <SOURCE_FILENAME>.yaml
kubectl apply -f mysql.yml
cat mysql.yml
apiVersion: v1
kind: Namespace
metadata:
  name: xian2304

---
apiVersion: v1
kind: Pod
metadata:
  name: database
  namespace: xian2304
  labels:
    name: database
spec:
  containers:
    - name: database
      image: 10.36.192.206:8088/library/mysql:5.7
      env:
        - name: MYSQL_ROOT_PASSWORD
# 删除资源: 根据资源清单
$ kubectl delete -f <SOURCE_FILENAME>.yaml
kubectl delete -f mysql.yml 
# 修改资源: 根据反射出的etcd中的配置内容, 生产中不允许该项操作, 且命令禁止
$ kubectl edit <SOURCE_NAME> <SOURCE_NAME_RANDOM_ID> -n <NAMESPACE>
kubectl edit pods kube-apiserver-kube-master -n kube-system

命令实践

 

# 查看node状态
$ kubectl get node # -o wide 显示更加详细的信息

# 查看service对象
$ kubectl get svc

# 查看kube-system名称空间内的Pod
$ kubectl get pod -n kube-system

# 查看所有名称空间内的pod
$ kubectl get pod -A

# 查看集群信息
$ kubectl cluster-info

# 查看各组件信息
$ kubectl -s https://kube-master:6443 get componentstatuses

# 查看各资源对象对应的api版本
$ kubectl explain pod

# 查看帮助信息
$ kubectl explain deployment
$ kubectl explain deployment.spec
$ kubectl explain deployment.spec.replicas

备注 

问题一 查看各组件信息,可能会发现错误
$ kubectl -s https://192.168.96.143:6443 get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS      MESSAGE                                                                                       ERROR
scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused   
controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused   
etcd-0               Healthy     {"health":"true"}                                                           

问题一解决
$ vim /etc/kubernetes/manifests/kube-scheduler.yaml
 10 spec:
 11   containers:
 12   - command:
 13     - kube-scheduler
 14     - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
 15     - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
 16     - --bind-address=127.0.0.1
 17     - --kubeconfig=/etc/kubernetes/scheduler.conf
 18     - --leader-elect=true
 19     - --port=0   # 将此行注释或删除
 
 $ vim /etc/kubernetes/manifests/kube-controller-manager.yaml
  10 spec:
 11   containers:
 12   - command:
 13     - kube-controller-manager
 14     - --allocate-node-cidrs=true
 15     - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
 16     - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
 17     - --bind-address=127.0.0.1
 18     - --client-ca-file=/etc/kubernetes/pki/ca.crt
 19     - --cluster-cidr=10.244.0.0/16
 20     - --cluster-name=kubernetes
 21     - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
 22     - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
 23     - --controllers=*,bootstrapsigner,tokencleaner
 24     - --kubeconfig=/etc/kubernetes/controller-manager.conf
 25     - --port=0 # 将此行注释或删除
 
$ systemctl restart kubelet
 
$ kubectl -s https://192.168.96.143:6443 get componentstatuses
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}

 Yaml语法解析

        YAML是一个类似 XML、JSON 的标记性语言。它强调以数据为中心,并不是以标识语言为重点。因而YAML本身的定义比较简单,号称"一种人性化的数据格式语言"。

YAML的语法比较简单,主要有下面几个:
1、大小写敏感
2、使用缩进表示层级关系
3、缩进不允许使用tab,只允许空格( 低版本限制 )
4、缩进的空格数不重要,只要相同层级的元素左对齐即可
5、'#'表示注释

YAML支持以下几种数据类型:
1、纯量:单个的、不可再分的值
2、对象:键值对的集合,又称为映射(mapping)/ 哈希(hash) / 字典(dictionary)
3、数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)

补充说明:
1、书写yaml切记: 后面要加一个空格
2、如果需要将多段yaml配置放在一个文件中,中间要使用---分隔

 举个例子,通过声明式配置yaml 创建名称空间

$ vim namespace.yaml
apiVersion: v1
    kind: Namespace
    metadata:
          name: webserver
  
$ kubectl apply -f namespace.yaml

# 如果通过命令行创建
$ kubectl create namespace webserver
# 删除名称空间[注意,这将删除名称空间下的所有资源]
$ kubectl delete namespace webserver

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元; Pod 中会启动一个或一组紧密相关的业务容器, 各个业务容器相当于Pod 中的各个进程, 此时就可以将Pod 作为虚拟机看待; 在创建 Pod 时会启动一个init容器, 用来初始化存储和网络, 其余的业务容器都将在init容器启动后启动, 业务容器共享init容器的存储和网络; Pod 只是一个逻辑单元, 并不是真实存在的“主机”, 这种类比主机的概念可以更好的符合现有互联网中几乎所有的虚拟化设计; 像之前运行在虚拟机中的 nginx、mysql、php均可以使用对应的镜像运行出对应的容器在Pod中, 来类比虚拟机中运行这三者;

  对于 Pod 而言, 在运行的过程中, k8s为了控制其生命周期的状态, 增加了容器探测指针资源限额期望状态保持多容器结合安全策略设定控制器受管故障处理策略 等; Pod在平时是不能够被单独创建的, 而是需要使用控制器对其创建, 这样可以时刻保持Pod的期望状态;

  在Kubernetes中所有的资源均可通过命令行参数或者资源清单[yaml/json]的方式进行创建和修改, 但由于Kubernetes属于声明式资源控制集群, 故大多管理Kubernetes集群的方式采用资源配置清单; 资源配置清单可以很好的追溯资源的原型和详细的配置, 且配合版本控制能够完成更好的溯源、回滚、发布等操作; 所以课程中所有的资源创建和修改都会采用资源配置清单的方式, 除部分命令行操作以外;

k8s中的Pod

  Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元; Pod 中会启动一个或一组紧密相关的业务容器, 各个业务容器相当于Pod 中的各个进程, 此时就可以将Pod 作为虚拟机看待; 在创建 Pod 时会启动一个init容器, 用来初始化存储和网络, 其余的业务容器都将在init容器启动后启动, 业务容器共享init容器的存储和网络; Pod 只是一个逻辑单元, 并不是真实存在的“主机”, 这种类比主机的概念可以更好的符合现有互联网中几乎所有的虚拟化设计; 像之前运行在虚拟机中的 nginx、mysql、php均可以使用对应的镜像运行出对应的容器在Pod中, 来类比虚拟机中运行这三者;

  对于 Pod 而言, 在运行的过程中, k8s为了控制其生命周期的状态, 增加了容器探测指针资源限额期望状态保持多容器结合安全策略设定控制器受管故障处理策略 等; Pod在平时是不能够被单独创建的, 而是需要使用控制器对其创建, 这样可以时刻保持Pod的期望状态;

  在Kubernetes中所有的资源均可通过命令行参数或者资源清单[yaml/json]的方式进行创建和修改, 但由于Kubernetes属于声明式资源控制集群, 故大多管理Kubernetes集群的方式采用资源配置清单; 资源配置清单可以很好的追溯资源的原型和详细的配置, 且配合版本控制能够完成更好的溯源、回滚、发布等操作; 所以课程中所有的资源创建和修改都会采用资源配置清单的方式, 除部分命令行操作以外;

Pod API 对象 

问题:

   通过yaml文件创建pod的时候里面有容器,这个文件里面到底哪些属性属于 Pod 对象,哪些属性属于 Container?

解决:

   共同特征是,它们描述的是"机器"这个整体,而不是里面运行的"程序"。

容器可选的设置属性包括:

Pod是 k8s 项目中的最小编排单位。将这个设计落实到 API 对象上,容器(Container)就成了 Pod 属性里一个普通的字段。
把 Pod 看成传统环境里的"虚拟机机器"、把容器看作是运行在这个"机器"里的"用户程序",那么很多关于 Pod 对象的设计就非常容易理解了。
凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的
比如:
配置这个"机器"的网卡(即:Pod 的网络定义)
配置这个"机器"的磁盘(即:Pod 的存储定义)
配置这个"机器"的防火墙(即:Pod 的安全定义)
这台"机器"运行在哪个服务器之上(即:Pod 的调度)
kind:指定了这个 API 对象的类型(Type),是一个 Pod,根据实际情况,此处资源类型可以是Deployment、Job、Ingress、Service等。
metadata:包含Pod的一些meta信息,比如名称、namespace、标签等信息.
spec:specification of the resource content 指定该资源的内容,包括一些container,storage,volume以及其他Kubernetes需要的参数,以及诸如是否在容器失败时重新启动容器的属性。可在特定Kubernetes API找到完整的Kubernetes Pod的属性。
specification----->[spesɪfɪˈkeɪʃn]
"name": 容器名称
"image": 容器镜像
"command": 容器启动指令
"args": 指令参数
"workingDir": 工作目录
"ports": 容器端口
"env": 环境变量
"resource": 资源限制
"volumeMounts": 卷挂载
"livenessProbe": 存活探针
"readinessProbe": 就绪探针
"startupProbe": 启动探针
"livecycle": 钩子函数
"terminationMessagePath": 容器的异常终止消息的路径,默认在 /dev/termination-log
"imagePullPolicy": 镜像拉去策略
"securityContext": 安全上下文
"stdin": 给容器分配标准输入,类似docker run -i
"tty": 分配终端

创建一个pod

$ vim nginx.yaml
apiVersion: v1
kind: Pod
metadata:name: nginxlabels:app: nginx
spec:containers:- name: nginximage: nginx:1.16.1ports:- containerPort: 80
​
$ kubectl apply -f nginx.yaml

pod是如何被创建的

  • step1: kubectl 向 k8s api server 发起一个create pod 请求

  • step2: k8s api server接收到pod创建请求后,不会去直接创建pod;而是生成一个包含创建信息的yaml。

  • step3: apiserver 将刚才的yaml信息写入etcd数据库。

  • step4: scheduler 查看 k8s api,判断:pod.spec.Node == null,若为null,表示这个Pod请求是新来的,需要创建;因此先进行调度计算,找到最适合的node。并更新数据库

  • step5: node节点上的Kubelet通过监听数据库更新,发现有新的任务与自己的node编号匹配,则进行任务创建

创建一个单容器pod

$ vim mysql.yaml
apiVersion: v1
kind: Pod
metadata:name: mysqllabels:name: mysql
spec:restartPolicy: OnFailurecontainers:- name: mysqlimage: mysql:5.7imagePullPolicy: IfNotPresentenv:- name: MYSQL_ROOT_PASSWORDvalue: "123456"resources:limits:memory: "1024Mi"cpu: "1000m"ports:- containerPort: 3306nodeSelector:kubernetes.io/hostname: kub-k8s-node2# nodeName: kub-k8s-node2
​
$ kubectl apply -f mysql.yaml
​
# 字段解析
restartPolicy:
pod 重启策略,可选参数有:
1、Always:Pod中的容器无论如何停止都会自动重启
2、OnFailure: Pod中的容器非正常停止会自动重启
3、Never: Pod中的容器无论怎样都不会自动重启
​
imagePullPolicy:
镜像拉取策略,可选参数有:
1、Always:总是重新拉取
2、IfNotPresent:默认,如果本地有,则不拉取
3、Never:只是用本地镜像,从不拉取
​
nodeSelector:
节点选择器:可以指定node的标签,查看标签指令:
nodeName:
节点名称: 可以指定node的名称进行调度
$ kubectl get node --show-labels

创建一个多容器pod

#vim lnmp.yaml
---
apiVersion: v1
kind: Pod
metadata:name: nginx-manynamespace: defaultlabels:app: nginx
spec:restartPolicy: OnFailurecontainers:- name: nginximage: nginx:1.16.1imagePullPolicy: IfNotPresentports:- containerPort: 80- name: php-fpmimage: php:8.0-fpm-alpineimagePullPolicy: IfNotPresentports:- containerPort: 9000
​
$ kubectl apply -f lnmp.yaml# 字段解析
nodeSelector:
节点选择器:可以指定node的标签,查看标签指令:
​
$ kubectl get node --show-labels
配置节点标签
添加标签
kubectl label nodes node3 name=value
删除标签
kubectl label nodes node3 name-

Pod容器的交互

创建pod,并做本地解析
vim host-alias.yaml
​
---
apiVersion: v1
kind: Pod
metadata:name: centoslabels:name: centos
spec:containers:- name: centosimage: daocloud.io/library/centos:7command:- "tail"- "-f"- "/dev/null"hostAliases:- ip: "192.168.165.135"hostnames:- "master"- "k8s-master"- "apiserver"
​
# 字段解析
command:
启动容器时执行的指令,类似于docker run -it 镜像 tail -f /dev/null
​
hostAliases:
在容器中的/etc/hosts文件中配置本地解析
pod共享进程
[root@kub-k8s-master prome]# kubectl delete -f pod.yml
pod "website" deleted
[root@kub-k8s-master prome]# vim pod.yml   #修改如下。最好是提前将镜像pull下来。
---
apiVersion: v1
kind: Pod
metadata:name: websitelabels:app: website
spec:shareProcessNamespace: true  #共享进程名称空间containers:- name: test-webimage: daocloud.io/library/nginxports:- containerPort: 80- name: busyboximage: daocloud.io/library/busyboxstdin: truetty: true2.创建
[root@kub-k8s-master prome]# kubectl apply -f pod.yml 
pod/website created
1. 定义了 shareProcessNamespace=true
表示这个 Pod 里的容器要共享进程(PID Namespace)如果是false则为不共享。
2. 定义了两个容器:
一个 nginx 容器
一个开启了 tty 和 stdin 的 busybos 容器
​
在 Pod 的 YAML 文件里声明开启它们俩,等同于设置了 docker run 里的 -it(-i 即 stdin,-t 即 tty)参数。此 Pod 被创建后,就可以使用 shell 容器的 tty 跟这个容器进行交互了。
我们通过kubectl可以查看到
# kubectl exec -it website -c busybox -- ps aux
PID   USER     TIME  COMMAND1 root      0:00 /pause7 root      0:00 nginx: master process nginx -g daemon off;35 101       0:00 nginx: worker process36 root      0:00 sh66 root      0:00 ps aux在busybox中可以查看到nginx的进程
pod共用宿主机namespace
刚才的都是pod里面容器的Namespace,并没有和本机的Namespace做共享,接下来我们可以做与本机的Namespace共享,可以在容器里面看到本机的进程。
​
[root@kub-k8s-master prome]# kubectl delete -f pod.yml 
pod "website" deleted
[root@kub-k8s-master prome]# vim pod.yml #修改如下
---
apiVersion: v1
kind: Pod
metadata:name: websitelabels:app: website
spec:hostNetwork: true  #共享宿主机网络hostIPC: true  #共享ipc通信hostPID: true  #共享宿主机的pidcontainers:- name: test-webimage: daocloud.io/library/nginxports:- containerPort: 80- name: busybosimage: daocloud.io/library/busyboxstdin: truetty: true
创建pod
[root@kub-k8s-master prome]# kubectl apply -f pod.yml 
pod/website created

定义了共享宿主机的 Network、IPC 和 PID Namespace。这样,此 Pod 里的所有容器,会直接使用宿主机的网络、直接与宿主机进行 IPC 通信、看到宿主机里正在运行的所有进程。

钩子函数lifecycle

kubernetes 在主容器启动之后和删除之前提供了两个钩子函数:

  • post start:容器创建之后执行,如果失败会重启容器

  • pre stop:容器删除之前执行,执行完成之后容器将成功删除,在其完成之前会阻塞删除容器的操作

  • 钩子函数有三种定义方式

  • 第一种 exec 执行指令

  • 第二种 在容器中请求端口

  • 第三种 向容器发起http请求

lifecycle:postStart: exec:command:- cat- /etc/host
lifecycle:postStart:tcpSocket:port: 8080
   lifecycle:postStart:httpGet:path: /                  # URI地址port: 80                 # 端口号host: 192.168.96.10     # 主机地址  scheme: HTTP
一个钩子函数的示例
$ vim nginx-lifecycle.yaml 
apiVersion: v1
kind: Pod
metadata:name: nginx-lifecyclenamespace: defaultlabels:app: nginx
spec:containers:- name: nginx-lifecycleimage: nginx:1.20.2ports:- containerPort: 80protocol: TCPlifecycle:postStart:exec:command: ["/bin/sh", "-c", "echo '<h1>this is a nginx-lifecycle test page</h1>' > /usr/share/nginx/html/index.html"]preStop:exec:command: ["/usr/sbin/nginx", "-s", "quit"]
​
$ kubectl apply -f nginx-lifecycle.yaml 
pod/pod-lifecycle created

容器监控检查及恢复机制

         在 k8s 中,可以为 Pod 里的容器定义一个健康检查"探针"(Probe)。kubelet 就会根据这个 Probe 的返回值决定这个容器的状态,而不是直接以容器是否运行(来自 Docker 返回的信息)作为依据。这种机制,是生产环境中保证应用健康存活的重要手段。

命令模式探针

Kubernetes 文档中的例子:

[root@kub-k8s-master ~]# cd prome/
[root@kub-k8s-master prome]# vim test-liveness-exec.yaml
---
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: test-liveness-exec
spec:containers:- name: livenessimage: nginxargs:- /bin/sh- -c  - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 50livenessProbe:    #探针,健康检查exec:    #类型command:  #命令- cat - /tmp/healthyinitialDelaySeconds: 5   #健康检查,在容器启动5s后开始执行periodSeconds: 5   #每5s执行一次
它在启动之后做的第一件事是在/tmp目录下创建了一个healthy文件,以此作为自己已经正常运行的标志。而30s过后,它会把这个文件删除掉。
与此同时,定义了一个这样的 livenessProbe(健康检查)。它的类型是 exec,它会在容器启动后,在容器里面执行一句我们指定的命令,比如:"cat /tmp/healthy"。这时,如果这个文件存在,这条命令的返回值就是 0,Pod就会认为这个容器不仅已经启动,而且是健康的。这个健康检查,在容器启动5s后开始执行(initialDelaySeconds: 5),每5s执行一次(periodSeconds: 5)。

创建Pod:

[root@kub-k8s-master prome]# kubectl apply -f test-liveness-exec.yaml 
pod/test-liveness-exec created

查看 Pod 的状态:

[root@kub-k8s-master prome]# kubectl get pod 
NAME                    READY   STATUS    RESTARTS   AGE
nginx-configmap         1/1     Running   0          16h
nginx-pod               1/1     Running   0          12h
test-liveness-exec      1/1     Running   0          75s

由于已经通过了健康检查,这个 Pod 就进入了 Running 状态。

然后30 s 之后,再查看一下 Pod 的 Events:

[root@kub-k8s-master prome]# kubectl describe pod test-liveness-exec

发现,这个 Pod 在 Events 报告了一个异常:

Events:Type     Reason     Age                  From                    Message----     ------     ----                 ----                    -------
Warning  Unhealthy  54s (x9 over 3m34s)  kubelet, kub-k8s-node1  Liveness probe failed: cat: /tmp/healthy: No such file or directory

这个健康检查探查到 /tmp/healthy 已经不存在了,所以它报告容器是不健康的。那么接下来会发生什么呢?

再次查看一下这个 Pod 的状态:

[root@kub-k8s-master prome]# kubectl get pod test-liveness-exec
NAME                 READY   STATUS    RESTARTS   AGE
test-liveness-exec   1/1     Running   4          5m19s

这时发现,Pod 并没有进入 Failed 状态,而是保持了 Running 状态。这是为什么呢?

RESTARTS 字段从 0 到 1 的变化,就明白原因了:这个异常的容器已经被 Kubernetes 重启了。在这个过程中,Pod 保持 Running 状态不变。 #注 k8s 中并没有 Docker 的 Stop 语义。所以如果容器被探针检测到有问题,查看状态虽然看到的是 Restart,但实际却是重新创建了容器。

这个功能就是 Kubernetes 里的Pod 恢复机制,也叫 restartPolicy。它是 Pod 的 Spec 部分的一个标准字段(pod.spec.restartPolicy),默认值是 Always,即:任何时候这个容器发生了异常,它一定会被重新创建。

小提示:

Pod 的恢复过程,永远都是发生在当前节点上,而不会跑到别的节点上去。事实上,一旦一个 Pod 与一个节点(Node)绑定,除非这个绑定发生了变化(pod.spec.node 字段被修改),否则它永远都不会离开这个节点。这也就意味着,如果这个宿主机宕机了,这个 Pod 也不会主动迁移到其他节点上去。

http get方式探针

[root@kub-k8s-master prome]# vim liveness-httpget.yaml
---
apiVersion: v1
kind: Pod
metadata:name: liveness-httpget-podnamespace: default
spec:containers:- name: liveness-exec-containerimage: nginximagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80livenessProbe:  #探针,健康检查httpGet:port: httppath: /index.htmlinitialDelaySeconds: 1periodSeconds: 3

创建该pod

[root@kub-k8s-master prome]# kubectl create -f liveness-httpget.yaml 
pod/liveness-httpget-pod created

查看当前pod的状态

[root@kub-k8s-master prome]# kubectl describe pod liveness-httpget-pod
...
Liveness:       http-get http://:http/index.html delay=1s timeout=1s period=3s #success=1 #failure=3
...

登陆容器

测试将容器内的index.html删除掉
[root@kub-k8s-master prome]# kubectl exec -it liveness-httpget-pod /bin/bash
root@liveness-httpget-pod:/# mv /usr/share/nginx/html/index.html index.html
root@liveness-httpget-pod:/# command terminated with exit code 137
可以看到,当把index.html移走后,这个容器立马就退出了。

此时,查看pod的信息

[root@kub-k8s-master prome]# kubectl describe pod liveness-httpget-pod
...
Normal   Killing    49s                  kubelet, kub-k8s-node2  Container liveness-exec-container failed liveness probe, will be restartedNormal   Pulled     49s                  kubelet, kub-k8s-node2  Container image "daocloud.io/library/nginx" already present on machine
...

看输出,容器由于健康检查未通过,pod会被杀掉,并重新创建

[root@kub-k8s-master prome]#  kubectl get pods
NAME                    READY   STATUS             RESTARTS   AGE
lifecycle-demo          1/1     Running            1          34h
liveness-httpget-pod    1/1     Running            1          5m42s
​
#restarts 为 1

重新登陆容器,发现index.html又出现了,证明容器是被重拉了。

[root@kub-k8s-master prome]# kubectl exec -it liveness-httpget-pod /bin/bash
root@liveness-httpget-pod:/# cat /usr/share/nginx/html/index.html

POD 的恢复策略

Pod  恢复策略:
可以通过设置 restartPolicy,改变 Pod 的恢复策略。一共有3种:
    1. Always:      在任何情况下,只要容器不在运行状态,就自动重启容器;
    2. OnFailure:    只在容器 异常时才自动重启容器;
    3. Never:         从来不重启容器。
实际使用时,需要根据应用运行的特性,合理设置这三种恢复策略。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/225040.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

案例064:基于微信小程序的考研论坛设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

深度学习常用数学知识

文章目录 向量的内积 a bHadamard积 a ⊙ b范数 向量的内积 a b 向量的内积也称为点积&#xff0c;用来计算两个向量之间的相似度。在数学上&#xff0c;两个向量的内积等于将一个向量投影到另一个向量上得到的长度再乘以两个向量之间的夹角的余弦值。 使用PyTorch进行向量…

XIAO ESP32S3之实现口罩检测

一、例程介绍 此例程是运行FOMO 轻量检测模型实现人员佩戴口罩检测&#xff0c;Demo中已包含训练好的模型参数&#xff0c;无需再训练。 FOMO(Faster Objects, More Objects) 是由 Edgeimpulse 工程师提出的一种轻量级的目标检测模型&#xff0c;其主要特点是模型非常小&#…

php入门、安装wampserver教程

php声称是全世界最好的语言&#xff0c;今天这篇文章就带大家入门学习php&#xff0c;php和python、javasript一样&#xff0c;是一种弱类型的脚本语言。 一、php开发环境搭建 作为初学者&#xff0c;学习php建议安装wampserver&#xff0c;wampserver是包含了apache、php和mys…

Unity项目里Log系统该怎么设计

其实并没有想完整就设计一个好用的Log系统&#xff0c;然后发出来。记录这个的原因&#xff0c;是在书里看到这么一句话&#xff0c;Log会消耗资源&#xff0c;特别是写文件&#xff0c;因此可以设置一个Log缓冲区&#xff0c;等缓冲区满了再一次性写入文件&#xff0c;以节省资…

MFC逆向之CrackMe Level3 过反调试 + 写注册机

今天我来分享一下,过反调试的方法以及使用IDA还原代码 写注册机的过程 由于内容太多,我准备分为两个帖子写,这个帖子主要是写IDA还原代码,下一个帖子是写反调试的分析以及过反调试和异常 这个CrackMe Level3是一个朋友发我的,我也不知道他在哪里弄的,我感觉挺好玩的,对反调试…

Docker笔记:Docker Swarm, Consul, Gateway, Microservices 集群部署

关于 Consul 服务 Consul是Go语言写的开源的服务发现软件Consul具有服务发现、健康检查、 服务治理、微服务熔断处理等功能 Consul 部署方式1: 直接在linux 上面部署 consul 集群 1 &#xff09;下载 在各个服务器上 下载 consul 后解压并将其目录配置到环境变量中&#xff…

VMP泄露编译的一些注意事项

VMP编译教程 鉴于VMP已经在GitHub上被大佬强制开源&#xff0c;特此出一期编译教程。各位熟悉的可以略过&#xff0c;不熟悉的可以参考一下。 环境&#xff08;软件&#xff09; Visual Studio 2015 - 2022 &#xff08;建议使用VS2019&#xff0c;Qt插件只有这个版本及以上…

vscode的文件和文件夹的警告标志如何消去

由于平时用vscode写一些java的小demo, 但是这个vscode的警告和错误管理很奇怪, 这个警告信息会显示在这个侧边的文件和文件夹中, 我上网上找能不能把这个给去掉的办法, 找了半天没找到。 于是我就自己去查了一下这个vscode的设置, 真让我找到了这方面的开关, 把下面的这个关闭…

Linux学习笔记-Ubuntu下ssh服务器连接异常Connection reset

文章目录 一、问题问题现象1.1 连接重置无法访问的的问题1.2 查看服务器连接状态1.3 使用调试模式查看的信息 二、临时解决方法三、从根源解决问题3.1 问题分析3.2 服务器的ssh日志3.3 修改ssh配置禁止root登录3.4 配置允许所有ip访问3.5 修改认证方法 角色&#xff1a;百世经纶…

selenium+xpath爬取二手房标题

贝壳找房标题爬取需要注意的是&#xff0c;在页面中间有一个小广告 而他就在ul的li下面&#xff0c;当我们进行title所以输出时&#xff0c;会报错。 所以在进行页面解析之前必须把广告叉掉&#xff0c;不然也把广告那一部分的li给爬取下来了 所以&#xff0c;我们&#xff0…

弹性架构:容错系统策略

如今软件无处不在 - 从我们的手机到汽车和电器。这意味着软件系统的可靠性、健壮性和弹性非常重要。 弹性系统可以承受故障或错误而不会完全崩溃。容错能力是弹性的关键部分。即使出现问题&#xff0c;它也能让系统保持正常工作。 在本文中&#xff0c;我们将了解为什么弹性和…

JsRpc技术服务搭建,最简单的JSRPC,Flask+undetected-chromedriver

只需10来行代码快速实现JSRpc&#xff0c;最简单的JSRPC 使用Flask和undetected-chromedriver快速实现JsRpc 推荐Python版本3.7.x及以上&#xff0c;需要pip安装 pip install Flask pip install undetected-chromedriver __author__ jiuLiang __email__ "jiuliangef…

软件测试职业规划

软件测试人员的发展误区【4】 公司开发的产品专业性较强&#xff0c;软件测试人员需要有很强的专业知识&#xff0c;现在软件测试人员发展出现了一种测试管理者不愿意看到的景象&#xff1a; 1、开发技术较强的软件测试人员转向了软件开发(非测试工具开发)&#xff1b; 2、业务…

蓝桥杯专题-真题版含答案-【古代赌局】【古堡算式】【微生物增殖】【密码发生器】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

K中期考核-降低显存的关键

读入模型参数-且不占用显卡 see_memory_usage(‘message’) # 4. 读入checkpiont参数 state_dicttorch.load(../train-output/ args.model_name_or_path.split(/)[-1] /unet/diffusion_pytorch_model.bin, map_locationcpu) # state_dicttorch.load(../train-output/ …

C++报错:error C2238: 意外的标记位于“;”之前

报错信息如下&#xff1a; 编译遇见这样的错误信息主要有一下几种&#xff1a; 情况一&#xff1a; 多数情况下出现这种问题的原因是因为头文件重复包含&#xff1a;即头文件A包含了B&#xff0c;头文件B又包含了A&#xff0c;导致编译器在加载头文件时陷入死循环。 解决办法…

力扣题:数字与字符串间转换-12.16

力扣题-12.16 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;640. 求解方程 解题思想&#xff1a;首先将方程按照“”进行划分&#xff0c;然后分别记录x的因数和常数项&#xff0c;最后进行返回的判断即可 class Solution(object):def solveEqu…

Ubuntu下COLMAP的编译与安装全攻略

文章目录 一、前言二、安装依赖库基本的依赖安装Ceres Solver安装不需要cuda支持需要cuda支持 三、编译colmap四、运行colmap五、总结 一、前言 在计算机视觉领域&#xff0c;colmap是一款功能强大的开源图像重建工具。它提供了包括SfM&#xff08;Structure from Motion&…

git变更关联的远程仓库

git变更关联的远程仓库 git 将本地关联的远程仓库1变更为新建的远程仓库2 1、移除本地的远程仓库关联关系 git remote remove origin 2、添加新的远程仓库地址&#xff1a; git remote add origin gitgithub.com:github-xiaobai/66-test-cc.git 3、生成本机的ssh-key(如果已…