发布于 2026-01-05 15 阅读
0

通过具体示例理解 Kubernetes

通过具体示例理解 Kubernetes

Date: July 12th, 2018
Kubernetes Version: v1.11.0
📝 is a sidebar
⚠️ is a warning
Enter fullscreen mode Exit fullscreen mode

Kubernetes 是一个容器编排系统。你可以把容器想象成一个应用程序,把多个容器想象成一个 Pod。编排部分指的是,你告诉 Kubernetes 你想运行哪些容器,它会负责在集群中实际运行这些容器、将流量路由到正确的 Pod 以及许多其他功能

Kubernetes 为 Pod 定义提供了一个模式。这意味着您只需填写一个文档完善的模板,然后将其提交给 Kubernetes 集群。Kubernetes 会确定哪些服务将在哪里运行,运行您的 Pod 并配置集群网络。如果某个 Pod 崩溃,Kubernetes 会检测到系统状态发生改变。Kubernetes 会采取措施将系统恢复到定义的状态。

我们来看一个例子:一个名为 devtoo.com 的博客平台,运行在 Kubernetes 集群上。

成分

第一步是确定 devtoo.com 的组成部分。假设以下是所有必要的组件:

  1. 接受来自互联网的 HTTP 流量的 Web 服务器。例如nginxapache就是 Web 服务器。
  2. 应用服务器负责将 Rails 应用加载到内存中并处理请求。devtoo.com 就是由这个 Rails 应用驱动的。
  3. 用于存储我们所有精彩文章的数据库。Postgres MySQLMongoDB都是数据库示例。
  4. 缓存可以绕过应用程序和数据库,直接返回结果。RedisMemcached就是缓存的例子。

最终目标

下一步是确定最终系统的架构。Kubernetes 在这方面提供了很多选择。各个组件可以各自运行在独立的 Pod 中,也可以全部放在同一个 Pod 里。我喜欢从最简单的方案入手,如果效果不好再进行改进。对我来说,这意味着每个组件都将运行在各自的 Pod 中。一个典型的 Web 请求会进入系统并到达 Web 服务器。Web 服务器会查询缓存中是否有该端点的响应。如果有,则立即返回结果。如果没有,则将请求传递给应用服务器。应用服务器配置为与数据库通信并生成动态内容,然后将这些内容发送回 Web 浏览器。

定义系统

Kubernetes 将服务映射到 Pod。每个 Pod 对应一个服务。这样,您就可以通过 DNS 引用其他 Pod。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: web
spec:
  containers:
  - name: nginx
    image: registry.hub.docker.com/library/nginx:1.15
    ports:
    - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
Enter fullscreen mode Exit fullscreen mode

该服务定义了一个选择器app: web。服务会将流量路由到任何与该选择器匹配的 Pod。如果您查看 Pod 定义,您会发现app: webPod 上定义了一个标签。这意味着流量通过 80 端口进入服务,并被发送到端口号为targetPort80 的 nginx Pod。`<selector>`targetPort和 `<label>`containerPort必须匹配。

在这里,你可以使用你的魔法棒生成一个嵌入到 nginx 镜像中的 nginx 配置,该配置会将流量发送到缓存,如果没有结果,则发送到应用服务器。

以下是缓存定义:

apiVersion: v1
kind: Pod
metadata:
  name: redis
  labels:
    app: cache
spec:
  containers:
  - name: redis
    image: registry.hub.docker.com/library/redis:4.0
    ports:
    - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: cache
spec:
  selector:
    app: cache
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379
Enter fullscreen mode Exit fullscreen mode

数据库定义:

apiVersion: v1
kind: Pod
metadata:
  name: postgres
  labels:
    app: db
spec:
  containers:
  - name: db
    image: registry.hub.docker.com/library/postgres:10.4
    ports:
    - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: database
spec:
  selector:
    app: cache
  ports:
  - protocol: TCP
    port: 6379
    targetPort: 6379
Enter fullscreen mode Exit fullscreen mode

以上就是 devtoo.com 部署所考虑的所有依赖项。接下来需要配置应用程序本身。Rails可以使用环境变量连接到数据库。您可以在 pod 的 YAML 文件中这样定义:

⚠️这样做非常不安全!Kubernetes 有更好的方法来做到这一点,但为了保持本文的“简洁性”,我省略了它们。

apiVersion: v1
kind: Pod
metadata:
  name: app
  labels:
    app: app
spec:
  containers:
  - name: devtoo-com
    env:
    - name: DATABASE_URL
      value: postgresql://user1:password1@database/dev_to_db
    image: registry.hub.docker.com/devtoo.com/app:v9001
    ports:
    - containerPort: 3001
---
apiVersion: v1
kind: Service
metadata:
  name: devtoo-com
spec:
  selector:
    app: app
  ports:
  - protocol: TCP
    port: 3001
    targetPort: 3001
Enter fullscreen mode Exit fullscreen mode

最后还需要一个入口点,即流量可以从外部世界进入集群的地方​​。

📝我略过了 IngressControllers,因为虽然它们是必需的,但在目前的理解水平下,它们只是一个实现细节,可以忽略不计。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dev-to
spec:
  backend:
    serviceName: web
    servicePort: 80
Enter fullscreen mode Exit fullscreen mode

web这表示在此入口点收到的任何流量都将发送到端口 80 上名为 的服务。

现在集群已经搭建完毕,让我们来追踪一下获取这篇博文的数据包。你在浏览器中输入http://devtoo.com/chuck_ha/this-post。http://devtoo.com通过 DNS 解析某个 IP 地址,该地址位于 Kubernetes 集群前端的负载均衡器上。负载均衡器将流量发送到入口点。由于入口点上只有一个服务,流量会被发送到映射到 Nginx Pod 的 Web 服务。Nginx 容器检查数据包并将其发送到映射到 Redis Pod 的缓存服务。Redis Pod 之前从未见过这个 URL,因此执行流程从 Nginx 继续。请求被发送到应用服务器,该服务器生成此页面,将其缓存并返回给你的浏览器。

然后点击🦄按钮!

📝 以下是我省略的一些内容,以便您能专注于重点,而不会迷失在细节中:

文章来源:https://dev.to/chuck_ha/understand-kubernetes-through-a-concrete-example-7d9