开始吧
为了让 Web 应用程序在所有机器上可用,我们必须将其容器化,而容器化这个词比 docker 更好。
我创建了一个 Dockerfile 来运行该应用程序,但我使用了多阶段格式
原因很简单,如果我在单个阶段中创建图像,它将消耗更多的机器空间,而通过使用多阶段构建,我们可以通过分离构建和运行时环境来优化图像的最终大小,并减少攻击我们图像的表面以获得更好的安全性
具体方法如下
# Start with a base image FROM golang:1.22 as base WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN go build -o main . ####################################################### # Reduce the image size using multi-stage builds # We will use a distroless image to run the application FROM gcr.io/distroless/base # Copy the binary from the previous stage COPY --from=base /app/main . # Copy the static files from the previous stage COPY --from=base /app/static ./static # Expose the port on which the application will run EXPOSE 8080 # Command to run the application CMD ["./main"]
现在我们有了 dockerfile,让我们构建它并将其部署到 dockerhub
docker build -t pankaj892/webapp:v1 .
我们尝试检查应用程序是否在本地计算机上按预期运行
docker run -p 8080:8080 pankaj892-webapp:v1
让我们将其推送到 dockerhub
docker Push pankaj892/webapp:v1 .
您可以使用 mininkube/kind 在本地创建集群,也可以使用云上的任何一种托管解决方案。我将使用 AWS 的 Elastic Kubernetes Service(EKS)。
您可以使用控制台或命令行在 EKS 中启动集群。我将使用命令行
eksctl create cluster--instance-selector-vcpus=2 --instance-selector-memory=4 --name <name-of-cluster> --region <region-code>
这将仅选择具有 2 个 vCPU 和 4GB 内存的节点组的机器类型
我们可以一一部署所有资源,但随着规模的扩大,管理它们会很困难,这就是 Helm 的用武之地,它充当包管理器,使用图表来管理我们的所有资源
创建舵图
# Start with a base image FROM golang:1.22 as base WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN go build -o main . ####################################################### # Reduce the image size using multi-stage builds # We will use a distroless image to run the application FROM gcr.io/distroless/base # Copy the binary from the previous stage COPY --from=base /app/main . # Copy the static files from the previous stage COPY --from=base /app/static ./static # Expose the port on which the application will run EXPOSE 8080 # Command to run the application CMD ["./main"]
Helm 将创建供我们使用的文件,但我们的项目不需要其中的大部分文件。
创建以下文件并添加到helm目录
部署
eksctl create cluster--instance-selector-vcpus=2 --instance-selector-memory=4 --name <name-of-cluster> --region <region-code>
服务
helm create web-app
入口
# This is a sample deployment manifest file for a simple web application. apiVersion: apps/v1 kind: Deployment metadata: name: web-app labels: app: web-app spec: replicas: 1 selector: matchLabels: app: web-app template: metadata: labels: app: web-app spec: containers: - name: web-app image: {{ .Values.image.repository }}:{{ .Values.image.tag }} ports: - containerPort: 8080
将值文件更新为此
# Service for the application apiVersion: v1 kind: Service metadata: name: web-app labels: app: web-app spec: ports: - port: 80 targetPort: 8080 protocol: TCP selector: app: web-app type: ClusterIP
Helm 部分现已完成,让我们继续部署我们的 CI
Github Actions 允许我们根据仓库中的一些事件(如推、拉)自动构建应用程序。
让我们创建管道文件
工作流程文件存储在(.github/workflows/cicd.yml)
# Ingress resource for the application apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-app annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: web-app.local http: paths: - path: / pathType: Prefix backend: service: name: web-app port: number: 80
这个工作流程文件首先从 dockerfile 构建我们的镜像,然后将其推送到 dockerhub,然后在 helm 的 Charts.yaml 文件中更新镜像的标签。
我们将使用 argocd 作为我们的 Cd 管道,因为 argocd 将能够从我们的 git 存储库中获取更改并在应用程序中更新它们。
让我们在集群上安装 argocd
kubectl 创建命名空间 argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
要访问 argocd 服务器,我们需要将服务更改为负载均衡器类型
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
对于 Windows,这将是
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
如果它不起作用,只需通过 kubectl 编辑服务并将类型更改为 LoadBalancer 它应该可以工作
现在获取服务的IP
kubectl get svc argocd-server -n argocd
我们获得了 IP,但需要密码才能登录 argocd
kubectl 获取秘密 argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 --解码
此命令将获取密码并解码密码,因为密码以 Base64 格式编码
登录后点击“新建项目”>;添加您的项目名称>添加存储库,以便 argocd 可以同步存储库 argocd 将自动查找值文件并在单击提交后选择该文件
我们构建了管道,但我们如何访问我们的应用程序,您不能每次都从 EKS 中输入集群 URL 来访问它,我们需要为此使用入口
我正在使用来自 AWS 的 Nginx Ingress,以便我可以访问该应用程序
在我们的集群上部署入口
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.1/deploy/static/provider/aws/deploy.yaml
现在 Ingress 已部署,我们需要将来自 EKS 的集群 IP 添加到本地主机文件(对于 Linux,其为 /etc/hosts),对于 Windows,它位于 C:WindowsSystem32etchosts
# Start with a base image FROM golang:1.22 as base WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN go build -o main . ####################################################### # Reduce the image size using multi-stage builds # We will use a distroless image to run the application FROM gcr.io/distroless/base # Copy the binary from the previous stage COPY --from=base /app/main . # Copy the static files from the previous stage COPY --from=base /app/static ./static # Expose the port on which the application will run EXPOSE 8080 # Command to run the application CMD ["./main"]
现在我们可以在 web-app.local 上访问我们的应用程序
我们已经完成了所有步骤,让我们测试我们的应用程序
如您所见,顶部的 url 是我们在主机文件中定义的
我们已经运行了应用程序,让我们添加一些内容并提交到我们的存储库,以便 argocd 可以获取该更改并部署到应用程序
我对我的存储库进行了更改,这应该会触发管道
管道已启动,完成后让我们看看 argocd 是否接受该更改
是的,我们看到应用程序发生了变化,argocd 确实拾取了更改并将我们的应用程序与最新更改同步
如果你做到了这一步那么恭喜!!!
这个项目对我来说是一次很棒的学习经历,从在 AWS 上部署 Kubernetes 到创建管道和部署以及对其进行故障排除。这个项目帮助我为 Go 应用程序创建了一个端到端的 DevOps 管道,并且它可以根据需求进行扩展。我计划进行更多探索,例如使用 terraform 或 cloudformation 堆栈部署 eks clutser 并进行更多改进。
如果你遇到困难,可以参考这个仓库
请在评论中告诉我您构建此管道的体验如何。
以上是使用 Gitops 和 Kubernetes 在 Golang Web 应用程序上进行 DevOps 管道的详细内容。更多信息请关注PHP中文网其他相关文章!