百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

回归基础:访问 Kubernetes Pod(concurrent.futures访问数据库)

mhr18 2025-05-10 23:31 25 浏览 0 评论

Kubernetes 是一头巨大的野兽。在它开始有用之前,您需要了解许多概念。在这里,学习几种访问集群外 pod 的方法。


Kubernetes 是一头巨大的野兽。在它开始有用之前,您需要了解许多不同的概念。一切都设置好后,您可能希望将一些 pod 暴露给集群外部。Kubernetes 提供了不同的方法来做到这一点:我将在这篇文章中描述它们。

设置

为了演示,我将使用kind:

kind 是一个使用 Docker 容器“节点”运行本地 Kubernetes 集群的工具。kind 主要是为测试 Kubernetes 本身而设计的,但也可以用于本地开发或 CI。

我将使用一个两节点集群:

YAML

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30800             # 1
    hostPort: 30800                  # 1
- role: worker                       # 2
- role: worker                       # 2


  • #1:端口转发以应对 Mac 上的 Docker VM 层(见下文)
  • #2:两个节点


kind create cluster -- config kind.yml

接下来,我们需要一个容器。它不应该只是运行和停止。让我们使用撰写本文时可用的最新 Nginx 映像。

使用 kind,我们必须预加载镜像以便它们可用。


docker pull nginx:1.23
kind load docker-image nginx:1.23


最后,我别名kubetclk


alias k=kubectl


默认情况下无外部访问

默认情况是不提供对集群外部的访问。


k create deployment nginx --image=nginx:1.23 # 1


  • #1:创建单个 pod 的部署。

让我们检查一下是否一切正常:


k get pods

纯文本

NAME                     READY   STATUS    RESTARTS   AGE
nginx-6c7985744b-c7cpl   1/1     Running   0          67s


pod 有一个 IP,但我们无法在集群外访问它。


k get pod nginx-6c7985744b-c7cpl --template '{{.status.podIP}}'

纯文本

10.244.1.2


让我们通过在 pod 内部运行 shell 来确认 IP:


k exec -it nginx-6c7985744b-c7cpl -- /bin/bash
hostname -I

纯文本

10.244.1.2

我们无法在集群外成功 ping 此 IP:它是一个内部 IP。

内部 IP 不稳定

我们创建了一个部署;因此,如果我们删除单个 Pod,Kubernetes 将检测到它并创建一个新 Pod,这要归功于它的自我修复功能。


k delete pod nginx-6c7985744b-c7cpl
k get pods

纯文本

NAME                     READY   STATUS    RESTARTS   AGE
nginx-6c7985744b-c6f92   1/1     Running   0          71s


让我们检查一下它的新IP:


k exec -it nginx-6c7985744b-c6f92 -- /bin/bash
hostname -I

纯文本

10.244.2.2


Kubernetes 创建了一个新的 Pod,但它的 IP 与删除的 Pod 不同。我们不能依赖这个 IP 进行 pod 到 pod 的通信。事实上,我们永远不应该直接使用 pod 的 IP。

为了解决这个问题,Kubernetes 提供了Service对象。服务代表 pod 前面的稳定接口。Kubernetes 管理服务与其 Pod 之间的映射。它绑定新的 Pod 并取消绑定已删除的 Pod。

ClusterIPService:在集群内部 IP 上公开。选择此值使Service唯一可从集群内访问。这是默认设置ServiceType

-出版服务 (ClusterIP)

让我们使用服务公开现有部署:


k expose deployment nginx --type=ClusterIP --port=8080
k get svc

纯文本

NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    9m47s
nginx        ClusterIP   10.96.93.97   <none>        8080/TCP   4s


从此时起,可以通过服务的ClusterIP.

全部设置为在集群内部进行访问。从外面看,这还不可能。那么我们为什么要使用ClusteIP呢?它对于您不想暴露给外界的服务非常有用:数据库、ElasticSearch 节点、Redis 节点等。

访问 Pod

当事情变得有趣时,从集群外部访问一个 pod。

我们首先需要删除现有的部署和服务。


k delete deployment nginx
k delete svc nginx


允许外部访问的最简单方法是将服务的类型更改为NodePort.
NodePort将访问端口添加到ClusterIP.

NodePort: 在每个节点的 IP 上的静态端口 (the NodePort) 上公开服务。ClusterIPService 路由到的ServiceNodePort是自动创建的。您可以NodePort通过请求从集群外部联系服务:

