Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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