【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

使用 Kubernetes 来管理 Docker 扩展

  • 2015-10-26
  • 本文字数:10274 字

    阅读完需:约 34 分钟

Kubernetes 是一款开源的项目,管理 Linux 容器集群,并可将集群作为一个单一的系统来对待。其可跨多主机来管理和运行 Docker 容器、提供容器的定位、服务发现以及复制控制。它由 Google 发起,现在得到了如微软、红帽、IBM 和Docker 等众多厂商的支持。

Google 使用容器技术有着超过十年的历史,每周要启动超过2 亿台容器。通过Kubernetes,Google 分享了他们关于容器的专业经验,即创建大规模运行容器的开放平台。

一旦用户开始使用Docker 容器,那么问题就来了,一、如何跨多个Docker 主机扩展和启动容器,且能够在主机间平衡这些容器。二、还需要高度抽象出API 来定义如何从逻辑上组织容器、定义容器池、负载均衡以及关联性。该项目就是为了解决这两个问题而生的。

Kubernetes 仍然处于早期阶段,这也就意味着会有很多新的变化进入到该项目,目前还仅有比较简单的实例,仍需要加入新的功能,但是它正在一步一步地平稳发展,也得到了很多大公司的支持,前途无量。

Kubernetes 概念

Kubernetes 的架构被定义为由一个 master 服务器和多个 minons 服务器组成。命令行工具连接到 master 服务器的 API 端点,其可以管理和编排所有的 minons 服务器,Docker 容器接收来自 master 服务器的指令并运行容器。

  • Master:Kubernetes API 服务所在,多 Master 的配置仍在开发中。
  • Minons:每个具有 Kubelet 服务的 Docker 主机,Kubelet 服务用于接收来自 Master 的指令,且管理运行容器的主机。
  • Pod :定义了一组绑在一起的容器,可以部署在同一 Minons 中,例如一个数据库或者是 web 服务器。
  • Replication controller :定义了需要运行多少个 Pod 或者容器。跨多个 minons 来调度容器。
  • Service:定义了由容器所发布的可被发现的服务/端口,以及外部代理通信。服务会映射端口到外部可访问的端口,而所映射的端口是跨多个 minons 的 Pod 内运行的容器的端口。
  • kubecfg:命令行客户端,连接到 master 来管理 Kubernetes。

(点击图片可放大显示)

Kubernetes 由状态所定义,而不是进程。当你定义了一个 pod 时,Kubernetes 会设法确保它会一直运行。如果其中的某个容器挂掉了,Kubernetes 会设法再启动一个新的容器。如果一个复制控制器定义了 3 份复制,Kubernetes 会设法一直运行这 3 份,根据需要来启动和停止容器。

本文中所用的例子应用是 Jenkins 持续集成服务,Jenkins 是典型的通过主从服务来建立分布式的工作任务的例子。Jenkins 由 jenkins swarm 插件来配置,运行一个 jenkins 主服务和多个 jenkins 从服务,所有的 Jenkins 服务都以 Docker 容器的方式跨多个主机运行。swarm 从服务在启动时连接到 Jenkins 主服务,然后就可以运行 Jenkins 任务了。例子中使用的配置文件可以从Github 上下载到,而该Docker 镜像可以从 casnchez/jenkins-swarm 获取,对于 Jenkins 主服务来说,可以通过 swarm 插件来扩展官方 Jenkins 镜像。对于 jenkins 从服务来说,可以从 csanchez/jenkins-swarm-slave 获取,它只是在 JVM 容器中运行了 jenkins 从服务而已。

创建 Kubernetes 集群

Kubernetes 提供了多个操作系统和云/虚拟化提供商下创建集群的脚本,有 Vagrant(用于本地测试)、Google Compute Engine、Azure、Rackspace 等。

本文所实践的例子就是运行在 Vagrant 之上的本地集群,使用 Fedora 作为操作系统,遵照的是官方入门指南,测试的 Kubernetes 版本是 0.5.4。取代了默认的 3 个 minion(Docker 主机),而是使用了 2 个 minion,两台主机就足以展示 Kubernetes 的能力了,三台有点浪费。

