Kubernetes 容器平台

目录

加载中...

Kubernetes容器平台

一、 K8S 概览

   Kubernetes(简称 K8s)是一个开源的容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。来源于 Google 在2014年开源的项目,同样类似的容器编排工具还有 docker swarm/mesos 等。 官网文档: https://kubernetes.io/zh-cn/docs/concepts/architecture/

1.1  K8S 特性

平台特性

  • 可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
  • 可扩展: 模块化, 插件化, 可挂载, 可组合
  • 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展

应用特点

  • 服务发现与负载均衡:无需修改你的应用程序即可使用陌生的服务发现机制。
  • 批量执行:除了服务之外,K8s还可以管理批处理和CI工作负载,替换掉失效的容器。
  • 水平扩缩:使用一个简单的命令、一个UI或基于CPU使用情况自动对应用程序进行扩缩。
  • 存储编排:自动挂载所选存储系统,包括本地存储。
  • Secret和配置管理:部署更新Secrets和应用程序的配置时不必重新构建容器镜像,且不必暴露配置中的加密信息。
  • 自动化上线和回滚:K8s会分步骤地将应用或其配置的更改上线,同时监视应用程序运行状况确保不会同时终止所有实例。
  • 自动放置:根据资源需求和其他约束自动放置容器,同时避免影响应用的可用性。
  • 自我修复:重新启动失败的容器,在节点死亡时替换并重新调度容器,杀死不响应健康检查的容器。

k8s 的设计目标是高度可扩展和高可用的,可以在大规模的集群上运行和管理应用程序。它可以部署在各种云平台和裸机环境中,支持多种操作系统和容器运行时。k8s 已经成为容器编排领域的事实标准,被广泛应用于云原生应用的开发和运维中。

1.2 K8S 功能

k8s 提供了一套丰富的功能,用于管理容器化应用的生命周期。它的核心概念包括:

Pod:Pod 是 k8s 管理的最小调度单位,它可以包含一个或多个容器,并共享网络和存储资源。Pod 提供了容器之间的通信和协作。
Deployment:Deployment 定义了应用程序的期望状态,并负责创建和管理 Pod 的副本。它支持滚动更新、回滚和扩缩容等操作。
Service:Service 定义了一组 Pod 的访问方式和网络策略,为 Pod 提供了稳定的网络端点。Service 可以通过负载均衡将请求分发到后端的 Pod上。
Namespace:Namespace 提供了一种逻辑隔离的机制,用于将集群中的资源划分为多个虚拟集群。不同的 Namespace 可以拥有独立的资源配额、访问控制策略等。
Volume:Volume 是用于持久化数据的抽象,它可以在 Pod 之间共享和持久化存储数据。k8s 支持多种类型的 Volume,如本地磁盘、网络存储等。


   k8s 还提供了许多其他功能,包括自动扩展、存储管理、配置管理、日志和监控等。它支持水平扩展和自动化恢复,可以根据应用程序的资源需求和约束条件自动调度和 管理容器的运行。k8s 还提供了丰富的 API 和命令行工具,使得开发者和运维人员可以方便地管理和操作容器化应用。

二、 架构及组件

2.1  架构

Kubernetes 集群由一个控制平面和一组用于运行容器化应用的工作机器组成, 这些工作机器称作节点(Node)。每个集群至少需要一个工作节点来运行 Pod。

工作节点托管着组成应用负载的 Pod。控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行,而一个集群通常运行多个节点,以提供容错和高可用。

k8s 通常是集群化部署,一个 k8s 集群由一组被称作节点(Node)的机器组成,一个节点可以理解为一台服务器,这些节点上运行 k8s 所管理的容器化应用。集群具有至少一个控制节点(MasterNode)和若干工作节点(WorkNode),节点可以是物理机或者虚拟机。

2.2 主要组件

Master 组件构成了集群的管理控制中心,通常在一台虚拟机或物理机上启动所有 Master 组件。

kube-apiserver:

API 服务器公开了 Kubernetes API,负责处理接受请求的工作。 API 服务器是 Kubernetes 控制平面的前端。

etcd

一致且高可用的键值存储,用作 Kubernetes 所有集群数据的后台数据库。

kube-scheduler:

kube-scheduler 是控制平面的组件, 负责监视新创建的、未指定运行节点(node)的 Pods, 并选择节点来让 Pod 在上面运行。

kube-controller-manager:

控制平面的组件, 负责运行控制器进程。控制器有许多不同类型,在同一个进程中运行。

节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行时环境。

kubelet