- 发布服务(NodePort)

我希望 pod 返回其 IP 和主机名以进行演示。我们必须从命令行转移到专用的 Kubernetes 清单文件,因为我们必须配置 Nginx。它导致与命令行相同的状态,并添加了 Nginx 配置:

YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23
        volumeMounts:                                                     # 1
          - name: conf
            mountPath: /etc/nginx/nginx.conf
            subPath: nginx.conf
            readOnly: true
      volumes:                                                            # 1
        - name: conf
          configMap:
            name: nginx-conf
            items:
              - key: nginx.conf
                path: nginx.conf
---
apiVersion: v1                                                            # 1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  nginx.conf: |
    events {
        worker_connections  1024;
    }
    http {
        server {
            location / {
                default_type text/plain;
                return 200 "host: $hostname\nIP:   $server_addr\n";
            }
        }
    }
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: NodePort                                                          # 2
  ports:
    - port: 80
      nodePort: 30800


  • #1:覆盖默认配置以返回主机名和 IP 地址。
  • #2:NodePort将 pod 的端口映射到外部可访问的端口。

让我们应用配置:


k apply -f deployment.yml


请注意,我在 Mac 上运行;因此,Docker 周围有一个 VM 容器,就像在 Windows 中一样。出于这个原因,kind 需要将 VM 端口转发到主机。请查看有关如何实现它的文档。

一旦 Kubernetes 调度了 pod,我们就可以在配置的端口上访问它:


curl localhost:30800

纯文本

host: nginx-b69d8877c-p2s79
IP:   10.244.2.2

请求的路径如下(尽管 Mac/Windows 上有 VM 层):

  • curl请求发送到任何节点。
  • 请注意,在云提供商设置中,您可以针对托管部署的 pod 部分的任何 Kubernetes 节点。通过本地设置,我们定位localhost并让 VM 层以节点为目标。
  • 节点看到端口30800并将请求转发到NodePort具有相关端口的服务。
  • 该服务将请求转发到 pod,将端口从 转换3080080

现在,让我们将部署中的 pod 数量增加到两个:


k scale deployment nginx --replicas=2
k get pods -o wide


Kubernetes 平衡集群,以便每个 pod 驻留在不同的节点上:

纯文本

NAME                    READY   STATUS    RESTARTS   AGE    IP           NODE           NOMINATED NODE   READINESS GATES
nginx-b69d8877c-w7db4   1/1     Running   0          129m   10.244.2.2   kind-worker    <none>           <none>
nginx-b69d8877c-z5kqs   1/1     Running   0          38m    10.244.1.2   kind-worker2   <none>           <none>


请求将发送到哪个节点/pod?


while true; do curl localhost:30800; done

纯文本

host: nginx-b69d8877c-w7db4
IP:   10.244.2.2
host: nginx-b69d8877c-w7db4
IP:   10.244.2.2
host: nginx-b69d8877c-z5kqs
IP:   10.244.1.2
host: nginx-b69d8877c-z5kqs
IP:   10.244.1.2
host: nginx-b69d8877c-w7db4
IP:   10.244.2.2
host: nginx-b69d8877c-w7db4
IP:   10.244.2.2

该服务平衡所有可用 pod 之间的请求。

负载平衡抽象

NodePort允许查询任何集群节点。LoadBalancer是集群上的一个外观,它确实......负载平衡。它是 Kubernetes 提供的一个抽象对象:每个云提供商根据其特性以不同的方式实现它,尽管行为是相同的。

LoadBalancer:使用云提供商的负载均衡器在外部公开服务。自动创建外部负载均衡器路由到的 NodePort 和 ClusterIP 服务。

- 发布服务(LoadBalander)

首先,我们需要一个LoadBalancer实现。kind 与 MetalLB 具有开箱即用的集成:

MetalLB 是裸机 Kubernetes 集群的负载均衡器实现,使用标准路由协议。

-金属LB

解释 kind 关于如何安装 MetalLB的优秀文档是没有用的。我们可以相应地更新清单:

YAML

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 30800


让我们看看服务:


k get svc

纯文本

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          4h37m
nginx        LoadBalancer   10.96.216.126   127.0.0.240   8080:31513/TCP   82m     # 1


  • #1:它有一个外部IP!

不幸的是,正如我上面提到的,在 Mac(和 Windows)上,Docker 在 VM 中运行。因此,我们无法从主机访问“外部”IP。拥有适当 Linux 系统的读者应该可以访问它。

