使用Puppet运行Kubernetes的“Guestbook”例子


在第一篇博文中,讲到Puppet和Kubernetes,介绍了新的关于Kubernetes的Puppet模块并且讲述了关于配置管理和现代分布式集群系统。在这篇文章中,我们通过具体的例子来深入更多细节。

Kubernetes的Hello World示例是一个“Guestbook”应用。它通过使用Kubernetes的RC和services来创建了一个redis的主从配置和web应用的一个负载均衡器。所以,还有什么例子能比这更好的展示新的Kubernetes的Puppet模块呢?

如果你想自己尝试一下,你需要一个可以工作的Kubernetes集群。官方文档写了很多自己搭建的方法;最简单的方法是使用Google的GCE服务。

设置

Kubernetes模块使用kubeclient库调用Kubernetes API。需要先安装这个库,但会根据安装Puppet的方式而有所不同,对于最新版的puppet-agent,你需要运行:
/opt/puppetlabs/puppet/bin/gem install kubeclient --no-ri --no-rdoc

之后通过下面方法来安装模块本身:
puppet module install garethr-kubernetes

最后需要给Puppet提供一个可运行的kubectl配置文件。假定我们使用如下配置来运行Kubernetes:
cp ~/.kube/config ~/.puppetlabs/etc/puppet/kubernetes.conf

接下来我们可以配置Puppet。

在Puppet中描述Kubernetes资源

接下来,演示官方guestbook的例子,使用特定的YAML文件和kubectl命令来创建资源。配置如下:
apiVersion: v1
kind: Service
metadata:
name: redis-master
labels:
app: redis
role: master
tier: backend
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: master
tier: backend

在下面的例子中,你会看到等价的Puppet的配置。首先,明显看到Puppet配置使用同样的结构。它提供了一个低层的接口,对于熟悉Kubernetes的人可以很快识别出。Puppet已经提供了很多方式在这些原始的接口上来构建新的抽象层。

