Merge pull request #3576 from jlowdermilk/examples

Update update-demo example to use kubectl
This commit is contained in:
Maxwell Forbes 2015-01-28 15:43:18 -08:00
commit 5500b1a261
13 changed files with 99 additions and 39 deletions

View File

@ -123,6 +123,10 @@ func TestExampleObjectSchemas(t *testing.T) {
"service": &api.Service{}, "service": &api.Service{},
"replication-controller": &api.ReplicationController{}, "replication-controller": &api.ReplicationController{},
}, },
"../examples/update-demo": {
"kitten-rc": &api.ReplicationController{},
"nautilus-rc": &api.ReplicationController{},
},
} }
for path, expected := range cases { for path, expected := range cases {

View File

@ -24,6 +24,9 @@ echo
echo " http://localhost:8001/static/" echo " http://localhost:8001/static/"
echo echo
export KUBE_ROOT=$(dirname $0)/../..
export KUBECTL=${KUBE_REPO_ROOT}/cluster/kubectl.sh
set -x set -x
../../cluster/kubecfg.sh -proxy -www local/ $KUBECTL proxy --www=local/

View File

@ -23,9 +23,11 @@ if [[ "${DOCKER_HUB_USER+set}" != "set" ]] ; then
exit 1 exit 1
fi fi
export KUBE_REPO_ROOT=${KUBE_REPO_ROOT-$(dirname $0)/../..} export KUBE_ROOT=$(dirname $0)/../..
export KUBECFG=${KUBECFG-$KUBE_REPO_ROOT/cluster/kubecfg.sh} export KUBECTL=${KUBE_REPO_ROOT}/cluster/kubectl.sh
set -x set -x
$KUBECFG -p 8080:80 run $DOCKER_HUB_USER/update-demo:nautilus 2 update-demo SCHEMA=${KUBE_REPO_ROOT}/examples/update-demo/nautilus-rc.yaml
cat ${SCHEMA} | sed "s/DOCKER_HUB_USER/${DOCKER_HUB_USER}/" | ${KUBECTL} create -f -

View File

@ -21,8 +21,8 @@ set -o pipefail
NEW_SIZE=${1:-4} NEW_SIZE=${1:-4}
export KUBE_REPO_ROOT=${KUBE_REPO_ROOT-$(dirname $0)/../..} export KUBE_REPO_ROOT=${KUBE_REPO_ROOT-$(dirname $0)/../..}
export KUBECFG=${KUBECFG-$KUBE_REPO_ROOT/cluster/kubecfg.sh} export KUBECTL=${KUBECTL-$KUBE_REPO_ROOT/cluster/kubectl.sh}
set -x set -x
$KUBECFG resize update-demo $NEW_SIZE $KUBECTL resize rc update-demo-nautilus --replicas=$NEW_SIZE

View File

@ -23,11 +23,13 @@ if [[ "${DOCKER_HUB_USER+set}" != "set" ]] ; then
exit 1 exit 1
fi fi
NEW_IMAGE=${1:-kitten} export KUBE_ROOT=$(dirname $0)/../..
TIMING=${2:-10s} export KUBECTL=${KUBE_ROOT}/cluster/kubectl.sh
export KUBE_REPO_ROOT=${KUBE_REPO_ROOT-$(dirname $0)/../..}
export KUBECFG=${KUBECFG-$KUBE_REPO_ROOT/cluster/kubecfg.sh}
set -x set -x
$KUBECFG -image $DOCKER_HUB_USER/update-demo:$NEW_IMAGE -u $TIMING rollingupdate update-demo NEW_IMAGE=${1:-kitten}
TIMING=${2:-10s}
SCHEMA=${KUBE_ROOT}/examples/update-demo/kitten-rc.yaml
cat ${SCHEMA} | sed "s/DOCKER_HUB_USER/${DOCKER_HUB_USER}/" | ${KUBECTL} rollingupdate update-demo-nautilus -f - --update-period=10s

View File

@ -18,10 +18,11 @@ set -o errexit
set -o nounset set -o nounset
set -o pipefail set -o pipefail
export KUBE_REPO_ROOT=${KUBE_REPO_ROOT-$(dirname $0)/../..} export KUBE_ROOT=$(dirname $0)/../..
export KUBECFG=${KUBECFG-$KUBE_REPO_ROOT/cluster/kubecfg.sh} export KUBECTL=${KUBE_ROOT}/cluster/kubectl.sh
set -x set -x
$KUBECFG stop update-demo rc="update-demo-kitten"
$KUBECFG rm update-demo
$KUBECTL stop rc ${rc}

View File

@ -61,8 +61,8 @@ separate terminal or run it in the background.
http://localhost:8001/static/ http://localhost:8001/static/
+ ../../cluster/kubecfg.sh -proxy -www local/ + ../../cluster/kubectl.sh proxy --www=local/
I0922 11:43:54.886018 15659 kubecfg.go:209] Starting to serve on localhost:8001 I0115 16:50:15.959551 19790 proxy.go:34] Starting to serve on localhost:8001
``` ```
Now visit the the [demo website](http://localhost:8001/static). You won't see anything much quite yet. Now visit the the [demo website](http://localhost:8001/static). You won't see anything much quite yet.
@ -92,12 +92,12 @@ We will now update the docker image to serve a different image by doing a rollin
```bash ```bash
$ ./4-rolling-update.sh $ ./4-rolling-update.sh
``` ```
The rollingUpdate command in kubecfg will do 2 things: The rollingUpdate command in kubectl will do 2 things:
1. Update the template in the replication controller to the new image (`$DOCKER_HUB_USER/update-demo:kitten`) 1. Create a new replication controller with a pod template that uses the new image (`$DOCKER_HUB_USER/update-demo:kitten`)
2. Kill each of the pods one by one. It'll let the replication controller create new pods to replace those that were killed. 2. Resize the old and new replication controllers until the new controller replaces the old. This will kill the current pods one at a time, spinnning up new ones to replace them.
Watch the UX, it will update one pod every 10 seconds until all of the pods have the new image. Watch the [demo website](http://localhost:8001/static/index.html), it will update one pod every 10 seconds until all of the pods have the new image.
### Step Five: Bring down the pods ### Step Five: Bring down the pods

View File

@ -0,0 +1,20 @@
kind: ReplicationController
id: update-demo-kitten
apiVersion: v1beta1
desiredState:
replicaSelector:
name: update-demo
version: kitten
podTemplate:
desiredState:
manifest:
containers:
- name: update-demo
image: DOCKER_HUB_USER/update-demo:kitten
ports:
- hostPort: 8080
containerPort: 80
protocol: TCP
labels:
name: update-demo
version: kitten

View File

@ -46,7 +46,7 @@ var updateServer = function($http, server) {
}; };
var updateData = function($scope, $http) { var updateData = function($scope, $http) {
var servers = $scope.servers var servers = $scope.servers;
for (var i = 0; i < servers.length; ++i) { for (var i = 0; i < servers.length; ++i) {
var server = servers[i]; var server = servers[i];
updateServer($http, server); updateServer($http, server);
@ -69,6 +69,10 @@ var getServer = function($scope, id) {
return null; return null;
}; };
var isUpdateDemoPod = function(pod) {
return pod.labels && pod.labels.name == "update-demo";
};
var update = function($scope, $http) { var update = function($scope, $http) {
if (!$http) { if (!$http) {
console.log("No HTTP!"); console.log("No HTTP!");
@ -79,9 +83,13 @@ var update = function($scope, $http) {
console.log(data); console.log(data);
var newServers = []; var newServers = [];
for (var i = 0; i < data.items.length; ++i) { for (var i = 0; i < data.items.length; ++i) {
var server = getServer($scope, data.items[i].id); var pod = data.items[i];
if (!isUpdateDemoPod(pod)) {
continue;
}
var server = getServer($scope, pod.id);
if (server == null) { if (server == null) {
server = { "id": data.items[i].id }; server = { "id": pod.id };
} }
newServers.push(server); newServers.push(server);
} }

View File

@ -0,0 +1,21 @@
kind: ReplicationController
id: update-demo-nautilus
apiVersion: v1beta1
desiredState:
replicas: 2
replicaSelector:
name: update-demo
version: nautilus
podTemplate:
desiredState:
manifest:
containers:
- name: update-demo
image: DOCKER_HUB_USER/update-demo:nautilus
ports:
- hostPort: 8080
containerPort: 80
protocol: TCP
labels:
name: update-demo
version: nautilus

View File

@ -40,7 +40,7 @@ function validate() {
sleep 2 sleep 2
local pod_id_list local pod_id_list
pod_id_list=($($KUBECFG -template='{{range.items}}{{.id}} {{end}}' -l name="${CONTROLLER_NAME}" list pods)) pod_id_list=($($KUBECTL get pods -o template --template='{{range.items}}{{.id}} {{end}}' -l name="${CONTROLLER_NAME}"))
echo " ${#pod_id_list[@]} out of ${num_replicas} created" echo " ${#pod_id_list[@]} out of ${num_replicas} created"
@ -62,13 +62,13 @@ function validate() {
# This template is unit-tested in kubec{tl|fg}, so if you change it, update the unit test. # This template is unit-tested in kubec{tl|fg}, so if you change it, update the unit test.
# #
# You can read about the syntax here: http://golang.org/pkg/text/template/ # You can read about the syntax here: http://golang.org/pkg/text/template/
template_string="{{and (exists . \"currentState\" \"info\" \"${CONTROLLER_NAME}\" \"state\" \"running\") (exists . \"currentState\" \"info\" \"POD\" \"state\" \"running\")}}" template_string="{{and (exists . \"currentState\" \"info\" \"${CONTROLLER_NAME}\" \"state\" \"running\") (exists . \"currentState\" \"info\" \"net\" \"state\" \"running\")}}"
current_status=$($KUBECFG -template="${template_string}" get "pods/$id") || { current_status=$($KUBECTL get pods "$id" -o template --template="${template_string}") || {
if [[ $current_status =~ "pod \"${id}\" not found" ]]; then if [[ $current_status =~ "pod \"${id}\" not found" ]]; then
echo " $id no longer exists" echo " $id no longer exists"
continue continue
else else
echo " kubecfg failed with error:" echo " kubectl failed with error:"
echo $current_status echo $current_status
exit -1 exit -1
fi fi
@ -81,14 +81,14 @@ function validate() {
echo " $id is created and both POD and update-demo containers are running: $current_status" echo " $id is created and both POD and update-demo containers are running: $current_status"
template_string="{{(index .currentState.info \"${CONTROLLER_NAME}\").image}}" template_string="{{(index .currentState.info \"${CONTROLLER_NAME}\").image}}"
current_image=$($KUBECFG -template="${template_string}" get "pods/$id") || true current_image=$($KUBECTL get pods "$id" -o template --template="${template_string}") || true
if [[ "$current_image" != "${DOCKER_HUB_USER}/update-demo:${container_image_version}" ]]; then if [[ "$current_image" != "${DOCKER_HUB_USER}/update-demo:${container_image_version}" ]]; then
echo " ${id} is created but running wrong image" echo " ${id} is created but running wrong image"
continue continue
fi fi
host_ip=$($KUBECFG -template='{{.currentState.hostIP}}' get pods/$id) host_ip=$($KUBECTL get pods "$id" -o template --template='{{.currentState.hostIP}}')
curl -s --max-time 5 --fail http://${host_ip}:8080/data.json \ curl -s --max-time 5 --fail http://${host_ip}:8080/data.json \
| grep -q ${container_image_version} || { | grep -q ${container_image_version} || {
echo " ${id} is running the right image but curl to contents failed or returned wrong info" echo " ${id} is running the right image but curl to contents failed or returned wrong info"
@ -104,7 +104,7 @@ function validate() {
return 0 return 0
} }
export DOCKER_HUB_USER=davidopp export DOCKER_HUB_USER=jlowdermilk
# Launch a container # Launch a container
${KUBE_ROOT}/examples/update-demo/2-create-replication-controller.sh ${KUBE_ROOT}/examples/update-demo/2-create-replication-controller.sh

View File

@ -36,9 +36,9 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
clientConfig, err := f.ClientConfig(cmd) clientConfig, err := f.ClientConfig(cmd)
checkErr(err) checkErr(err)
server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig, port) server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig)
checkErr(err) checkErr(err)
glog.Fatal(server.Serve()) glog.Fatal(server.Serve(port))
}, },
} }
cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the prefix /static") cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the prefix /static")

View File

@ -29,12 +29,11 @@ import (
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server. // ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
type ProxyServer struct { type ProxyServer struct {
httputil.ReverseProxy httputil.ReverseProxy
Port int
} }
// NewProxyServer creates and installs a new ProxyServer. // NewProxyServer creates and installs a new ProxyServer.
// It automatically registers the created ProxyServer to http.DefaultServeMux. // It automatically registers the created ProxyServer to http.DefaultServeMux.
func NewProxyServer(filebase string, cfg *client.Config, port int) (*ProxyServer, error) { func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) {
prefix := cfg.Prefix prefix := cfg.Prefix
if prefix == "" { if prefix == "" {
prefix = "/api" prefix = "/api"
@ -52,9 +51,9 @@ func NewProxyServer(filebase string, cfg *client.Config, port int) (*ProxyServer
return proxy, nil return proxy, nil
} }
// Serve starts the server (http.DefaultServeMux) on TCP port 8001, loops forever. // Serve starts the server (http.DefaultServeMux) on given port, loops forever.
func (s *ProxyServer) Serve() error { func (s *ProxyServer) Serve(port int) error {
addr := fmt.Sprintf(":%d", s.Port) addr := fmt.Sprintf(":%d", port)
return http.ListenAndServe(addr, nil) return http.ListenAndServe(addr, nil)
} }