Skip to content

Commit

Permalink
updates to service injection policy proposal
Browse files Browse the repository at this point in the history
Signed-off-by: Jess Frazelle <acidburn@google.com>
  • Loading branch information
jessfraz committed Jan 18, 2017
1 parent 0ed6327 commit 653908b
Show file tree
Hide file tree
Showing 2 changed files with 279 additions and 65 deletions.
279 changes: 279 additions & 0 deletions contributors/design-proposals/service-injection-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
# Service Injection Policy

## Abstract

Describes a policy resource that allows loose coupling from services to the pods
that consume them.

## Motivation

Consuming a service involves more than just connectivity. In addition to
coordinates to reach the service, credentials and non-secret configuration
parameters are typically needed to use the service. The primitives for this
already exist, but a gap exists where loose coupling is desired: it should be
possible to inject pods with the information they need to use a service on a
service-by-service basis, without the pod authors having to incorporate the
information into every pod spec where it is needed.

## Constraints and Assumptions

1. New mechanisms must be made to work with controllers such as deployments and
replicasets that create pods. Existing controllers that create pods should
recreate their pods when a new Service Injection Policy is added that would
effect them.

## Use Cases

1. As a user, I want to be able to describe a way that pods should be injected
with the information to consume a particular service in a loosely-coupled
way, so that I can concisely model the information about how the service
should be consumed without altering every consuming pod spec.

### Loose coupling between services and their consumers

Using a Service Injection Policy allows pod authors to not have to explicitly
set information for every pod. The information will be injected based off the
policy's `Selector`.

## Proposed Changes

### ServiceInjectionPolicy API object

```go
type ServiceInjectionPolicy struct {
unversioned.TypeMeta
ObjectMeta

Spec ServiceInjectionPolicySpec
}

type ServiceInjectionPolicySpec struct {
// Service is a reference to the service being injected (optional, immutable).
Service string
// Selector defines which Pods should be modified (required, immutable).
Selector *unversioned.LabelSelector
// Env defines the collection of EnvVar to inject (optional, mutable).
Env []EnvVar
// EnvFrom defines the collection of EnvVarFrom to inject (optional, mutable).
EnvFrom []EnvVarFrom
// Volumes defines the collection of Volume to inject (optional, mutable).
Volumes []Volume
// VolumeMounts defines the collection of VolumeMount to inject (optional, mutable).
VolumeMounts []VolumeMount
}
```

### AdmissionControl Plugin: ServiceInjectionPolicy

The **ServiceInjectionPolicy** plugin introspects all incoming pod creation
requests and injects the pod based off a `LabelSelector` with the desired
attributes.

#### Behavior

This will modify the containers in the pod spec. The supported changes to
`Env`, `EnvFrom`, and `VolumeMounts` apply to the container spec for
all containers in the pod with the specified matching `Selector`. The
changes to `Volumes` apply to the pod spec for all pods matching `Selector`.

*Why modify all containers in a pod?*

Currently there is no concept of labels on specific containers in a pod which
would be necessary for per-container service injections. We could add labels
for specific containers which would allow this and be the best solution to not
injecting all. Container labels have been discussed various times through
multiple issues and proposals, which all congregate to this thread on the
[kubernetes-sig-node mailing
list](https://groups.google.com/forum/#!topic/kubernetes-sig-node/gijxbYC7HT8).

Other solutions include basing the container to inject based off
matching its name to another field in the `ServiceInjectionPolicy` spec, but
this would not scale well and would cause annoyance with configuration
management.

The resultant modified pod spec will be annotated to show that it was modified by
the `ServiceInjectionPolicy`.

#### Optional Behavior with implicit injections

The above described the behavior for explicitly defining what should be
injected into a pod.

But a helper has been discussed to automatically fill in the
`ServiceInjectionSpec` values based off annotations on a service defining the
resources you need. This would be similar to the functionality ConfigMaps and
Secrets.

## Examples

### Simple Pod Spec Example

This is a simple example to show how a Pod spec is modified by the Service
Injection Policy.

**User submitted pod spec:**

```yaml
apiVersion: v1
kind: Pod
metadata:
name: website
labels:
app: website
role: frontend
spec:
containers:
- name: website
image: ecorp/website
ports:
- containerPort: 80
```
**Example service injection policy:**
```yaml
kind: ServiceInjectionPolicy
apiVersion: extensions/v1beta1
metadata:
name: allow-database
namespace: myns
spec:
service: db
selector:
matchLabels:
role: frontend
env:
- name: DB_PORT
value: 6379
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
```
**Pod spec after admission controller:**
```yaml
apiVersion: v1
kind: Pod
metadata:
name: website
labels:
app: website
role: frontend
annotations:
serviceinjectionpolicy.k8s.io/db: allow-database
spec:
containers:
- name: website
image: ecorp/website
volumeMounts:
- mountPath: /cache
name: cache-volume
ports:
- containerPort: 80
env:
- name: DB_PORT
value: 6379
volumes:
- name: cache-volume
emptyDir: {}
```
### ReplicaSet with Pod Spec Example
The following example shows that only the pod spec is modified by the Service
Injection Policy.
**User submitted ReplicaSet:**
```yaml
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
```
**Example service injection policy:**
```yaml
kind: ServiceInjectionPolicy
apiVersion: extensions/v1beta1
metadata:
name: allow-database
namespace: myns
spec:
service: db
selector:
matchLabels:
tier: frontend
env:
- name: DB_PORT
value: 6379
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
```
**Pod spec after admission controller:**
```yaml
kind: Pod
metadata:
labels:
app: guestbook
tier: frontend
annotations:
serviceinjectionpolicy.k8s.io/db: allow-database
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /cache
name: cache-volume
env:
- name: GET_HOSTS_FROM
value: dns
- name: DB_PORT
value: 6379
ports:
- containerPort: 80
volumes:
- name: cache-volume
emptyDir: {}
```
65 changes: 0 additions & 65 deletions contributors/design-proposals/service_injection_policy.md

This file was deleted.

0 comments on commit 653908b

Please sign in to comment.