{"id":17344139,"url":"https://github.com/typhoonzero/kubernetes","last_synced_at":"2025-04-13T19:10:26.976Z","repository":{"id":99429598,"uuid":"61509558","full_name":"typhoonzero/kubernetes","owner":"typhoonzero","description":"A practical and thus comprehensive guide to concepts in Kubernetes","archived":false,"fork":false,"pushed_at":"2016-08-01T12:51:47.000Z","size":1034,"stargazers_count":0,"open_issues_count":0,"forks_count":8,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-27T09:49:22.674Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typhoonzero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-20T01:48:39.000Z","updated_at":"2017-04-29T06:04:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"b5b51430-9ee4-457c-b5fa-2a923dafc756","html_url":"https://github.com/typhoonzero/kubernetes","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fkubernetes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fkubernetes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fkubernetes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typhoonzero%2Fkubernetes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typhoonzero","download_url":"https://codeload.github.com/typhoonzero/kubernetes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248766736,"owners_count":21158301,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T16:24:11.677Z","updated_at":"2025-04-13T19:10:26.957Z","avatar_url":"https://github.com/typhoonzero.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# A Practical and Comprehensive Guide to Kubernetes\n\nThis trial covers\n[Kubernetes 101](http://kubernetes.io/docs/user-guide/walkthrough/),\n[Kubernetes 201](http://kubernetes.io/docs/user-guide/walkthrough/k8s201/),\nand the\n[Guestbook example](https://github.com/kubernetes/kubernetes/blob/release-1.2/examples/guestbook/README.md),\nbut interleaved more explanation to Kubernetes concepts and internals.\n\nKubernetes concepts covered in this document include:\n\n1. cluster\n1. nodes (and node IP)\n1. pods (and pod IP)\n1. labels\n1. replication controller (or RC for short)\n1. service\n1. deployment\n\nTo run this trial, we need a Kubernetes cluster.  We can follow\nhttps://github.com/k8sp/vagrant-coreos to create one running on a\nVagrant cluster of CoreOS virtual machines.\n\n## The Cluster\n\nNow we have a Kubernetes cluster running.  To get some information about it, we run `kubectl cluster-info`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl cluster-info\nKubernetes master is running at https://172.17.4.101:443\nHeapster is running at https://172.17.4.101:443/api/v1/proxy/namespaces/kube-system/services/heapster\nKubeDNS is running at https://172.17.4.101:443/api/v1/proxy/namespaces/kube-system/services/kube-dns\n```\n\nwhere `172.17.4.101` is the IP address of a virtual machine (or,\n*node*) that runs the Kubernetes master piece (or, *control node*).\n\n\n## Nodes\n\nIn additional to the control node, there are other nodes in the\ncluster.  To show them, we use `kubectl get nodes`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get nodes\nNAME           STATUS                     AGE\n172.17.4.101   Ready,SchedulingDisabled   5h\n172.17.4.201   Ready                      5h\n```\n\nEach node has an IP address, simply because each virtual machine has an IP address.\nWhen we create this virtual machine cluster, we specify node IPs in\nVagrant file.  If the Kubernetes cluster is created using Vagrant, we\nshould be able to `ping 172.17.4.101` or `ping 172.17.4.201` on the\nhost, just as we ping virtual machine from host.\n\nPlease be aware that *node IP* is different from *pod IP*.  In order\nto know more about *pod IP*, let's create some pods.\n\n\n## Pods\n\nWe can create a pod by `kubectl create -f pod_description.yaml`.  An\nexample pod description YAML file is\n[pod_nginx.yaml](./pod_nginx.yaml):\n\n```\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx\nspec:\n  containers:\n  - name: nginx\n    image: nginx\n    ports:\n    - containerPort: 80\n```\n\nHere is the way to create a pod from `pod_nginx.yaml`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f pod_nginx.yaml \npod \"nginx\" created\n```\n\nUsually, it takes sometime for Kubernetes to download the Docker image\nof the pod.  So the initial status of the pod is `ContainerCreating`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pod\nNAME      READY     STATUS              RESTARTS   AGE\nnginx     0/1       ContainerCreating   0          3s\n```\n\nBy giving `-o wide` to `kubectl get pod`, we can see the IP of the\nnode on which the pod is running:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pod -o wide\nNAME      READY     STATUS    RESTARTS   AGE       NODE\nnginx     1/1       Running   0          15s       172.17.4.201\n```\n\nIt is important to know that each pod in a Kubernetes cluster is\nassigned an IP in a flat shared networking namespace.  This allows for\na clean network model where Pods, from a networking perspective, can\nbe treated much like virtual machines or physical\nhosts. (c.f. https://coreos.com/kubernetes/docs/latest/kubernetes-networking.html)\n\nTo get the pod IP, we provide a customized template to the `-o` flag:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pod nginx -o go-template={{.status.podIP}}\n10.2.75.4\n```\n\nNote that pod IPs are not visible outside of the Kubernetes.  For\nabove example, if we want to access the nginx pod, we need to log into\na node:\n\n```\nyi@WangYis-iMac:~/work/k8sp/vagrant-coreos/coreos-kubernetes/multi-node/vagrant (master)*$ vagrant ssh w1 -c \"curl http://10.2.75.4\"\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n\u003ctitle\u003eWelcome to nginx!\u003c/title\u003e\n...\n\u003c/body\u003e\n\u003c/html\u003e\nConnection to 127.0.0.1 closed.\n```\n\nHow if we want to be able to access the pod from outside the cluster?\nWe need to create a *service* around the pod, because *service* is a\nKubernetes object for exposing pods to the outside world.  But before\ngetting into services, we need to understand *labels* and *replication\ncontroller*.\n\n\n## Label\n\nFor tolerance, a service is usually composed of a group of redundant\npods.  How can we select such a group?  Pod name doesn't work, because\neach pod has its unique name.  So here comes *labels*.  We can assign\nmultiple pods the same label, and select these pods as a group by\nusing the label.\n\n[`pod_nginx_with_label.yaml`](./pod_nginx_with_label.yaml) shows how\nto define a label `app: nginx` in addition to `pod_nginx.yaml`:\n\n```\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx\n  labels:       # \u003c-\n    app: nginx  # \u003c-\nspec:\n  containers:\n  - name: nginx\n    image: nginx\n    ports:\n    - containerPort: 80\n```\n\nBecause `pod_nginx_with_label.yaml` also defines a pod named `nginx`\nas `pod_nginx.yaml` does, we need to delete the pod created from\n`pod_nginx.yaml` before we create a new pod from\n`pod_nginx_with_label.yaml`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl delete pod nginx\npod \"nginx\" deleted\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f pod_nginx_with_label.yaml \npod \"nginx\" created\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nNAME      READY     STATUS              RESTARTS   AGE\nnginx     0/1       ContainerCreating   0          6s\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods -l app=nginx\nNAME      READY     STATUS    RESTARTS   AGE\nnginx     1/1       Running   0          16s\n```\n\nNote again that we cannot create two pods with the same name.\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f pod_nginx.yaml \nError from server: error when creating \"pod_nginx.yaml\": pods \"nginx\" already exists\n```\n\n\n## Replication Controllers\n\nHow if we want to create 10 pods, all running nginx, so to create a\nservice?  We can create them one-by-one manually, each with its unique\nname.  But a smarter way is to use *replication controller*.\n\nAn example replication controller (RC for short) is\n[`rc_nginx.yaml`](./rc_nginx.yaml):\n\n```\napiVersion: v1\nkind: ReplicationController\nmetadata:\n  name: nginx-controller\nspec:\n  replicas: 2\n  # selector identifies the set of Pods that this\n  # replication controller is responsible for managing\n  selector:\n    app: nginx\n  # podTemplate defines the 'cookie cutter' used for creating\n  # new pods when necessary\n  template:\n    metadata:\n      labels:\n        # Important: these labels need to match the selector above\n        # The api server enforces this constraint.\n        app: nginx\n    spec:\n      containers:\n      - name: nginx\n        image: nginx\n        ports:\n        - containerPort: 80\n```\n\n`rc_nginx.yaml` creates an rc named `nginx-controller` that wants 2\nreplicas of nginx pods with label `app: nginx`.  Note that\n`rc_nginx.yaml` contains a \"template\" section which is the template of\npod definition.  The template in `rc_nginx.yaml` looks very similar to\nthe content of [pod_nginx.yaml](./pod_nginx.yaml).\n\nRemember that we already have one pod with label `app: nginx` running,\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nNAME      READY     STATUS    RESTARTS   AGE\nnginx     1/1       Running   0          25m\n```\n\nso, when we create this rc, Kubernetes starts only one new pod:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f rc_nginx.yaml \nreplicationcontroller \"nginx-controller\" created\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nNAME                     READY     STATUS              RESTARTS   AGE\nnginx                    1/1       Running             0          25m\nnginx-controller-58t5s   0/1       ContainerCreating   0          5s\n```\n\n`kubectl get rc` lists this rc:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get rc\nNAME               DESIRED   CURRENT   AGE\nnginx-controller   2         2         36s\n```\n\nDeleting this rc deletes all two pods, including the one we created\nmanually from `pod_nginx.yaml`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl delete rc nginx-controller\nreplicationcontroller \"nginx-controller\" deleted\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\n```\n\n## Services\n\nFinally we have a replicated set of nginx pods, we can wrap them up as\na service now.  [`service_nginx.yaml`](./service_nginx.yaml) shows how\nto do this:\n\n```\napiVersion: v1\nkind: Service\nmetadata:\n  name: nginx-service\nspec:\n  ports:\n  - port: 8000 # the port that this service should serve on\n    # the container on each pod to connect to, can be a name\n    # (e.g. 'www') or a number (e.g. 80)\n    targetPort: 80\n    protocol: TCP\n  # just like the selector in the replication controller,\n  # but this time it identifies the set of pods to load balance\n  # traffic to.\n  selector:\n    app: nginx\n```\n\nRemember that we already have an RC of two nginx pods running.  All\nthese pods have label `app: nginx`.  So the following command wraps\nthese pods up:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f service_nginx.yaml \nservice \"nginx-service\" created\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nNAME                     READY     STATUS    RESTARTS   AGE\nnginx-controller-0xc3c   1/1       Running   0          23m\nnginx-controller-oii7h   1/1       Running   0          23m\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get rc\nNAME               DESIRED   CURRENT   AGE\nnginx-controller   2         2         24m\n```\n\nDeleting the service doesn't affect the RC and pods:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl delete service nginx-service\nservice \"nginx-service\" deleted\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nNAME                     READY     STATUS    RESTARTS   AGE\nnginx-controller-0xc3c   1/1       Running   0          24m\nnginx-controller-oii7h   1/1       Running   0          24m\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get rc\nNAME               DESIRED   CURRENT   AGE\nnginx-controller   2         2         24m\n```\n\nIf we want to clean up, we need to explicitly delete the RC, then the\npods are deleted as well:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl delete rc nginx-controller\nreplicationcontroller \"nginx-controller\" deleted\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\n```\n\nWhen there are no pods with label `app: nginx` running, we can still\ncreate a service, but it doesn't' include any pods yet:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f service_nginx.yaml \nservice \"nginx-service\" created\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get rc\n```\n\nNow we can create pods with service-wanted label `app: nginx`:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl create -f rc_nginx.yaml \nreplicationcontroller \"nginx-controller\" created\n```\n\nThen we check that the service noticed and selected these pods:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl describe service\nName:\t\t\tkubernetes\n  ....\nName:\t\t\tnginx-service\n  ....\nEndpoints:\t\t10.2.75.4:80,10.2.75.5:80\n  ....\n  ```\n\nNoticed the two endpoints?  They are actually the newly started two\nnginx pods.  To confirm this, we check the pod IPs of these two pods:\n\n```\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pods -l app=nginx -o wide\nNAME                     READY     STATUS    RESTARTS   AGE       NODE\nnginx-controller-pioas   1/1       Running   0          8m        172.17.4.201\nnginx-controller-s9q1l   1/1       Running   0          8m        172.17.4.201\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pod nginx-controller-pioas -o go-template={{.status.podIP}}\n10.2.75.4\nyi@WangYis-iMac:~/work/k8sp/kubernetes $ kubectl get pod nginx-controller-s9q1l -o go-template={{.status.podIP}}\n10.2.75.5\n```\n\nThe two pods have pod IPs `10.2.75.4` and `10.2.75.5`, which are those\nshown as endpoints of service `nginx-service`.\n\n\n## Load Balancer\n\nBy this time, you might want to check if we can access the nginx\nservice from outside of the Kubernetes cluster.  Unfortunately, we\ncannot, because we have been doing above steps in a Vagrant cluster,\nwhich doesn't provide Kubernetes a *load balancer*, which expose\nservices to the outside world.\n\n*Load balancer* is one of the three ways that Kubernetes expose\nservices.  The other two are *ClusterIP* and *NodePort*.  As explained\nin http://rafabene.com/2015/11/11/how-expose-kubernetes-services/:\n\n1. `ClusterIP`: use a cluster-internal IP only - this is the default\n   and is discussed above. Choosing this value means that you want\n   this service to be reachable only from inside of the cluster.\n1. `NodePort` : on top of having a cluster-internal IP, expose the\n   service on a port on each node of the cluster (the same port on\n   each node). You’ll be able to contact the service on any :NodePort\n   address.\n1. `LoadBalancer`: on top of having a cluster-internal IP and exposing\n   service on a NodePort also, ask the cloud provider for a load\n   balancer which forwards to the Service exposed as a :NodePort for\n   each Node.\n\nWe can choose among the three ways by setting the `ServiceType`\nattribute in the YAML file.\n\nIf we run above steps on GKE or AWS, we can choose `LoadBalancer`,\nsince GKE and AWS provides load balancers.  Given that we have been\nusing Vagrant cluster, we can choose `NodePort`.  For more details,\nplease refer to\nhttp://rafabene.com/2015/11/11/how-expose-kubernetes-services/:.\n\n\n## Networking\n\nYou might be wondering about how all these networking related things,\nnode IP, pod IP, external IP, work.\nhttps://coreos.com/kubernetes/docs/latest/kubernetes-networking.html\nexplained this:\n\nTo understand load balancer, we need to understand the types of\nKubernetes communication:\n\n1. *Container-to-Container Communication*: Kubernetes assigns an IP\n   addres to each pod, therefore containers within a pod are\n   identified with `localhost` and different ports.\n1. *Pod-to-Pod Communication*: Each Pod in a Kubernetes cluster is\n   assigned an IP in a flat shared networking namespace.  We do not\n   need to explicitly create links between pods and we almost never\n   need to deal with mapping container ports to host ports.  This\n   creates a clean, backwards-compatible model where pods can be\n   treated much like VMs or physical hosts from the perspectives of\n   port allocation, naming, service discovery, load balancing,\n   application configuration, and migration.\n1. *Pod-to-Service Communication*: Services are implemented by\n   assigning Virtual IPs which clients can access and are\n   transparently proxied to the Pods grouped by that service. Requests\n   to the Service IPs are intercepted by a kube-proxy process running\n   on all hosts, which is then responsible for routing to the correct\n   Pod.\n1. *External-to-Internal Communication:* Accessing services from\n   outside the cluster is generally implemented by configuring\n   external load balancers which target all nodes in the cluster. Once\n   traffic arrives at a node, it is routed to the correct Service\n   backends via the kube-proxy.  See Kubernetes Networking for more\n   detailed information on the Kubernetes network model and\n   motivation.\n\nMore about Kubernetes networking is at [here](./networking/README.md).\n\n## Deployment\n\nAbove examples show how to create pods using RC and how to wrap\ncreated pods into a service.  In practice, we rarely use RC directly\nto create pods; instead, we use *deployment*.  This is because we want\n*deployment* to take care of the roll-out and rollback affair.\n\nTo be continued.\n\n\u003c!--  LocalWords:  Guestbook kubectl Heapster KubeDNS yaml nginx ssh\n --\u003e\n\u003c!--  LocalWords:  SchedulingDisabled apiVersion metadata podIP html\n --\u003e\n\u003c!--  LocalWords:  containerPort ContainerCreating DOCTYPE app md rc\n --\u003e\n\u003c!--  LocalWords:  ReplicationController podTemplate api www NodePort\n --\u003e\n\u003c!--  LocalWords:  replicationcontroller targetPort kubernetes GKE\n --\u003e\n\u003c!--  LocalWords:  ClusterIP LoadBalancer ServiceType AWS kube\n --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyphoonzero%2Fkubernetes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftyphoonzero%2Fkubernetes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyphoonzero%2Fkubernetes/lists"}