xuanyuanaosheng / xuanyuanaosheng.github.io

个人网站:灵梦缘
https://xuanyuanaosheng.github.io/
2 stars 0 forks source link

K8S集群管理员基础知识 #18

Open xuanyuanaosheng opened 1 month ago

xuanyuanaosheng commented 1 month ago

1. Kubernetes 基础知识

Q1: 什么是Kubernetes?Kubernetes主要解决了哪些问题?

回答要点

Q2: 描述一下Kubernetes中的主要组件及其作用?

回答要点

Q3: 什么是Pod?为什么Pod是Kubernetes的基础单位?

回答要点

Q4: 什么是ReplicaSet,Deployment与StatefulSet之间的区别?

回答要点

Q5: ConfigMap和Secret有什么区别?

回答要点


2. 集群管理

Q6: 描述一下Kubernetes的调度策略。

回答要点

Q7: 什么是Taints和Tolerations?

回答要点

Q8: 如何在Kubernetes中进行滚动更新和回滚?

回答要点

Q9: Kubernetes中的Service有哪几种类型?分别有什么作用?

回答要点

Q10: 如何对K8S集群进行自动伸缩(Horizontal Pod Autoscaling, HPA)?

回答要点


3. 高级主题

Q11: 在Kubernetes中,如何管理存储?PersistentVolume和PersistentVolumeClaim有什么作用?

回答要点

Q12: 如何在Kubernetes中实现安全性?如何进行网络隔离?

回答要点

Q13: 什么是Kubernetes的Ingress?如何配置HTTPS的Ingress?

回答要点

Q14: Helm是什么?它是如何工作的?

回答要点

Q15: 如何备份和恢复Kubernetes集群中的etcd数据?

回答要点


4. Kubernetes故障排查与优化

Q16: 当Pod状态为CrashLoopBackOff时,如何进行故障排查?

回答要点

Q17: 如何监控Kubernetes集群的运行状况?

回答要点

Q18: 如何管理多个Kubernetes集群?

回答要点

Q19: 你如何优化Kubernetes集群的性能?

回答要点

Q20: 如何在Kubernetes中进行日志收集和集中管理?

回答要点

xuanyuanaosheng commented 1 month ago

怎样在命令行下管理多个K8S集群

在命令行下管理多个 Kubernetes 集群,通常使用 kubectl 工具结合 Kubernetes 的 kubeconfig 文件。以下是管理多个 Kubernetes 集群的基本步骤和技巧:

1. 配置 kubeconfig

Kubernetes 使用 kubeconfig 文件来存储集群的配置信息。您可以在一个 kubeconfig 文件中配置多个集群和用户。

创建/更新 kubeconfig 文件

  1. 合并多个 kubeconfig 文件:

    如果您已经有多个集群的 kubeconfig 文件,可以使用以下命令合并它们:

    KUBECONFIG=~/.kube/config:~/.kube/other-config kubectl config view --merge --flatten > ~/.kube/merged-config

    然后,您可以使用合并后的配置文件:

    export KUBECONFIG=~/.kube/merged-config
  2. 手动添加集群配置:

    您可以通过以下命令手动添加集群和上下文配置:

    kubectl config set-cluster CLUSTER_NAME --server=https://your-cluster-api-server --certificate-authority=/path/to/ca.crt
    kubectl config set-credentials USER_NAME --token=YOUR_TOKEN
    kubectl config set-context CONTEXT_NAME --cluster=CLUSTER_NAME --user=USER_NAME
  3. 选择上下文:

    kubeconfig 文件中,您可以定义多个上下文(contexts),每个上下文代表一个集群、用户和命名空间的组合。您可以使用以下命令查看当前上下文和所有上下文:

    kubectl config current-context
    kubectl config get-contexts

    切换到另一个上下文:

    kubectl config use-context CONTEXT_NAME

2. 使用命令行管理集群

一旦配置好 kubeconfig 文件,您就可以使用 kubectl 命令管理不同的集群。以下是一些常见的命令示例:

3. 使用环境变量管理 KUBECONFIG

如果您经常需要在多个集群之间切换,可以通过设置 KUBECONFIG 环境变量来简化流程。例如:

export KUBECONFIG=~/.kube/config:~/.kube/other-config

这允许您一次性访问多个集群的配置。

4. 使用工具

还有一些工具可以帮助管理多个 Kubernetes 集群:

5. 结论

通过配置 kubeconfig 文件和使用 kubectl 命令,您可以方便地在命令行中管理多个 Kubernetes 集群。结合使用工具如 kubectx 可以进一步简化管理流程。

xuanyuanaosheng commented 1 month ago

在K8S中怎样使用RBAC来控制一个用户能的操作的权限?

在 Kubernetes (K8S) 中,用户(User)用户组(Group) 的管理不是通过 Kubernetes 自身来进行的,而是通过外部认证机制来管理的。Kubernetes 集群通常不会直接管理用户和组的创建、删除或管理,而是通过 认证(Authentication)授权(Authorization) 来控制用户的权限和访问操作。

然而,我们可以通过以下方式实现用户和用户组的管理和权限控制:

  1. 使用外部认证系统:如 OIDC、LDAP、证书等,管理用户。
  2. 通过 RBAC 配置用户权限:使用 Kubernetes 的 RBAC(Role-Based Access Control)机制来配置用户和用户组的权限。

在 Kubernetes (K8S) 中,RBAC(Role-Based Access Control,基于角色的访问控制)允许你通过角色和绑定来精确地控制用户和服务账户在集群中的权限。你可以通过定义不同的 RoleClusterRole 来控制用户能够执行的操作,以及通过 RoleBindingClusterRoleBinding 来将这些角色分配给用户。

基本概念

RBAC 控制权限的基本步骤

1. 创建 RoleClusterRole

Role 适用于某个 Namespace 内的资源控制,而 ClusterRole 则适用于集群范围内的控制。我们先来看如何创建一个 Role

示例:创建一个 Role,只允许用户在 dev-namespace 中管理 Pods
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev-namespace
  name: pod-manager
rules:
- apiGroups: [""]  # "" 代表核心 API 组,用于控制像 Pod 这样的基本资源
  resources: ["pods"]
  verbs: ["create", "delete", "get", "list", "watch", "update"]
创建 Role:
kubectl apply -f pod-manager-role.yaml

2. 创建 RoleBindingClusterRoleBinding

你需要创建一个 RoleBindingClusterRoleBinding,将刚刚创建的 Role 绑定到一个用户或组上。

示例:将 pod-manager Role 绑定到一个用户 user1
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-manager-binding
  namespace: dev-namespace
subjects:
- kind: User  # 这里可以是 User, Group, 或 ServiceAccount
  name: user1  # 绑定的用户名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role  # 绑定的角色是 Role
  name: pod-manager  # Role 的名称
  apiGroup: rbac.authorization.k8s.io
创建 RoleBinding:
kubectl apply -f pod-manager-binding.yaml

3. 使用 ClusterRoleClusterRoleBinding 进行集群范围的权限控制

如果你希望在集群范围内进行权限控制,可以使用 ClusterRoleClusterRoleBindingClusterRole 还可以用来控制某些特定非命名空间资源(如节点、命名空间、持久卷等)。

示例:创建一个 ClusterRole,允许用户查看所有命名空间中的 Pods
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: view-pods
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
创建 ClusterRole:
kubectl apply -f view-pods-clusterrole.yaml
将 ClusterRole 绑定到一个用户 user2
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: view-pods-binding
subjects:
- kind: User
  name: user2
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view-pods
  apiGroup: rbac.authorization.k8s.io
创建 ClusterRoleBinding:
kubectl apply -f view-pods-binding.yaml

4. 验证用户权限

在绑定角色后,用户应该只能执行他们所被允许的操作。你可以使用 kubectl auth can-i 命令来验证某个用户是否有执行某些操作的权限。

kubectl auth can-i create pods --as=user1 --namespace=dev-namespace
kubectl auth can-i get pods --as=user2 --namespace=default

总结

通过 RBAC,你可以灵活控制用户或组对 Kubernetes 资源的访问权限。以下是配置 RBAC 的主要步骤:

  1. 定义 Role 或 ClusterRole: 通过 RoleClusterRole 来定义某个命名空间或集群范围内的访问权限。
  2. RoleBinding 或 ClusterRoleBinding: 使用 RoleBindingClusterRoleBinding 将用户或组与相应的 RoleClusterRole 绑定。
  3. 验证用户权限: 使用 kubectl auth can-i 验证用户的权限。

通过这种方式,你可以为不同角色和用户设置不同的权限,从而确保 Kubernetes 集群的安全性。


在 Kubernetes 中,您可以通过 kubectl auth can-i 命令查看某个账户在集群中的资源权限。该命令用于检查某个用户是否有权执行特定的操作。下面是一些具体的使用方式:

1. 查看当前用户的权限

kubectl auth can-i <verb> <resource> --namespace=<namespace>

示例:

# 查看当前用户是否可以获取 pods 资源
kubectl auth can-i get pods

# 查看当前用户是否可以删除 services 资源
kubectl auth can-i delete services --namespace=my-namespace

2. 查看某个用户的权限

通过指定 --as 选项,您可以模拟某个用户来查看他们的权限。

kubectl auth can-i <verb> <resource> --namespace=<namespace> --as=<username>

示例:

# 查看名为 "user123" 的用户是否可以创建 deployments 资源
kubectl auth can-i create deployments --as=user123

# 查看 "user123" 是否可以在 "prod" 命名空间中删除 pods
kubectl auth can-i delete pods --namespace=prod --as=user123

3. 查看所有资源权限

如果您想查看用户在命名空间中的所有资源权限,可以使用以下命令列出用户可以进行的所有操作:

kubectl auth can-i --list --namespace=<namespace> --as=<username>

示例:

# 查看当前用户在 "default" 命名空间的所有权限
kubectl auth can-i --list