当你下载了 Kubernetes ,然后将至解压后,即可在本地的目录下运行这些示例了。初学者创建集群仅需要一个命令,即./cluster/kube-up.sh。

复制代码
$ export KUBERNETES_PROVIDER=vagrant
$ export KUBERNETES_NUM_MINIONS=2
$ ./cluster/kube-up.sh

获取示例配置文件:

复制代码
$ git clone https://github.com/carlossg/kubernetes-jenkins.git

集群创建的快慢取决于机器的性能和内部的带宽。但是其最终完成不能有任何的错误,而且它仅需要运行一次。

命令行工具

和 Kubernetes 交互的命令行工具叫做 kubecfg,此脚本位于 cluster/kubecfg.sh。

为了检验我们刚才创建的两个 minons 已经启动并运行了,只需运行 kubecfg list minions 命令即可,它的结果会显示 Vagrant 的两台虚拟机。

复制代码
$ ./cluster/kubecfg.sh list minions
Minion identifier
----------
10.245.2.2
10.245.2.3

Pod

在 Kubernetes 的术语中,Jenkins 主服务被定义为一个 pod 。在一个 pod 中可以指定多个容器,这些容器均部署在同一 Docker 主机中,在一个 pod 中的容器的优势在于可以共享资源,例如存储,而且使用相同的网络命名空间和IP 地址。默认的卷是空的目录,类型为emptyDir,它的生存时间就是pod 的生命周期,而并非是指定的容器,所以如果一个容器失效了,但是其持久性的存储仍然在。另外一个卷的类型是hostDir,它是将主机的一个目录挂载到容器中。

在这个具体的Jenkins 示例中,我们所创建的pod 是两个容器,分别是Jenkins 主服务和MySQL,前者作为实例,后者作为数据库。然而我们只需要关心jenkins 主服务容器即可。

为了创建一个Jenkins pod,我们运行定义了Jenkins 容器pod 的kubecfg,使用Docker 镜像csanchez/jenkins-swarm,为了能够访问Jenkins 的Web 界面和从服务的API,我们将主机的端口8080 和50000 映射到容器,以及将/var/jenkins_home 挂载为卷。读者可从 Github 下载到示例代码。

Jenkins Web 界面的 pod(pod.json)的定义如下:

复制代码
{
"id": "jenkins",
"kind": "Pod",
"apiVersion": "v1beta1",
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "jenkins",
"containers": [
{
"name": "jenkins",
"image": "csanchez/jenkins-swarm:1.565.3.3",
"ports": [
{
"containerPort": 8080,
"hostPort": 8080
},
{
"containerPort": 50000,
"hostPort": 50000
}
],
"volumeMounts": [
{
"name": "jenkins-data",
"mountPath": "/var/jenkins_home"
}
]
}
],
"volumes": [
{
"name": "jenkins-data",
"source": {
"emptyDir": {}
}
}
]
}
},
"labels": {
"name": "jenkins"
}
}

然后使用下面命令来创建:

复制代码
$ ./cluster/kubecfg.sh -c kubernetes-jenkins/pod.json create pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 <unassigned> name=jenkins Pending</unassigned>

这需要等待一段时间,具体时间的长短要视你的网络而定,因为它会从 Docker Hub 上下载 Docker 镜像到 minion,我们可以查看它的状态,以及在那个 minion 中启动了。

复制代码
$ ./cluster/kubecfg.sh list pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 10.0.29.247/10.0.29.247 name=jenkins Running

如果我们使用 SSH 登录到 minion 中,此 minion 即是 pod 被分配到的 minion-1 或 minion-2,我们就可以看到 Docker 按照所定义的那样启动起来了。其中还包括了用于 Kubernetes 内部管理的容器(kubernetes/pause 和 google/cadvisor)。

