Advertisement

Kubernetes: The Ultimate Guide to Deploying Containeriz

阅读量:

作者:禅与计算机程序设计艺术

1.简介

云计算正在改变 IT 的世界。Kubernetes 是当今容器编排领域的事实标准,它通过自动化部署、扩展和管理容器化应用成为云基础设施中不可或缺的一部分。本专业技术博客文章旨在帮助读者掌握 Kubernetes 及其相关技术的知识和技能,构建云上基于 Kubernetes 的高可用、弹性、易扩展的容器化应用架构,解决实际场景中的问题。

2. 基本概念术语说明

2.1 Kubernetes 简介

Kubernetes (K8s) 是 Google 推出的开源容器集群管理系统,其用于管理云平台上多种类型的容器化应用。从 v1.0 版本起,K8s 成为云计算领域里最热门的容器调度框架,已经成为事实上的标准。K8s 提供了声明式 API 和强大的可扩展性,能够让开发人员轻松创建、组合和管理容器化应用。

2.2 控制器模式

Kubernetes 中,控制器就是一个运行在集群外的后台进程,它根据集群当前状态和用户的指令来对集群进行重新配置、滚动升级等操作。在 K8s 中,控制器主要分成两类:

  1. 副本控制器(ReplicaSet Controller):负责确保期望数量的 Pod 在任何时刻都保持运行。

  2. Deployment Controller:Deployment 是 Kubernetes 中的资源对象之一,用来描述一个部署,包括一个固定的 Pod 模板和多个基于 Label Selector 的目标 Pod。Deployment Controller 通过 ReplicaSet 来实现 Pod 水平扩展,并提供更新过程的暂停、回滚和扩缩容功能。

2.3 核心组件

K8s 有着复杂的架构,包括以下核心组件:

  1. Kubelet:运行在每个节点上,负责维护运行容器所需的所有信息。

  2. kube-proxy:运行在每个节点上,作为网络代理,负责维护集群内部服务之间通信的规则和转发数据包。

  3. etcd:用于存储集群元数据的分布式 key-value 数据库。

  4. control plane:包括主控器(Controller Manager)和 API 服务(API Server)。主控器运行控制循环,API 服务处理客户端请求并响应。

  5. kubelet、kube-proxy、etcd 和控制面都运行在集群的各个节点上,并通过 Master 节点进行协调。

2.4 Namespace 机制

Namespace 是一种虚拟隔离环境,用来将不同团队或者项目的工作负载进行逻辑划分和隔离。K8s 支持多租户并且可以通过命名空间实现资源的隔离。通过命名空间,可以将资源如 Pod、Service 分组到不同的环境中,比如测试环境、开发环境、生产环境等。

2.5 Secret 机制

Secret 是 Kubernetes 中用来保存敏感信息如密码、密钥等的资源类型。Pod 创建的时候可以指定所需要的 Secret,然后 kubelet 会自动把 Secret 中的数据注入到 Pod 的文件系统中。这样就不用再把密码暴露在 Pod 的镜像层中了,提升了安全性。

2.6 Service 机制

Service 是 K8s 中用于暴露容器服务的资源类型,它会给 Pod 分配一个稳定且唯一的网络 IP 地址和端口,通过这个 IP 地址就可以访问到对应的容器,还可以通过 Label Selector 指定 Service 想要代理哪些 Pod。而 Service 有两种类型:

  1. ClusterIP:默认类型,只有内部的 Pod 可以访问。

  2. NodePort:对外开放,可以在任意端口暴露 Pod 服务,所有集群内的主机都可以直接访问。

2.7 ConfigMap 机制

ConfigMap 是 Kubernetes 中用来保存配置信息的资源类型。Pod 启动时可以引用 ConfigMap 中的数据,也可以在运行过程中更新 ConfigMap 中的数据,这样无需重启 Pod 即可完成配置更新。

2.8 RBAC 机制

RBAC (Role-Based Access Control),即基于角色的权限控制,是 Kubernetes 用来授权访问权限的机制。通过 RBAC,可以细粒度地分配各个用户在集群中的权限,并使得 Kubernetes 集群更加安全可靠。

2.9 其他关键组件

除了以上核心组件,还有以下几个关键组件:

  1. DNS:通过 DNS,可以方便地访问 Kubernetes 集群内的服务。

  2. Ingress:Ingress 是 Kubernetes 中用来暴露 HTTP/HTTPS 服务的资源类型,通过 Ingress,可以实现反向代理、负载均衡、基于名称的虚拟主机以及 TLS 终止。

  3. Horizontal Pod Autoscaler (HPA):HPA 根据 CPU 使用率或内存使用量对 Deployment 或 ReplicaSet 中的 Pod 进行自动伸缩。

  4. Storage Class:Storage Class 用来动态配置 PV 的类别、大小和访问模式。