# 查看名为 "user123" 的用户在 "dev" 命名空间的所有权限
kubectl auth can-i --list --namespace=dev --as=user123

4. 通过 RoleBinding 和 ClusterRoleBinding 查看权限

如果您想了解某个用户或者服务账户绑定了哪些角色,您可以查看相关的 RoleBindingClusterRoleBinding

查看 ClusterRoleBindings:

kubectl get clusterrolebindings --field-selector subjects.kind=User,subjects.name=<username> -o yaml

查看 RoleBindings:

kubectl get rolebindings --namespace=<namespace> --field-selector subjects.kind=User,subjects.name=<username> -o yaml

示例:

# 查看 user123 绑定的 ClusterRoleBinding
kubectl get clusterrolebindings --field-selector subjects.kind=User,subjects.name=user123 -o yaml

# 查看 user123 在 "dev" 命名空间中绑定的 RoleBinding
kubectl get rolebindings --namespace=dev --field-selector subjects.kind=User,subjects.name=user123 -o yaml

5. 查看某个 ServiceAccount 的权限

对于 ServiceAccount,您可以通过以下命令查看权限:

kubectl auth can-i --as=system:serviceaccount:<namespace>:<serviceaccount> <verb> <resource>

示例:

# 查看 default 命名空间中的 my-serviceaccount 是否可以创建 pods
kubectl auth can-i create pods --as=system:serviceaccount:default:my-serviceaccount

总结

xuanyuanaosheng commented 1 month ago

在K8S中怎样调度GPU资源?

在 Kubernetes (K8S) 中,调度和使用 GPU 资源需要做一些配置,涉及 GPU 驱动、设备插件以及指定资源请求等。以下是调度 GPU 资源的具体步骤:

image

1. 准备 GPU 节点

要调度 GPU 资源,首先需要确保在 Kubernetes 集群中的节点具备 GPU,并安装了相应的驱动程序。

1.1 安装 NVIDIA 驱动程序

如果使用 NVIDIA GPU,首先需要在节点上安装 NVIDIA GPU 驱动程序。

在大多数情况下,你可以按照以下步骤安装 NVIDIA 驱动:

# 1. 添加 NVIDIA repository
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# 2. 安装 NVIDIA 驱动
sudo apt-get update
sudo apt-get install -y nvidia-driver-470

根据你的系统类型(例如 Ubuntu 或 CentOS),可能需要调整安装过程。如果在云平台(如 AWS、GCP 等)使用 GPU 节点,通常系统会预装必要的驱动。

1.2 安装 NVIDIA Docker 和设备插件

接下来,你需要为 Docker 安装 nvidia-docker 来管理 GPU 资源。

# 安装 nvidia-container-toolkit
sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

Kubernetes GPU 调度依赖于 NVIDIA 的 NVIDIA Kubernetes Device Plugin,用于暴露 GPU 设备给 Kubernetes。接下来我们来安装这个插件。

2. 部署 NVIDIA Device Plugin

NVIDIA 提供了一个设备插件(device plugin)用于管理 GPU。通过这个插件,Kubernetes 可以自动发现并调度 GPU 资源。

2.1 部署设备插件

使用 kubectl apply 来部署 NVIDIA 设备插件:

kubectl apply -f https://github.com/NVIDIA/k8s-device-plugin/raw/main/nvidia-device-plugin.yml

这个插件会在每个拥有 GPU 的节点上运行,并将 GPU 资源报告给 Kubernetes。部署完成后,你可以通过以下命令来验证设备插件是否正常运行:

## DaemonSet
kubectl get ds -n kube-system

查看 nvidia-device-plugin 的状态,确保设备插件已经正常部署到所有 GPU 节点上。

3. 检查 GPU 资源

部署 NVIDIA 设备插件后,Kubernetes 将自动检测节点上的 GPU 并将其作为资源。你可以通过以下命令检查 GPU 资源是否可用:

kubectl describe nodes | grep -A 5 "Capacity"

在输出中,你应该能看到类似如下的 GPU 资源:

nvidia.com/gpu:  1

这表示该节点上有 1 个 NVIDIA GPU 可供调度。

4. 使用 GPU 资源的 Pod 配置

在创建需要使用 GPU 的 Pod 时,可以在 spec 中指定 GPU 资源请求。下面是一个示例,演示如何请求使用 1 个 GPU 的 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
  - name: gpu-container
    image: nvidia/cuda:10.0-base
    resources:
      limits:
        nvidia.com/gpu: 1  # 请求 1 个 GPU
    command: ["nvidia-smi"]

在这个 Pod 配置中,nvidia.com/gpu: 1 表示请求 1 个 GPU 资源。可以根据实际需要调整请求的 GPU 数量。

5. 部署 GPU 作业

使用 kubectl apply 命令部署 Pod:

kubectl apply -f gpu-pod.yaml

你可以通过 kubectl logs 命令查看容器日志,确认 GPU 是否正常工作:

kubectl logs gpu-pod

例如,使用 nvidia/cuda 镜像并执行 nvidia-smi 命令可以查看 GPU 的工作状态。

6. 为工作负载调度 GPU 资源

在 K8S 集群中,GPU 是作为一种 可限制的资源 来管理的,类似于 CPU 和内存。当你定义工作负载(如 Pod、Deployment 等)时,可以在 resources 字段下设置对 GPU 资源的请求和限制。

resources:
  limits:
    nvidia.com/gpu: 1  # 限制容器最多使用 1 个 GPU

Kubernetes 通过设备插件自动发现并分配 GPU 资源,调度器根据这些资源请求为 Pod 安排 GPU 节点。如果节点上没有可用的 GPU,Pod 将处于 Pending 状态,直到有 GPU 可用。

7. 验证 GPU 调度

你可以通过以下命令查看 Pod 是否成功调度到 GPU 节点上:

kubectl get pods -o wide

查看 Pod 所在节点,并确认该节点上是否有 GPU。

总结

调度 GPU 资源的关键步骤包括:

  1. 安装 GPU 驱动程序:在拥有 GPU 的节点上安装 GPU 驱动。
  2. 部署 NVIDIA 设备插件:通过 nvidia/k8s-device-plugin 来将 GPU 资源暴露给 Kubernetes。
  3. 为 Pod 分配 GPU 资源:在工作负载配置中请求 GPU 资源。
  4. 验证 GPU 调度:确认 Pod 被调度到具有 GPU 的节点上,并使用 GPU 资源。

通过以上步骤,您可以在 Kubernetes 集群中高效地调度和管理 GPU 资源,支持需要 GPU 加速的计算任务(如深度学习、图像处理等)。

参考文档

xuanyuanaosheng commented 1 month ago

K8S网络插件

Kubernetes(K8S)的网络插件用于管理和配置集群中的网络通信,确保Pod之间以及Pod与外部服务之间的连接。Kubernetes本身提供了基本的网络模型,但具体的网络实现是通过插件来完成的。网络插件一般遵循CNI(Container Network Interface)标准,并为集群提供了不同的功能和特性,如网络隔离、服务发现、负载均衡等。


总结

Kubernetes中的网络插件非常多样,选择合适的插件取决于具体的需求,如性能、易用性、安全性、网络策略支持等。以下是常见场景下的推荐插件:

选择适合的网络插件可以帮助提高集群的性能、灵活性和安全性。

以下是常见的Kubernetes网络插件及其介绍:


1. Flannel

Flannel 是最简单、最常见的Kubernetes网络插件之一,专注于为Kubernetes集群中的每个节点提供IP地址空间。

适用场景:适用于对网络要求不高的场景,尤其是开发或测试环境。


2. Calico

Calico 是一个功能强大的网络插件,提供IP数据包路由和网络策略控制,支持大规模Kubernetes集群。

适用场景:适用于对网络安全、性能和可扩展性要求较高的场景,尤其是生产环境。


3. Weave Net

Weave Net 是一个简单易用的Kubernetes网络插件,支持网络隔离和加密功能。

适用场景:适用于中小规模集群,尤其是对安全性和易用性有要求的环境。


4. Cilium

Cilium 是一个基于eBPF(Extended Berkeley Packet Filter)的网络插件,专注于提供安全性和可观察性,尤其适用于微服务架构。

适用场景:适用于微服务架构、云原生应用以及对网络安全和监控有较高要求的场景。


5. Canal

Canal 是Calico和Flannel的结合体,兼具两者的优点,提供了网络策略支持和简化的配置。

适用场景:适合需要网络策略但又想要保持简单配置的场景。


6. Kube-Router

Kube-Router 是一个Kubernetes网络插件,专注于提供高效的网络转发、网络策略和负载均衡功能。

适用场景:适合对网络性能要求较高的场景,尤其是需要复杂路由和负载均衡的场景。


7. Multus

Multus 是一个多网络插件,允许在Kubernetes中为Pod分配多个网络接口。

适用场景:适合需要多网络接口或多CNI插件的复杂网络环境。


8. Open vSwitch (OVS) + OVN (Open Virtual Network)

OVS + OVN 是一个强大的网络解决方案,基于Open vSwitch的虚拟交换技术。

适用场景:适合需要复杂虚拟网络架构的场景,如企业数据中心或云计算环境。


以K8S里面的Calico网络插件为例,详细讲解下Gitlab各组件之间的网络通信

在一个典型的Kubernetes (K8S) 集群中,网络插件(如Calico)为容器提供了跨节点的网络通信能力。将GitLab部署在K8S上时,不同组件之间的通信必须依赖于K8S的网络模型和插件来实现。

下面我将以Calico网络插件为例,详细讲解GitLab各个组件在K8S中如何进行网络通信。

1. K8S 网络模型与Calico插件的作用

Kubernetes中的每个Pod都通过网络插件(例如Calico)拥有一个独立的IP地址,这使得不同Pod之间的通信能够像同一个虚拟网络中设备的通信一样。

2. GitLab的各个组件与K8S中的部署

GitLab通常由多个独立的服务组件组成,常见的GitLab服务组件包括:

在K8S中,这些组件通常被分别部署为多个Pod,运行在不同的节点上。

3. GitLab各组件之间的通信需求

在K8S集群中,GitLab的不同组件通过服务发现和网络层进行通信。这些组件之间的通信需求包括:

4. Calico如何保障各组件之间的通信

通过Calico网络插件,每个Pod都有一个唯一的IP地址,这意味着GitLab的各个Pod可以通过IP地址和K8S的DNS服务相互发现和通信。

4.1 Pod与Pod之间的通信

Calico通过路由机制和BGP协议保证跨节点的Pod间通信。无论GitLab的不同组件运行在哪个节点,它们都可以通过Pod IP直接通信。通信的方式可以是:

4.2 服务发现与DNS解析

K8S的服务发现机制通过内部的CoreDNS服务,允许Pod使用服务名称来解析到其他服务的IP。例如,GitLab Web Service Pod可以通过名称gitlab-postgresql找到PostgreSQL数据库Pod的IP地址。

Calico确保所有Pod都可以在整个集群内通过IP和DNS解析来找到彼此,从而实现GitLab各组件之间的通信。

4.3 网络策略与访问控制

Calico不仅提供了网络连接能力,还支持定义网络策略(NetworkPolicy)来控制哪些Pod或服务能够访问特定的GitLab组件。这可以用来加强GitLab部署的安全性。

例如,可以通过Calico的网络策略实现以下访问控制:

通过这些策略,Calico可以有效控制GitLab各个组件之间的通信,确保其在安全和性能上得到保证。

5. GitLab和外部网络的通信

6. GitLab的CI/CD与Runner的通信

GitLab Runner负责执行CI/CD任务,并需要与GitLab Web Service进行通信。这一过程通常涉及多种网络操作:

使用Calico,Runner Pod无论部署在哪个节点上,都可以通过DNS解析找到GitLab Web Service的地址,并通过Pod间通信机制访问该服务。

7. 网络通信示例

以下是一个GitLab各组件的网络通信示例:

总结

在K8S中部署GitLab时,Calico网络插件通过为每个Pod提供唯一的IP地址和跨节点通信能力,确保GitLab的各个组件可以正常通信。同时,借助Calico的网络策略,用户还可以加强GitLab各个服务之间的网络访问控制,提升集群的安全性。

通过这种方式,GitLab的各个服务组件(Web Service、PostgreSQL、Redis、Sidekiq、Runner等)可以通过K8S的网络模型高效地互相通信,同时保证整个集群的安全和性能。


下面以网络插件Calico为例,详细讲解下怎么定义网络策略来实现K8S内网络的详细控制

以Gitlab里面的组件为例 (下面的例子并未实际测试,默认通过Helm搭建的Gitlab也不知道有木有对应的网络策略控制,可以自己确认下),在 Kubernetes 中,Calico 是一个广泛使用的网络插件之一,它不仅提供容器间的网络通信功能,还支持网络策略(Network Policy),用于控制不同 Pod 之间的网络访问权限。通过 Calico 的网络策略,我们可以细粒度地定义哪些 Pod 或服务能够访问特定的 GitLab 组件。

1. 什么是网络策略 (Network Policy)?

网络策略(Network Policy)是 Kubernetes 提供的一种功能,允许管理员定义集群中不同 Pod 之间的网络通信规则。通过网络策略,你可以限制哪些 Pod 可以访问其他 Pod 或服务,或者限制 Pod 的出站访问权限。

Calico 作为一个强大的网络插件,扩展了 Kubernetes 的网络策略功能,支持更多的匹配选项和更复杂的规则。使用 Calico,你可以控制 Pod 的入站和出站流量。

网络策略的主要功能:

2. GitLab 组件的网络策略需求

在 GitLab 部署中,多个组件(如 GitLab Web ServiceGitLab RedisGitLab Runner 等)需要进行通信。为了确保安全性,你可能希望控制哪些 Pod 能够访问某些 GitLab 组件。

假设有以下 GitLab 组件:

需求可能包括:

3. Calico 网络策略的设置

为了实现这些访问控制,我们可以使用 Calico 定义的网络策略来限制哪些 Pod 或服务能够访问特定的 GitLab 组件。每个网络策略都是一个 Kubernetes 资源,用 YAML 文件进行定义。

3.1 网络策略结构

一个网络策略通常包括以下几部分:

3.2 示例策略:允许 GitLab Web Service 访问 GitLab Redis

下面是一个网络策略的示例,用于允许 gitlab-webservice Pod 访问 gitlab-redis Pod,同时禁止其他 Pod 访问 Redis。

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: allow-webservice-to-redis
  namespace: default # 假设所有 GitLab 组件都在 'default' namespace
spec:
  selector: app == 'gitlab-redis' # 选择 GitLab Redis Pod
  ingress:
    - action: Allow
      source:
        selector: app == 'gitlab-webservice' # 只允许 GitLab Web Service 访问 Redis
  egress:
    - action: Allow
      destination:
        selector: app == 'gitlab-webservice' # 允许 Redis 响应 Web Service 的请求
  types:
    - Ingress
    - Egress

解释:

3.3 示例策略:允许 GitLab Runner 访问 GitLab Web Service

接下来,我们定义一个策略,允许 GitLab Runner 访问 GitLab Web Service,但限制其他 Pod 的访问。

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: allow-runner-to-webservice
  namespace: default # 假设所有 GitLab 组件都在 'default' namespace
spec:
  selector: app == 'gitlab-webservice' # 选择 GitLab Web Service Pod
  ingress:
    - action: Allow
      source:
        selector: app == 'gitlab-runner' # 只允许 GitLab Runner 访问 Web Service
  egress:
    - action: Allow
      destination:
        selector: app == 'gitlab-runner' # 允许 Web Service 响应 Runner 的请求
  types:
    - Ingress
    - Egress

解释:

3.4 示例策略:阻止所有外部访问

如果你想限制所有外部流量,只允许内部组件互相通信,可以定义一条网络策略来阻止所有未授权的外部访问。比如,阻止对 GitLab Web Service 的任何外部访问:

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: deny-external-to-webservice
  namespace: default
spec:
  selector: app == 'gitlab-webservice'
  ingress:
    - action: Deny # 拒绝所有没有明确允许的流量
      source:
        notSelector: app in ('gitlab-runner', 'gitlab-redis') # 不允许来自 Runner 和 Redis 以外的流量
  types:
    - Ingress

解释:

4. Calico 网络策略的应用与排查

4.1 应用网络策略

将上述策略定义好之后,可以通过 kubectl apply 命令将其应用到 Kubernetes 集群:

kubectl apply -f allow-webservice-to-redis.yaml
kubectl apply -f allow-runner-to-webservice.yaml
kubectl apply -f deny-external-to-webservice.yaml

这将生效并影响相应的网络流量。

4.2 验证网络策略

你可以使用 kubectl exec 命令进入 Pod 并尝试访问其他 Pod 来验证网络策略是否生效。例如,尝试从 gitlab-runner Pod 中访问 gitlab-webservice

kubectl exec -it <gitlab-runner-pod> -- curl gitlab-webservice.default.svc.cluster.local

如果策略生效,应该能够访问 Web Service。

4.3 调试网络策略

如果你发现某些 Pod 无法访问预期的服务,可以通过以下方法进行调试:

5. 总结

通过 Calico 提供的网络策略功能,你可以精细化地控制 Kubernetes 集群中不同 Pod 之间的网络通信。这对于 GitLab 等多组件应用尤为重要,能够防止未经授权的 Pod 或服务访问敏感组件,如 GitLab Redis 或 Web Service。通过合理的网络策略配置,可以确保集群的安全性和可维护性。

核心步骤回顾:

  1. 定义网络策略文件 (NetworkPolicy)。
  2. 使用 kubectl apply 应用策略。
  3. 验证和调试策略是否按预期生效。

Calico 的网络策略功能非常灵活,适用于 Kubernetes 中的多种安全和隔离场景。

xuanyuanaosheng commented 1 month ago

K8S 调度器的工作原理

Kubernetes 调度器(Scheduler)是 Kubernetes 中负责将新创建的未指定节点的 Pod 分配到合适的节点上的组件。调度器是 Kubernetes 系统中非常关键的一部分,因为它决定了工作负载如何在集群内的节点上分布,从而影响资源利用率、应用程序的性能和集群的健壮性。

K8S 调度器的工作原理

当一个新的 Pod 被创建时,它处于一个未调度(Pending)的状态,并且没有分配到任何节点上。此时,Kubernetes 调度器会负责以下操作:

  1. 过滤阶段(Filtering Phase):调度器首先会根据 Pod 的要求和节点的条件,对所有的节点进行筛选,过滤掉不符合要求的节点。这些条件可能包括:

    • 节点的可用资源(CPU、内存等)
    • Pod 与节点的污点和容忍度
    • 节点的亲和性和反亲和性
    • 节点的健康状况(如是否准备就绪)
  2. 优选阶段(Scoring Phase):在过滤完所有不适合的节点之后,调度器会对剩余的候选节点进行评分。评分的依据可以是多种因素,例如:

    • 节点的剩余资源
    • 节点和 Pod 之间的亲和性(如区域、拓扑、标签)
    • 节点的负载均衡情况(如优先分配到负载较低的节点)
  3. 绑定阶段(Binding Phase):最后,调度器会将 Pod 绑定到得分最高的节点上。这个步骤完成后,Kubelet(节点上的代理)会开始在该节点上运行这个 Pod。

调度器的核心功能

调度器的关键组件

  1. Predicate 算法:在过滤阶段,调度器会使用多个 Predicate 函数来确定某个节点是否能够运行特定的 Pod。这些函数包括检查节点的可用性、资源、污点、Pod 的请求等。

  2. Priority 算法:在优选阶段,调度器使用 Priority 函数对候选节点进行评分。这些评分由多个因素决定,例如节点的剩余资源、负载均衡情况、亲和性等。

  3. 调度周期:调度器定期执行调度循环,在这个过程中会检查所有的 Pending Pod,尝试将它们调度到合适的节点。

