CKA认证模块②-K8S企业运维和落地实战

CKA认证模块②-K8S企业运维和落地实战

Pod高级实战-Pod生命周期-启动钩子,停止钩子

Pod生命周期完整流程介绍

容器钩子; 容器探测; Pod重启策略; Pod的终止过程;

Init容器;

初始化容器最佳实践

初始化容器与主容器区别是?

init容器没有readinessProbe…

[root@k8s-master01 pod-2]# cat init.yaml
apiVersion: v1
kind: Pod
metadata:name: myapp-podlabels:app: myapp
spec:initContainers:- name: init-myserviceimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]- name: init-mydbimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]containers:- name: myapp-containerimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          1s
# 初始化容器创建不出来,主容器就出不来[root@k8s-master01 pod-2]# kubectl delete -f init.yaml 
pod "myapp-pod" deleted
[root@k8s-master01 pod-2]# cat init.yaml 
apiVersion: v1
kind: Pod
metadata:name: myapp-podlabels:app: myapp
spec:initContainers:- name: init-myserviceimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "sleep 2"]- name: init-mydbimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]containers:- name: myapp-containerimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', 'echo The app is running! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          2s
myapp-pod   0/1     Init:1/2   0          4s
myapp-pod   0/1     Init:1/2   0          5s[root@k8s-master01 pod-2]# kubectl delete -f init.yaml 
pod "myapp-pod" deleted
[root@k8s-master01 pod-2]# cat init.yaml 
apiVersion: v1
kind: Pod
metadata:name: myapp-podlabels:app: myapp
spec:initContainers:- name: init-myserviceimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "sleep 2"]- name: init-mydbimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', "sleep 2"]containers:- name: myapp-containerimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ['sh', '-c', 'echo 主容器正常启动! && sleep 3600']
[root@k8s-master01 pod-2]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8s-master01 ~]# kubectl get pods -w
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Pending   0          0s
myapp-pod   0/1     Init:0/2   0          0s
myapp-pod   0/1     Init:0/2   0          1s
myapp-pod   0/1     Init:0/2   0          1s
myapp-pod   0/1     Init:1/2   0          4s
myapp-pod   0/1     Init:1/2   0          5s
myapp-pod   0/1     PodInitializing   0          7s
myapp-pod   1/1     Running           0          8s
# init容器必须全能执行成功,主容器才能运行起来
初始化容器生产应用

主容器运行nginx服务,初始化容器用来给主容器生成index.html文件

[root@k8s-master01 pod-2]# cat init-1.yaml 
apiVersion: v1
kind: Pod
metadata:name: initnginx
spec:initContainers:- name: installimage: docker.io/library/busybox:1.28imagePullPolicy: IfNotPresentcommand:- wget- "-O"- "/work-dir/index.html"- "https://www.baidu.com"volumeMounts:- name: workdirmountPath: /work-dircontainers:- name: nginximage: docker.io/xianchao/nginx:v1imagePullPolicy: IfNotPresentports:- containerPort: 80volumeMounts:- name: workdirmountPath: /usr/share/nginx/htmlvolumes:- name: workdiremptyDir: {}[root@k8s-master01 pod-2]# kubectl apply -f init-1.yaml 
pod/initnginx created
[root@k8s-master01 pod-2]# kubectl get pods -owide
NAME        READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
initnginx   1/1     Running   0          14s   10.244.85.195   k8s-node01   <none>           <none>
[root@k8s-master01 pod-2]# curl 10.244.85.195
...
[root@k8s-master01 pod-2]# kubectl exec -it initnginx -c nginx -- /bin/bash
root@initnginx:/# ls /usr/share/nginx/html/           
index.html
Pod生命周期-容器钩子

postStartpreStop

[root@k8s-master01 pod-2]# kubectl explain pod.spec.containers.lifecycle
# 查看帮助及写法
[root@k8s-master01 pod-2]# kubectl delete -f init-1.yaml 
pod "initnginx" deleted
[root@k8s-master01 pod-2]# cat pre-start.yaml 
apiVersion: v1
kind: Pod
metadata:name: life-demo
spec:containers:- name: lifecycle-demo-containerimage: docker.io/xianchao/nginx:v1imagePullPolicy: IfNotPresentlifecycle:postStart:exec:command: ["/bin/sh", "-c","echo 'lifecycle hookshandler' > /usr/share/nginx/html/test.html"]preStop:exec:command:- "/bin/sh"- "-c"- "nginx -s stop"[root@k8s-master01 pod-2]# kubectl apply -f pre-start.yaml 
pod/life-demo created
[root@k8s-master01 pod-2]# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
life-demo   1/1     Running   0          25s
[root@k8s-master01 pod-2]# kubectl exec -it life-demo -- /bin/bash
root@life-demo:/# cd /usr/share/nginx/html/
root@life-demo:/usr/share/nginx/html# cat test.html 
lifecycle hookshandler
# 测试成功[root@k8s-master01 pod-2]# kubectl delete -f pre-start.yaml 
pod "life-demo" deleted
# 清除环境

总结:

pod在整个生命周期中有非常多的用户行为:

  1. 初始化容器完成初始化

  2. 主容器启动后可以做启动后钩子(postStart)

  3. 主容器结束前可以做结束前钩子(preStop)

  4. 在主容器运行中可以做一些健康检测,如:startupProbe, livenessProbe, readnessProbe

零故障升级之Pod健康检测

启动探测startupProbe

小测试

[root@k8s-master01 ~]# mkdir pod-4
[root@k8s-master01 ~]# cd pod-4
[root@k8s-master01 pod-4]# cat check.yaml
apiVersion: v1
kind: Pod
metadata:name: checknamespace: defaultlabels:app: check
spec:containers:- name: checkimage: busybox:1.28imagePullPolicy: IfNotPresentcommand:- /bin/sh- -c- sleep 10; exit
# 使容器运行10秒后就退出
[root@k8s-master01 pod-4]# kubectl apply -f check.yaml
pod/check created
[root@k8s-master01 pod-2]# kubectl get pods -w
NAME    READY   STATUS    RESTARTS   AGE
check   0/1     Pending   0          0s
check   0/1     Pending   0          0s
check   0/1     ContainerCreating   0          0s
check   0/1     ContainerCreating   0          1s
check   1/1     Running             0          2s
check   0/1     Completed           0          12s
check   1/1     Running             1 (2s ago)   13s
check   0/1     Completed           1 (12s ago)   23s
# 检查pod状态[root@k8s-master01 pod-4]# kubectl delete -f check.yaml 
pod "check" deleted
# 清除环境
提问: k8s提供了三种探针实现容器探测,哪三种? 作用分别是什么?

