diff --git a/architecture/core_concepts/pods_and_services.adoc b/architecture/core_concepts/pods_and_services.adoc index b1f387349ed2..746f3d0157cf 100644 --- a/architecture/core_concepts/pods_and_services.adoc +++ b/architecture/core_concepts/pods_and_services.adoc @@ -12,179 +12,173 @@ toc::[] == Pods -In Kubernetes environments, like OpenShift, a pod is a group of shared -link:containers_and_images.html#containers[docker containers] on a host, and the -smallest deployable unit that can be created, scheduled, and managed. - -Each pod has its own IP address, therefore owning its entire port space, and -containers within pods can share storage. Pods can be "tagged" with one or more -labels, which are then used to select and manage groups of pods in a single -operation. - -.Pod Object Definition +OpenShift leverages the Kubernetes concept of a `*pod*`, which is one or +more link:containers_and_images.html#containers[containers] deployed +together on one host, and the smallest compute unit that can be defined, +deployed, and managed. + +Pods are the rough equivalent of OpenShift v2 gears, with containers +the rough equivalent of v2 cartridge instances. Each pod is allocated +its own internal IP address, therefore owning its entire port space, +and containers within pods can share their local storage and networking. + +Pods have a lifecycle; they are defined, then they are assigned to run on +a node, then they run until their container(s) exit or they are removed +for some other reason. Pods, depending on policy and exit code, may be +removed after exiting, or may be retained in order to enable access to +the logs of their containers. + +OpenShift treats pods as largely immutable; changes cannot be made to +a pod definition while it is running. OpenShift implements changes by +terminating an existing pod and recreating it with modified configuration, +base image(s), or both. Pods are also treated as expendable, and do not +maintain state when recreated. Therefore pods should usually be managed by +higher-level link:deployments.html#replication-controllers[controllers], +rather than directly by users. + +Below is an example definition of a pod that provides a long-running +service, which is actually a part of the OpenShift infrastructure: the +private Docker registry. It demonstrates many features of pods, most of +which are discussed in other topics and thus only briefly mentioned here: + +.Pod Object Definition (YAML) ==== -[source,json] +[source,yaml] ---- -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "e9bae2ce-9761-11e4-86f8-f0def1de880f", - "namespace": "default", - "selfLink": "/api/v1/namespaces/default/pods/e9bae2ce-9761-11e4-86f8-f0def1de880f", - "uid": "e9bae2ce-9761-11e4-86f8-f0def1de880f", - "resourceVersion": "14", - "creationTimestamp": "2015-01-08T18:12:31Z", - "annotations": { - "deployment": "docker-registry-1" <1> - } - }, - "spec": { - "containers": [ - { - "name": "deployment", - "image": "openshift/origin-deployer", <2> - "env": [ - { - "name": "OPENSHIFT_DEPLOYMENT_NAME", - "value": "docker-registry-1" - }, - { - "name": "OPENSHIFT_DEPLOYMENT_NAMESPACE", - "value": "default" - }, - { - "name": "KUBERNETES_MASTER", - "value": "http://10.18.57.24:8080" - }, - { - "name": "OPENSHIFT_MASTER", - "value": "http://10.18.57.24:8080" - } - ], - "resources": {}, - "terminationMessagePath": "/dev/termination-log", - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": {}, - "privileged": false - } - } - ], - "restartPolicy": "Never", - "dnsPolicy": "ClusterFirst" - }, - "status": { - "phase": "Failed", - "podIP": "172.17.0.2", - "containerStatuses": [ - { - "name": "deployment", - "state": { - "termination": { - "exitCode": 255, - "startedAt": "2015-01-08T18:12:41Z", - "finishedAt": "2015-01-08T18:12:42Z" - } - }, - "lastState": {}, - "ready": false, - "restartCount": 0, - "image": "openshift/origin-deployer", - "imageID": "", - "containerID": "docker://0d9b9c3dee08c6b5f22ef5d6fcba2f3991d713c6b337d036d5434b496ae207ef" - }, - { - "name": "net", - "state": { - "running": { - "startedAt": "2015-01-13T12:10:50Z" - } - }, - "lastState": {}, - "ready": false, - "restartCount": 1, - "image": "kubernetes/pause:latest", - "imageID": "", - "containerID": "docker://4617946052b093310d14516e14279232da1a220bcf81a46b50dc94ae11065ea2" - } - ] - } -} +apiVersion: v1 +kind: Pod +metadata: + annotations: { ... } + labels: <1> + deployment: docker-registry-1 + deploymentconfig: docker-registry + docker-registry: default + generateName: docker-registry-1- <2> +spec: + containers: <3> + - env: <4> + - name: OPENSHIFT_CA_DATA + value: ... + - name: OPENSHIFT_CERT_DATA + value: ... + - name: OPENSHIFT_INSECURE + value: "false" + - name: OPENSHIFT_KEY_DATA + value: ... + - name: OPENSHIFT_MASTER + value: https://master.example.com:8443 + image: openshift/origin-docker-registry:v0.6.2 <5> + imagePullPolicy: IfNotPresent + name: registry + ports: <6> + - containerPort: 5000 + protocol: TCP + resources: {} + securityContext: { ... } <7> + volumeMounts: <8> + - mountPath: /registry + name: registry-storage + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: default-token-br6yz + readOnly: true + dnsPolicy: ClusterFirst + imagePullSecrets: + - name: default-dockercfg-at06w + restartPolicy: Always + serviceAccount: default <9> + volumes: <10> + - emptyDir: {} + name: registry-storage + - name: default-token-br6yz + secret: + secretName: default-token-br6yz ---- ==== -<1> The labels are stored in key/value format in the `*annotation*` hash. The -label in this example is *deployment=docker-registry-1*. -<2> The docker image(s) that define the pod are provided in the `containers` -list along with related environment variable mappings. + +<1> Pods can be "tagged" with one or more link:#labels[labels], which can then be used +to select and manage groups of pods in a single operation. +The labels are stored in key/value format in the `*metadata*` hash. One +label in this example is *docker-registry=default*. +<2> Pods must have a unique name within their +link:projects_and_users.html#namespaces[namespace]. A pod definition may specify +the basis of a name with the `*generateName*` attribute, and random characters will +be added automatically to generate a unique name. +<3> `*containers*` specifies an array of container definitions; in this case (as with most), just one. +<4> Environment variables can be specified to pass necessary values to each container. +<5> Each container in the pod is instantiated from its own link:containers_and_images.html#docker-images[Docker image]. +<6> The container can bind to ports which will be made available on the pod's IP. +<7> OpenShift defines a security context for containers which specifies whether they are allowed +to run as privileged containers, run as a user of their choice, and more. The default context is +very restrictive but administrators can modify this as needed. +<8> The container specifies where external storage volumes should +be mounted within the container. In this case, there is a volume for +storing the registry's data, and one for access to credentials the +registry needs for making requests against the OpenShift API. +<9> Pods making requests against the OpenShift API is a common enough +pattern that there is a `*serviceAccount*` field for specifying which +service account user the pod should authenticate as when making +the requests. This enables fine-grained access control for custom +infrastructure components. +<10> The pod defines storage volumes that are available to its +container(s) to use. In this case, it provides an ephemeral volume for +the registry storage and a `*secret*` volume containing the service +account credentials. + +Note that this pod definition does not include attributes that +are filled by OpenShift automatically after the pod is created and +its lifecycle begins. For complete details of the pod REST API object +attributes, consult the link:../../rest_api/kubernetes_v1.html[Kubernetes +API documentation]. See also the +link:https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/pods.md[Kubernetes +pod documentation] for more about the functionality and purpose of pods. == Services -A service identifies a set of link:#pods[pods] and proxies the connections it -receives to them. Pods can be added or taken away from a service any number of -times. +A Kubernetes `*service*` serves as an internal load balancer. It identifies +a set of replicated link:#pods[pods] in order to proxy the connections it +receives to them. Backing pods can be added to or removed from a service +arbitrarily while the service remains consistently available, enabling +anything that depends on the service to refer to it at a consistent +internal address. -Services assign clients an IP address and port pair that, when accessed, -redirect to the appropriate back end. A service uses a label selector to find +Services are assigned an IP address and port pair that, when accessed, +proxy to an appropriate backing pod. A service uses a label selector to find all the containers running that provide a certain network service on a certain -port. The service is then bound to a local port, so to access the service from -inside your application or container you simply bind to the local network on the -port number for the service. +port. -Like pods, services are REST objects. To create a new service, a service -definition can be sent to the API server using a `POST` operation. The following -example shows the definition of a service with a name of *frontend*, which -forwards to container TCP port *8080* on any pod with the *name=frontend* label -attached: +Like pods, services are REST objects. The following +example shows the definition of a service for the pod defined above: -.Service Object Definition +.Service Object Definition (YAML) ==== -[source,json] +[source,yaml] ---- -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "frontend", - "namespace": "myproject", <1> - "selfLink": "/api/v1/namespaces/myproject/services/frontend", - "uid": "cb733818-ea98-11e4-a239-0800279696e1", - "resourceVersion": "204", - "creationTimestamp": "2015-04-24T15:44:29Z", - "labels": { - "template": "application-template-dockerbuild" - } - }, - "spec": { - "ports": [ - { - "protocol": "TCP", - "port": 5432, <2> - "targetPort": 8080, <3> - "nodePort": 0 - } - ], - "selector": { - "name": "frontend" <4> - }, - "portalIP": "172.30.217.106", <5> - "type": "ClusterIP", - "sessionAffinity": "None" - } -} +apiVersion: v1 +kind: Service +metadata: + name: docker-registry <1> +spec: + selector: <2> + docker-registry: default + portalIP: 172.30.136.123 <3> + ports: + - nodePort: 0 + port: 5000 <4> + protocol: TCP + targetPort: 5000 ---- -<1> Service name of *frontend*. -<2> Port the service runs on. -<3> Port on the container to which the service forwards connections. -<4> Label selector finds all containers with the *name=frontend* label attached. -<5> Virtual IP of the service. Automatically assigned by the Kubernetes master -at creation and used by -link:../infrastructure_components/kubernetes_infrastructure.html#service-proxy[service -proxies]. +<1> The service name *docker-registry* also is used to construct an +environment variable with the service IP that is inserted into other +pods in the same namespace. +<2> The label selector identifies all pods with the +*docker-registry=frontend* label attached as its backing pods. +<3> Virtual IP of the service, allocated automatically at creation from a pool of internal IPs. +<4> Port the service listens on. +<5> Port on the backing pods to which the service forwards connections. ==== See the @@ -193,23 +187,30 @@ documentation] for more information on services. == Labels -Labels are used to organize, group, or select objects and resources, such as -pods. Pods are "tagged" with labels, and then services and replication -controllers use labels to indicate the pods they relate to. This makes it -possible for services and replication controllers to reference groups of pods, -or treat pods with potentially different docker containers as similar entities. +Labels are used to organize, group, or select API objects. +For example, link:#pods[pods] are "tagged" with labels, and then +link:#service[services] use label selectors to identify the pods they +proxy to. This makes it possible for services to reference groups of +pods, even treating pods with potentially different docker containers +as related entities. -Labels are a key/value pair, and shown in the following example: +Most objects can include labels in their metadata. So labels can +be used to group arbitrarily-related objects, for instance, +all of the link:#pods[pods], link:#service[services], +link:deployments.html#replication-controllers[replication +controllers], and +link:deployments.html#deployments-and-deployment-configurations[deployment +configurations] of a particular application. + +Labels are simple key/value pairs, as in the following example: ==== -[source,json] +[source,yaml] ---- - -"labels": { - "key1" : "value1", - "key2" : "value2" -} +labels: + key1: value1 + key2: value2 ---- ==== @@ -218,11 +219,11 @@ Consider: - A pod consisting of an *nginx* docker container, with the label *role=webserver*. -- A pod consisting of an *Apache* docker container, with the same label +- A pod consisting of an *Apache httpd* docker container, with the same label *role=webserver*. A service or replication controller that is defined to use pods with the -`role=webserver` label treats both of these pods as part of the same group. +*role=webserver* label treats both of these pods as part of the same group. See the https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/labels.md[Kubernetes