常见的调度策略

调度器的可扩展性

Kubernetes 调度器是可扩展的,允许你根据集群的需求自定义调度逻辑:

  1. 自定义调度器:如果默认调度器不满足你的需求,你可以编写自定义调度器,并将其部署到 Kubernetes 中。自定义调度器可以使用不同的调度算法和策略来调度 Pod。

  2. 调度器扩展点:Kubernetes 还提供了调度器扩展点(Scheduler Extender),允许你在现有调度器的基础上添加额外的调度逻辑,比如增加过滤条件或对节点进行额外评分。

  3. 多调度器支持:Kubernetes 允许你运行多个调度器,不同的 Pod 可以通过 schedulerName 字段来指定使用哪个调度器。

调度器的优化

为了提高集群效率,调度器需要经过调优,以下是一些常见的调优策略:

  1. 资源分配策略:合理配置 Pod 的 CPU、内存请求和限制,避免资源超分配或不足。
  2. 节点负载均衡:确保工作负载在多个节点间合理分布,防止单个节点过载。
  3. 分布式应用调度:结合拓扑感知调度,确保分布式应用(如微服务、数据库等)可以高效运行并具备容灾能力。
  4. 优先级和抢占:为关键工作负载设置更高的优先级,并允许其抢占低优先级的 Pod。

调度器的日志和监控

调度器的日志非常重要,它可以帮助你理解调度决策并排查问题。常见的调度器日志包括:

另外,你可以使用 Prometheus 等监控工具来监控调度器的行为,捕获调度延迟、调度成功率等关键指标。


Kubernetes 调度器在确保集群资源的高效利用、Pod 的可靠调度和应用程序的可用性方面起到了至关重要的作用。你可以通过调优、监控和扩展来更好地满足不同业务需求。如果你有更多的具体问题或场景,可以进一步讨论!

xuanyuanaosheng commented 1 month ago

K8S的HPA

Kubernetes 的 HPA(Horizontal Pod Autoscaler,水平 Pod 自动伸缩)是 Kubernetes 中的一项核心功能,它允许基于集群的实时负载自动调整工作负载的副本数量,以保证应用的高可用性和弹性。HPA 能根据资源使用情况或自定义指标的变化,自动增加或减少 Pod 数量,从而优化资源利用和应用性能。

HPA 的工作原理

HPA 的核心功能是监控某个工作负载(如 Deployment、ReplicaSet 或 StatefulSet)的资源使用情况(例如 CPU、内存)或其他自定义指标,当负载达到某个预定义的阈值时,它会动态调整副本的数量,确保应用具有足够的资源来处理负载变化。

HPA 的主要工作流程如下:

  1. 监控指标:HPA 定期(默认 15 秒)通过 Kubernetes 的资源度量 API(Metrics API)或自定义指标 API 收集 Pod 的资源使用情况或自定义指标。

  2. 计算副本数:根据预定义的目标值和当前的资源使用情况,HPA 计算出应该增加或减少多少个 Pod。例如,如果 CPU 使用率超过目标值,它会增加 Pod 数量,反之则减少。

  3. 更新副本数:HPA 将新计算的副本数量更新到控制器(如 Deployment),以调整 Pod 副本的数量。

配置 HPA

使用 HPA 需要定义一个 HPA 资源对象,这个对象指定了:

基于 CPU 使用率的 HPA 配置示例

以下是一个简单的 HPA 配置示例,基于 CPU 使用率自动伸缩:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-deployment  # 需要伸缩的对象
  minReplicas: 2  # 最小副本数
  maxReplicas: 10  # 最大副本数
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50  # 目标 CPU 使用率

在上面的配置中:

基于自定义指标的 HPA 配置示例

你也可以基于自定义指标(如应用程序请求数、队列长度等)来定义 HPA。这需要借助外部监控工具如 Prometheus 和自定义指标 API。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: custom_requests_per_second  # 自定义指标名称
      target:
        type: AverageValue
        averageValue: 100  # 每秒请求数的目标值

在这个示例中,HPA 会基于 custom_requests_per_second 指标来调整副本数。

HPA 的主要组件

  1. Metrics Server:HPA 默认通过 Metrics Server 来获取资源使用数据,特别是 CPU 和内存使用率。Metrics Server 是 Kubernetes 内置的资源监控工具,它定期从节点和 Pod 中收集指标。

  2. Custom Metrics API:如果你想要基于自定义指标进行伸缩(例如业务指标、Prometheus 指标等),则需要配置 Custom Metrics API,并与外部的监控系统(如 Prometheus)集成。

  3. Control Loop:HPA 是一个控制回路(control loop)组件,它会定期评估当前的资源使用情况,并与目标值对比,然后做出决策。如果发现当前使用率超过或低于目标值,HPA 就会相应地增减 Pod 的数量。

HPA 的伸缩算法

HPA 的伸缩逻辑是基于资源使用率的目标值。伸缩算法可以总结为以下公式:

desiredReplicas = ceil(currentReplicas * (currentMetricValue / desiredMetricValue))

例如,如果当前有 5 个 Pod,每个 Pod 的 CPU 使用率为 80%,而目标 CPU 使用率是 50%,则 HPA 将计算出新的副本数量:

desiredReplicas = ceil(5 * (80 / 50)) = ceil(5 * 1.6) = 8

HPA 会将副本数从 5 个增加到 8 个。

HPA 的高级配置和策略

Kubernetes 的 HPA 提供了多个高级选项,帮助你更好地管理自动伸缩行为:

  1. 冷却时间(Stabilization Window):你可以设置一个冷却时间,避免 HPA 频繁地扩展或缩减副本数。默认情况下,HPA 会在缩减 Pod 数时采用 5 分钟的冷却时间。

    behavior:
     scaleDown:
       stabilizationWindowSeconds: 300  # 5 分钟冷却时间
  2. 伸缩速率:你可以限制每次伸缩操作的最大增长或减少幅度,避免过度伸缩导致系统不稳定。

    behavior:
     scaleUp:
       policies:
       - type: Percent
         value: 50  # 每次最多扩展 50%
         periodSeconds: 60
     scaleDown:
       policies:
       - type: Pods
         value: 4  # 每次最多缩减 4 个 Pod
         periodSeconds: 60
  3. 最小副本数与最大副本数:你可以设置最小和最大副本数,防止自动伸缩时 Pod 数过低影响可用性,或过高造成资源浪费。

  4. 自定义指标:通过 Custom Metrics API,你可以使用 Prometheus 等外部系统作为自定义指标数据源。例如,基于请求率或队列长度来调整副本数。

HPA 的监控和故障排查

  1. 查看 HPA 状态:可以使用以下命令查看 HPA 的当前状态,包括当前副本数、目标值和实际的资源使用情况:

    kubectl get hpa
    kubectl describe hpa <hpa-name>
  2. 监控 HPA:可以使用 Prometheus 和 Grafana 来监控 HPA 的伸缩行为和 Pod 的资源使用情况。

  3. 调试问题:如果 HPA 没有按预期工作,常见的故障排查步骤包括:

    • 确保 Metrics Server 正常工作并返回正确的数据。
    • 检查 HPA 目标的 Deployment 或 ReplicaSet 是否工作正常。
    • 查看 HPA 事件日志,分析调度器是否存在错误或资源不足。

HPA 的应用场景

  1. 自动伸缩 Web 服务:对于处理用户请求的 Web 应用,HPA 可以根据 CPU 使用率或请求率自动扩展或缩减副本,确保在高负载时有足够的资源应对流量。

  2. 批处理任务:HPA 可以根据任务队列长度或工作负载的数量自动增加 Pod 数量,以加快处理速度。当任务完成后,它会自动缩减副本数。

  3. 微服务架构:在微服务架构中,不同服务的负载可能差异较大,HPA 能够为每个服务动态调整副本数,从而优化资源利用率并提高服务的稳定性。

总结

Kubernetes 的 HPA 是实现应用程序自动伸缩的强大工具,通过动态调整 Pod 数量来应对负载波动。它可以基于多种指标(如 CPU、内存、请求数等)来执行自动伸缩操作,帮助你更好地管理资源,提高系统的弹性和可用性。

xuanyuanaosheng commented 1 month ago

关于K8S的一些待解决的问题

  1. 线上核心业务比方说数据库,redis这些有状态服务有部署在K8S里面么?
  2. K8S的备份只用备份Etcd就可以么?是否需要备sc对于的存储。
  3. 通过helm部署应用修改配置出现劈叉问题即怎么找到某个应用的部署源头(可能不是helm部署的)或者说怎么查询一个服务有部署源头,从而实现快速拍错更改配置
  4. 一个通过 Deployment和StatefulSet部署的有状态服务例如Mysql有什么区别?
xuanyuanaosheng commented 3 weeks ago

一个通过 Deployment和StatefulSet部署的有状态服务例如Mysql有什么区别?

在 Kubernetes 中,DeploymentStatefulSet 是用于管理应用程序的两种不同的控制器。它们都能用来部署和管理应用程序的副本,但它们的工作方式和适用场景不同,尤其是在管理有状态服务(例如 MySQL)时。

