1.1 Namespace命名空间
1.1.1 Namespace核心概念
Kubernetes 的 Namespace(命名空间)是一种用于创建逻辑隔离分区的机制,它的主要作用是用来实现多套环境的资源隔,它允许用户在同一个物理集群中模拟出多个虚拟集群的效果。以下是 Namespace 的一些关键特点和用途:
-
资源隔离:Namespace 允许你将集群内的资源划分为不同的组,每个组内的资源是相互隔离的。这可以防止不同组之间的资源冲突,提高集群的安全性。
-
多租户支持:通过为每个租户分配一个独立的 Namespace,Kubernetes 可以支持多租户部署。每个租户只能在自己的 Namespace 内创建和管理资源,无法访问其他 Namespace 的资源。
-
资源配额:Kubernetes 允许你为每个 Namespace 设置资源配额(Resource Quotas),限制该 Namespace 可以使用的资源总量(如 CPU、内存等)。这有助于防止资源的过度使用,并确保关键应用有足够的资源可用。
-
命名空间的生命周期管理:Namespace 有其生命周期,可以被创建、配置、删除等。通过管理 Namespace 的生命周期,可以更好地控制资源的分配和使用。
-
默认命名空间:在 Kubernetes 中,
default
是一个特殊的 Namespace,如果没有明确指定 Namespace,所有的资源默认会被创建在default
Namespace 中。 -
授权和访问控制:Kubernetes 的 RBAC(基于角色的访问控制)机制允许你为不同的 Namespace 设置不同的权限,控制用户对资源的访问。
-
网络隔离:虽然 Kubernetes 的 Namespace 主要用于逻辑隔离,但也可以与网络策略(Network Policies)结合使用,实现一定程度的网络隔离。
-
监控和日志:在 Namespace 级别进行监控和日志记录可以简化管理,因为你可以针对特定的 Namespace 进行资源使用分析和问题排查。
-
部署和测试:Namespace 常用于开发、测试和生产环境的隔离。例如,开发团队可以在自己的 Namespace 中部署和测试新的应用版本,而不会影响到生产环境。
-
清理资源:Namespace 可以方便地用于资源的批量删除。当你需要删除一个项目或应用的所有资源时,只需删除对应的 Namespace 即可。
kubernetes在集群启动之后,会默认创建几个namespace
[root@K8s-master ~]# kubectl get namespaces NAME STATUS AGE default Active 2d19h #创建资源时没有指定特定的Namespace,会被自动分配到 default Namespace中 kube-node-lease Active 2d19h #集群节点之间的心跳维护,v1.13开始引入 kube-public Active 2d19h #此命名空间下的资源可以被所有人访问(包括未认证用户) kube-system Active 2d19h #所有由Kubernetes系统创建的资源都处于这个命名空间
1.1.2 基本操作
1.1.2.1 查看
[root@K8s-master ~]# kubectl get namespaces NAME STATUS AGE default Active 2d19h kube-node-lease Active 2d19h kube-public Active 2d19h kube-system Active 2d19h [root@K8s-master ~]# kubectl get ns #ns为简写 NAME STATUS AGE default Active 2d19h kube-node-lease Active 2d19h kube-public Active 2d19h kube-system Active 2d19h [root@K8s-master ~]# kubectl get ns default #查看指定的命名空间 NAME STATUS AGE default Active 2d19h [root@K8s-master ~]# kubectl get ns default -o yaml #-o指定查看格式 apiVersion: v1 kind: Namespace metadata:creationTimestamp: "2024-05-04T06:23:23Z"labels:kubernetes.io/metadata.name: defaultname: defaultresourceVersion: "199"uid: 6568a7d2-64a2-484f-a01d-aa914ad9f8f0 spec:finalizers:- kubernetes status:phase: Active [root@K8s-master ~]# kubectl get ns default -o json {"apiVersion": "v1","kind": "Namespace","metadata": {"creationTimestamp": "2024-05-04T06:23:23Z","labels": {"kubernetes.io/metadata.name": "default"},"name": "default","resourceVersion": "199","uid": "6568a7d2-64a2-484f-a01d-aa914ad9f8f0"},"spec": {"finalizers": ["kubernetes"]},"status": {"phase": "Active"} } [root@K8s-master ~]# kubectl describe ns default #查看详情 Name: default Labels: kubernetes.io/metadata.name=default Annotations: <none> Status: Active No resource quota. No LimitRange resource.
1.1.2.2 创建删除
[root@K8s-master ~]# kubectl create ns test namespace/test created [root@K8s-master ~]# kubectl delete ns test namespace "test" deleted [root@K8s-master ~]# vim test.yml #yaml文件创建 --- apiVersion: v1 kind: Namespace metadata:name: test [root@K8s-master ~]# kubectl apply -f test.yml namespace/test created [root@K8s-master ~]# kubectl get ns test NAME STATUS AGE test Active 10s [root@K8s-master ~]# kubectl delete ns test namespace "test" deleted
1.2 Pod最小调度单元
-
Pod 在 Kubernetes 中是最基本的部署单元,它是一个逻辑实体,用于封装一个或多个容器(通常是 Docker 容器),这些容器共享网络和存储资源。Pod 的设计目的是作为运行应用程序的一个单元,使得容器可以作为一个整体进行管理。
1.2.1 Pod 的核心概念
特性 | 描述 |
---|---|
共享资源 | Pod 内的容器共享网络和存储资源,如存储卷和网络接口。 |
协同工作 | Pod 支持运行协同工作的容器,它们可以作为一个整体运行。 |
生命周期管理 | Pod 内的容器要么同时运行,要么同时停止,便于统一管理。 |
环境隔离 | 每个 Pod 拥有独立的 IP 地址和运行环境,实现资源隔离。 |
易于部署和管理 | Pod 作为部署单元,简化了容器化应用程序的部署和管理。 |
服务发现和负载均衡 | Pod 可以被 Kubernetes 服务发现,支持负载均衡。 |
健康检查 | Kubernetes 可以对 Pod 进行健康检查,并在必要时重启容器。 |
标签和选择器 | Pod 可以被赋予标签,与选择器结合使用,实现基于标签的管理。 |
kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。
[root@K8s-master ~]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-74586cf9b6-96v5x 1/1 Running 0 2d19h coredns-74586cf9b6-f5q7h 1/1 Running 0 2d19h etcd-k8s-master 1/1 Running 0 2d19h kube-apiserver-k8s-master 1/1 Running 0 2d19h kube-controller-manager-k8s-master 1/1 Running 0 2d19h kube-flannel-ds-6gqmv 1/1 Running 0 2d18h kube-flannel-ds-g7zcj 1/1 Running 0 2d18h kube-flannel-ds-hh52b 1/1 Running 0 2d18h kube-proxy-glhml 1/1 Running 0 2d18h kube-proxy-klcs2 1/1 Running 0 2d18h kube-proxy-x9v8k 1/1 Running 0 2d19h kube-scheduler-k8s-master 1/1 Running 0 2d19h - coredns:提供集群内部的 DNS 服务。 - etcd:用于存储集群状态的分布式键值存储。 - kube-apiserver:API 服务器,对外提供 Kubernetes API。 - kube-controller-manager:控制器管理器,负责各种控制器的运行。 - kube-flannel-ds:Flannel 是一个网络插件,提供覆盖网络。 - kube-proxy:负责实现 Kubernetes 服务的网络代理。 - kube-scheduler:调度器,负责 Pod 的调度。
1.2.2 Pod的基本操作
1.2.2.1 创建并运行
-
kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
-
命令格式: kubectl run (pod控制器名称) [参数]
-
kubectl run (pod控制器名称):这是创建 Pods 的基本命令格式,其中
pod控制器名称
是您希望给这个 Pod 控制器(通常是 Deployment 或 Pod)的名称。
-
--image:指定用于创建 Pod 的容器镜像的名称。这个参数是必须的,因为 Kubernetes 需要知道使用哪个镜像来运行容器。
-
--port:指定容器内部的端口,以便 Kubernetes 可以知道如何将容器的端口映射到 Pod 上。这通常用于服务发现和负载均衡。
-
--namespace:指定 Pod 应该创建在哪个 Kubernetes Namespace 中。如果不指定,默认是在
default
Namespace。
-
--replicas:指定创建的 Pod 副本数量。对于 Deployment 类型的控制器,默认为 1。
-
--labels:为 Pod 添加标签,以便于后续的查询和选择。
-
--env:设置环境变量,传递给容器的配置信息。
-
--restart:设置重启策略,如
Always
、OnFailure
或Never
。
-
--overrides:用于指定一个 JSON 格式的字符串,其中包含一个或多个字段,用于覆盖生成的 Pod 模板。
-
[root@K8s-master ~]# kubectl run nginx --image=nginx --port=80 --namespace test #拉圈一个Nginx镜像 pod/nginx created [root@K8s-master ~]# kubectl get pod -n test NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 10s [root@K8s-master ~]# kubectl get pod -n test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 1/1 Running 0 2m40s 10.244.2.3 k8s-node-02 <none> <none>
1.2.2.2 访问Pod
[root@K8s-master ~]# curl 10.244.2.3 #只能再集群内部访问 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
1.2.2.3 删除指定Pod
[root@K8s-master ~]# kubectl delete pod nginx -n test pod "nginx" deleted [root@K8s-master ~]# kubectl get pods -n test No resources found in test namespace.
1.2.2.4 配置写法
[root@K8s-master ~]# vim nginx.yml --- apiVersion: v1 kind: Pod metadata:name: nginxnamespace: test spec:containers:- image: nginxname: podports:- name: nginx-portcontainerPort: 80protocol: TCP [root@K8s-master ~]# kubectl apply -f nginx.yml pod/nginx created [root@K8s-master ~]# kubectl get pod -n test NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 14s
1.3 Label标签
在 Kubernetes 中,Label(标签)是一种附加到资源(如 Pods、Services、Deployments 等)上的键值对,用于标识资源的特征或属性。Label 的设计目的主要是为了帮助用户以灵活和强大的方式来组织和选择资源。
1.3.1 Label特性
-
键值对:Label 是由一个键(Key)和一个值(Value)组成的,例如
environment=production
。 -
资源标识:Label 允许用户为资源定义自定义标识符,这些标识符可以用于区分和选择资源。
-
选择器(Selectors):Kubernetes 中的选择器可以根据 Label 来选择一组资源。例如,一个 Deployment 可以定义一个选择器来指定它应该管理哪些带有特定 Label 的 Pods。
-
批量操作:通过 Label,用户可以轻松地对带有相同 Label 的资源执行批量操作,如启动、停止或更新一组 Pods。
-
组织和分类:Label 可以用于不同的目的,比如环境(开发、测试、生产)、应用程序版本、服务所有者等。
-
动态查询:Kubernetes 提供了基于 Label 的查询功能,允许用户动态查询带有特定 Label 的资源。
-
无需预定义:与某些系统不同,Kubernetes 不要求预定义 Label。用户可以根据自己的需要自由地添加和使用 Label。
-
不唯一性:单个资源可以有多个 Label,且 Label 本身不要求唯一性。
-
命名空间内有效:Label 在定义它们的命名空间内有效,不同命名空间的资源可以有相同的 Label。
-
用于服务发现:在某些情况下,Label 可以用于服务发现,尤其是当结合服务选择器(Service Selectors)时。
1.3.2 Label 的使用场景:
-
版本标签:用于标识资源的版本,如
version: release
或version: stable
。 -
环境标签:用于标识资源所属的环境,如
environment: dev
、environment: test
或environment: prod
。 -
架构标签:用于标识资源在系统架构中的角色,如
tier: frontend
或tier: backend
。
1.3.3 Label Selector标签选择器
-
Label Selector 用于查询和筛选具有特定标签的资源对象。
1.3.3.1 基于等式的 Label Selector:
-
name = slave
:选择所有包含键为name
且值为slave
的 Label 的对象。 -
env != production
:选择所有包含键为env
且值不等于production
的 Label 的对象。
1.3.3.2 基于集合的 Label Selector:
-
name in (master, slave)
:选择所有包含键为name
且值为master
或slave
的 Label 的对象。 -
name not in (frontend)
:选择所有包含键为name
且值不等于frontend
的 Label 的对象。
1.3.3.3 合多个 Label Selector:
-
可以使用多个 Label Selector 进行组合,使用逗号
,
分隔。 -
例如:
name=slave,env!=production
或name not in (frontend),env!=production
1.3.3 Label基本操作
1.3.3.1 设置更新Label
[root@K8s-master ~]# kubectl label pod nginx version=1.0 -n test #为Pod打标签 pod/nginx labeled [root@K8s-master ~]# kubectl label pod nginx version=2.0 -n test --overwrite #更新标签 pod/nginx labeled
1.3.3.2 查看标签
[root@K8s-master ~]# kubectl get pod nginx -n test --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 18m version=2.0
1.3.3.3 筛选标签
[root@K8s-master ~]# kubectl get pod -n test -l version!=2.0 --show-labels #筛选把版本不为2.0的 No resources found in test namespace. [root@K8s-master ~]# kubectl get pod -n test -l version=2.0 --show-labels #筛选把版本为2.0的 NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 21m version=2.0
1.3.3.4 删除标签
[root@K8s-master ~]# kubectl label pod nginx version- -n test pod/nginx unlabeled [root@K8s-master ~]# kubectl get pod nginx -n test --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 25m <none>
1.3.4 Label配置文件编写
[root@K8s-master ~]# vim nginx.yml --- apiVersion: v1 kind: Pod metadata:name: nginxnamespace: testlabels:env: "test"version: "3.0" spec:containers:- image: nginxname: podports:- name: nginx-portcontainerPort: 80protocol: TCP [root@K8s-master ~]# kubectl apply -f nginx.yml pod/nginx created [root@K8s-master ~]# kubectl get pod -n test --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 70s env=test,version=3.0
1.4 Deployment控制器
-
在 Kubernetes 中,虽然 Pod 是最小的控制单元,但直接操作 Pod 并不是常见的做法。相反,Kubernetes 通常使用 Pod 控制器(Pod Controller)来管理和维护 Pod。Pod 控制器是一种高层次的 API 对象,它负责确保容器运行在 Pod 中的副本数量始终符合用户定义的预期状态。
-
Deployment 是 Kubernetes 中最常用的 Pod 控制器之一,它提供了一种声明式更新 Pod 的方法。
1.4.1 Deployment特性
-
声明式管理:用户可以声明他们希望 Pod 达到的状态,而无需了解如何达到该状态的具体细节。
-
自动滚动更新:Deployment 支持无停机更新(zero-downtime updates),即滚动更新。在更新过程中,旧版本的 Pods 会逐渐被新版本的 Pods 替换。
-
副本保证:确保指定数量的 Pod 副本始终运行。如果由于故障导致 Pod 终止,Deployment 会自动创建新的 Pod 来替换。
-
版本控制和回滚:Deployment 会自动保存历史版本,用户可以选择回滚到之前的版本。
-
健康检查:可以配置健康检查来确定何时 Pod 准备好接收流量,以及何时 Pod 应该被替换。
-
水平扩展:Deployment 允许用户根据需要手动扩展 Pod 的副本数量,或者配置自动扩展规则。
-
标签和选择器:Deployment 使用标签来选择要管理的 Pod。选择器确保 Deployment 管理与指定标签匹配的 Pod。
-
环境隔离:不同的 Deployment 可以用于不同的环境,如开发、测试和生产环境,每个环境可以有不同的配置。
-
资源配额和限制:可以为 Deployment 配置资源配额和限制,以控制 Pod 使用的资源。
-
策略和调度:可以为 Deployment 指定调度策略,例如亲和性规则或污点容忍,以控制 Pod 在集群中的调度方式。
1.4.2 基本操作
-
命令格式:
kubectl run deployment名称 [参数]
-
参数
-
--image:指定用于创建 Pod 的容器镜像的名称。这个参数是必需的,因为 Kubernetes 需要知道使用哪个镜像来运行容器。
-
--port:指定容器内部的端口,这样 Kubernetes 可以知道如何将容器的端口映射到 Pod 上。这通常用于服务发现和负载均衡。
-
--replicas:指定创建的 Pod 副本数量。这是为了确保高可用性,即使某些 Pod 发生故障,也能保证服务的持续性。
-
--namespace:指定 Deployment 应该创建在哪个 Kubernetes Namespace 中。如果不指定,Deployment 默认会被创建在
default
Namespace。
-
--labels:为 Deployment 添加标签,以便于后续的查询和选择。
-
--env:设置环境变量,传递给容器的配置信息。
-
--restart:设置重启策略,如
Always
、OnFailure
或Never
。
-
--overrides:用于指定一个 JSON 格式的字符串,其中包含一个或多个字段,用于覆盖生成的 Pod 模板。
-
1.4.2.1 创建运行Deployment
[root@K8s-master ~]# kubectl create deployment nginx-01 --image nginx --port 80 --replicas 3 -n test deployment.apps/nginx-01 created
1.4.2.2 查看
[root@K8s-master ~]# kubectl get deployments.apps -n test #3个都运行起来了 NAME READY UP-TO-DATE AVAILABLE AGE nginx-01 3/3 3 3 98s [root@K8s-master ~]# kubectl get pod -n test NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 28m nginx-01-6c7d9d55d9-2cvw5 1/1 Running 0 13s nginx-01-6c7d9d55d9-tqx5t 1/1 Running 0 13s nginx-01-6c7d9d55d9-vdhrj 1/1 Running 0 13s [root@K8s-master ~]# kubectl get deployments.apps -n test -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx-01 3/3 3 3 4m51s nginx nginx app=nginx-01 # UP-TO-DATE:成功升级的副本数量 # AVAILABLE:可用副本的数量 [root@K8s-master ~]# kubectl describe deployments.apps nginx-01 -n test #查看详细信息
1.4.2.3 删除
[root@K8s-master ~]# kubectl delete pod nginx-01-6c7d9d55d9-2cvw5 -n test #删除其中一个Pod pod "nginx-01-6c7d9d55d9-2cvw5" deleted [root@K8s-master ~]# kubectl get pod -n test #立马会再重启一个Pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 38m nginx-01-6c7d9d55d9-flvcz 1/1 Running 0 57s nginx-01-6c7d9d55d9-tqx5t 1/1 Running 0 109s nginx-01-6c7d9d55d9-vdhrj 1/1 Running 0 109s [root@K8s-master ~]# kubectl delete deployments.apps nginx-01 -n test #删除控制器 deployment.apps "nginx-01" deleted
1.4.3 配置文件编写
[root@K8s-master ~]# vim nginx.yml --- apiVersion: apps/v1 kind: Deployment metadata:name: nginxnamespace: test spec:replicas: 3selector:matchLabels:run: nginxtemplate:metadata:labels:run: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80protocol: TCP[root@K8s-master ~]# kubectl apply -f deploy-nginx.yml deployment.apps/nginx created [root@K8s-master ~]# kubectl get pod -n test --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 50m env=test,version=3.0 nginx-7b59b97bcf-dlzsk 1/1 Running 0 2m15s pod-template-hash=7b59b97bcf,run=nginx nginx-7b59b97bcf-lt4rl 1/1 Running 0 2m15s pod-template-hash=7b59b97bcf,run=nginx nginx-7b59b97bcf-qvpqf 1/1 Running 0 2m15s pod-template-hash=7b59b97bcf,run=nginx
属性 | 描述 |
---|---|
apiVersion | Kubernetes API 的版本,这里是 apps/v1 。 |
kind | 资源类型,这里是 Deployment 。 |
metadata | 资源的元数据,包括名称和命名空间。 |
name | Deployment 的名称,这里是 nginx 。 |
namespace | Deployment 所在的命名空间,这里是 test 。 |
spec | 资源的规格说明,定义了 Deployment 的期望状态。 |
replicas | 期望的 Pod 副本数量,这里是 3 。 |
selector | 用于选择要管理的 Pods 的标签选择器。 |
matchLabels | 匹配的标签,这里是 run: nginx 。 |
template | Pod 模板,定义了 Deployment 创建的 Pod 的规格。 |
metadata | Pod 的元数据,包括标签。 |
labels | Pod 的标签,这里是 run: nginx 。 |
spec | Pod 的规格,定义了 Pod 内部的容器设置。 |
containers | Pod 中的容器列表。 |
name | 容器的名称,这里是 nginx 。 |
image | 容器使用的镜像,这里是 nginx 。 |
ports | 容器需要暴露的端口列表。 |
containerPort | 容器内部的端口号,这里是 80 。 |
protocol | 端口使用的协议,这里是 TCP 。 |
1.5 Service
1.5.1 Service介绍
-
在 Kubernetes 架构中,Service 是一种核心的抽象概念,用于定义访问一组具有相同功能的 Pods 的策略。Service 为 Pods 提供了一种稳定和统一的访问方法,无论 Pods 的数量如何变化,或者它们的 IP 地址如何变化,Service 都保持不变。
-
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
-
在 Kubernetes 集群中,每个 Pod 被分配一个唯一的 IP 地址(Pod IP),用于 Pod 之间的网络通信。然而,Pod IP 地址确实存在一些限制,这可能会导致服务访问和管理上的困难,为了解决这些问题,Kubernetes 引入了 Service 这一抽象
-
Pod IP 的变化:当 Pod 被删除并重新创建时(例如,由于故障、缩放操作或部署更新),它将获得一个新的 IP 地址。这意味着如果直接使用 Pod IP 来通信,客户端需要处理 IP 地址变化的情况。
-
Pod IP 的可见性:Pod IP 是虚拟的,并且只在 Kubernetes 集群内部可见。这意味着从集群外部无法直接访问 Pod。
-
[root@K8s-master ~]# kubectl get pod -n test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 1/1 Running 0 4h40m 10.244.2.5 k8s-node-02 <none> <none> nginx-7b59b97bcf-dlzsk 1/1 Running 0 3h52m 10.244.2.11 k8s-node-02 <none> <none> nginx-7b59b97bcf-lt4rl 1/1 Running 0 3h52m 10.244.2.10 k8s-node-02 <none> <none> nginx-7b59b97bcf-qvpqf 1/1 Running 0 3h52m 10.244.1.7 k8s-node-01 <none> <none> #这里nginx-7b59b97bcf-qvpqf的IP为10.244.1.7 [root@K8s-master ~]# kubectl delete pod nginx-7b59b97bcf-qvpqf -n test #删除这个Pod pod "nginx-7b59b97bcf-qvpqf" deleted [root@K8s-master ~]# kubectl get pod -n test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 1/1 Running 0 4h42m 10.244.2.5 k8s-node-02 <none> <none> nginx-7b59b97bcf-dlzsk 1/1 Running 0 3h54m 10.244.2.11 k8s-node-02 <none> <none> nginx-7b59b97bcf-lt4rl 1/1 Running 0 3h54m 10.244.2.10 k8s-node-02 <none> <none> nginx-7b59b97bcf-xxhfv 1/1 Running 0 41s 10.244.1.8 k8s-node-01 <none> <none> #自动生成Pod nginx-7b59b97bcf-xxhfv的IP变为10.244.1.8
1.5.2 基本操作
1.5.2.1 搭建集群内部可访问的Service
[root@K8s-master ~]# kubectl expose deployment nginx --name=svc-nginx-01 --type=ClusterIP --port=80 --target-port=80 -n test service/svc-nginx-01 exposed [root@K8s-master ~]# kubectl get service svc-nginx-01 -n test -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR svc-nginx-01 ClusterIP 10.110.170.62 <none> 80/TCP 80s run=nginx # 这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的 # 可以通过这个IP访问当前service对应的POD [root@K8s-master ~]# curl http://10.110.170.62 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
1.5.2.2 搭建集群外部可访问的Service
-
上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问
-
如果需要创建外部也可以访问的Service,需要修改type为NodePort
[root@K8s-master ~]# kubectl expose deployment nginx --name=svc-nginx-02 --type=NodePort --port=80 --target-port=80 -n test service/svc-nginx-02 exposed [root@K8s-master ~]# kubectl get service svc-nginx-02 -n test -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR svc-nginx-02 NodePort 10.108.6.6 <none> 80:31690/TCP 28s run=nginx [root@K8s-master ~]# curl http://192.168.110.21:31690 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
-
ClusterIP:
-
服务仅在 Kubernetes 集群内部可访问。
-
通过集群内部的 IP 地址进行访问。
-
这是默认的服务类型。
-
-
ExternalName:
-
服务不直接暴露任何 Pod,而是指向外部的 DNS 名称。
-
kubedns 或类似的 DNS 服务会返回一个 CNAME 记录,指向这个外部名称。
-
这种方式通常用于将服务映射到外部服务上,比如指向一个外部数据库或 API。
-
-
LoadBalancer:
-
服务将通过外部负载均衡器暴露给外部访问(如果云服务提供商支持)。
-
除了提供
ClusterIP
类型的内部访问外,还会分配一个外部可访问的地址。 -
这通常用于让外部用户能够访问集群中的服务。
-
-
NodePort:
-
服务将在集群中所有节点的特定端口上暴露。
-
结合了
ClusterIP
类型,允许集群外部通过节点的 IP 地址和指定端口访问服务。 -
这种方式适用于需要从集群外部访问服务,但不希望或不需要使用外部负载均衡器的情况。
-
1.5.2.3 删除Service
[root@K8s-master ~]# kubectl delete service svc-nginx-01 -n test service "svc-nginx-01" deleted [root@K8s-master ~]# kubectl delete service svc-nginx-02 -n test service "svc-nginx-02" deleted
1.5.3 配置文件编写
[root@K8s-master ~]# vim svc-nginx.yaml --- apiVersion: v1 kind: Service metadata:name: svc-nginxnamespace: test spec:ports:- port: 80protocol: TCPtargetPort: 80selector:run: nginxtype: NodePort[root@K8s-master ~]# kubectl apply -f svc-nginx.yaml service/svc-nginx created [root@K8s-master ~]# kubectl get service -n test NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc-nginx NodePort 10.102.4.48 <none> 80:31832/TCP 27s
1.6 Kubernetes开启IPVS
Kubernetes 开启 IPVS(IP Virtual Server)主要是因为 IPVS 提供了一些关键优势,这些优势对于大规模生产环境来说非常重要:
-
高性能:IPVS 作为内核空间的一部分,可以提供比用户空间的代理更高的吞吐量和更低的延迟。这是因为所有的网络操作都在内核空间中完成,减少了上下文切换的开销。
-
更好的扩展性:IPVS 支持大量的并发连接,这对于处理成千上万的 Pod 和服务的 Kubernetes 集群来说是必要的。
-
负载均衡:IPVS 支持多种负载均衡算法,如轮询(round-robin)、最少连接(least-connection)、源地址哈希(source IP hash)等,这允许 Kubernetes 根据需要选择最合适的算法。
-
会话保持:IPVS 可以实现会话保持功能,确保来自同一客户端的请求总是被定向到后端的同一个 Pod,这对于维护状态的应用程序非常重要。
-
健康检查:IPVS 可以与 Kubernetes 的健康检查机制集成,自动将流量从不健康的后端 Pod 重定向到健康的 Pod。
-
安全性:IPVS 运行在内核空间,相比用户空间的网络服务,更不容易受到外部攻击。
-
直接服务器响应(DSR):IPVS 支持直接服务器响应模式,可以减少数据包的复制开销,提高效率。
-
节省资源:由于 IPVS 是内核模块,它比用户空间的负载均衡器更节省资源。
[root@K8s-master ~]# ipvsadm -Ln #默认没有开启 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port Forward Weight ActiveConn InActConn
1.6.1 加载内核模快
[root@K8s-master ~]# lsmod | grep ip_vs ip_vs_sh 12288 0 ip_vs_ftp 12288 0 nf_nat 57344 5 ip6table_nat,xt_nat,iptable_nat,xt_MASQUERADE,ip_vs_ftp ip_vs_sed 12288 0 ip_vs_dh 12288 0 ip_vs_lblcr 12288 0 ip_vs_lblc 12288 0 ip_vs_wrr 12288 0 ip_vs_rr 12288 0 ip_vs_wlc 12288 0 ip_vs_lc 12288 0 ip_vs 200704 20 ip_vs_wlc,ip_vs_rr,ip_vs_dh,ip_vs_lblcr,ip_vs_sh,ip_vs_lblc,ip_vs_wrr,ip_vs_lc,ip_vs_sed,ip_vs_ftp nf_conntrack 188416 6 xt_conntrack,nf_nat,xt_nat,nf_conntrack_netlink,xt_MASQUERADE,ip_vs nf_defrag_ipv6 24576 2 nf_conntrack,ip_vs libcrc32c 12288 5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs
1.6.2 修改kube-proxy配置
[root@K8s-master ~]# kubectl edit configmap kube-proxy -n kube-system mode: "ipvs" #修改此处,默认为空
1.6.3 删除所有kube-proxy的pod
[root@K8s-master ~]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-74586cf9b6-96v5x 1/1 Running 0 3d2h coredns-74586cf9b6-f5q7h 1/1 Running 0 3d2h etcd-k8s-master 1/1 Running 0 3d2h kube-apiserver-k8s-master 1/1 Running 0 3d2h kube-controller-manager-k8s-master 1/1 Running 0 3d2h kube-flannel-ds-6gqmv 1/1 Running 0 3d kube-flannel-ds-g7zcj 1/1 Running 0 3d kube-flannel-ds-hh52b 1/1 Running 0 3d kube-proxy-glhml 1/1 Running 0 3d1h kube-proxy-klcs2 1/1 Running 0 3d1h kube-proxy-x9v8k 1/1 Running 0 3d2h kube-scheduler-k8s-master 1/1 Running 0 3d2h [root@K8s-master ~]# kubectl delete pod kube-proxy-glhml kube-proxy-klcs2 kube-proxy-x9v8k -n kube-system pod "kube-proxy-glhml" deleted pod "kube-proxy-klcs2" deleted pod "kube-proxy-x9v8k" deleted [root@K8s-master ~]# kubectl get pod -n kube-system #会重新生成新的Pod NAME READY STATUS RESTARTS AGE coredns-74586cf9b6-96v5x 1/1 Running 0 3d2h coredns-74586cf9b6-f5q7h 1/1 Running 0 3d2h etcd-k8s-master 1/1 Running 0 3d2h kube-apiserver-k8s-master 1/1 Running 0 3d2h kube-controller-manager-k8s-master 1/1 Running 0 3d2h kube-flannel-ds-6gqmv 1/1 Running 0 3d kube-flannel-ds-g7zcj 1/1 Running 0 3d kube-flannel-ds-hh52b 1/1 Running 0 3d kube-proxy-bwxdq 1/1 Running 0 31s kube-proxy-rvfgk 1/1 Running 0 31s kube-proxy-tm4pt 1/1 Running 0 31s kube-scheduler-k8s-master 1/1 Running 0 3d2h
1.6.4 查看
[root@K8s-master ~]# kubectl logs kube-proxy-bwxdq -n kube-system | grep ipvs I0507 08:40:20.093060 1 server_others.go:269] "Using ipvs Proxier" I0507 08:40:20.093080 1 server_others.go:271] "Creating dualStackProxier for ipvs" [root@K8s-master ~]# kubectl logs kube-proxy-rvfgk -n kube-system | grep ipvs I0507 08:40:19.845750 1 server_others.go:269] "Using ipvs Proxier" I0507 08:40:19.845811 1 server_others.go:271] "Creating dualStackProxier for ipvs" [root@K8s-master ~]# kubectl logs kube-proxy-tm4pt -n kube-system | grep ipvs I0507 08:40:20.310143 1 server_others.go:269] "Using ipvs Proxier" I0507 08:40:20.310171 1 server_others.go:271] "Creating dualStackProxier for ipvs" [root@K8s-master ~]# ipvsadm -Ln #默认调度算法为轮询 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.110.21:31832 rr-> 10.244.1.8:80 Masq 1 0 0 -> 10.244.2.10:80 Masq 1 0 0 -> 10.244.2.11:80 Masq 1 0 0 TCP 10.96.0.1:443 rr-> 192.168.110.21:6443 Masq 1 0 0 TCP 10.96.0.10:53 rr-> 10.244.1.2:53 Masq 1 0 0 -> 10.244.1.3:53 Masq 1 0 0 TCP 10.96.0.10:9153 rr-> 10.244.1.2:9153 Masq 1 0 0 -> 10.244.1.3:9153 Masq 1 0 0 TCP 10.102.4.48:80 rr-> 10.244.1.8:80 Masq 1 0 0 -> 10.244.2.10:80 Masq 1 0 0 -> 10.244.2.11:80 Masq 1 0 0 TCP 10.244.0.0:31832 rr-> 10.244.1.8:80 Masq 1 0 0 -> 10.244.2.10:80 Masq 1 0 0 -> 10.244.2.11:80 Masq 1 0 0 UDP 10.96.0.10:53 rr-> 10.244.1.2:53 Masq 1 0 0 -> 10.244.1.3:53 Masq 1 0 0