Kubernetes 部署 - DevOps CI/CD详细指南
什么是Kubernetes部署?
在此文章中,我们将探索Kubernetes(K8s),结合DigitalOcean Kubernetes集群与Buddy自动化运维系统部署以达到以下列出的目标:
- 使用一个K8s示例应用通过Buddy流水线操作构建Docker镜像并推送至Docker Hub注册中心
- 通过K8s示例应用设置两个Hello World演示部署于K8s集群之中以便测试负载均衡器
- 为K8s示例应用安装Ingress NGINX控制器于K8s集群之中
- 使用Cert-Manager添加域名SSL证书
K8s优势
K8s可以将其描述为一个容器编排平台,它可以在云端或远程机器上扩展和运行您的应用程序。为了更容易理解,您可以把它想象成一个容器管理器,它会自动处理您必须手动执行的操作。
以下是使用K8s的一些优势:
- 自愈能力 – 通过自动调度程序,K8s能够在出现错误或超时的情况下用新容器替换容器。
- 滚动(Rollouts)与回滚(Rollbacks) – 除了自我修复能力外,K8s还实现了新部署滚动,类似于蓝绿色部署,大大减少了停机机会。
- 负载分配和自动发现 – 在K8s上运行的解耦应用程序能够在本地集群网络上进行通信,从而减少公开应用程序地址所需的工作量。除此之外,K8s还有多个负载分配点。这意味着,您可以将负载从入口层和服务层分配到Pod。
- 横向与纵向扩展 – K8s允许我们根据场景进行横纵扩展。您可以运行同一应用程序的500多个容器,并且仍然几乎毫不费力地管理分配给每个容器的资源。说明K8s为您的应用程序提供弹性伸缩!
- 交付速率 – 发布应用程序的速度对当今每个团队都至关重要。过去,发布必须由许多团队成员在预定维护期间完成,期间会出现很多中断和停机时间。
即使没有持续部署,K8s也能够在几乎没有停机时间的情况下促进和管理各种规模的发布。
K8s构架
K8s本身由几个组件组成。但我们不会在本文中介绍所有内容,主要关注于容器,我们还将使用Docker。
K8s上的容器以称为Pod的组合运行。Pod中的容器共享相同的网络、存储和地址。这说明访问pod的地址实际上意味着访问pod中的容器之一:
虽然您确实不需要流水线来让应用程序在云服务上运行,但由于SDK,在更大范围内,团队会发现依赖本地机子部署效率非常低。
K8s部署工作原理
流水线可以被认为是将服务或应用程序从A点移动到B点的一种方式。在CI/CD方面,我们可以将其分为三种类型:
- 持续集成 – 通过GitHub等版本控制平台对代码进行测试和版本控制。这就是Buddy的用武之地,它提供了更简单、更高效的流水线配置方式。
- 持续交付 – 有助于将应用程序从版本控制平台部署到云服务或其他供应商特定的服务。交付流水线需要批准才能部署到特定环境,例如生产环境或面向客户的环境。
- 持续部署 – 无需人为干预、批准或输入,即可轻松自动部署到云端。
微服务模式引入了一种新的软件实现方式。将此视为一种移动模式,涉及多个移动部件,所有部件都统一起来以呈现单个应用程序。
无论有没有DevOps工作人员,您的团队都不必担心与运维相关的问题,比如弄清楚三个应用程序组件的交付。最重要的是保持对产品的聚焦。
K8s自动化陷阱
技术栈
过去,部署堆栈主要基于Shell脚本构建。对于以前没有堆栈经验的团队成员来说,这通常很复杂。现在,几乎每个平台都提供 YAML。作为一种声明式和更透明的语言,YAML的学习曲线相当容易。然而,不幸的是,有些平台仍然需要YAML上对shell的解决方案。
Buddy凭借着其直观的GUI和流水线声明式YAML配置解决了这些问题。
安全性
安全性是任何流水线的关键组成部分。关键的安全问题之一是处理密钥和敏感信息。在大多数情况下,密钥或敏感信息在进行加密后作为环境变量添加到平台上,然后在构建过程中进行转译和解密。在定义这些作业的过程中,很容易通过打印密钥或对公共Docker镜像进行版本控制来泄露这些细节信息。同时还建议避免在第三方服务上使用不受限制的API密钥。
Buddy如何处理安全问题
- 只需按一下按钮即可自动加密和手动加密。
- 存储仓通用的操作变量建议和默认环境变量
模糊的平台与工具关联
平台关联肯定是最大的挑战之一。不同的团队以不同的方式处理此问题:从开箱即用的特定于平台YAML模块到脚本连接。建议采用模块化方法代替脚本化流水线,通常涉及几个步骤:从获取SDK到授权,再到实际部署。这通常会导致相当复杂、容易出错且体积庞大的流水线。
Buddy提供与各大商家的各种集成,以及具有声明性流水线操作模式丰富的buddy.yml
脚本。
K8s部署如何工作? 示例流水线
本文的K8s示例应用可以在这个GitHub Repo中下载源码!
构建与推送Docker镜像
首先创建一个名为hello的Buddy项目,并选择Buddy自带的Git托管作为代码存储仓:
- 如果您还没有Buddy帐号可在此免费创建一个
下载GitHub存储仓中的源码并推送至刚刚创建的项目存储仓:
然后在Buddy中添加DigitalOcean集成,以方便持续集成所要使用的DigitalOcean Kubernetes集群:
流水线中添加操作
在hello项目中创建一条流水线:
接下来,我们将在流水线上添加第一个操作,即Docker构建镜像,为将所构建的镜像推送至Docker Hub而做准备:
选择存储仓上的Dockerfile
文件并提交完成添加Docker构建镜像操作:
添加第二个操作:推送Docker镜像
推送Docker镜像的作用是可将上一个操作构建好的镜像推送至目标Docker注册中心,也就是Docker镜像存储仓,例如:Docker Hub、Amazon ECR、Google GCR以及私有的镜像注册中心等等不一。
如果您是第一次接触Docker镜像构建,推荐使用Docker Hub,目前只需要在Docker官方网站上免费注册一个帐户即可使用。
填写好相关要推送的镜像信息完成添加推送Docker镜像
此时,您应该看到如下图有两个操作添加于流水线之中:
运行流水线
点击以上蓝色“运行”按钮开始运行流水线:
获取Docker镜像信息
运行完成之后,我们就可以在Docker Hub帐户中看到已有相关镜像信息显示:
自动化部署K8s集群
部署第一个Hello World
在hello项目存储仓中添加第一个Hello World YAML文件hello-kubernetes-first.yaml
,同时在文件中添加以下代码:
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes-first
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: hello-kubernetes-first
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes-first
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes-first
template:
metadata:
labels:
app: hello-kubernetes-first
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: 这是第一个Hello World部署!
此配置定义了部署(Deployment
)和服务(Service
)。 部署包含aulbouwer/hello-kubernetes:1.7
镜像的三个副本(replicas
)和一个名为MESSAGE
的环境变量(您将在访问应用程序时看到此信息)。这里的服务(Service
)定义为在80
端口显露(expose
)集群内的部署(Deployment
)。
在流水线中添加K8s提交部署操作:
添加hello-kubernetes-first.yaml
文件,这个文件将在流水线运行时提交部署至K8s集群中:
部署第二个Hello World
根据以上相同的添加步骤再添加一个hello-kubernetes-second.yaml
文件作为第二个Hello World演示,并在文件中添加以下代码:
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes-second
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: hello-kubernetes-second
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes-second
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes-second
template:
metadata:
labels:
app: hello-kubernetes-second
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
env:
- name: MESSAGE
value: 这是第二个Hello World部署!
此时我们就可以在流水线中看到如下图所示的流水线信息:
如上图在流水线上点击蓝色“运行”按钮,将会看到如下图所示的构建Docker镜像、推送Docker镜像以及提交两个Hello World YAML配置文件至K8s集群的流水线运行信息:
在命令行界面上运行以下命令:(创建DigitalOcean Kubernetes集群时会提示您如何配置您的电脑与其连接)
kubectl get service
运行以上代码后会显示以下信息
hello-kubernetes-first和hello-kubernetes-second都已列出,说明已经创建成功Kubernetes。
您已经使用Buddy自动化运维创建了hello-kubernetes应用程序的两个部署。每个在部署规范中都有不同的信息显示,以便在测试期间区分。 下一步,我们将安装Nginx Ingress Controller:
安装Nginx Ingress
我们将使用Helm安装Nginx Ingress 控制器
Nginx Ingress控制器 由一个Pod和一个Service组成。Pod运行控制器,控制器不断轮询集群API服务器上的/ingresses
端点以获取可用Ingress资源的更新。该服务的类型为LoadBalancer
。因为您将其部署到DigitalOcean Kubernetes集群,集群将自动创建一个DigitalOcean负载均衡器,所有外部流量将通过该负载均衡器流向控制器。然后控制器会将流量路由到适当的服务,如Ingress资源中定义的那样。
只有LoadBalancer
服务知道自动创建的负载均衡IP地址。某些应用程序(例如:ExternalDNS)需要知道其IP地址,但只能读取Ingress的配置。通过在helm install
安装期间将controller.publishService.enabled
参数设置为true
,可以将控制器配置为在每个Ingress上发布IP地址。建议启用此设置以支持可能依赖于负载均衡器IP地址的应用程序。
要安装 K8s Nginx Ingress 控制器,我们首先需要通过运行以下命令将其存储库添加到Helm:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
更新系统,让Helm知道所包含的内容:
helm repo update
最后,运行以下命令安装Nginx Ingress:
helm install nginx-ingress ingress-nginx/ingress-nginx --set controller.publishService.enabled=true
此命令从稳定chart存储仓安装Nginx Ingress,将Helm版本命名为nginx-ingress
,并将publishService
参数设置为true
。
运行后,您将看到类似以下的输出:
Helm已将其在Kubernetes中创建的资源记录为chart安装的一部分。
运行此命令以查看负载均衡器是否可用:
kubectl --namespace default get services -o wide -w nginx-ingress-ingress-nginx-controller
该命令在默认命名空间中获取Nginx Ingress服务并输出其信息,但该命令不会立即退出。使用-w
参数,它会在发生更改时监测并刷新输出信息。
我们已经安装了由Kubernetes社区维护的Nginx Ingress。它将HTTP和HTTPS流量从负载均衡器路由到Ingress资源中适配后端服务。 下一步,我们将显露(expose)公开hello-kubernetes
应用程序部署。
使用Ingress显露公开应用程序
在公开应用程序之前,我们需要准备两个域名并指向负载均衡器IP,我们将使用以下两个域名作为演示:
- 1.m2jd.com
- 2.m2jd.com
首先,通过以上已在Buddy创建的hello项目存储仓中再创建一个名为hello-kubernetes-ingress.yaml的文件,并添加以下代码部署两个示例域名以便在浏览器中测试:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: "1.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-first
port:
number: 80
- host: "2.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-second
port:
number: 80
我们使用名称hello-kubernetes-ingress定义Ingress资源。然后指定两个主机规则,以便将1.m2jd.com域名转向路由到hello-kubernetes-first服务,并将2.m2jd.com域名转向路由到第二个部署hello-kubernetes-second的服务。
接下来,添加hello-kubernetes-ingress.yaml文件到流水线操作提交Kubernetes部署之中并运行流水线。我们就可看到如下图的hello-kubernetes-ingress部署到K8s集群的Buddy流水线运行记录:
现在我们可以在浏览器中打开域名1.m2jd.com即可看到如下显示:
在浏览器中打开域名2.m2jd.com即可看到如下显示:
用Cert-Manager加强Ingress安全
为了保护Ingress资源,我们将安装Cert-Manager,为生产运营创建ClusterIssuer
,并修改Ingress的配置以使用TLS证书。安装和配置后,应用程序将在HTTPS之下运行。
ClusterIssuers
是Kubernetes中的Cert-Manager资源,它为整个集群提供TLS证书。ClusterIssuer
是一种特定类型的发行者。
在通过Helm将Cert-Manager安装到您的集群之前,您将为它创建一个命名空间:
kubectl create namespace cert-manager
这时,您需要将Jetstack Helm存储仓添加到托管Cert-Manager图谱(chart)的Helm。 为此,运行以下命令:
helm repo add jetstack https://charts.jetstack.io
Helm将显示以下输出信息:
更新Helm图谱缓存:
helm repo update
更新命令运行将显示以下输出信息:
最后,通过运行以下命令将Cert-Manager安装到cert-manager命名空间中:
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.10.1 --set installCRDs=true
在此命令中,我们也将installCRDs
参数设置为true
,以便在Helm安装期间安装cert-managerCustomResourceDefinition
配置清单。在写本文时,v1.10.1是最新版本。您可以参考ArtifactHub查找最新版本号。
除了在命令行界面上运行Helm命令,您也可以在Buddy流水线上添加Helm CLI操作并运行流水线:
输出信息将显示如下:
我们现在创建一个由Let's Encrypt颁发的证书,并将其配置存储在名为production_issuer.yaml
的文件中。在hello项目存储仓中创建并打开此文件并添加以下代码:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# Email address used for ACME registration
email: 请在此输入您的电子邮件地址
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-prod-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
接下来,同样在流水线中添加production_issuer.yaml文件到流水线操作提交Kubernetes部署之中并运行流水线:
在hello-kubernetes-ingress.yaml文件中添加以下高亮背景颜色的代码:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- 1.m2jd.com
- 2.m2jd.com
secretName: hello-kubernetes-tls
rules:
- host: "1.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-first
port:
number: 80
- host: "2.m2jd.com"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: hello-kubernetes-second
port:
number: 80
提交文件后Buddy将自动为您运行流水线,此时您的域名已支持SSL证书,恭喜!
在实际操作中,请将域名换成您自己的域名,而不是照搬1.m2jd.com与2.m2jd.com,那样将不会正常运行!
K8s部署优化
Kubernetes是一个基于容器的平台,用于部署、扩展和运行应用程序。Buddy让您可以通过一系列专用的K8s操作来自动化您的Kubernetes交付工作流。
每次更改应用程序代码或Kubernetes配置时,您都有两个选项来更新集群:kubectl apply
或 kubectl set image
。
在这种情况下,您的工作流程通常如下所示:
- 编辑代码或配置.yaml
- 将其推送至您的Git存储仓
- 构建新的Docker镜像
- 推送至Docker镜像
- 登录至您的K8s集群
- 运行
kubectl apply
或kubectl set image
如果您经常使用 kubectl apply
或 kubectl set image
,这个就是更好的解决方案!
如何自动运行K8s pod或任务
如果你经常在容器中运行任务,比如:
- 新版本部署时数据库迁移
- 备份
- 批量处理作业,例如:为新版本的应用程序创建目录结构。
您可以使用pods或任务,第一种类型使用任务启动单个pod;第二个启动系列pod,直到指定数量的pod以成功状态结束。
用于运行K8s pods或任务的流水线配置
假设您在K8s集群上有一个应用程序,存储仓包含如下内容:
- 您的应用程序源码
- 一个Dockerfile文件,其中包含有关创建应用程序镜像的说明。
- 数据库迁移脚本
- 一个Dockerfile文件,其中包含有关创建将在部署期间运行迁移的镜像说明(数据库迁移运行器)。
在这种情况下,您可以配置一个流水线:
A. 构建应用程序并迁移镜像(第一个操作)
B. 推送至Docker Hub(第二个操作)
C. 触发数据库迁移 使用先前构建的镜像(第三个操作)。您可以使用YAML文件定义镜像、命令和部署:
进行推送后,流水线将自动构建并将镜像推送到存储仓并运行迁移脚本,是不是很酷?
作业操作将等到命令执行完毕,如果退出状态不同于0,则操作将被标记为“失败”。
D. 最后一个操作是使用提交Kubernetes部署或Kubernetes设置镜像来更新K8s应用程序中的镜像。添加操作后,整个流水线将如下所示:
一切就绪后,再次推送,即可看到Buddy自动执行整个工作流程。
希望您有所收获,非常感谢您花时间阅读本文!
Kubernetes 部署 - DevOps CI/CD详细指南的更多相关文章
- VSTS跟Kubernetes整合进行CI/CD
利用VSTS跟Kubernetes整合进行CI/CD 为什么VSTS要搭配Kubernetes? 通常我们在开发管理软件项目的时候都会碰到一个很头痛的问题,就是开发.测试.生产环境不一致,导致开发 ...
- DevOps - CI&CD
1 - CI与CD的联系与区别 持续集成(Continuous Integration).持续交付(Continuous Delivery)和持续部署(Continuous Deployment)的过 ...
- 【进阶之路】持续集成、持续交付与持续部署(CI/CD)
由来 记得7月份刚刚换工作的时候,中午和老大一起去吃饭,回来的路上老大问我:"南橘,CI/CD有没有研究过?" 我隐隐约约在哪里听过这个名词,但是又想不起来,秉着实事求是的态度,我 ...
- DevOps - CI/CD - Jenkins
Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建.测试和部署等功能.本文以 CentOS7 环境为例,总结了 Jenkin ...
- CI Weekly #1 | 这份周刊,带你了解 CI/CD 、DevOps、自动化测试
原文首次发布与 flow.ci Blog >> 链接,转载请联系:) 准备了很久,CI Weekly 第一期终于来了. CI Weekly 围绕『 软件工程效率提升』 进行一系列技术内容分 ...
- 基于 Kubernetes 实践弹性的 CI/CD 系统
大家好,我是来自阿里云容器服务团队的华相.首先简单解释一下何为 Kubernetes 来帮助大家理解.Kuberentes 是一个生产可用的容器编排系统.Kuberentes 一方面在集群中把所有 N ...
- 实例演示:如何在Kubernetes上大规模运行CI/CD
本周四晚上8:30,第二期k3s在线培训如约开播!本期课程将介绍k3s的核心架构,如高可用架构以及containerd.一起来进阶探索k3s吧! 报名及观看链接:http://z-mz.cn/PmwZ ...
- Docker集群管理工具 - Kubernetes 部署记录 (运维小结)
一. Kubernetes 介绍 Kubernetes是一个全新的基于容器技术的分布式架构领先方案, 它是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernete ...
- Docker+Vagrant+Gitlab 构建自动化的 CI/CD
如果你的开发流程是下面这个样子的, 那么你一定很好奇, 为什么我提交到仓库的代码可以自动部署并访问到最新的提交内容 这就是近年来兴起的 DevOps 文化, 很方便的解决了开发人员和运维人员每次发布版 ...
- Kubernetes 部署失败的 10 个最普遍原因
[原文].后面我们可能还会看到一个 OOMKilled 错误. 我们的应用正在挂掉?为什么? 首先我们查看应用日志.假定你发送应用日志到 stdout(事实上你也应该这么做),你可以使用 kubect ...
随机推荐
- uoj349【WC2018】即时战略
题目链接 WC出了点意外滚粗了,来补补题. \(O(n^2)\)的时间复杂度,\(O(nlogn)\)的询问次数应该还是比较好想的,每次要打通到x的路径,对当前已知的树不断的找重心并询问在重心的哪颗子 ...
- 20220728 - DP训练 #1
20220728 - DP训练 #1 时间记录 \(8:00-9:00\) T1 尝试做 \(T1\),可惜并未做出,没有想到是资源分配 设置三维状态,初值一直不知道怎么设置 并且对于距离有一部分不会 ...
- 齐博x1钩子自动添加频道参数变量
频道或插件,增加功能的时候,可能要在后台增加开关参数.这个时候只需要增强对应的接口文件即可,比如创建这样一个文件\application\shop\ext\setting_get\give_jifen ...
- Java 动态代理原理图解 (附:2种实现方式详细对比)
动态代理在 Java 中有着广泛的应用,例如:Spring AOP 面向切面编程,Hibernate 数据查询.以及 RPC Dubbo 远程调用等,都有非常多的实际应用@mikechen 目录 ...
- Django Admin save 重写 保存
在 django admin管理控制台中,用户按下"Save and add another",表单的字段值仍然填充最后插入的值 并且保存 在ModelAdmin中添加选项save ...
- Codeforces Round #802 (Div. 2)C. Helping the Nature(差分)
题目链接 题目大意: 给你一个有n个元素的数组a,你可以通过一下三种操作使数组的每一个值都为0: 选择一个下标i,然后让a[1],a[2]....a[ i ] 都减一; 选择一个下标i,然后让a[i] ...
- vue3中使用computed
演示示例(vant组件库的轮播图): <van-swipe :loop="false" :width="150" class="my-Swipe ...
- Terminal(oh-my-zsh) 美化
如果你使用Mac进行开发,那么Terminal.app应该是你使用非常频繁的app了.初体验Terminal时你可能觉得单调乏味,阅读密密麻麻的内容也很费劲.但是如果你跟着我一起配置它,就会发现你平时 ...
- vue3 结合 element-plus 框架实现增删改查功能(不连接数据库)
一.效果图 二.代码 2.1.导入依赖(已经安装过node.js) npm install element-plus --save 注意:要是安装失败,可以使用淘宝镜像进行下载,如下: 2.2.设置淘 ...
- 本地GoLand编辑与调试远端服务器上的代码
Goland是专为Go开发人员构建的跨平台IDE,功能非常强大,拥有强大的代码洞察力,帮助所有Go开发人员即时错误检测和修复建议,快速和安全的重构,一步撤销,智能代码完成,死代码检测和文档提示,让您创 ...