一篇文章带你玩转 Kubernetes:组件、核心概念和Nginx实战演示

一、简介

Kubernetes(这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系)。
它是一个开源的容器编排平台,解决了许多容器化应用程序在部署、管理和扩展方面面临的复杂性和挑战。最初由 Google 开发,现在由云原生计算基金会(CNCF)维护。

1.1 容器部署时代

在这里插入图片描述
这张图片展示了我们服务部署的三个时代:

  1. 传统部署时代:早期,各个组织是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用,因此会导致资源分配问题。 例如,如果在同一台物理服务器上运行多个应用程序, 则可能会出现一个应用程序占用大部分资源的情况,而导致其他应用程序的性能下降。 一种解决方案是将每个应用程序都运行在不同的物理服务器上, 但是当某个应用程式资源利用率不高时,剩余资源无法被分配给其他应用程式, 而且维护许多物理服务器的成本很高。

  2. 虚拟化部署时代:因此,虚拟化技术被引入了。虚拟化技术允许你在单个物理服务器的 CPU 上运行多台虚拟机(VM)。 虚拟化能使应用程序在不同 VM 之间被彼此隔离,且能提供一定程度的安全性, 因为一个应用程序的信息不能被另一应用程序随意访问。虚拟化技术能够更好地利用物理服务器的资源,并且因为可轻松地添加或更新应用程序, 而因此可以具有更高的可扩缩性,以及降低硬件成本等等的好处。 通过虚拟化,你可以将一组物理资源呈现为可丢弃的虚拟机集群。每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。

  3. 容器部署时代:容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM 类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。

容器因具有许多优势而变得流行起来,例如:

  • 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
  • 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。
  • 关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。
  • 可观察性:不仅可以显示 OS 级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
  • 跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。
  • 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
  • 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
  • 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
  • 资源隔离:可预测的应用程序性能。
  • 资源利用:高效率和高密度。

1.2 Kubernetes有哪些优点

容器是打包和运行应用程序的好方式
在生产环境中, 你需要管理运行着应用程序的容器,并确保服务不会下线。 例如,如果一个容器发生故障,则你需要启动另一个容器。 如果此行为交由给系统处理,是不是会更容易一些?这就是 Kubernetes 要来做的事情! Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移你的应用、提供部署模式等。

  1. 自动化部署:Kubernetes 允许用户通过配置文件定义容器化应用程序的部署、服务、存储等资源,可以自动化部署应用程序,避免了繁琐的手动操作。

  2. 自动扩展:Kubernetes 可以根据应用程序的负载自动扩展容器实例数量,从而确保应用程序的高可用性和性能。用户可以根据 CPU、内存等指标自定义自动扩展的策略。

  3. 自我修复:Kubernetes 可以检测到容器或节点的故障,并自动重新启动或迁移容器实例,确保应用程序的高可用性和稳定性。

  4. 负载均衡:Kubernetes 支持多种负载均衡策略,可以将流量均衡到多个容器实例中,从而确保应用程序的高可用性和性能。

  5. 服务发现和 DNS:Kubernetes 可以通过 Service 和 Endpoint 对象来管理容器化应用程序的服务发现和负载均衡,同时提供了内置的 DNS 服务,使得应用程序可以方便地互相通信。

  6. 配置管理:Kubernetes 可以使用 ConfigMap 和 Secret 对象来管理容器化应用程序的配置信息,可以动态更新应用程序的配置,同时确保配置的安全性。

总之,Kubernetes 解决了容器化应用程序的部署、管理、扩展、自我修复、负载均衡和配置等方面的问题,使得用户可以更加轻松地构建、部署和运行云原生应用程序。

二、Kubernetes 组件介绍

在这里插入图片描述

上图展示了k8s集群的架构,Kubernetes 集群由多个组件组成,每个组件都有不同的职责和功能,共同协作来实现容器编排、部署、管理等任务。下面是 Kubernetes 集群的主要组件:

  1. kube-apiserver:Kubernetes API 服务器,作为 Kubernetes 集群的控制面板,负责处理所有 API 请求。

  2. etcd:分布式键值存储,用于存储 Kubernetes 集群的配置数据、元数据和状态信息。

  3. kube-controller-manager:控制器管理器,负责监控集群状态变化,并自动进行调整和修复。

  4. kube-scheduler:调度器,负责将 Pod 调度到合适的节点上运行。

  5. kubelet:节点代理,负责管理节点上的容器和镜像,以及监控和报告节点状态。

  6. kube-proxy:网络代理,负责为 Pod 提供网络代理和负载均衡功能。