复制代码
$ vagrant ssh minion-2 -c "docker ps"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f6825a80c8a google/cadvisor:0.6.2 "/usr/bin/cadvisor" 3 minutes ago Up 3 minutes k8s_cadvisor.b0dae998_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_28df406a
5c02249c0b3c csanchez/jenkins-swarm:1.565.3.3 "/usr/local/bin/jenk 3 minutes ago Up 3 minutes k8s_jenkins.f87be3b0_jenkins.default.etcd_901e8027-759b-11e4-bfd0-0800279696e1_bf8db75a
ce51fda15f55 kubernetes/pause:go "/pause" 10 minutes ago Up 10 minutes k8s_net.dbcb7509_0d38f5b2-759c-11e4-bfd0-0800279696e1.default.etcd_0d38fa52-759c-11e4-bfd0-0800279696e1_e4e3a40f
e6f00165d7d3 kubernetes/pause:go "/pause" 13 minutes ago Up 13 minutes 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp k8s_net.9eb4a781_jenkins.default.etcd_901e8027-759b-11e4-bfd0-0800279696e1_7bd4d24e
7129fa5dccab kubernetes/pause:go "/pause" 13 minutes ago Up 13 minutes 0.0.0.0:4194->8080/tcp k8s_net.a0f18f6e_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_659a7a52

还有,我们一旦拿到了容器的 ID,就可以通过如 vagrant ssh minion-1 -c "docker logs cec3eab3f4d3"这样的命令来查看容器的日志了。

我们也可以访问 Jenkins 的 Web 界面,至于要访问的 URL 是 http://10.245.2.2:8080/ 还是 http://10.0.29.247:8080/,要看用到了那个 minion。

服务发现

Kubernetes 支持定义服务,一种为容器使用发现和代理请求到合适的 pod 的方法。下面示例使用了 service-http.json 文件来创建一个服务,其将 id 为 jenkins 指向了贴有标签为 name=jenkins 的 pod。而标签是在如上面 pod 的定义中所声明的。且将端口 8888 重定向到容器的 8080 。

复制代码
{
"id": "jenkins",
"kind": "Service",
"apiVersion": "v1beta1",
"port": 8888,
"containerPort": 8080,
"selector": {
"name": "jenkins"
}
}

使用 kubecfg 来创建服务:

复制代码
$ ./cluster/kubecfg.sh -c kubernetes-jenkins/service-http.json create services
Name Labels Selector IP Port
---------- ---------- ---------- ---------- ----------
jenkins name=jenkins 10.0.29.247 8888

每个服务都会被分配一个唯一的 IP 地址,且此 IP 地址会伴随服务的整个生命周期。如果我们有多个 pod 匹配服务的定义,服务就会在所有它们之上提供负载均衡。

服务的另外一个特性是可以为由 Kubernetes 来运行的容器设置一些环境变量,使其可以连接到该服务容器,这和运行已链接的 Docker 容器有些类似,它可以帮助我们从若干从服务中找到 Jenkins 主服务。

复制代码
JENKINS_PORT='tcp://10.0.29.247:8888'
JENKINS_PORT_8080_TCP='tcp://10.0.29.247:8888'
JENKINS_PORT_8080_TCP_ADDR='10.0.29.247'
JENKINS_PORT_8080_TCP_PORT='8888'
JENKINS_PORT_8080_TCP_PROTO='tcp'
JENKINS_SERVICE_PORT='8888'
SERVICE_HOST='10.0.29.247'

在此示例中,我们还需要打开端口 50000,Jenkins swarm 插件需要用这个端口。我们创建另外一个 service-slave.json 文件,这样 Kubernetes 就可以重定向端口到 Jenkins 服务容器了。

复制代码
{
"id": "jenkins-slave",
"kind": "Service",
"apiVersion": "v1beta1",
"port": 50000,
"containerPort": 50000,
"selector": {
"name": "jenkins"
}
}

再次使用 kubecfg 来创建:

复制代码
$ ./cluster/kubecfg.sh -c kubernetes-jenkins/service-slave.json create services
Name Labels Selector IP Port
---------- ---------- ---------- ---------- ----------
jenkins-slave name=jenkins 10.0.86.28 50000

列出所有可用的已经定义的服务,包括一些 Kubernetes 内部的服务:

复制代码
$ ./cluster/kubecfg.sh list services
Name Labels Selector IP Port
---------- ---------- ---------- ---------- ----------
kubernetes-ro component=apiserver,provider=kubernetes 10.0.22.155 80
kubernetes component=apiserver,provider=kubernetes 10.0.72.49 443
jenkins name=jenkins 10.0.29.247 8888
jenkins-slave name=jenkins 10.0.86.28 50000

