什么是 Kubernetes? 容器化和部署指南
已发表: 2022-03-11不久前,我们使用了单体式 Web 应用程序:庞大的代码库随着新功能和特性的增长而发展,直到它们变成巨大的、移动缓慢、难以管理的巨人。 现在,越来越多的开发人员、架构师和 DevOps 专家开始认为,使用微服务比使用巨型单体更好。 通常,使用基于微服务的架构意味着将您的单体应用程序拆分为至少两个应用程序:前端应用程序和后端应用程序(API)。 在决定使用微服务之后,就会出现一个问题:在什么环境下运行微服务比较好? 我应该选择什么来使我的服务稳定且易于管理和部署? 简短的回答是:使用 Docker!
在本文中,我将向您介绍容器,解释 Kubernetes,并教您如何使用 CircleCI 将应用程序容器化并部署到 Kubernetes 集群。
码头工人? 什么是 Docker?
Docker 是一个旨在让 DevOps(和您的生活)更轻松的工具。 使用 Docker,开发人员可以在容器中创建、部署和运行应用程序。 容器允许开发人员将应用程序与它需要的所有部分(例如库和其他依赖项)打包在一起,并将它们作为一个包全部发送出去。
使用容器,开发人员可以轻松(重新)将映像部署到任何操作系统。 只需安装 Docker,执行一个命令,您的应用程序就会启动并运行。 哦,不用担心与主机操作系统中的新版本库有任何不一致。 此外,您可以在同一主机上启动更多容器——它是同一个应用程序还是另一个? 没关系。
似乎 Docker 是一个很棒的工具。 但是我应该如何以及在哪里启动容器?
关于容器的运行方式和位置有很多选择:AWS Elastic Container Service(AWS Fargate 或具有水平和垂直自动缩放功能的预留实例); 在 Azure 或 Google Cloud 中具有预定义 Docker 映像的云实例(带有模板、实例组和自动缩放); 使用 Docker 在您自己的服务器上; 或者,当然,Kubernetes! Kubernetes 是 Google 的工程师在 2014 年专门为虚拟化和容器创建的。
Kubernetes? 那是什么?
Kubernetes 是一个开源系统,它允许您运行容器、管理容器、自动化部署、扩展部署、创建和配置入口、部署无状态或有状态应用程序以及许多其他事情。 基本上,您可以启动一个或多个实例并安装 Kubernetes 以将它们作为 Kubernetes 集群运行。 然后获取 Kubernetes 集群的 API 端点,配置kubectl
(管理 Kubernetes 集群的工具),Kubernetes 就可以服务了。
那么我为什么要使用它呢?
使用 Kubernetes,您可以最大限度地利用计算资源。 使用 Kubernetes,您将成为您的船(基础设施)的船长,Kubernetes 将助您一臂之力。 使用 Kubernetes,您的服务将是 HA。 最重要的是,使用 Kubernetes,您将节省大量资金。
看起来很有希望! 特别是如果它会省钱! 让我们多谈谈吧!
Kubernetes 日复一日地越来越受欢迎。 让我们更深入地研究引擎盖下的内容。
引擎盖下:什么是 Kubernetes?
Kubernetes 是整个系统的名称,但就像您的汽车一样,有许多小部件完美协调地协同工作以使 Kubernetes 发挥作用。 让我们了解它们是什么。
主节点——整个 Kubernetes 集群的控制面板。 master 的组件可以在集群中的任何节点上运行。 关键组件是:
- API 服务器:所有 REST 命令的入口点,是用户可访问的主节点的唯一组件。
- 数据存储: Kubernetes 集群使用的强大、一致且高可用的键值存储。
- 调度程序:监视新创建的 pod 并将它们分配给节点。 由于调度程序,将 Pod 和服务部署到节点上。
- 控制器管理器:运行集群中处理日常任务的所有控制器。
- Worker 节点:主节点代理,也称为 Minion 节点。 豆荚在这里运行。 工作节点包含所有必要的服务来管理容器之间的网络、与主节点通信以及为调度的容器分配资源。
- Docker:在每个工作节点上运行并下载图像和启动容器。
- Kubelet:监控 pod 的状态并确保容器启动并运行。 它还与数据存储进行通信,获取有关服务的信息并写入有关新创建的服务的详细信息。
- Kube-proxy:单个工作节点上服务的网络代理和负载均衡器。 它负责流量路由。
- Kubectl:用户与 Kubernetes API 服务器通信的 CLI 工具。
什么是 Pod 和服务?
Pod 是Kubernetes集群的最小单元,它就像一栋巨大建筑的墙上的一块砖。 Pod 是一组需要一起运行并且可以共享资源(Linux 命名空间、cgroup、IP 地址)的容器。 豆荚的寿命不长。
服务是许多 pod 之上的抽象,通常需要一个代理,其他服务才能通过虚拟 IP 地址与其通信。
简单部署示例
我将使用一个简单的 Ruby on Rails 应用程序和 GKE 作为运行 Kubernetes 的平台。 实际上,您可以在 AWS 或 Azure 中使用 Kubernetes,甚至可以在自己的硬件中创建集群,或者使用minikube
在本地运行 Kubernetes——您可以在此页面上找到所有选项。
此应用程序的源文件可在此 GitHub 存储库中找到。
要创建一个新的 Rails 应用程序,请执行:
rails new blog
在config/database.yml file
中为生产配置 MySQL 连接:
production: adapter: mysql2 encoding: utf8 pool: 5 port: 3306 database: <%= ENV['DATABASE_NAME'] %> host: 127.0.0.1 username: <%= ENV['DATABASE_USERNAME'] %> password: <%= ENV['DATABASE_PASSWORD'] %>
要创建 Article 模型、控制器、视图和迁移,请执行:
rails g scaffold Article title:string description:text
要将 gem 添加到 Gemfile:
gem 'mysql2', '< 0.6.0', '>= 0.4.4' gem 'health_check'
要创建 Docker 映像,请获取我的 Dockerfile 并执行:
docker build -t REPO_NAME/IMAGE_NAME:TAG . && docker push REPO_NAME/IMAGE_NAME:TAG
是时候创建一个 Kubernetes 集群了。 打开 GKE 页面并创建 Kubernetes 集群。 创建集群后,单击“连接按钮”并复制命令——确保您已安装并配置 gCloud CLI 工具(操作方法)和 kubectl。 在您的 PC 上执行复制的命令并检查与 Kubernetes 集群的连接; 执行kubectl cluster-info
。
该应用程序已准备好部署到 k8s 集群。 让我们创建一个 MySQL 数据库。 在 gCloud 控制台中打开 SQL 页面并为应用程序创建一个 MySQL 数据库实例。 实例准备就绪后,创建用户和数据库并复制实例连接名称。
此外,我们需要在API & Services页面中创建一个服务帐户密钥,以便从 sidecar 容器访问 MySQL 数据库。 您可以在此处找到有关该过程的更多信息。 将下载的文件重命名为service-account.json
。 我们稍后会回到那个文件。
我们已经准备好将我们的应用程序部署到 Kubernetes,但首先,我们应该为我们的应用程序创建秘密——Kubernetes 中为存储敏感数据而创建的秘密对象。 上传之前下载的service-account.json
文件:
kubectl create secret generic mysql-instance-credentials \ --from-file=credentials.json=service-account.json
为应用程序创建秘密:

kubectl create secret generic simple-app-secrets \ --from-literal=username=$MYSQL_PASSWORD \ --from-literal=password=$MYSQL_PASSWORD \ --from-literal=database-name=$MYSQL_DB_NAME \ --from-literal=secretkey=$SECRET_RAILS_KEY
不要忘记用您的值替换值或设置环境变量。
在创建部署之前,让我们看一下部署文件。 我将三个文件合并为一个; 第一部分是一个服务,它将公开端口 80 并将所有来自端口 80 的连接转发到 3000。该服务有一个选择器,服务通过该选择器知道它应该向哪些 pod 转发连接。
文件的下一部分是部署,它描述了部署策略——将在 pod 内启动的容器、环境变量、资源、探测器、每个容器的挂载以及其他信息。
最后一部分是 Horizontal Pod Autoscaler。 HPA有一个非常简单的配置。 请记住,如果您没有在部署部分为容器设置资源, HPA将无法工作。
您可以在 GKE 编辑页面中为您的 Kubernetes 集群配置 Vertical Autoscaler。 它也有一个非常简单的配置。
是时候将它发送到 GKE 集群了! 首先,我们应该通过 job 运行迁移。 执行:
kubectl apply -f rake-tasks-job.yaml
- 此作业对 CI/CD 流程很有用。
kubectl apply -f deployment.yaml
– 创建服务、部署和 HPA。
然后通过执行以下命令检查您的 pod: kubectl get pods -w
NAME READY STATUS RESTARTS AGE sample-799bf9fd9c-86cqf 2/2 Running 0 1m sample-799bf9fd9c-887vv 2/2 Running 0 1m sample-799bf9fd9c-pkscp 2/2 Running 0 1m
现在让我们为应用程序创建一个入口:
- 创建静态 IP:
gcloud compute addresses create sample-ip --global
- 创建入口(文件):
kubectl apply -f ingress.yaml
- 检查入口是否已经创建并获取IP:
kubectl get ingress -w
- 为您的应用程序创建域/子域。
CI/CD
让我们使用 CircleCI 创建一个 CI/CD 管道。 实际上,使用 CircleCI 创建 CI/CD 管道很容易,但请记住,没有像这样的测试的快速而肮脏的全自动部署过程将适用于小型项目,但请不要为任何严重的事情这样做,因为,如果任何新代码在生产中出现问题,你就会赔钱。 这就是为什么你应该考虑设计一个健壮的部署过程,在完全推出之前启动金丝雀任务,在金丝雀启动后检查日志中的错误等等。
目前,我们有一个小而简单的项目,所以让我们创建一个完全自动化的、无需测试的 CI/CD 部署过程。 首先,您应该将 CircleCI 与您的存储库集成——您可以在此处找到所有说明。 然后我们应该创建一个配置文件,其中包含 CircleCI 系统的说明。 配置看起来很简单。 要点是 GitHub repo 中有两个分支: master
和production
。
- master 分支用于开发,用于新代码。 当有人将新代码推送到主分支时,CircleCI 会启动主分支的工作流程——构建和测试代码。
- 生产分支用于将新版本部署到生产环境。 生产分支的工作流程如下:推送新代码(或者更好的是,从主分支打开 PR 到生产)以触发新的构建和部署过程; 在构建过程中,CircleCI 创建新的 Docker 镜像,将其推送到 GCR 并为部署创建新的 rollout; 如果推出失败,CircleCI 会触发回滚过程。
在运行任何构建之前,您应该在 CircleCI 中配置一个项目。 在 API 中创建一个新的服务帐户,并在 GCloud 中使用以下角色创建一个服务页面:完全访问 GCR 和 GKE,打开下载的 JSON 文件并复制内容,然后在 CircleCI 的项目设置中创建一个新的环境变量,名称为GCLOUD_SERVICE_KEY
并将服务帐户文件的内容粘贴为值。 此外,您需要创建下一个环境变量: GOOGLE_PROJECT_ID
(您可以在 GCloud 控制台主页上找到它)、 GOOGLE_COMPUTE_ZONE
(您的 GKE 集群的区域)和GOOGLE_CLUSTER_NAME
(GKE 集群名称)。
CircleCI 的最后一步(部署)如下所示:
kubectl patch deployment sample -p '{"spec":{"template":{"spec":{"containers":[{"name":"sample","image":"gcr.io/test-d6bf8/simple:'"$CIRCLE_SHA1"'"}]}}}}' if ! kubectl rollout status deploy/sample; then echo "DEPLOY FAILED, ROLLING BACK TO PREVIOUS" kubectl rollout undo deploy/sample # Deploy failed -> notify slack else echo "Deploy succeeded, current version: ${CIRCLE_SHA1}" # Deploy succeeded -> notify slack fi deployment.extensions/sample patched Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "sample" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "sample" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "sample" rollout to finish: 2 of 3 updated replicas are available... Waiting for deployment "sample" rollout to finish: 2 of 3 updated replicas are available... deployment "sample" successfully rolled out Deploy succeeded, current version: 512eabb11c463c5431a1af4ed0b9ebd23597edd9
结论
看起来创建新的 Kubernetes 集群的过程并不难! CI/CD 过程真的很棒!
是的! Kubernetes 太棒了! 使用 Kubernetes,您的系统将更加稳定、易于管理,并使您成为系统的负责人。 更不用说,Kubernetes 对系统进行了一点游戏化,将为您的营销提供 +100 分!
现在您已经掌握了基础知识,您可以更进一步,将其转变为更高级的配置。 我计划在以后的文章中介绍更多内容,但与此同时,这里有一个挑战:为您的应用程序创建一个健壮的 Kubernetes 集群,其中有一个位于集群内部的有状态数据库(包括用于进行备份的 sidecar Pod),将 Jenkins 安装在相同的 Kubernetes 集群用于 CI/CD 管道,并让 Jenkins 使用 pod 作为构建的从属。 使用 certmanager 为您的入口添加/获取 SSL 证书。 使用 Stackdriver 为您的应用创建监控和警报系统。
Kubernetes 很棒,因为它易于扩展,没有供应商锁定,而且由于您为实例付费,因此可以节省资金。 然而,并不是每个人都是 Kubernetes 专家或有时间建立一个新的集群——对于另一种观点,Toptaler Amin Shah Gilani 提出了使用 Heroku、GitLab CI 和他已经想出的大量自动化的案例为了在How to Build an Effective Initial Deployment Pipeline中编写更多的代码,做更少的操作任务。
- 做数学:使用 Orchestrator 自动扩展微服务应用程序
- K8s/Kubernetes:AWS 与 GCP 与 Azure
- Kubernetes 服务网格比较