3.2 Pod的基本用法
在对Pod的用法进行说明之前,有必要先对Docker容器中应用的运行要求进行说明。
在使用Docker时,可以使用docker run命令创建并启动一个容器。而在Kubernetes系统中对长时间运行容器的要求是:其主程序需要一直在前台执行。如果我们创建的Docker镜像的启动命令是后台执行程序,例如Linux脚本:
nohup ./start.sh &
则在kubelet创建包含这个容器的Pod之后运行完该命令,即认为Pod执行结束,将立刻销毁该Pod。如果为该Pod定义了ReplicationController,则系统会监控到该Pod已经终止,之后根据RC定义中Pod的replicas副本数量生成一个新的Pod。一旦创建新的Pod,就在执行完启动命令后陷入无限循环的过程中。这就是Kubernetes需要我们自己创建的Docker镜像并以一个前台命令作为启动命令的原因。
对于无法改造为前台执行的应用,也可以使用开源工具Supervisor辅助进行前台运行的功能。Supervisor提供了一种可以同时启动多个后台应用,并保持Supervisor自身在前台执行的机制,可以满足Kubernetes对容器的启动要求。关于Supervisor的安装和使用,请参考官网http://supervisord.org的文档说明。
接下来对Pod对容器的封装和应用进行说明。
Pod可以由1个或多个容器组合而成。在上一节Guestbook的例子中,名为frontend的Pod只由一个容器组成:
apiVersion: v1 kind: Pod metadata: name: frontend labels: name: frontend spec: containers: - name: frontend image: kubeguide/guestbook-php-frontend env: - name: GET_HOSTS_FROM value: env ports: - containerPort: 80
这个frontend Pod在成功启动之后,将启动1个Docker容器。
另一种场景是,当frontend和redis两个容器应用为紧耦合的关系,并组合成一个整体对外提供服务时,应将这两个容器打包为一个Pod,如图3.1所示。
图3.1 包含两个容器的Pod
配置文件frontend-localredis-pod.yaml的内容如下:
apiVersion: v1 kind: Pod metadata: name: redis-php labels: name: redis-php spec: containers: - name: frontend image: kubeguide/guestbook-php-frontend:localredis ports: - containerPort: 80 - name: redis image: kubeguide/redis-master ports: - containerPort: 6379
属于同一个Pod的多个容器应用之间相互访问时仅需要通过localhost就可以通信,使得这一组容器被“绑定”在了一个环境中。
在Docker容器kubeguide/guestbook-php-frontend:localredis的PHP网页中,直接通过URL地址“localhost:6379”对同属于一个Pod的redis-master进行访问。guestbook.php的内容如下:
<? set_include_path('.:/usr/local/lib/php'); error_reporting(E_ALL); ini_set('display_errors', 1); require 'Predis/Autoloader.php'; Predis\Autoloader::register(); if (isset($_GET['cmd']) === true) { $host = 'localhost'; if (getenv('REDIS_HOST') && strlen(getenv('REDIS_HOST')) > 0 ) { $host = getenv('REDIS_HOST'); } header('Content-Type: application/json'); if ($_GET['cmd'] == 'set') { $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => $host, 'port' => 6379, ]); $client->set($_GET['key'], $_GET['value']); print('{"message": "Updated"}'); } else { $host = 'localhost'; if (getenv('REDIS_HOST') && strlen(getenv('REDIS_HOST')) > 0 ) { $host = getenv('REDIS_HOST'); } $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => $host, 'port' => 6379, ]); $value = $client->get($_GET['key']); print('{"data": "' . $value . '"}'); } } else { phpinfo(); } ?>
运行kubectl create命令创建该Pod:
$ kubectl create -f frontend-localredis-pod.yaml pod "redis-php" created
查看已经创建的Pod:
# kubectl get pods NAME READY STATUS RESTARTS AGE redis-php 2/2 Running 0 10m
可以看到READY信息为2/2,表示Pod中的两个容器都成功运行了。
查看这个Pod的详细信息,可以看到两个容器的定义及创建的过程(Event事件信息):
# kubectl describe pod redis-php Name: redis-php Namespace: default Node: k8s/192.168.18.3 Start Time: Thu, 28 Jul 2016 12:28:21 +0800 Labels: name=redis-php Status: Running IP: 172.17.1.4 Controllers: <none> Containers: frontend: Container ID: docker://ccc8616f8df1fb19abbd0ab189a36e6f6628b78ba7b97b1077d86e7fc224ee08 Image: kubeguide/guestbook-php-frontend:localredis Image ID: docker://sha256:d014f67384a11186e135b95a7ed0d794674f7ce258f0dce47267c3052a0d0fa9 Port: 80/TCP State: Running Started: Thu, 28 Jul 2016 12:28:22 +0800 Ready: True Restart Count: 0 Environment Variables: <none> redis: Container ID: docker://c0b19362097cda6dd5b8ed7d8eaaaf43aeeb969ee023ef255604bde089808075 Image: kubeguide/redis-master Image ID: docker://sha256:405a0b586f7ebeb545ec65be0e914311159d1baedccd3a93e9d3e3b249ec5cbd Port: 6379/TCP State: Running Started: Thu, 28 Jul 2016 12:28:23 +0800 Ready: True Restart Count: 0 Environment Variables: <none> Conditions: Type Status Initialized True Ready True PodScheduled True Volumes: default-token-97j21: Type: Secret (a volume populated by a Secret) SecretName: default-token-97j21 QoS Tier: BestEffort Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- ----- ------ ------- 18m 18m 1 {default-scheduler } Normal Scheduled Successfully assigned redis-php to k8s-node-1 18m 18m 1 {kubelet k8s-node-1} spec.containers{frontend} Normal Pulled Container image "kubeguide/guestbook-php-frontend:localredis" already present on machine 18m 18m 1 {kubelet k8s-node-1} spec.containers{frontend} Normal Created Created container with docker id ccc8616f8df1 18m 18m 1 {kubelet k8s-node-1} spec.containers{frontend} Normal Started Started container with docker id ccc8616f8df1 18m 18m 1 {kubelet k8s-node-1} spec.containers{redis} Normal Pulled Container image "kubeguide/redis-master" already present on machine 18m 18m 1 {kubelet k8s-node-1} spec.containers{redis} Normal Created Created container with docker id c0b19362097c 18m 18m 1 {kubelet k8s-node-1} spec.containers{redis} Normal Started Started container with docker id c0b19362097c