复制控制器

复制控制器允许在多个 minion 中运行多个 pod。Jenkins 的从服务以此方式来运行,可以确保一直有一个运行 Jenkins 任务的从服务池。

创建 replication.json,所定义的内容如下:

复制代码
{
"id": "jenkins-slave",
"apiVersion": "v1beta1",
"kind": "ReplicationController",
"desiredState": {
"replicas": 1,
"replicaSelector": {
"name": "jenkins-slave"
},
"podTemplate": {
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "jenkins-slave",
"containers": [
{
"name": "jenkins-slave",
"image": "csanchez/jenkins-swarm-slave:1.21",
"command": [
"sh", "-c", "/usr/local/bin/jenkins-slave.sh
-master http://$JENKINS_SERVICE_HOST:$JENKINS_SERVICE_PORT -tunnel
$JENKINS_SLAVE_SERVICE_HOST:$JENKINS_SLAVE_SERVICE_PORT -username
jenkins -password jenkins -executors 1"
]
}
]
}
},
"labels": {
"name": "jenkins-slave"
}
}
},
"labels": {
"name": "jenkins-slave"
}
}

podTemplate 一节允许和 pod 的定义进行一样的配置。在此示例中,我们打算让 Jenkins 从服务自动地连接到 Jenkins 主服务,而不是利用 Jenkins 主服务的多播发现。要实现此想法,我们需要执行 jenkins-slave.sh 命令,指定参数 -master,从而实现在 Kubernetes 中让从服务连接到主服务。注意,上述配置文件中,我们使用了 Kubernetes 所提供的为 Jenkins 服务定义的环境变量(JENKINS_SERVICE_HOST 和 JENKINS_SERVICE_PORT)。此方法中镜像的命令覆盖了容器的配置,为的是利用已经下载好的镜像。这也同样可以在 pod 的定义中去实现。

使用 kubecfg 来创建副本:

复制代码
$ ./cluster/kubecfg.sh -c kubernetes-jenkins/replication.json create replicationControllers
Name Image(s) Selector Replicas
---------- ---------- ---------- ----------
jenkins-slave csanchez/jenkins-swarm-slave:1.21 name=jenkins-slave 1

现在执行 pod 列表,可以看到新的 pod 已经创建,其数量是由我们刚刚所定义的复制控制器所决定的。

复制代码
$ ./cluster/kubecfg.sh list pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 10.245.2.3/10.245.2.3 name=jenkins Running
07651754-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.2/10.245.2.2 name=jenkins-slave Pending

第一次运行的 jenkins-swarm-slave 镜像是 minion 从 Docker 仓库下载下来的,但是一段时间之后(这取决于你的互联网连接),Jenkins 从服务会自动连接到 Jenkins 主服务。登录到 Jenkins 从服务所在的服务器,docker ps 会显示出运行中的容器和 Docker 的日志,这能够帮助你来调试容器启动中出现的问题。

复制代码
$ vagrant ssh minion-1 -c "docker ps"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
870665d50f68 csanchez/jenkins-swarm-slave:1.21 "/usr/local/bin/jenk About a minute ago Up About a minute k8s_jenkins-slave.74f1dda1_07651754-4f88-11e4-b01e-0800279696e1.default.etcd_11cac207-759f-11e4-bfd0-0800279696e1_9495d10e
cc44aa8743f0 kubernetes/pause:go "/pause" About a minute ago Up About a minute k8s_net.dbcb7509_07651754-4f88-11e4-b01e-0800279696e1.default.etcd_11cac207-759f-11e4-bfd0-0800279696e1_4bf086ee
edff0e535a84 google/cadvisor:0.6.2 "/usr/bin/cadvisor" 27 minutes ago Up 27 minutes k8s_cadvisor.b0dae998_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_588941b0
b7e23a7b68d0 kubernetes/pause:go "/pause" 27 minutes ago Up 27 minutes 0.0.0.0:4194->8080/tcp k8s_net.a0f18f6e_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0.default.file_cadvisormanifes12uqn2ohido76855gdecd9roadm7l0_57a2b4de

复制控制器可以自动的调整任何想要的副本数量:

复制代码
$ ./cluster/kubecfg.sh resize jenkins-slave 2

