mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Merge pull request #9086 from jeffmendoza/environment-guide
Add Environment Guide example.
This commit is contained in:
commit
81213cec0c
92
examples/environment-guide/README.md
Normal file
92
examples/environment-guide/README.md
Normal file
@ -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).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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 <public ip>: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 <ip>` 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
|
||||||
|
|
||||||
|
|
||||||
|
[]()
|
30
examples/environment-guide/backend-rc.yaml
Normal file
30
examples/environment-guide/backend-rc.yaml
Normal file
@ -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
|
13
examples/environment-guide/backend-srv.yaml
Normal file
13
examples/environment-guide/backend-srv.yaml
Normal file
@ -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
|
23
examples/environment-guide/containers/README.md
Normal file
23
examples/environment-guide/containers/README.md
Normal file
@ -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/<project-name>/show .
|
||||||
|
gcloud preview docker push gcr.io/<project-name>/show
|
||||||
|
|
||||||
|
Docker Hub
|
||||||
|
----------
|
||||||
|
docker build -t <username>/show .
|
||||||
|
docker push <username>/show
|
||||||
|
|
||||||
|
Change Pod Definitions
|
||||||
|
----------------------
|
||||||
|
Edit both `show-rc.yaml` and `backend-rc.yaml` and replace the
|
||||||
|
specified `image:` with the one that you built.
|
||||||
|
|
||||||
|
|
||||||
|
[]()
|
2
examples/environment-guide/containers/backend/Dockerfile
Normal file
2
examples/environment-guide/containers/backend/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM golang:onbuild
|
||||||
|
EXPOSE 8080
|
37
examples/environment-guide/containers/backend/backend.go
Normal file
37
examples/environment-guide/containers/backend/backend.go
Normal file
@ -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))
|
||||||
|
}
|
2
examples/environment-guide/containers/show/Dockerfile
Normal file
2
examples/environment-guide/containers/show/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM golang:onbuild
|
||||||
|
EXPOSE 8080
|
95
examples/environment-guide/containers/show/show.go
Normal file
95
examples/environment-guide/containers/show/show.go
Normal file
@ -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))
|
||||||
|
}
|
BIN
examples/environment-guide/diagram.png
Normal file
BIN
examples/environment-guide/diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
32
examples/environment-guide/show-rc.yaml
Normal file
32
examples/environment-guide/show-rc.yaml
Normal file
@ -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
|
15
examples/environment-guide/show-srv.yaml
Normal file
15
examples/environment-guide/show-srv.yaml
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user