导图社区 Kubernates概念辨析
这是一篇关于Kubernates概念辨析的思维导图,主要内容包括:PV PVC,ConfigMap,Service,StatefulSet,Doployment,Pod,资料。
编辑于2025-02-09 20:31:02Kubernates概念辨析
资料
关于我
深圳某厂 Java 后端开发,4年开发经验。 致力于高效学习和总结知识图谱。
扣丁狼资料
讲师:刘刚 bilibili:https://www.bilibili.com/video/BV1MT411x7GH
Pod
最小化配置
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: nginx:1.21.6 解释: spec: Specification,表示资源的“规格”或者“详细配置”。 metadata.name: pod的名称,用于service headless路由。 spec.containers.name: 容器名称,因为一个pod可以放多个容器。
常用配置
apiVersion: v1 kind: Pod metadata: name: my-pod namespace: default labels: app: my-app spec: restartPolicy: Always containers: - name: my-container image: nginx:1.21.6 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" volumeMounts: - name: my-volume mountPath: /usr/share/nginx/html volumes: - name: my-volume emptyDir: {} nodeSelector: disktype: ssd
Doployment
最小化配置
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 1 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx:1.21.6
小结
解释: spec.template: 里面其实就是Pod的配置. Q: Deployment是如何管理pod的? 通过selector和template.metadata.labels来标识和管理Pod,而不是Pod的名称。所以这两个值必须要一致。 Q: 为什么Deployment的spec.template.metadata.name不是必填的? 单独配置 Pod 时,metadata.name是必填的,因为单独配置是不会自动生成 Pod 的名字。但是在Deployment创建pod时,会根据Deployment的名称+随机字符串为 Pod 自动生成唯一的名称。比如`my-deployment-5f4b8d9c7b-xyz12`.所以可以不指定。 有用的知识: k8s整体上是通过label来关联资源和管理调度的。
常用配置
--- # ConfigMap 定义 apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: default data: # 模拟配置文件内容 config.properties: | app.name=MyApp app.version=1.0.0 # 用于环境变量的键值对 ENVIRONMENT: production --- # Deployment 定义 apiVersion: apps/v1 kind: Deployment metadata: name: configmap-deployment namespace: default labels: app: configmap-demo spec: replicas: 2 selector: matchLabels: app: configmap-demo template: metadata: labels: app: configmap-demo spec: containers: - name: app-container image: nginx:1.21.6 volumeMounts: # 挂载 ConfigMap 中的配置文件为容器内的文件 - name: config-volume mountPath: /etc/app-config readOnly: true env: # 将 ConfigMap 的键值对注入为环境变量 - name: ENVIRONMENT valueFrom: configMapKeyRef: name: app-config key: ENVIRONMENT volumes: - name: config-volume configMap: name: app-config
小结
StatefulSet
最小化配置
apiVersion: apps/v1 kind: StatefulSet metadata: name: minimal-statefulset spec: replicas: 2 selector: matchLabels: app: minimal-app serviceName: minimal-service template: metadata: labels: app: minimal-app spec: containers: - name: minimal-container image: nginx:1.21.6 ports: - containerPort: 80 Q: metadata.name和spec.serviceName有什么区别? metadata.name用于应用在指定生成pod名称的前缀。比如pod的名称为minimal-statefulset-xfdafsdfa spec.serviceName:为有状态应用的Pod提供唯一的dns标识。比如稳定的dns标识为minimal-service-0。 Q: Deployment和StatefulSet的核心区别是什么? Deployment是为了无状态应用启动的控制器。(无状态应用主要指不需要存储的应用,如后端服务),所以可以并发启动(一次性启动好几个)。 StatefulSet是为了有状态应用启动的控制器。(有状态应用主要指需要存储数据的应用,而需要存储数据的应用就涉及不用应用之间的数据同步。,如mysql、redis、kafka)StatefulSet最主要的区别是按照顺序从小到大启动,回滚时从大到小回滚。也就是不能并发启动和回滚(默认规则)。当然你也可以允许并发启动。 比如默认规则下:statefulSet永远会先启动inimal-service-0这个pod,在inimal-service-0的就绪探针返回真,才会启动inimal-service-1。
常用配置
apiVersion: apps/v1 kind: StatefulSet metadata: name: my-statefulset spec: serviceName: "my-headless-service" replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: my-image:latest ports: - containerPort: 8080 resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1" volumeMounts: - name: data-volume mountPath: /data terminationGracePeriodSeconds: 30 volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi updateStrategy: type: RollingUpdate rollingUpdate: partition: 1 podManagementPolicy: OrderedReady --- apiVersion: v1 kind: Service metadata: name: my-headless-service spec: clusterIP: None selector: app: my-app ports: - port: 8080 targetPort: 8080 --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-pdb spec: minAvailable: 2 # 至少保证 2 个 Pod 是可用的 selector: matchLabels: app: my-app # 与 StatefulSet 的标签选择器匹配 --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-pdb spec: minAvailable: 2 selector: matchLabels: app: my-app
小结
Q: 规定启动和回滚顺序就能让mysql实现主从数据同步了? 当然不是,主从数据同步是需要我们额外编写代码实现的。 假设我们需要实现一主一从的mysql。业界通用是mysql-servcie-0是主节点,mysql-service-1是从节点。是因为我们在pod的启动命名和初始化容器时写了逻辑主从逻辑。 在启动命令中,可以拿到自己的是serviceName名称是mysql-servcie-0。然后类似写个if(serviceName == mysql-servcie-0){启动,初始化} else{从主节点拷贝数据逻辑;启动一个进程一直同步主节点数据}等。 Q:sts支持的启动和删除策略是什么? spec.podManagementPolicy: OrderedReady(顺序启动就绪)、Parallel(并行) Q: sts支持的更新策略都有什么? 通过spec.updateStrategy指定策略。支持“RollingUpdate”和“OnDelete”两种策略。 Q: sts的默认的策略顺序是? RollingUpdate。滚动更新策略。 举例:(默认策略) spec.replicas: 3 spec.podManagementPolicy: OrderedReady spec.updateStrategy: type: RollingUpdate partition: 0 含义:按照顺序启动三个副本,假设为pod-0,pod-1,pod-2。 启动顺序:pod-0启且就绪探针ok,pod-1启动且就绪探针ok... 删除顺序:删除pod-2,删除pod-1,删除pod-0 更新顺序: 先更新第0个且就绪之后;更新第1个且就绪之后,更新第2个且就绪 spec.replicas: 3 spec.podManagementPolicy: OrderedReady spec.updateStrategy: type: RollingUpdate partition: 1 含义:含义:按照顺序启动三个副本,假设为pod-0,pod-1,pod-2。 partition=1 控制的是从哪个位置开始更新和删除 Pods。大于等于1的会被更新,小于1的保持旧版本。 启动顺序:pod-0启且就绪探针ok,pod-1启动且就绪探针ok,pod-2启动且就绪探针ok 删除顺序:删除pod-2,删除pod-1,pod-0不会自动删除,只能管理员手动删除。 更新策略:先更新第1pod就绪,在更新第二个pod。第0个需要管理员手动更新。 Ondelete: 管理员手动删除旧pod,才会启动新pod。用于完全控制更新顺序。 Q:volumeClaimTemplates的作用? StatefulSet独有的配置,用于为每个pod动态创建独立的pvc。如果没有storageClass,则需要先手动创建pv. Q: volumeClaimTemplates 和 persistentVolumeClaim 的区别是什么? volumeClaimTemplates是sts独有配置,为每个sts pod创建相互隔离的pvc. persistentVolumeClaim 是pod的volumes类型,需要预先创建pvc。可以手动挂载给不同的pod实现数共享。
Service
最小化配置
apiVersion: v1 kind: Service metadata: name: my-service spec: ports: - port: 80 selector: app: my-app Q:Service的作用是什么? Service给一组pod提供统一的路由访问地址和负载均衡。作用类似于Nacos的注册中心。因为pod可能因为经常重启而变换ip. Q:spec.selector 匹配的标签是 Deployment 的还是 Pod 的? 当然是pod里的标签。因为是给一组pod提供稳定的dns访问地址。 也就是deployment配置的spec.template.metadata.labels
常用配置
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: my-app ports: - port: 80 targetPort: 8080 nodePort: 30080 # 服务暴露的节点端口 type: NodePort
小结
Q:spec.type有哪些类型? ClusterIP:默认策略,只支持在集群内部访问,比如pod与pod之间。pod调用service地址。 NodePort: 节点访问,可以通过宿主机节点+端口访问到Service,Service负载均衡到pod. NodePort相对于ClusterIP的区别在于多了从宿主机访问的能力,即能够访问宿主机,就能访问到pod. Q:ports的 port targetPort nodePort的区别? port: Service自己也作为独立的服务(想象的Nacos自己的端口) targetPort: 目标服务的端口,也就是pod中容器的端口。 nodePort:宿主机暴露的端口,建议在30000-32767 路由是有nodePort转发到port,再到targetPort. Q: 什么是headless-service? headless Service 一般与Statefulset 服务一起使用。用来给sts应用的每个pod提供稳定的DNS路由。 不进行负载均衡,而是给每个pod提供稳定的dns域名 路由拼接规则: <pod-name>.<service-name>.<namespace>.svc.cluster.local myapp1-0.my-headless-service.default.svc.cluster.local Q:service的域名补全机制? 假设user-pod1服务需要调用mysql服务。 user-pod1 位于 testa命名空间下。 mysql-0 位于testb命名空间下,service服务名为mysql-headless-service。 则调用mysql-0的域名: 1. 短连接 mysql-0.mysql-headless-service :默认会补全为当前pod所在的命名空间,即为mysql-0.mysql-headless-service.testa.svc.cluster.local,无法找到。 2. 跨命名空间: mysql-0.mysql-headless-service.testb: 正确调用 3.写完整路径: mysql-0.mysql-headless-service.testa.svc.cluster.local .svc 表示service的缩写,表示是服务路由。 .cluster.local k8s集群统一后缀 Q:mysql-0.mysql-headless-service.testa.svc.cluster.local. 最后加个点是什么意思? 表示完全限定dns路由,k8s不会尝试继续拼接后缀解析。
headless service
apiVersion: v1 kind: Service metadata: name: my-headless-service # Headless Service 名称 spec: clusterIP: None # 关键配置,表示这是一个 Headless Service selector: app: myapp ports: - port: 8080 targetPort: 8080 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp1 spec: serviceName: "my-headless-service" # 绑定 Headless Service replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp image: myapp-image
ConfigMap
最小化配置
apiVersion: v1 kind: ConfigMap metadata: name: my-config data: key: value Q:如何通过命名行创建? kubectl create configmap my-config --from-literal=key=value
常用配置
apiVersion: v1 kind: ConfigMap metadata: name: my-config data: APP_MODE: "production" DB_HOST: "mysql-service" DB_PORT: "3306" config.json: | { "app_name": "MyApp", "log_level": "debug" } --- apiVersion: v1 kind: Pod metadata: name: pod-env spec: containers: - name: my-container image: busybox command: ["sh", "-c", "echo DB_HOST=$DB_HOST && echo APP_MODE=$APP_MODE"] envFrom: - configMapRef: name: my-config # 引用 ConfigMap 中的所有键值对 env: - name: DB_PORT valueFrom: configMapKeyRef: name: my-config key: DB_PORT # 只挂载 `DB_PORT` --- apiVersion: v1 kind: Pod metadata: name: pod-file spec: containers: - name: my-container image: busybox command: ["sh", "-c", "cat /etc/config/DB_HOST && cat /etc/config/config.json"] volumeMounts: - name: config-volume mountPath: "/etc/config" # 挂载目录 volumes: - name: config-volume configMap: name: my-config
小结
Q:configMap作为文件挂载和环境变量挂载的区别? 用于管理配置文件和环境变量。可以把配置文件写在ConfigMap中,再挂载到环境变量中。 用于把文件或者环境变量添加到容器中。 当挂载为环境变量时:需要时key-value形式。否则可能破坏环境变量格式。 当是文件时: key为文件名,value为文件内容。 yaml中的 > |- 用来接下来多行文本,处理多余字符串的。
PV PVC
pv
pvc