在集群中每个节点(node)上运行。 接收提供给它的 PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。

kube-proxy(可选)

每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。 维护节点上的一些网络规则, 允许从集群内部或外部的网络会话与 Pod 进行网络通信。如果使用网络插件为 Service 实现本身的数据包转发,则不需要在节点上运行 kube-proxy。

容器环境Dockerd

这个基础组件使 Kubernetes 能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。支持许多容器运行环境,例如 containerd、 CRI-O 以 及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。

插件(Addons)

插件使用 Kubernetes 资源(DaemonSet、 Deployment 等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于 kube-system 命名空间。集群日志(fluentd)、Web 界面(仪表盘)、DNS、容器资源监控、网络插件。

三、 安装部署

k8s 根据使用场景不同安装方案,学习环境minikube可单机部署; 生产环境安装参照官方文档,由于组件安装比较复杂,推荐使用安装工具来安装并管理,如:KubeOperator、Kubesphere、Kubeboard。

3.1  minikube

Linux 环境下载安装:

curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64
启动程序:

minikube start

3.2 kubectl 工具

kubectl 命令工具,通过命令行管理k8s集群和应用。下载安装,集群证书保存到用户目录下。

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

kubectl cluster-info

kubectl --help

3.3  部署应用

部署应用 (deployment): echo-server

kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0
kubectl expose deployment hello-minikube --type=NodePort --port=8080

验证部署的服务:kubectl get services hello-minikube

开放服务端口:kubectl port-forward service/hello-minikube 7080:8080

访问服务: http://localhost:7080/

应用负载均衡LoadBalancer

kubectl create deployment balanced --image=kicbase/echo-server:1.0
kubectl expose deployment balanced --type=LoadBalancer --port=8080

增加 ingres 后完整配置文件 ingress-example.yaml :

kind: Pod
apiVersion: v1
metadata:
  name: foo-app
  labels:
    app: foo
spec:
  containers:
    - name: foo-app
      image: 'kicbase/echo-server:1.0'
---
kind: Service
apiVersion: v1
metadata:
  name: foo-service
spec:
  selector:
    app: foo
  ports:
    - port: 8080
---
kind: Pod
apiVersion: v1
metadata:
  name: bar-app
  labels:
    app: bar
spec:
  containers:
    - name: bar-app
      image: 'kicbase/echo-server:1.0'
---
kind: Service
apiVersion: v1
metadata:
  name: bar-service
spec:
  selector:
    app: bar
  ports:
    - port: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
    - http:
        paths:
          - pathType: Prefix
            path: /foo
            backend:
              service:
                name: foo-service
                port:
                  number: 8080
          - pathType: Prefix
            path: /bar
            backend:
              service:
                name: bar-service
                port:
                  number: 8080
---

kubectl apply -f ingress-example.yaml

检查应用:kubectl get ingress

访问服务:

$ curl <ip_from_above>/foo

四、命名空间和Pod

4.1 Namespace

  命名空间(Namespace) 使用名称提供了一个范围,集群中的资源划分为相互隔离的组,资源名称(如pod、services、replication controllers或其他)在命名空间内唯一性,命名空间是用来隔离资源的,不隔离网路。

从两个初始命名空间开始:

  • default

    kubernetes 默认的命名空间,无需创建新的命名空间即可开始使用新集群。

  • kube-system

    该命名空间使用kubernetes系统创建的对象。

通过命令(或者yaml)创建:

kubectl create namespace test-ns

查看:kubectl get namespaces

删除:kubectl delete namespace test-ns

kubectl 调配资源时,使用参数  --namespace=命名空间  指明所在的命名空间(短参数 -n ),未指定则为 default

底层资源(如Node和persistentVolumes)不在任何Namespace中。Events也可能没有Namespace,具体取决于Events的对象。

4.2 Pod

  Pod 是在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod(豌豆荚)是一组(一个或多个) 容器; 这些容器共享存储、网络和容器的规约,其中包含一个或多个应用容器。

通常不需要直接创建Pod,而用工作负载 Deployment、 StatefulSet、 DaemonSet这类资源来创建 Pod。

资源存储共享和网络通信
一个 Pod 可以设置一组共享的存储卷。
每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。 Pod 中的每个容器共享网络名字空间,IP 地址和网络端口。 Pod 内的容器可以使用 localhost 互相通信。 当 Pod 中的容器与 Pod 之外的实体通信时,必须协调如何使用共享的网络资源(例如端口)。
安全设置: 要对 Pod 和容器设置安全约束,请使用 Pod 规约中的 securityContext 字段

有些 Pod 具有 Init 容器和 应用容器。 Init 容器默认会在启动应用容器之前运行并完成如文件目录权限。还可以拥有为主应用 Pod 提供辅助服务的边车容器。

五、应用(工作负载)

  应用在k8s统一是为工作负载(workload),应用根据运行状态分为Deployment、 StatefulSet、 DaemonSet。

5.1 Deployment(无状态)

  Deployment 用于管理运行一个应用负载的一组 Pod,通常适用于不保持状态的负载,如web服务。为 Pod 和 ReplicaSet 提供声明式的更新能力。

Deployment 示例。其中创建了一个 ReplicaSet,负责启动三个 nginx Pod创建一个使用文件

https://k8s.io/examples/controllers/nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

部署:kubectl apply -f  nginx-deployment.yaml

查看: kubectl get deployments

kubectl rollout status deployment/nginx-deployment

kubectl get rs

kubectl describe deployments

历史

kubectl rollout history deployment/nginx-deployment

kubectl rollout undo deployment/nginx-deployment

伸缩:

kubectl set image deployment/nginx-deployment nginx=nginx:sometag

kubectl scale deployment/nginx-deployment --replicas=10

kubectl autoscale rs frontend --max=10 --min=3 --cpu-percent=50

创建Deployment后,master将应用程序实例调整到集群中的各个节点上。如果运行实例的节点关闭或被删除,控制器会将该实例替换为集群中另一个节点上的实例,这提供了一种自我修复机制。

ReplicaSet

ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 然而,Deployment 是一个更高级的概念,它管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此,使用 Deployment 而不是直接使用 ReplicaSet。

实际上意味着,可能永远不需要操作 ReplicaSet 对象:而是使用 Deployment,并在 spec 部分定义应用。

5.2 StatefulSet(有状态)

  StatefulSet 运行一组 Pod,并为每个 Pod 保留一个稳定的标识。 这可用于管理需要持久化存储或稳定、唯一网络标识的应用,如数据库应用。

StatefulSet 管理基于相同容器规约的一组 Pod。 为每个 Pod 维护了一个有粘性的 ID,无论怎么调度,每个 Pod 都有一个永久不变的 ID。如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。

示例   https://k8s.io/examples/application/web/web.yaml:

apiVersion: v1
kind: Service
metadata:
 name: nginx
 labels:
 app: nginx
spec:
 ports:
 - port: 80
 name: web
 clusterIP: None
 selector:
 app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 selector:
 matchLabels:
 app: nginx # 必须匹配 .spec.template.metadata.labels
 serviceName: "nginx"
 replicas: 3 # 默认值是 1
 minReadySeconds: 10 # 默认值是 0
 template:
 metadata:
 labels:
 app: nginx # 必须匹配 .spec.selector.matchLabels
 spec:
 terminationGracePeriodSeconds: 10
 containers:
 - name: nginx
 image: registry.k8s.io/nginx-slim:0.24
 ports:
 - containerPort: 80
 name: web
 volumeMounts:
 - name: www
 mountPath: /usr/share/nginx/html
 volumeClaimTemplates:
 - metadata:
 name: www
 spec:
 accessModes: [ "ReadWriteOnce" ]
 storageClassName: "my-storage-class"
 resources:
 requests:
 storage: 1Gi

kubectl apply -f  web.yaml
kubectl get statefulset web
kubectl get service nginx

kubectl scale sts web --replicas=5


持久化存储 PersistentVolumeClaim,示例策略:
apiVersion: apps/v1
kind: StatefulSet
...
spec:
 persistentVolumeClaimRetentionPolicy:
 whenDeleted: Retain
 whenScaled: Delete
...

持久卷部署 WordPress 和 MySQL示例:https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml

5.3 DaemonSet(守护)

  DaemonSet 定义了提供节点本地设施的 Pod。这些设施可能对于集群的运行至关重要,例如网络辅助工具,或者作为 add-on 的一部分。一些典型用法:

  • 在每个节点上运行集群守护进程
  • 在每个节点上运行日志收集守护进程
  • 在每个节点上运行监控守护进程

一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志。典型应用如 prometheus 监控,后台服务如存储CSI插件。

示例:https://k8s.io/examples/controllers/daemonset.yaml

Daemon Pods 调度确保所有符合条件的节点都运行该 Pod 的一个副本,

nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchFields:
 - key: metadata.name
 operator: In
 values:
 - target-host-name

节点污点(Taint)和容忍度(Toleration):DaemonSet 控制器会自动将一组容忍度添加到 DaemonSet Pod

六、服务和网络

  Service 是将运行在一个或一组 Pod 上的网络应用程序公开为网络服务。

6.1 集群网络

  集群网络系统是 Kubernetes 的核心部分。处理:Pod 间通信(Pod内容器直接通信);Pod 与 Service 间通信;外部与 Service 间通信。

Kubernetes 集群需要从以下组件中配置的可用地址范围中为 Pod、Service 和 Node 分配不重叠的 IP 地址:

  • 网络插件配置为向 Pod 分配 IP 地址。
  • kube-apiserver 配置为向 Service 分配 IP 地址。
  • kubelet 或 cloud-controller-manager 配置为向 Node 分配 IP 地址。

 

网络模型可选Flannel、Calico插件。

6.2 服务(Service)

  Service 将在集群中运行的应用通过同一个面向外界的端点公开出去,即使工作负载分散于多个后端也完全可行。

kubectl expose deployment/my-nginx

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

kubectl get svc my-nginx

Service创建时被分配一个唯一的 IP 地址(clusterIP),与 Pod通信同时还被自动地负载均衡使用。

访问 Service:支持两种查找服务的主要模式:环境变量和 DNS,后者则需要 CoreDNS 集群插件。

Service加载tls证书,配置证书和configmap实现加密保存,加载http 服务。

Service 映射到外部 IP 地址上两种方式:NodePort 和 LoadBalancer。

Service 类型:

ClusterIP 通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。
NodePort: 通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问。LoadBalancer: 使用云平台的负载均衡器向外部公开 Service。或者安装负载均衡组件。
ExternalName将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。 该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。

6.3 Ingress

  Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。

Ingress 可为 Service 提供外部可访问的 URL、对其流量作负载均衡、 终止 SSL/TLS,以及基于名称的虚拟托管等能力。通常使用 Service.Type=NodePort 或  Service.Type=LoadBalancer 类型的 Service。

主机名通配符

主机名可以是精确匹配(例如 “foo.bar.com”)或者使用通配符来匹配 (例如 “*.foo.com”)。

扇出(Fanout)配置根据请求的 HTTP URI 将来自同一 IP 地址的流量路由到多个 Service。 Ingress 允许将负载均衡器的数量降至最低。

基于名称的虚拟主机服务

基于名称的虚拟主机支持将针对多个主机名的 HTTP 流量路由到同一 IP 地址上。

TLS证书

使用配置 TLS 证书的Secret 来保护 流量。 Ingress 资源只支持一个 TLS 端口 443。 如果 Ingress 中的 TLS 配置部分指定了不同主机,那么它们将通过 SNI TLS 扩展指定的主机名(如果 Ingress 控制器支持 SNI)在同一端口上进行复用。 TLS Secret 的数据中必须包含键名为 tls.crt 的证书和键名为 tls.key 的私钥, 才能用于 TLS 目的。

Ingress控制器

实现ingress控制器可选云平台集成,或者 traefik/nginx等

七、存储

  为容器实现数据的存储,PV(PersistentVolume)、PVC(PersistentVolumeClaim)、StorageClass、CSI。

7.1 持久卷(PV)

  emptyDir(临时目录) 用于数据的临时存储; hostPath(宿主机目录映射); 使用插件支持多种常用存储。

使用PVC(PersistentVolumeClaim)申请获得 PV(PersistentVolume)。

apiVersion: v1
kind: PersistentVolume
metadata:
 name: pv0003
spec:
 capacity:
 storage: 5Gi
 volumeMode: Filesystem
 accessModes:
 - ReadWriteOnce
 persistentVolumeReclaimPolicy: Recycle
 storageClassName: slow
 mountOptions:
 - hard
 - nfsvers=4.1
 nfs:
 path: /tmp
 server: 172.17.0.2
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: foo-pvc
 namespace: foo
spec:
 storageClassName: "" # 此处须显式设置空字符串,否则会被设置为默认的 StorageClass
 volumeName: foo-pv
 ...
apiVersion: v1
kind: PersistentVolume
metadata:
 name: foo-pv
spec:
 storageClassName: ""
 claimRef:
 name: foo-pvc
 namespace: foo
 ...
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
 name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
 resturl: "http://192.168.10.100:8080"
 restuser: ""
 secretNamespace: ""
 secretName: ""
allowVolumeExpansion: true

7.2 存储类(SC)

  StorageClass为集群提供了使用不同存储的方法。

sc-nfs.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: "false"

Ceph RBD(已弃用)  Kubernetes v1.28

####