Kubernetes架构原则和对象设计(三)
云原生学习路线导航页(持续更新中)
- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes常见问题解答
本文主要对kubernetes的核心技术概念和核心API进行介绍,深入理解kubernetes对象设计原则
1.Kubernetes核心技术概念
1.1.Kubernetes API对象属性
- kubernetes对象,是其设计最牛的地方。kubernetes诞生时,要和openStack、docker等技术争夺天下,项目是很难推进的,因此谷歌做了两件事:
- 基于强大的borg系统
- 通过定义API规范,将自己做成业界规范。因此kubernetes将云计算领域所有的对象 ,都纳入其管控范围
- kubernetes为什么要定义规范?
- kubernetes把 计算节点应该如何、作业应该如何、服务应该如何、入栈流量应该如何、防火墙规则应该如何 等等,都定成标准和规范,自己专注于API层,就把自己的行业地位固化住了。
- 其他公司可以 对kubernetes的API进行各种实现,这就相当于加入了kubernetes生态,拉着全世界所有的云计算公司站队kubernetes。
- 规范强大起来后,其他公司在自己另起炉灶的意义就不大了,就逐渐都复用这个完善的规范了。
- 一个kubernetes对象,一般包含4个部分:
- TypeMeta:定义对象是什么
- Metadata:定义对象元数据,如 名字、标签、基本属性等
- Spec:对象的期望终态
- Status:对象的实时状态
1.2.TypeMeta
- TypeMeta 的内容其实就是GKV
- group:将对象进行分组,类似java的package
- kind:表示对象的类型,类似java的class
- version:表示这个对象的不同版本
- 为什么要有version
- 社区以前是每年发4个版本,现在是每年发3个版本,相当于每个季度多点 就会发一个新版本。
- 而我们做任何系统的时候都不是一个瀑布型的,都是有不停的迭代的,对象有可能发生变化,没有人能说第一天就把一个对象定义的特别清楚,所以要保证 API 的向前兼容。version就是为了保证API的向前兼容性
- 常见的version演进路线:alpha(demo)–>beta(基本稳定)–>v1(正式版)
- 每个对象在kubernetes系统内部中都存在两种版本:内部版本、外部版本
- 内部版本:etcd中真正存储的对象版本,不会直接暴露给用户看到,只是为了便于实现所有版本之间的转换。
- k8s对象,如果存在多版本,就需要为其提供一些conversion方法,负责 内部版本<–>所有外部版本 之间的转换, 使得同一个对象,不论使用哪个版本读取,都能读出来。
- 比如有10个版本,每个版本都提供 和 internalVersion之间的转换方法,就可以实现所有版本之间的互相转换,而不需要把所有版本之间的互相转换方法都写全(v1->v2,v2->v3,v2->v5…),即:拓扑型–>星型
- 如v1–>v2,只需要 v1–>internalVersion–>v2即可
- 外部版本:暴露给用户使用的版本,比如 v1alpha1、v1beta1、v1等
- 内部版本:etcd中真正存储的对象版本,不会直接暴露给用户看到,只是为了便于实现所有版本之间的转换。
1.3.Metadata
1.3.1.namespace 和 name 组成的对象唯一标识
- k8s的对象可以分成2类:Namespace对象、NoNamespace对象
- Namespace对象:即使用了Namespace隔离,Namespace下共享,在不同Namespace下允许重名
- NoNamespace对象:即未使用Namespace隔离的全局对象,集群共享,全局中不允许存在重名对象
- 因此,对象唯一性可以这么归纳:
- Namespace对象:Namespace+Name需要唯一,不允许重复。如 Pod、Service
- NoNamespace对象:Name需要唯一,不允许重复。如 Node
- namespace 和 name 组成的对象唯一标识,也被称为 对象的Key
1.3.2.uid:对象唯一id
- Metadata下是有唯一uid的,不过uid一般很少使用,有些场合下会用,之后遇到会讲。
1.3.3.label:标签
- label:标签,map[string]string,一般用于filter查询过滤
- 比如
kubectl get ns -l a=b
- 比如
- label的使用场景
- 比如说现在做成本控制,每个 作业或应用 都要规定好属于哪个业务部门,这叫成本分配,最终要去统计资源利用率的时候,就知道 a部门到底产生了哪些 作业或应用,最后公司财务再去review,审查每一个应用的财务开销。
- 这个例子中,作业或应用就可以打上 特定的label,用于标识 属于哪个业务部门
1.3.4.annotation:注解
- annotation,map[string]string,一般用于扩展对象功能
- 当你觉得kubernetes对象里面的属性不太够用,但是改动CRD的动作太大(涉及到CRD升级回滚各种风险),此时就可以做一些附加属性写到annotation
- annotation的key命名有一些不成文的规范:项目域名/功能名。比如:
flannel.alpha.coreos.com/backend-type
1.3.5.Finalizer:对象终止器,资源锁
- Finalizer:对象终止器,[]string,本质是一个资源锁
- 当Finalizer中存在值的时候,kubernetes是不会直接把pod删除的,delete命令只会让其进入Terminating状态。
- 只要Finalizer不为空即可,kubernetes不会管里面是什么,里面的值应该是Controller自己定义的
- 为什么要有Finalizer?
- 假如我有一个CRD+对应的Controller,此时Controller有bug crush死掉了,或者OOM了。用户如果发送一个delete命令,kubernetes就会直接把它删了,等Controller 恢复后,就可能会丢数据或者丢事件
- 而如果有Finalizer资源锁机制,Controller给自己管理的每个对象都打上特定的finalizer,并且只有自己会移除它。那么即便Controller死掉,pod也无法被真正的delete掉,Controller重启后会继续处理该pod的相关事件,处理完成后移除finalizer,kubernetes才会真正把pod删除
- Finalizer的使用场景:pod删除前的 外部依赖清理,防止泄漏
- 比如 pod 的 podIp 被写入了注册中心用于负载均衡,或者pod被分配了外部IP和外部DNS域名等,如果pod没有Finalizer,有可能被直接干掉。干掉后其他服务还会通过 外部ip或域名 请求到它,就发生了资源泄漏
- 有了Finalizer,控制器在发现deletionTimestamp有值后,就知道该pod要被删除了,会先行把外部依赖都解决,分配的IP和域名进行清理,其他服务的请求就不会打到这台机器了,解决了资源泄漏问题
1.3.6.ResourceVersion:用于版本控制的 分布式乐观锁
- ResourceVersion:用于版本控制的 分布式乐观锁
- 在分布式系统里,一般一个对象会被多个控制器管理,为了避免多个线程读写同一个对象所造成的资源冲突,就需要加锁。
- 可是加锁可能会带来一系列问题:线程饥饿、死锁等,因此就选择了版本控制的乐观锁方式。
- 当发生对象写操作时,apiserver会查看提交数据的ResourceVersion,如果<当前版本,说明该资源是根据较旧的版本更改的,拒绝本次更新,并返回一个409(“Conflict”)给写进程。写进程接收到后就知道发生了并发冲突,就需要根据最新数据处理后再提交
1.4.Spec和Status
- Spec 和 Status 根据需要定义,比如 Namespace资源 的Spec就是空的,因为它不需要定义什么,它只是一个目录。而Namespace的Status也只是表示其状态为 active 还是 terminating 等
- 不过我们查看Namespace时,会看到在spec中有个finalizers,这应该算是历史遗留问题。早期Namespace Controller通过.spec.finalizers保证在删除ns时,能够先把ns下所有的资源都清理掉
- 现在 在通用属性Metadata中也包括finalizer了,其实可以重构一下
2.Kubernetes 常用API对象
这里只列举一些最常用的API对象,更详细的学习和深入,直接去看官方文档就好
2.1.Kubernetes常用API对象及其分组
- 核心对象core:基本上是能够满足一个应用的最小集合
- 随着一个对象的迭代和成熟度,可能会被划分到不同的group中,比如deployment以前就是属于extensions/v1beta1,现在划分到apps/v1了
2.2.Pod:Kubernetes调度的基本单位
2.2.1.Pod基本介绍
- Pod是kubernetes调度的基本单位,一个pod可以包含多个容器,它们共享network、PID、IPC、UTS namespace。另外,一个Pod的volume默认也被多个容器间共享
- 一个pod中多个容器 network、volume 默认就是共享的,因此容器之间可以通过localhost去通信,多个容器的端口也不能冲突的。
- 而 PID、IPC 这些namespace是默认是不共享的,但是可以通过属性控制。比如使用 Pod .spec 中的 shareProcessNamespace 字段可以启用进程命名空间共享
apiVersion: v1 kind: Pod metadata:name: nginx spec:shareProcessNamespace: truecontainers:- name: nginximage: nginx- name: shellimage: busybox:1.28command: ["sleep", "3600"]securityContext:capabilities:add:- SYS_PTRACEstdin: truetty: true
2.2.2.Pod中配置来源
- 一个应用,配置一般要和代码进行分离,代码从容器镜像来,配置的来源就比较多了,比如作为环境变量写入,或者外挂一个存储卷,读取一个配置文件
2.2.2.1.Pod中的环境变量配置
- pod中环境变量的数据来源,一般包括4种。
- ConfigMap 和 Secret
- configmap是Kubernetes用于保存应用配置的对象,内容是明文保存。
- configmap的结构由 TypeMeta、Metadata、Data(map[string]string) 等属性组成,它不包含Spec,或者说data就是它的spec。
- secret和configmap 结构一样,不过它是加密的
2.2.2.2.Pod中外挂存储卷配置
- 之前在讲Docker的时候,使用
docker run -v
命令时有挂载过外部存储到容器中。kubernetes中也是一样的,比如定义一个Pod,也可以为Pod中的容器挂载存储。 - 存储卷使用分为两部分:声明卷、挂载卷
- 声明卷Volume:卷名称、卷类型,表明卷的数据来源
- 挂载卷VolumeMount:卷名称、挂载到哪个目录
2.2.3.Pod网络
2.2.4.Pod资源限制
- 如何查看 Pod容器 的资源限制
- 方法一:进入pod内部查看
- 进入pod内部,在 /sys/fs/cgroup下面,可以看到当前pod的所有 cgroup设置
- 比如 /sys/fs/cgroup/cpu 中,cpu.cfs_period_us、cpu.cfs_quota_us 就以绝对值的方式,设置了pod的 cpu limit
- 再比如,在 /sys/fs/cgroup/memory 中,memory.limit_in_bytes 就设置了pod的 memory limit
- 方法二:在pod所在主机上查看
- 进入主机的 /sys/fs/cgroup,每一个子系统中,都有一个kubepods的目录,里面存储着所有pod的cgroup
- kubepods里面,还有一个burstable目录,这就是所有pod cgroup的存储位置
- 比如,查看一个pod的cpu cgroup,就应该进入:
/sys/fs/cgroup/cpu/kubepods/burstable/podxxxx-xxxx/
- 其中 podxxxx-xxxx 表示pod的uid,可以使用kubectl get pods podxxx -oyaml找到
- 方法一:进入pod内部查看
2.2.5.Pod健康检查
-
健康探针官方文档 官方文档写的很通俗,建议这块直接看文档
-
Deployment 滚动升级配置 MaxUnavailable 和 MaxSurge
- MaxUnavailable:最大不可用pod数量,即无法正常提供服务的pod数量,如果达到了这个阈值,滚动升级是要暂停的
- MaxSurge:pod总数量可以超过 .spec.replicas 多少
-
Pod 字段
.status.ready
- Pod中有一个字段
.status.ready
,代表这个pod是否完全准备好对外提供服务了 - service做负载均衡 流量转发的时候,默认不会把没 Ready 的pod加入负载列表
- Pod中有一个字段
-
Pod 的有3种健康探测方式
- LivenessProbe:存活探针,判断应用是否还存活,不存活则杀死
- ReadinessProbe:就绪探针,判断应用是否就绪,没有就绪则不应该接收流量,pod会表现为NotReady,但不会杀死或重启pod
- StartupProbe:启动探针,判断应用是否启动完成
- 配置了StartupProbe时,LivenessProbe和ReadinessProbe 会在StartupProbe成功后才生效。
- 我们可以为StartupProbe配置较低的探测频率,保证慢启动应用的 数据库、端口、缓存预热 等依赖加载的过程中,不会太频繁的探测造成应用压力,也不会在启动时就被LivenessProbe和ReadinessProbe判定为失败
-
健康探测的一些配置
- periodSeconds:每次探测的间隔时间。periodSeconds要合理,太短会加大应用压力,太长会较慢发现故障
-
Pod 的3种探活方式
- Exec:去这个容器里面执行一个命令,命令返回非0则失败,返回0则成功
- 下面就是 cat一个文件,如果文件存在则探测成功,文件不存在肯定会报错
- 下面就是 cat一个文件,如果文件存在则探测成功,文件不存在肯定会报错
- TCP socket:由kubelet发起对 指定host+port的端口连通性检查
- HTTP:由kubelet发起一条真正的http请求,容器化应用开发时一般都会预留一个端口用于http的健康检查
- Exec:去这个容器里面执行一个命令,命令返回非0则失败,返回0则成功
2.2.6.Pod的配置:ConfigMap、Secret
2.3.用户UserAccount 和 服务账户ServiceAccount
- 当一个组件要跟 API Server 通信的时候,要做认证健全,就一定要有个身份,所以任何的 Kubernetes pod 都需要以一个 service account的身份运行
- 这个Service Account会以一个volume的形式,被mount到一个Pod里面,里面的应用就可以读取这个service account 所对应的 TOKEN 或 ca证书文件 来跟API Server通信。
2.4.负载均衡Service
- 下面举例Service
- clusterIp:为service分配的集群内ip,集群外无法访问
- ipFamilies:定义service的ip协议栈是 IPv4
- ipFamilypolicy:协议栈类型为单栈
- 详细的配置访问可以看官方文档:IPv4/IPv6 双协议栈
- ports:后端业务的访问信息
- selector:label选择器,选择service要管理哪些pod
2.5.副本集ReplicaSet
2.6.部署 Deployment
2.7.Deployment 和 Service 练习
2.8.有状态服务集 Statefulset
-
Statefulset 和 Deployment 的差异
- 名称规则不同:
- Statefulset:创建的多副本,名称是固定的,
按照数字序号递增
- Deployment:创建的多副本,名字比较长:
deployment名称-podTemplate哈希值-随机字符串
- Statefulset:创建的多副本,名称是固定的,
- 创建/更新顺序不同
- Statefulset:创建是从小号–>大号,更新和删除是从大号–>小号。其中升级的时候支持滚动升级、分片升级、OnDelete升级
- Deployment:创建/更新/删除 都是随机的。
- Pod行为不同
- Statefulset:因为名称是固定的,所以每个pod都是独立的个体,可以为它们声明不同的volume,当pod发生重建后可以关联旧的volume继承数据
- Deployment:因为名称是随机的,所以每个pod无法做到独立个体,pod发生重建后名称就改变了,不太方便做到继承旧数据
- 名称规则不同:
2.9.任务 Job
- Deployment、Statefulset都是 Running 长时任务,有时还有一些 Short 短时任务,Kuberenetes提供了Job资源类型用于短时任务,Job完成之后是completed状态,结束后不会再被拉起
2.10.后台支撑服务集 DaemonSet
2.11.存储PV和PVC
- 无论存储来自于本地还是网络,都可以通过PV和PVC去挂载
2.12.CRD:CustomResourceDefinition
- CRD可以理解为数据库的开放式表,当基本对象没有办法支撑你的需求时,可以通过CRD的这种对象扩展一个当前业务。
- 比如:Calico,目前开源的最成熟的纯三层网络框架之一,它其实就依赖于一堆CRD
- 目前所有围绕着Kubernetes的大的生态项目基本都有自己的CRD和控制器,无论是运维还是开发最后都会涉及到有CRD
2.13.课后练习
2.13.1.启动一个envoy并查看进程及配置
apiVersion: v1
kind: PersistentVolume
metadata:name: envoy-pv
spec:storageClassName: local-storagecapacity:storage: 10GiaccessModes:- ReadWriteOncehostPath:path: /data---apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: envoy-pvc
spec:storageClassName: local-storageaccessModes:- ReadWriteOnceresources:requests:storage: 10Gi---apiVersion: apps/v1
kind: Deployment
metadata:name: envoy-deployment
spec:replicas: 1selector:matchLabels:app: envoytemplate:metadata:labels:app: envoyspec:containers:- name: envoyimage: envoyproxy/envoy:v1.19.1ports:- containerPort: 8080volumeMounts:- name: envoy-datamountPath: /datavolumes:- name: envoy-datapersistentVolumeClaim:claimName: envoy-pvc
# 将上述文件保存为yaml文件,然后apply即可
[root@VM-226-235-tencentos ~/yamls]# kubectl apply -f envoy.yaml# 查看创建好的pv、pvc、deploy
[root@VM-226-235-tencentos ~/yamls]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
envoy-pvc Bound envoy-pv 10Gi RWO local-storage 12m
[root@VM-226-235-tencentos ~/yamls]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
envoy-pv 10Gi RWO Retain Bound default/envoy-pvc local-storage 12m
[root@VM-226-235-tencentos ~/yamls]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
envoy-deployment 1/1 1 1 22m# 进入pod内部
[root@VM-226-235-tencentos ~/yamls]# kubectl exec -it envoy-deployment-68cd599779-4chjj -- /bin/bash# 可以看到1号进程即为envoy进程,命令中指定的了config文件路径
root@envoy-deployment-68cd599779-4chjj:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
envoy 1 0 0 13:41 ? 00:00:01 envoy -c /etc/envoy/envoy.yaml
root 104 0 0 13:52 pts/0 00:00:00 /bin/bash
root 114 104 0 13:52 pts/0 00:00:00 ps -ef# 查看 envoy 的 config 文件
root@envoy-deployment-68cd599779-4chjj:/# cat /etc/envoy/envoy.yaml
admin:address:socket_address:protocol: TCPaddress: 0.0.0.0# envoy 的 监听端口port_value: 9901
static_resources:listeners:- name: listener_0address:socket_address:protocol: TCPaddress: 0.0.0.0port_value: 10000filter_chains:- filters:- name: envoy.filters.network.http_connection_managertyped_config:"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagerscheme_header_transformation:scheme_to_overwrite: httpsstat_prefix: ingress_httproute_config:name: local_routevirtual_hosts:- name: local_servicedomains: ["*"]routes:- match:prefix: "/"route:host_rewrite_literal: www.envoyproxy.iocluster: service_envoyproxy_iohttp_filters:- name: envoy.filters.http.routerclusters:- name: service_envoyproxy_ioconnect_timeout: 30stype: LOGICAL_DNS# Comment out the following line to test on v6 networksdns_lookup_family: V4_ONLYlb_policy: ROUND_ROBINload_assignment:cluster_name: service_envoyproxy_ioendpoints:- lb_endpoints:- endpoint:address:socket_address:address: www.envoyproxy.ioport_value: 443transport_socket:name: envoy.transport_sockets.tlstyped_config:"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContextsni: www.envoyproxy.io
-
此时我们还没有从外部挂载配置到容器中,envoy使用默认配置,放在容器的/etc/envoy/envoy.yaml。所以待会我们从外部挂载配置的时候,要挂载到这个目录下
-
从配置中可以看出,虽然我们在 Pod 中 容器containerPort写的是8080,但是envoy实际监听的端口是9901,curl一下试试
# 首先使用kubectl get pods -owide找到podIp [root@VM-226-235-tencentos ~/zgy/yamls]# kubectl get pods -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES envoy-deployment-555699d88-bmxxx 1/1 Running 0 13m 10.244.0.214 vm-226-235-tencentos <none> <none># 然后curl一下指定端口[root@VM-226-235-tencentos ~/zgy/yamls]# curl 10.244.0.214:8080 curl: (7) Failed connect to 10.244.0.214:8080; Connection refused# [root@VM-226-235-tencentos ~/zgy/yamls]# curl 10.244.0.214:9901<head><title>Envoy Admin</title><link rel='shortcut icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAH9SURBVEhL7ZRdTttAFIUrUFaAX5w9gIhgUfzshFRK+gIbaVbAzwaqCly1dSpKk5A485/YCdXpHTB4BsdgVe0bD0cZ3Xsm38yZ8byTUuJ/6g3wqqoBrBhPTzmmLfptMbAzttJTpTKAF2MWC7ADCdNIwXZpvMMwayiIwwS874CcOc9VuQPR1dBBChPMITpFXXU45hukIIH6kHhzVqkEYB8F5HYGvZ5B7EvwmHt9K/59CrU3QbY2RNYaQPYmJc+jPIBICNCcg20ZsAsCPfbcrFlRF+cJZpvXSJt9yMTxO/IAzJrCOfhJXiOgFEX/SbZmezTWxyNk4Q9anHMmjnzAhEyhAW8LCE6wl26J7ZFHH1FMYQxh567weQBOO1AW8D7P/UXAQySq/QvL8Fu9HfCEw4SKALm5BkC3bwjwhSKrA5hYAMXTJnPNiMyRBVzVjcgCyHiSm+8P+WGlnmwtP2RzbCMiQJ0d2KtmmmPorRHEhfMROVfTG5/fYrF5iWXzE80tfy9WPsCqx5Buj7FYH0LvDyHiqd+3otpsr4/fa5+xbEVQPfrYnntylQG5VGeMLBhgEfyE7o6e6qYzwHIjwl0QwXSvvTmrVAY4D5ddvT64wV0jRrr7FekO/XEjwuwwhuw7Ef7NY+dlfXpLb06EtHUJdVbsxvNUqBrwj/QGeEUSfwBAkmWHn5Bb/gAAAABJRU5'/><style>.home-table {........```
-
我们接下来外挂存储的时候正好测试一下把端口修改为8080,和pod的containerPort保持一致
2.13.2.挂载外部配置到Pod并测试访问
-
创建一个configMap
apiVersion: v1 kind: ConfigMap metadata:name: envoy-config data:envoy.yaml: |admin:address:socket_address:protocol: TCPaddress: 0.0.0.0port_value: 8080static_resources:listeners:- name: listener_0address:socket_address:protocol: TCPaddress: 0.0.0.0port_value: 10000filter_chains:- filters:- name: envoy.filters.network.http_connection_managertyped_config:"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagerscheme_header_transformation:scheme_to_overwrite: httpsstat_prefix: ingress_httproute_config:name: local_routevirtual_hosts:- name: local_servicedomains: ["*"]routes:- match:prefix: "/"route:host_rewrite_literal: www.envoyproxy.iocluster: service_envoyproxy_iohttp_filters:- name: envoy.filters.http.routerclusters:- name: service_envoyproxy_ioconnect_timeout: 30stype: LOGICAL_DNSdns_lookup_family: V4_ONLYlb_policy: ROUND_ROBINload_assignment:cluster_name: service_envoyproxy_ioendpoints:- lb_endpoints:- endpoint:address:socket_address:address: www.envoyproxy.ioport_value: 443transport_socket:name: envoy.transport_sockets.tlstyped_config:"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContextsni: www.envoyproxy.io
-
将configmap mount到deploy中
apiVersion: apps/v1kind: Deploymentmetadata:name: envoy-deploymentspec:replicas: 1selector:matchLabels:app: envoytemplate:metadata:labels:app: envoyspec:containers:- name: envoyimage: envoyproxy/envoy:v1.19.1ports:- containerPort: 8080volumeMounts:- name: envoy-datamountPath: /data- name: envoy-config-volumemountPath: /etc/envoyvolumes:- name: envoy-datapersistentVolumeClaim:claimName: envoy-pvc- name: envoy-config-volumeconfigMap:name: envoy-config
-
yaml准备好后,apply到环境中
kubectl apply -f cm.yaml kubectl apply -f deploy.yaml
-
进入pod内部,查看/etc/envoy/envoy.yaml,可以看到已经挂载上来了
root@envoy-deployment-555699d88-bmxxx:/# ls /etc/envoy envoy.yaml
-
重新获取podip,然后curl一下8080,可以看到监听端口已经换成8080了
# [root@VM-226-235-tencentos ~/zgy/yamls]# curl 10.244.0.214:8080<head><title>Envoy Admin</title><link rel='shortcut icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAH9SURBVEhL7ZRdTttAFIUrUFaAX5w9gIhgUfzshFRK+gIbaVbAzwaqCly1dSpKk5A485/YCdXpHTB4BsdgVe0bD0cZ3Xsm38yZ8byTUuJ/6g3wqqoBrBhPTzmmLfptMbAzttJTpTKAF2MWC7ADCdNIwXZpvMMwayiIwwS874CcOc9VuQPR1dBBChPMITpFXXU45hukIIH6kHhzVqkEYB8F5HYGvZ5B7EvwmHt9K/59CrU3QbY2RNYaQPYmJc+jPIBICNCcg20ZsAsCPfbcrFlRF+cJZpvXSJt9yMTxO/IAzJrCOfhJXiOgFEX/SbZmezTWxyNk4Q9anHMmjnzAhEyhAW8LCE6wl26J7ZFHH1FMYQxh567weQBOO1AW8D7P/UXAQySq/QvL8Fu9HfCEw4SKALm5BkC3bwjwhSKrA5hYAMXTJnPNiMyRBVzVjcgCyHiSm+8P+WGlnmwtP2RzbCMiQJ0d2KtmmmPorRHEhfMROVfTG5/fYrF5iWXzE80tfy9WPsCqx5Buj7FYH0LvDyHiqd+3otpsr4/fa5+xbEVQPfrYnntylQG5VGeMLBhgEfyE7o6e6qYzwHIjwl0QwXSvvTmrVAY4D5ddvT64wV0jRrr7FekO/XEjwuwwhuw7Ef7NY+dlfXpLb06EtHUJdVbsxvNUqBrwj/QGeEUSfwBAkmWHn5Bb/gAAAABJRU5'/><style>.home-table {........
2.13.3.级联删除和非级联删除
-
级联删除(Cascading Delete)是指在删除一个父资源对象时,Kubernetes会自动删除与之相关联的子资源对象。例如,如果删除一个命名空间(Namespace),级联删除将同时删除该命名空间中的所有Pod、Service、Deployment等子资源对象。
-
非级联删除(Non-Cascading Delete)是指在删除一个父资源对象时,Kubernetes只删除该父资源对象本身,而不会自动删除与之相关联的子资源对象。这意味着删除操作只影响到被删除的父资源对象,而不会影响到其他关联的子资源对象。
-
级联删除:删除deploy,默认会把replicaset和pod全部删除
[root@VM-226-235-tencentos ~/zgy/yamls]# kubectl delete deploy envoy-deployment deployment.apps "envoy-deployment" deleted [root@VM-226-235-tencentos ~/zgy/yamls]# kubectl get pods| grep envoy-deployment [root@VM-226-235-tencentos ~/zgy/yamls]# kubectl get replicaset| grep envoy-deployment No resources found in default namespace.
-
非级联删除:删除deploy,默认会保留replicaset和pod等子资源
[root@VM-226-235-tencentos ~/zgy/yamls]# kubectl delete deploy envoy-deployment --cascade=false deployment.apps "envoy-deployment" deleted [root@VM-226-235-tencentos ~/zgy/yamls]# kubectl get pods NAME READY STATUS RESTARTS AGE clunky-serval-promtail-rcccj 0/1 ImagePullBackOff 0 6h2m envoy-deployment-555699d88-gr9qq 1/1 Running 0 69s [root@VM-226-235-tencentos ~/zgy/yamls]# kubectl get replicaset NAME DESIRED CURRENT READY AGE envoy-deployment-555699d88 1 1 1 77s
相关文章:
Kubernetes架构原则和对象设计(三)
云原生学习路线导航页(持续更新中) kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计(一)Kubernetes架构原则和对象设计(二)Kubernetes常见问题解答 本文主要对kubernetes的核心技术概念和核心A…...
Qt+海康虚拟相机的调试
做机器视觉项目的时候,在没有相机或需要把现场采集的图片在本地跑一下做测试时,可以使用海康的虚拟相机调试。以下是设置步骤: 1.安装好海康MVS软件,在菜单栏->工具选择虚拟相机工具,如下图: 2.打开虚拟…...
485网关数据收发测试
目录 1.UDP SERVER数据收发测试 使用产品: || ZQWL-GW1600NM 产品||【智嵌物联】智能网关型串口服务器 1.UDP SERVER数据收发测试 A(TX)连接RX B(RX)连接TX 打开1个网络调试助手,模拟用户的UDP客户端设…...
【C#】一维、二维、三维数组的使用
在C#中,数组是用于存储固定数量相同类型元素的数据结构。根据维度的不同,可以分为一维数组、二维数组(矩阵阵列)、三维数组等。每增加一个维度,数据的组织方式就会变得更加复杂。 一维数组 一维数组是最简单的数组形…...
65【服务器攻击原理讲解】
我们经常可能会听说,某某的服务器被打了,被打死了,这里的打死并不一是指服务器直接死机 服务器有2个决定性参数 1:宽带,宽带越大,能传输的数据就越多 2:CPU,CPU越好能处理的运算…...
用AI写游戏3——模拟发牌
提示词 写一个python程序 ,输入参数为玩家数,输出参数为每个玩家的3张扑克牌 # 写一个python程序 ,输入参数为玩家数,输出参数为每个玩家的3张扑克牌 # 为了实现这个功能,我们可以使用Python的标准库random来生成随机…...
React 生命周期函数详解
React 组件在其生命周期中有多个阶段,每个阶段都有特定的生命周期函数(Lifecycle Methods)。这些函数允许你在组件的不同阶段执行特定的操作。以下是 React 组件生命周期的主要阶段及其对应的生命周期函数,并结合了 React 16.3 的…...
android 动态库加载机制
省流:android 不兼容 glibc,而是写了一套独立的 c 运行时库 (bionic libc),为移动设备和 google 自己推的东西做了大量优化。在这套工具链里,aosp 实现了一个兼容 bionic libc 的链接器,放到系统中代替 ld。 这个链接…...
PyTorch torch.sign函数介绍
torch.sign 是 PyTorch 库中用于计算输入张量每个元素符号的函数。下面从功能概述、函数原型、参数解释、返回值、使用示例以及与相关函数对比等方面详细介绍 torch.sign。 功能概述 torch.sign 函数会返回一个与输入张量形状相同的新张量,其中每个元素的值表示输…...
Flink CDC YAML:面向数据集成的 API 设计
摘要:本文整理自阿里云智能集团 、Flink PMC Member & Committer 徐榜江(雪尽)老师在 Flink Forward Asia 2024 数据集成(一)专场中的分享。主要分为以下四个方面: Flink CDC YAML API Transform A…...
计算机网络知识速记:TCP 与 UDP
计算机网络知识速记:TCP 与 UDP 一、概念 TCP (Transmission Control Protocol): 一个面向连接的协议,确保数据在传输过程中完整无误。通过建立连接和数据确认机制,提高数据传输的可靠性。是面向字节传输的。 UDP (User Datagram Protocol)…...
差分算法解析
差分(Difference Array)是一种常见的算法技巧,广泛应用于区间更新与区间查询的问题。它通过将数组的更新操作转化为数组的差分操作,使得某些类型的算法能在更短的时间内完成计算,尤其在处理频繁的区间更新时表现得尤为…...
makefile 的strip,filter,ifeq,ifneq基础使用
目录 一、strip1.1 语法1.2 示例1.3 使用场景 二、filter2.1 语法2.2 示例2.3 使用 * 和 ? 通配符2.4 结合使用2.5 使用场景 三、ifeq 和 ifneq3.1 ifeq3.1.1 语法3.1.2 示例 3.2 ifneq3.2.1 语法3.2.2 示例 3.3 典型使用场景3.3.1 根据版本控制编译选项:3.3.2 选择不同的源文…...
SOA(面向服务架构)全面解析
1. 引言 什么是SOA(面向服务架构) SOA(Service-Oriented Architecture,面向服务架构)是一种将应用程序功能以“服务”的形式进行模块化设计的架构风格。这些服务是独立的功能模块,它们通过定义明确的接口…...
B树详解及其C语言实现
目录 一、B树的基本原理 二、B树操作过程图形化演示 三、B树的应用场景 四、C语言实现B树及示例 五、代码执行结果说明 六、应用实例:文件系统目录索引 七、总结 一、B树的基本原理 B树(B-Tree) 是一种自平衡的树数据结构,…...
3.1 学习UVM中的uvm_component类分为几步?
文章目录 前言一、定义1.1 角色和功能:1.2 与其他UVM类的区别:1.3 主要属性和方法: 二、使用方法2.1 定义和实例化:2.2 生命周期管理:2.3 组件间通信: 三、何时使用3.1 使用场景3.2 适用组件3.3 与uvm_obje…...
python:面向对象之魔法方法
概念:主要是提供一些特殊的功能。 1.__init__方法: 一.不带参数: python中类似__xx__() __init__():初始化对象class Car():def __init__(self):self.color blueself.type suvdef info(self):print(f车的颜色是:{self.color})p…...
postgresql 游标(cursor)的使用
概述 PostgreSQL游标可以封装查询并对其中每一行记录进行单独处理。当我们想对大量结果集进行分批处理时可以使用游标,因为一次性处理可能造成内存溢出。 另外我们可以定义函数返回游标类型变量,这是函数返回大数据集的有效方式,函数调用者…...
vivado 7 系列器件时钟
7 系列器件时钟 注释: 本章节以 Virtex -7 时钟源为例。 Virtex-6 的时钟资源与此类似。如果使用不同的架构,请参阅有关器件的 《时 钟资源指南》 [ 参照 40] 。 Virtex-6 和 Virtex-7 器件内含 32 个称为 BUFG 的全局时钟缓存。 BUFG 可满…...
Vue 3 部分新特性解析
1. 引言 Vue 3 引入了许多新特性和改进,使得开发更加高效和灵活。本文将深入探讨 Vue 3 的高阶部分,包括 Composition API、自定义指令、插件开发、状态管理和性能优化。 2. Composition API 2.1 引入 Composition API Composition API 是 Vue 3 中引…...
ubuntu24.04安装布置ros
最近换电脑布置机器人环境,下了24.04,但是网上的都不太合适,于是自己试着布置好了,留作有需要的人一起看看。 文章目录 目录 前言 一、确认 ROS 发行版名称 二、检查你的 Ubuntu 版本 三、安装正确的 ROS 发行版 四、对于Ubuntu24…...
数据结构与算法-链表
单向链表(带哨兵) public class SinglyLinkedList {private Node head new Node(Integer.MIN_VALUE, null); // 定义一个哨兵节点作为头部节点,避免对头节点进行特殊处理// 节点类,包含值和指向下一个节点的引用private static …...
【图片合并转换PDF】如何将每个文件夹下的图片转化成PDF并合并成一个文件?下面基于C++的方式教你实现
医院在为患者进行诊断和治疗过程中,会产生大量的医学影像图片,如 X 光片、CT 扫描图、MRI 图像等。这些图片通常会按照检查时间或者检查项目存放在不同的文件夹中。为了方便医生查阅和患者病历的长期保存,需要将每个患者文件夹下的图片合并成…...
协议-ACLLite-ffmpeg
是什么? FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。 libavcodec是一个领先的音频/视频编解码器库&…...
flask开发的网站,后端服务关闭后,可以找回之前的数据的吗
如果使用 Flask 开发的网页,后端服务关闭后,是否还能找回数据取决于数据的存储方式: 可能找回数据的情况: 数据库存储(MySQL、PostgreSQL、SQLite 等) 如果 Flask 连接的是持久化数据库,即使后…...
deepseek API开发简介
1、申请deepseek api key: https://platform.deepseek.com/api_keys创建API Key,并复制Key 2、安装python、pip,然后安装requests pip install requests3、.示例代码 import requests import json# DeepSeek API 地址 API_URL "ht…...
【AI】在Ubuntu中使用docker对DeepSeek的部署与使用
这篇文章前言是我基于部署好的deepseek-r1:8b模型跑出来的 关于部署DeepSeek的前言与介绍 在当今快速发展的技术环境中,有效地利用机器学习工具来解决问题变得越来越重要。今天,我将引入一个名为DeepSeek 的工具,它作为一种强大的搜索引擎&a…...
Baklib推进内容中台智能推荐系统的技术创新与执行方案
内容概要 在当前数字化快速发展的背景下,内容中台的智能化推荐系统显得尤为重要。通过技术创新,Baklib致力于提升平台的用户体验,实现精准的个性化推荐,满足多样化的用户需求。内容中台不仅能够高效管理和组织大量的信息与知识&a…...
MySQL8.0实现MHA高可用
一、简介 MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点…...
ip地址是手机号地址还是手机地址
在数字化生活的浪潮中,IP地址、手机号和手机地址这三个概念如影随形,它们各自承载着网络世界的独特功能,却又因名称和功能的相似性而时常被混淆。尤其是“IP地址”这一术语,经常被错误地与手机号地址或手机地址划上等号。本文旨在…...
多光谱成像技术在华为Mate70系列的应用
华为Mate70系列搭载了光谱技术的产物——红枫原色摄像头,这是一款150万像素的多光谱摄像头。 相较于普通摄像头,它具有以下优势: 色彩还原度高:色彩还原准确度提升约 120%,能捕捉更多光谱信息,使拍摄照片色…...
21.2.6 字体和边框
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 通过设置Rang.Font对象的几个成员就可以修改字体,设置Range.Borders就可以修改边框样式。 【例 21.6】【项目ÿ…...
详解命令模式
引言 当遇到发送者和接受者之间不是直接连接关系,而是间接连接关系,即发送者和接受者之间需要解耦,我们通常需要命令模式。比如电灯和开关,开关设计时并不知道自己是控制电灯的,也可能控制排气扇、电力设备等等&#x…...
Debian 安装 Nextcloud 使用 MariaDB 数据库 + Caddy + PHP-FPM
前言 之前通过 docker在ubuntu上安装Nextcloud,但是现在我使用PVE安装Debian虚拟机,不想通过docker安装了。下面开始折腾。 安装过程 步骤 1:更新系统并安装必要的软件 sudo apt update && sudo apt upgrade -y sudo apt install…...
string 与 wstring 的字符编码
测试代码: #include<stdio.h> #include<stdlib.h> #include<windows.h> #include <locale.h> #include <string> #include <iostream>// 函数用于计算UTF-8字符串中的字符数 int utf8_strlen(const char* str) {int len = 0;for (; *s…...
golang 开启HTTP代理认证
内部网路不能直接访问外网接口,可以通过代理发送HTTP请求。 HTTP代理服务需要进行认证。 package cmdimport ("fmt""io/ioutil""log""net/http""net/url""strings" )// 推送CBC07功能 func main() {l…...
第九届华为ICT大赛实践赛中国总决赛举行通知及考试地址
经大赛组委会决定,第九届华为ICT大赛实践赛中国总决赛将于2025年3月8日-9日举行具体赛事安排如下,期待与您顶峰相见! 理论考试:线上答题,团队3名成员共同完成1套试题,统一提交一份答案【60分钟,20道试题(含判断、单选…...
FFmpeg 与 FFplay 参数详解:-f、-pix_fmt、-pixel_format 和 -video_size 的区别与用法
FFmpeg 与 FFplay 参数详解:-f、-pix_fmt、-pixel_format 和 -video_size 的区别与用法 在使用 FFmpeg 和 FFplay 进行视频处理和播放时,-f、-pix_fmt、-pixel_format 和 -video_size 是常用的参数。这些参数的作用和使用场景略有不同,理解它们的区别和用法对于正确处理和播…...
深入理解 C++17 std::is_swappable
文章目录 深入理解 C17 std::is_swappable引言std::is_swappable 概述std::is_swappable 的工作原理std::is_swappable 的变体注意事项结论 深入理解 C17 std::is_swappable 引言 在 C 编程中,交换两个对象的值是一个常见的操作。为了确保代码的通用性和安全性&am…...
直接插入排序
一:直接插入排序是什么。 二:如何实现直接插入排序 三:直接插入排序时间复杂度 一:直接插入排序它是排序得一种,其目的无非是将乱序通过排序排成有序的。 我们可以通过动画直观看什么是直接插入排序 这是我找的直接…...
基于可信数据空间的企业数据要素与流通体系建设(附ppt 下载)
近期,可信数据空间会议召开。大数据系统软件国家工程研究中心总工程师王晨发表了题为《基于可信数据空间的企业数据要素与流通体系建设》主旨演讲。 WeChat Subscription Account【智慧城市指北】,可搜索相关关键字“20250107”,可获取具体获…...
处理 this
this指向改变this this指向 构造函数和原型对象都指向 实例 改变this指向的三个方法: call()apply()bind() call() apply() 与call的区别就是call中参数任意,但是apply中参数必须是数组 bind()(最重要) 与…...
kafka服务端之日志存储
文章目录 日志布局日志索引日志清理日志删除基于时间基千日志大小基于日志起始偏移量 日志压缩总结 日志布局 Ka饮a 中的消息是以主题为基本单位进行归类的, 各个主题在逻辑 上相互独立。 每个主题又可以分为一个或多个分区, 分区的数量可以在主题创建的…...
【Apache Paimon】-- 15 -- 利用 paimon-flink-action 同步 postgresql 表数据
利用 Paimon Schema Evolution 核心特性同步变更的 postgresql 表结构和数据 1、背景信息 在Paimon 诞生以前,若 mysql/pg 等数据源的表结构发生变化时,我们有几种处理方式 (1)人工消息通知,然后手动同步到数据仓库中(2)使用 flink 消费 DDL binlog ,然后自动更新 Hi…...
正则表达式进阶(二)——零宽断言详解:\b \B \K \z \A
在正则表达式中,零宽断言是一种非常强大的工具,能够在不消费字符的情况下对匹配位置进行约束。除了环视(lookahead 和 lookbehind)以外,还有一些常用的零宽断言,它们用于处理边界、字符串的开头和结尾等特殊…...
java poi Excel 文件导入导出常见错误及解决方案
在使用 Apache POI 进行 Excel 文件的导入导出操作时,可能会遇到各种问题。以下是一些常见的错误及其解决方案: 一、文件格式相关问题 1. 文件格式不兼容 问题描述:尝试使用 HSSFWorkbook 读取 .xlsx 文件,或者使用 XSSFWorkbo…...
批量提取word表格数据到一个excel
新建一个excel到word同级目录altf11打开vba窗口并新建模块粘贴下方代码(修改一些必要参数)回到excel表格界面,altf8选择执行该宏注意要在信任中心开启运行vba宏 Sub 批量提取word表格数据到excel()Dim wdApp As Object, wdDoc As ObjectDim …...
快速建立私有化知识库(私有化训练DeepSeek,通过ollama方式)
简介 什么?!老是有人问你需求,不同版本的需求你记不清还得去扒拉过程文档、设计文档? 什么?!领导会询问功能使用情况、用户相关数据,你每次还得手动查询反馈? 什么?&…...
python 一句话打印行号
在C语言中,打印行号可以直接用预定义的宏__LINE__,打印当前行号,方便调试。 printf("%d", __LINE__); // C语言打印当前行号 python中没有这样的预定义宏。 但可以用这种方式,实现一句话打印行号: impor…...
设计模式-生产者消费者模型
阻塞队列: 在介绍生产消费者模型之前,我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列,常用于生产者消费者模型,它提供了线程安全的队列操作,并且在队列为空或满时,能够阻塞等待,…...