【编者的话】Rimas Mocevicius是云计算, CoreOS , Kubernetes , DEIS和应用程序容器解决方案架构师 。CoreOS Essentials一书作者。目前就职于DEIS。本文是其发表在DEIS上的官方博客,介绍Kubernetes的系列教程的第一篇。
Kubernetes 是在群集中管理跨多台主机容器化应用的开源系统。
Kubernetes提供了应用部署,调度,更新,维护和扩缩的机制。 Kubernetes的一个重要特点是,它可以主动管理的容器,以确保集群的状态持续匹配用户的意图。
Kubernetes使您可以通过扩缩或推出新功能快速响应客户的需求。它还允许你最大限度使用硬件资源。
Kubernetes是:
- _精益的_:轻量级的,简单,操作方便
- _便携的_:公开的,私有的,混合的多种云方式
- _可扩展的_:模块化,可插拔,插件化,可组合并且可工具化
- _自愈性_:自动部署,自动重启,自动复制
Kubernetes是建立在 十五年来谷歌运行大规模生产系统的经验 ,并结合了来自社区的顶级创意和实践。
Kubernetes支持 Docker 和 rkt 容器,更多的容器类型将在未来予以支持。
在这篇短文里,我们会从基本要素介绍Kubernetes。
让我们先从基本的组成部分开始。
kubectl实用程序可以与Kubernetes集群管理器交互。例如,您可以添加和删除节点,Pod,复制控制器和服务。你也可以检查它们的状态,等等。
欲了解更多信息,请参阅 文档 。
群集是一组物理机或虚拟机(或两者)与使用Kubernetes运行应用程序等基础资源的总和。
在下图中,我们可以看到一组不同种类的用户指定的容器都整齐地并自动打包成Kubernetes可用节点。
我们可以使用cluster-info命令获取集群的基本信息。
下面是例子:
$ kubectl cluster-info
Kubernetes master is running at http://172.19.17.99:8080
Kube-dns is running at http://172.19.17.99:8080/api/v1/proxy/namespaces/kube-system/services/kube-dns
KubeUI is running at http://172.19.17.99:8080/api/v1/proxy/namespaces/kube-system/services/kube-ui
Kubernetes控制面板被分成多个组件。这些组件协同工作以提供 集群的统一视图 。
所有的持久状态数据存储在etcd集群中。它提供了一种分布式的方式来可靠地存储配置数据。
主服务是一套主要的Kubernetes控制服务,通常运行在一台服务器上。如果需要高可用性,可在负载均衡器之后运行多台服务器。
主服务包括以下几个部分:
换句话说,API服务器验证并配置(通过命令)pod,服务,和复制控制器的数据。它还分配pod到服务节点和同步pod的配置信息。
换句话说,controller manager监视etcd中的复制任务并使用API来保证所需的状态。
一个节点(有时称为工作节点)是运行Kubernetes服务用以调度Pod的一个物理或虚拟机。
节点可以被控制面板管理。
Kubernetes在每个节点上运行的服务包括:
你可以通过下面的命令获取节点运行情况列表:
$ kubectl get nodes
NAME LABELS STATUS
172.19.17.99 kubernetes.io/hostname=172.19.17.99 Ready
Kubernetes通过配置文件(称为 _manifests_),它可以是YAML或JSON格式。
命名空间就像一个资源名称的前缀。命名空间帮助不同的项目,环境(例如,开发和生产),团队或客户共享同一个集群。它能够阻止名称冲突。
命名空间可以通过配置文件创建。
创建一个命名为 development-ns.yaml
的文件,并写入以下内容:
kind: "Namespace"
apiVersion: "v1"
metadata:
name: "development"
labels:
name: "development"
然后可以运行下面的命令创建新的命名空间:
$ kubectl create -f development-ns.yaml
namespaces/development
去查看已经存在的命名空间,运行:
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
development name=development Active
欲了解更多有关命名空间的内容,请参阅 文档 。
_Pod_是一组并置的应用容器,这些容器是共享磁盘卷的。
Pod是可以被创建,调度,并与Kubernetes管理最小部署单元。Pod可以单独创建。由于Pods没有受管的生命周期,如果他们进程死掉了,他们将不会重新创建。出于这个原因,建议您使用复制控制器(我们将在后面介绍),即使你创造了单独的Pod。
所有在Pod的应用使用相同的网络命名空间,IP地址及端口空间。他们可以找到并互相使用 localhost
沟通。每个Pod有一个与跨网络的其他物理计算机和容器充分沟通的扁平网络共享命名空间中的IP地址。
让我们为一个nginx网络容器创建一个简单的Pod定义。
创建一个命名为 nginx.yaml
的文件,并写入下列内容:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx-server
image: nginx
ports:
- containerPort: 80
在这个文件中:
Name
是容器的名称 image
是将要使用的Docker镜像的名称 containerPort
对外暴露容器的端口,这样我们可以通过Pod的IP地址与nginx服务器通信 定义在镜像中的 entrypoint 默认会被运行。随着我们的nginx镜像,该命令运行nginx。
让我们通过运行下列命令来创建Pod
$ kubectl create -f nginx.yaml
pods/nginx
就这么简单!
你可以通过下列命令检查创建是否生效:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 1m
哦了。这里,我们看见一分钟之前创建的nginx的Pod了。
我们可以继续检查将要运行的Pod的资源状况:
$ kubectl describe pod nginx
Name: nginx
Namespace: default
Image(s): nginx
Node: 172.19.17.99/172.19.17.99
Labels: <none>
Status: Running
Reason:
Message:
IP: 10.244.3.2
Replication Controllers: <none>
Containers:
nginx:
Image: nginx
State: Running
Started: Sat, 29 Aug 2015 18:23:15 +0100
Ready: True
Restart Count: 0
Conditions:
Type Status
Ready True
并且我们可以删除该Pod:
$ kubectl delete pod nginx
pods/nginx
看见了吧,它生效了:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
欲了解更多关于Pod的内容,请参阅 文档 。
_复制控制器_管理Pod的生命周期。它们保证指定数量的Pod在任何给定的时间都在运行。他们通过创建或删除Pod做到这一点。出于这个原因,建议您使用复制控制器,即使你创造了单独的Pod。
让我们为我们以前使用nginx的Pod创建复制控制器。
创建 nginxrc.yaml
文件,并写入:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
现在创建该文件复制控制器:
$ kubectl create -f nginxrc.yaml
replicationcontrollers/my-nginx
我们可以看到有多少副本:
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
my-nginx nginx nginx app=nginx 1
我们可以很容易地扩展Pod:
$ kubectl scale --replicas=3 rc my-nginx
并检查它是否生效:
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
my-nginx nginx nginx app=nginx 3
在这里,我们看到在复制控制器将Pod从一个副本扩展为三个副本。
复制控制器将保证特定数量的副本将在任何时候都可以运行。
下图展示了复制管理器如何工作的:
正如你所看到的,它知道有三个标签为nginx的Pod。并监视着这些Pod,准备在必要时创建一个。
欲了解更多关于复制控制器的内容,请参阅 文档 。
服务为一组Pod提供单一稳定的名称和地址。他们作为基本负载均衡器而存在。
Pod大多数被设计为长期运行的,但一旦单个进程死亡,Pod也跟着退出。如果Pod退出,复制控制器使用新的Pod替换它。每个Pod都有自己专用的IP地址,这使得容器具有相同的端口,即使他们共享相同的主机。但每次Pod由复制控制器启动,Pod将获取一个新的IP地址。
这是服务真正其作用的地方。服务附加到一个复制控制器。每个服务被分配了虚拟IP地址,它保持恒定不变。只要我们知道服务IP地址,服务本身将跟踪由复制控制器创建的Pod,并将请求分发给它们。
现在让我们为 my-nginx
复制控制器创建一个服务。
创一个 nginxsvc.yaml
文件,并写入:
apiVersion: v1
kind: Service
metadata:
name: nginxsvc
labels:
app: nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
app: nginx
现在我们可以运行下列命令创建服务:
$ kubectl create -f nginxsvc.yaml
并检查其是否工作:
$ kubectl get svc nginxsvc
NAME LABELS SELECTOR IP(S) PORT(S)
nginxsvc app=nginx app=nginx 10.100.168.74 80/TCP
因为在Kubernetes群集中的每个节点都运行一个kube-proxy,它监视Kubernetes API服务器的添加和删除动作。对于每一个新的服务,kube-proxy打开本地节点上的(随机选择)端口。到该端口的任何连接被代理到对应后端一个Pod中。
下图展示了 nginxsvc
如何工作的:
正如你所看到的,进入HTTP端口80的请求在到达 nginxsvc
服务后被代理到三个 nginx
的Pod中的一个上。
欲了解更多关于服务的内容,请参阅 文档 。
标签用于组织和选择基于键值对的对象组。
它们被用于每一个Kubernetes组件。例如:复制控制器使用他们做服务发现。
让我们看看标签如何运用在链接复制控制器my-nginx和 nginxsvc
服务。
my-nginx
复制控制器配置包括如下:
...
metadata:
labels:
app: nginx
...
app
标签设置给 nginx
。
这种标签用于我们的 nginxsvc
服务配置:
...
selector:
app: nginx
...
此标签用于链接服务和复制控制器。
你可以运行下列命令查看服务正在使用那一个选择器:
$ kubectl get svc nginxsvc
NAME LABELS SELECTOR IP(S) PORT(S)
nginxsvc app=nginx app=nginx 10.100.168.74 80/TCP
欲了解更多关于标签的内容,请参阅 文档 。
在Kubernetes的短片教程的第一部分,我们看了kubectl,集群,控制面板,命名空间,Pod,服务,复制控制器和标签。
在第二部分,我们将涉及卷,加密,滚动更新和Helm。
===========================================译者介绍,当当网架构师,开源数据库分库分表中间件作者。目前从事Docker相关调研工作。