如何将用于 Rails 开发的 Docker Compose 工作流迁移到 Kubernetes

介绍

在构建现代、无状态的应用程序时, 容器化应用程序的组件是部署和扩展在分布式平台上的第一步。

  • 從您的代碼中提取必要的配置資訊
  • 卸載您的應用程式的狀態
  • 包裝您的應用程式以供重複使用

您还将有书面服务定义,说明您的容器图像应该如何运行。

要在像 Kubernetes这样的分布式平台上运行您的服务,您需要将您的 Compose 服务定义翻译成 Kubernetes 对象,这将使您能够 以弹性扩展您的应用程序

在本教程中,您将使用 kompose 将 Compose 服务翻译为 Kubernetes objects 您将使用 kompose 提供的对象定义作为起点,并进行调整,以确保您的设置将使用 Secrets, ServicesPersistentVolumeClaims 以 Kubernetes 预期的方式。在教程结束时,您将有一个单个实例 Rails 应用程序,具有在 Kubernetes 集群上运行的 PostgreSQL 数据库。此设置将反映在 Containerizing a Ruby on Rails Application for Development with Docker Compose 中描述的

前提条件

此设置将使用 DigitalOcean Kubernetes cluster,但您可以自由地 使用另一种方法创建一个集群

步骤1 - 安装组件

要开始使用 kompose,请导航到 项目的GitHub Releases页面,并复制当前版本的链接(本文的版本 1.22.0)。

1curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-linux-amd64 -o kompose

有关在非 Linux 系统上安装的详细信息,请参阅 安装说明

使二进制可执行:

1chmod +x kompose

把它移动到你的路径:

1sudo mv ./kompose /usr/local/bin/kompose

要验证它是否正确安装,您可以进行版本检查:

1kompose version

如果安装成功,您将看到如下输出:

1[secondary_label Output]
21.22.0 (955b78124)

隨著「kompose」已安裝並準備使用,您現在可以克隆您將翻譯成 Kubernetes 的 Node.js 項目代碼。

步骤 2 – 克隆和包装应用程序

要使用我们的应用程序与Kubernetes,我们需要克隆项目代码并包装应用程序,以便kubelet服务可以拉出图像。

我们的第一步是将 rails-sidekiq 存储库DigitalOcean 社区 GitHub 帐户克隆。这个存储库包括在 Containerizing a Ruby on Rails Application for Development with Docker Compose中描述的设置中的代码,该存储库使用 Rails 演示应用程序来展示如何使用 Docker Compose 设置开发环境。

将存储库克隆成名为rails_project的目录:

1git clone https://github.com/do-community/rails-sidekiq.git rails_project

导航到rails_project目录:

1cd rails_project

现在从构成工作流分支中检查本教程的代码:

1git checkout compose-workflow
1[secondary_label Output]
2Branch 'compose-workflow' set up to track remote branch 'compose-workflow' from 'origin'.
3Switched to a new branch 'compose-workflow'

rails_project目录包含用于使用用户输入的鲨鱼信息应用程序的文件和目录,它已被现代化,以便与容器工作:敏感和特定的配置信息已从应用程序代码中删除,并重构为在运行时注入,并将应用程序的状态下载到PostgreSQL数据库中。

有关设计现代、无状态的应用程序的更多信息,请参阅 Kubernetes 的应用程序架构Kubernetes 的应用程序现代化

项目目录中包含一个Dockerfile,包含构建应用程序图像的说明,让我们现在构建图像,以便您可以将其推到您的Docker Hub帐户并在您的Kubernetes设置中使用。

使用 docker build 命令,用 -t 旗帜构建图像,允许您用可记忆的名称标记图像,在这种情况下,用您的 Docker Hub 用户名标记图像,并将其命名为 rails-kubernetes 或您自己的名字:

1docker build -t your_dockerhub_user/rails-kubernetes .

命令中的 . 指定了构建背景是当前目录。

它需要一两分钟才能构建图像.一旦完成,请检查您的图像:

1docker images

您将看到以下结果:

1[secondary_label Output]
2REPOSITORY TAG IMAGE ID CREATED SIZE
3your_dockerhub_user/rails-kubernetes latest 24f7e88b6ef2 2 days ago 606MB
4alpine latest d6e46aa2470d 6 weeks ago 5.57MB

接下来,登录您在前提条件下创建的 Docker Hub 帐户:

1docker login -u your_dockerhub_user

当被提示时,请输入您的 Docker Hub 帐户密码. 以此方式登录将创建一个 ~/.docker/config.json 文件,在您的用户主目录中与您的 Docker Hub 凭证。

使用 docker push 命令将应用程序图像推到 Docker Hub。 请记住用自己的 Docker Hub 用户名替换 your_dockerhub_user:

1docker push your_dockerhub_user/rails-kubernetes

您现在有一个应用程序图像,您可以将其拉到运行您的应用程序与Kubernetes. 下一步将是将您的应用程序服务定义翻译为Kubernetes对象。

步骤 3 — 将复合服务翻译成 Kubernetes 对象

我们的 Docker Compose 文件,在这里称为docker-compose.yml,列出了将使用 Compose 运行我们的服务的定义。Compose 中的 service 是一个运行容器,而 service definitions 包含有关每个容器图像将如何运行的信息。在这个步骤中,我们将使用kompose创建yaml文件来将这些定义翻译为 Kubernetes 对象。

我们将使用这些文件来创建不同类型的对象: 服务,这将确保运行我们的容器的 Pods仍然可用; 部署,这将包含关于我们Pod的所需状态的信息; PersistentVolumeClaim为我们的数据库提供存储; ConfigMap为运行时注入的环境变量;和 秘密为我们的应用程序的数据库用户和密码。

首先,我们需要修改我们的docker-compose.yml文件中的某些定义以便与Kubernetes合作。我们将在我们的app服务定义中包含我们新建的应用程序图像的引用,并删除我们使用的 bind mouts, volumes和额外的 命令来运行与Compose开发中的应用程序容器,此外,我们还将重新定义两个容器的重新启动策略,以符合 Kubernetes 期望的行为

如果您已经遵循本教程中的步骤,并检查了 git 的构成工作流分支,那么您应该在工作目录中有一个docker-compose.yml文件。

如果您没有docker-compose.yml,请访问本系列的上一本教程,Containerizing a Ruby on Rails Application for Development with Docker Compose,并将链接的部分中的内容粘贴到新的docker-compose.yml文件中。

使用「nano」或您最喜歡的編輯器開啟檔案:

1nano docker-compose.yml

app应用程序服务的当前定义看起来如下:

 1[label ~/rails_project/docker-compose.yml]
 2. . .
 3services:
 4  app:
 5    build:
 6      context: .
 7      dockerfile: Dockerfile
 8    depends_on:
 9      - database
10      - redis
11    ports:
12      - "3000:3000"
13    volumes:
14      - .:/app
15      - gem_cache:/usr/local/bundle/gems
16      - node_modules:/app/node_modules
17    env_file: .env
18    environment:
19      RAILS_ENV: development
20. . .

对您的服务定义进行以下编辑:

  • 將「build:」字符串替換為「image: your_dockerhub_user/rails-kubernetes」
  • 刪除下列「背景:.」字符串和「dockerfile: Dockerfile」字符串
  • 刪除「卷」列表

已完成的服务定义现在将是这样的:

 1[label ~/rails_project/docker-compose.yml]
 2. . .
 3services:
 4  app:
 5    image: your_dockerhub_user/rails-kubernetes
 6    depends_on:
 7      - database
 8      - redis
 9    ports:
10      - "3000:3000"
11    env_file: .env
12    environment:
13      RAILS_ENV: development
14. . .

