如何使用Okteto在Kubernetes上开发应用程序
作为 Write for DOnations 计划的一部分,作者选择了 Girls Who Code 来接受捐赠。
介绍
Okteto CLI 是一个开源项目,为在 Kubernetes 上运行的应用程序提供本地开发体验。 有了它,您可以在本地 IDE 上编写代码,一旦保存文件,更改就可以推送到您的 Kubernetes 集群,您的应用程序将立即更新。 整个过程无需构建 Docker 映像或应用 Kubernetes 清单即可完成,这可能需要相当长的时间。
在本教程中,您将在开发 Kubernetes 原生应用程序时使用 Okteto 来提高工作效率。 首先,您将创建一个 Kubernetes 集群并使用它来运行一个标准的“Hello World”应用程序。 然后,您将使用 Okteto 开发和自动更新您的应用程序,而无需在本地安装任何东西。
先决条件
在开始本教程之前,您需要以下内容:
- 一个 Kubernetes 1.12+ 集群。 在本教程中,设置将使用具有三个节点的 DigitalOcean Kubernetes 集群,但您可以使用另一种方法 自由创建 集群。
kubectl
和doctl
已安装并配置 以与您的集群通信。- Docker Hub 账号
- Docker 在你的本地机器上运行。
第 1 步 — 创建 Hello World 应用程序
“Hello World”程序是 Web 开发中由来已久的传统。 在这种情况下,它是一个简单的 Web 服务,它对每个请求都响应“Hello World”。 现在您已经创建了 Kubernetes 集群,让我们在 Golang 中创建一个“Hello World”应用程序以及您将用于在 Kubernetes 上部署它的清单。
首先更改到您的主目录:
cd ~
现在创建一个名为 hello_world
的新目录并在其中移动:
mkdir hello_world cd hello_world
使用您喜欢的 IDE 或文本编辑器创建并打开一个名为 main.go
的新文件:
nano main.go
main.go
将是一个返回消息 Hello world!
的 Golang Web 服务器。 因此,让我们使用以下代码:
main.go
package main import ( "fmt" "net/http" ) func main() { fmt.Println("Starting hello-world server...") http.HandleFunc("/", helloServer) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } func helloServer(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world!") }
main.go
中的代码执行以下操作:
- Go 源文件中的第一条语句必须是
package
名称。 可执行命令必须始终使用package main
。 import
部分指示代码所依赖的包。 在这种情况下,它使用fmt
进行字符串操作,并将net/http
用于 HTTP 服务器。main
函数是二进制文件的入口点。http.HandleFunc
方法用于配置服务器在收到对/
路径的请求时调用helloServer
函数。http.ListenAndServe
启动一个 HTTP 服务器,它侦听端口8080
上的所有网络接口。helloServer
函数包含您的请求处理程序的逻辑。 在这种情况下,它将写入Hello world!
作为对请求的响应。
您需要创建一个 Docker 映像并将其推送到您的 Docker 注册表,以便 Kubernetes 可以拉取它,然后运行应用程序。
使用您喜欢的 IDE 或文本编辑器打开一个名为 Dockerfile
的新文件:
nano Dockerfile
Dockerfile
将包含构建应用程序的 Docker 容器所需的命令。 让我们使用以下代码:
Dockerfile
FROM golang:alpine as builder RUN apk --update --no-cache add bash WORKDIR /app ADD . . RUN go build -o app FROM alpine as prod WORKDIR /app COPY --from=builder /app/app /app/app EXPOSE 8080 CMD ["./app"]
Dockerfile
包含两个阶段,builder
和 prod
:
builder
阶段包含 Go 构建工具。 它负责复制文件并构建 Go 二进制文件。prod
阶段是最终图像。 它将只包含一个精简的操作系统和应用程序二进制文件。
这是一个很好的做法。 它使您的生产容器更小更安全,因为它们只包含您的应用程序以及运行它所需的内容。
构建容器镜像(将 your_DockerHub_username
替换为您的 Docker Hub 用户名):
docker build -t your_DockerHub_username/hello-world:latest
现在将其推送到 Docker Hub:
docker push your_DockerHub_username/hello-world:latest
接下来,为 Kubernetes 清单创建一个新文件夹:
mkdir k8s
当你使用 Kubernetes 清单时,你告诉 Kubernetes 你希望你的应用程序如何运行。 这一次,您将创建一个 deployment 对象。 因此,使用您喜欢的 IDE 或文本编辑器创建一个新文件 deployment.yaml
:
nano k8s/deployment.yaml
以下内容描述了一个运行 okteto/hello-world:latest
Docker 镜像的 Kubernetes 部署对象。 将此内容添加到您的新文件中,但在您的情况下,将 image
标签后列出的 okteto
替换为 your_DockerHub_username
:
~/hello_world/k8s/deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: hello-world spec: selector: matchLabels: app: hello-world replicas: 1 template: metadata: labels: app: hello-world spec: containers: - name: hello-world image: your_DockerHub_username/hello-world:latest ports: - containerPort: 8080
部署清单包含三个主要部分:
metadata
定义部署的名称。replicas
定义了你想要运行的副本数。template
告诉 Kubernetes 部署什么,添加什么标签。 在这种情况下,单个容器,带有okteto/hello-world:latest
图像,侦听端口8080
,并带有app: hello-world
标签。 请注意,此标签与selector
部分中使用的标签相同。
您现在需要一种方法来访问您的应用程序。 您可以通过创建 service 对象在 Kubernetes 上公开应用程序。 让我们继续使用清单来做到这一点。 使用您喜欢的 IDE 或文本编辑器创建一个名为 service.yaml
的新文件:
nano k8s/service.yaml
以下内容描述了公开 hello-world
部署对象的服务,该对象在后台将使用 DigitalOcean 负载均衡器:
k8s/service.yaml
apiVersion: v1 kind: Service metadata: name: hello-world spec: type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 8080 name: http selector: app: hello-world
服务清单有四个主要部分:
metadata
告诉 Kubernetes 如何命名你的服务。type
告诉 Kubernetes 你想如何公开你的服务。 在这种情况下,它将通过数字海洋负载均衡器将其暴露在外部。ports
标签告诉 Kubernetes 您要公开哪些端口,以及如何将它们映射到您的部署。 在这种情况下,您将在外部公开端口80
并将其定向到部署中的端口8080
。selector
告诉 Kubernetes 如何引导流量。 在这种情况下,任何带有app: hello-world
标签的 pod 都会收到流量。
您现在已准备好在 Kubernetes 上部署“Hello World”应用程序。 我们接下来会这样做。
第 2 步 — 部署您的 Hello World 应用程序
在这一步中,您将在 Kubernetes 上部署您的“Hello World”应用程序,然后您将验证它是否正常工作。
首先在 Kubernetes 上部署您的应用程序:
kubectl apply -f k8s
您将看到以下输出:
Outputdeployment.apps "hello-world" created service "hello-world" created
大约一分钟左右后,您将能够检索应用程序的 IP。 使用此 kubectl
命令检查您的服务:
kubectl get service hello-world
您将看到这样的输出,其中列出了您的 Kubernetes 服务对象。 在 EXTERNAL-IP
列中记下您的应用程序的 IP:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-world ClusterIP your_cluster_ip your_external_ip 8080/TCP 37s
打开您的浏览器并转到为您的“Hello World”应用程序列出的 your_external_ip
。 在继续下一步之前,请确认您的应用程序已启动并正在运行。
直到现在,您都遵循了使用 Kubernetes 开发应用程序的相当传统的途径。 展望未来,每当您想更改应用程序中的代码时,您都必须构建并推送一个新的 Docker 镜像,然后从 Kubernetes 中拉取该镜像。 这个过程可能需要相当长的时间。 Okteto 旨在简化这种开发内部循环。 让我们看一下 Okteto CLI,看看它如何提供帮助。
第 3 步 — 安装 Okteto CLI
现在,您将通过安装 Okteto CLI 来提高 Kubernetes 开发效率。 Okteto 命令行界面 是一个开源项目,可让您将应用程序代码更改同步到在 Kubernetes 上运行的应用程序。 您可以继续使用您最喜欢的 IDE、调试器或编译器,而无需像在前面的步骤中那样提交、构建、推送或重新部署容器来测试您的应用程序。
要在 macOS 或 Linux 机器上安装 Okteto CLI,请运行以下命令:
curl https://get.okteto.com -sSfL | sh
让我们仔细看看这个命令:
curl
命令用于将数据传输到服务器或从服务器传输数据。-s
标志禁止任何输出。-S
标志显示错误。-f
标志会导致请求因 HTTP 错误而失败。-L
标志使请求遵循重定向。|
运算符将此输出通过管道传递给sh
命令,该命令将在本地计算机上下载并安装最新的okteto
二进制文件。
如果您运行的是 Windows,您也可以通过网络浏览器 下载文件 并手动将其添加到您的 $PATH
。
安装 Okteto CLI 后,您就可以将“Hello World”应用程序置于开发模式。
第 4 步 — 将您的 Hello World 应用程序置于开发模式
Okteto CLI 旨在将 Kubernetes 集群上运行的应用程序与您机器中的代码交换。 为此,Okteto 使用 Okteto manifest 文件提供的信息。 此文件声明将与您的本地代码交换的 Kubernetes 部署对象。
使用您喜欢的 IDE 或文本编辑器创建一个名为 okteto.yaml
的新文件:
nano okteto.yaml
让我们编写一个基本清单,您可以在其中定义部署对象名称、要使用的 Docker 基础映像和一个 shell。 我们稍后将返回此信息。 使用以下示例内容文件:
okteto.yaml
name: hello-world image: okteto/golang:1 workdir: /app command: ["bash"]
准备通过运行以下命令将您的应用程序置于开发模式:
okteto up
Output ✓ Development environment activated ✓ Files synchronized Namespace: default Name: hello-world Welcome to your development environment. Happy coding! default:hello-world /app>
okteto up
命令将“Hello World”应用程序交换到开发环境中,这意味着:
- Hello World 应用程序容器使用 docker 映像
okteto/golang:1
进行更新。 此映像包含构建、测试、调试和运行“Hello World”应用程序所需的开发工具。 - 创建 文件同步服务 以使您的更改在本地文件系统和应用程序 pod 之间保持最新。
- 远程 shell 在您的开发环境中启动。 现在您可以像在本地机器上一样构建、测试和运行您的应用程序。
- 无论您在远程 shell 中运行什么进程,都将获得与原始“Hello World”应用程序 pod 相同的传入流量、相同的环境变量、卷或机密。 这反过来又为您提供了一个高度逼真的、类似生产的开发环境。
在同一个控制台中,现在像往常一样运行应用程序(无需构建和推送 Docker 映像),如下所示:
go run main.go
OutputStarting hello-world server...
第一次运行应用程序时,Go 将下载你的依赖项并编译你的应用程序。 等待此过程完成并通过打开浏览器并刷新应用程序页面来测试您的应用程序,就像您之前所做的那样。
现在您已准备好开始直接在 Kubernetes 上进行开发。
第 5 步 — 直接在 Kubernetes 上开发
让我们开始对“Hello World”应用程序进行更改,然后看看这些更改如何反映在 Kubernetes 中。
使用您喜欢的 IDE 或文本编辑器打开 main.go
文件。 例如,打开一个单独的控制台并运行以下命令:
nano main.go
然后,将您的响应消息更改为 Hello world from DigitalOcean!
:
main.go
package main import ( "fmt" "net/http" ) func main() { fmt.Println("Starting hello-world server...") http.HandleFunc("/", helloServer) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } func helloServer(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world from DigitalOcean!") }
正是在这里,您的工作流程发生了变化。 Okteto 无需构建镜像和重新部署容器来更新“Hello World”应用程序,而是将您的更改同步到 Kubernetes 上的开发环境。
从您执行 okteto up
命令的控制台,按 CTRL + C
取消 go run main.go
的执行。 现在重新运行应用程序:
default:hello-world /app> go run main.go
OutputStarting hello-world server...
返回浏览器并重新加载“Hello World”应用程序的页面。
您的代码更改会立即应用到 Kubernetes,而且无需任何提交、构建或推送。
结论
Okteto 只需单击一个按钮,即可将您的 Kubernetes 集群转变为功能齐全的开发平台。 在本教程中,您安装并配置了 Okteto CLI 以尽可能快地在 Kubernetes 上直接迭代您的代码更改,就像您键入代码一样快。 现在您可以前往 Okteto 示例存储库 了解如何将 Okteto 与不同的编程语言和调试器一起使用。
此外,如果您与团队共享 Kubernetes 集群,请考虑让每个成员访问安全的 Kubernetes 命名空间,该命名空间配置为与在同一集群上工作的其他开发人员隔离。 DigitalOcean Kubernetes Marketplace 中的 Okteto App 也提供了这一强大功能。