MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kubernetes 实现微服务服务编排的实战指南

2023-10-283.8k 阅读

1. 微服务架构与 Kubernetes 概述

1.1 微服务架构简介

微服务架构是一种将应用程序构建为一组小型、自治服务的架构风格。每个服务都围绕特定业务能力构建,有自己独立的进程,可以使用不同的编程语言和数据存储技术。这种架构使得系统更加灵活、可独立部署和扩展,降低了系统的耦合度,便于开发团队并行工作。例如,一个电商系统可以拆分为用户服务、商品服务、订单服务等多个微服务。用户服务负责处理用户的注册、登录、信息管理等功能;商品服务专注于商品的展示、库存管理;订单服务则处理订单的创建、支付、配送跟踪等业务。

1.2 Kubernetes 基础

Kubernetes (简称 K8s)是一个开源的容器编排平台,旨在自动化容器化应用的部署、扩展和管理。它提供了一个强大的基础设施,使得微服务的运行和管理变得更加高效。Kubernetes 基于容器技术,如 Docker,将应用及其依赖打包成容器,然后进行编排和调度。

Kubernetes 中的核心概念包括 Pod、Service、Deployment 等。Pod 是 Kubernetes 中最小的可部署和可管理的计算单元,一个 Pod 可以包含一个或多个紧密相关的容器。例如,一个 Web 应用可能由一个后端 API 容器和一个前端静态资源容器组成,它们可以放在同一个 Pod 中。Service 则是一种抽象,用于将一组 Pod 暴露为一个网络服务,提供稳定的网络端点。Deployment 用于管理 Pod 和 ReplicaSet 的生命周期,通过 Deployment 可以轻松实现应用的滚动升级、回滚等操作。

2. 环境搭建

2.1 安装 Kubernetes 集群

搭建 Kubernetes 集群有多种方式,这里以 Minikube 为例,Minikube 是一个在本地运行 Kubernetes 集群的工具,非常适合开发和测试环境。

首先,确保你的系统安装了虚拟化软件,如 VirtualBox(对于 Windows 和 macOS)或 KVM(对于 Linux)。然后,根据你的操作系统下载并安装 Minikube。

2.1.1 在 Linux 上安装 Minikube

  1. 下载 Minikube
    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    sudo install minikube-linux-amd64 /usr/local/bin/minikube
    
  2. 启动 Minikube
    minikube start
    

2.1.2 在 macOS 上安装 Minikube

  1. 通过 Homebrew 安装
    brew install minikube
    
  2. 启动 Minikube
    minikube start
    

2.1.3 在 Windows 上安装 Minikube

  1. 下载 Minikube 安装程序:从Minikube 官方网站下载安装程序并运行。
  2. 启动 Minikube:打开 PowerShell 并运行 minikube start

2.2 安装 kubectl

kubectl 是 Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互。

2.2.1 在 Linux 上安装 kubectl

  1. 下载 kubectl
    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
    

2.2.2 在 macOS 上安装 kubectl

  1. 通过 Homebrew 安装
    brew install kubectl
    

2.2.3 在 Windows 上安装 kubectl

  1. 下载 kubectl 安装包:从Kubernetes 官方网站下载安装包并安装。安装完成后,将 kubectl 可执行文件所在路径添加到系统环境变量中。

3. 创建微服务应用

3.1 示例微服务应用 - 简单的图书管理系统

我们以一个简单的图书管理系统为例,该系统包含两个微服务:图书服务(Book Service)和借阅服务(Borrow Service)。

3.1.1 图书服务

图书服务负责管理图书的基本信息,如书名、作者、出版年份等。以下是一个简单的基于 Python Flask 的图书服务示例代码:

from flask import Flask, jsonify

app = Flask(__name__)

books = [
    {
        "id": 1,
        "title": "Python 编程从入门到实践",
        "author": "Eric Matthes",
        "year": 2015
    },
    {
        "id": 2,
        "title": "Effective Java",
        "author": "Joshua Bloch",
        "year": 2008
    }
]


@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

3.1.2 借阅服务

借阅服务负责处理图书的借阅和归还操作。以下是一个基于 Node.js Express 的借阅服务示例代码:

const express = require('express');
const app = express();
const port = 3000;

// 模拟借阅记录
const borrowRecords = [];

app.post('/borrow', (req, res) => {
    const { bookId, userId } = req.body;
    borrowRecords.push({ bookId, userId });
    res.send('Book borrowed successfully');
});

app.post('/return', (req, res) => {
    const { bookId, userId } = req.body;
    const index = borrowRecords.findIndex(record => record.bookId === bookId && record.userId === userId);
    if (index!== -1) {
        borrowRecords.splice(index, 1);
        res.send('Book returned successfully');
    } else {
        res.status(404).send('Borrow record not found');
    }
});

