通过具体示例理解 Kubernetes
Date: July 12th, 2018
Kubernetes Version: v1.11.0
📝 is a sidebar
⚠️ is a warning
Kubernetes 是一个容器编排系统。你可以把容器想象成一个应用程序,把多个容器想象成一个 Pod。编排部分指的是,你告诉 Kubernetes 你想运行哪些容器,它会负责在集群中实际运行这些容器、将流量路由到正确的 Pod 以及许多其他功能。
Kubernetes 为 Pod 定义提供了一个模式。这意味着您只需填写一个文档完善的模板,然后将其提交给 Kubernetes 集群。Kubernetes 会确定哪些服务将在哪里运行,运行您的 Pod 并配置集群网络。如果某个 Pod 崩溃,Kubernetes 会检测到系统状态发生改变。Kubernetes 会采取措施将系统恢复到定义的状态。
我们来看一个例子:一个名为 devtoo.com 的博客平台,运行在 Kubernetes 集群上。
成分
第一步是确定 devtoo.com 的组成部分。假设以下是所有必要的组件:
- 接受来自互联网的 HTTP 流量的 Web 服务器。例如nginx和apache就是 Web 服务器。
- 应用服务器负责将 Rails 应用加载到内存中并处理请求。devtoo.com 就是由这个 Rails 应用驱动的。
- 用于存储我们所有精彩文章的数据库。Postgres 、MySQL和MongoDB都是数据库示例。
- 缓存可以绕过应用程序和数据库,直接返回结果。Redis和Memcached就是缓存的例子。
最终目标
下一步是确定最终系统的架构。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
该服务定义了一个选择器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
数据库定义:
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
以上就是 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
最后还需要一个入口点,即流量可以从外部世界进入集群的地方。
📝我略过了 IngressControllers,因为虽然它们是必需的,但在目前的理解水平下,它们只是一个实现细节,可以忽略不计。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dev-to
spec:
backend:
serviceName: web
servicePort: 80
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