Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
339 changes: 170 additions & 169 deletions architecture/core_concepts/pods_and_services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
----

====
Expand All @@ -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
Expand Down