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

本系列文章探讨了企业客户在使用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

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

原文链接:https://dzone.com/articles/kubernetes-demystified-solving-service-dependencie

原文作者:Leona Zhang

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

FFmpeg菜鸡互啄#第2篇#配置VS开发环境

下载FFmpeg 首先是下载FFmpeg的win32库,我用的版本是2.5.2(和其他2.x.x版本应该不会有太大差别)。FFmpeg的官网上好像已经找不到旧版...

4186
来自专栏Kubernetes

Kubernetes DNS Service技术研究

本文主要是对kubernetes 1.2和1.3的DNS Service的内部实现分别进行研究,得出其内部实现框架和交互逻辑,并对它们的实现进行了比较。 Kub...

4039
来自专栏沃趣科技

ASM 翻译系列第十三弹:ASM 高级知识 - Forcing the issue

原作者:Bane Radulovic 译者: 庄培培 审核: 魏兴华 DBGeeK社群联合出品 Forcing the issue ASM中有部分的...

3855
来自专栏Laoqi's Linux运维专列

Ansible自动化编译安装Nginx服务

2275
来自专栏耕耘实录

国内环境Kubernetes v1.12.1的安装与配置

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

1723
来自专栏一场梦

腾讯发布新版QQv8.9.6 可撤回他人消息

1925
来自专栏腾讯云容器服务团队的专栏

K8s Network Policy Controller之Kube-router功能介绍

Network Policy是k8s提供的一种资源,用于定义基于pod的网络隔离策略。它描述了一组pod是否可以与其它组pod,以及其它network endp...

4991
来自专栏Java技术分享

如何解决ajax跨域问题

由 于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决 ajax的...

2228
来自专栏散尽浮华

记录一次redis cluster集群故障-运维笔记

公司的一个系统业务出现故障,提示查询redis失败。查询相关日志,分析过程记录如下:

2575

了解微服务,第6部分:健康检查

随着我们的微服务和它们运营的环境变得越来越复杂,让我们的服务为Docker Swarm提供一种安全检查机制也变得日益重要。因此,我们将在博客系列的第六部分中介绍...

6623

扫码关注云+社区