app.listen(port, () => {
    console.log(`Borrow Service listening at http://localhost:${port}`);
});

4. 容器化微服务

4.1 图书服务容器化

为了将图书服务容器化,我们需要创建一个 Dockerfile。在图书服务项目目录下创建一个名为 Dockerfile 的文件,内容如下:

# 使用 Python 官方镜像作为基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制 requirements.txt 和当前目录下的所有文件到工作目录
COPY requirements.txt.
COPY.

# 安装项目依赖
RUN pip install -r requirements.txt

# 暴露 5000 端口
EXPOSE 5000

# 启动应用
CMD ["python", "app.py"]

然后,在项目目录下执行以下命令构建 Docker 镜像:

docker build -t book -service:v1.0.0.

4.2 借阅服务容器化

同样,为借阅服务创建一个 Dockerfile

# 使用 Node.js 官方镜像作为基础镜像
FROM node:14

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package - lock.json 到工作目录
COPY package.json package - lock.json.

# 安装项目依赖
RUN npm install

# 复制当前目录下的所有文件到工作目录
COPY.

# 暴露 3000 端口
EXPOSE 3000

# 启动应用
CMD ["node", "app.js"]

在借阅服务项目目录下执行以下命令构建 Docker 镜像:

docker build -t borrow -service:v1.0.0.

5. 在 Kubernetes 中部署微服务

5.1 创建 Deployment 资源

5.1.1 图书服务 Deployment

在 Kubernetes 中,我们使用 Deployment 来管理微服务的副本。创建一个名为 book - service - deployment.yaml 的文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: book - service - deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: book - service
  template:
    metadata:
      labels:
        app: book - service
    spec:
      containers:
      - name: book - service
        image: book - service:v1.0.0
        ports:
        - containerPort: 5000

在上述文件中,我们定义了一个 Deployment,副本数为 3,选择器匹配标签 app: book - service。Pod 模板中的容器使用我们之前构建的 book - service:v1.0.0 镜像,并暴露 5000 端口。

使用以下命令创建 Deployment:

kubectl apply -f book - service - deployment.yaml

5.1.2 借阅服务 Deployment

创建 borrow - service - deployment.yaml 文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: borrow - service - deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: borrow - service
  template:
    metadata:
      labels:
        app: borrow - service
    spec:
      containers:
      - name: borrow - service
        image: borrow - service:v1.0.0
        ports:
        - containerPort: 3000

定义了借阅服务的 Deployment,副本数为 2。使用以下命令创建 Deployment:

kubectl apply -f borrow - service - deployment.yaml

5.2 创建 Service 资源

5.2.1 图书服务 Service

为了让其他微服务或外部客户端能够访问图书服务,我们需要创建一个 Service。创建 book - service - service.yaml 文件:

apiVersion: v1
kind: Service
metadata:
  name: book - service - service
spec:
  selector:
    app: book - service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000
  type: ClusterIP

上述 Service 使用 ClusterIP 类型,将集群内部流量从端口 80 转发到图书服务容器的 5000 端口。使用以下命令创建 Service:

kubectl apply -f book - service - service.yaml

5.2.2 借阅服务 Service

创建 borrow - service - service.yaml 文件:

apiVersion: v1
kind: Service
metadata:
  name: borrow - service - service
spec:
  selector:
    app: borrow - service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: ClusterIP

同样,为借阅服务创建一个 ClusterIP 类型的 Service。使用以下命令创建 Service:

kubectl apply -f borrow - service - service.yaml

6. 微服务之间的通信

6.1 使用 Service 名称进行通信

在 Kubernetes 集群中,微服务之间可以通过 Service 名称进行通信。例如,如果借阅服务需要调用图书服务获取图书信息,可以通过 book - service - service 这个 Service 名称来访问图书服务。

假设借阅服务需要在处理借阅请求时获取图书信息,在 Node.js 代码中可以使用 axios 库来调用图书服务:

const axios = require('axios');

app.post('/borrow', async (req, res) => {
    const { bookId, userId } = req.body;
    try {
        const response = await axios.get('http://book - service - service/books');
        const book = response.data.find(b => b.id === bookId);
        if (book) {
            borrowRecords.push({ bookId, userId });
            res.send('Book borrowed successfully');
        } else {
            res.status(404).send('Book not found');
        }
    } catch (error) {
        console.error('Error calling book service:', error);
        res.status(500).send('Internal server error');
    }
});

6.2 服务发现机制

