mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Add ability to consume secrets in env vars
This commit is contained in:
parent
dc83a11758
commit
c548054560
16
docs/user-guide/secrets/secret-env-pod.yaml
Normal file
16
docs/user-guide/secrets/secret-env-pod.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: secret-env-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: test-container
|
||||
image: gcr.io/google_containers/busybox
|
||||
command: [ "/bin/sh", "-c", "env" ]
|
||||
env:
|
||||
- name: MY_SECRET_DATA
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: test-secret
|
||||
key: data-1
|
||||
restartPolicy: Never
|
@ -354,8 +354,9 @@ func TestExampleObjectSchemas(t *testing.T) {
|
||||
"rc": &api.ReplicationController{},
|
||||
},
|
||||
"../docs/user-guide/secrets": {
|
||||
"secret-pod": &api.Pod{},
|
||||
"secret": &api.Secret{},
|
||||
"secret-pod": &api.Pod{},
|
||||
"secret": &api.Secret{},
|
||||
"secret-env-pod": &api.Pod{},
|
||||
},
|
||||
"../examples/spark": {
|
||||
"spark-master-controller": &api.ReplicationController{},
|
||||
|
@ -560,8 +560,8 @@ type GitRepoVolumeSource struct {
|
||||
// as files using the keys in the Data field as the file names.
|
||||
// Secret volumes support ownership management and SELinux relabeling.
|
||||
type SecretVolumeSource struct {
|
||||
// Name of the secret in the pod's namespace to use
|
||||
SecretName string `json:"secretName"`
|
||||
// Name of the secret in the pod's namespace to use.
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// Represents an NFS mount that lasts the lifetime of a pod.
|
||||
@ -721,6 +721,8 @@ type EnvVarSource struct {
|
||||
FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty"`
|
||||
// Selects a key of a ConfigMap.
|
||||
ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
|
||||
// Selects a key of a secret in the pod's namespace.
|
||||
SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectFieldSelector selects an APIVersioned field of an object.
|
||||
@ -741,6 +743,14 @@ type ConfigMapKeySelector struct {
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// SecretKeySelector selects a key of a Secret.
|
||||
type SecretKeySelector struct {
|
||||
// The name of the secret in the pod's namespace to select from.
|
||||
LocalObjectReference `json:",inline"`
|
||||
// The key of the secret to select from. Must be a valid secret key.
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// HTTPGetAction describes an action based on HTTP Get requests.
|
||||
type HTTPGetAction struct {
|
||||
// Optional: Path to access on the HTTP server.
|
||||
|
@ -724,9 +724,9 @@ type GitRepoVolumeSource struct {
|
||||
// as files using the keys in the Data field as the file names.
|
||||
// Secret volumes support ownership management and SELinux relabeling.
|
||||
type SecretVolumeSource struct {
|
||||
// SecretName is the name of a secret in the pod's namespace.
|
||||
// Name of the secret in the pod's namespace to use.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#secrets
|
||||
SecretName string `json:"secretName"`
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
}
|
||||
|
||||
// Represents an NFS mount that lasts the lifetime of a pod.
|
||||
@ -847,6 +847,8 @@ type EnvVarSource struct {
|
||||
FieldRef *ObjectFieldSelector `json:"fieldRef,omitempty"`
|
||||
// Selects a key of a ConfigMap.
|
||||
ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
|
||||
// Selects a key of a secret in the pod's namespace
|
||||
SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectFieldSelector selects an APIVersioned field of an object.
|
||||
@ -865,6 +867,14 @@ type ConfigMapKeySelector struct {
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// SecretKeySelector selects a key of a Secret.
|
||||
type SecretKeySelector struct {
|
||||
// The name of the secret in the pod's namespace to select from.
|
||||
LocalObjectReference `json:",inline"`
|
||||
// The key of the secret to select from. Must be a valid secret key.
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// HTTPGetAction describes an action based on HTTP Get requests.
|
||||
type HTTPGetAction struct {
|
||||
// Path to access on the HTTP server.
|
||||
|
@ -1369,6 +1369,7 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Contain
|
||||
var (
|
||||
tmpEnv = make(map[string]string)
|
||||
configMaps = make(map[string]*apiextensions.ConfigMap)
|
||||
secrets = make(map[string]*api.Secret)
|
||||
mappingFunc = expansion.MappingFuncFor(tmpEnv, serviceEnv)
|
||||
)
|
||||
for _, envVar := range container.Env {
|
||||
@ -1405,6 +1406,21 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Contain
|
||||
if !ok {
|
||||
return result, fmt.Errorf("Couldn't find key %v in ConfigMap %v/%v", key, pod.Namespace, name)
|
||||
}
|
||||
case envVar.ValueFrom.SecretKeyRef != nil:
|
||||
name := envVar.ValueFrom.SecretKeyRef.Name
|
||||
key := envVar.ValueFrom.SecretKeyRef.Key
|
||||
secret, ok := secrets[name]
|
||||
if !ok {
|
||||
secret, err = kl.kubeClient.Secrets(pod.Namespace).Get(name)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
runtimeValBytes, ok := secret.Data[key]
|
||||
if !ok {
|
||||
return result, fmt.Errorf("Couldn't find key %v in Secret %v/%v", key, pod.Namespace, name)
|
||||
}
|
||||
runtimeVal = string(runtimeValBytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
var _ = Describe("Secrets", func() {
|
||||
f := NewFramework("secrets")
|
||||
|
||||
It("should be consumable from pods [Conformance]", func() {
|
||||
It("should be consumable from pods in volume [Conformance]", func() {
|
||||
name := "secret-test-" + string(util.NewUUID())
|
||||
volumeName := "secret-volume"
|
||||
volumeMountPath := "/etc/secret-volume"
|
||||
@ -74,7 +74,7 @@ var _ = Describe("Secrets", func() {
|
||||
},
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "secret-test",
|
||||
Name: "secret-volume-test",
|
||||
Image: "gcr.io/google_containers/mounttest:0.2",
|
||||
Args: []string{
|
||||
"--file_content=/etc/secret-volume/data-1",
|
||||
@ -97,4 +97,63 @@ var _ = Describe("Secrets", func() {
|
||||
"mode of file \"/etc/secret-volume/data-1\": -r--r--r--",
|
||||
}, f.Namespace.Name)
|
||||
})
|
||||
|
||||
It("should be consumable from pods in env vars [Conformance]", func() {
|
||||
name := "secret-test-" + string(util.NewUUID())
|
||||
|
||||
secret := &api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Namespace: f.Namespace.Name,
|
||||
Name: name,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"data-1": []byte("value-1"),
|
||||
},
|
||||
}
|
||||
|
||||
By(fmt.Sprintf("Creating secret with name %s", secret.Name))
|
||||
defer func() {
|
||||
By("Cleaning up the secret")
|
||||
if err := f.Client.Secrets(f.Namespace.Name).Delete(secret.Name); err != nil {
|
||||
Failf("unable to delete secret %v: %v", secret.Name, err)
|
||||
}
|
||||
}()
|
||||
var err error
|
||||
if secret, err = f.Client.Secrets(f.Namespace.Name).Create(secret); err != nil {
|
||||
Failf("unable to create test secret %s: %v", secret.Name, err)
|
||||
}
|
||||
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "pod-secrets-" + string(util.NewUUID()),
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "secret-env-test",
|
||||
Image: "gcr.io/google_containers/busybox",
|
||||
Command: []string{"sh", "-c", "env"},
|
||||
Env: []api.EnvVar{
|
||||
{
|
||||
Name: "SECRET_DATA",
|
||||
ValueFrom: &api.EnvVarSource{
|
||||
SecretKeyRef: &api.SecretKeySelector{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: name,
|
||||
},
|
||||
Key: "data-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: api.RestartPolicyNever,
|
||||
},
|
||||
}
|
||||
|
||||
testContainerOutput("consume secrets", f.Client, pod, 0, []string{
|
||||
"SECRET_DATA=value-1",
|
||||
}, f.Namespace.Name)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user