首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes揭秘:解决服务依赖问题

Kubernetes揭秘:解决服务依赖问题

作者头像
February
修改2018-11-09 17:09:53
4.4K1
修改2018-11-09 17:09:53
举报
文章被收录于专栏:技术翻译技术翻译技术翻译

本系列文章探讨了企业客户在使用Kubernetes时遇到的一些常见问题。Container Service客户经常提出的一个问题是,“我如何处理服务之间的依赖关系?”

在应用程序中,组件依赖性指的是中间件服务和业务服务。在传统的软件部署方法中,必须按特定顺序完成应用程序启动和停止任务。

当使用Kubernetes,Docker Swarm和其他容器编排技术在分布式环境中部署应用程序时,不同的组件会同时启动,因此无法确保某个启动顺序。此外,当应用程序运行时,它们所依赖的服务可能会失败或被迁移。因此,解决容器之间的服务依赖性是客户经常提出的问题。

方法1:检查应用程序中的依赖项

我们可以在应用程序启动逻辑中添加服务依赖性检查逻辑。如果无法访问应用程序所需的服务,则会重试该服务。如果在经过一定次数的重试后服务仍然无法访问,则应用程序会自动放弃。根据容器的重启策略,Kubernetes和Docker等待一段时间后再自动放弃。

在下文中,我们使用一个简单的Golang应用程序作为示例来检查MySQL服务依赖性是否已准备就绪。

   ...
    // Connect to database.
    hostPort := net.JoinHostPort(config.Host, config.Port)
    log.Println("Connecting to database at", hostPort)
    dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?timeout=30s",
        config.Username, config.Password, hostPort, config.Database)
    db, err = sql.Open("mysql", dsn)
    if err != nil {
        log.Println(err)
    }
    var dbError error
    maxAttempts := 20
    for attempts := 1; attempts <= maxAttempts; attempts++ {
        dbError = db.Ping()
        if dbError == nil {
            break
        }
        log.Println(dbError)
        time.Sleep(time.Duration(attempts) * time.Second)
    }
    if dbError != nil {
        log.Fatal(dbError)
    }
    log.Println("Application started successfully.")
    ...

“快速失败”是契约式设计的一项重要原则,有助于确保系统的稳健性和可预测性。在上面的代码中,如果重试机制失败,则报告log.Fatal(dbError)并且该过程结束。此外,K8S和Docker容器重新启动回滚功能可确保系统资源不会因重复尝试访问应用程序依赖项而失败。

方法2:独立服务依赖检查逻辑

在现实世界中,一些遗留应用程序和框架无法调整。因此,我们希望将其检查策略和应用程序逻辑分离。

一种常见方法是在容器的Dockerfile启动脚本中添加相关的服务依赖性检查逻辑。有关此方法的详细信息,请参阅此Docker文档。另一种方法是使用Kubernetes pod机制本身来添加依赖性检查逻辑。

在开始之前,我们必须了解pod生命周期。

首先,pod包含三种类型的容器:

  1. 基础设施容器:这是着名的暂停容器。
  2. Init容器:这是一个初始化容器,通常用于初始化和准备应用程序。只有在等待所有初始化容器完成运行后,应用程序容器才能启动。
  3. 主容器:这是一个应用程序容器。

Kubernetes的最佳实践通常依赖于初始化容器来检查服务依赖性。我们使用以下WordPress示例来说明如何完成此操作。

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None
  ports:
  - name: mysql
    port: 3306
  selector:
    app: mysql
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  ports:
  - name: wordpress
    port: 80
    targetPort: 80
  selector:
    app: wordpress
  type: NodePort
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  serviceName: mysql 
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ALLOW_EMPTY_PASSWORD
          value: "true"
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping"]
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            # Check we can execute queries over TCP (skip-networking is off).
            command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
          initialDelaySeconds: 5
          periodSeconds: 2
          timeoutSeconds: 1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - name: wordpress
        image: wordpress:4
        ports:
        - containerPort: 80
        env:
        - name: WORDPRESS_DB_HOST
          value: mysql
        - name: WORDPRESS_DB_PASSWORD
          value: ""
      initContainers:
      - name: init-mysql
        image: busybox
        command: ['sh', '-c', 'until nslookup mysql; do echo waiting for mysql; sleep 2; done;']

在WordPress部署窗格定义中,我们添加了initContainers。这将检查是否可以解析MySQL域名以确定MySQL服务依赖性是否已准备就绪。

与此同时,我们在MySQL StatefulSet中引入了一个readinessProbelivenessProbe以确定MySQL进程是否已为业务做好准备。在K8S中,只要pod是健康的,它就可以执行ClusterIP访问或DNS解析。

$ kubectl create -f wordpress.yaml
service "mysql" created
service "wordpress" created
statefulset "mysql" created
deployment "wordpress" created
$ kubectl get pods
NAME                         READY     STATUS     RESTARTS   AGE
mysql-0                      0/1       Running    0          5s
wordpress-797655cf44-w4p87   0/1       Init:0/1   0          5s
$ kubectl get pods
NAME                         READY     STATUS     RESTARTS   AGE
mysql-0                      1/1       Running    0          11s
wordpress-797655cf44-w4p87   0/1       Init:0/1   0          11s
$ kubectl get pods
NAME                         READY     STATUS            RESTARTS   AGE
mysql-0                      1/1       Running           0          14s
wordpress-797655cf44-w4p87   0/1       PodInitializing   0          14s
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
mysql-0                      1/1       Running   0          17s
wordpress-797655cf44-w4p87   1/1       Running   0          17s
$ kubectl describe pods wordpress-797655cf44-w4p87
...

注意:

  1. 活动探测:此探测主要用于确定容器是否处于运行状态。例如,它可以检测服务死锁,响应缓慢和其他情况。
  2. 准备探针:此探针主要用于确定服务是否已正常工作。
  3. 准备探针不能在init容器中使用。
  4. 如果pod重新启动,则必须再次运行其所有init容器。

结论

本文讨论了用于检查服务依赖性的常用解决方案,并提供了一个示例来演示如何使用init容器,活动性和就绪性探针以及其他服务运行状况检查和依赖性检查功能。

Kubernetes提供灵活的pod生命周期管理功能。由于篇幅限制,我们没有讨论postStart,preStop和其他生命周期曲线。

原文标题《Kubernetes Demystified: Solving Service Dependencies》

作者:Leona Zhang

译者:February

不代表云加社区观点,更多详情请查看原文链接

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方法1:检查应用程序中的依赖项
  • 方法2:独立服务依赖检查逻辑
  • 结论
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档