再次列出 pod 的话,可以看到每个副本是在哪里运行的。

复制代码
$ ./cluster/kubecfg.sh list pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
07651754-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.2/10.245.2.2 name=jenkins-slave Running
a22e0d59-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.3/10.245.2.3 name=jenkins-slave Pending
jenkins csanchez/jenkins-swarm:1.565.3.3 10.245.2.3/10.245.2.3 name=jenkins Running

调度

目前默认的调度是随机的,但是基于资源的调度很快就将实现了。在写作本文的时候,基于内存和 CPU 利用率的调度还有一些没有修复的问题。还有整合 Apache Mesos 的调度也在紧锣密鼓的进行中。Apache Mesos 是一款分布式系统的框架,提供了资源管理的 API,和跨整个数据中心或云环境的调度。

自愈

使用 Kubernetes 的一大好处就是其能够自动管理和修复容器。

如果运行 Jenkins 服务的容器由于某些原因宕机了,比如说进程崩溃了,那么 Kubernetes 就会得到通知,并会在几秒钟之后创建一个新的容器。

复制代码
$ vagrant ssh minion-2 -c 'docker kill `docker ps | grep csanchez/jenkins-swarm: | sed -e "s/ .*//"`'
51ba3687f4ee
$ ./cluster/kubecfg.sh list pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 10.245.2.3/10.245.2.3 name=jenkins Failed
07651754-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.2/10.245.2.2 name=jenkins-slave Running
a22e0d59-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.3/10.245.2.3 name=jenkins-slave Running

稍后再执行 list pod 命令,一般不会超过 1 分钟,会看到如下内容:

复制代码
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 10.245.2.3/10.245.2.3 name=jenkins Running
07651754-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.2/10.245.2.2 name=jenkins-slave Running
a22e0d59-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.3/10.245.2.3 name=jenkins-slave Running

将 Jeknkis 的数据目录以卷的形式运行,我们保证了在容器宕机之后仍然能够保留数据,所以不会丢失任何 Jenkins 的任务或者是已经创建好的数据。而且因为 Kubernetes 在每个 minion 都代理了服务,Jenkins 从服务会自动连接到 Jenkins 主服务,而根本无须关心它是在哪里运行的!而且 Jenkins 从服务容器宕掉,系统也会自动创建新的容器,服务发现会将之自动加入到 Jenkins 服务池中。

如果发生了更加严重的情况,比如 minion 挂掉了,Kubernetes 目前还没能提供将现有容器重新调度到其它仍在运行的 minion 中的能力,它仅仅会显示某个 pod 失效,如下所示:

复制代码
$ vagrant halt minion-2
==> minion-2: Attempting graceful shutdown of VM...
$ ./cluster/kubecfg.sh list pods
Name Image(s) Host Labels Status
---------- ---------- ---------- ---------- ----------
jenkins csanchez/jenkins-swarm:1.565.3.3 10.245.2.3/10.245.2.3 name=jenkins Failed
07651754-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.2/10.245.2.2 name=jenkins-slave Running
a22e0d59-4f88-11e4-b01e-0800279696e1 csanchez/jenkins-swarm-slave:1.21 10.245.2.3/10.245.2.3 name=jenkins-slave Failed

清理

kubecfg 还提供了一些命令来停止和删除复制控制器、pod、以及服务等。

要停止复制控制器,设置复制数为 0,所有 Jenkins 从服务的容器都会被终止:

复制代码
$ ./cluster/kubecfg.sh stop jenkins-slave

删除它:

复制代码
$ ./cluster/kubecfg.sh rm jenkins-slave

删除 Jenkins 服务 Pod,Jenkins 主服务的容器会被终止:

复制代码
$ ./cluster/kubecfg.sh delete pods/jenkins

删除服务:

复制代码
$ ./cluster/kubecfg.sh delete services/jenkins
$ ./cluster/kubecfg.sh delete services/jenkins-slave

总结

Kubernetes 还是一个尚处于早期的项目,但是极有希望来管理 Docker 的跨服务器部署以及简化执行长时间运行和分布式的 Docker 容器。通过抽象基础设施概念,定义状态而不是进程,它提供了集群的简单定义,包括脱离管理的自我修复能力。简而言之,Kubernetes 让 Docker 的管理更加的轻松。