Kubernetes 内置了服务发现机制,通过 DNS 来实现。当一个 Service 创建后,Kubernetes 会为其分配一个 DNS 名称。例如,图书服务的 Service 可以通过 book - service - service.default.svc.cluster.local 这个 DNS 名称来访问(default 是命名空间,svc 表示 Service,cluster.local 是集群的 DNS 后缀)。这种机制使得微服务之间的通信更加简单和可靠,无需手动维护服务的 IP 地址。

7. 微服务的扩展与伸缩

7.1 手动扩展 Deployment

Kubernetes 可以轻松地对 Deployment 进行扩展,以应对不同的负载需求。例如,当图书服务的流量增加时,我们可以手动增加图书服务 Deployment 的副本数。

使用以下命令将图书服务的副本数扩展到 5:

kubectl scale deployment book - service - deployment --replicas = 5

7.2 自动伸缩(Horizontal Pod Autoscaler)

Kubernetes 提供了 Horizontal Pod Autoscaler(HPA)来根据资源使用情况自动调整 Deployment 的副本数。

首先,确保你的 Kubernetes 集群启用了 Metrics Server,它为 HPA 提供资源使用数据。

然后,创建一个 HPA 配置文件,例如 book - service - hpa.yaml

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: book - service - hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: book - service - deployment
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70

上述配置表示根据图书服务 Deployment 的 CPU 利用率来自动调整副本数,最小副本数为 3,最大副本数为 10,当 CPU 利用率超过 70% 时增加副本,低于 70% 时减少副本。

使用以下命令创建 HPA:

kubectl apply -f book - service - hpa.yaml

8. 微服务的升级与回滚

8.1 滚动升级 Deployment

假设我们对图书服务进行了更新,例如添加了新的图书字段。我们可以通过更新 Deployment 的镜像来进行滚动升级。

首先,更新图书服务的代码,然后重新构建 Docker 镜像:

docker build -t book - service:v1.1.0.

然后,更新 Deployment 的镜像版本:

kubectl set image deployment/book - service - deployment book - service = book - service:v1.1.0

Kubernetes 会自动进行滚动升级,每次替换一个旧版本的 Pod 为新版本,确保服务的连续性。

8.2 回滚 Deployment

如果在升级过程中发现问题,我们可以回滚到上一个版本。使用以下命令查看 Deployment 的历史版本:

kubectl rollout history deployment/book - service - deployment

然后,使用以下命令回滚到上一个版本:

kubectl rollout undo deployment/book - service - deployment

9. 配置管理

9.1 使用 ConfigMap

ConfigMap 是 Kubernetes 中用于存储配置数据的对象。例如,图书服务可能需要配置数据库连接字符串等信息。

创建一个 book - service - configmap.yaml 文件:

apiVersion: v1
kind: ConfigMap
metadata:
  name: book - service - config
data:
  database - url: "mongodb://localhost:27017/book - db"

在图书服务的 Deployment 中,可以通过以下方式挂载 ConfigMap:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: book - service - deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: book - service
  template:
    metadata:
      labels:
        app: book - service
    spec:
      containers:
      - name: book - service
        image: book - service:v1.0.0
        ports:
        - containerPort: 5000
        env:
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: book - service - config
              key: database - url

9.2 使用 Secret

对于敏感信息,如数据库密码,我们使用 Secret 来管理。创建一个 book - service - secret.yaml 文件:

apiVersion: v1
kind: Secret
metadata:
  name: book - service - secret
type: Opaque
data:
  database - password: <base64 - encoded - password>

在 Deployment 中挂载 Secret:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: book - service - deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: book - service
  template:
    metadata:
      labels:
        app: book - service
    spec:
      containers:
      - name: book - service
        image: book - service:v1.0.0
        ports:
        - containerPort: 5000
        env:
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: book - service - secret
              key: database - password

10. 网络策略

10.1 定义网络策略

网络策略用于控制 Pod 之间的网络流量。例如,我们可以限制只有借阅服务可以访问图书服务。

创建一个 book - service - network - policy.yaml 文件:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: book - service - network - policy
spec:
  podSelector:
    matchLabels:
      app: book - service
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: borrow - service
    ports:
    - protocol: TCP
      port: 5000

上述网络策略表示只有带有 app: borrow - service 标签的 Pod 可以访问带有 app: book - service 标签的 Pod 的 5000 端口。

使用以下命令创建网络策略:

kubectl apply -f book - service - network - policy.yaml

通过以上步骤,我们完成了在 Kubernetes 中实现微服务服务编排的实战过程,从环境搭建、微服务创建与容器化,到部署、通信、扩展、升级以及配置管理和网络策略等方面,全面展示了如何利用 Kubernetes 构建和管理微服务架构。