首先创建redis master的 RC。会按流程创建单个Pod来运行redis。
kubernetes_replication_controller { 'redis-master':
ensure   => 'present',
metadata => {
'labels' => {'app' => 'redis', 'role' => 'master', 'tier' => 'backend'},
'namespace' => 'default',
},
spec     => {
'replicas' => 1,
'template' => {
  'metadata' => {
    'labels' => {'app' => 'redis', 'role' => 'master', 'tier' => 'backend'},
  },
  'spec' => {
    'containers' => [
      {
        'image' => 'redis',
        'name' => 'master',
        'ports' => [
          {'containerPort' => 6379, 'protocol' => 'TCP'}
        ],
        'resources' => {
          'requests' => {
            'cpu' => '100m',
            'memory' => '100Mi',
          }
        }
      }
    ]
  }
}
}


我们同样可以使用如下配置文件,来运行创建对应的redis master service。
kubernetes_service { 'redis-master':
ensure   => 'present',
metadata => {
'labels' => {'app' => 'redis', 'role' => 'master', 'tier' => 'backend'},
'namespace' => 'default',
},
spec     => {
'ports' => [
  {'port' => 6379, 'protocol' => 'TCP', 'targetPort' => 6379}
],
'selector' => {
  'app' => 'redis',
  'role' => 'master',
  'tier' => 'backend',
}
}
}
接下来启动redis slave的RC配置,运行两个备份。同样以类似YAML格式的配置来匹配。
kubernetes_replication_controller { 'redis-slave':
ensure   => 'present',
metadata => {
'labels' => {'app' => 'redis', 'role' => 'slave', 'tier' => 'backend'},
'namespace' => 'default',
},
spec     => {
'replicas' => '2',
'template' => {
  'metadata' => {
    'labels' => {'app' => 'redis', 'role' => 'slave', 'tier' => 'backend'}
  },
  'spec' => {
    'containers' => [
      {
        'env' => [{'name' => 'GET_HOSTS_FROM', 'value' => 'dns'}],
        'image' => 'gcr.io/google_samples/gb-redisslave:v1',
        'name' => 'slave',
        'ports' => [
          {'containerPort' => '6379', 'protocol' => 'TCP'}
        ],
        'resources' => {'requests' => {'cpu' => '100m', 'memory' => '100Mi'}},
      }
    ]
  }
}
}


同时创建与生成的Pods对应的Service。
kubernetes_service { 'redis-slave':
ensure   => 'present',
metadata => {
'labels' => {'app' => 'redis', 'role' => 'slave', 'tier' => 'backend'},
'namespace' => 'default',
},
spec     => {
'ports' => [
  {'port' => 6379, 'protocol' => 'TCP'}
],
'selector' => {
  'app' => 'redis',
  'role' => 'slave',
  'tier' => 'backend',
}
}
}
接下来是前端的负载均衡控制器,为web应用提供服务的RC数为3个。
kubernetes_replication_controller { 'frontend':
ensure   => 'present',
metadata => {
'labels' => {'app' => 'guestbook', 'tier' => 'frontend'},
'namespace' => 'default',
},
spec     => {
'replicas' => '3',
'template' => {
  'metadata' => {
    'labels' => {'app' => 'guestbook', 'tier' => 'frontend'}
  },
  'spec' => {
    'containers' => [
      {
        'env' => [{'name' => 'GET_HOSTS_FROM', 'value' => 'dns'}],
        'image' => 'gcr.io/google_samples/gb-frontend:v3',
        'name' => 'php-redis',
        'ports' => [
          {'containerPort' => '80', 'protocol' => 'TCP'}
        ],
        'resources' => {'requests' => {'cpu' => '100m', 'memory' => '100Mi'}},
      }
    ]
  }
}
}


最后为前端的web应用Pod创建一个负载均衡service。

运行实例

以上截取的片段是官方指南中的六个步骤。通过Puppet,我们使用一条命令和一个配置文件就可以创建出所有这些资源。以上所有源代码都可以在示例目录模块找到(https://github.com/garethr/gar ... ok.pp)。

通过Puppet本地测试用例如下所示:
$ puppet apply examples/guestbook.pp --test
Info: Loading facts
Info: Loading facts
Notice: Compiled catalog for pro.local in environment production in 0.33 seconds
Info: Applying configuration version '1448445589'
Info: Checking if frontend exists
Info: Creating kubernetes_service frontend
Notice: /Stage[main]/Main/Kubernetes_service[frontend]/ensure: created
Info: Checking if frontend exists
Info: Creating kubernetes_replication_controller frontend
Notice: /Stage[main]/Main/Kubernetes_replication_controller[frontend]/ensure: created
Info: Checking if redis-master exists
Info: Creating kubernetes_service redis-master
Notice: /Stage[main]/Main/Kubernetes_service[redis-master]/ensure: created
Info: Checking if redis-master exists
Info: Creating kubernetes_replication_controller redis-master
Notice: /Stage[main]/Main/Kubernetes_replication_controller[redis-master]/ensure: created
Info: Checking if redis-slave exists
Info: Creating kubernetes_service redis-slave
Notice: /Stage[main]/Main/Kubernetes_service[redis-slave]/ensure: created
Info: Checking if redis-slave exists
Info: Creating kubernetes_replication_controller redis-slave
Notice: /Stage[main]/Main/Kubernetes_replication_controller[redis-slave]/ensure: created
Notice: Finished catalog run in 2.61 seconds

这里大概会有60s左右的时间完成guestbook所有实例的创建,一旦镜像下载完并且pod启动之后。你可以使用kubectl命令来找到负载均衡服务的IP地址:
$ kubectl get services frontend
NAME           LABELS                                    SELECTOR            IP(S)            PORT(S)
frontend       name=frontend                             name=frontend       10.191.253.158   80/TCP
                                                                         104.197.92.229
$ kubectl describe services frontend | grep "LoadBalancer Ingress"
LoadBalancer Ingress: 104.197.92.229

整理

Puppet声明的模块意味着我们可以做其他有意义的事情,像移除某些特定资源。在这个例子中,我们可以使用简单的配置来清除使用手册应用。对简单的资源,如下所示:
kubernetes_replication_controller { 'redis-master':
ensure => absent,


这个模块的示例目录下有一个完整的配置用来删除所有操作手册应用。就像在本地使用如下命令:
$ puppet apply examples/guestbook-delete.pp --test  ~/Documents/garethr-kubernetes
Info: Loading facts
Info: Loading facts
Notice: Compiled catalog for pro.local in environment production in 0.27 seconds
Info: Applying configuration version '1448445744'
Info: Checking if frontend exists
Info: Deleting kubernetes_service frontend
Notice: /Stage[main]/Main/Kubernetes_service[frontend]/ensure: removed
Info: Checking if frontend exists
Info: Deleting kubernetes_replication_controller frontend
Notice: /Stage[main]/Main/Kubernetes_replication_controller[frontend]/ensure: removed
Info: Checking if redis-master exists
Info: Deleting kubernetes_service redis-master
Notice: /Stage[main]/Main/Kubernetes_service[redis-master]/ensure: removed
Info: Checking if redis-master exists
Info: Deleting kubernetes_replication_controller redis-master
Notice: /Stage[main]/Main/Kubernetes_replication_controller[redis-master]/ensure: removed
Info: Checking if redis-slave exists
Info: Deleting kubernetes_service redis-slave
Notice: /Stage[main]/Main/Kubernetes_service[redis-slave]/ensure: removed
Info: Checking if redis-slave exists
Info: Deleting kubernetes_replication_controller redis-slave
Notice: /Stage[main]/Main/Kubernetes_replication_controller[redis-slave]/ensure: removed
Notice: Finished catalog run in 2.56 seconds

结论

以上只是演示了标准Kubernetes YAML格式和Puppet配置之间的基本相似的特征。我们已经看到仅对Service和RC的支持,但是还支持一些其他模块像Secrets,Volume,Quotas等。

使用Puppet管理Kubernetes的真正意义,在于构建封装和管理Kubernetes的状态。例如:
  • 在以上的配置示例中,我们可以改变值和简单重分配配置(使用Puppet agent来实现)。例如,改变前端控制器的副本数量。
  • 尽管没有修改配置,我们可以重新运行Puppet。在这种情况下,Puppet不会修改任何东西,并会告诉我们所有状态都如预期。
  • 我们也注意到独立的配置有很多重复。使用简化的type,我们可以删掉那些重复的配置,并且把重要的变量作为操作手册的type参数。
  • Puppet语言同样有工作来校验和编写单元测试,像分发和共享可重用模块一样。


原文链接:The Kubernetes Guestbook Example in Puppet(翻译:张怡)

0 个评论

要回复文章请先登录注册