3. Kubernetes 核心算法原理

3.1 Kubernetes 编排流程图

如下图所示,Kubernetes 编排流程如下:

  1. 用户提交 YAML 文件或 JSON 配置至 Kubernetes API Server;

  2. API Server 将 YAML 文件转换成 API 对象;

  3. API Server 验证 API 对象是否符合 Kubernetes 规定的规范;

  4. 如果 API 对象合法,API Server 将 API 对象存入 Etcd 中;

  5. Kubernetes Controller Manager 从 Etcd 中获取待处理的 API 对象;

  6. Kubernetes Controller Manager 检查该 API 对象是否符合 Kubernetes 资源控制器的要求(如 Deployment 需要满足一定数量的 Pod),如果资源控制器支持该资源类型,则调用相应的资源控制器来处理 API 对象;

  7. 资源控制器检查该 API 对象,并对其进行必要的检查和修改(如生成或删除 Pod),然后将修改后的 API 对象存入 Etcd;

  8. Kubernetes Scheduler 检查新的或变更后的 API 对象,选择合适的 Node 执行该对象的 Pod,并将执行结果写入 Etcd。

  9. Kubernetes Controller Manager 根据 Etcd 中资源状态的变化来更新集群状态。

  10. 节点上的 kubelet 监听 Etcd 获取集群状态,并执行实际的工作负载。

3.2 节点选择算法

Kubernetes 节点选择算法主要由两个部分组成,分别是过滤和排序。

3.2.1 过滤阶段

过滤阶段由 scheduler 组件进行处理,主要依据有以下几点:

  • 硬件资源(CPU、内存、磁盘):节点具有的特定资源(比如 CPU、内存)决定了能否被调度,只有具备充足资源的节点才可以被调度;
  • 时间约束:kube-scheduler 通过优先级和抢占机制保证 QoS 最高的任务得到处理机资源;
  • 硬件亲和性:kube-scheduler 可以指定某些标签(label)的节点只能被调度到,可以限制特定的应用程序运行在特定机器上;
  • 软硬件约束条件:kube-scheduler 可以定义软硬件约束条件,当节点的某个标签满足条件时才能被调度;
  • 节点污染:kube-scheduler 可以监测节点的污染情况,限制一些特定标签的节点被调度;

过滤完毕后,剩余的节点列表按照优先级进行排序,先考虑 Pod 的重要性和紧迫程度,再考虑 Node 上的资源利用率。

3.2.2 排序阶段

排序阶段由 priority function 决定的,它是一个函数,通过输入包括 Pod 信息、节点信息等参数,输出是一个数字,代表当前节点的优先级。优先级越高,则优先被选中。排序阶段根据 priority function 对节点列表进行排序。

3.3 资源控制器机制

Kubernetes 的资源控制器主要是指 deployment、statefulset、daemonset、job、cronjob 这几类资源。这些控制器定义了 Pod 模板、集群节点的选择范围、Pod 生命周期、Pod 重试策略、滚动升级策略等。这些控制器通过管理 pod 的运行方式,达到应用发布和管理的目的。

3.4 自动伸缩机制

Kubernetes 的自动伸缩机制主要由 HPA (Horizontal Pod Autoscaler)控制器和 VPA (Vertical Pod Autoscaler)控制器构成。前者基于 pod 的使用率自动增加或减少 pod 的个数,后者根据 pod 的资源使用情况自动调整 pod 的资源限制和请求。

3.5 调度器

Kubernetes 调度器基于多维度的资源约束和节点的资源状况,为新创建的 pod 选择最佳的宿主机节点。

4. 具体代码实例和解释说明

4.1 最小示例

创建一个名为 nginx 的 deployment,每个 pod 中有一个 nginx 容器:

复制代码
    apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
    kind: Deployment
    metadata:
    name: nginx-deployment
    labels:
    app: nginx
    spec:
    replicas: 3 # by default is 1
    selector:
    matchLabels:
    app: nginx
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

该 Deployment 配置创建了一个名为 nginx 的 Deployment,创建三个 pod ,每个 pod 中有一个 nginx 容器,对应于上面 YAML 文件中的 replicas 参数值。可以通过 kubectl create -f <file> 命令创建该 Deployment。

查看 Deployment 的详细信息:

复制代码
    $ kubectl describe deployment nginx-deployment
    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Sun, 03 Sep 2020 14:27:28 +0800
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision: 1
    Selector:               app=nginx
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
    Labels:           app=nginx
    Annotations:      <none>
    Containers:
    nginx:
    Image:        nginx:1.7.9
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
    Volumes:        <none>
    Conditions:
    Type           Status  Reason
    ----           ------  ------
    Available      True    MinimumReplicasAvailable
    Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   nginx-deployment-7c9ccdc5d8 (3/3 replicas created)
    Events:
    Type    Reason             Age   From                   Message
    ----    ------             ----  ----                   -------
    Normal  ScalingReplicaSet  2m    horizontal-pod-autoscaler  Scaled up replica set nginx-deployment-7c9ccdc5d8 to 1
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

可以通过 kubectl get pods 命令查看到三个 pod 已成功创建。

编辑 Deployment 的 YAML 文件:

复制代码
    ......
    containers:
    - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
    resources:
    requests:
    cpu: "200m"
    memory: "64Mi"
    limits:
    cpu: "500m"
    memory: "256Mi"
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

添加 resources 字段来设置容器的资源请求和限制。保存退出。

复制代码
    $ kubectl apply -f /path/to/your/nginx-deployment.yaml --record # add "--record" flag to record the command history in the resource's annotation field
    deployment.apps/nginx-deployment configured
    
      
    
    代码解读

查看 Deployment 的详细信息:

复制代码
    $ kubectl describe deployment nginx-deployment
    ......
    Containers:
    nginx:
    Image:        nginx:1.7.9
    Port:         80/TCP
    Host Port:    0/TCP
    Requests:
    cpu:        200m
    memory:     64Mi
    Limits:
    cpu:        500m
    memory:     256Mi
    ......
    
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

确认该 Deployment 的资源限制和请求配置正确生效。

删除 Deployment:

复制代码
    $ kubectl delete deployment nginx-deployment
    deployment.apps "nginx-deployment" deleted
    
      
    
    代码解读

确认三个 pod 已停止运行。

4.2 Service 示例

创建一个 nginx service:

复制代码
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: my-service
    spec:
    type: LoadBalancer
    ports:
    - port: 80
    targetPort: 80
    selector:
    app: nginx
    
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

该 Service 配置创建了一个名为 my-service 的 Service,类型为 LoadBalancer,目标端口为 80,selector 为 app=nginx,对应于上面 YAML 文件中的 portstargetPortselector。可以通过 kubectl create -f <file> 命令创建该 Service。

查看 Service 的详细信息:

复制代码
    $ kubectl describe service my-service
    Name:                     my-service
    Namespace:                default
    Labels:                   <none>
    Annotations:              <none>
    Selector:                 app=nginx
    Type:                     LoadBalancer
    IP:                       10.109.16.37
    LoadBalancer Ingress:     xxxxxxx
    Port:                     http  80/TCP
    TargetPort:               80/TCP
    NodePort:                 http  31904/TCP
    Endpoints:                172.22.12.2:80,172.22.13.2:80,172.22.13.3:80 + 3 more...
    Session Affinity:         None
    External Traffic Policy:  Cluster
    HealthCheck NodePort:     30029
    Events:                   <none>
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

可以通过 kubectl get svc 命令查看到 my-service 已经成功创建。

编辑 Service 的 YAML 文件:

复制代码
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: my-service
    spec:
    type: LoadBalancer
    externalTrafficPolicy: Local
    ports:
    - port: 80
    targetPort: 80
    selector:
    app: nginx
    
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

添加 externalTrafficPolicy 字段设置为 Local,表示只将流量导入目标节点。保存退出。

复制代码
    $ kubectl apply -f /path/to/your/my-service.yaml 
    service/my-service unchanged
    
      
    
    代码解读

查看 Service 的详细信息:

复制代码
    $ kubectl describe service my-service
    Name:                     my-service
    Namespace:                default
    Labels:                   <none>
    Annotations:              <none>
    Selector:                 app=nginx
    Type:                     LoadBalancer
    IP:                       10.109.16.37
    LoadBalancer Ingress:     xxxxxxx
    Port:                     http  80/TCP
    TargetPort:               80/TCP
    NodePort:                 http  31904/TCP
    Endpoints:                172.22.12.2:80,172.22.13.2:80,172.22.13.3:80 + 3 more...
    Session Affinity:         None
    External Traffic Policy:  Local
    HealthCheck NodePort:     30029
    Events:                   <none>
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

确认 externalTrafficPolicy 设置生效。

删除 Service:

复制代码
    $ kubectl delete service my-service
    service "my-service" deleted
    
      
    
    代码解读

确认 my-service 已删除。

全部评论 (0)

还没有任何评论哟~