diff --git a/examples/environment-guide/README.md b/examples/environment-guide/README.md new file mode 100644 index 00000000000..bd796f161c6 --- /dev/null +++ b/examples/environment-guide/README.md @@ -0,0 +1,92 @@ +Environment Guide Example +========================= +This example demonstrates running pods, replication controllers, and +services. It shows two types of pods: frontend and backend, with +services on top of both. Accessing the frontend pod will return +environment information about itself, and a backend pod that it has +accessed through the service. The goal is to illuminate the +environment metadata available to running containers inside the +Kubernetes cluster. The documentation for the kubernetes environment +is [here](/docs/container-environment.md). + +![Diagram](diagram.png) + +Prerequisites +------------- +This example assumes that you have a Kubernetes cluster installed and +running, and that you have installed the `kubectl` command line tool +somewhere in your path. Please see the [getting +started](/docs/getting-started-guides) for installation instructions +for your platform. + +Optional: Build your own containers +----------------------------------- +The code for the containers is under +[containers/](containers) + +Get everything running +---------------------- + + kubectl create -f ./backend-rc.yaml + kubectl create -f ./backend-srv.yaml + kubectl create -f ./show-rc.yaml + kubectl create -f ./show-srv.yaml + +Query the service +----------------- +Use `kubectl describe service show-srv` to determine the public IP of +your service. + +> Note: If your platform does not support external load balancers, + you'll need to open the proper port and direct traffic to the + internal IP shown for the frontend service with the above command + +Run `curl :80` to query the service. You should get +something like this back: + +``` +Pod Name: show-rc-xxu6i +Pod Namespace: default +USER_VAR: important information + +Kubenertes environment variables +BACKEND_SRV_SERVICE_HOST = 10.147.252.185 +BACKEND_SRV_SERVICE_PORT = 5000 +KUBERNETES_RO_SERVICE_HOST = 10.147.240.1 +KUBERNETES_RO_SERVICE_PORT = 80 +KUBERNETES_SERVICE_HOST = 10.147.240.2 +KUBERNETES_SERVICE_PORT = 443 +KUBE_DNS_SERVICE_HOST = 10.147.240.10 +KUBE_DNS_SERVICE_PORT = 53 + +Found backend ip: 10.147.252.185 port: 5000 +Response from backend +Backend Container +Backend Pod Name: backend-rc-6qiya +Backend Namespace: default +``` + +First the frontend pod's information is printed. The pod name and +[namespace](/docs/design/namespaces.md) are retreived from the +[Downward API](/docs/downward_api.md). Next, `USER_VAR` is the name of +an environment variable set in the [pod +definition](show-rc.yaml). Then, the dynamic kubernetes environment +variables are scanned and printed. These are used to find the backend +service, named `backend-srv`. Finally, the frontend pod queries the +backend service and prints the information returned. Again the backend +pod returns its own pod name and namespace. + +Try running the `curl` command a few times, and notice what +changes. Ex: `watch -n 1 curl -s ` Firstly, the frontend service +is directing your request to different frontend pods each time. The +frontend pods are always contacting the backend through the backend +service. This results in a different backend pod servicing each +request as well. + +Cleanup +------- + kubectl delete rc,service -l type=show-type + kubectl delete rc,service -l type=backend-type + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/environment-guide/README.md?pixel)]() diff --git a/examples/environment-guide/backend-rc.yaml b/examples/environment-guide/backend-rc.yaml new file mode 100644 index 00000000000..6c57b95dac9 --- /dev/null +++ b/examples/environment-guide/backend-rc.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: backend-rc + labels: + type: backend-type +spec: + replicas: 3 + template: + metadata: + labels: + type: backend-type + spec: + containers: + - name: backend-container + image: gcr.io/google-samples/env-backend:1.1 + imagePullPolicy: Always + ports: + - containerPort: 5000 + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace diff --git a/examples/environment-guide/backend-srv.yaml b/examples/environment-guide/backend-srv.yaml new file mode 100644 index 00000000000..7083b37bf88 --- /dev/null +++ b/examples/environment-guide/backend-srv.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: backend-srv + labels: + type: backend-type +spec: + ports: + - port: 5000 + protocol: TCP + selector: + type: backend-type diff --git a/examples/environment-guide/containers/README.md b/examples/environment-guide/containers/README.md new file mode 100644 index 00000000000..2e08760ce14 --- /dev/null +++ b/examples/environment-guide/containers/README.md @@ -0,0 +1,23 @@ +Building +-------- +For each container, the build steps are the same. The examples below +are for the `show` container. Replace `show` with `backend` for the +backend container. + +GCR +--- + docker build -t gcr.io//show . + gcloud preview docker push gcr.io//show + +Docker Hub +---------- + docker build -t /show . + docker push /show + +Change Pod Definitions +---------------------- +Edit both `show-rc.yaml` and `backend-rc.yaml` and replace the +specified `image:` with the one that you built. + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/environment-guide/containers/README.md?pixel)]() diff --git a/examples/environment-guide/containers/backend/Dockerfile b/examples/environment-guide/containers/backend/Dockerfile new file mode 100644 index 00000000000..3fa58ff7abe --- /dev/null +++ b/examples/environment-guide/containers/backend/Dockerfile @@ -0,0 +1,2 @@ +FROM golang:onbuild +EXPOSE 8080 diff --git a/examples/environment-guide/containers/backend/backend.go b/examples/environment-guide/containers/backend/backend.go new file mode 100644 index 00000000000..b4edf75ff5d --- /dev/null +++ b/examples/environment-guide/containers/backend/backend.go @@ -0,0 +1,37 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "log" + "net/http" + "os" +) + +func printInfo(resp http.ResponseWriter, req *http.Request) { + name := os.Getenv("POD_NAME") + namespace := os.Getenv("POD_NAMESPACE") + fmt.Fprintf(resp, "Backend Container\n") + fmt.Fprintf(resp, "Backend Pod Name: %v\n", name) + fmt.Fprintf(resp, "Backend Namespace: %v\n", namespace) +} + +func main() { + http.HandleFunc("/", printInfo) + log.Fatal(http.ListenAndServe(":5000", nil)) +} diff --git a/examples/environment-guide/containers/show/Dockerfile b/examples/environment-guide/containers/show/Dockerfile new file mode 100644 index 00000000000..3fa58ff7abe --- /dev/null +++ b/examples/environment-guide/containers/show/Dockerfile @@ -0,0 +1,2 @@ +FROM golang:onbuild +EXPOSE 8080 diff --git a/examples/environment-guide/containers/show/show.go b/examples/environment-guide/containers/show/show.go new file mode 100644 index 00000000000..56bd988b400 --- /dev/null +++ b/examples/environment-guide/containers/show/show.go @@ -0,0 +1,95 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "io" + "log" + "net/http" + "os" + "sort" + "strings" +) + +func getKubeEnv() (map[string]string, error) { + environS := os.Environ() + environ := make(map[string]string) + for _, val := range environS { + split := strings.Split(val, "=") + if len(split) != 2 { + return environ, fmt.Errorf("Some weird env vars") + } + environ[split[0]] = split[1] + } + for key := range environ { + if !(strings.HasSuffix(key, "_SERVICE_HOST") || + strings.HasSuffix(key, "_SERVICE_PORT")) { + delete(environ, key) + } + } + return environ, nil +} + +func printInfo(resp http.ResponseWriter, req *http.Request) { + kubeVars, err := getKubeEnv() + if err != nil { + http.Error(resp, err.Error(), http.StatusInternalServerError) + return + } + + backendHost := os.Getenv("BACKEND_SRV_SERVICE_HOST") + backendPort := os.Getenv("BACKEND_SRV_SERVICE_PORT") + backendRsp, backendErr := http.Get(fmt.Sprintf( + "http://%v:%v/", + backendHost, + backendPort)) + if backendErr == nil { + defer backendRsp.Body.Close() + } + + name := os.Getenv("POD_NAME") + namespace := os.Getenv("POD_NAMESPACE") + fmt.Fprintf(resp, "Pod Name: %v \n", name) + fmt.Fprintf(resp, "Pod Namespace: %v \n", namespace) + + envvar := os.Getenv("USER_VAR") + fmt.Fprintf(resp, "USER_VAR: %v \n", envvar) + + fmt.Fprintf(resp, "\nKubenertes environment variables\n") + var keys []string + for key := range kubeVars { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + fmt.Fprintf(resp, "%v = %v \n", key, kubeVars[key]) + } + + fmt.Fprintf(resp, "\nFound backend ip: %v port: %v\n", backendHost, backendPort) + if backendErr == nil { + fmt.Fprintf(resp, "Response from backend\n") + io.Copy(resp, backendRsp.Body) + } else { + fmt.Fprintf(resp, "Error from backend: %v", backendErr.Error()) + } +} + +func main() { + http.HandleFunc("/", printInfo) + log.Fatal(http.ListenAndServe(":8080", nil)) +} diff --git a/examples/environment-guide/diagram.png b/examples/environment-guide/diagram.png new file mode 100644 index 00000000000..dd5d1551631 Binary files /dev/null and b/examples/environment-guide/diagram.png differ diff --git a/examples/environment-guide/show-rc.yaml b/examples/environment-guide/show-rc.yaml new file mode 100644 index 00000000000..4de94c06ca3 --- /dev/null +++ b/examples/environment-guide/show-rc.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: show-rc + labels: + type: show-type +spec: + replicas: 3 + template: + metadata: + labels: + type: show-type + spec: + containers: + - name: show-container + image: gcr.io/google-samples/env-show:1.1 + imagePullPolicy: Always + ports: + - containerPort: 8080 + protocol: TCP + env: + - name: USER_VAR + value: important information + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace diff --git a/examples/environment-guide/show-srv.yaml b/examples/environment-guide/show-srv.yaml new file mode 100644 index 00000000000..25a2d7473e0 --- /dev/null +++ b/examples/environment-guide/show-srv.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: show-srv + labels: + type: show-type +spec: + type: LoadBalancer + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + type: show-type