除了上述核心组件之外,Kubernetes 还有一些其他的组件和插件,例如:

  1. Ingress Controller:负责将外部流量路由到集群内部的服务。

  2. DNS 插件:为 Kubernetes 集群中的服务提供 DNS 解析功能。

  3. Dashboard:Web 界面,用于监控和管理 Kubernetes 集群。

  4. Helm:包管理工具,用于管理 Kubernetes 应用程序的打包、发布和升级。

三、Kubernetes 核心概念

有两种方式可以创建k8s资源:

  1. 可以通过执行kubectl命令
  2. 执行yaml资源文件

3.1 Namespace

Namespace (NS):命名空间,是 Kubernetes 中的虚拟集群,用于隔离和管理不同的资源。不同命名空间中的资源是相互独立的,同一命名空间中的资源可以直接访问。

# 查看现有的全部命名空间 
kubectl get ns 
# 构建命名空间 
kubectl create ns test
# 删除现有命名空间, 并且会删除空间下的全部资源 
kubectl delete ns test
apiVersion: v1
kind: Namespace
metadata:
 name: test

通过kubectl apply或者kubectl delete的方式部署yaml文件

kubectl apply -f yaml文件名称
kubectl delete -f yaml文件名称

3.2 Pod

Pod:是 Kubernetes 中最小的部署单元,由一个或多个容器组成。Pod 提供容器运行时的环境,同时也提供了一些共享的资源,例如网络和存储卷。

# 查看所有运行的pod
kubectl get pods -A 

# 查看指定Namespace下的Pod (默认default)
kubectl get pod -n test  

# 创建Pod
kubectl run my-nginx-pod --image=nginx -n test

# 查看Pod详细信息
kubectl describe pod my-nginx-pod -n test

# 删除pod
kubectl delete pod my-nginx-pod -n test 

# 查看pod输出的日志
kubectl logs -f my-nginx-pod -n test

# 进去pod容器内部
kubectl exec -it my-nginx-pod -- bash

# 查看kubernetes给Pod分配的ip信息,并且通过ip和容器的端口,可以直接访问
kubectl get pod -owide -n test
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx-pod
  name: nginx-pod
  namespace: test
spec:
  containers:
    - image: nginx:latest
      name: nginx

执行kubectl apply -f nginx-pod.yaml命令进行部署。

3.3 Deployment

Deployment:是用于管理 Pod 的控制器,用于创建、更新和删除 Pod。Deployment 确保 Pod 的副本数始终处于指定状态,同时支持滚动升级和回滚操作。

用Deployment启动的容器,如果直接删除Pod则会在被删除后自动再次创建pod,只有这个Deployment被删除才能永久删除pod。

# 基于Deployment启动容器
kubectl create deployment my-nginx-deployment --image=nginx -n test

# 指定副本数为3
kubectl create deployment my-nginx-deployment --image=nginx --replicas 3 -n test

# 查看现在的deployment
kubectl get deployment -n test

# 删除deployment 
kubectl delete deployment my-nginx-deployment -n test

# 基于scale实现弹性伸缩
kubectl scale deploy/my-nginx-deployment --replicas 2 -n test

#修改yaml文件
kubectl edit deploy my-nginx-deployment -n test

#更改镜像版本 Deploy可以在部署新版本数据时,成功启动一个pod,才会下线一个老版本的Pod
kubectl set image deployment/my-nginx-deployment 容器名=镜像:版本 

准备yaml文件,创建镜像为nginx,端口号为80,创建三个容器副本:

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

执行kubectl apply -f nginx-deploy.yaml命令进行部署。

3.4 Service

Service:是一组 Pod 的抽象,用于提供对这组 Pod 的访问和负载均衡。Service 可以通过集群内部 IP、DNS 名称或外部 IP(NodePort 或 LoadBalancer)提供服务。
如果不指定 service type,则创建的Service默认为ClusterIP,这种方式只能在Pod内部实现访问。
指定type为NodePort类型,可以实现Pod外暴露访问。

# 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器 默认为ClusterIP 类型
kubectl expose deployment nginx-deployment --port=8888 --target-port=80

# NodePort类型 
kubectl expose deployment nginx-deployment --port=8888 --target-port=80 --type=NodePort