Pod探针相关属性

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.exec
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-exec.yaml 
apiVersion: v1
kind: Pod
metadata:name: startupprobe
spec:containers:- name: startupimage: xianchao/tomcat-8.5-jre8:v1imagePullPolicy: IfNotPresentports:- containerPort: 8080startupProbe:exec:command:- "/bin/sh"- "-c"- "ps aux | grep tomcat"initialDelaySeconds: 20 #容器启动后多久开始探测periodSeconds: 20 #执行探测的时间间隔timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间successThreshold: 1 #成功多少次才算成功failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-exec.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          15s
startupprobe   0/1     Running             0          20s
startupprobe   1/1     Running             0          20s
# 测试探测时间[root@k8s-master01 pod-4]# kubectl delete -f startup-exec.yaml 
pod "startupprobe" deleted
# 删除环境[root@k8s-master01 pod-4]# cat startup-exec.yaml 
apiVersion: v1
kind: Pod
metadata:name: startupprobe
spec:containers:- name: startupimage: xianchao/tomcat-8.5-jre8:v1imagePullPolicy: IfNotPresentports:- containerPort: 8080startupProbe:exec:command:- "/bin/sh"- "-c"- "aa ps aux | grep tomcat1" # 修改为一条不存在的命令测试initialDelaySeconds: 20 #容器启动后多久开始探测periodSeconds: 20 #执行探测的时间间隔timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间successThreshold: 1 #成功多少次才算成功failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-exec.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          2s
startupprobe   0/1     Running             1 (0s ago)   81s
startupprobe   0/1     Running             2 (1s ago)   2m41s
startupprobe   0/1     Running             3 (1s ago)   4m1s
# 测试探测[root@k8s-master01 pod-4]# kubectl delete -f startup-exec.yaml 
pod "startupprobe" deleted
# 删除环境
提问: 第一次探测失败多久会重启?

根据如上测试回答,为什么是60秒?为什么是80秒

tcpSocket模式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.tcpSocket
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:name: startupprobe
spec:containers:- name: startupimage: xianchao/tomcat-8.5-jre8:v1imagePullPolicy: IfNotPresentports:- containerPort: 8080startupProbe:tcpSocket:port: 8080initialDelaySeconds: 20 #容器启动后多久开始探测periodSeconds: 20 #执行探测的时间间隔timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间successThreshold: 1 #成功多少次才算成功failureThreshold: 3 #失败多少次才算失败
[root@k8s-master01 pod-4]# kubectl apply -f startup-tcpsocket.yaml 
pod/startupprobe created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          1s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          40s
startupprobe   1/1     Running             0          40s
# 测试tcpSocket[root@k8s-master01 pod-4]# kubectl delete -f startup-tcpsocket.yaml 
pod "startupprobe" deleted
# 清除环境

httpGet模式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.startupProbe.httpGet.
# 查看帮助
[root@k8s-master01 pod-4]# cat startup-httpget.yaml 
apiVersion: v1
kind: Pod
metadata:name: startupprobe
spec:containers:- name: startupimage: xianchao/tomcat-8.5-jre8:v1imagePullPolicy: IfNotPresentports:- containerPort: 8080startupProbe:httpGet:path: /port: 8080initialDelaySeconds: 20 #容器启动后多久开始探测periodSeconds: 20 #执行探测的时间间隔timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间successThreshold: 1 #成功多少次才算成功failureThreshold: 3 #失败多少次才算失败[root@k8s-master01 pod-4]# kubectl apply -f startup-httpget.yaml 
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     Pending   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     ContainerCreating   0          0s
startupprobe   0/1     Running             0          1s
startupprobe   0/1     Running             0          41s
startupprobe   1/1     Running             0          41s
# 测试httpGet[root@k8s-master01 pod-4]# kubectl delete -f startup-httpget.yaml 
pod "startupprobe" deleted
# 清除环境

启动探测间隔说明: 不同探针可能有误差,影响不大

存活性探测livenessProbe

exec方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.exec.
# 查看帮助
[root@k8s-master01 pod-4]# cat liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:name: liveness-execlabels:app: liveness
spec:containers:- name: livenessimage: busybox:1.28imagePullPolicy: IfNotPresentargs:                       #创建测试探针探测的文件- /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600livenessProbe:initialDelaySeconds: 10   #延迟检测时间periodSeconds: 5          #检测时间间隔exec:command:- cat- /tmp/healthy
[root@k8s-master01 pod-4]# kubectl apply -f liveness-exec.yaml
pod/liveness-exec created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   0/1     Pending   0          0s
liveness-exec   0/1     Pending   0          0s
liveness-exec   0/1     ContainerCreating   0          0s
liveness-exec   0/1     ContainerCreating   0          1s
liveness-exec   1/1     Running             0          2s
liveness-exec   1/1     Running             1 (1s ago)   76s
liveness-exec   1/1     Running             2 (0s ago)   2m31s
# 测试exec[root@k8s-master01 pod-4]# kubectl delete -f liveness-exec.yaml
pod "liveness-exec" deleted
# 清除环境

httpGet方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.httpGet.
# 查看帮助
[root@k8s-master01 pod-4]# ctr -n k8s.io images import springboot.tar.gz 
[root@k8s-node01 images]# ctr -n k8s.io images import springboot.tar.gz 
[root@k8s-node02 images]# ctr -n k8s.io images import springboot.tar.gz
# 节点导入镜像
[root@k8s-master01 pod-4]# cat liveness-http.yaml 
apiVersion: v1
kind: Pod
metadata:name: liveness-httplabels:test: liveness
spec:containers:- name: livenessimage: mydlqclub/springboot-helloworld:0.0.1imagePullPolicy: IfNotPresentlivenessProbe:initialDelaySeconds: 20   #延迟加载时间periodSeconds: 5          #重试时间间隔timeoutSeconds: 10        #超时时间设置httpGet:scheme: HTTPport: 8081path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f liveness-http.yaml 
pod/liveness-http created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME            READY   STATUS    RESTARTS   AGE
liveness-http   0/1     Pending   0          0s
liveness-http   0/1     Pending   0          0s
liveness-http   0/1     ContainerCreating   0          0s
liveness-http   0/1     ContainerCreating   0          0s
liveness-http   1/1     Running             0          1s
[root@k8s-master01 pod-4]# kubectl get pods -owide
NAME            READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
liveness-http   1/1     Running   0          5m24s   10.244.58.209   k8s-node02   <none>           <none>
[root@k8s-master01 pod-4]# curl 10.244.58.209:8081/actuator/health
{"status":"UP"}
# 测试httpGet[root@k8s-master01 pod-4]# kubectl delete -f liveness-http.yaml 
pod "liveness-http" deleted
# 清除环境

tcpSocket方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.livenessProbe.tcpSocket.
# 查看帮助
[root@k8s-master01 pod-4]# cat liveness-tcp.yaml 
apiVersion: v1
kind: Pod
metadata:name: liveness-tcplabels:app: liveness
spec:containers:- name: livenessimage: docker.io/xianchao/nginx:v1imagePullPolicy: IfNotPresentlivenessProbe:initialDelaySeconds: 15periodSeconds: 20tcpSocket:port: 80
[root@k8s-master01 pod-4]# kubectl apply -f liveness-tcp.yaml 
pod/liveness-tcp created
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME           READY   STATUS    RESTARTS   AGE
liveness-tcp   0/1     Pending   0          0s
liveness-tcp   0/1     Pending   0          0s
liveness-tcp   0/1     ContainerCreating   0          0s
liveness-tcp   0/1     ContainerCreating   0          0s
liveness-tcp   1/1     Running             0          2s
# 测试tcpSocket[root@k8s-master01 pod-4]# kubectl delete -f liveness-tcp.yaml 
pod "liveness-tcp" deleted
# 清除环境
就绪性探测readinessProbe

exec方式

[root@k8s-master01 pod-4]# kubectl explain pod.spec.containers.readinessProbe.
# 查看帮助
[root@k8s-master01 pod-4]# cat readiness-exec.yaml 
apiVersion: v1
kind: Service
metadata:name: springbootlabels:app: springboot
spec:type: NodePortports:- name: serverport: 8080targetPort: 8080nodePort: 31180- name: managementport: 8081targetPort: 8081nodePort: 31181selector:app: springboot
---
apiVersion: v1
kind: Pod
metadata:name: springbootlabels:app: springboot
spec:containers:- name: springbootimage: mydlqclub/springboot-helloworld:0.0.1imagePullPolicy: IfNotPresentports:- name: servercontainerPort: 8080- name: managementcontainerPort: 8081readinessProbe:initialDelaySeconds: 20   periodSeconds: 5          timeoutSeconds: 10   httpGet:scheme: HTTPport: 8081path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f readiness-exec.yaml 
service/springboot created
pod/springboot created
[root@k8s-master01 pod-4]# kubectl get pods -l app=springboot -w
NAME         READY   STATUS    RESTARTS   AGE
springboot   0/1     Pending   0          1s
springboot   0/1     Pending   0          3s
springboot   0/1     ContainerCreating   0          3s
springboot   0/1     ContainerCreating   0          6s
springboot   0/1     Running             0          9s
springboot   1/1     Running             0          49s
[root@k8s-master01 pod-4]# kubectl get svc -w
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   4d2h
springboot   NodePort    10.106.29.40   <none>        8080:31180/TCP,8081:31181/TCP   0s
# 只有pod就绪了,才能被service关联到,所以就绪探测很重要

注意: 存活探测和就绪探测不存在先后,而是平行

启动,就绪,存活探测混合使用
[root@k8s-master01 pod-4]# cat start-read-live.yaml 
apiVersion: v1
kind: Service
metadata:name: springboot-livelabels:app: springboot
spec:type: NodePortports:- name: serverport: 8080targetPort: 8080nodePort: 31180- name: managementport: 8081targetPort: 8081nodePort: 31181selector:app: springboot
---
apiVersion: v1
kind: Pod
metadata:name: springboot-livelabels:app: springboot
spec:containers:- name: springbootimage: mydlqclub/springboot-helloworld:0.0.1imagePullPolicy: IfNotPresentports:- name: servercontainerPort: 8080- name: managementcontainerPort: 8081readinessProbe:initialDelaySeconds: 20   periodSeconds: 5          timeoutSeconds: 10   httpGet:scheme: HTTPport: 8081path: /actuator/healthlivenessProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet:scheme: HTTPport: 8081path: /actuator/healthstartupProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet:scheme: HTTPport: 8081path: /actuator/health
[root@k8s-master01 pod-4]# kubectl apply -f start-read-live.yaml 
service/springboot-live created
pod/springboot-live created[root@k8s-master01 pod-4]# kubectl exec -it springboot-live -- kill 1
# 等容器起来再执行
[root@k8s-master01 pod-4]# kubectl get pods -w
NAME              READY   STATUS    RESTARTS   AGE
springboot-live   0/1     Pending   0          0s
springboot-live   0/1     Pending   0          0s
springboot-live   0/1     ContainerCreating   0          0s
springboot-live   0/1     ContainerCreating   0          1s
springboot-live   0/1     Running             0          4s
springboot-live   0/1     Running             0          26s
# 注意这里为什么会有两个,因为我们设置了存活和就绪探测
springboot-live   1/1     Running             0          26s
springboot-live   0/1     Error               0          61s
springboot-live   0/1     Running             1 (3s ago)   63s
springboot-live   0/1     Running             1 (26s ago)   86s
# 同上
springboot-live   1/1     Running             1 (26s ago)   86s[root@k8s-master01 pod-4]# kubectl delete -f start-read-live.yaml 
service "springboot-live" deleted
pod "springboot-live" deleted
# 清除环境

三种探测大致可以理解为:

startupProbe用于pod启动探测

livenessProbe用于容器启动探测

readinessProbe用于容器内服务状态探测

K8S控制器ReplicaSet入门到企业实战应用

ReplicaSet资源-YAML文件编写技巧
[root@k8s-master01 rs]# kubectl explain replicaset.
# 查看帮助ctr -n k8s.io images import frontend.tar.gz
ctr -n k8s.io images import myapp-blue-v1.tar.gz
ctr -n k8s.io images import myapp-blue-v2.tar.gz
ctr -n k8s.io images import myapp-v2.tar.gz
# 导入镜像[root@k8s-master01 rs]# cat replicaset.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:name: frontendnamespace: defaultlabels:app: guestbooktier: frontend
spec:replicas: 3selector:matchLabels:tier1: frontend1template:metadata:labels:tier1: frontend1spec:containers:- name: php-redisimage: docker.io/yecc/gcr.io-google_samples-gb-frontend:v3imagePullPolicy: IfNotPresentports:- containerPort: 80startupProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet: scheme: HTTPport: 80path: /livenessProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet: scheme: HTTPport: 80path: /readinessProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet: scheme: HTTPport: 80path: /
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@k8s-master01 rs]# kubectl get pod -w
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   0/1     Pending   0          0s
frontend-2h7l7   0/1     Pending   0          0s
frontend-2xmw6   0/1     Pending   0          0s
frontend-6cb5q   0/1     Pending   0          0s
frontend-2xmw6   0/1     Pending   0          0s
frontend-6cb5q   0/1     Pending   0          0s
frontend-2xmw6   0/1     ContainerCreating   0          0s
frontend-2h7l7   0/1     ContainerCreating   0          0s
frontend-6cb5q   0/1     ContainerCreating   0          0s
frontend-2h7l7   0/1     ContainerCreating   0          1s
frontend-2xmw6   0/1     ContainerCreating   0          1s
frontend-6cb5q   0/1     ContainerCreating   0          1s
frontend-2xmw6   0/1     Running             0          2s
frontend-6cb5q   0/1     Running             0          2s
frontend-2h7l7   0/1     Running             0          2s
frontend-2h7l7   0/1     Running             0          21s
frontend-2h7l7   1/1     Running             0          21s
frontend-6cb5q   0/1     Running             0          21s
frontend-6cb5q   1/1     Running             0          21s
frontend-2xmw6   0/1     Running             0          22s
frontend-2xmw6   1/1     Running             0          22s
[root@k8s-master01 rs]# kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         0       10s
# 创建ReplicaSet[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   1/1     Running   0          57s
frontend-2xmw6   1/1     Running   0          57s
frontend-6cb5q   1/1     Running   0          57s
[root@k8s-master01 rs]# kubectl delete pod frontend-2h7l7
pod "frontend-2h7l7" deleted
[root@k8s-master01 rs]# kubectl get pod -w
NAME             READY   STATUS    RESTARTS   AGE
frontend-2h7l7   1/1     Running   0          75s
frontend-2xmw6   1/1     Running   0          75s
frontend-6cb5q   1/1     Running   0          75s
frontend-2h7l7   1/1     Terminating   0          79s
frontend-g6prf   0/1     Pending       0          1s
frontend-g6prf   0/1     Pending       0          1s
frontend-g6prf   0/1     ContainerCreating   0          1s
frontend-2h7l7   1/1     Terminating         0          80s
frontend-g6prf   0/1     ContainerCreating   0          2s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-2h7l7   0/1     Terminating         0          81s
frontend-g6prf   0/1     Running             0          3s
frontend-g6prf   0/1     Running             0          27s
frontend-g6prf   1/1     Running             0          27s
# 测试删除ReplicaSet管理的pod,如果少了replicaSet会重新创建一个pod
ReplicaSet实现pod扩缩容和更新
[root@k8s-master01 rs]# cat replicaset.yaml |grep replicas:replicas: 4
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2xmw6   1/1     Running   0          31m
frontend-69p98   1/1     Running   0          52s
frontend-6cb5q   1/1     Running   0          31m
frontend-g6prf   1/1     Running   0          30m
# 直接修改yaml文件然后应用实现pod扩容[root@k8s-master01 rs]# cat replicaset.yaml |grep replicas:replicas: 2
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-2xmw6   1/1     Running   0          33m
frontend-g6prf   1/1     Running   0          31m
# 实现pod缩容[root@k8s-master01 rs]# cat replicaset.yaml |grep image:image: docker.io/ikubernetes/myapp:v2
[root@k8s-master01 rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend configured
[root@k8s-master01 rs]# kubectl get pods -owide
NAME             READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
frontend-2xmw6   1/1     Running   0          35m   10.244.85.205   k8s-node01   <none>           <none>
frontend-g6prf   1/1     Running   0          33m   10.244.85.206   k8s-node01   <none>           <none>
[root@k8s-master01 rs]# curl 10.244.85.205 |head -n3% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     100   921  100   921    0     0   527k      0 --:--:-- --:--:-- --:--:--  899k
<html ng-app="redis"><head><title>Guestbook</title>
# ReplicaSet没有更新容器使用镜像,仍然是之前的内容
[root@k8s-master01 rs]# kubectl delete pod frontend-2xmw6
pod "frontend-2xmw6" deleted
[root@k8s-master01 rs]# kubectl delete pod frontend-g6prf
pod "frontend-g6prf" deleted
[root@k8s-master01 rs]# kubectl get pods -owide
NAME             READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
frontend-8cdmn   1/1     Running   0          2m13s   10.244.58.221   k8s-node02   <none>           <none>
frontend-mk6ln   0/1     Running   0          25s     10.244.85.207   k8s-node01   <none>           <none>
[root@k8s-master01 rs]# curl 10.244.58.221
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# ReplicaSet无法自动完成更新,必须手动删除pod[root@k8s-master01 rs]# kubectl delete -f replicaset.yaml 
replicaset.apps "frontend" deleted
# 清除环境

总结:

生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs1,再创建一个rs2(控制器),通过修改service标签,修改service可以匹配到rs2的控制器,这样才是蓝绿发布,这个也需要我们精心的部署规划,我们有一个控制器就是建立在rs之上完成的,叫做Deployment

K8S控制器Deployment入门到企业实战应用

Deployment资源基本介绍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意: rollingUpdate更新策略计算方式
[root@k8s-master01 ~]# kubectl explain deploy.spec.strategy.rollingUpdate.
# 查看帮助

最多可用小数直接进一位

最多不可用小数直接舍去保留整数

replicas: 5

​ maxSurge: 25% 5*25%=1.25 -> 5+2=7

​ maxUnanvilable: 25% 5*25%=1.25 -> 5-1=4

Deployment资源-YAML文件编写技巧
[root@k8s-master01 ~]# mkdir deployment
[root@k8s-master01 ~]# cd deployment/
[root@k8s-master01 deployment]# kubectl explain deploy.
# 查看帮助ctr -n k8s.io images import myapp-blue-v1.tar.gz 
ctr -n k8s.io images import myapp-blue-v2.tar.gz
# 导入镜像[root@k8s-master01 deployment]# cat deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-v1namespace: default
spec:replicas: 2selector:matchLabels:app: myappversion: v1template:metadata:labels:app: myappversion: v1spec:containers:- name: myappimage: janakiramm/myapp:v1imagePullPolicy: IfNotPresentports:- containerPort: 80startupProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet:port: 80path: /scheme: HTTPlivenessProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet:port: 80path: /scheme: HTTPreadinessProbe:initialDelaySeconds: 20periodSeconds: 5timeoutSeconds: 10httpGet:port: 80path: /scheme: HTTP
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 created
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          77s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          77s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   2         2         2       79s
[root@k8s-master01 deployment]# kubectl get deployment
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           86s
# 创建deployment
Deployment实现pod扩缩容
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:replicas: 3
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-b64k7   1/1     Running   0          32s
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          3m3s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          3m3s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       3m9s
[root@k8s-master01 deployment]# kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   3/3     3            3           3m11s
# 通过修改yaml文件中的replicas实现pod扩容[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:replicas: 2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          4m15s
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          4m15s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   2         2         2       4m17s
[root@k8s-master01 deployment]# kubectl get deployment
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           4m20s
# 实现pod缩容,会随机删除pod
Deployment实现Pod滚动更新
[root@k8s-master01 deployment]# kubectl explain deploy.spec.strategy.
# 查看帮助
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep replicas:replicas: 3
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
# 先将pod副本数调为3并应用[root@k8s-master01 deployment]# kubectl describe deployments.apps myapp-v1 |grep -i strategy
StrategyType:           RollingUpdate
RollingUpdateStrategy:  25% max unavailable, 25% max surge
# 可以看到默认策略是滚动更新
# 默认最多不可用是25%,最多可用也为25%

replicas: 3
maxSurge: 25% -> 3+1=4
maxUnavailabel: 25% -> 3-0=3

[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:image: janakiramm/myapp:v2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
# 修改使用镜像使滚动更新
[root@k8s-master01 deployment]# kubectl get pods -w
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-bn79v   1/1     Running   0          29m
myapp-v1-58bdffcdd7-cqz99   1/1     Running   0          29m
myapp-v1-58bdffcdd7-vxbjk   1/1     Running   0          5m4s
####################
myapp-v1-744bfb8886-8xrzt   0/1     Pending   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     Pending   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     ContainerCreating   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     ContainerCreating   0          0s
myapp-v1-744bfb8886-8xrzt   0/1     Running             0          1s
myapp-v1-744bfb8886-8xrzt   0/1     Running             0          25s
myapp-v1-744bfb8886-8xrzt   1/1     Running             0          25s
myapp-v1-58bdffcdd7-vxbjk   1/1     Terminating         0          6m4s
myapp-v1-744bfb8886-92vvt   0/1     Pending             0          0s
myapp-v1-744bfb8886-92vvt   0/1     Pending             0          0s
myapp-v1-744bfb8886-92vvt   0/1     ContainerCreating   0          0s
myapp-v1-58bdffcdd7-vxbjk   1/1     Terminating         0          6m5s
...
[root@k8s-master01 deployment]# kubectl get rs -w
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       29m
###################
myapp-v1-744bfb8886   1         0         0       0s
myapp-v1-744bfb8886   1         0         0       0s
myapp-v1-744bfb8886   1         1         0       0s
myapp-v1-744bfb8886   1         1         1       25s
myapp-v1-58bdffcdd7   2         3         3       30m
...
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   0         0         0       31m
myapp-v1-744bfb8886   3         3         3       83s
# 滚动更新完成
Deployment回滚
[root@k8s-master01 deployment]# kubectl rollout history deployment myapp-v1 
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none># 查看deployment滚动更新历史
[root@k8s-master01 deployment]# kubectl rollout undo deployment/myapp-v1 --to-revision=1
deployment.apps/myapp-v1 rolled back
[root@k8s-master01 deployment]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-58bdffcdd7-2tgr2   1/1     Running   0          2m2s
myapp-v1-58bdffcdd7-bk6w7   1/1     Running   0          101s
myapp-v1-58bdffcdd7-lrjhp   1/1     Running   0          81s
[root@k8s-master01 deployment]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-58bdffcdd7   3         3         3       35m
myapp-v1-744bfb8886   0         0         0       5m57s
# 实现回滚
自定义Deployment更新策略
[root@k8s-master01 deployment]# kubectl explain deploy.spec.strategy.
# 查看帮助
[root@k8s-master01 deployment]# cat deploy-demo.yaml |head -n15
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-v1namespace: default
spec:strategy: rollingUpdate:maxSurge: 1maxUnavailable: 1replicas: 3selector:matchLabels:app: myappversion: v1
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:image: janakiramm/myapp:v2
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods -w
...
# 测试rollingUpdate

当前pod数量为3,限定后更新过程中pod可用数量为2-4.

测试Recreate

生产环境一定别用,因为全部重建需要时间,生产业务是不能down掉的

[root@k8s-master01 deployment]# cat deploy-demo.yaml |head -n15
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-v1namespace: default
spec:strategy: type: Recreatereplicas: 3selector:matchLabels:app: myappversion: v1template:metadata:
[root@k8s-master01 deployment]# cat deploy-demo.yaml |grep image:image: janakiramm/myapp:v1
[root@k8s-master01 deployment]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 configured
[root@k8s-master01 deployment]# kubectl get pods -w
...[root@k8s-master01 deployment]# kubectl delete -f deploy-demo.yaml 
deployment.apps "myapp-v1" deleted
# 清除环境
蓝绿部署基本介绍

蓝绿部署中,一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的、正在运行的系统,只是系统版本和对外服务情况不同。(蓝绿都可代表新旧系统,理解意思即可,不必在乎颜色)

开发新版本,要用新版本替换线上的旧版本,在线上的系统之外,搭建了一个使用新版本代码的全新系统。 这时候,一共有两套系统在运行,正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。

优点:

1、更新过程无需停机,风险较少

2、回滚方便,只需要更改路由或者切换DNS服务器,效率较高

缺点:

1、成本较高,需要部署两套环境。如果新版本中基础服务出现问题,会瞬间影响全网用户;如果新版本有问题也会影响全网用户。

2、需要部署两套机器,费用开销大

3、在非隔离的机器(Docker、VM)上操作时,可能会导致蓝绿环境被摧毁风险

4、负载均衡器/反向代理/路由/DNS处理不当,将导致流量没有切换过来情况出现

基于k8s实现蓝绿部署

Kubernetes不支持内置的蓝绿部署.目前最好的方式市创建新的deployment,然后更新应用程序的service以指向新的deployment部署的应用

ctr -n k8s.io images import myapp-lan.tar.gz
ctr -n k8s.io images import myapp-lv.tar.gz
# 节点导入镜像[root@k8s-master01 deployment]# kubectl create ns blue-green
namespace/blue-green created
[root@k8s-master01 deployment]# cat lan.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-v1namespace: blue-green
spec:replicas: 3selector:matchLabels:app: myappversion: v1template:metadata:labels:app: myappversion: v1spec:containers:- name: myappimage: janakiramm/myapp:v1imagePullPolicy: IfNotPresentports:- containerPort: 80[root@k8s-master01 deployment]# kubectl apply -f lan.yaml 
deployment.apps/myapp-v1 created
# 部署正在提供服务的系统
[root@k8s-master01 deployment]# cat service_lanlv.yaml 
apiVersion: v1
kind: Service
metadata:name: myapp-lan-lvnamespace: blue-greenlabels:app: myapp
spec:type: NodePortports:- port: 80nodePort: 30062name: httpselector:app: myappversion: v1[root@k8s-master01 deployment]# kubectl apply -f service_lanlv.yaml 
service/myapp-lan-lv created
[root@k8s-master01 deployment]# kubectl describe svc myapp-lan-lv -n blue-green |grep -i endpoints:
Endpoints:                10.244.58.236:80,10.244.58.237:80,10.244.85.217:80
# 编写service的yaml文件对外提供服务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网页访问正常

[root@k8s-master01 deployment]# cat lv.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp-v2namespace: blue-green
spec:replicas: 3selector:matchLabels:app: myappversion: v2template:metadata:labels:app: myappversion: v2spec:containers:- name: myappimage: janakiramm/myapp:v2imagePullPolicy: IfNotPresentports:- containerPort: 80[root@k8s-master01 deployment]# kubectl apply -f lv.yaml 
deployment.apps/myapp-v2 created
# 部署第二套系统,也就是准备发布的新系统
[root@k8s-master01 deployment]# kubectl get pods -n blue-green
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          3m11s
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          3m11s
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          3m11s
myapp-v2-5779dc88f-55566    1/1     Running   0          16s
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          16s
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          16s
[root@k8s-master01 deployment]# kubectl get pods --show-labels -n blue-green
NAME                        READY   STATUS    RESTARTS   AGE     LABELS
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          5m25s   app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v2-5779dc88f-55566    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          2m30s   app=myapp,pod-template-hash=5779dc88f,version=v2
[root@k8s-master01 deployment]# cat service_lanlv.yaml 
apiVersion: v1
kind: Service
metadata:name: myapp-lan-lvnamespace: blue-greenlabels:app: myapp
spec:type: NodePortports:- port: 80nodePort: 30062name: httpselector:app: myappversion: v2
# 只需修改service的yaml文件的匹配标签即可,这里我们修改了version为v2
[root@k8s-master01 deployment]# kubectl apply -f service_lanlv.yaml 
service/myapp-lan-lv configured
[root@k8s-master01 deployment]# kubectl describe svc myapp-lan-lv -n blue-green |grep -i endpoints:
Endpoints:                10.244.58.238:80,10.244.85.218:80,10.244.85.219:80
[root@k8s-master01 deployment]# kubectl get pods --show-labels -n blue-green -owide
NAME                        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES   LABELS
myapp-v1-7b55fffbb5-2vpt7   1/1     Running   0          5m40s   10.244.58.237   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-gfnnt   1/1     Running   0          5m40s   10.244.85.217   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v1-7b55fffbb5-xpk2f   1/1     Running   0          5m40s   10.244.58.236   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=7b55fffbb5,version=v1
myapp-v2-5779dc88f-55566    1/1     Running   0          2m45s   10.244.58.238   k8s-node02   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-cjnrp    1/1     Running   0          2m45s   10.244.85.218   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
myapp-v2-5779dc88f-sz2m9    1/1     Running   0          2m45s   10.244.85.219   k8s-node01   <none>           <none>            app=myapp,pod-template-hash=5779dc88f,version=v2
# 已经切换为新的系统[root@k8s-master01 deployment]# kubectl delete -f lv.yaml 
deployment.apps "myapp-v2" deleted
[root@k8s-master01 deployment]# kubectl delete -f lan.yaml 
deployment.apps "myapp-v1" deleted
[root@k8s-master01 deployment]# kubectl delete -f service_lanlv.yaml 
service "myapp-lan-lv" deleted
# 清除环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网页访问正常

基于k8s实现金丝雀发布
金丝雀发布简介

**金丝雀发布的由来:**17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;当瓦斯含量超过一定限度时,虽然人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为瓦斯检测指标,以便在危险状况下紧急撤离。

**金丝雀发布(又称灰度发布、灰度更新):**金丝雀发布一般先发1台,或者一个小比例,例如2%的服务器,主要做流量验证用,也称为金丝雀 (Canary) 测试 (国内常称灰度测试)。

简单的金丝雀测试一般通过手工测试验证,复杂的金丝雀测试需要比较完善的监控基础设施配合,通过监控指标反馈,观察金丝雀的健康状况,作为后续发布或回退的依据。 如果金丝测试通过,则把剩余的V1版本全部升级为V2版本。如果金丝雀测试失败,则直接回退金丝雀,发布失败。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[root@k8s-master01 deployment]# kubectl apply -f lan.yaml 
deployment.apps/myapp-v1 created
[root@k8s-master01 deployment]# kubectl set image deployment myapp-v1 myapp=docker.io/xianchao/nginx:v1  -n blue-green && kubectl rollout pause deployment myapp-v1 -n blue-green
deployment.apps/myapp-v1 image updated
deployment.apps/myapp-v1 paused
[root@k8s-master01 deployment]# kubectl get pods -n blue-green -w
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-7b55fffbb5-46cqg   1/1     Running   0          5s
myapp-v1-7b55fffbb5-8mh8k   1/1     Running   0          5s
myapp-v1-7b55fffbb5-fnb8c   1/1     Running   0          5s
#######################myapp-v1-644d75999-2dlks    0/1     Pending   0          0s
myapp-v1-644d75999-2dlks    0/1     Pending   0          0s
myapp-v1-644d75999-2dlks    0/1     ContainerCreating   0          0s
myapp-v1-644d75999-2dlks    0/1     ContainerCreating   0          0s
myapp-v1-644d75999-2dlks    1/1     Running             0          1s
# 新起一个pod做金丝雀发布,其余三个pod为暂停状态,也就是暂不更新,还是跑着旧业务[root@k8s-master01 deployment]# kubectl rollout resume deployment myapp-v1 -n blue-green
deployment.apps/myapp-v1 resumed
[root@k8s-master01 deployment]# kubectl get pods -n blue-green -w
...
[root@k8s-master01 deployment]# kubectl get rs -n blue-green
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-644d75999    3         3         3       2m25s
myapp-v1-7b55fffbb5   0         0         0       2m32s
# 如果没有问题,就全部更新,解除暂停状态

K8S四层代理Service入门到企业实战

Service四层代理基本介绍
提问: 为什么要有Service?

Service概述

较新的版本使用的是coredns),service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要再部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。

每个K8s节点上都有一个组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式。

Service工作原理

k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)

