GitHub PullRequestReviewCommentEvent at 2014-10-02 17:12:39
Repository: kubernetes
Actor: erictune
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/18352686","id":18352686,"diff_hunk":"@@ -0,0 +1,229 @@\n+# Durable Local Volumes: Design Alternatives\n+\n+## Related Issues\n+Request for Durable Local Storage: https://github.com/GoogleCloudPlatform/kubernetes/issues/598\n+\n+The life of a Pod: https://github.com/GoogleCloudPlatform/kubernetes/pull/1406\n+\n+## Requirements\n+\n+Kubernetes requirements:\n+  - Do not provide a direct mechanism to pin pods to minions.\n+  - Security and isolation between unrelated pods (HostDirectory does not provide this)\n+  - Work regardless of CloudProvider.\n+  - Support local restarts of containers that depend on durable data\n+    - Desirable for high availability and bootstrapping.\n+  - A container spec with no volumes should have an identical filesystem view on every container instantation.  \n+    - Allows writing truly stateless containers.\n+\n+Application requirements:\n+  - have a chunk of writeable data which is not automatically deleted by Kubernetes due to certain _events_, described\n+    below.  (EmptyDirectory does not provide this, nor does the containers writeable file layer.)\n+  - high speed access (networked storage may not provide this.  local SSD does.).\n+\n+Application Examples:\n+  - Mysql database.  Either single instance, or master-slave replicated.  Tables expected in `/var/lib/mysql`, which we\n+    want to be some kind of durable local volume.  Want to updgrade mysql version without losing tables or incurring\n+    traffic to recover from replica.\n+  - Video streaming server holds large cache of videos to stream.  This set of videos changes slowly over time.\n+  - Mongdb database.  Uses replication for high availability.  Data stored at `/var/lib/mongodb/`, which we want to be\n+    some kind of durable local volume.  If one of the physical nodes hosting pod unexpectedly reboots, is partitioned,\n+    or has a hardware failure, want to create a new replica.  Replication controller accomplishes this.  MongoDB will\n+    automatically fail over to a replica if the lost pod was a master.\n+\n+## Current Behavior\n+\n+A Pod has a (current and desired) PodState, which has ContainerManifest that lists the Volumes and Containers of a Pod.\n+A Container always has a writeable filesystem, and it can attach Volumes to that which are also writeable.  Writes not\n+to a volume are not visible to other containers and are not preserved past container failures.  Writes to an\n+EmptyDirectory volume are visible to other containers in the pod.  An EmptyDirectory is only shared by containers which\n+are part of the same pod ID (UID in v1beta3) and is garbage collected when no longer referenced (the PR that adds\n+garbage collection is not merged, but this description is written assuming it is.)\n+\n+How specific events are handled:\n+  - *Container Failure*: Container exits abnormally (out of memory, segfault, assertion failed, etc), or normally, or fails a healthcheck.\n+    - Kubelet restarts it if policy allows (RestartAlways or RestartOnFailure and exited abnormally).  The\n+      EmptyDirectory is reused because PodID is the same.  The docker writable layer is discarded.\n+    - If policy does not allow restart, then it will not run again with the same UID.  Therefore, EmptyDirectory is not reused and is eventually garbage collected.\n+    - Use of restartPolicy other than Always is not recommended with replicationController (see #1406)\n+  - *Pod Update*:  desiredState modified, but Pod Name and UID are unchanged (e.g. used updates to new version of docker image)\n+    - Kubelet sees a mismatch between checksums of current and desired ContainerManifest, so it deletes the\n+      docker containers and starts them again.  Since Pod UID is unchanged, it reuses the EmptyDirectory. The docker writable layer is discarded.\n+    - No-restart Updates not currently supported, but may be required in future (e.g. change resource limits, health check\n+      settings, etc).  In this case, the docker writable layer is not discarded because the docker container keeps\n+      running.\n+  - *Replication Count Reduced*: user modifies replicationController resource.\n+    - Note: current plan for Rolling updates involves reducing the count on one replicationController and increasing on\n+      another.\n+    - Pod is deleted by replicationController when replication count is reduced by user.\n+    - EmptyDirectory is garbage collected.  It will not be reused by same-Name different-UID pods.\n+  - *Node Partition*: A node is partitioned from network and then rejoins network.\n+    - Current behavior is that the pod is still running afterwards, with its data\n+    - Planned behavior described in #1406 is that pod will be terminated and deleted if minion unreachable for longer than some\n+      threshold.  When kubelet returns and does not see the the pod on the list of pods for its minion, it terminates\n+      the running pod.  The EmptyDirectory is garbage collected, so data is lost.\n+  - *Node Reboots*\n+    - Current behavior is that after a reboot, Kubelet sees no running containers and sees pods listed in etcd, and so\n+      starts pods.  API shows the pod as running the whole time.  Since the pods have the same UID, then the existing\n+      EmptyDirectory is reused. \n+    - Planned behavior described in #1406 is that a pod might be deleted, depending on the timing of the reboot and the\n+      node controller threshold.  In this case, a replacement may be created by the replicationController.  There will\n+      be no resue of the data due to the new pod UID.\n+  - *Kubelet Restarts*: the kubelet binary crashes or exits normally, then restarts.\n+    - Currently, Kubelet restart will allow pod to remain running, data intact.\n+  - *Storage Device Fails*\n+    - Pod may get errors on reads/writes.  Failure of health check is likely.  See *Container Failure*.  If\n+      RestartAlways, then pod will likely enter endless fail and restart loop.\n+    - Failure could happen immediately following reboot, prior to pod restart.  Data lost in this case too.\n+    - Expect that will need to implement a control loop that detects bad storage hardware and deletes the pods that\n+      depend on them.\n+\n+## Alternatives\n+\n+There appear to be two main design alternatives:\n+  1. *Durable Pods*: Make pods live longer than reboots, network partitions, etc.  Their data (in one or more EmptyDirectory) is then also long lived.\n+  1. *New Resource Kind*: Make an object that represents data that has a long lifetime, and allow pods to attach to it.\n+\n+They are explained in the next two subsections.\n+\n+### Durable Pods\n+\n+Changes:\n+  - Bit(s) on a Pod which indicates whether durability is requested.\n+  - Kubelet sees whole pod object (currently has only ContainerManifest) to get UID.\n+  - Kubelet preserves EmptyDirectory when stopping pod which wants durable data.\n+  - Kubelet attaches preseved EmptyDirectory when starting pod that wants durable data and has matching UID.\n+  - Kubelet to inventory existing EmptyDirectory objects after reboot.\n+  - Kubelet may need checkpoint or the equivalent to track the preserved EmptyDirectory dirs on disk, and to remember\n+    the UID of stopped-and-about-to-be-recreated pods.\n+  - A new model for rolling upgrades which uses updates rather than delete-recreate of pods.\n+\n+How events handled:\n+  - Container Failure\n+    - No change from current.\n+  - Pod Update\n+    - No change from current.\n+  - Replication Count Reduced\n+    - Not able to directly handle this case.\n+  - Node Reboots\n+    - Kubelet now detects existing EmptyDirectory after reboot and attaches to matching Pods when starting those Pods.\n+  - Node Partition\n+    - No change required under current code.\n+    - When NodeController (#1406) implemented, it should not delete a pod wanting durability from a node that is\n+      unreachable (or wait for forgiveness-specified duration before deleting).\n+  - Kubelet Restarts\n+    - No change.\n+  - Storage Device Fails\n+    - No change.  If a control loop is added to detect failed storage hardware, then it would delete the pods that had\n+      EmptyDirectories on the failed device.\n+\n+### New Resource Kind\n+\n+Changes:\n+  - Add a new /data REST resource (not necessarily final name) that represents a chunk of data on a storage device\n+    somewhere.  Has lifetime independent of a pod.\n+  - Add a new type of [Volume](../volumes.md) that a pod can request with selector to match /data objects that satisfy\n+    it.\n+  - Scheduler changes to handle Data.\n+    - always try to bind an unbound pod that needs a Data to an existing bound matching Data, if one exists.\n+    - If both a pod and a matching Data are both unbound, and the previous step failed, the scheduler binds the Pod and\n+      the Data at the same time (to ensure that the Pods constraints are met and that they both fit in the free space of\n+      the node.)\n+    - Once a /data is bound, it stays bound until the user deletes the /data.\n+  - Kubelet changes to support creating a Data, and to detect an existing Data after reboot.\n+  - Kubecfg support for /data.\n+  - Replication control for Data?\n+\n+How events handled:\n+  - Container Failure\n+    - If RestartAlways selected, all volumes (EmptyDirectory, /data volumes) remain. No change.\n+    - *Changed.*  If other restart policy selected, a new UID but same config pod will reattach to an existing Data.\n+  - Pod Update\n+    - No change.\n+  - Replication Count Reduced\n+    - *Changed*.  A /data remains until explictly removed.  This allows the Pod Replication Count to be lowered and then raised again\n+      without loss of data. \n+  - Node Reboots\n+    - Kubelet will see what pods and data object the node should have.  It will see existing data objects and leave them\n+      alone.  It sees missing pods, so it starts them and attaches them to their data.\n+  - Node Partition\n+    - Currently, no change.\n+    - When NodeController implemented, it can terminate all pods on a machine that has been unresponsive for a long\n+      time.  It does not delete /data.\n+  - Kubelet Restarts\n+    - No change.\n+  - Storage Device Fails\n+    - No change.  If controller is added to detect failed storage hardware, then it would delete the lost /data object,\n+      and either delete to pods too, or put the pod back in a pending state to be rescheduled.\n+\n+\n+## Evaluation of Alternatives\n+\n+Either alternative can easily handle resource limits for Volumes and resource capacities for minions, and new storage\n+(disk, ssd) resource types.  This is not a deciding factor.\n+\n+In either alternative, and in the current state, a pod with RestartAlways policy has to handle both the case when it\n+starts with an empty volume, and when it restarts with a non-empty volume.  This is not a factor.\n+\n+Either alternative can easily handle a configurable tradeoff between waiting for an unavailable minion to return versus\n+starting a new instance of the pod and data elsewhere (_forgiveness_).  This is not a deciding factor.\n+\n+Either alternative can be adapted to allow hedging bets: simultaneously starting a new pod/data pair while waiting for a\n+lost pod/data to come back.  This is not a deciding factor.\n+\n+Either alternative can be adapted to support rolling restarts.   The approaches are different.  This is probably not a\n+deciding factor.\n+\n+Either alternative can be adapted to allow a controller to automatically delete pods/datas in case of a storage device\n+hardware failure.    This is not a deciding factor.\n+\n+New Resource Kind adds more resource types for users to learn about (though you do not need to know about Data to use\n+Kubernetes).  This is a point in favor of Durable Pods.\n+\n+Under the New Resource Kind alternative, a Pod is stateless (assuming it has no HostDirectory or other remote volumes), and\n+the Data represents state without computation.  This has an attractive simplicity.  Minor point for New Resource Kind.\n+\n+Under the Durable Pods alternative, the NodeController has to reason about both minions (whether they are likely to be\n+operating correctly) and about pods (what forgivenesses they want).  Under the New Resource Kind alternative, the","path":"docs/proposals/durable_data.md","position":187,"original_position":187,"commit_id":"1b8c3253f52f89cb95a881902d444d30ce167fcf","original_commit_id":"1b8c3253f52f89cb95a881902d444d30ce167fcf","user":{"login":"erictune","id":8105590,"avatar_url":"https://avatars.githubusercontent.com/u/8105590?v=2","gravatar_id":"","url":"https://api.github.com/users/erictune","html_url":"https://github.com/erictune","followers_url":"https://api.github.com/users/erictune/followers","following_url":"https://api.github.com/users/erictune/following{/other_user}","gists_url":"https://api.github.com/users/erictune/gists{/gist_id}","starred_url":"https://api.github.com/users/erictune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erictune/subscriptions","organizations_url":"https://api.github.com/users/erictune/orgs","repos_url":"https://api.github.com/users/erictune/repos","events_url":"https://api.github.com/users/erictune/events{/privacy}","received_events_url":"https://api.github.com/users/erictune/received_events","type":"User","site_admin":false},"body":"Yes.  I expect forgiveness to come into either solution at some point.  ","created_at":"2014-10-02T17:12:39Z","updated_at":"2014-10-02T17:12:39Z","html_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515#discussion_r18352686","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/18352686"},"html":{"href":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515#discussion_r18352686"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515","id":22021761,"html_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515","diff_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515.diff","patch_url":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/1515","number":1515,"state":"open","locked":false,"title":"Durable data","user":{"login":"erictune","id":8105590,"avatar_url":"https://avatars.githubusercontent.com/u/8105590?v=2","gravatar_id":"","url":"https://api.github.com/users/erictune","html_url":"https://github.com/erictune","followers_url":"https://api.github.com/users/erictune/followers","following_url":"https://api.github.com/users/erictune/following{/other_user}","gists_url":"https://api.github.com/users/erictune/gists{/gist_id}","starred_url":"https://api.github.com/users/erictune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erictune/subscriptions","organizations_url":"https://api.github.com/users/erictune/orgs","repos_url":"https://api.github.com/users/erictune/repos","events_url":"https://api.github.com/users/erictune/events{/privacy}","received_events_url":"https://api.github.com/users/erictune/received_events","type":"User","site_admin":false},"body":"I'm not looking to actually merge this PR, just get some feedback on two possible approaches.\r\n\r\nIf there is agreement on one approach, then I will code it up, and convert this design document into user documentation.  \r\n\r\nI'm inclined to add a new type of REST resource to model Durable local data.  I know new resources are always  controversial, so I've written this doc to compare the alternatives.  Comments welcome from anyone.  I'd particularly like comments from @dchen1107 @bgrant0607 @thockin @brendanburns @jbeda @lavalamp @smarterclayton.\r\n","created_at":"2014-09-30T17:42:30Z","updated_at":"2014-10-02T17:12:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2ebc3599c8c61640cdcfa6e4310ef74e695b6253","assignee":null,"milestone":{"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/milestones/1","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/milestones/1/labels","id":768069,"number":1,"title":"v1.0","description":"","creator":{"login":"bgrant0607","id":7725777,"avatar_url":"https://avatars.githubusercontent.com/u/7725777?v=2","gravatar_id":"","url":"https://api.github.com/users/bgrant0607","html_url":"https://github.com/bgrant0607","followers_url":"https://api.github.com/users/bgrant0607/followers","following_url":"https://api.github.com/users/bgrant0607/following{/other_user}","gists_url":"https://api.github.com/users/bgrant0607/gists{/gist_id}","starred_url":"https://api.github.com/users/bgrant0607/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgrant0607/subscriptions","organizations_url":"https://api.github.com/users/bgrant0607/orgs","repos_url":"https://api.github.com/users/bgrant0607/repos","events_url":"https://api.github.com/users/bgrant0607/events{/privacy}","received_events_url":"https://api.github.com/users/bgrant0607/received_events","type":"User","site_admin":false},"open_issues":7,"closed_issues":3,"state":"open","created_at":"2014-08-27T23:42:27Z","updated_at":"2014-10-01T21:20:52Z","due_on":null},"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/{number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/1515/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/1b8c3253f52f89cb95a881902d444d30ce167fcf","head":{"label":"erictune:durable_data","ref":"durable_data","sha":"1b8c3253f52f89cb95a881902d444d30ce167fcf","user":{"login":"erictune","id":8105590,"avatar_url":"https://avatars.githubusercontent.com/u/8105590?v=2","gravatar_id":"","url":"https://api.github.com/users/erictune","html_url":"https://github.com/erictune","followers_url":"https://api.github.com/users/erictune/followers","following_url":"https://api.github.com/users/erictune/following{/other_user}","gists_url":"https://api.github.com/users/erictune/gists{/gist_id}","starred_url":"https://api.github.com/users/erictune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erictune/subscriptions","organizations_url":"https://api.github.com/users/erictune/orgs","repos_url":"https://api.github.com/users/erictune/repos","events_url":"https://api.github.com/users/erictune/events{/privacy}","received_events_url":"https://api.github.com/users/erictune/received_events","type":"User","site_admin":false},"repo":{"id":21629362,"name":"kubernetes","full_name":"erictune/kubernetes","owner":{"login":"erictune","id":8105590,"avatar_url":"https://avatars.githubusercontent.com/u/8105590?v=2","gravatar_id":"","url":"https://api.github.com/users/erictune","html_url":"https://github.com/erictune","followers_url":"https://api.github.com/users/erictune/followers","following_url":"https://api.github.com/users/erictune/following{/other_user}","gists_url":"https://api.github.com/users/erictune/gists{/gist_id}","starred_url":"https://api.github.com/users/erictune/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erictune/subscriptions","organizations_url":"https://api.github.com/users/erictune/orgs","repos_url":"https://api.github.com/users/erictune/repos","events_url":"https://api.github.com/users/erictune/events{/privacy}","received_events_url":"https://api.github.com/users/erictune/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/erictune/kubernetes","description":"Container Cluster Manager","fork":true,"url":"https://api.github.com/repos/erictune/kubernetes","forks_url":"https://api.github.com/repos/erictune/kubernetes/forks","keys_url":"https://api.github.com/repos/erictune/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/erictune/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/erictune/kubernetes/teams","hooks_url":"https://api.github.com/repos/erictune/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/erictune/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/erictune/kubernetes/events","assignees_url":"https://api.github.com/repos/erictune/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/erictune/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/erictune/kubernetes/tags","blobs_url":"https://api.github.com/repos/erictune/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/erictune/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/erictune/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/erictune/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/erictune/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/erictune/kubernetes/languages","stargazers_url":"https://api.github.com/repos/erictune/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/erictune/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/erictune/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/erictune/kubernetes/subscription","commits_url":"https://api.github.com/repos/erictune/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/erictune/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/erictune/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/erictune/kubernetes/issues/comments/{number}","contents_url":"https://api.github.com/repos/erictune/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/erictune/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/erictune/kubernetes/merges","archive_url":"https://api.github.com/repos/erictune/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/erictune/kubernetes/downloads","issues_url":"https://api.github.com/repos/erictune/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/erictune/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/erictune/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/erictune/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/erictune/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/erictune/kubernetes/releases{/id}","created_at":"2014-07-08T21:00:59Z","updated_at":"2014-07-17T20:45:22Z","pushed_at":"2014-10-01T20:36:43Z","git_url":"git://github.com/erictune/kubernetes.git","ssh_url":"git@github.com:erictune/kubernetes.git","clone_url":"https://github.com/erictune/kubernetes.git","svn_url":"https://github.com/erictune/kubernetes","homepage":null,"size":11043,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"ca547bd29b00269f7ba0d86e7c0eba4d57fe56e2","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=2","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":20580498,"name":"kubernetes","full_name":"GoogleCloudPlatform/kubernetes","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=2","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/kubernetes","description":"Container Cluster Manager","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/comments/{number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/releases{/id}","created_at":"2014-06-06T22:56:04Z","updated_at":"2014-10-02T13:22:44Z","pushed_at":"2014-10-02T16:49:57Z","git_url":"git://github.com/GoogleCloudPlatform/kubernetes.git","ssh_url":"git@github.com:GoogleCloudPlatform/kubernetes.git","clone_url":"https://github.com/GoogleCloudPlatform/kubernetes.git","svn_url":"https://github.com/GoogleCloudPlatform/kubernetes","homepage":null,"size":34783,"stargazers_count":3821,"watchers_count":3821,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":547,"mirror_url":null,"open_issues_count":242,"forks":547,"open_issues":242,"watchers":3821,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515"},"html":{"href":"https://github.com/GoogleCloudPlatform/kubernetes/pull/1515"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/1515"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/issues/1515/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/pulls/1515/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/kubernetes/statuses/1b8c3253f52f89cb95a881902d444d30ce167fcf"}}}}