接下来,滚到数据库服务定义,并进行以下编辑:

  • 移除 -./init.sql:/docker-entrypoint-initdb.d/init.sql 卷线. 而不是从本地 SQL 文件中使用值,我们将将我们的 POSTGRES_USERPOSTGRES_PASSWORD 的值传输到我们在 [步骤 4] 中创建的秘密数据库容器中(#step-4-%E2%80%94-creating-kubernetes-secrets)。
  • 添加一个 port: 部分,使 PostgreSQL 在您的 Kubernetes 集群内可用在端口 5432.
  • 添加一个 environment: 部分,其中有 PGDATA 变量 指向 `/var

数据库服务的定义在您完成编辑时应该是这样的:

 1[label ~/rails_project/docker-compose.yml]
 2. . .
 3  database:
 4    image: postgres:12.1
 5    volumes:
 6      - db_data:/var/lib/postgresql/data
 7    ports:
 8      - "5432:5432"
 9    environment:
10      PGDATA: /var/lib/postgresql/data/pgdata
11. . .

接下来,编辑redis服务定义以揭露其默认的TCP端口,通过添加一个port:部分与默认的6379端口。

1[label ~/rails_project/docker-compose.yml]
2. . .
3  redis:
4    image: redis:5.0.7
5    ports:
6      - "6379:6379"

编辑文件的重置部分后,继续到sidekiq服务定义. 与app服务一样,您需要从构建本地 docker 图像切换到从 Docker Hub 切换。

  • 將「build:」字符串替換為「image: your_dockerhub_user/rails-kubernetes」
  • 刪除下列「背景:.」字符串和「dockerfile: Dockerfile」字符串
  • 刪除「卷」列表
 1[label ~/rails_project/docker-compose.yml]
 2. . .
 3  sidekiq:
 4    image: your_dockerhub_user/rails-kubernetes
 5    depends_on:
 6      - app
 7      - database
 8      - redis
 9    env_file: .env
10    environment:
11        RAILS_ENV: development
12    entrypoint: ./entrypoints/sidekiq-entrypoint.sh

最后,在文件的底部,从顶级的键中删除gem_cachenode_modules的卷。

1[label ~/rails_project/docker-compose.yml]
2. . .
3volumes:
4  db_data:

保存并关闭文件,当你完成编辑。

作为参考,您完成的 docker-compose.yml 文件应该包含以下内容:

 1[label ~/rails_project/docker-compose.yml]
 2version: '3'
 3
 4services:
 5  app:
 6    image: your_dockerhub_user/rails-kubernetes
 7    depends_on:
 8        - database
 9        - redis
10    ports:
11        - "3000:3000"
12    env_file: .env
13    environment:
14        RAILS_ENV: development
15
16  database:
17    image: postgres:12.1
18    volumes:
19        - db_data:/var/lib/postgresql/data
20    ports:
21        - "5432:5432"
22    environment:
23        PGDATA: /var/lib/postgresql/data/pgdata
24
25  redis:
26    image: redis:5.0.7
27    ports:
28        - "6379:6379"
29
30  sidekiq:
31    image: your_dockerhub_user/rails-kubernetes
32    depends_on:
33        - app
34        - database
35        - redis
36    env_file: .env
37    environment:
38        RAILS_ENV: development
39    entrypoint: ./entrypoints/sidekiq-entrypoint.sh
40
41volumes:
42  db_data:

在翻譯我們的服務定義之前,我們需要寫下「.env」檔案,而「kompose」將用來用我們非敏感資訊來創建 ConfigMap. 請參閱 Step 2Containerizing a Ruby on Rails Application for Development with Docker Compose的更多解釋。

在该教程中,我们添加了 .env 到我们的 .gitignore 文件,以确保它不会被复制到版本控制. 这意味着它没有被复制,当我们在 [本教程的第 2 步] 中克隆了 rails-sidekiq 存储库(#step-2-%E2%80%94-cloning-and-packaging-the-application)。

创建文件:

1nano .env

kompose将使用此文件为我们的应用程序创建 ConfigMap. 但是,而不是在我们的 Compose 文件中分配所有从app服务定义的变量,我们只会为 PostgreSQL 和 Redis 添加设置。 当我们在 [步骤 4] 中手动创建秘密对象时,我们将单独分配数据库名、用户名和密码(#step-4-%E2%80%94-creating-kubernetes-secrets)。

将以下端口和数据库名称信息添加到.dll 文件中. 如果您想要,请自由更名您的数据库:

1[label ~/rails_project/.env]
2DATABASE_HOST=database
3DATABASE_PORT=5432
4REDIS_HOST=redis
5REDIS_PORT=6379

保存并关闭文件,当你完成编辑。

你现在已经准备好用你的对象规格来创建文件了。 kompose 提供了 多个选项来翻译你的资源。

  • 创建 yaml 文件,基于您的 docker-compose.yml 文件中的服务定义,使用 kompose convert
  • 直接创建 Kubernetes 对象,使用 kompose up
  • 创建一个 Helm 图表,使用 kompose convert -c

目前,我们将服务定义转换为yaml文件,然后添加并修改kompose创建的文件。

用以下命令将服务定义转换为‘yaml’文件:

1kompose convert

运行此命令后,kompose 将输出有关它创建的文件的信息:

 1[secondary_label Output]
 2INFO Kubernetes file "app-service.yaml" created   
 3INFO Kubernetes file "database-service.yaml" created
 4INFO Kubernetes file "redis-service.yaml" created
 5INFO Kubernetes file "app-deployment.yaml" created
 6INFO Kubernetes file "env-configmap.yaml" created
 7INFO Kubernetes file "database-deployment.yaml" created
 8INFO Kubernetes file "db-data-persistentvolumeclaim.yaml" created
 9INFO Kubernetes file "redis-deployment.yaml" created
10INFO Kubernetes file "sidekiq-deployment.yaml" created

这些包括用于 Rails 应用程序服务、部署和 ConfigMap 的 yaml 文件,以及 PersistentVolumeClaim 和 PostgreSQL 数据库部署的 db-data 文件。

要将这些宣言保留在您的 Rails 项目的主目录中,请创建一个名为k8s-manifests的新目录,然后使用mv命令将生成的文件移动到其中:

1mkdir k8s-manifests
2mv *.yaml k8s-manifests

最后,‘cd’进入‘k8s-manifests’目录,从现在开始,我们将从这个目录内部工作,以保持事情的顺序:

1cd k8s-manifests

这些文件是一个很好的起点,但为了使我们的应用程序的功能符合在 Containerizing a Ruby on Rails Application for Development with Docker Compose中描述的设置,我们需要对构成所生成的文件进行一些添加和更改。

第4步:创建Kubernetes的秘密

为了使我们的应用程序以我们预期的方式运作,我们需要对构成创建的文件进行一些修改。 这些变化中的第一个将是为我们的数据库用户和密码生成一个秘密,并将其添加到我们的应用程序和数据库部署中。 Kubernetes提供两种工作方式与环境变量: ConfigMaps和秘密。

手动创建秘密的第一步是将数据转换为 base64,这是一种编码方案,允许您均匀传输数据,包括二进制数据。

首先将数据库名称转换为 base64 加密数据:

1echo -n 'your_database_name' | base64

记下编码的值。

转换您的数据库用户名:

1echo -n 'your_database_username' | base64

再次记录您在输出中看到的值。

最后,转换您的密码:

1echo -n 'your_database_password' | base64

在这里也注意输出中的价值。

打开秘密的文件:

1nano secret.yaml

<$>[注] 注: Kubernetes 对象是 通常定义使用 YAML,这严格禁止卡,并需要两个空格来插入。如果您想检查任何yaml文件的格式化,您可以使用 linter或使用cubectl create来测试您的语法的有效性,使用dry-runvalidate旗帜:

1kubectl create -f your_yaml_file.yaml --dry-run --validate=true

一般来说,在使用kubectl创建资源之前,最好先验证语法

将以下代码添加到文件中,以创建一个秘密,该代码将使用您刚刚创建的编码值定义您的DATABASE_NAME,DATABASE_USERDATABASE_PASSWORD

1[label ~/rails_project/k8s-manifests/secret.yaml]
2apiVersion: v1
3kind: Secret
4metadata:
5  name: database-secret
6data:
7  DATABASE_NAME: your_database_name
8  DATABASE_PASSWORD: your_encoded_password
9  DATABASE_USER: your_encoded_username

我们已经将秘密对象命名为数据库秘密,但您可以随意命名它。

这些秘密与 Rails 应用程序一起使用,以便它可以连接到 PostgreSQL. 但是,数据库本身需要以这些值进行初始化。 因此,接下来,复制三个行并粘贴到文件末尾。 编辑最后三个行,并将每个变量的DATABASE前缀更改为POSTGRES。 最后,更改POSTGRES_NAME变量以读取POSTGRES_DB

您的最终 secret.yaml 文件应该包含以下内容:

 1[label ~/rails_project/k8s-manifests/secret.yaml]
 2apiVersion: v1
 3kind: Secret
 4metadata:
 5  name: database-secret
 6data:
 7  DATABASE_NAME: your_database_name
 8  DATABASE_PASSWORD: your_encoded_password
 9  DATABASE_USER: your_encoded_username
10  POSTGRES_DB: your_database_name
11  POSTGRES_PASSWORD: your_encoded_password
12  POSTGRES_USER: your_encoded_username

当您完成编辑时,请保存并关闭此文件. 就像您在您的.env 文件中一样,请确保将 secret.yaml' 添加到您的 .gitignore' 文件中,以使其脱离版本控制。

隨著「secret.yaml」寫入,我們的下一步將是確保我們的應用程式和資料庫部署都使用我們添加到檔案的值。

打开名为 'app-deployment.yaml' 的文件:

1nano app-deployment.yaml

文件的容器规格包括以下env键下定义的环境变量:

 1[label ~/rails_project/k8s-manifests/app-deployment.yaml]
 2apiVersion: apps/v1
 3kind: Deployment
 4. . .
 5    spec:
 6      containers:
 7        - env:
 8            - name: DATABASE_HOST
 9              valueFrom:
10                configMapKeyRef:
11                  key: DATABASE_HOST
12                  name: env
13            - name: DATABASE_PORT
14              valueFrom:
15                configMapKeyRef:
16                  key: DATABASE_PORT
17                  name: env
18            - name: RAILS_ENV
19              value: development
20            - name: REDIS_HOST
21              valueFrom:
22                configMapKeyRef:
23                  key: REDIS_HOST
24                  name: env
25            - name: REDIS_PORT
26              valueFrom:
27                configMapKeyRef:
28                  key: REDIS_PORT
29                  name: env
30. . .

我们将需要添加链接到我们的秘密,以便我们的应用程序可以访问这些值。而不是添加一个configMapKeyRef密钥,以指向我们的env ConfigMap,就像现有的值一样,我们将包括一个秘密KeyRef密钥,以指向我们的数据库秘密中的值。

将以下秘密引用添加到 - 名称: REDIS_PORT 变量部分后:

 1[label ~/rails_project/k8s-manifests/app-deployment.yaml]
 2. . .
 3    spec:
 4      containers:
 5        - env:
 6        . . .  
 7            - name: REDIS_PORT
 8              valueFrom:
 9                configMapKeyRef:
10                  key: REDIS_PORT
11                  name: env
12            - name: DATABASE_NAME
13              valueFrom:
14                secretKeyRef:
15                  name: database-secret
16                  key: DATABASE_NAME
17            - name: DATABASE_PASSWORD
18              valueFrom:
19                secretKeyRef:
20                  name: database-secret
21                  key: DATABASE_PASSWORD
22            - name: DATABASE_USER
23              valueFrom:
24                secretKeyRef:
25                  name: database-secret
26                  key: DATABASE_USER
27. . .

当您完成编辑时,请保存并关闭该文件. 与您的'secrets.yaml' 文件一样,请确保使用 'kubectl' 验证您的编辑,以确保没有间隔、卡和插入问题:

1kubectl create -f app-deployment.yaml --dry-run --validate=true
1[secondary_label Output]
2deployment.apps/app created (dry run)

接下来,我们会将相同的值添加到 database-deployment.yaml 文件中。

打开文件以编辑:

1nano database-deployment.yaml

在此文件中,我们将为以下变量键添加我们的秘密引用: POSTGRES_DB, POSTGRES_USERPOSTGRES_PASSWORD. postgres 图像使这些变量可用,以便您可以修改数据库实例的初始化。 POSTGRES_DB 创建了一个默认数据库,在容器启动时可用。

使用这些值意味着我们创建的用户可以访问 PostgreSQL 中的所有管理和操作权限。

POSTGRES_DB,POSTGRES_USERPOSTGRES_PASSWORD变量下,添加对秘密值的引用:

 1[label ~/rails_project/k8s-manifests/database-deployment.yaml]
 2apiVersion: apps/v1
 3kind: Deployment
 4. . .
 5    spec:
 6      containers:
 7        - env:
 8            - name: PGDATA
 9              value: /var/lib/postgresql/data/pgdata
10            - name: POSTGRES_DB
11              valueFrom:
12                secretKeyRef:
13                  name: database-secret
14                  key: POSTGRES_DB
15            - name: POSTGRES_PASSWORD
16              valueFrom:
17                secretKeyRef:
18                  name: database-secret
19                  key: POSTGRES_PASSWORD        
20            - name: POSTGRES_USER
21              valueFrom:
22                secretKeyRef:
23                  name: database-secret
24                  key: POSTGRES_USER
25. . .

当您完成编辑时,请保存并关闭文件. 再次,请确保使用 kubectl 将编辑的文件链接到 --dry-run --validate=true 参数。

有了您的秘密,您可以继续创建数据库服务,并确保您的应用程序容器只在完全设置和初始化后尝试连接到数据库。

步骤 5 – 更改持久 VolumeClaim 并暴露应用程序前端

在运行我们的应用程序之前,我们将做出两个最终的更改,以确保我们的数据库存储空间得到适当的配置,并且我们可以使用 LoadBalancer 曝光我们的应用程序前端。

首先,让我们修改为我们创建的 PersistentVolumeClaim 中定义的 storage resource 这个声明允许我们 dynamically provision 存储来管理我们的应用程序的状态。

要使用 PersistentVolumeClaims,您必须创建并配置一个 StorageClass以提供存储资源. 在我们的情况下,因为我们正在使用 DigitalOcean Kubernetes,我们的默认 StorageClass provisioner 设置为 dobs.csi.digitalocean.com - DigitalOcean Block Storage

我们可以通过键入来检查:

1kubectl get storageclass

如果您正在使用 DigitalOcean 集群,您将看到以下输出:

1[secondary_label Output]
2NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3do-block-storage (default)   dobs.csi.digitalocean.com Delete Immediate true 76m

如果您不使用 DigitalOcean 集群,则需要创建 StorageClass 并配置您所选择的供应商

kompose创建db-data-persistentvolumeclaim.yaml时,它将存储``资源设置为不符合我们供应商的最低尺寸要求的尺寸。

打开db-data-persistentvolumeclaim.yaml:

1nano db-data-persistentvolumeclaim.yaml

存储值替换为1Gi:

 1[label ~/rails_project/k8s-manifests/db-data-persistentvolumeclaim.yaml]
 2apiVersion: v1
 3kind: PersistentVolumeClaim
 4metadata:
 5  creationTimestamp: null
 6  labels:
 7    io.kompose.service: db-data
 8  name: db-data
 9spec:
10  accessModes:
11    - ReadWriteOnce
12  resources:
13    requests:
14      storage: 1Gi
15status: {}

另外,请注意accessMode:ReadWriteOnce意味着本声明所提供的内容仅由单个节点进行读写。

保存并关闭文件,当你完成。

接下来,打开app-service.yaml:

1nano app-service.yaml

我们将使用 DigitalOcean Load Balancer外部展示此服务。如果您不使用 DigitalOcean 集群,请参阅您的云提供商的相关文档,以获取其负载平衡器的信息。

在服务规格中,指定LoadBalancer作为服务类型:

1[label ~/rails_project/k8s-manifests/app-service.yaml]
2apiVersion: v1
3kind: Service
4. . .
5spec:
6  type: LoadBalancer
7  ports:
8. . .

当我们创建应用服务时,将自动创建负载平衡器,为我们提供一个外部IP,我们可以访问我们的应用。

保存并关闭文件,当你完成编辑。

有了我们所有的文件,我们已经准备好启动和测试应用程序。

<$>[注] 注: 如果您想将编辑的Kubernetes宣言与一组参考文件进行比较,以确保您的更改与本教程相匹配,则 companion Github repository包含一组经过测试的宣言。

如果您选择切换分支,请确保将您的secrets.yaml文件复制到新版本,因为我们在教程中早些时候添加到.gitignore

步骤 6 – 启动和访问应用程序

是时候创建我们的Kubernetes对象,并测试我们的应用程序是否按预期工作。

为了创建我们已经定义的对象,我们将使用 kubectl create 带有 -f 旗帜,这将允许我们指定为我们创建的 compose 文件,以及我们写的文件。

1kubectl create -f app-deployment.yaml,app-service.yaml,database-deployment.yaml,database-service.yaml,db-data-persistentvolumeclaim.yaml,env-configmap.yaml,redis-deployment.yaml,redis-service.yaml,secret.yaml,sidekiq-deployment.yaml

您将收到以下输出,表示已创建对象:

 1[secondary_label Output]
 2deployment.apps/app created
 3service/app created
 4deployment.apps/database created
 5service/database created
 6persistentvolumeclaim/db-data created
 7configmap/env created
 8deployment.apps/redis created
 9service/redis created
10secret/database-secret created
11deployment.apps/sidekiq created

要检查你的 Pods 是否正在运行,键入:

1kubectl get pods

您不需要在这里指定 Namespace,因为我们在默认 Namespace 中创建了我们的对象. 如果您正在使用多个 Namespaces,请确保在运行这个kubectl 创建命令时包括-n 旗帜,以及您的 Namespace 名称。

当您的数据库容器启动时,您将看到类似于以下的输出(状态将是悬挂ContainerCreating):

1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3app-854d645fb9-9hv7w 1/1 Running 0 23s
4database-c77d55fbb-bmfm8 0/1 Pending 0 23s
5redis-7d65467b4d-9hcxk 1/1 Running 0 23s
6sidekiq-867f6c9c57-mcwks 1/1 Running 0 23s

一旦启动数据库容器,您将有这样的输出:

1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3app-854d645fb9-9hv7w 1/1 Running 0 30s
4database-c77d55fbb-bmfm8 1/1 Running 0 30s
5redis-7d65467b4d-9hcxk 1/1 Running 0 30s
6sidekiq-867f6c9c57-mcwks 1/1 Running 0 30s

运行 状态 表示您的 Pod 绑定到节点,并且与这些 Pod 相关的容器正在运行。

<$>[注] 注: 如果您在状态列中看到意想不到的阶段,请记住,您可以使用以下命令来解决您的Pod:

1kubectl describe pods your_pod
2kubectl logs your_pod

美元

现在您的应用程序已启动并运行,需要执行的最后一步是运行 Rails 的数据库迁移。

要运行等待迁移,您将执行到正在运行的应用程序Pod,然后调用rake db:migrate命令。

首先,用以下命令找到应用程序pod的名称:

1kubectl get pods

在以下输出中找到与您的应用程序相匹配的pod,如突出的pod名称:

1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3app-854d645fb9-9hv7w 1/1 Running 0 30s
4database-c77d55fbb-bmfm8 1/1 Running 0 30s
5redis-7d65467b4d-9hcxk 1/1 Running 0 30s
6sidekiq-867f6c9c57-mcwks 1/1 Running 0 30s

有了这个 pod 名称,您现在可以运行kubectl exec命令来完成数据库迁移步骤。

使用此命令运行迁移:

1kubectl exec your_app_pod_name -- rake db:migrate

您应该收到类似于以下的输出,这表明数据库方案已加载:

 1[secondary_label Output]
 2== 20190927142853 CreateSharks: migrating =====================================
 3-- create_table(:sharks)
 4   -> 0.0190s
 5== 20190927142853 CreateSharks: migrated (0.0208s) ============================
 6
 7== 20190927143639 CreatePosts: migrating ======================================
 8-- create_table(:posts)
 9   -> 0.0398s
10== 20190927143639 CreatePosts: migrated (0.0421s) =============================
11
12== 20191120132043 CreateEndangereds: migrating ================================
13-- create_table(:endangereds)
14   -> 0.8359s
15== 20191120132043 CreateEndangereds: migrated (0.8367s) =======================

随着容器运行和数据加载,您现在可以访问应用程序. 要获取应用程序LoadBalancer的IP,键入:

1kubectl get svc

您将收到如下的输出:

1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)          AGE
3app LoadBalancer 10.245.73.142 your_lb_ip 3000:31186/TCP 21m
4database ClusterIP 10.245.155.87   <none>           5432/TCP 21m
5kubernetes ClusterIP 10.245.0.1      <none>           443/TCP 21m
6redis ClusterIP 10.245.119.67   <none>           6379/TCP 21m

应用服务相关联的EXTERNAL_IP是您可以访问应用程序的IP地址,如果您在EXTERNAL_IP列中看到<pending>状态,则意味着您的负载平衡器仍在创建中。

一旦您在该列中看到一个IP,请在浏览器中导航到它: http://your_lb_ip:3000

你应该看到下面的登陆页面:

Application Landing Page

点击获取鲨鱼信息按钮,您将有一个页面以创建新鲨鱼的按钮:

Shark Info Form

点击它,当提示时,输入上一系列教程中的用户名和密码. 如果您没有更改这些值,则默认值分别为sammyshark

在表格中,添加您所选择的鲨鱼。 为了示范,我们将Megalodon Shark添加到 Shark Name字段,并将Ancient添加到 Shark Character字段:

Filled Shark Form

点击提交按钮,您将看到一个页面,其中有这些鲨鱼信息向您显示:

Shark Output

您现在有一个单个实例设置 Rails 应用程序与运行在 Kubernetes 集群上的 PostgreSQL 数据库. 您还有一个 Redis 缓存和一个 Sidekiq 工人来处理用户提交的数据。

结论

您在本教程中创建的文件是一个很好的起点,当您向生产前进时,您可以建立一个良好的起点。

  • ** 集中伐木和监测**。 请参看[更新Kubernetes的应用程序(https://andsky.com/tech/tutorials/modernizing-applications-for-kubernetes)中的相关讨论,以了解概况。 也可以研究[如何在Kubernetes上设置弹性搜索、流利和基巴纳(EFK)记录堆栈(https://andsky.com/tech/tutorials/how-to-set-up-an-elasticsearch-fluentd-and-kibana-efk-logging-stack-on-kubernetes),以学习如何用弹性搜索流利地Kibana设置伐木堆栈。 另请检查服务网点介绍,了解Istio等服务网点如何实施此功能。 () ( )* ** 入侵资源通往您的集群**。 这在您正在运行多个服务时(每个服务都需要自己的LoadBalancer),或者您想要实施应用级的路由策略(例如A/B & 金丝雀测试)的情况下,是一个很好的替代品. 欲了解更多信息,请查看DigitalOcean Kubernetes上的Nginx Engress与Cert-Manager一起设置一个Nginx Engress,以及服务Meshes介绍中服务网上路由的相关讨论*。 ** Kubernetes对象的备份策略**。 关于使用DigitalOcean的Kubernetes产品Verero实施备份的指导意见,请参见如何备份并恢复DigitalOcean使用Velero的Kubernetes集群。 () (英语)
Published At
Categories with 技术
comments powered by Disqus