K8S集群中有三类IP地址

  1. Node Network(节点网络)
  2. Pod Network(Pod网络)
  3. Cluster Network(集群地址,也称为service network)
Service代理-ClusterIP类型
[root@k8s-master01 ~]# kubectl explain service.spec.
# 查看帮助[root@k8s-node01 images]# ctr -n k8s.io images import nginx.tar.gz
[root@k8s-node02 images]# ctr -n k8s.io images import nginx.tar.gz
# 工作节点导入镜像[root@k8s-master01 ~]# mkdir service
[root@k8s-master01 ~]# cd service/
[root@k8s-master01 service]# cat pod_test.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: my-nginx
spec:selector:matchLabels:run: my-nginxreplicas: 2template:metadata:labels:run: my-nginxspec:containers:- name: my-nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80  #pod中的容器需要暴露的端口startupProbe:periodSeconds: 5initialDelaySeconds: 60# 初始检测时间设置长一点,方便测试timeoutSeconds: 10httpGet:scheme: HTTPport: 80path: /livenessProbe:periodSeconds: 5initialDelaySeconds: 60timeoutSeconds: 10httpGet:scheme: HTTPport: 80path: /readinessProbe:periodSeconds: 5initialDelaySeconds: 60timeoutSeconds: 10httpGet:scheme: HTTPport: 80path: /
[root@k8s-master01 service]# kubectl apply -f pod_test.yaml 
deployment.apps/my-nginx created
# 创建deployment生成pod
[root@k8s-master01 service]# kubectl get pods --show-labels
NAME                        READY   STATUS    RESTARTS   AGE   LABELS
my-nginx-7468bcb55b-b7vnl   0/1     Running   0          23s   pod-template-hash=7468bcb55b,run=my-nginx
my-nginx-7468bcb55b-zzpw2   0/1     Running   0          23s   pod-template-hash=7468bcb55b,run=my-nginx
# 查看pod标签
[root@k8s-master01 service]# cat service_test.yaml 
apiVersion: v1
kind: Service
metadata:name: my-nginxlabels:run: my-nginx
spec:type: ClusterIPports:- port: 80# service的端口,暴露给k8s集群内部服务访问protocol: TCPtargetPort: 80# pod容器中定义的端口selector:run: my-nginx# 选择拥有run=my-nginx标签的pod
[root@k8s-master01 service]# kubectl apply -f service_test.yaml 
service/my-nginx created
# 创建service
[root@k8s-master01 service]# kubectl get svc -l run=my-nginx
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.98.163.90   <none>        80/TCP    50s
[root@k8s-master01 service]# curl 10.98.163.90
...
# 测试service,ClusterIP类型只有集群内部可访问
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.58.246:80,10.244.85.224:80[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-b7vnl   1/1     Running   0          5m53s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          5m53s
[root@k8s-master01 service]# kubectl delete pod my-nginx-7468bcb55b-b7vnl 
pod "my-nginx-7468bcb55b-b7vnl" deleted
[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-8vz67   0/1     Running   0          49s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          6m46s
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.85.224:80
# 在pod的服务没有就绪前不会代理
[root@k8s-master01 service]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-7468bcb55b-8vz67   1/1     Running   0          63s
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          7m
[root@k8s-master01 service]# kubectl get pods -owide
NAME                        READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
my-nginx-7468bcb55b-8vz67   1/1     Running   0          74s     10.244.58.247   k8s-node02   <none>           <none>
my-nginx-7468bcb55b-zzpw2   1/1     Running   0          7m11s   10.244.85.224   k8s-node01   <none>           <none>
[root@k8s-master01 service]# kubectl describe svc my-nginx |grep -i endpoints:
Endpoints:         10.244.58.247:80,10.244.85.224:80
# 所以就绪探测很重要,不然可能造成service代理了但是服务没起来的情况[root@k8s-master01 service]# kubectl delete -f pod_test.yaml 
deployment.apps "my-nginx" deleted
[root@k8s-master01 service]# kubectl delete -f service_test.yaml 
service "my-nginx" deleted
# 清除环境

以这个service为例,它的全称为my-nginx.default.svc.cluster.local

也就是: 服务名.命名空间.域名后缀

这个全称只能在关联的pod里访问,集群节点也是无法访问的

Service代理-NodePort类型
[root@k8s-master01 service]# cat pod_nodeport.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: my-nginx-nodeport
spec:selector:matchLabels:run: my-nginx-nodeportreplicas: 2template:metadata:labels:run: my-nginx-nodeportspec:containers:- name: my-nginx-nodeport-containerimage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80[root@k8s-master01 service]# kubectl apply -f pod_nodeport.yaml 
deployment.apps/my-nginx-nodeport created
[root@k8s-master01 service]# cat service_nodeport.yaml 
apiVersion: v1
kind: Service
metadata:name: my-nginx-nodeportlabels:run: my-nginx-nodeport
spec:type: NodePortports:- port: 80protocol: TCPtargetPort: 80nodePort: 30380selector:run: my-nginx-nodeport[root@k8s-master01 service]# kubectl apply -f service_nodeport.yaml 
service/my-nginx-nodeport created
[root@k8s-master01 service]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
my-nginx-nodeport-85c4df8944-g8s85   1/1     Running   0          19s
my-nginx-nodeport-85c4df8944-k6b9f   1/1     Running   0          19s
[root@k8s-master01 service]# kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP        8d
my-nginx-nodeport   NodePort    10.110.139.100   <none>        80:30380/TCP   13s
# 创建pod和NodePort类型的service[root@k8s-master01 service]# ss -lntup |grep 30380
# 查端口是查不到的
[root@k8s-master01 service]# ipvsadm -Ln |head -n10
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30380 rr-> 10.244.58.249:80             Masq    1      0          0         -> 10.244.85.227:80             Masq    1      0          0         
TCP  192.168.1.181:30380 rr-> 10.244.58.249:80             Masq    1      1          0         -> 10.244.85.227:80             Masq    1      0          1 
# 查询防火墙规则[root@k8s-master01 service]# kubectl delete -f pod_nodeport.yaml 
deployment.apps "my-nginx-nodeport" deleted
[root@k8s-master01 service]# kubectl delete -f service_nodeport.yaml 
service "my-nginx-nodeport" deleted
# 清除环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据转发流程:

客户端请求http://192.168.1.181:30380->docker0虚拟网卡:172.17.0.1:30380->10.244.121.36:80,10.244.102.86:80

Service代理-ExternalName类型

应用场景:跨名称空间访问

需求:default名称空间下的client 服务想要访问nginx-ns名称空间下的nginx-svc服务

[root@k8s-node01 images]# ctr -n k8s.io images import busybox.tar.gz
[root@k8s-node02 images]# ctr -n k8s.io images import busybox.tar.gz
# 工作节点导入镜像[root@k8s-master01 service]# kubectl create ns nginx-ns
namespace/nginx-ns created
[root@k8s-master01 service]# cat server_nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxnamespace: nginx-ns
spec: replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresent[root@k8s-master01 service]# kubectl apply -f server_nginx.yaml 
deployment.apps/nginx created
# 部署nginx-ns名称空间下的pod跑nginx服务
[root@k8s-master01 service]# cat nginx_svc.yaml 
apiVersion: v1
kind: Service
metadata:name: nginx-svcnamespace: nginx-ns
spec:selector:app: nginxports:- name: httpprotocol: TCPport: 80targetPort: 80
[root@k8s-master01 service]# kubectl apply -f nginx_svc.yaml 
service/nginx-svc created
# 部署nginx的service,类型为ClusterIP
[root@k8s-master01 service]# cat client.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: client
spec: replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboximagePullPolicy: IfNotPresentcommand: ["/bin/sh","-c","sleep 36000"][root@k8s-master01 service]# kubectl apply -f client.yaml 
deployment.apps/client created
# 部署默认名称空间下的client
[root@k8s-master01 service]# cat client_svc.yaml 
apiVersion: v1
kind: Service
metadata:name: client-svc
spec:type: ExternalNameexternalName: nginx-svc.nginx-ns.svc.cluster.localports:- name: httpport: 80targetPort: 80[root@k8s-master01 service]# kubectl apply -f client_svc.yaml 
service/client-svc created
# 创建ExternalName类型的service
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP                            PORT(S)   AGE
client-svc   ExternalName   <none>       nginx-svc.nginx-ns.svc.cluster.local   80/TCP    89s
kubernetes   ClusterIP      10.96.0.1    <none>                                 443/TCP   8d
[root@k8s-master01 service]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
client-798446484b-wrz86   1/1     Running   0          2m6s
[root@k8s-master01 service]# kubectl exec -it client-798446484b-wrz86 -- /bin/sh
/ # wget -q -O - client-svc
...
/ # wget -q -O - client-svc.default.svc.cluster.local
...
/ # wget -q -O - nginx-svc.nginx-ns.svc.cluster.local
...
# 上面三个请求结果一样[root@k8s-master01 service]# kubectl delete -f client_svc.yaml 
service "client-svc" deleted
[root@k8s-master01 service]# kubectl delete -f client.yaml 
deployment.apps "client" deleted
[root@k8s-master01 service]# kubectl delete -f server_nginx.yaml 
deployment.apps "nginx" deleted
# 清除环境
Service代理-自定义Endpoints资源

k8s最佳实践:映射外部服务案例分享

场景1:k8s集群引用外部的mysql数据库

[root@k8s-node02 ~]# yum -y install mariadb-server
[root@k8s-node02 ~]# systemctl enable --now mariadb
[root@k8s-node02 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.68-MariaDB MariaDB ServerCopyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.MariaDB [(none)]> quit
Bye
# 在node2安装节点外部服务mariadb-server做测试[root@k8s-master01 service]# cat mysql_service.yaml
apiVersion: v1
kind: Service
metadata:name: mysqlnamespace: default
spec:type: ClusterIPports:- port: 3306
[root@k8s-master01 service]# kubectl apply -f mysql_service.yaml 
service/mysql created
# 创建ClusterIP类型的service
[root@k8s-master01 service]# kubectl get svc |grep mysql
mysql        ClusterIP   10.106.232.15   <none>        3306/TCP   43s
[root@k8s-master01 service]# kubectl describe svc mysql |grep -i endpoints:
Endpoints:         <none>
# 可以看到Endpoints: 字段是空的,所以我们要去添加一个[root@k8s-master01 service]# kubectl explain endpoints.
# 查看帮助
[root@k8s-master01 service]# cat mysql_endpoints.yaml
apiVersion: v1
kind: Endpoints
metadata:name: mysql# 注意这里要与service名字相同,不然找不到namespace: default
subsets:
- addresses: - ip: 192.168.1.192ports:- port: 3306
[root@k8s-master01 service]# kubectl apply -f mysql_endpoints.yaml 
endpoints/mysql created
# 创建mysql的endpoints
[root@k8s-master01 service]# kubectl describe svc mysql |grep -i endpoints:
Endpoints:         192.168.1.192:3306
# 可以看到已经匹配上[root@k8s-master01 service]# kubectl delete -f mysql_endpoints.yaml 
endpoints "mysql" deleted
[root@k8s-master01 service]# kubectl delete -f mysql_service.yaml 
service "mysql" deleted
[root@k8s-node02 ~]# yum -y remove mariadb-server
# 清除环境

这样集群内部就可以访问service到外部的服务了

coredns组件详解

CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务, CoreDNS 的实现非常简单。

验证coredns

[root@k8s-node01 ~]# ctr -n k8s.io images import dig.tar.gz
[root@k8s-node02 ~]# ctr -n k8s.io images import dig.tar.gz
# 工作节点导入镜像[root@k8s-master01 service]# cat dig.yaml 
apiVersion: v1
kind: Pod
metadata:name: dignamespace: default
spec:containers:- name: digimage:  xianchao/dig:latestimagePullPolicy: IfnotPresentcommand:- sleep- "3600"imagePullPolicy: IfNotPresentrestartPolicy: Always[root@k8s-master01 service]# kubectl apply -f dig.yaml 
pod/dig created
[root@k8s-master01 service]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
dig    1/1     Running   0          114s
# 创建测试pod
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d
[root@k8s-master01 service]# kubectl exec -it dig -- /bin/bash
bash-4.3# nslookup kubernetes
Server:		10.96.0.10
Address:	10.96.0.10#53Name:	kubernetes.default.svc.cluster.local
Address: 10.96.0.1
# 测试集群内部
bash-4.3# nslookup baidu.com
Server:		10.96.0.10
Address:	10.96.0.10#53Non-authoritative answer:
Name:	baidu.com
Address: 39.156.66.10
Name:	baidu.com
Address: 110.242.68.66
# 测试集群外部bash-4.3# exit
exit
[root@k8s-master01 service]# kubectl delete -f dig.yaml 
pod "dig" deleted
[root@k8s-master01 service]# kubectl delete -f .
# 清除环境

ot@k8s-master01 service]# kubectl delete -f mysql_endpoints.yaml
endpoints “mysql” deleted
[root@k8s-master01 service]# kubectl delete -f mysql_service.yaml
service “mysql” deleted
[root@k8s-node02 ~]# yum -y remove mariadb-server

清除环境


这样集群内部就可以访问service到外部的服务了#### coredns组件详解**CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师都会使用 CoreDNS 为集群提供服务发现的功能,Kubernetes 就在集群中使用 CoreDNS 解决服务发现的问题。 作为一个加入 CNCF(Cloud Native Computing Foundation)的服务**, **CoreDNS 的实现非常简单。**验证coredns```shell
[root@k8s-node01 ~]# ctr -n k8s.io images import dig.tar.gz
[root@k8s-node02 ~]# ctr -n k8s.io images import dig.tar.gz
# 工作节点导入镜像[root@k8s-master01 service]# cat dig.yaml 
apiVersion: v1
kind: Pod
metadata:name: dignamespace: default
spec:containers:- name: digimage:  xianchao/dig:latestimagePullPolicy: IfnotPresentcommand:- sleep- "3600"imagePullPolicy: IfNotPresentrestartPolicy: Always[root@k8s-master01 service]# kubectl apply -f dig.yaml 
pod/dig created
[root@k8s-master01 service]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
dig    1/1     Running   0          114s
# 创建测试pod
[root@k8s-master01 service]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d
[root@k8s-master01 service]# kubectl exec -it dig -- /bin/bash
bash-4.3# nslookup kubernetes
Server:		10.96.0.10
Address:	10.96.0.10#53Name:	kubernetes.default.svc.cluster.local
Address: 10.96.0.1
# 测试集群内部
bash-4.3# nslookup baidu.com
Server:		10.96.0.10
Address:	10.96.0.10#53Non-authoritative answer:
Name:	baidu.com
Address: 39.156.66.10
Name:	baidu.com
Address: 110.242.68.66
# 测试集群外部bash-4.3# exit
exit
[root@k8s-master01 service]# kubectl delete -f dig.yaml 
pod "dig" deleted
[root@k8s-master01 service]# kubectl delete -f .
# 清除环境

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

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

相关文章

【机器学习】七、降维与度量学习

1. 维数灾难 样本的特征数称为维数&#xff08;dimensionality&#xff09;&#xff0c;当维数非常大时&#xff0c;也就是现在所说的维数灾难。 维数灾难具体表现在&#xff1a;在高维情形下&#xff0c;数据样本将变得十分稀疏&#xff0c;因为此时要满足训练样本为“密采样…

Postgres主键自增时重复键违反唯一约束

错误: 重复键违反唯一约束\"bue_new_copy1_pkey\"\n 详细&#xff1a;键值\"(id)(31)\"已经存在\n 新增的数据的id跟表里面的数据id重复了&#xff0c;这种一般是手动导入数据或者复制表等情况造成的&#xff0c;直接修改表的序列为当前最大的id&#xf…

25期代码随想录算法训练营第十四天 | 二叉树 | 递归遍历、迭代遍历

目录 递归遍历前序遍历中序遍历后序遍历 迭代遍历前序遍历中序遍历后序遍历 递归遍历 前序遍历 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # …

python实现全向轮EKF_SLAM

python实现全向轮EKF_SLAM 代码地址及效果运动预测观测修正参考算法 代码地址及效果 代码地址 运动预测 简化控制量 u t u_t ut​ 分别定义为 v x Δ t v_x \Delta t vx​Δt&#xff0c; v y Δ t v_y \Delta t vy​Δt&#xff0c;和 ω z Δ t \omega_z \Delta t ωz…

【pytorch深度学习】使用张量表征真实数据

使用张量表征真实数据 本文为书pytorch深度学习实战的一些学习笔记和扩展知识&#xff0c;涉及到的csv文件等在这里不会给出&#xff0c;但是我会尽量脱离这一些文件将书本想要表达的内容给展示出来。 文章目录 使用张量表征真实数据1. 加载图像文件2. 改变布局3. 加载目录下…

自然语言处理(一):RNN

「循环神经网络」&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一个非常经典的面向序列的模型&#xff0c;可以对自然语言句子或是其他时序信号进行建模。进一步讲&#xff0c;它只有一个物理RNN单元&#xff0c;但是这个RNN单元可以按照时间步骤进行展开…

立冬特辑-----链表OJ题优选合集~~

目录 ​​​​​​​前言&#x1f333; 1.链表中倒数第k个结点&#x1f338; 1.1 思路 1.2 代码 2. 链表的回文结构&#x1fab8; 2.1 思路 2.2 代码 3.相交链表&#x1f32a;️ 3.1 思路 3.2 代码 4.环形链表I&#x1f30a;&#x1f6f3;️ 4.1 思路 4.2 代码 4…

Redis(三)

4、分布式锁 4.1 、基本原理和实现方式对比 分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路 那么…

HTTP-FLV详解及分析

文章目录 前言一、HTTP-FLV 简介1、市场上使用 http-flv 的商家2、http-flv、rtmp 和 hls 直播的优缺点3、http-flv 技术实现 二、Nginx 配置 http-flv1、Windows 安装 nginx&#xff0c;已经集成 nginx-http-flv-module2、nginx.conf 配置文件3、运行 nginx 服务器4、ffmpeg 推…

FiRa标准——MAC实现(二)

在IEEE 802.15.4z标准中&#xff0c;最关键的就是引入了STS&#xff08;加扰时间戳序列&#xff09;&#xff0c;实现了安全测距&#xff0c;大大提高了测距应用的安全性能。在FiRa的实现中&#xff0c;其密钥派生功能是非常重要的一个部分&#xff0c;本文首先对FiRa MAC中加密…

MeterSphere 任意文件读取漏洞(CVE-2023-25814)

MeterSphere 任意文件读取漏洞&#xff08;CVE-2023-25814&#xff09; 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: title"MeterSphere" 漏洞复现1. 构造poc2. 发送数据包3. 查看文件 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好地…

Python异常处理:三种不同方法的探索与最佳实践

Python异常处理&#xff1a;三种不同方法的探索与最佳实践 前言 本文旨在探讨Python中三种不同的异常处理方法。通过深入理解各种异常处理策略&#xff0c;我们可以更好地应对不同的编程场景&#xff0c;选择最适合自己需求的方法。 异常处理在编程中扮演着至关重要的角色。合…