如何在DigitalOcean Kubernetes上部署弹性Go应用程序

The author selected Girls Who Code to receive a donation as part of the Write for DOnations program.

作者选择了《编码的女孩》作为Write for DOnations计划的一部分来接受捐赠。

介绍 (Introduction)

Docker is a containerization tool used to provide applications with a filesystem holding everything they need to run, ensuring that the software will have a consistent run-time environment and will behave the same way regardless of where it is deployed. Kubernetes is a cloud platform for automating the deployment, scaling, and management of containerized applications.

Docker是一种容器化工具,用于为应用程序提供一个文件系统,其中包含运行所需的一切,以确保该软件具有一致的运行时环境,并且无论部署在何处,其行为方式都相同。 Kubernetes是一个云平台,用于自动化容器化应用程序的部署,扩展和管理。

By leveraging Docker, you can deploy an application on any system that supports Docker with the confidence that it will always work as intended. Kubernetes, meanwhile, allows you to deploy your application across multiple nodes in a cluster. Additionally, it handles key tasks such as bringing up new containers should any of your containers crash. Together, these tools streamline the process of deploying an application, allowing you to focus on development.

通过利用Docker,您可以在支持Docker的任何系统上部署应用程序,并且可以始终按预期运行。 同时,Kubernetes允许您跨集群中的多个节点部署应用程序。 此外,它还处理关键任务,例如在您的任何容器崩溃时提起新容器。 这些工具在一起可以简化部署应用程序的过程,使您可以专注于开发。

In this tutorial, you will build an example application written in Go and get it up and running locally on your development machine. Then you’ll containerize the application with Docker, deploy it to a Kubernetes cluster, and create a load balancer that will serve as the public-facing entry point to your application.

在本教程中,您将构建一个用Go编写的示例应用程序,并将其安装并在开发计算机上本地运行。 然后,您将使用Docker对该应用程序进行容器化,将其部署到Kubernetes集群,并创建一个负载平衡器,该负载平衡器将作为应用程序的面向公众的入口点。

先决条件 (Prerequisites)

Before you begin this tutorial, you will need the following:

在开始本教程之前,您需要满足以下条件:

  • A development server or local machine from which you will deploy the application. Although the instructions in this guide will largely work for most operating systems, this tutorial assumes that you have access to an Ubuntu 18.04 system configured with a non-root user with sudo privileges, as described in our Initial Server Setup for Ubuntu 18.04 tutorial.

    您将从中部署应用程序的开发服务器或本地计算机。 尽管本指南中的说明在大多数操作系统上都适用,但本教程假定您可以访问配置了具有sudo特权的非root用户的Ubuntu 18.04系统,如我们的Ubuntu 18.04初始服务器设置教程中所述。

  • The docker command-line tool installed on your development machine. To install this, follow Steps 1 and 2 of our tutorial on How to Install and Use Docker on Ubuntu 18.04.

    开发机器上安装的docker命令行工具。 要安装它,请遵循我们的教程如何在Ubuntu 18.04上安装和使用Docker的 步骤1和2

  • The kubectl command-line tool installed on your development machine. To install this, follow this guide from the official Kubernetes documentation.

    开发机器上安装的kubectl命令行工具。 要安装它,请遵循Kubernetes官方文档中的本指南

  • A free account on Docker Hub to which you will push your Docker image. To set this up, visit the Docker Hub website, click the Get Started button at the top-right of the page, and follow the registration instructions.

    Docker Hub上的一个免费帐户,您可以将Docker映像推送到该帐户。 要进行设置,请访问Docker Hub网站 ,单击页面右上方的“ 入门”按钮,然后按照注册说明进行操作。

  • A Kubernetes cluster. You can provision a DigitalOcean Kubernetes cluster by following our Kubernetes Quickstart guide. You can still complete this tutorial if you provision your cluster from another cloud provider. Wherever you procure your cluster, be sure to set up a configuration file and ensure that you can connect to the cluster from your development server.

    Kubernetes集群 您可以按照我们的Kubernetes快速入门指南来配置DigitalOcean Kubernetes集群 。 如果您从其他云提供商配置群集,则仍然可以完成本教程。 无论在何处采购群集,请确保设置配置文件,并确保可以从开发服务器连接到群集。

步骤1 —在Go中构建示例Web应用程序 (Step 1 — Building a Sample Web Application in Go)

In this step, you will build a sample application written in Go. Once you containerize this app with Docker, it will serve My Awesome Go App in response to requests to your server’s IP address at port 3000.

在这一步中,您将构建一个用Go编写的示例应用程序。 使用Docker将此应用容器化后,它将在“端口3000对服务器IP地址的请求中响应My Awesome Go App

Get started by updating your server’s package lists if you haven’t done so recently:

通过最近更新服务器的软件包列表来开始使用:

  • sudo apt update

    sudo apt更新

Then install Go by running:

然后运行以下命令安装Go:

  • sudo apt install golang

    sudo apt安装golang

Next, make sure you’re in your home directory and create a new directory which will contain all of your project files:

接下来,确保您位于主目录中,并创建一个包含所有项目文件的新目录:

  • cd && mkdir go-app

    cd && mkdir go-app

Then navigate to this new directory:

然后导航到该新目录:

  • cd go-app/

    cd go-app /

Use nano or your preferred text editor to create a file named main.go which will contain the code for your Go application:

使用nano或您喜欢的文本编辑器创建一个名为main.go的文件,其中将包含Go应用程序的代码:

  • nano main.go

    纳米main.go

The first line in any Go source file is always a package statement that defines which code bundle the file belongs to. For executable files like this one, the package statement must point to the main package:

任何Go源文件中的第一行始终是package语句,用于定义文件所属的代码束。 对于像这样的可执行文件, package语句必须指向main包:

go-app/main.go
go-app / main.go
package main

Following that, add an import statement where you can list all the libraries the application will need. Here, include fmt, which handles formatted text input and output, and net/http, which provides HTTP client and server implementations:

接下来,添加一个import语句,您可以在其中列出该应用程序所需的所有库。 在这里,包括处理格式化文本输入和输出的fmt和提供HTTP客户端和服务器实现的net/http

go-app/main.go
go-app / main.go
package main

import (
  "fmt"
  "net/http"
)

Next, define a homePage function which will take in two arguments: http.ResponseWriter and a pointer to http.Request. In Go, a ResponseWriter interface is used to construct an HTTP response, while http.Request is an object representing an incoming request. Thus, this block reads incoming HTTP requests and then constructs a response:

接下来,定义一个homePage函数,该函数将包含两个参数: http.ResponseWriter和一个指向http.Request的指针。 在Go中, ResponseWriter接口用于构造HTTP响应,而http.Request是表示传入请求的对象。 因此,此块读取传入的HTTP请求,然后构造一个响应:

go-app/main.go
go-app / main.go
. . .

import (
  "fmt"
  "net/http"
)

func homePage(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "My Awesome Go App")
}

After this, add a setupRoutes function which will map incoming requests to their intended HTTP handler functions. In the body of this setupRoutes function, add a mapping of the / route to your newly defined homePage function. This tells the application to print the My Awesome Go App message even for requests made to unknown endpoints:

此后,添加setupRoutes函数,它将传入请求映射到其预期的HTTP处理程序函数。 在该setupRoutes函数的主体中,将/ route的映射添加到新定义的homePage函数。 这告诉应用My Awesome Go App即使对未知端点发出的请求也要打印My Awesome Go App消息:

go-app/main.go
go-app / main.go
. . .

func homePage(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "My Awesome Go App")
}

func setupRoutes() {
  http.HandleFunc("/", homePage)
}

And finally, add the following main function. This will print out a string indicating that your application has started. It will then call the setupRoutes function before listening and serving your Go application on port 3000.

最后,添加以下main功能。 这将打印出一个字符串,指示您的应用程序已启动。 然后, setupRoutes在侦听端口3000上的Go应用程序并setupRoutes提供服务之前,调用setupRoutes函数。

go-app/main.go
go-app / main.go
. . .

func setupRoutes() {
  http.HandleFunc("/", homePage)
}

func main() {
  fmt.Println("Go Web App Started on Port 3000")
  setupRoutes()
  http.ListenAndServe(":3000", nil)
}

After adding these lines, this is how the final file will look:

添加这些行之后,这就是最终文件的外观:

go-app/main.go
go-app / main.go
package main

import (
  "fmt"
  "net/http"
)

func homePage(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "My Awesome Go App")
}

func setupRoutes() {
  http.HandleFunc("/", homePage)
}

func main() {
  fmt.Println("Go Web App Started on Port 3000")
  setupRoutes()
  http.ListenAndServe(":3000", nil)
}

Save and close this file. If you created this file using nano, do so by pressing CTRL + X, Y, then ENTER.

保存并关闭此文件。 如果使用nano创建此文件,请按CTRL + XY ,然后按ENTER

Next, run the application using the following go run command. This will compile the code in your main.go file and run it locally on your development machine:

接下来,使用以下go run命令运行该应用程序。 这将编译main.go文件中的代码,并在开发计算机上本地运行:

  • go run main.go

    去运行main.go

   
   
Output
Go Web App Started on Port 3000

This output confirms that the application is working as expected. It will run indefinitely, however, so close it by pressing CTRL + C.

此输出确认该应用程序按预期运行。 但是它将无限期运行,因此请按CTRL + C其关闭。

Throughout this guide, you will use this sample application to experiment with Docker and Kubernetes. To that end, continue reading to learn how to containerize your application with Docker.

在本指南中,您将使用该示例应用程序来实验Docker和Kubernetes。 为此,请继续阅读以了解如何使用Docker容器化您的应用程序。

第2步-对您的Go应用进行Docker化 (Step 2 — Dockerizing Your Go Application)