kubectl get service

kubectl get svc

#以通过Deployment名称.namespace名称.svc作为域名访问,但是只能在容器内部访问
curl nginx-service.test.svc:8888

准备yaml资源文件:创建 了service,将集群的8888端口映射到容器80端口。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-service
  name: nginx-service
  namespace: test
spec:
  selector:
    app: nginx-deployment
  ports:
    - port: 8888
      protocol: TCP
      targetPort: 80

执行kubectl apply -f nginx-service.yaml命令进行部署。

3.5 Ingress

Ingress:是一种 Kubernetes 中的资源,用于将外部流量路由到集群内部的服务。Ingress 可以基于 URL、域名或 HTTP 头将流量路由到不同的服务中。

准备yaml文件创建Ingress,定义一个rule:host为nginx.deploy.com, Prefix表示去除前缀路径,转发到/ 8888端口。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: test
spec:
  ingressClassName: ingress
  rules:
  - host: nginx.deploy.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: nginx-service
              port:
                number: 8888

执行kubectl apply -f nginx-ingress.yaml命令进行部署。

四、Kubernetes 核心概念实战

接下来通过部署nginx给大家实战演示一下k8s核心概念

4.1 部署yaml文件

准备yaml资源文件:

  1. 创建Namespace为test
  2. 创建Deployment容器镜像为nginx,端口为80,副本数为2
  3. 创建Service将8888端口映射到容器的80端口
  4. 创建Ingress将nginx.deploy.com域名映射到Service
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: test
  labels:
    app: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deployment
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
        - name: nginx-deployment
          image: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: test
  labels:
    app: nginx-service
  name: nginx-service
spec:
  selector:
    app: nginx-deployment
  ports:
    - port: 8888
      protocol: TCP
      targetPort: 80
  type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-deployment-ingress
  namespace: test
spec:
  ingressClassName: ingress
  rules:
  - host: nginx.deploy.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: nginx-service
              port:
                number: 8888

使用kubectl命令查看创建情况:

kubectl get ns -A
kubectl get deploy -n test
kubectl get pods -n test
kubectl get svc -n test
kubectl get ingress -n test

在这里插入图片描述

4.2 通过Pod IP访问Nginx

通过Pod IP访问Nginx:

# 查看pod ip、节点信息
kubectl get pods -n test -o wide
curl 10.244.140.79
curl 10.244.140.80

在这里插入图片描述

4.3 通过Service IP访问Nginx

通过Service IP访问Nginx:

kubectl get svc -n test -o wide
curl 10.107.134.62:8888

在这里插入图片描述

4.4 修改index.html 演示Service负载均衡

进入nginx 容器内部修改index.html,区分不同pod演示负载均衡

kubectl get pods -n test
kubectl exec -it nginx-deployment-69cfdf5bc7-25ph9 -n test -- bash 
# 进入/usr/share/nginx/html/目录
cd /usr/share/nginx/html/
echo "1111" > index.html 
cat index.html 

#相同方法修改第二个nginx
kubectl exec -it nginx-deployment-69cfdf5bc7-82c4l -n test -- bash 

echo "2222" > index.html 

在这里插入图片描述

再次使用Service IP访问,可以看到请求是负载均衡到达pod(不过不是轮询方式)。

kubectl get svc -n test -o wide
curl 10.107.134.62:8888

在这里插入图片描述

在容器内部可以使用 Service 域名的方式负载均衡访问
域名规则为:ServiceName.Namespace.svc
进入pod内部

kubectl exec -it nginx-deployment-69cfdf5bc7-25ph9 -n test -- bash 
curl nginx-service.test.svc:8888

在这里插入图片描述

4.5 在外部通过ServiceNodePort访问Pod

因为创建的Service是NodePort类型,可以通过k8s集群任意IP+Service对外暴露的端口访问到pod:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.5 在外部使用Ingress Host访问Pod

在外部使用Ingress 配置的rule访问:
配置hosts文件,将nginx.deploy.com 映射为 k8s集群地址
在这里插入图片描述
然后再浏览器通过Ingress域名+Service的暴露端口进行访问
在这里插入图片描述

结束

本次文章内容到这里就结束了
后续博主还会继续分享k8s中ConfigMapSecret两个概念
请大家多多支持

猜你喜欢

转载自blog.csdn.net/DreamsArchitects/article/details/126300496