关于作者

Carlos Sanchez在自动化、软件开发质量、QA 以及运维等方面有超过 10 年的经验,范围涉及从构建工具、持续集成到部署自动化,DevOps 最佳实践,再到持续交付。他曾经为财富 500 强的公司实施过解决方案,在多家美国的创业公司工作过,最近任职的公司叫做 MaestroDev,这也是他一手创建的公司。Carlos 曾经在世界各地的各种技术会议上作演讲,包括 JavaOne、EclipseCON、ApacheCON、JavaZone、Fosdem 和 PuppetConf。他非常积极的参与开源,是 Apache 软件基金会的成员,同时也是其它一些开源团体的成员,为很多个开源项目做过贡献,比如 Apache Maven、Fog 和 Puppet。

查看英文原文: Scaling Docker with Kubernetes


感谢夏雪对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-10-26 14:3212085
用户头像

发布了 33 篇内容, 共 11.6 次阅读, 收获喜欢 13 次。

关注

评论

发布
暂无评论
发现更多内容

【笔记】学《郭东白的架构课》:访谈|对话于冰(上)

术子米德

架构师成长笔记

电商系统微服务化

皓月

「架构实战营」

虎年就要玩虎符 春节就要瓜分虎符虎年大礼包

区块链前沿News

Hoo虎符 Hoo 虎年 春节活动

快递,菜鸟驿站,直播购物:老年人的电商之墙

脑极体

如何写好一个Java方法?

蜜糖的代码注释

Java 后端开发 写好代码

Microchip发布具有强大编程和调试功能的新型在线仿真器(ICE)

Geek_2d6073

模块六作业

黄秀明

「架构实战营」

双龙贺岁,龙蜥 LoongArch GA 版正式发布

OpenAnolis小助手

Linux 开源 新年

架构训练营 week8 作业

红莲疾风

「架构实战营」

模块六 - 电商系统微服务设计

圈圈gor

架构实战营 「架构实战营」

openLooKeng助力中移在线获“ICT优秀案例”

openLooKeng

【笔记】学《郭东白的架构课》:访谈|对话于冰(下)

术子米德

架构师成长笔记

如何系统分析项目的干系人?

石云升

项目管理 1月月更

ReactNative进阶(四十):应用 ListView 实现分组列表

No Silver Bullet

ListView React Native 1月月更

并发不是并行

en

再见,Microsoft Academic——你好,开放式研究基础设施?

DisonTangor

搜索引擎

【笔记】学《郭东白的架构课》:访谈|对话于冰(中)

术子米德

架构师成长笔记

建一座国际连锁「商场」:openEuler 的雄心与蓝图 | 开源访谈《源创者说》首播

科技热闻

openLooKeng算子接口和执行流程

openLooKeng

建木持续集成平台v2.2.1发布

Jianmu

DevOps 持续集成 CI/CD

(1-24/24)awesome「结构」

mtfelix

300天创作 2022Y300P

第六节:SpingBoot基本配置一

入门小站

springboot java

LabVIEW播放提示声音或者音乐

不脱发的程序猿

LabVIEW 播放提示声音或者音乐

ReactNative进阶(四十二):面试必备:2022 ReactNative 经典面试题总结(含答案)

No Silver Bullet

面试题 1月月更 ReactNative

Hoo虎符研究院 | 币圈后浪 BreederDAO区块链游戏的NFT工厂

区块链前沿News

虎符 Hoo 虎符交易所

Go 语言快速入门指南:Go 实现简易Web应用

宇宙之一粟

Go web服务器 Go 语言 1月月更

openLooKeng | Oracle update和delete支持简介及实现

openLooKeng

Spark合并Iceberg小文件内存溢出问题定位和解决方案

漫长的白日梦

spark iceberg 小文件

在线时间戳计算时间差

入门小站

工具

拆分电商系统为微服务

tony

ReactNative进阶(四十一):应用 FlatList 实现分组列表

No Silver Bullet

1月月更 ReactNative FlatList

使用Kubernetes来管理Docker扩展_DevOps & 平台工程_Carlos Sanchez_InfoQ精选文章