根据云提供商的不同,LoadBalancer可能会提供额外的专有功能。

入口,当您需要路由时

Ingress专注于将请求路由到集群中的服务。

它与以下内容共享一些方面LoadBalancer

  • 它拦截入站流量。
  • 它依赖于实现,并且实现提供不同的功能:例如. , Nginx , Traefik , HAProxy等

但是,它不是一个Service.

Ingress 将来自集群外部的 HTTP 和 HTTPS 路由暴露给集群内的服务。流量路由由 Ingress 资源上定义的规则控制。

-什么是入口?

安装一个Ingress很大程度上取决于实现。唯一的共同因素是它涉及CRD。

为了演示,我将使用Apache APISIX Ingress 控制器。我不会解释Minikube 上 Ingress APISIX 的安装说明。唯一的区别是将 设置NodePort为设定值:


helm install apisix apisix/apisix \
  --set gateway.type=NodePort \
  --set gateway.http.nodePort=30800 \
  --set ingress-controller.enabled=true \
  --namespace ingress-apisix \
  --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix


请注意,虽然文档中提到了 Minikube,但它适用于任何本地集群,包括 kind。

命名空间中应提供以下服务ingress-apisix

纯文本

NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
apisix-admin                ClusterIP   10.96.98.159   <none>        9180/TCP            22h
apisix-etcd                 ClusterIP   10.96.80.154   <none>        2379/TCP,2380/TCP   22h
apisix-etcd-headless        ClusterIP   None           <none>        2379/TCP,2380/TCP   22h
apisix-gateway              NodePort    10.96.233.74   <none>        80:30800/TCP        22h
apisix-ingress-controller   ClusterIP   10.96.125.41   <none>        80/TCP              22h


为了演示,我们将有两个服务:每个服务都有一个 pod 的底层部署。请求/left将命中一项服务并返回left/right, right.

让我们相应地更新拓扑:

YAML

apiVersin: apps/v1
kind: Deployment
metadata:
  name: left
  labels:
    app: left
spec:
  replicas: 1
  selector:
    matchLabels:
      app: left
  template:
    metadata:
      labels:
        app: left
    spec:
      containers:
      - name: nginx
        image: nginx:1.23
        volumeMounts:
          - name: conf
            mountPath: /etc/nginx/nginx.conf
            subPath: nginx.conf
            readOnly: true
      volumes:
        - name: conf
          configMap:
            name: left-conf
            items:
              - key: nginx.conf
                path: nginx.conf
---
apiVersion: v1
kind: Service
metadata:
  name: left
spec:
  selector:
    app: left
  ports:
    - port: 80
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: left-conf
data:
  nginx.conf: |
    events {
        worker_connections  1024;
    }
    http {
        server {
            location / {
                default_type text/plain;
                return 200 "left\n";
            }
        }
    }


上面的片段只描述了left路径。它应该包含类似的right路径配置。

此时,我们可以创建配置以将路径路由到服务:

YAML

apiVersion: apisix.apache.org/v2beta3            # 1
kind: ApisixRoute                                # 1
metadata:
  name: apisix-route
spec:
  http:
  - name: left
    match:
      paths:
      - "/left"
    backends:
    - serviceName: left                          # 2
      servicePort: 80                            # 2
  - name: right
    match:
      paths:
        - "/right"
    backends:
    - serviceName: right                         # 3
      servicePort: 80                      


  1. 使用ApisixRoute安装创建的 CRD。
  2. 将请求转发到left服务。
  3. 将请求转发到right服务。

这是它应该是什么样子。请注意,我选择仅表示left路径和一个节点,以免图表过载。

为了检查它是否有效,让我们再次卷曲。


curl localhost:30800

纯文本

{"error_msg":"404 找不到路由"}


这是一个好兆头:APISIX 正在响应。

我们现在可以尝试 curlright路径以确保它会转发到相关的 pod。


curl localhost:30800/right

纯文本

正确的


/left,它也有效。

结论

在这篇文章中,我描述了几种访问集群外部 pod 的方法:NodePort以及LoadBalancerservices 和Ingress. 对于Ingress,您可能已经注意到该ApisixRoute对象是专有 CRD。为了避免这种情况,Kubernetes 旨在提供一个抽象:CNCF 正在开发一个网关 API项目。

我会在以后的文章中描述它。

这篇文章的完整源代码可以在GitHub上找到。



相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: