《每天5分钟玩转kubernetes》读书笔记

笔记

概念

Pod是脆弱的,但应用是健壮的。

kubelet运行在Cluster所有节点上,负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。

Pending、ContainerCreating、ImagePullBackOff都表明Pod没有就绪,Running才是就绪状态。

k8s的系统组件都被放到kube-system namespace中。

kubelet是唯一没有以容器形式运行的k8s组件,它在Ubuntu中通过Systemd服务运行。

出于安全考虑,默认配置下k8s不会将Pod调度到Master节点。如果希望将k8s-master也当作Node使用,可执行如下命令:
kubectl taint node <k8s-node> node-role.kubernetes.io/master-
如果要恢复Master Only状态,执行如下命令:
kubectl taint node <k8s-node> node-role.kubernetes.io/master="":NoSchedule

默认配置下,Scheduler会将Pod调度到所有可用的Node。不过有些情况希望将Pod部署到指定的Node,如将有大量磁盘I/O的Pod部署到配置SSD的Node;或Pod需要GPU,需要运行在配置GPU的节点上。k8s是通过label来实现这个功能的。

设置label:
kubectl label node <k8s-node> disktype=ssd
查看节点的label:
kubectl get node --show-labels
然后可以编辑 yml 文件设置nodeSelector:disktype:ssd
删除label,-即删除的意思:
kubectl label node <k8s-node> disktype-
删除label后,除非在yml中删除nodeSelector设置,并执行kubectl apply命令重新部署,否则删除label不会生效。

Service

Service从逻辑上代表一组Pod,具体是哪些Pod则是由label来挑选的。Service有自己的不变的IP,客户端只需要访问Service的IP,k8s则负责建立和维护Service与Pod的映射关系。无论后端Pod如何变化,对客户端没有任何影响,因为Service没有变。

Cluster IP是一个虚拟IP,是由k8s节点上的iptables规则管理的。可以通过iptables-save命令打印出当前节点的iptables规则。Cluster的每一个节点都配置了相同的iptables规则,这样就确保了整个Cluster都能够通过Service的Cluster IP访问Service。

除可以通过Cluster IP访问Service,k8s还提供更为方便的DNS访问。k8s部署时会默认安装kube-dns组件,每当有新的Service被创建,kube-dns会添加该Service的DNS记录。Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service。如果在同一个namespace,则可以省略.<NAMESPACE_NAME>

DNS服务器是kube-dns.kube-system.svc.cluster.local,这实际上就是kube-dns组件,它本身是部署在kube-system namespace中的一个Service。

用nslookup查看httpd-svc的DNS信息。

除了Cluster内部可以访问Service,很多情况下也希望应用的Service能够暴露给Cluster外部。k8s提供多种类型的Service,默认是ClusterIP:

  • ClusterIP:Service通过Cluster内部的IP对外提供服务,只有Cluster内的节点和Pod可访问,这是默认的Service类型
  • NodePort:Service通过Cluster节点的静态端口对外提供服务。Cluster外部可以通过<NodeIP>:<NodePort>访问Service
  • LoadBalancer:Service利用cloud provider特有的load balancer对外提供服务,cloud provider负责将load balancer的流量导向Service。目前支持的cloud provider有GCP、AWS、Azure等。

DaemonSet

典型应用场景:

  1. 在集群的每个节点上运行存储Daemon,如glusterd或ceph
  2. 在每个节点上运行日志收集Daemon,如flunentd或logstash
  3. 在每个节点上运行监控Daemon,如Prometheus Node Exporter或collectd

Job Pod执行完容器已经退出,需要用--show-all才能查看Completed状态的Pod。

同时运行多个Pod,提高Job的执行效率。这个可以通过parallelism设置。
completions设置Job成功完成Pod的总数。

spec:
  completions: 6
  parallelism: 2

配置解读:每次运行两个Pod,直到总共有6个Pod成功完成。
如果不指定completions和parallelism,默认值均为1。

k8s默认没有enable CronJob功能,需要在kube-apiserver中加入这个功能,修改kube-apiserver的配置文件/etc/kubernetes/manifests/kubeapiserver.yaml,在启动参数中加上--runtime-config=batch/v2alpha1=true,然后重启kubelet服务即可:systemctl restart kubelet.service
验证,输入命令kubectl api-versions,或者执行更精确的命令:kubectl api-versions | grep batch/v2alpha1

健康检查

即Health Check。
k8s默认的健康检查机制:每个容器启动时都会执行一个进程,此进程由Dockerfile的CMD或ENTRYPOINT指定。如果进程退出时返回码非零,则认为容器发生故障,k8s就会根据restartPolicy重启容器。

Liveness探测指定k8s什么时候通过重启容器实现自愈;
Readiness探测指定k8s什么时候可以将容器加入到Service负载均衡池中,对外提供服务。

区别:

  1. Liveness探测和Readiness探测是两种Health Check机制,如果不特意配置,k8s将对两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断探测是否成功
  2. 两种探测的配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness探测是重启容器;Readiness探测则是将容器设置为不可用,不接收Service转发的请求
  3. Liveness探测和Readiness探测是独立执行的,二者之间没有依赖,可单独使用,也可以同时使用。用Liveness探测判断容器是否需要重启以实现自愈;用Readiness探测判断容器是否已经准备好对外提供服务。

健康检查的应用场景:

  1. Scale Up
  2. Rolling Update

滚动更新通过参数maxSurge和maxUnavailable来控制副本替换的数量:

  1. maxSurge:控制滚动更新过程中副本总数超过DESIRED的上限。可以是具体的整数,也可以是百分百,向上取整。maxSurge默认值为25%
  2. maxUnavailable:控制滚动更新过程中,不可用的副本相占DESIRED的最大比例。可以是具体的整数,也可以是百分百,向下取整。maxUnavailable默认值为25%

maxSurge值越大,初始创建的新副本数量就越多;maxUnavailable值越大,初始销毁的旧副本数量就越多。

滚动更新失败,可以通过kubectl rollout undo回滚到上一个版本

回滚

kubectl apply每次更新应用时,k8s都会记录下当前的配置,保存为一个revision,这样就可以回滚到某个特定revision。默认配置下,k8s只会保留最近的几个revision,可在Deployment配置文件中通过revisionHistoryLimit属性配置revision数量。

数据管理

容器和Pod是短暂的。其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,可以使用k8s Volume。Volume的生命周期独立于容器,Pod中的容器可能被销毁和重建,但Volume会被保留。

本质上,k8s Volume是一个目录,这一点与Docker Volume类似。k8s Volume也支持多种backend类型,包括emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph等。

emptyDir Volume对于容器来说是持久的,对于Pod则不是。当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不受影响。

emptyDir Volume的生命周期与Pod一致。Pod中的所有容器都可以共享Volume,它们可以指定各自的mount路径。

PVC

Pod通常是由应用的开发人员维护,Volume则通常是由存储系统的管理员维护。开发人员要获得上面的信息,要么询问管理员,要么自己就是管理员。这样就带来一个管理上的问题:应用开发人员和系统管理员的职责耦合在一起了。

解决方案:PVC
PV:PersistentVolume,是外部存储系统中的一块存储空间,由管理员创建和维护。与Volume一样,PV具有持久性,生命周期独立于Pod。

PVC:PersistentVolumeClaim ,是对PV的申请(Claim)。PVC通常由普通用户创建和维护。需要为Pod分配存储资源时,用户可以创建一个PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,k8s会查找并提供满足条件的PV。

有了PVC,用户只需要告诉k8s需要什么样的存储资源,而不必关心真正的空间从哪里分配、如何访问等底层细节信息。这些Storage Provider的底层信息交给管理员来处理,只有管理员才应该关心创建PersistentVolume的细节信息。

accessModes:支持的访问模式有3种,ReadWriteOnce表示PV能以read-write模式mount到单个节点,ReadOnlyMany表示PV能以read-only模式mount到多个节点,ReadWriteMany表示PV能以read-write模式mount到多个节点。

persistentVolumeReclaimPolicy:指定当PV的回收策略为Recycle,支持的策略有3种,Retain表示需要管理员手工回收;Recycle表示清除PV中的数据,效果相当于执行rm -rf/thevolume/*;Delete表示删除Storage Provider上的对应存储资源,例如AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume等。

回收PV

当不需要使用PV时,可用删除PVC回收PV。当PVC被删除后,k8s启动一个新Pod recycler-for-<pv>,这个Pod的作用就是清除PV的数据。此时mypv1的状态为Released,表示已经解除了与PVC的Bound,正在清除数据,不过此时还不可用。当数据清除完毕,PV的状态重新变为Available,此时可以被新的PVC申请。

PV还支持Delete的回收策略,会删除PV在Storage Provider上对应的存储空间。NFS的PV不支持Delete,支持Delete的Provider有AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume。

PV动态供给

Static Provision:静态供给,提前创建PV,通过PVC申请PV并在Pod中使用。

Dynamical Provision:动态供给,即如果没有满足PVC条件的PV,会动态创建PV。相比静态供给,动态供给有明显的优势:不需要提前创建PV,减少管理员的工作量,效率高。动态供给是通过StorageClass实现的,StorageClass定义如何创建PV。StorageClass支持Delete和Retain两种reclaimPolicy,默认是Delete。

Secret & Configmap

Secret会以密文的方式存储数据,会以Volume的形式被mount到Pod,容器可通过文件的方式使用Secret中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。

创建Secret的四种方法:

  • --from-literal:一个--from-literal对应一个信息条目
  • --from-file:一个文件内容对应一个信息条目
  • --from-env-file:文件中每行Key=Value对应一个信息条目
  • YAML:文件中的敏感数据必须是通过base64编码后数据

查看Secret

kubectl get secret <secret_name>
kubectl describe secret <secret_name>
kubectl edit secret <secret_name> # 查看加密信息

与Secret一样,ConfigMap也支持四种创建方式。

Helm

两个概念:chart和release

  • chart是创建一个应用的信息集合,包括各种k8s对象的配置模板、参数定义、依赖关系、文档说明等。chart是应用部署的自包含逻辑单元。可以将chart想象成apt、yum中的软件安装包
  • release是chart的运行实例,代表一个正在运行的应用。当chart被安装到k8s集群,就生成一个release。chart能够多次安装到同一个集群,每次安装都是一个release。

Helm是包管理工具,包就是指chart。Helm能够:

  • 从零创建新chart
  • 与存储chart的仓库交互,拉取、保存和更新chart
  • 在k8s集群中安装和卸载release
  • 更新、回滚和测试release

Helm包含两个组件:Helm客户端和Tiller服务器。

Helm客户端是终端用户使用的命令行工具,用户可以:

  • 在本地开发chart
  • 管理chart仓库
  • 与Tiller服务器交互
  • 在远程k8s集群上安装chart
  • 查看release信息
  • 升级或卸载已有的release

Tiller服务器运行在k8s集群中,它会处理Helm客户端的请求,与k8s API Server交互。Tiller服务器负责:

  • 监听来自Helm客户端的请求
  • 通过chart构建release
  • 在k8s中安装chart,并跟踪release的状态
  • 通过API Server升级或卸载已有的release

总结:Helm客户端负责管理chart,Tiller服务器负责管理release。

chart

Helm的应用打包格式,由一系列文件组成,这些文件描述k8s部署应用时所需要的资源。chart将这些文件放置在预定义的目录结构中,通常整个chart被打成tar包,标注上版本信息,便于Helm部署。

Helm采用Go语言的模板来编写chart。Go模板非常强大,支持变量、对象、函数、流控制等功能。

如果存在一些信息多个模板都会用到,则可在templates/_helpers.tpl中将其定义为子模板,然后通过templates函数引用。

randAlphaNumb64encquote都是Go模板语言支持的函数,函数之间可以通过管道|连接。

Helm有两种方式传递配置参数。

常用命令:

helm create mychart # 创建chart
helm lint mychart # 检测chart的语法,报告错误以及给出建议
helm install --dry-run mychart --debug  # 模拟安装chart,并输出每个模板生成的YAML内容
helm search mychart
helm repo add myrepo http://
helm install myrepo/mychart
helm repo update

任何HTTP Server都可以用作chart仓库。

Helm支持四种安装方法:

  1. 安装仓库中的chart,如helm install stable/nginx
  2. 通过tar包安装,如helm install./nginx-1.2.3.tgz
  3. 通过chart本地目录安装,如helm install./nginx
  4. 通过URL安装,如helm install https://example.com/charts/nginx-1.2.3.tgz

网络

基于扁平地址空间的网络模型,集群中的每个Pod都有自己的IP地址,Pod之间不需要配置NAT就能直接通信。另外,同一个Pod中的容器共享Pod的IP,能够通过localhost通信。

CNI,Container Networking Interface规范。CNI是由CoreOS提出的容器网络规范,使用插件(Plugin)模型创建容器的网络栈。

目前已有多种k8s网络方案,如Flannel、Calico、Canal、Weave Net等。因为它们都实现CNI规范,用户无论选择哪种方案,得到的网络模型都一样,即每个Pod都有独立的IP,可以直接通信。区别在于不同方案的底层实现不同,有的采用基于VxLAN的Overlay实现,有的则是Underlay,性能上有区别。再有就是是否支持Network Policy。

Network Policy

k8s的一种资源,Network Policy通过Label选择Pod,并指定其他Pod或外界如何与这些Pod通信。

默认情况下,所有Pod是非隔离的,即任何来源的网络流量都能够访问Pod,没有任何限制。当为Pod定义Network Policy时,只有Policy允许的流量才能访问Pod。不是所有的k8s网络方案都支持Network Policy。比如Flannel就不支持,Calico是支持的。
Canal用Flannel实现k8s集群网络,同时用Calico实现Network Policy。

Dashboard

k8s默认没有部署Dashboard,安装命令:
kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/charts/kubernetes-dashboard.yaml

Dashboard会在kube-system namespace中创建自己的Deployment和Service,

Service是ClusterIP类型,为方便使用,可通过kubectl --namespace=kube-system edit service kubernetes-dashboard修改成NodePort类型。

Dashboard支持Kubeconfig和Token两种认证方式。可以通过配置文件dashboard-admin.yaml为Dashboard默认用户赋予admin权限。

kubectl apply -f dashboard-admin.yaml命令使文件修改生效。

集群监控

Weave Scope

安装:``

Scope会自动构建应用和集群的逻辑拓扑,单击顶部PODS,会显示所有Pod以及Pod之间的依赖关系。

Scope支持关键字搜索和定位资源,还可以进行条件搜索,比如查找和定位MEMORY大于100MB的Pod。

Heapster

Heapster是k8s原生的集群监控方案。Heapster以Pod的形式运行,它会自动发现集群节点,从节点上的Kubelet获取监控数据。Kubelet则是从节点上的cAdvisor收集数据。Heapster将数据按照Pod进行分组,将它们存储到预先配置的backend并进行可视化展示。Heapster当前支持的backend有InfluxDB(通过Grafana展示)、Google Cloud Monitoring等。

整体架构
在这里插入图片描述

Prometheus Operator

Prometheus Operator基于基于Prometheus,可以监控k8s的API Server、Scheduler、Controller Manager等管理组件是否正常工作以及负荷是否过大。

Prometheus Operator的目标是尽可能简化在k8s中部署和维护Prometheus的工作。为方便管理,创建一个单独的Namespace monitoring,Prometheus Operator相关的组件都会部署到这个Namespace。

架构
在这里插入图片描述
组件

  • Prometheus Operator:在k8s中以Deployment运行。其职责是部署和管理Prometheus Server,根据ServiceMonitor动态更新Prometheus Server的监控对象。
  • Prometheus Server会作为k8s应用部署到集群中。为了更好地在k8s中管理Prometheus,CoreOS的开发人员专门定义了一个命名为Prometheus类型的k8s定制化资源。我们可以把Prometheus看作一种特殊的Deployment,它的用途就是专门部署Prometheus Server
  • Service就是Cluster中的Service资源,也是Prometheus要监控的对象,在Prometheus中叫作Target。每个监控对象都有一个对应的Service。比如要监控k8s Scheduler,就得有一个与Scheduler对应的Service。当然,k8s集群默认是没有这个Service的,Prometheus Operator会负责创建。
  • Operator能够动态更新Prometheus的Target列表,ServiceMonitor就是Target的抽象。比如想监控k8s Scheduler,用户可以创建一个与Scheduler Service相映射的ServiceMonitor对象。Operator则会发现这个新的ServiceMonitor,并将Scheduler的Target添加到Prometheus的监控列表中。ServiceMonitor也是Prometheus Operator专门开发的一种k8s定制化资源类型。
  • 除了Prometheus和ServiceMonitor,Alertmanager是Operator开发的第三种k8s定制化资源。我们可以把Alertmanager看作一种特殊的Deployment,它的用途就是专门部署Alertmanager组件。

集群日志管理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Maven【入门笔记】

Maven 解决版本依赖的问题 https://www.liaoxuefeng.com/wiki/1252599548343744/1309301146648610 如果没有项目管理工具&#xff0c;在开发项目的时候&#xff0c;我们需要手动管理依赖包&#xff0c;需要管理依赖包的版本、去找到并下载依赖包、还有依赖包所依赖的包 等等。…

【C语言进阶】数据的存储----浮点型篇

&#x1f341; 博客主页:江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言—探索高效编程的基石 &#x1f4bb; 其他专栏&#xff1a;数据结构探索 ​&#x1f4a1;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa; 社区&#xff1a;GeekHub &#x1f341; 如果觉得博…

途游游戏 x 极狐GitLab “通关” DevOps :单元测试从无到优,覆盖率 0→80%

目录 4 个工具孤岛 → 极狐GitLab 全家桶&#xff0c; 被动的「人找进度」 → 高效的「进度找人」 把 Code Review 做扎实 代码质量「向左移」&#xff0c;修复成本「往下降」 从无到「优」 自动执行单元测试&#xff0c;覆盖率 0→80% 你喜欢玩游戏吗&#xff1f; 最近…

IE浏览器,和Edge浏览器

目录 一.IE浏览器&#xff08;前世今生&#xff09; 1.什么是IE浏览器&#xff1f; 2.IE浏览器发展历程 3.IE浏览器在早些年为什么这么流行 4.ie浏览器为什么被停用? 5.IE浏览器无法适应如今的Web发展原因 二.Edge&#xff08;发展&#xff09; 1.什么是Edge浏览器&…

docker【安装、存储、镜像、仓库、网络、监控】

docker-0110.0.0.51docker-0210.0.0.52docker-0310.0.0.53 【1】docker安装 docker-01 [rootdocker-01 ~]# vim /etc/yum.conf [main] cachedir/var/cache/yum/$basearch/$releasever keepcache1 debuglevel2 logfile/var/log/yum.log exactarch1 obsoletes1 gpgcheck1 plugin…

k8s ingress获取客户端客户端真实IP

背景 在Kubernetes中&#xff0c;获取客户端真实IP地址是一个常见需求。这是因为在负载均衡架构中&#xff0c;原始请求的源IP地址会被替换成负载均衡器的IP地址。 获取客户端真实IP的需求背景包括以下几点&#xff1a; 安全性&#xff1a;基于客户端IP进行访问控制和认证授…

做好“关键基础设施提供商”角色,亚马逊云科技加快生成式AI落地

一场关于生产力的革命已在酝酿之中。全球管理咨询公司麦肯锡在最近的报告《生成式人工智能的经济潜力&#xff1a;下一波生产力浪潮》中指出&#xff0c;生成式AI每年可能为全球经济增加2.6万亿到4.4万亿美元的价值。在几天前的亚马逊云科技纽约峰会中&#xff0c;「生成式AI」…

熟练掌握ChatGPT解决复杂问题——学会提问

目录 引言 一、5W1H分析法 1. 简单的问题&#xff08;what、where、when、who&#xff09; 2.复杂的问题&#xff08;why、how&#xff09; 2.1 为什么&#xff08;Why&#xff09;——原因 2.2 方式 &#xff08;How&#xff09;——如何 二、如何提问得到更高质量的答案…

pycharm运行pytest无法实时输出信息

需要去掉控制台输出。根据查询相关信息显示pycharm运行pytest无法实时输出信息&#xff0c;需要去掉pycharm里面的运行模式&#xff0c;点击减号&#xff0c;再点击加号&#xff0c;添加python执行文件即可实时输出信息。 问题描述&#xff1a; 使用pycharm运行代码时&#x…

uniapp 持续获取定位(登录状态下才获取)(不采用定时器)(任意页面都可监听定位改变)

基于上次文章做了优化和改良,保证在登录状态下才获取定位信息 uniapp 小程序实时且持续获取定位信息(全局设置一次)(单页面监听定位改变)(不采用定时器)_uniapp小程序定位_前端小胡兔的博客-CSDN博客本篇文章实现了uniapp 微信小程序实时获取定位信息,小程序打开即可持续获取定…

2023年第四届“华数杯”数学建模思路 - 案例:退火算法

## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 退火算法原理 1.1 物理背景 在热力学上&#xff0c;退火&#xff08;annealing&#xff09;现象指物体逐渐降温的物理现象&#xff0c;温度愈低&#…

C++ 数组作为函数参数

数组元素和数组名都可以作为函数的参数以实现函数间数据的传递和共享。 可以用数组元素作为调用函数时的实参&#xff0c;这与使用该类型的一个变量&#xff08;或对象&#xff09;作实参是完全相同的。 如果使用数组名作为函数的参数&#xff0c;则实参和形参都应该是数组名…

企业上云实施路线图

企业上云步骤主要分为规划、设计、实施、验证、运维五个阶段。https://articles.e-works.net.cn/cloud/article144684.htm

XXL-JOB定时任务框架(Oracle定制版)

特点 xxl-job是一个轻量级、易扩展的分布式任务调度平台&#xff0c;能够快速开发和简单学习。开放源代码并被多家公司线上产品使用&#xff0c;开箱即用。尽管其确实非常好用&#xff0c;但我在工作中使用的是Oracle数据库&#xff0c;因为xxl-job是针对MySQL设计的&#xff…

group normalization

1、 Theory look for this link for more information, actually only this image can illustrate the group normalization.you can ignore the rest of this artical. 2、 Code check this link for detailed about the formulation and the theory of the group normalzi…

问题解决和批判性思维是软件工程的重要核心

软件工程的重心在于问题解决和批判性思维&#xff08;合理设计和架构降低复杂度&#xff09;&#xff0c;而非仅局限于编程。 许多人误以为软件工程就只是编程&#xff0c;即用编程语言编写指令&#xff0c;让计算机按照这些指令行事。但实际上&#xff0c;软件工程的内涵远超…

git 公钥密钥 生成与查看

1.什么是公钥 很多服务器都是需要认证的&#xff0c;ssh认证是其中的一种。在客户端生成公钥&#xff0c;把生成的公钥添加到服务器&#xff0c;你以后连接服务器就不用每次都输入用户名和密码了。 很多git服务器都是用ssh认证方式&#xff0c;你需要把你生成的公钥发送给代码仓…

模板方法模式(Template Method)

模板方法模式是一种行为设计模式&#xff0c;在超类中定义了一个算法的框架&#xff0c;而将一些步骤的实现延迟到子类中&#xff0c;使得子类可重定义该算法的特定步骤。 Template Method is a behavior design pattern. It defines an algorithm framework in the superclas…

Docker容器技术

前言 容器技术、虚拟化技术已经成为一种被大家广泛认可的服务器资源共享方式&#xff0c;容器技术可以在按需构建操作系统实例的过程当中为系统管理员提供极大的灵活性。由于hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题&#xff0c;因此容器技术&#xff0…

Python爬虫遇到重定向问题解决办法汇总

在进行Python爬虫任务时&#xff0c;遇到重定向问题是常见的问题之一。重定向是指在发送请求时&#xff0c;服务器会返回一个新的URL&#xff0c;将请求重新定向到该URL。为了帮助您解决这个问题&#xff0c;本文将提供一些实用的解决办法&#xff0c;并给出相关的代码示例&…