github.com/deemoprobe/k8s-first-commit@v0.0.0-20230430165612-a541f1982be3/examples/guestbook/guestbook.md (about)

     1  ## GuestBook example
     2  
     3  This example shows how to build a simple multi-tier web application using Kubernetes and Docker.
     4  
     5  The example combines a web frontend, a redis master for storage and a replicated set of redis slaves.
     6  
     7  ### Step Zero: Prerequisites
     8  This example assumes that you have forked the repository and turned up a Kubernetes cluster.
     9  
    10  
    11  ### Step One: Turn up the redis master.
    12  
    13  Create a file named redis-master.json, this file is describes a single task, which runs a redis key-value server in a container.
    14  
    15  ```javascript
    16  {
    17    "id": "redis-master-2",
    18    "desiredState": {
    19      "manifest": {
    20        "containers": [{
    21          "name": "master",
    22          "image": "dockerfile/redis",
    23          "ports": [{
    24            "containerPort": 6379,
    25            "hostPort": 6379 
    26          }]
    27        }]
    28      }
    29    },
    30    "labels": {
    31      "name": "redis-master"
    32    }
    33  }
    34  ```
    35  
    36  Once you have that task file, you can create the redis task in your Kubernetes cluster using the cloudcfg cli:
    37  
    38  ```shell
    39  ./src/scripts/cloudcfg.sh -c redis-master.json create /tasks
    40  ```
    41  
    42  Once that's up you can list the tasks in the cluster, to verify that the master is running:
    43  
    44  ```shell
    45  ./src/scripts/cloudcfg.sh list /tasks
    46  ```
    47  
    48  You should see a single redis master task.  It will also display the machine that the task is running on.  If you ssh to that machine, you can run
    49  ```shell
    50  sudo docker ps
    51  ```
    52  
    53  And see the actual task.  (note that initial ```docker pull``` may take a few minutes, depending on network conditions.
    54  
    55  ### Step Two: Turn up the master service.
    56  A Kubernetes 'service' is named load balancer that proxies traffic to one or more containers.  The services in a Kubernetes cluster are discoverable inside other containers via environment variables.  Services find the containers to load balance based on task labels.  The task that you created in Step One has the label "name=redis-master", so the corresponding service is defined by that label.  Create a file named redis-master-service.json that contains:
    57  
    58  ```javascript
    59  {
    60    "id": "redismaster",
    61    "port": 10000,
    62    "labels": {
    63      "name": "redis-master"
    64    }
    65  }
    66  ```
    67  
    68  Once you have that service description, you can create the service with the cloudcfg cli:
    69  
    70  ```shell
    71  ./src/scripts/cloudcfg.sh -c redis-master-service create /services
    72  ```
    73  
    74  Once created, the service proxy on each minion is configured to set up a proxy on the specified port (in this case port 10000).
    75  
    76  ### Step Three: Turn up the replicated slave service.
    77  Although the redis master is a single task, the redis read slaves are a 'replicated' task, in Kubernetes, a replication controller is responsible for managing multiple instances of a replicated task.  Create a file named redis-slave-controller.json that contains:
    78  
    79  ```javascript
    80    {
    81      "id": "redisSlaveController",
    82      "desiredState": {
    83        "replicas": 2,
    84        "replicasInSet": {"name": "redis-slave"},
    85        "taskTemplate": {
    86          "desiredState": {
    87             "manifest": {
    88               "containers": [{
    89                 "image": "brendanburns/redis-slave",
    90                 "ports": [{"containerPort": 6379, "hostPort": 6380}]
    91               }]
    92             }
    93           },
    94           "labels": {"name": "redis-slave"}
    95          }},
    96      "labels": {"name": "redis-slave"}
    97    }
    98  ```
    99  
   100  Then you can create the service by running:
   101  
   102  ```shell
   103  ./src/scripts/cloudcfg.sh -c redis-slave-controller.json create /replicationControllers
   104  ```
   105  
   106  The redis slave configures itself by looking for the Kubernetes service environment variables in the container environment.  In particular, the redis slave is started with the following command:
   107  
   108  ```shell
   109  redis-server --slaveof $SERVICE_HOST $REDISMASTER_SERVICE_PORT
   110  ```
   111  
   112  Once that's up you can list the tasks in the cluster, to verify that the master and slaves are running:
   113  
   114  ```shell
   115  ./src/scripts/cloudcfg.sh list /tasks
   116  ```
   117  
   118  You should see a single redis master task, and two redis slave tasks.
   119  
   120  ### Step Four: Create the redis slave service.
   121  
   122  Just like the master, we want to have a service to proxy connections to the read slaves.  In this case, in addition to discovery, the slave service provides transparent load balancing to clients.  As before, create a service specification:
   123  
   124  ```javascript
   125  {
   126    "id": "redisslave",
   127    "port": 10001,
   128    "labels": {
   129      "name": "redis-slave"
   130    }
   131  }
   132  ```
   133  
   134  This time the label query for the service is 'name=redis-slave'
   135  
   136  Now that you have created the service specification, create it in your cluster with the cloudcfg cli:
   137  
   138  ```shell
   139  ./src/scripts/cloudcfg.sh -c redis-slave-service.json create /services
   140  ```
   141  
   142  ### Step Five: Create the frontend service.
   143  
   144  This is a simple PHP server that is configured to talk to both the slave and master services depdending on if the request is a read or a write.  It exposes a simple AJAX interface, and serves an angular based U/X.  Like the redis read slaves it is a replicated service instantiated by a replication controller.  Create a file named frontend-controller.json:
   145  
   146  ```javascript
   147    {
   148      "id": "frontendController",
   149      "desiredState": {
   150        "replicas": 3,
   151        "replicasInSet": {"name": "frontend"},
   152        "taskTemplate": {
   153          "desiredState": {
   154             "manifest": {
   155               "containers": [{
   156                 "image": "brendanburns/php-redis",
   157                 "ports": [{"containerPort": 80, "hostPort": 8080}]
   158               }]
   159             }
   160           },
   161           "labels": {"name": "frontend"}
   162          }},
   163      "labels": {"name": "frontend"}
   164    }
   165  ```
   166  
   167  With this file, you can turn up your frontend with:
   168  
   169  ```shell
   170  ./src/scripts/cloudcfg.sh -c frontend-controller.json create /replicationControllers
   171  ```
   172  
   173  Once that's up you can list the tasks in the cluster, to verify that the master, slaves and frontends are running:
   174  
   175  ```shell
   176  ./src/scripts/cloudcfg.sh list /tasks
   177  ```
   178  
   179  You should see a single redis master task, two redis slave and three frontend tasks.
   180  
   181  The code for the PHP service looks like this:
   182  ```php
   183  <?
   184  
   185  set_include_path('.:/usr/share/php:/usr/share/pear:/vendor/predis');
   186  
   187  error_reporting(E_ALL);
   188  ini_set('display_errors', 1);
   189  
   190  require 'predis/autoload.php';
   191  
   192  if (isset($_GET['cmd']) === true) {
   193    header('Content-Type: application/json');
   194    if ($_GET['cmd'] == 'set') {
   195      $client = new Predis\Client([
   196        'scheme' => 'tcp',
   197        'host'   => getenv('SERVICE_HOST'),
   198        'port'   => getenv('REDISMASTER_SERVICE_PORT'),
   199      ]);
   200      $client->set($_GET['key'], $_GET['value']);
   201      print('{"message": "Updated"}');
   202    } else {
   203      $read_port = getenv('REDISMASTER_SERVICE_PORT');
   204  
   205      if (isset($_ENV['REDISSLAVE_SERVICE_PORT'])) {
   206        $read_port = getenv('REDISSLAVE_SERVICE_PORT');
   207      }
   208      $client = new Predis\Client([
   209        'scheme' => 'tcp',
   210        'host'   => getenv('SERVICE_HOST'),
   211        'port'   => $read_port,
   212      ]);
   213  
   214      $value = $client->get($_GET['key']);
   215      print('{"data": "' . $value . '"}');
   216    }
   217  } else {
   218    phpinfo();
   219  } ?>
   220  ```
   221  
   222  To play with the service itself, find the name of a frontend, grab the external IP of that host from the Google Cloud Console, and visit http://&lt;host-ip&gt;:8080, note you may need to open the firewall for port 8080 using the console or the gcloud tool.