微服务部署与交付流水线实战指南
在微服务架构盛行的今天,如何高效、可靠地部署和交付微服务成为了关键问题。本文将深入探讨微服务在Kubernetes集群中的部署、回滚操作,以及如何构建一个基于Jenkins的持续交付流水线。
1. 微服务在Kubernetes集群中的部署与操作
在Kubernetes集群中部署微服务时,除了正常的部署流程,还需要考虑异常情况的处理,如版本回滚,以及服务之间的连接方式。
1.1 版本回滚
当成功部署微服务的新版本后,如果出现问题,可以使用部署对象进行回滚操作。具体步骤如下:
-
查看回滚历史
:使用以下命令查看部署的回滚历史。
$ kubectl rollout history deployment/market-data
该命令会返回两个版本信息,即原始部署版本和v2部署版本。
-
执行回滚操作
:指定目标版本进行回滚。
$ kubectl rollout undo deployment/market-data --to-revision=1
此操作将执行与之前滚动更新相反的操作,使底层副本集恢复到原始状态。
1.2 连接多个服务
单个微服务的作用有限,许多服务依赖于其他服务提供的功能。为了避免将端口号或IP地址硬编码到每个服务中,Kubernetes集成了本地DNS服务。当创建新服务时,DNS服务会为其分配一个格式为
{my-svc}.{my-namespace}.svc.cluster.local
的名称。例如,可以使用
market-data.default.svc.cluster.local
从任何其他Pod解析
market-data
服务。
可以通过以下步骤进行测试:
1. 使用
kubectl
在集群中运行一个任意容器,这里选择
busybox
镜像。
$ kubectl run -i --tty lookup --image=busybox /bin/sh
-
在容器内执行
nslookup命令。
/ # nslookup market-data.default.svc.cluster.local
预期输出如下:
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: market-data.default.svc.cluster.local
Address 1: 10.0.0.156 market-data.default.svc.cluster.local
最后一行的IP地址应与为服务分配的集群IP相匹配。
2. 微服务部署的关键要点总结
将微服务打包为不可变的可执行工件,可以通过简单的添加或删除容器操作来编排部署。调度器和容器抽象了底层机器管理,使服务开发和部署更加便捷。调度器通过匹配应用的资源需求和集群机器的资源使用情况,并对运行的服务进行健康检查,确保服务正常运行。Kubernetes提供了微服务部署平台的理想特性,包括密钥管理、服务发现和水平扩展。用户定义集群服务的期望状态,Kubernetes会不断执行观察 - 差异 - 行动的循环来实现该状态。
以下是Kubernetes中一些重要概念的总结:
| 概念 | 说明 |
| ---- | ---- |
| Pod | Kubernetes中的逻辑应用单元,由一个或多个容器共同执行 |
| 副本集 | 管理Pod组的生命周期,在现有Pod失败时启动新的Pod |
| 部署 | 通过跨副本集对Pod进行滚动更新来维持服务可用性 |
| 服务对象 | 对底层Pod进行分组,并使其对集群内外的其他应用可用 |
3. 构建微服务交付流水线
快速、可靠地将新的微服务和功能发布到生产环境对于维护微服务应用至关重要。与单体应用不同,微服务部署需要考虑多个服务的不同语言和依赖关系。通过应用持续交付原则,可以实现可靠的微服务发布。
3.1 使部署变得轻松
理想的微服务部署过程应满足两个目标:
-
安全与速度的平衡
:快速部署新服务和更改,同时最大程度地保证安全,验证更改不会对服务稳定性产生负面影响。
-
一致性
:不同服务的部署过程保持一致,无论底层技术栈如何,有助于减轻技术隔离,使操作更具可预测性和可扩展性。
持续交付通过以下方式在降低风险和提高速度之间取得理想平衡:
- 发布较小的提交集,减少同一时间的更改量,提高安全性,并且更易于分析。
- 自动化的提交验证流水线增加了给定更改集无缺陷的可能性。
下面是一个典型的部署流水线示例:
graph LR
A[工程师提交代码] --> B[构建自动化服务器构建代码]
B --> C{构建是否成功}
C -- 是 --> D[运行单元测试]
C -- 否 --> E[失败反馈]
D --> F{单元测试是否通过}
F -- 是 --> G[打包服务并存储到制品库]
F -- 否 --> H[失败反馈]
G --> I[部署到暂存环境]
I --> J{暂存环境测试是否通过}
J -- 是 --> K[部署到生产环境]
J -- 否 --> L[失败反馈]
3.2 使用Jenkins构建流水线
Jenkins是一个广泛使用的开源构建自动化工具,可以将之前使用的命令行脚本步骤连接成一个连贯、可重用和可扩展的部署流水线。
以下是使用Jenkins构建流水线的详细步骤:
3.2.1 配置构建流水线
Jenkins应用由主节点和可选的多个代理节点组成。运行Jenkins作业时,会在代理节点上执行脚本以执行部署活动。
为了编写构建流水线,使用Scripted Pipeline功能,通过Groovy语言编写的通用领域特定语言(DSL)来表达构建流水线。DSL定义了一些常用方法,如
sh
用于执行shell脚本,
stage
用于标识构建流水线的不同部分。
首先,创建一个基本的
Jenkinsfile
,示例如下:
stage("Build Info") {
node {
def commit = checkout scm
echo "Latest commit id: ${commit.GIT_COMMIT}"
}
}
当Jenkins运行此脚本时,会将代码仓库检出为工作区,并将最新的提交ID写入控制台。
创建流水线作业的步骤如下:
1. 将
chapter-10/market-data
内容复制到新目录,并推送到Git仓库,建议推送到公共仓库,如GitHub。
2. 在仓库根目录创建
Jenkinsfile
。
3. 提交
Jenkinsfile
并推送到远程仓库。
4. 打开Jenkins UI(可以使用
minikube service jenkins
打开)。
5. 导航到
Create New Jobs
页面。
6. 输入作业名称
market-data
,选择
Multibranch Pipeline
作为作业类型,然后点击
OK
。
7. 在后续页面中,选择
Branch Source
为
Git
,并将仓库的克隆URL添加到
Project Repository
字段。如果使用私有Git仓库,还需要配置凭证。
8. 选择每分钟定期扫描流水线,以便在检测到更改时触发构建。
9. 保存更改。
Jenkins会扫描仓库中包含
Jenkinsfile
的分支,并为每个分支生成唯一的构建。
3.2.2 构建镜像
使用Docker来构建和打包镜像,修改
Jenkinsfile
如下:
def withPod(body) {
podTemplate(label: 'pod', serviceAccount: 'jenkins', containers: [
containerTemplate(name: 'docker', image: 'docker', command: 'cat',
➥ttyEnabled: true),
containerTemplate(name: 'kubectl', image: 'morganjbruce/kubectl',
➥command: 'cat', ttyEnabled: true)
],
volumes: [
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath:
➥'/var/run/docker.sock'),
]
) { body() }
}
withPod {
node('pod') {
def tag = "${env.BRANCH_NAME}.${env.BUILD_NUMBER}"
def service = "market-data:${tag}"
checkout scm
container('docker') {
stage('Build') {
sh("docker build -t ${service} .")
}
}
}
}
这个脚本会构建服务,并使用当前构建号标记生成的Docker容器。具体操作步骤如下:
1. 定义一个用于构建的Pod模板,Jenkins会使用该模板在Kubernetes上为构建代理创建Pod。这个Pod包含两个容器:Docker和kubectl。
2. 请求Pod模板的一个实例。
3. 从Git检出最新代码。
4. 进入Pod的Docker容器。
5. 开始一个新的流水线阶段。
6. 运行
docker
命令构建服务镜像。
通过以上步骤,我们可以在Kubernetes集群中实现微服务的可靠部署和持续交付,提高开发和运维效率,降低风险。
4. 管理暂存和生产环境
在构建微服务交付流水线的过程中,管理暂存和生产环境是确保服务质量和稳定性的重要环节。
4.1 暂存环境的重要性
暂存环境是生产环境的一个近似副本,用于在将代码部署到生产环境之前进行全面测试。在暂存环境中,可以模拟生产环境的各种条件,包括与其他实时协作服务的交互,从而发现潜在的问题和冲突。
以下是暂存环境的主要作用:
-
集成测试
:确保微服务与其他相关服务能够正常协作,验证接口的兼容性和数据的一致性。
-
性能测试
:评估服务在接近生产负载下的性能表现,发现性能瓶颈并进行优化。
-
用户验收测试
:让业务用户在真实场景下对新功能进行验收,确保满足业务需求。
4.2 管理暂存环境
使用Jenkins和Kubernetes可以方便地管理暂存环境。在前面的Jenkinsfile基础上,可以进一步扩展以支持暂存环境的部署和测试。
以下是一个简单的扩展示例,用于将构建好的镜像部署到暂存环境并进行测试:
withPod {
node('pod') {
def tag = "${env.BRANCH_NAME}.${env.BUILD_NUMBER}"
def service = "market-data:${tag}"
checkout scm
container('docker') {
stage('Build') {
sh("docker build -t ${service} .")
}
}
container('kubectl') {
stage('Deploy to Staging') {
sh("kubectl apply -f deployment-staging.yaml --namespace=staging")
}
stage('Test in Staging') {
sh("curl http://market-data-staging.svc.cluster.local/health")
}
}
}
}
上述代码中,增加了两个新的阶段:
-
Deploy to Staging
:使用
kubectl apply
命令将部署配置文件
deployment-staging.yaml
应用到暂存环境的命名空间
staging
中。
-
Test in Staging
:使用
curl
命令对暂存环境中的服务进行健康检查,确保服务正常运行。
4.3 生产环境部署
经过暂存环境的测试后,就可以将代码部署到生产环境。在部署到生产环境时,需要更加谨慎,确保服务的稳定性和可靠性。
可以在Jenkinsfile中添加一个新的阶段来实现生产环境的部署:
withPod {
node('pod') {
def tag = "${env.BRANCH_NAME}.${env.BUILD_NUMBER}"
def service = "market-data:${tag}"
checkout scm
container('docker') {
stage('Build') {
sh("docker build -t ${service} .")
}
}
container('kubectl') {
stage('Deploy to Staging') {
sh("kubectl apply -f deployment-staging.yaml --namespace=staging")
}
stage('Test in Staging') {
sh("curl http://market-data-staging.svc.cluster.local/health")
}
stage('Deploy to Production') {
sh("kubectl apply -f deployment-production.yaml --namespace=production")
}
}
}
}
在
Deploy to Production
阶段,使用
kubectl apply
命令将生产环境的部署配置文件
deployment-production.yaml
应用到生产环境的命名空间
production
中。
5. 使用特性标志和暗发布
在微服务部署中,部署和发布是两个不同的概念。部署是将代码推送到生产环境,而发布是让用户能够访问新功能。使用特性标志和暗发布可以有效地将部署和发布分离,降低风险。
5.1 特性标志
特性标志是一种在代码中控制功能是否启用的机制。通过在配置文件或数据库中设置标志,可以动态地开启或关闭某个功能,而无需重新部署代码。
以下是一个简单的特性标志示例:
FEATURE_FLAGS = {
"new_feature": False
}
def new_feature_enabled():
return FEATURE_FLAGS["new_feature"]
def main():
if new_feature_enabled():
# 执行新功能的代码
print("New feature is enabled!")
else:
# 执行旧功能的代码
print("New feature is disabled.")
if __name__ == "__main__":
main()
在上述示例中,通过修改
FEATURE_FLAGS
字典中的
new_feature
标志的值,可以控制新功能是否启用。
5.2 暗发布
暗发布是指在生产环境中部署新功能,但默认情况下不向用户公开。可以通过特性标志来控制新功能的可见性,只对特定的用户群体(如内部测试人员、特定客户)开放,进行灰度测试。
以下是暗发布的主要步骤:
1.
部署新功能
:将包含新功能的代码部署到生产环境。
2.
设置特性标志
:默认情况下,将新功能的特性标志设置为关闭状态。
3.
灰度测试
:选择一部分用户群体,将他们的特性标志设置为开启状态,进行测试。
4.
监控和评估
:监控灰度测试期间的各项指标,如性能、错误率、用户反馈等,评估新功能的稳定性和可用性。
5.
全面发布
:如果灰度测试结果良好,将特性标志设置为对所有用户开放,完成新功能的全面发布。
6. 总结与展望
通过本文的介绍,我们了解了微服务在Kubernetes集群中的部署、回滚操作,以及如何构建一个基于Jenkins的持续交付流水线。同时,我们还探讨了管理暂存和生产环境、使用特性标志和暗发布等重要技术。
| 技术点 | 作用 |
|---|---|
| 版本回滚 | 在部署出现问题时,将服务恢复到之前的稳定版本 |
| 服务连接 | 通过Kubernetes的本地DNS服务,实现微服务之间的连接 |
| 持续交付流水线 | 自动化构建、测试和部署过程,提高开发和运维效率 |
| 暂存环境管理 | 在部署到生产环境之前进行全面测试,降低风险 |
| 特性标志和暗发布 | 分离部署和发布,实现灰度测试,提高新功能的稳定性和可用性 |
在未来的微服务开发和部署中,我们可以进一步优化和扩展这些技术。例如,可以引入更高级的自动化测试框架,提高测试的覆盖率和准确性;使用更智能的调度算法,优化资源分配;结合人工智能和机器学习技术,实现自动故障诊断和修复等。通过不断地探索和实践,我们能够更好地应对微服务架构带来的挑战,实现高效、可靠的软件交付。
graph LR
A[部署新功能到生产环境] --> B[设置特性标志为关闭]
B --> C[选择部分用户进行灰度测试]
C --> D{灰度测试结果是否良好}
D -- 是 --> E[全面发布新功能]
D -- 否 --> F[修复问题并重新测试]
F --> C
通过以上步骤和技术,我们可以构建一个高效、可靠的微服务交付流水线,确保微服务的质量和稳定性,为业务的发展提供有力支持。
超级会员免费看

844

被折叠的 条评论
为什么被折叠?