Deployment 与 StatefulSet 的主要区别

  1. Pod 标识(唯一性)

    • Deployment:Pod 是无状态的,所有 Pod 都是相同的,没有固定的标识。如果某个 Pod 崩溃了,Deployment 会创建一个新的 Pod 来替代它,这个新的 Pod 与之前的 Pod 没有任何关系。它无法保证新的 Pod 拥有与之前 Pod 相同的名称和存储。
    • StatefulSet:每个 Pod 都有唯一的固定标识,Pod 的名称遵循固定的顺序(如 mysql-0mysql-1mysql-2)。如果某个 Pod 崩溃,StatefulSet 会重新创建一个同名的 Pod,且该 Pod 会重新绑定到原来的存储卷上。这对有状态应用非常重要,因为它需要持久化存储和固定的 Pod 身份。
  2. 存储卷的持久化

    • Deployment:Pod 是无状态的,它们使用的存储卷通常是临时的(emptyDir 或者非持久化存储)。如果 Pod 重新创建,可能会分配到不同的节点,并且使用不同的存储卷,因此无法保证数据的持久性。
    • StatefulSet:每个 Pod 都会有一个与之对应的持久存储卷(PersistentVolume,PV)。即使 Pod 被删除或重新调度到其他节点,StatefulSet 也会将其绑定到相同的持久卷上,确保数据不丢失。这对有状态应用(如 MySQL)非常关键,因为它们依赖于数据的持久性。
  3. 启动和终止顺序

    • Deployment:Pod 启动和终止的顺序是无关紧要的,Kubernetes 可以并行地创建或删除 Pod。对于无状态服务(如 Web 服务),这种模式非常高效。
    • StatefulSet:Pod 的启动、终止和更新顺序是严格控制的。Pod 是按顺序启动的(例如,mysql-0 启动后,才会启动 mysql-1),同样,Pod 的删除和更新也遵循同样的顺序。这对有状态服务(如 MySQL 主从架构)非常重要,因为它们需要确保在数据复制、集群管理等方面的一致性和顺序性。
  4. 网络标识(网络名)

    • Deployment:Pod 的网络标识是动态的,Pod 被重新创建时会获得新的 IP 地址,Pod 名称不固定。因此,Pod 之间的通信通常依赖于 Kubernetes 服务(Service)来实现负载均衡。
    • StatefulSet:每个 Pod 都有一个固定的 DNS 名称(例如 mysql-0 会有一个 mysql-0.<service-name> 的 DNS 记录)。即使 Pod 重新创建,它的 DNS 名称和 IP 地址保持不变。这对有状态服务(如 MySQL 集群)非常有用,因为服务可以通过固定的 DNS 名称找到特定的 Pod。
  5. 滚动更新(Rolling Updates)

    • Deployment:支持无中断的滚动更新,即在部署新的应用版本时,Kubernetes 会逐步替换旧的 Pod,新 Pod 和旧 Pod 可以并行运行,保证更新的连续性。
    • StatefulSet:同样支持滚动更新,但更新是按照顺序进行的(按 Pod 名称排序),而且只有上一个 Pod 更新完成并处于就绪状态后,才会更新下一个 Pod。这保证了有状态服务更新时的稳定性。

部署 MySQL 的对比

  1. 使用 Deployment 部署 MySQL

    • 适合于无状态或临时 MySQL 实例(例如用于测试或开发环境)。
    • 每次 Pod 重启或重新调度后,Pod 的存储和网络标识都会发生变化,数据可能丢失。
    • 不适合生产环境,因为生产环境的 MySQL 需要持久化数据和固定的存储。
  2. 使用 StatefulSet 部署 MySQL

    • 适合用于生产环境中的有状态服务。MySQL 是一个需要持久化存储的数据库,因此 StatefulSet 是更合适的选择。
    • 每个 MySQL 实例会有固定的 DNS 名称和持久化存储卷。如果某个 MySQL Pod 发生重启或调度到新的节点,它会重新连接到之前的存储卷,数据不会丢失。
    • MySQL 主从架构也依赖于 StatefulSet 的严格启动顺序和持久存储,确保主从复制的一致性和可靠性。

适用场景

总结

如果要部署 MySQL 这样的有状态服务,应该选择 StatefulSet,这样可以保证 MySQL 的数据持久性、可靠性以及主从架构的一致性。

xuanyuanaosheng commented 3 weeks ago

K8S集群中的DNS系统 -- CoreDNS

在 Kubernetes 集群中,CoreDNS 是默认的 DNS 服务,用于为集群内部的服务提供服务发现和名称解析。它通过为集群中的服务、Pod 提供 DNS 解析,帮助这些组件在网络中找到彼此,从而实现通信。

1. CoreDNS 的作用

CoreDNS 是 K8S 中的关键组件,负责将集群中的服务名称(如 Service 和 Pod)解析为 IP 地址,允许不同的服务、Pod 通过名称互相通信,而不需要明确使用 IP 地址。

主要功能包括:

2. CoreDNS 的基本工作原理

CoreDNS 是一个灵活的 DNS 服务器,通过其配置文件(通常是 Corefile)定义不同的解析规则。对于 Kubernetes 集群,它的主要功能是解析服务名称并返回相应的服务 IP 地址。

2.1 DNS 服务

在 K8S 集群中,每个服务创建时,K8S API 会为其生成一个 DNS 名称。这些服务的 DNS 名称通常为 service-name.namespace.svc.cluster.local,可以通过该名称解析到服务的 ClusterIP(虚拟 IP 地址)。

CoreDNS 主要负责以下工作:

2.2 CoreDNS 配置文件(Corefile)

CoreDNS 使用 Corefile 来配置其行为。在 Kubernetes 中,Corefile 通常会包含处理 cluster.local 域的配置,这是 Kubernetes 内部服务使用的默认域名。

一个典型的 Corefile 可能如下:

.:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}

2.3 服务名称解析过程

当集群内的一个 Pod 通过服务名称访问另一个服务时,会发起 DNS 请求。CoreDNS 会从 K8S API 获取与该服务对应的 IP 并返回,具体流程如下,以gitlab系统里面的组件通信为例:

2.4 外部 DNS 请求

如果某个 Pod 发起的 DNS 请求不是针对集群内部的服务,比如查询 google.com,CoreDNS 会根据 Corefile 中的 forward 配置,将查询请求转发到外部 DNS 服务器(如 /etc/resolv.conf 配置的 DNS 服务器),并将结果返回给 Pod。

3. CoreDNS 与 Calico 的协同工作

Calico 提供了 Pod 间的网络通信,而 CoreDNS 则提供了服务发现和名称解析功能。它们协同工作,为集群内的 Pod 和服务之间提供无缝的通信能力。

例如,GitLab 部署在 K8S 上,GitLab Web Service 需要访问 GitLab Redis。这时,GitLab Web Service 通过服务名称(如 gitlab-redis.default.svc.cluster.local)来访问 Redis。CoreDNS 解析该名称并返回 Redis 服务的 ClusterIP,Calico 则负责将数据包从 Web Service Pod 路由到 Redis Pod,完成整个通信过程。

4. CoreDNS 插件化架构

CoreDNS 的一个重要特性是其插件化架构,它支持通过插件来扩展其功能。每个 DNS 请求通过 CoreDNS 时,插件会按照配置的顺序处理。

常用的插件包括:

这些插件使得 CoreDNS 非常灵活,可以根据需要配置各种功能。

5. CoreDNS 在 GitLab 部署中的作用

当 GitLab 各组件通过 Kubernetes 的 DNS 名称进行通信时,CoreDNS 会发挥作用。例如:

6. 如何排查 CoreDNS 问题

当在 K8S 中遇到 DNS 解析问题时,通常可以采取以下步骤进行排查:

  1. 查看 CoreDNS Pod 状态: 通过命令查看 CoreDNS 是否正常运行:

    kubectl get pods -n kube-system -l k8s-app=kube-dns
  2. 检查 CoreDNS 日志: 查看 CoreDNS 的日志以排查是否有错误:

    kubectl logs -n kube-system -l k8s-app=kube-dns
  3. 验证 DNS 配置: 使用 Pod 内的工具(如 nslookupdig)检查 DNS 解析是否正常:

    kubectl exec -it <pod-name> -- nslookup gitlab-redis.default.svc.cluster.local
  4. 检查 Corefile 配置: 查看 Corefile 配置是否正确,是否存在配置错误:

    kubectl get configmap coredns -n kube-system -o yaml
  5. 外部 DNS 解析: 如果集群内部的 Pod 无法解析外部域名,可以检查 CoreDNS 是否能够正确转发到外部 DNS 服务器。

总结

CoreDNS 是 Kubernetes 中提供 DNS 服务和服务发现的关键组件,尤其是在像 GitLab 这种多服务、多组件的系统中,它的作用尤为重要。通过 CoreDNS,K8S 中的每个 Pod 和服务可以通过服务名称进行通信

xuanyuanaosheng commented 2 weeks ago

常用的K8S管理工具

xuanyuanaosheng commented 2 weeks ago

云原生的CI/CD

xuanyuanaosheng commented 2 weeks ago

K8S二次开发

xuanyuanaosheng commented 2 weeks ago

K8S的网络

image

image

节点内的Pod网络

K8S Nginx-Ingress-Controller 原理

企业微信截图_17144571129654

Ingress通过HostPost(80/443)来对外进行暴露的,可以理解为一种特殊的Service

参考资料

xuanyuanaosheng commented 2 weeks ago

技术文档

xuanyuanaosheng commented 2 weeks ago

K8S的包管理器

xuanyuanaosheng commented 2 weeks ago

K8S问题处理

xuanyuanaosheng commented 4 days ago

Docker的实现原理

Docker 的实现原理主要基于以下几个关键技术:

1. Linux 容器技术 (Linux Containers)

Docker 使用 Linux 容器技术来隔离应用。容器与虚拟机不同,虚拟机提供完全的操作系统隔离,而容器共享宿主机操作系统的内核,只隔离应用和应用的运行环境。Linux 的命名空间 (Namespaces) 和控制组 (Control Groups, cgroups) 是实现容器的核心技术。

2. Namespace(命名空间)

命名空间用于隔离系统资源,使得每个容器中的进程都认为自己是独立的。例如:

3. Control Groups(控制组,cgroups)

控制组用于限制和监控资源的使用(如 CPU、内存、磁盘 I/O 等)。每个容器可以分配特定的资源限制,以避免资源滥用和实现高效的资源利用。

4. 联合文件系统(UnionFS)

Docker 使用联合文件系统(如 AUFS、OverlayFS、btrfs 等)来管理镜像和容器的文件系统。UnionFS 支持对文件系统的分层操作,将多个目录叠加在一起提供一个文件系统视图。镜像由一系列只读的层构成,容器启动时会在其上添加一个可写层。这种分层文件系统使得镜像可以复用,减少了存储空间占用并提高了部署速度。

5. Docker 镜像和容器

6. Docker 的网络原理

Docker 使用虚拟网络技术为容器提供网络隔离和连接能力,支持多种网络模式,包括:

7. 容器存储驱动

Docker 提供多种存储驱动(如 AUFS、OverlayFS、Device Mapper、btrfs 等),通过分层文件系统实现镜像和容器的文件隔离和共享。

8. Docker Daemon (守护进程)

Docker 守护进程(dockerd)运行在宿主机上,负责管理容器的生命周期,包括构建、启动、停止和删除容器。Docker Daemon 通过 REST API 提供服务,客户端通过 Docker CLI 命令与守护进程通信。

9. 容器编排

在多节点环境中,Docker 使用编排工具(如 Docker Swarm、Kubernetes)管理集群中的容器。编排工具提供容器调度、自动扩缩容、服务发现和负载均衡等功能,提升了容器的可管理性和可扩展性。

10. 镜像分发与存储

Docker Hub 是 Docker 的公共镜像仓库,用于存储和分发容器镜像。开发者可以将构建好的镜像推送到 Docker Hub,用户则可以从 Docker Hub 拉取镜像。此外,也支持私有镜像仓库以满足安全需求。

总结

Docker 利用 Linux 的容器技术、命名空间、控制组、联合文件系统、以及网络虚拟化技术,实现了轻量级的应用隔离和高效的资源利用。容器的镜像和分层文件系统使得应用可以便捷地进行分发和部署,从而加快了开发和运维的流程。Docker 的网络和存储插件体系为容器提供了灵活的网络拓扑和数据持久化解决方案。同时,通过编排工具,Docker 适合在大规模集群环境中管理容器应用。

这些技术相互配合,使 Docker 成为了现代云原生架构和 DevOps 工具链中不可或缺的一部分。

xuanyuanaosheng commented 3 days ago

在 Kubernetes (K8S) 集群中,进行故障排查是确保集群稳定性和可用性的重要工作。K8S 提供了一系列工具和方法帮助管理员识别、诊断和解决问题。以下是常用的故障排查步骤和方法:

1. 检查 Pod 状态

使用 kubectl get pods 命令查看 Pod 的状态。如果 Pod 处于 PendingCrashLoopBackOffError 等状态,说明可能有问题。

   kubectl get pods -n <namespace> -o wide

2. 查看 Pod 的详细信息

使用 kubectl describe pod 查看 Pod 的详细信息,包括事件、容器状态、错误信息等,可以帮助定位问题。

   kubectl describe pod <pod-name> -n <namespace>

3. 查看 Pod 日志

使用 kubectl logs 查看 Pod 内部容器的日志,日志通常包含错误信息和诊断信息。

   kubectl logs <pod-name> -n <namespace> --container <container-name>

4. 排查服务 (Service) 问题

使用 kubectl get serviceskubectl describe service 检查服务配置和状态,以确认服务是否正确创建以及是否正确暴露了端口。

5. 检查 Deployment、ReplicaSet 等控制器状态

使用 kubectl get deploymentkubectl describe deployment 等命令检查 Deployment、ReplicaSet 的状态,确认副本数量、滚动更新状态等是否正常。

   kubectl get deployment -n <namespace>
   kubectl describe deployment <deployment-name> -n <namespace>

6. 检查 Node 状态

使用 kubectl get nodes 检查集群中节点的状态,确保节点处于 Ready 状态。如果节点不可用,会导致 Pod 无法调度。

   kubectl get nodes
   kubectl describe node <node-name>

7. 检查容器资源限制

Pod 和容器可以配置资源限制(如 CPU 和内存),如果配置不当会导致资源不足或频繁 OOM 重启。可以使用以下命令查看 Pod 配置的资源限制:

   kubectl describe pod <pod-name> -n <namespace>

8. 检查网络和 DNS 配置

网络问题会导致 Pod 之间、服务之间通信异常,可以使用以下方法检查网络:

9. 查看事件日志

Kubernetes 中的事件日志可以帮助定位问题,尤其是资源调度和 Pod 生命周期管理相关的问题。

   kubectl get events -n <namespace>

10. 查看 K8S 组件日志

Kubernetes 的控制组件(如 API Server、Scheduler、Controller Manager)运行在 Master 节点上,可以查看这些组件的日志以获取更多诊断信息。

11. 排查存储问题

如果 Pod 挂载的存储(如 PVC)存在问题,可能会导致 Pod 卡在 ContainerCreatingPending 状态。

12. 使用 Debug 工具

13. 排查 YAML 配置文件

在故障排查过程中,经常会遇到配置错误导致资源创建失败或状态异常。在 K8S 中,许多资源的创建都是通过 YAML 文件定义的。我们可以使用以下方法检查配置文件是否有误:

14. 检查资源的依赖关系

K8S 中的资源往往具有依赖关系。例如,Deployment 依赖于 Pod,Service 依赖于 Pod 和 Endpoints。如果一个资源出现问题,可能会影响其他相关资源:

15. 利用 Debug Pod

Kubernetes 提供了 kubectl debug 功能,可以创建临时的调试容器。在需要深入排查应用环境或配置的场景下,可以使用 kubectl debug 进入 Pod 并执行特定调试操作。

kubectl debug -it <pod-name> --image=busybox --target=<container-name>

这种方式可以帮助你排查网络连接、权限问题、环境变量等。

16. 网络排查工具

网络故障是 K8S 中的常见问题之一,尤其是在使用不同的网络插件时。以下是几种网络排查的方法:

17. 利用监控系统的故障排查

如果集群中已经部署了 Prometheus 和 Grafana 之类的监控工具,可以通过它们来查看集群资源的运行情况,进一步分析系统的瓶颈和异常:

18. 日志分析

日志可以为故障排查提供丰富的线索。建议使用集中化的日志收集和分析工具(如 ELK 或 Loki)来管理 K8S 集群的日志数据:

19. 复现与自动化测试

如果问题难以排查或偶发,尝试在开发环境或测试集群中复现问题,有助于精确诊断。可以通过以下方式进行测试:

20. 故障预防与策略

故障排查不仅仅是处理问题,更重要的是预防问题。以下是一些常见的故障预防措施:

总结

Kubernetes 故障排查涉及多个方面,从基础的 Pod、Service 状态检查,到日志分析、网络排查,再到利用监控系统和自动化工具进行全面诊断。每个步骤都可以帮助我们深入了解系统的健康状态,定位故障的根源。

xuanyuanaosheng commented 3 days ago

在 Kubernetes (K8S) 中,Pod 调度是指将 Pod 分配到合适的节点上运行的过程。K8S 的调度器负责决定每个 Pod 应该被分配到哪个节点,调度策略和规则有助于实现资源的有效分配、应用的高可用性等。以下是 K8S 中 Pod 的调度方法和策略:

1. Node Selector (节点选择器)

nodeSelector 是一种简单的调度方法,用于将 Pod 限制到具有特定标签的节点上。可以在 Pod 的 YAML 配置中使用 nodeSelector 字段指定目标节点的标签。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  nodeSelector:
    disktype: ssd  # 只有带有 "disktype=ssd" 标签的节点会被选择
  containers:
    - name: nginx
      image: nginx

这种方法适合简单的场景,但不够灵活,主要用在标签匹配的静态调度场景。

2. Node Affinity (节点亲和性)

nodeAffinitynodeSelector 的增强版,提供了更多条件组合和灵活性。nodeAffinity 支持三种不同的条件:

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: disktype
                operator: In
                values:
                  - ssd
  containers:
    - name: nginx
      image: nginx

nodeAffinity 更加灵活,可以实现按需资源分配和分布策略控制。

3. Pod Affinity and Anti-Affinity (Pod 亲和性与反亲和性)

Pod AffinityPod Anti-Affinity 用于控制 Pod 与其他 Pod 的分布。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - web-server
          topologyKey: "kubernetes.io/hostname"  # 在同一主机上
  containers:
    - name: nginx
      image: nginx

Pod Anti-Affinity 常用于确保关键应用实例分布在不同节点上,以防止单点故障。

4. Taints and Tolerations (污点和容忍度)

TaintsTolerations 是一种节点隔离策略,用于防止不符合条件的 Pod 被调度到指定节点上。管理员可以在节点上设置污点 (taint),只有包含相应 tolerations 的 Pod 才能被调度到该节点上。

示例:

给节点添加污点:

kubectl taint nodes <node-name> key=value:NoSchedule

Pod 配置容忍度:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  tolerations:
    - key: "key"
      operator: "Equal"
      value: "value"
      effect: "NoSchedule"
  containers:
    - name: nginx
      image: nginx

Taints and Tolerations 非常适用于划分节点池和控制特定工作负载的调度。

5. Resource Requests and Limits (资源请求与限制)

Pod 在定义容器时,可以设置 requestslimits,用于资源调度时的要求:

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: nginx
      image: nginx
      resources:
        requests:
          cpu: "500m"
          memory: "128Mi"
        limits:
          cpu: "1"
          memory: "256Mi"

资源请求与限制可以帮助 K8S 在调度时选择符合资源要求的节点,避免资源不足或浪费。

6. 优先级调度 (Priority Scheduling)

K8S 支持基于优先级的调度,在资源紧张时,优先级高的 Pod 可以优先调度,甚至可以驱逐低优先级的 Pod。

示例:

创建一个高优先级的 PriorityClass:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000
globalDefault: false
description: "This is a high priority class"

在 Pod 中指定优先级:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  priorityClassName: high-priority
  containers:
    - name: nginx
      image: nginx

优先级调度可以确保关键任务在资源紧张时优先运行。

7. 自定义调度器 (Custom Scheduler)

Kubernetes 支持自定义调度器,管理员可以根据需求实现自定义的调度逻辑。例如,可以通过编写自定义调度器实现基于特定策略的调度行为。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  schedulerName: my-custom-scheduler
  containers:
    - name: nginx
      image: nginx

8. Topology Spread Constraints (拓扑扩展约束)

Topology Spread Constraints 是一种可以控制 Pod 在不同拓扑域(如区域或可用区)之间均匀分布的调度策略,适用于高可用性要求较高的场景。

示例:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: "topology.kubernetes.io/zone"
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          app: web-server
  containers:
    - name: nginx
      image: nginx

Topology Spread Constraints 可确保 Pod 在不同区域或节点均匀分布,从而提高容错性。

总结

K8S 提供了多种调度方法来满足不同的调度需求,包括:

这些调度策略可以单独使用,也可以组合使用,以实现最佳的 Pod 调度

xuanyuanaosheng commented 3 days ago

在 Kubernetes 和现代应用程序的交付过程中,有多种发布策略可以用来部署和更新应用程序。不同的发布策略适用于不同的场景和需求,选择合适的策略可以在确保稳定性的同时,提升用户体验。以下是常见的发布策略:

1. 滚动更新 (Rolling Update)

滚动更新是 Kubernetes 中默认的发布策略,通过逐步替换旧版本的 Pod 为新版本,从而实现无中断更新。在更新过程中,K8S 控制器会逐个地删除旧的 Pod,并创建新的 Pod。

配置示例

在 Deployment 中指定 strategyRollingUpdate

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    spec:
      containers:
        - name: app
          image: example-app:v2

2. 重建 (Recreate)

重建发布策略是一种“替换式”的策略,即先终止所有旧版本的 Pod,然后再启动新版本的 Pod。这种策略适用于对中断不敏感的应用场景。

配置示例

在 Deployment 中指定 strategyRecreate

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  strategy:
    type: Recreate
  template:
    spec:
      containers:
        - name: app
          image: example-app:v2

3. 蓝绿部署 (Blue-Green Deployment)

蓝绿部署通过创建两个完全独立的环境(通常称为蓝色环境和绿色环境)来进行发布,确保旧版本和新版本环境互相隔离。更新时先在绿色环境中部署新版本,然后在切换流量前进行验证,一旦验证通过,切换所有流量到新版本。

实现方法

在 Kubernetes 中可以通过使用两个 Deployment(蓝色和绿色)结合服务切换来实现。

4. 金丝雀发布 (Canary Release)

金丝雀发布是一种渐进式发布策略,通过将新版本发布给部分用户进行测试,逐步增加新版本的流量,直到所有流量都切换到新版本。这样可以在小范围内验证新版本的稳定性,逐步推广更新。

实现方法

可以通过 Kubernetes 的 Deployment 配合 Service 或 Istio 等服务网格工具进行金丝雀流量的控制。

5. A/B 测试 (A/B Testing)

A/B 测试策略类似于金丝雀发布,但主要用于同时运行多个版本来测试不同功能或配置的效果。用户会被分配到不同版本上,以收集用户反馈或行为数据,从而确定最佳版本。

实现方法

可以通过服务网格(如 Istio 或 Linkerd)来实现不同流量策略。

6. 分阶段发布 (Phased Rollout)

分阶段发布是一种分批发布的策略,将整个更新过程分为多个阶段,每个阶段逐步增加新版本的 Pod 数量。每一阶段结束后进行验证,确保没有问题再进入下一阶段。

实现方法

可以在 Kubernetes 中通过配置 Deployment 的 RollingUpdate 策略,并结合流量控制工具来逐步增加更新的范围。

7. 影子发布 (Shadow Release)

影子发布是在生产环境中将真实的用户流量“影射”到新版本上,但不对用户产生实际影响。影子发布的流量仅用于测试和验证新版本的稳定性,不会影响到现有的生产版本。

实现方法

通常需要使用 API 网关或服务网格(如 Istio),将流量复制到新版本的 Pod。

8. 无中断发布 (Zero Downtime Deployment)

无中断发布是一种确保发布过程对用户透明的策略,通过合理的调度策略、健康检查和负载均衡来实现发布过程中的服务不中断。滚动更新、金丝雀发布和蓝绿部署都是实现无中断发布的常见方式。

总结

不同的发布策略在实际使用中各有优缺点,选择合适的发布策略应根据应用的特性、用户需求和资源成本来决定:

这些发布策略可以单独使用,也可以组合使用。比如,可以先进行影子发布测试新版本,然后使用金丝雀发布逐步引入流量,最后使用蓝绿部署进行全量切换。这些组合能够在确保服务稳定性的同时,灵活地满足不同的发布需求。

xuanyuanaosheng commented 2 days ago

在 Kubernetes 中,pause 容器是一种特殊的容器,它通常作为 Pod 的“基础容器”存在。它有以下主要作用和意义:


1. 提供网络和 Linux Namespace 的隔离基础


2. Pod 生命周期管理


3. 简化容器管理


4. 资源最小化


典型镜像和内容


总结

pause 容器在 Kubernetes 中是 Pod 资源隔离的基础,它负责:

虽然它本身不起眼,但在 Kubernetes 的资源管理和调度中扮演了重要角色。

xuanyuanaosheng commented 2 days ago

在 Kubernetes 中,静态 Pod 是一种特殊类型的 Pod,它由 Kubelet 直接管理,而不是通过 Kubernetes API Server 创建或管理。它适用于需要直接运行在某个节点上的关键组件或独立服务。


静态 Pod 的特点

  1. 由 Kubelet 管理

    • 静态 Pod 是 Kubelet 自行监控和管理的,与 Kubernetes 控制平面无关。
    • 它不会被 Kubernetes 的调度器(Scheduler)调度。
  2. 文件定义

    • 静态 Pod 是通过节点上的本地配置文件定义的,文件通常存放在指定的路径(例如 /etc/kubernetes/manifests)。
  3. 无 ReplicaSet 或 Deployment

    • 静态 Pod 直接定义 Pod 的属性,没有副本控制器(如 ReplicaSet)来管理。
  4. 自动注册到 API Server

    • 虽然静态 Pod 是由 Kubelet创建的,但它们会被自动注册到 API Server 中,仅用于显示状态(status)。
    • 注意:API Server 中注册的静态 Pod 仅供查看和调试,不能通过 API 修改。

静态 Pod 的用途

  1. 运行关键组件

    • 静态 Pod 通常用于运行 Kubernetes 的核心组件(如 etcdkube-apiserverkube-scheduler 等),尤其是在高可用集群中。
  2. 节点专属任务

    • 某些任务需要固定运行在特定节点上时,可以使用静态 Pod。
  3. 不依赖控制平面

    • 在 Kubernetes 控制平面还未完全启动的情况下(例如集群初始化时),静态 Pod 可确保关键服务先行运行。

创建静态 Pod 的步骤

  1. 确定静态 Pod 的存储路径

    • Kubelet 的配置中有一个参数 --pod-manifest-path,用于指定静态 Pod 文件的目录(例如 /etc/kubernetes/manifests)。
  2. 编写 Pod 配置文件

    • 定义一个标准的 Pod 配置文件(YAML 格式),例如:
      apiVersion: v1
      kind: Pod
      metadata:
      name: static-pod-example
      namespace: default
      spec:
      containers:
       - name: static-container
         image: nginx:latest
         ports:
           - containerPort: 80
  3. 将配置文件放置到指定目录

    • 将上述文件保存到 Kubelet 的 --pod-manifest-path 所指定的目录中。
  4. Kubelet 自动管理

    • Kubelet 会自动检测到该配置文件并启动对应的静态 Pod。

静态 Pod 的优缺点

优点

  1. 独立性强

    • 静态 Pod 不依赖 Kubernetes 控制平面,可以在控制平面不可用时继续运行。
  2. 适合节点级别的关键任务

    • 对于需要绑定到特定节点的服务,静态 Pod 是理想选择。
  3. 简单性

    • 不需要通过 API Server 或复杂的 YAML 定义即可快速部署。

缺点

  1. 管理复杂性

    • 静态 Pod 缺乏 Kubernetes 的自动化管理能力,例如扩展、滚动更新和重调度。
  2. 调试困难

    • 由于不经过调度器管理,调试和跟踪其问题可能更加困难。
  3. 不支持高级功能

    • 例如无法通过 Deployment 或 HPA(水平自动伸缩)进行自动管理。

总结

静态 Pod 是 Kubernetes 中一种特殊的运行方式,主要用于关键组件和节点级别的任务。它由 Kubelet 直接管理,适合需要独立于控制平面运行的场景,但在管理能力和灵活性上不如常规 Pod。

xuanyuanaosheng commented 2 days ago

在 Kubernetes 中,Pod 是由一个或多个容器组成的,容器在执行过程中可能会因为各种原因退出。Kubernetes 使用容器的退出码(exit code)来表示容器的执行状态和退出原因。退出码是操作系统提供的标准方式,用于指示程序的终止状态。

Kubernetes Pod 中容器的退出码

每个容器在运行过程中都可以退出,并且退出时会返回一个退出码。退出码是一个整数,用于标识容器是否成功执行,或者失败的具体原因。

  1. 退出码 0

    • 成功:退出码为 0 表示容器执行完成且没有错误,通常用于成功的任务或正常退出的容器。
    • 例如,容器中的应用正常执行并退出时,退出码为 0。
  2. 退出码 1

    • 一般错误:退出码为 1 通常表示容器内的程序发生了错误,但并没有特别详细的错误信息。容器可能遇到了无法处理的错误并退出。
    • 例如,容器启动的应用程序配置错误或依赖项丢失,导致应用无法正常运行。
  3. 退出码 137

    • 容器被系统终止:退出码 137 表示容器由于系统的外部干预而被终止。通常是由于 SIGKILL 信号发送给容器,可能是因为资源限制(如内存限制)超出了容器的资源请求。
    • 例如,容器超过了设定的内存限制时,Kubernetes 会强制杀掉容器,从而触发退出码 137。
  4. 退出码 139

    • 段错误(Segmentation fault):退出码 139 表示容器中的程序发生了段错误。段错误通常是由于访问了无效内存或非法操作导致的程序崩溃。
  5. 退出码 143

    • 容器接收到 SIGTERM 信号:退出码 143 表示容器收到了 SIGTERM 信号,通常是 Kubernetes 或用户手动停止了容器时发生的。
    • 在正常情况下,Kubernetes 会向容器发送 SIGTERM 信号,请求容器优雅地关闭。如果容器在一定时间内没有响应,Kubernetes 会发送 SIGKILL 强制终止容器。
  6. 退出码 255

    • 未捕获的异常:退出码 255 通常表示容器中执行的程序未能正确捕获异常,导致容器异常退出。

Kubernetes 中的容器退出码相关字段

Kubernetes 会将容器的退出码和其他信息记录在 Pod 的状态中。你可以通过 kubectl 命令查看容器的状态,包括退出码。

例如,查看 Pod 的详细状态:

kubectl describe pod <pod-name>

输出中会包括容器的状态,例如:

Containers:
  <container-name>:
    Container ID:   docker://<container-id>
    Image:          <image-name>
    Image ID:       <image-id>
    Port:           <port>
    State:          Terminated
      Reason:       Completed
      Exit Code:    0

如何使用退出码进行故障排除

Kubernetes 提供了通过 Pod 状态查看容器退出码的能力。利用这些退出码,你可以进行故障排除,快速确定容器退出的原因。

  1. 容器正常退出(Exit Code: 0):容器正常执行并退出,通常不需要任何操作,可能是容器的任务完成了。
  2. 容器因错误退出(Exit Code: 1):容器执行失败,可能需要查看容器日志(kubectl logs <pod-name> -c <container-name>)来诊断问题。
  3. 容器因超出资源限制退出(Exit Code: 137):容器超出了 CPU 或内存限制,可能需要增加资源限制或优化容器应用的性能。
  4. 容器因信号终止退出(Exit Code: 143):容器被正常停止,可能是 Kubernetes 进行了滚动更新或用户手动停止了容器。

重启策略

Kubernetes 允许为 Pod 设置重启策略,通常有以下三种:

  1. Always:无论容器退出状态如何,容器都会重新启动。
  2. OnFailure:只有当容器返回非 0 的退出码时,容器才会重启。
  3. Never:容器无论退出码是多少都不会重启。

通过合理的重启策略,可以确保容器根据退出状态适当地进行重启。

总结

Kubernetes 中的 Pod 退出码是容器执行结果的一个重要指标,帮助开发者了解容器是否成功运行,或者在发生错误时追踪问题的根本原因。通过查看容器的退出码和日志,用户可以迅速定位并解决问题。

xuanyuanaosheng commented 2 days ago

下面是一个实际生产可用的deployment.ymlservice.yml, CI/CD的过程就是生成对应的K8S

apiVersion: apps/v1                    # 使用 apps/v1 API 版本来定义部署。
kind: Deployment                        # 定义资源类型为 Deployment。
metadata:
  name: dcspp-mgmt--deployment--a        # Deployment 的名称,唯一标识该部署对象。
  namespace: channels-istio             # 指定该 Deployment 属于的 Kubernetes 命名空间。
  labels:                               # 用于标识和组织资源的标签。
    app: dcspp-mgmt-a                   # 定义标签 app,其值为 dcspp-mgmt-a,用于选择 Pod。

spec:
  minReadySeconds: 10                   # Pod 准备好后的等待时间(秒),保证稳定性。
  progressDeadlineSeconds: 600          # 最大等待时间(秒),若超出则标记为失败。
  replicas: 6                           # 指定创建的 Pod 副本数。
  revisionHistoryLimit: 2               # 保留的旧版本数量,最多保留 2 个历史版本。
  selector:
    matchLabels:
      app: dcspp-mgmt-a                  # Pod 选择器,根据标签 app=dcspp-mgmt-a 来匹配 Pods。

  strategy:
    type: RollingUpdate                 # 使用滚动更新策略,逐步替换旧版 Pod。
    rollingUpdate:
      maxSurge: 50%                     # 在更新期间允许的最大额外 Pod 数量(百分比)。
      maxUnavailable: 0                 # 更新期间不可用的最大 Pod 数量为 0,确保无停机。

  template:                             # Pod 模板定义
    metadata:
      annotations:
        prometheus.io/path: /metrics                    # 指定 Prometheus 的监控路径
        prometheus.io/port: "5556"                      # Prometheus 的监控端口
        prometheus.io/scrape: "true"                    # 启用 Prometheus 数据抓取
      labels:
        app: dcspp-mgmt-a                                # Pod 的标签,用于服务发现和选择
        artifactId: dcspp-mgmt                           # 指定构件 ID
        slot: a                                         # 槽位标签,用于区分不同版本
        version: 60009.0.0                              # 应用版本

    spec:
      affinity:                                         # 节点亲和性设置
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: type                           # 指定要调度的节点类型
                    operator: In                        # 要求节点标签 type 的值必须在下面的列表中
                    values:
                      - app                             # 匹配 type=app 的节点

      containers:                                       # 容器定义
        - name: dcspp-mgmt--deployment--a                # 容器名称
          image: bruce.du.me/pre-releases/dcspp/dcspp-mgmt:60009.0.0-beta.9 # 容器镜像
          imagePullPolicy: Always                       # 每次都拉取最新镜像
          ports:
            - containerPort: 8080                       # 容器监听的第一个端口(8080),命名为 8080tcp2,协议为 TCP
              name: 8080tcp2
              protocol: TCP
            - containerPort: 6300                       # 容器监听的第二个端口(6300),协议为 TCP
              name: 6300tcp2
              protocol: TCP
            - containerPort: 5556                       # Prometheus 监控端口(5556)
              name: 5556tcp2
              protocol: TCP
          env:                                          # 环境变量定义
            - name: POD_IP                              # Pod IP 地址
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: status.podIP
            - name: POD_NAME                            # Pod 名称
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            - name: VERSION                             # 应用版本
              value: 60009.0.0-beta.9+1daac54

          livenessProbe:                                # 活性探针配置,用于监控容器的健康状态
            httpGet:
              path: dcspp-mgmt/ping                      # 访问路径
              port: 8080                                # 访问端口
              scheme: HTTP                              # 使用 HTTP 协议
            initialDelaySeconds: 30                     # 初始延迟时间(秒)
            periodSeconds: 10                           # 探测周期(秒)
            timeoutSeconds: 10                          # 探测超时时间(秒)

          readinessProbe:                               # 就绪探针配置,确保容器可接收流量
            httpGet:
              path: dcspp-mgmt/ping
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 10

          resources:                                    # 容器资源限制
            limits:
              cpu: "1"                                  # 限制容器 CPU 使用量为 1 个核
              memory: 1Gi                               # 内存限制为 1 GiB
            requests:
              cpu: 50m                                  # 最小 CPU 请求量 50 毫核
              memory: 512Mi                             # 最小内存请求量 512 MiB

          volumeMounts:                                 # 挂载卷定义
            - mountPath: /opt/pod                       # 主机路径卷挂载到 /opt/pod
              name: host-path
            - mountPath: /opt/app-cert                  # 证书卷挂载到 /opt/app-cert
              name: cacerts
            - mountPath: /opt/dcspp                      # NFS 卷挂载到 /opt/dcspp
              name: nfs-volume-1

      volumes:                                          # 卷定义
        - name: host-path                               # 定义主机路径卷
          hostPath:
            path: /data/logs/dcspp/dcspp-mgmt             # 主机上日志目录路径
            type: DirectoryOrCreate                     # 若目录不存在则创建
        - name: cacerts                                 # 定义证书密钥卷
          secret:
            secretName: baidu-cert                       # 使用名为 baidu-cert 的 Secret
            items:
              - key: tls.crt                            # Secret 中的密钥条目
                path: tls-uat.crt                       # 在容器中保存的路径
        - name: nfs-volume-1                            # 定义 NFS 卷
          nfs:
            path: /data/application/data/dcspp           # NFS 路径
            server: bjdck8snfs01.me                      # NFS 服务器地址
apiVersion: v1                             # API 版本为 v1,表示使用 Kubernetes 核心 API 组中的 v1 版本
kind: Service                               # 定义资源类型为 Service,用于在 Kubernetes 集群中暴露服务
metadata:
  name: dcspp-mgmt                           # 服务的名称,唯一标识该 Service
  namespace: channels-istio                 # 命名空间(namespace),用于隔离资源
  labels:
    artifactId: dcspp-mgmt                   # 标签,用于标识和选择特定应用的资源

spec:
  ports:                                    # 定义服务的端口映射
  - name: default                           # 端口的名称,用于在应用内部引用
    port: 80                                # 服务的端口号,客户端连接服务时使用此端口
    protocol: TCP                           # 传输协议类型,TCP 是常见的默认选项
    targetPort: 8080                        # 后端容器的端口号,与应用容器中的端口对应

  - name: jacoco                            # 另一个端口名称,提供其他服务(例如测试覆盖率服务)
    port: 6300                                # 服务的端口号,客户端连接服务时使用此端口
    protocol: TCP                            # 传输协议为 TCP
    targetPort: 6300                         # 后端容器的端口号,与应用容器中的端口对应

  selector:
    artifactId: dcspp-mgmt                   # 选择标签,用于将该服务与相同标签的 Pod 关联,使服务流量导向符合条件的 Pod

  sessionAffinity: None                      # 会话亲和性配置为 None,表示不绑定特定客户端到特定 Pod
  type: ClusterIP                                # 服务类型为 ClusterIP,默认类型,服务只在集群内部可访问