In its current state, the Go application you just created is only running on your development server. In this step, you’ll make this new application portable by containerizing it with Docker. This will allow it to run on any machine that supports Docker containers. You will build a Docker image and push it to a central public repository on Docker Hub. This way, your Kubernetes cluster can pull the image back down and deploy it as a container within the cluster.

在当前状态下,您刚创建的Go应用程序仅在开发服务器上运行。 在此步骤中,您将通过使用Docker对其进行容器化来使此新应用程序可移植。 这将使其能够在支持Docker容器的任何机器上运行。 您将构建一个Docker映像并将其推送到Docker Hub上的中央公共存储库。 这样,您的Kubernetes群集可以拉回映像并将其部署为群集内的容器。

The first step towards containerizing your application is to create a special script called a Dockerfile. A Dockerfile typically contains a list of instructions and arguments that run in sequential order so as to automatically perform certain actions on a base image or create a new one.

容器化应用程序的第一步是创建一个名为Dockerfile的特殊脚本。 Dockerfile通常包含按顺序运行的指令和参数的列表,以便自动在基本映像上执行某些操作或创建一个新映像。

Note: In this step, you will configure a simple Docker container that will build and run your Go application in a single stage. If, in the future, you want to reduce the size of the container where your Go applications will run in production, you may want to look into mutli-stage builds.

注意:在此步骤中,您将配置一个简单的Docker容器,该容器将在一个阶段中构建和运行Go应用程序。 如果将来您想减小Go应用程序将在生产环境中运行的容器的大小,则可能需要研究多阶段构建

Create a new file named Dockerfile:

创建一个名为Dockerfile的新文件:

  • nano Dockerfile

    纳米Dockerfile

At the top of the file, specify the base image needed for the Go app:

在文件顶部,指定Go应用所需的基本图像:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9

Then create an app directory within the container that will hold the application’s source files:

然后在容器中创建一个app目录,其中将包含应用程序的源文件:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9
RUN mkdir /app

Below that, add the following line which copies everything in the root directory into the app directory:

在其下,添加以下行,它将root目录中的所有内容复制到app目录中:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9
RUN mkdir /app
ADD . /app

Next, add the following line which changes the working directory to app, meaning that all the following commands in this Dockerfile will be run from that location:

接下来,添加以下行,将工作目录更改为app ,这意味着将从该位置运行此Dockerfile中的以下所有命令:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9
RUN mkdir /app
ADD . /app
WORKDIR /app

Add a line instructing Docker to run the go build -o main command, which compiles the binary executable of the Go app:

添加一行指令Docker运行go build -o main命令,该命令将编译Go应用程序的二进制可执行文件:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN go build -o main .

Then add the final line, which will run the binary executable:

然后添加最后一行,它将运行二进制可执行文件:

go-app/Dockerfile
go-app / Dockerfile
FROM golang:1.12.0-alpine3.9
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN go build -o main .
CMD ["/app/main"]

Save and close the file after adding these lines.

添加这些行后,保存并关闭文件。

Now that you have this Dockerfile in the root of your project, you can create a Docker image based off of it using the following docker build command. This command includes the -t flag which, when passed the value go-web-app, will name the Docker image go-web-app and tag it.

既然您已经在项目的根目录中拥有了该Dockerfile ,则可以使用以下docker build命令基于该Dockerfile创建一个Docker映像。 此命令包括-t标志,当传递值go-web-app ,它将命名Docker映像go-web-app并对其进行标记

Note: In Docker, tags allow you to convey information specific to a given image, such as its version number. The following command doesn’t provide a specific tag, so Docker will tag the image with its default tag: latest. If you want to give an image a custom tag, you would append the image name with a colon and the tag of your choice, like so:

注意 :在Docker中,标签允许您传达特定于给定映像的信息,例如其版本号。 以下命令未提供特定标签,因此Docker将使用其默认标签( latest来标记映像。 如果要为图像提供自定义标签,则可以在图像名称后附加一个冒号和您选择的标签,如下所示:

  • docker build -t sammy/image_name:tag_name .

    docker build -t sammy / image_name : tag_name 。

Tagging an image like this can give you greater control over your images. For example, you could deploy an image tagged v1.1 to production, but deploy another tagged v1.2 to your pre-production or testing environment.

像这样标记图像可以使您更好地控制图像。 例如,您可以将标记为v1.1的映像部署到生产中,而将另一个标记为v1.2的映像部署到生产前或测试环境中。

The final argument you’ll pass is the path: .. This specifies that you wish to build the Docker image from the contents of the current working directory. Also, be sure to update sammy to your Docker Hub username:

您将传递的最后一个参数是path . 。 这指定您希望从当前工作目录的内容构建Docker映像。 另外,请确保将sammy更新为您的Docker Hub用户名:

  • docker build -t sammy/go-web-app .

    docker build -t sammy / go-web-app。

This build command will read all of the lines in your Dockerfile, execute them in order, and then cache them, allowing future builds to run much faster:

此构建命令将读取Dockerfile所有行,按顺序执行它们,然后对其进行缓存,从而使以后的构建运行得更快:


   
   
Output
. . . Successfully built 521679ff78e5 Successfully tagged go-web-app:latest

Once this command finishes building it, you will be able to see your image when you run the docker images command like so:

一旦此命令完成构建,您将可以在运行docker images命令时看到您的图像,如下所示:

  • docker images

    码头工人图像

   
   
Output
REPOSITORY TAG IMAGE ID CREATED SIZE sammy/go-web-app latest 4ee6cf7a8ab4 3 seconds ago 355MB

Next, use the following command create and start a container based on the image you just built. This command includes the -it flag, which specifies that the container will run in interactive mode. It also has the -p flag which maps the port on which the Go application is running on your development machine — port 3000 — to port 3000 in your Docker container:

接下来,使用以下命令根据刚构建的映像创建并启动容器。 此命令包括-it标志,该标志指定容器将以交互方式运行。 它还具有-p标志,该标志将您的开发机器上运行Go应用程序的端口(端口3000映射到Docker容器中的端口3000

  • docker run -it -p 3000:3000 sammy/go-web-app

    码头工人运行-it -p 3000:3000 sammy / go-web-app


   
   
Output
Go Web App Started on Port 3000

If there is nothing else running on that port, you’ll be able to see the application in action by opening up a browser and navigating to the following URL:

如果该端口上没有其他任何运行,则可以通过打开浏览器并导航到以下URL来查看正在运行的应用程序:

http://your_server_ip:3000

Note: If you’re following this tutorial from your local machine instead of a server, visit the application by instead going to the following URL:

注意:如果您是从本地计算机而不是服务器上学习本教程,请访问以下URL来访问该应用程序:

http://localhost:3000

After checking that the application works as expected in your browser, stop it by pressing CTRL + C in your terminal.

检查应用程序在浏览器中是否可以正常运行后,请在终端中按CTRL + C停止它。

When you deploy your containerized application to your Kubernetes cluster, you’ll need to be able to pull the image from a centralized location. To that end, you can push your newly created image to your Docker Hub image repository.

在将容器化的应用程序部署到Kubernetes集群时,您将需要能够从集中位置提取映像。 为此,您可以将新创建​​的映像推送到Docker Hub映像存储库。

Run the following command to log in to Docker Hub from your terminal:

运行以下命令从您的终端登录Docker Hub:

  • docker login

    码头工人登录

This will prompt you for your Docker Hub username and password. After entering them correctly, you will see Login Succeeded in the command’s output.

这将提示您输入Docker Hub用户名和密码。 正确输入后,您将在命令的输出中看到“ Login Succeeded

After logging in, push your new image up to Docker Hub using the docker push command, like so:

登录后,使用docker push命令将新映像推送到Docker Hub,如下所示:

  • docker push sammy/go-web-app

    码头工人推萨米 / go-web-app

Once this command has successfully completed, you will be able to open up your Docker Hub account and see your Docker image there.

成功完成此命令后,您将可以打开Docker Hub帐户并在其中查看Docker映像。

Now that you’ve pushed your image to a central location, you’re ready to deploy it to your Kubernetes cluster. First, though, we will walk through a brief process that will make it much less tedious to run kubectl commands.

既然已经将映像推送到一个中央位置,就可以将其部署到Kubernetes集群了。 不过,首先,我们将通过一个简短的过程,使运行kubectl命令的工作变得不那么繁琐。

第3步—改进kubectl可用性 (Step 3 — Improving Usability for kubectl)

By this point, you’ve created a functioning Go application and containerized it with Docker. However, the application still isn’t publicly accessible. To resolve this, you will deploy your new Docker image to your Kubernetes cluster using the kubectl command line tool. Before doing this, though, let’s make a small change to the Kubernetes configuration file that will help to make running kubectl commands less laborious.

至此,您已经创建了一个正常运行的Go应用程序,并使用Docker对其进行了容器化。 但是,该应用程序仍无法公开访问。 为了解决这个问题,您将使用kubectl命令行工具将新的Docker映像部署到Kubernetes集群。 不过,在执行此操作之前,让我们对Kubernetes配置文件进行一些小的更改,这将有助于减少运行kubectl命令的kubectl

By default, when you run commands with the kubectl command-line tool, you have to specify the path of the cluster configuration file using the --kubeconfig flag. However, if your configuration file is named config and is stored in a directory named ~/.kube, kubectl will know where to look for the configuration file and will be able pick it up without the --kubeconfig flag pointing to it.

默认情况下,当使用kubectl命令行工具运行命令时,必须使用--kubeconfig标志指定集群配置文件的路径。 但是,如果您的配置文件名为config并存储在名为~/.kube的目录中,则kubectl将知道在何处查找配置文件,并且无需--kubeconfig标志指向即可获取该文件。

To that end, if you haven’t already done so, create a new directory called ~/.kube:

为此,如果您尚未这样做,请创建一个名为~/.kube的新目录:

  • mkdir ~/.kube

    mkdir〜/ .kube

Then move your cluster configuration file to this directory, and rename it config in the process:

然后将集群配置文件移动到此目录,并在此过程中将其重命名为config

  • mv clusterconfig.yaml ~/.kube/config

    mv clusterconfig .yaml〜/ .kube / config

Moving forward, you won’t need to specify the location of your cluster’s configuration file when you run kubectl, as the command will be able to find it now that it’s in the default location. Test out this behavior by running the following get nodes command:

继续前进,在运行kubectl时,您无需指定集群配置文件的位置,因为该命令现在可以在默认位置找到它了。 通过运行以下get nodes命令来测试此行为:

  • kubectl get nodes

    kubectl获取节点

This will display all of the nodes that reside within your Kubernetes cluster. In the context of Kubernetes, a node is a server or a worker machine on which one or more pods can be deployed:

这将显示Kubernetes集群中的所有节点 。 在Kubernetes的上下文中,节点是可以在其上部署一个或多个Pod的服务器或工作机:


   
   
Output
NAME STATUS ROLES AGE VERSION k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfd Ready <none> 1m v1.13.5 k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfi Ready <none> 1m v1.13.5 k8s-1-13-5-do-0-nyc1-1554148094743-1-7lfv Ready <none> 1m v1.13.5

With that, you’re ready to move on and deploy your application to your Kubernetes cluster. You will do this by creating two Kubernetes objects: one that will deploy the application to some pods in your cluster and another that will create a load balancer, providing an access point to your application.

这样,您就可以继续并将应用程序部署到Kubernetes集群。 您将通过创建两个Kubernetes对象来做到这一点:一个将应用程序部署到集群中的某些Pod,另一个将创建负载均衡器,为您的应用程序提供访问点。

步骤4 —创建部署 (Step 4 — Creating a Deployment)

RESTful resources make up all the persistent entities wihtin a Kubernetes system, and in this context they’re commonly referred to as Kubernetes objects. It’s helpful to think of Kubernetes objects as the work orders you submit to Kubernetes: you list what resources you need and how they should work, and then Kubernetes will constantly work to ensure that they exist in your cluster.

RESTful资源构成了Kubernetes系统中的所有持久性实体,在这种情况下,它们通常被称为Kubernetes对象 。 将Kubernetes对象视为提交给Kubernetes的工作订单会很有帮助:您列出所需的资源以及它们应如何工作,然后Kubernetes将不断工作以确保它们存在于您的集群中。

One kind of Kubernetes object, known as a deployment, is a set of identical, indistinguishable pods. In Kubernetes, a pod is a grouping of one or more containers which are able to communicate over the same shared network and interact with the same shared storage. A deployment runs more than one replica of the parent application at a time and automatically replaces any instances that fail, ensuring that your application is always available to serve user requests.

一种Kubernetes对象(称为部署 )是一组相同的,无法区分的Pod。 在Kubernetes中, 吊舱是一个或多个容器的组合,这些容器能够通过同一共享网络进行通信并与同一共享存储进行交互。 部署一次运行多个父应用程序的副本,并自动替换任何失败的实例,以确保您的应用程序始终可用于满足用户请求。

In this step, you’ll create a Kubernetes object description file, also known as a manifest, for a deployment. This manifest will contain all of the configuration details needed to deploy your Go app to your cluster.

在此步骤中,您将为部署创建一个Kubernetes对象描述文件,也称为清单 。 此清单将包含将Go应用程序部署到集群所需的所有配置详细信息。

Begin by creating a deployment manifest in the root directory of your project: go-app/. For small projects such as this one, keeping them in the root directory minimizes the complexity. For larger projects, however, it may be beneficial to store your manifests in a separate subdirectory so as to keep everything organized.

首先在项目的根目录go-app/创建部署清单。 对于像这样的小型项目,将它们保留在根目录中可以最大程度地减少复杂性。 但是,对于较大的项目,将清单存储在单独的子目录中以使所有内容井井有条可能是有益的。

Create a new file called deployment.yml:

创建一个名为deployment.yml的新文件:

  • nano deployment.yml

    纳米部署

Different versions of the Kubernetes API contain different object definitions, so at the top of this file you must define the apiVersion you’re using to create this object. For the purpose of this tutorial, you will be using the apps/v1 grouping as it contains many of the core Kubernetes object definitions that you’ll need in order to create a deployment. Add a field below apiVersion describing the kind of Kubernetes object you’re creating. In this case, you’re creating a Deployment:

不同版本的Kubernetes API包含不同的对象定义,因此,在此文件的顶部,您必须定义用于创建此对象的apiVersion 。 就本教程而言,您将使用apps/v1分组,因为它包含创建部署所需的许多核心Kubernetes对象定义。 在apiVersion下面添加一个字段,描述您正在创建的Kubernetes对象的kind 。 在这种情况下,您要创建一个Deployment

go-app/deployment.yml
go-app / deployment.yml
---
apiVersion: apps/v1
kind: Deployment

Then define the metadata for your deployment. A metadata field is required for every Kubernetes object as it contains information such as the unique name of the object. This name is useful as it allows you to distinguish different deployments from one another and identify them using names that are human-readable:

然后为您的部署定义metadata 。 每个Kubernetes对象都需要一个metadata字段,因为它包含诸如对象的唯一name之类的信息。 此name很有用,因为它使您能够区分不同的部署,并使用易于理解的名称来标识它们:

go-app/deployment.yml
go-app / deployment.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: go-web-app

Next, you’ll build out the spec block of your deployment.yml. A spec field is a requirement for every Kubernetes object, but its precise format differs for each type of object. In the case of a deployment, it can contain information such as the number of replicas of you want to run. In Kubernetes, a replica is the number of pods you want to run in your cluster. Here, set the number of replicas to 5:

接下来,你将构建出spec你的块deployment.yml 。 每个Kubernetes对象都必须有一个spec字段,但是每种对象的精确格式都不同。 在部署的情况下,它可以包含诸如您要运行的副本数之类的信息。 在Kubernetes中,副本是您要在集群中运行的Pod数量。 在这里,将replicas数设置为5

go-app/deployment.yml
go-app / deployment.yml
. . .
metadata:
    name: go-web-app
spec:
  replicas: 5

Next, create a selector block nested under the spec block. This will serve as a label selector for your pods. Kubernetes uses label selectors to define how the deployment finds the pods which it must manage.

接下来,创建一个嵌套在spec块下的selector块。 这将用作您的广告连播的标签选择器 。 Kubernetes使用标签选择器来定义部署如何查找其必须管理的Pod。

Within this selector block, define matchLabels and add the name label. Essentially, the matchLabels field tells Kubernetes what pods the deployment applies to. In this example, the deployment will apply to any pods with the name go-web-app:

在此selector块中,定义matchLabels并添加name标签。 本质上, matchLabels字段告诉Kubernetes部署适用于哪些容器。 在此示例中,部署将应用于名称为go-web-app所有Pod:

go-app/deployment.yml
go-app / deployment.yml
. . .
spec:
  replicas: 5
  selector:
    matchLabels:
      name: go-web-app

After this, add a template block. Every deployment creates a set of pods using the labels specified in a template block. The first subfield in this block is metadata which contains the labels that will be applied to all of the pods in this deployment. These labels are key/value pairs that are used as identifying attributes of Kubernetes objects. When you define your service later on, you can specify that you want all the pods with this name label to be grouped under that service. Set this name label to go-web-app:

之后,添加一个template板块。 每个部署创建一组使用指定的标签荚的template块。 此块中的第一个子字段是metadata ,其中包含将应用于此部署中所有吊舱的labels 。 这些标签是键/值对,用作标识Kubernetes对象的属性。 稍后定义服务时,可以指定要将具有此name标签的所有Pod分组到该服务下。 将此name标签设置为go-web-app

go-app/deployment.yml
go-app / deployment.yml
. . .
spec:
  replicas: 5
  selector:
    matchLabels:
      name: go-web-app
  template:
    metadata:
      labels:
        name: go-web-app

The second part of this template block is the spec block. This is different from the spec block you added previously, as this one applies only to the pods created by the template block, rather than the whole deployment.

这第二部分template块是spec块。 这与您之前添加的spec模块不同,因为该模块仅适用于template模块创建的吊舱,而不适用于整个部署。

Within this spec block, add a containers field and once again define a name attribute. This name field defines the name of any containers created by this particular deployment. Below that, define the image you want to pull down and deploy. Be sure to change sammy to your own Docker Hub username:

在此spec块中,添加一个containers字段,然后再次定义name属性。 此name字段定义此特定部署创建的任何容器的名称。 在此之下,定义要下拉并部署的image 。 确保将sammy更改为您自己的Docker Hub用户名:

go-app/deployment.yml
go-app / deployment.yml
. . .
  template:
    metadata:
      labels:
        name: go-web-app
    spec:
      containers:
      - name: application
        image: sammy/go-web-app

Following that, add an imagePullPolicy field set to IfNotPresent which will direct the deployment to only pull an image if it has not already done so before. Then, lastly, add a ports block. There, define the containerPort which should match the port number that your Go application listens on. In this case, the port number is 3000:

之后,将设置为IfNotPresentimagePullPolicy字段添加到IfNotPresent ,该字段将指示部署仅拉取之前尚未执行过操作的图像。 然后,最后添加ports块。 在此定义containerPort ,该containerPort端口应与Go应用程序侦听的端口号匹配。 在这种情况下,端口号是3000

go-app/deployment.yml
go-app / deployment.yml
. . .
    spec:
      containers:
      - name: application
        image: sammy/go-web-app
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 3000

The full version of your deployment.yml will look like this:

您的deployment.yml的完整版本如下所示:

go-app/deployment.yml
go-app / deployment.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-web-app
spec:
  replicas: 5
  selector:
    matchLabels:
      name: go-web-app
  template:
    metadata:
      labels:
        name: go-web-app
    spec:
      containers:
      - name: application
        image: sammy/go-web-app
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 3000

Save and close the file.

保存并关闭文件。

Next, apply your new deployment with the following command:

接下来,使用以下命令应用新部署:

  • kubectl apply -f deployment.yml

    kubectl套用-f deployment.yml

Note: For more information on all of the configuration available to you for deployments, please check out the official Kubernetes documentation here: Kubernetes Deployments

注意:有关部署可用的所有配置的更多信息,请在此处查看Kubernetes官方文档: Kubernetes部署

In the next step, you’ll create another kind of Kubernetes object which will manage how you access the pods that exist in your new deployment. This service will create a load balancer which will then expose a single IP address, and requests to this IP address will be distributed to the replicas in your deployment. This service will also handle port forwarding rules so that you can access your application over HTTP.

在下一步中,您将创建另一种Kubernetes对象,该对象将管理如何访问新部署中存在的Pod。 该服务将创建一个负载平衡器,该负载平衡器然后将公开一个IP地址,并且对该IP地址的请求将分发到您部署中的副本。 该服务还将处理端口转发规则,以便您可以通过HTTP访问应用程序。

第5步-创建服务 (Step 5 — Creating a Service)

Now that you have a successful Kubernetes deployment, you’re ready to expose your application to the outside world. In order to do this, you’ll need to define another kind of Kubernetes object: a service. This service will expose the same port on all of your cluster’s nodes. Your nodes will then forward any incoming traffic on that port to the pods running your application.

既然您已经成功部署了Kubernetes,则可以将应用程序暴露给外界了。 为此,您需要定义另一种Kubernetes对象: service 。 该服务将在群集的所有节点上公开相同的端口。 然后,您的节点会将该端口上的所有传入流量转发到运行您的应用程序的Pod。

Note: For clarity, we will define this service object in a separate file. However, it is possible to group multiple resource manifests in the same YAML file, as long as they’re separated by ---. See this page from the Kubernetes documentation for more details.

注意:为清楚起见,我们将在单独的文件中定义此服务对象。 但是,可以将多个资源清单组合在同一个YAML文件中,只要它们用---分隔即可。 有关更多详细信息,请参阅Kubernetes文档中的此页面

Create a new file called service.yml:

创建一个名为service.yml的新文件:

  • nano service.yml

    纳米服务

Start this file off by again defining the apiVersion and the kind fields in a similar fashion to your deployment.yml file. This time, point the apiVersion field to v1, the Kubernetes API commonly used for services:

通过以与deployment.yml文件类似的方式再次定义apiVersionkind字段来启动此文件。 这次,将apiVersion字段指向v1 ,即通常用于服务的Kubernetes API:

go-app/service.yml
go-app / service.yml
---
apiVersion: v1
kind: Service

Next, add the name of your service in a metadata block as you did in deployment.yml. This could be anything you like, but for clarity we will call it go-web-service:

接下来,像在deployment.yml一样,在metadata块中添加服务的名称。 这可以是您喜欢的任何东西,但为清楚起见,我们将其称为go-web-service

go-app/service.yml
go-app / service.yml
---
apiVersion: v1
kind: Service
metadata:
  name: go-web-service

Next, create a spec block. This spec block will be different than the one included in your deployment, and it will contain the type of this service, as well as the port forwarding configuration and the selector.

接下来,创建一个spec块。 此spec块与您的部署中包含的块不同,它将包含此服务的type以及端口转发配置和selector

Add a field defining this service’s type and set it to LoadBalancer. This will automatically provision a load balancer that will act as the main entry point to your application.

添加一个定义此服务type的字段,并将其设置为LoadBalancer 。 这将自动设置一个负载平衡器,该负载平衡器将成为您应用程序的主要入口点。

Warning: The method for creating a load balancer outlined in this step will only work for Kubernetes clusters provisioned from cloud providers that also support external load balancers. Additionally, be advised that provisioning a load balancer from a cloud provider will incur additional costs. If this is a concern for you, you may want to look into exposing an external IP address using an Ingress.

警告:本步骤概述的创建负载均衡器的方法仅适用于从也支持外部负载均衡器的云提供商调配的Kubernetes群集。 此外,请注意,从云提供商处配置负载平衡器将产生额外费用。 如果您对此感到担心,则可以考虑使用Ingress公开外部IP地址。

go-app/service.yml
go-app / service.yml
---
apiVersion: v1
kind: Service
metadata:
  name: go-web-service
spec:
  type: LoadBalancer

Then add a ports block where you’ll define how you want your apps to be accessed. Nested within this block, add the following fields:

然后添加ports块,您将在其中定义希望访问应用程序的方式。 嵌套在此块中,添加以下字段:

  • name, pointing to http

    name ,指向http

  • port, pointing to port 80

    port ,指向端口80

  • targetPort, pointing to port 3000

    targetPort ,指向端口3000

This will take incoming HTTP requests on port 80 and forward them to the targetPort of 3000. This targetPort is the same port on which your Go application is running:

这将在端口80上接收传入的HTTP请求,并将它们转发到3000targetPort 。 此targetPort是您的Go应用程序运行所在的端口:

go-app/service.yml
go-app / service.yml
---
apiVersion: v1
kind: Service
metadata:
  name: go-web-service
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 3000

Lastly, add a selector block as you did in the deployments.yml file. This selector block is important, as it maps any deployed pods named go-web-app to this service:

最后,像在deployments.yml文件中一样添加selector块。 该selector块很重要,因为它将所有名为go-web-app部署Pod映射到该服务:

go-app/service.yml
go-app / service.yml
---
apiVersion: v1
kind: Service
metadata:
  name: go-web-service
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 3000
  selector:
    name: go-web-app

After adding these lines, save and close the file. Following that, apply this service to your Kubernetes cluster by once again using the kubectl apply command like so:

添加这些行之后,保存并关闭文件。 之后,再次使用kubectl apply命令将此服务应用于您的Kubernetes集群,如下所示:

  • kubectl apply -f service.yml

    kubectl应用-f service.yml

This command will apply the new Kubernetes service as well as create a load balancer. This load balancer will serve as the public-facing entry point to your application running within the cluster.

该命令将应用新的Kubernetes服务以及创建负载均衡器。 该负载平衡器将充当集群中运行的应用程序的面向公众的入口点。

To view the application, you will need the new load balancer’s IP address. Find it by running the following command:

要查看该应用程序,您将需要新的负载平衡器的IP地址。 通过运行以下命令找到它:

  • kubectl get services

    kubectl获得服务

   
   
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE go-web-service LoadBalancer 10.245.107.189 203.0.113.20 80:30533/TCP 10m kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 3h4m

You may have more than one service running, but find the one labeled go-web-service. Find the EXTERNAL-IP column and copy the IP address associated with the go-web-service. In this example output, this IP address is 203.0.113.20. Then, paste the IP address into the URL bar of your browser to the view the application running on your Kubernetes cluster.

您可能正在运行多个服务,但是找到了一个标记为go-web-service 。 找到EXTERNAL-IP列,然后复制与go-web-service关联的IP地址。 在此示例输出中,此IP地址为203.0.113.20 。 然后,将IP地址粘贴到浏览器的URL栏中,以查看在Kubernetes集群上运行的应用程序。

Note: When Kubernetes creates a load balancer in this manner, it does so asynchronously. Consequently, the kubectl get services command’s output may show the EXTERNAL-IP address of the LoadBalancer remaining in a <pending> state for some time after running the kubectl apply command. If this the case, wait a few minutes and try re-running the command to ensure that the load balancer was created and is functioning as expected.

注意:当Kubernetes以这种方式创建负载均衡器时,它是异步进行的。 因此, kubectl get services命令的输出可能显示在运行kubectl apply命令后一段时间内, LoadBalancerEXTERNAL-IP地址保持<pending>状态。 在这种情况下,请等待几分钟,然后尝试重新运行该命令,以确保已创建负载均衡器并按预期运行。

The load balancer will take in the request on port 80 and forward it to one of the pods running within your cluster.

负载平衡器将在端口80上接收请求,并将其转发到集群中运行的Pod之一。

With that, you’ve created a Kubernetes service coupled with a load balancer, giving you a single, stable entry point to application.

这样,您就创建了一个Kubernetes服务以及一个负载均衡器,从而为您提供了一个稳定的应用程序入口点。

结论 (Conclusion)

In this tutorial, you’ve built Go application, containerized it with Docker, and then deployed it to a Kubernetes cluster. You then created a load balancer that provides a resilient entry point to this application, ensuring that it will remain highly available even if one of the nodes in your cluster fails. You can use this tutorial to deploy your own Go application to a Kubernetes cluster, or continue learning other Kubernetes and Docker concepts with the sample application you created in Step 1.

在本教程中,您已经构建了Go应用程序,并使用Docker对其进行了容器化,然后将其部署到Kubernetes集群中。 然后,您创建了一个负载平衡器,为该应用程序提供了一个弹性的入口点,以确保即使集群中的一个节点发生故障,它也将保持高可用性。 您可以使用本教程将自己的Go应用程序部署到Kubernetes集群,或者继续使用在步骤1中创建的示例应用程序学习其他Kubernetes和Docker概念。

Moving forward, you could map your load balancer’s IP address to a domain name that you control so that you can access the application through a human-readable web address rather than the load balancer IP. Additionally, the following Kubernetes tutorials may be of interest to you:

展望未来,您可以将负载均衡器的IP地址映射到您控制的域名,以便可以通过人类可读的Web地址而不是负载均衡器IP访问应用程序。 此外,您可能会对以下Kubernetes教程感兴趣:

Finally, if you’d like to learn more about Go, we encourage you to check out our series on How To Code in Go.

最后,如果您想了解有关Go的更多信息,我们建议您阅读有关如何在Go中进行编码的系列文章

翻译自: https://www.digitalocean.com/community/tutorials/how-to-deploy-resilient-go-app-digitalocean-kubernetes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值