全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2021-01-15_每天部署数千个容器实例,扩缩容复杂性该如何管理?

您的位置:首页 >> 新闻 >> 行业资讯

每天部署数千个容器实例,扩缩容复杂性该如何管理? 作者 | Anjana Fernando 译者 | 张健欣策划 | 田晓旭无论是大型软件公司还是小型软件公司,现在每天都要部署数千个容器实例,这种扩缩容的复杂性是他们必须要管理的。本文介绍了如何将 Kubernetes 纳入到现有的传统 CI/CD 管道中,并实现服务的高可用性,以及随时在生产环境中进行代码变更。 基于容器的微服务架构改变了开发和运维团队测试和部署现代应用程序 / 服务的方式。容器通过简化应用程序的扩缩容和部署来帮助公司实现现代化,但容器也创建了一个全新的基础设施生态系统,从而引入了新的挑战和更多的复杂性。 无论是大型软件公司还是小型软件公司,现在每天都要部署数千个容器实例,这种扩缩容的复杂性是他们必须要管理的。那么他们是怎么做的呢? 秘诀就是 KubernetesKubernetes 最初由 Google 开发,是一个开源的容器编排平台,旨在自动化容器化应用程序的部署、扩缩容和管理。 在本教程中,我们将介绍如何将 Kubernetes 纳入到现有的传统 CI/CD 管道中,并实现服务的高可用性,以及随时(是的,任何时候都不会影响服务)在生产环境中进行代码变更。 使用到的工具本教程是基于你对如下主题有基本 / 良好的理解的基础上的。 Kubernetes(我们的服务在 Kubernetes 上运行) Jenkins 以及 Jenkins 共享库(CI/CD 工具) GIT(SCM 工具) HAProxy(网络负载均衡器) Ansible(配置管理工具) CI/CD 安装Jenkins 服务器——与 Docker、Ansible 和 Kubectl 一起安装(将 Kube 管理配置.kube 从 K8s master 复制到 Jenkins 服务器的主目录中) 具有一主两从三个节点的 K8s 集群 HAProxy 服务器 使用 K8s 的 CI/CD GIT & Jenkins让我们来详细介绍一下如何配置所有这些不同的工具,并使其能够完美地运行。 我们的示例应用程序,名为 shoppingapp,在 GitHub 中有三个存储库,每个库都具有特定的微服务。 shoppingapp-home:首页微服务 shoppingapp-kids :儿童版页面微服务 shoppingapp-mens:男士版页面微服务 类似地,针对这三个库我们有三个 Jenkins 管道作业,并在存储库中设置了 GitHub webhook,以便在有新提交时自动启动构建。 Jenkins 管道作业 我们来看下 shoppingapp-home 作业的配置。 Jenkins 管道配置 在 shoppingapp-home 的管道作业中,仓库 URL 指向 shoppingapp-home 的 GitHub 存储库。类似地,另外两个管道作业也指向各自的存储库。 下面是 shoppingapp-home 存储库中的 Jenkinsfile。 @Library('jenkins-shared-library') _ pipeline { agent any environment { app = 'shoppingapp' service = 'shoppingapp-home' registryCredential = 'dockerhub' dockerImage = '' imageid = "deepanmurugan/shoppingapp-home:$BUILD_NUMBER" } stages { stage('Build') { steps { script { dockerImage = dockerbuild(imageid) } } } stage('Test') { steps { testcase() } } stage('Publish') { steps{ script { imagepush(imageid) } } } stage('Pull Playbook Repo') { steps { dir('/tmp/ansible-playbooks/') { gitcheckout( branch: "master", repoUrl: "https://github.com/deepanmurugan/Ansible_Playbook.git" ) } } } stage ('Deploy') { steps { dir('/tmp/ansible-playbooks/') { script{ deploytok8s(imageid,app,service) } } } } } } shoppingapp-home 存储库的 Jenkinsfile 以下是管道作业中的不同步骤。作业声明了几个变量,app——指我们的应用程序名,service——指我们的服务名,registryCredentials——是我们保存在 Jenkins 中的 dockerhub 用户名和密码,imageid——带有标签的 Docker 容器镜像名,这里的标签将是 Jenkins 的内部版本号。 在上面的 Jenkinsfile 中,我使用了共享库(如果你不熟悉共享库的话,请参考 Jenkins 网站)。 在“Build”(构建)阶段,我在共享库中调用了函数dockerbuild,并将 imageid 作为参数进行传递。以下是dockerbuild函数的定义。 def call(String dockerImage) { script { docker.build "${dockerImage}" } } Build 阶段 它仅使用我们传递的 imageid 作为参数调用 docker.build,就会触发docker build -t imageid, 并基于 Dockerfile 创建一个 Docker 镜像。我们稍后再看 Dockerfile。 下一步是“Test”(测试),此时我们可以运行测试用例。我目前不执行任何测试用例,因为这是一个非常基础的应用程序。 def call() { sh """ echo "Testing the docker built image" """ } Test 阶段 接下来,我们进入“Publish”(发布)阶段,该阶段将再次调用imagepush函数,其中 imageid 作为共享库中的参数。该函数基本上要登录到 Docker Hub,并将镜像推送到 Docker Hub 中。 def call(String dockerImage) { echo "${dockerImage}" withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'hubUsername', passwordVariable: 'hubPassword')]) { sh """ docker login --username="${hubUsername}" --password="${hubPassword}" docker push "${dockerImage}" """ } } Publish 阶段 下一步是“Pull Playbook Repo”,仅克隆存储库,该库中包含了我们所有的 playbook。 def call(Map stageParams){ checkout([$class: 'GitSCM', branches: [[name: stageParams.branch]], userRemoteConfigs: [[credentialsId: 'github_repo', url: stageParams.repoUrl]]]) } Pull Playbook Repo 阶段 接下来是“Deploy”(部署)阶段,该阶段触发 playbook 将容器部署到 Kubernetes 集群中。 def call(String dockerImage, String app, String service) { sh """ ansible-playbook deploy_k8s.yml --extra-vars \"image_id=${dockerImage} app_name=${app} service_name=${service}\" """ } Deploy 阶段 现在,我们对如何开发和维护每个微服务的存储库、如何配置 Jenkins 管道来创建 Docker 镜像并将镜像推送到 Docker Hub 以及触发 Ansible Playbook 将容器部署到 K8s 集群都已经相当清楚了。那我们来看一下它的 Dockerfile 是什么样的。 Dockerize 应用程序FROM python:3.7.3-alpine3.9 RUN mkdir -p /app WORKDIR /app COPY ./src/requirements.txt /app/requirements.txt RUN pip install -r requirements.txt COPY ./src/ /app ENV FLASK_APP=server.py CMD flask run -h 0.0.0.0 -p 5000 Dockerfile Dockerfile 使用 python:3.7.3-alpine3.9 作为基础镜像,我们安装了一个 flask 应用程序来打印某些文本。有关代码,请参阅 shoppingapp-home 的 GitHub 存储库。该应用程序运行在端口 5000 上。 使用 Ansible Playbook 来进一步接管下面是 Ansible Playbook 的 deploy_k8s.yml,它是由 Jenkins 管道作业触发的。 - hosts: localhost user: ubuntu tasks: - name: Deploy the service k8s: state: present definition: "{{ lookup('template', 'k8s/{{app_name}}/{{service_name}}/deployment.yml') | from_yaml }}" validate_certs: no namespace: default - name: Deploy the application k8s: state: present validate_certs: no namespace: default definition: "{{ lookup('template', 'k8s/{{app_name}}/{{service_name}}/service.yml') | from_yaml }}" - name: Deploy the Ingress k8s: state: present validate_certs: no namespace: default definition: "{{ lookup('template', 'k8s/{{app_name}}/common/ingress.yml') | from_yaml }}" 使用 Ansible 部署 K8s 组件 Kubernetes 集群现在我们来看一下 K8s 集群。集群中有一个主节点和两个工作节点。 ubuntu@kube-master:~$ kubectl get nodes NAME STATUS ROLES AGE VERSION kube-master Ready master 10d v1.19.4 kube-worker1 Ready none 10d v1.19.4 kube-worker2 Ready none 9d v1.19.4 此外,我们还安装了 Traefik Ingress 控制器,作为集群中两个副本的部署(deployment)。 ubuntu@kube-master:~$ kubectl get pods -n kube-system|grep ingress traefik-ingress-controller-6b7f594d46–5jqzq 1/1 Running 0 7d12h traefik-ingress-controller-6b7f594d46-vvfch 1/1 Running 0 8d 为了无缝地部署 / 扩展我们的服务,我们以特定的格式组织了 Ansible Playbook 库。 K8s 服务定义的目录结构 每个服务都有两个特定于该服务的文件 deployment 和 service,common 目录中则包含了 ingress 配置定义。 apiVersion: apps/v1 kind: Deployment metadata: labels: app: "{{ app_name }}" name: {{ service_name }}-deloyment spec: replicas: 2 selector: matchLabels: app: "{{ app_name }}" task: "{{ service_name }}" template: metadata: labels: app: "{{ app_name }}" task: "{{ service_name }}" spec: containers: - name: {{ service_name }}-pod image: "{{ image_id }}" imagePullPolicy: Always ports: - containerPort: 5000 imagePullSecrets: - name: dockerhubsecret strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 deployment.yml 上面的 deployment 文件是通用的,它从 Jenkins 管道作业中获取所有传输到 deploy_k8s.yml 的变量,并将其传输到该 K8s 的 deployment.yml 中。因此,若要用更多的微服务来扩展应用程序,只需在 Ansible Playbook 库中创建适当的目录结构以及具有 ingress 配置的 Jenkins 管道,即可实现完美地运行。 在创建部署之后,我们需要创建一个服务来公开该部署。该服务将端口 80 映射到 pod 的端口 5000。 apiVersion: v1 kind: Service metadata: name: {{ service_name }}-service spec: selector: app: "{{ app_name }}" task: "{{ service_name }}" ports: - protocol: TCP port: 80 targetPort: 5000 name: http service.yml Deployment.yml 和 Service.yml 文件对于 shoppingapp 服务下的所有微服务都是通用的。 另外,我们看一下 common/ingress.yml 中 ingress 配置。ingress 的主机(host)名是 app.shoppingapp.com,它具有基于路径的规则,可将流量重定向到特定的服务。 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ app_name }}-ingress annotations: kubernetes.io/ingress.class: traefik traefik.frontend.rule.type: PathPrefixStrip spec: rules: - host: app.shoppingapp.com http: paths: - path: /home backend: serviceName: shoppingapp-home-service servicePort: http - path: /kids backend: serviceName: shoppingapp-kids-service servicePort: http - path: /mens backend: serviceName: shoppingapp-mens-service servicePort: http ingress.yml 引入 HAProxy另外,我还使用了 HAProxy 负载均衡器来平衡 K8s 集群中两个节点之间的流量。我已经将前端和后端添加到现有的 HAProxy 配置文件中。后端服务器是 K8s 集群中的工作节点。 frontend http_front bind *:80 mode http default_backend http_back backend http_back balance roundrobin server kube 172.31.35.122:32365 check server kube 172.31.40.13:32365 check 端口 32365 是 traefik-ingress-service 服务公开的端口。DNS 是为 ingress.yml 中提到的主机名 app.shoppingapp.com 创建的,该主机名会被解析为 HAProxy IP(我使用的是 AWS Route 53 内部域名来创建的域名和 DNS 记录) ubuntu@jenkins_ansible:~$ kubectl describe svc traefik-ingress-service -n kube-system Name: traefik-ingress-service Namespace: kube-system Labels: none Annotations: none Selector: k8s-app=traefik-ingress-lb Type: NodePort IP: 10.102.149.216 Port: web 80/TCP TargetPort: 80/TCP NodePort: web 32365/TCP Endpoints: 10.244.1.99:80,10.244.3.19:80 Port: admin 8080/TCP TargetPort: 8080/TCP NodePort: admin 31387/TCP Endpoints: 10.244.1.99:8080,10.244.3.19:8080 Session Affinity: None External Traffic Policy: Cluster Events: none 真实的流程对于这个为我们的微服务应用程序而创建的 CI/CD 管道,其所需的所有组件我们都已经了解了。现在,让我们将这些组件组装起来,以了解该流程的工作原理。 开发人员提交代码到微服务仓库(shoppingapp-kids) GitHub 中配置的 Webhook 通知 Jenkins 并触发相应的管道作业(shoppingapp kids) 管道作业克隆 shoppingapp-kids 存储库,并开始执行 Jenkinsfile。 Jenkinsfile 中的构建阶段使用克隆的 shoppingapp-kids 存储库中的 Dockerfile 创建 Docker 镜像(deepanmurugan/shoppingapp-kids:21)。 测试 Docker 镜像,如果测试通过,则将镜像推送到 Docker Hub。 触发 Ansible Playbook,使用 app_name、service_name 以及 image_id 变量将 Docker 镜像部署到 K8s 集群。 Ansible Playbook 将读取所有与 deployment/servive/ingress 相关的 K8s 定义,并在集群中创建所需的组件。 向管道中添加新的微服务假设我们有一个请求,要求在该架构中再添加一个名为 shoppingapp-ladies 的微服务。开发人员创建了一个名为 shoppingapp-ladies 的存储库,并使用相同的 Docker 和 Jenkinsfile 提交了代码,唯一的变化是 Jenkinsfile 中的 service_name=shoppingapp-ladies 变量。 修改文件夹结构后,添加新的微服务 修改 common/ingress.yml,并添加一个名为 /ladies 的新路径,端点是 shoppingapp-ladies-service。 - path: /ladies backend: serviceName: shoppingapp-ladies-service servicePort: http 拷贝现有的 Jenkins 管道作业,并创建一个名为 shoppingapp-ladies 的新管道作业。 Jenkins 管道作业列表 在新作业 shoppingapp-ladies 的管道中,只需添加新的存储库 URL,然后执行管道作业,仅此而已。它将创建一个新的部署和服务并修改 ingress。 ubuntu@jenkins_ansible:/opt/python$ curl app.shoppingapp.com/ladies Welcome to shoppingapp — Ladies section — shoppingapp-ladies-deloyment-656f6f9d9f-dms8w 原文链接: https://medium.com/awsblogs/ci-cd-with-kubernetes-3c29e8073c38 你也「在看」吗???

上一篇:2022-10-29_「转」字节跳动开源BitSail:重构数据集成引擎,走向云原生化、实时化 下一篇:2020-11-17_偏见,人工智能的真正风险

TAG标签:

18
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价