Merge pull request #588 from kubernetes/master

Rebasing 1.3 with all the churn in the 1.2 docs.
pull/611/head
johndmulhausen 2016-05-31 13:25:36 -07:00
commit 94aaca027b
219 changed files with 14278 additions and 5287 deletions

21
404.md
View File

@ -6,7 +6,7 @@ permalink: /404.html
<script language="JavaScript">
$( document ).ready(function() {
var oldURLs=["/README.md","/README.html",".html",".md","/v1.1/","/v1.0/"];
var fwdDirs=["examples/","cluster/"];
var fwdDirs=["examples/","cluster/","docs/devel","docs/design"];
var doRedirect = false;
var notHere = false;
var forwardingURL=window.location.href;
@ -15,16 +15,31 @@ $( document ).ready(function() {
notHere = true;
window.location.replace("http://kubernetes.io/kubernetes/third_party/swagger-ui/");
}
if (forwardingURL.indexOf("docs/design") > -1)
if (forwardingURL.indexOf("resource-quota") > -1)
{
notHere = true;
window.location.replace("https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/design");
window.location.replace("http://kubernetes.io/docs/admin/resourcequota/");
}
if (forwardingURL.indexOf("horizontal-pod-autoscaler") > -1)
{
notHere = true;
window.location.replace("http://kubernetes.io/docs/user-guide/horizontal-pod-autoscaling/");
}
if (forwardingURL.indexOf("docs/roadmap") > -1)
{
notHere = true;
window.location.replace("https://github.com/kubernetes/kubernetes/milestones/");
}
if (forwardingURL.indexOf("api-ref/") > -1)
{
notHere = true;
window.location.replace("http://kubernetes.io/docs/api/");
}
if (forwardingURL.indexOf("docs/user-guide/overview") > -1)
{
notHere = true;
window.location.replace("http://kubernetes.io/docs/whatisk8s/");
}
for (i=0;i<fwdDirs.length;i++) {
if (forwardingURL.indexOf(fwdDirs[i]) > -1)
{

View File

@ -133,6 +133,17 @@ The current version of the website is served out of the `master` branch.
All versions of the site that relate to past and future versions will be named after their Kubernetes release number. For example, [the old branch for the 1.1 docs is called `release-1.1`](https://github.com/kubernetes/kubernetes.github.io/tree/release-1.1).
Changes in the "docsv2" branch (where we are testing a revamp of the docs) are automatically staged here:
http://k8sdocs.github.io/docs/tutorials/
Changes in the "release-1.1" branch (for k8s v1.1 docs) are automatically staged here:
http://kubernetes-v1-1.github.io/
Changes in the "release-1.3" branch (for k8s v1.3 docs) are automatically staged here:
http://kubernetes-v1-3.github.io/
Editing of these branches will kick off a build using Travis CI that auto-updates these URLs; you can monitor the build progress at [https://travis-ci.org/kubernetes/kubernetes.github.io](https://travis-ci.org/kubernetes/kubernetes.github.io).
## Thank you!
Kubernetes thrives on community participation and we really appreciate your

View File

@ -8,22 +8,121 @@ toc:
section:
- title: What is Kubernetes?
path: /docs/whatisk8s/
- title: Downloading Kubernetes
- title: Downloading or Building Kubernetes
path: /docs/getting-started-guides/binary_release/
- title: Hello World Walkthrough
path: /docs/hellonode/
- title: Kubernetes 101
path: /docs/user-guide/walkthrough/
- title: Kubernetes 201
path: /docs/user-guide/walkthrough/k8s201/
- title: Online Training Course
path: https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615
- title: Accessing the Cluster
section:
- title: Installing and Setting up kubectl
path: /docs/user-guide/prereqs/
- title: Accessing Clusters
path: /docs/user-guide/accessing-the-cluster/
- title: Sharing Cluster Access with kubeconfig
path: /docs/user-guide/sharing-clusters/
- title: Authenticating Across Clusters with kubeconfig
path: /docs/user-guide/kubeconfig-file/
- title: User Guide
path: /docs/user-guide/
- title: Admin Guide
path: /docs/admin/
- title: Web UI (Dashboard)
path: /docs/user-guide/ui/
- title: Running Kubernetes
- title: Workload Deployment and Management
section:
- title: Launching, Exposing, and Killing Applications
path: /docs/user-guide/quick-start/
- title: Deploying Applications
path: /docs/user-guide/deploying-applications/
- title: Managing Resources
path: /docs/user-guide/managing-deployments/
- title: Replication Controller Operations
path: /docs/user-guide/replication-controller/operations/
- title: Resizing a Replication Controller
path: /docs/user-guide/resizing-a-replication-controller/
- title: Rolling Updates
path: /docs/user-guide/rolling-updates/
- title: Rolling Update Demo
path: /docs/user-guide/update-demo/
- title: Secrets Walkthrough
path: /docs/user-guide/secrets/walkthrough/
- title: Using ConfigMap
path: /docs/user-guide/configmap/
- title: Horizontal Pod Autoscaling
path: /docs/user-guide/horizontal-pod-autoscaling/walkthrough/
- title: Best Practices for Configuration
path: /docs/user-guide/config-best-practices/
- title: Using kubectl to Manage Resources
path: /docs/user-guide/working-with-resources/
- title: Service Discovery and Load Balancing
section:
- title: Connecting Applications with Services
path: /docs/user-guide/connecting-applications/
- title: Service Operations
path: /docs/user-guide/services/operations/
- title: Creating an External Load Balancer
path: /docs/user-guide/load-balancer/
- title: Configuring Your Cloud Provider's Firewalls
path: /docs/user-guide/services-firewalls/
- title: Containers and Pods
section:
- title: Running Your First Containers
path: /docs/user-guide/simple-nginx/
- title: Creating Single-Container Pods
path: /docs/user-guide/pods/single-container/
- title: Creating Multi-Container Pods
path: /docs/user-guide/pods/multi-container/
- title: Configuring Containers
path: /docs/user-guide/configuring-containers/
- title: Working with Containers in Production
path: /docs/user-guide/production-pods/
- title: Commands and Capabilities
path: /docs/user-guide/containers/
- title: Using Environment Variables
path: /docs/user-guide/environment-guide/
- title: Managing Compute Resources
path: /docs/user-guide/compute-resources/
- title: The Lifecycle of a Pod
path: /docs/user-guide/pod-states/
- title: Checking Pod Health
path: /docs/user-guide/liveness/
- title: Container Lifecycle Hooks
path: /docs/user-guide/container-environment/
- title: Assigning Pods to Nodes
path: /docs/user-guide/node-selection/
- title: Using the Downward API to Convey Pod Properties
path: /docs/user-guide/downward-api/
- title: Downward API Volumes
path: /docs/user-guide/downward-api/volume
- title: Persistent Volumes Walkthrough
path: /docs/user-guide/persistent-volumes/walkthrough/
- title: Monitoring, Logging, and Debugging Containers
section:
- title: Resource Usage Monitoring
path: /docs/user-guide/monitoring/
- title: Logging
path: /docs/getting-started-guides/logging/
- title: Logging with Elasticsearch and Kibana
path: /docs/getting-started-guides/logging-elasticsearch/
- title: Elasticsearch/Kibana Logging Demo
path: /docs/user-guide/logging-demo
- title: Running Commands in a Container with kubectl exec
path: /docs/user-guide/getting-into-containers/
- title: Connect with Proxies
path: /docs/user-guide/connecting-to-applications-proxy/
- title: Connect with Port Forwarding
path: /docs/user-guide/connecting-to-applications-port-forward/
- title: Using Explorer to Examine the Runtime Environment
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/explorer
- title: Creating a Cluster
section:
- title: Picking the Right Solution
path: /docs/getting-started-guides/
@ -31,10 +130,10 @@ toc:
section:
- title: Running Kubernetes Locally via Docker
path: /docs/getting-started-guides/docker/
- title: Running Kubernetes Locally via Vagrant
path: /docs/getting-started-guides/vagrant/
- title: Running Kubernetes Locally with No VM
path: /docs/getting-started-guides/locally/
- title: Running Kubernetes Locally with Vagrant
path: /docs/getting-started-guides/vagrant/
- title: Running Kubernetes on Turn-key Cloud Solutions
section:
- title: Running Kubernetes on Google Container Engine
@ -45,21 +144,31 @@ toc:
path: /docs/getting-started-guides/aws/
- title: Running Kubernetes on Azure
path: /docs/getting-started-guides/coreos/azure/
- title: Running Kubernetes on CenturyLink Cloud
path: /docs/getting-started-guides/clc/
- title: Portable Multi-Node Clusters
section:
- title: Installing a Kubernetes Master Node via Docker
path: /docs/getting-started-guides/docker-multinode/master/
- title: Adding a Kubernetes Worker Node via Docker
path: /docs/getting-started-guides/docker-multinode/worker/
- title: Deploying DNS
path: /docs/getting-started-guides/docker-multinode/deployDNS/
- title: Running Kubernetes on Custom Solutions
section:
- title: Getting Started From Scratch
- title: Creating a Custom Cluster from Scratch
path: /docs/getting-started-guides/scratch/
- title: Custom Cloud Solutions
section:
- title: AWS or GCE on CoreOS
- title: CoreOS on AWS or GCE
path: /docs/getting-started-guides/coreos/
- title: AWS or Joyent on Ubuntu
- title: Ubuntu on AWS or Joyent
path: /docs/getting-started-guides/juju/
- title: Rackspace on CoreOS
- title: CoreOS on Rackspace
path: /docs/getting-started-guides/rackspace/
- title: On-Premise VMs
section:
- title: Vagrant or VMware
- title: CoreOS on Vagrant
path: /docs/getting-started-guides/coreos/
- title: Cloudstack
path: /docs/getting-started-guides/cloudstack/
@ -69,13 +178,13 @@ toc:
path: /docs/getting-started-guides/juju/
- title: DCOS
path: /docs/getting-started-guides/dcos/
- title: libvirt on CoreOS
- title: CoreOS on libvirt
path: /docs/getting-started-guides/libvirt-coreos/
- title: oVirt
path: /docs/getting-started-guides/ovirt/
- title: libvirt or KVM
path: /docs/getting-started-guides/fedora/flannel_multi_node_cluster/
- title: Multinode Cluster on CoreOS
- title: OpenStack Heat
path: /docs/getting-started-guides/openstack-heat/
- title: CoreOS on Multinode Cluster
path: /docs/getting-started-guides/coreos/coreos_multinode_cluster/
- title: Fedora With Calico Networking
path: /docs/getting-started-guides/fedora/fedora-calico/
@ -99,161 +208,60 @@ toc:
path: /docs/getting-started-guides/fedora/fedora_manual_config/
- title: Fedora (Multi Node)
path: /docs/getting-started-guides/fedora/flannel_multi_node_cluster/
- title: Centos
- title: CentOS
path: /docs/getting-started-guides/centos/centos_manual_config/
- title: Ubuntu
path: /docs/getting-started-guides/ubuntu/
- title: Docker (Multi-Node)
path: /docs/getting-started-guides/docker-multinode/
- title: CoreOS with Calico
path: /docs/getting-started-guides/coreos/bare_metal_calico/
- title: Ubuntu Nodes with Calico
path: /docs/getting-started-guides/ubuntu-calico/
- title: Building Large Clusters
path: /docs/admin/cluster-large/
- title: Running in Multiple Zones
path: /docs/admin/multiple-zones/
- title: Building High-Availability Clusters
path: /docs/admin/high-availability/
- title: Administering Clusters
section:
- title: Admin Guide
path: /docs/admin/
- title: Cluster Management Guide
path: /docs/admin/cluster-management/
- title: Cluster Management Tools
- title: Sharing a Cluster with Namespaces
path: /docs/admin/namespaces/
- title: Namespaces Walkthrough
path: /docs/admin/namespaces/walkthrough/
- title: Setting Pod CPU and Memory Limits
path: /docs/admin/limitrange/
- title: Understanding Resource Quotas
path: /docs/admin/resourcequota/
- title: Applying Resource Quotas and Limits
path: /docs/admin/resourcequota/walkthrough/
- title: Kubernetes Components
path: /docs/admin/cluster-components/
- title: Configuring Kubernetes Use of etcd
path: /docs/admin/etcd/
- title: Using Multiple Clusters
path: /docs/admin/multi-cluster/
- title: Using Large Clusters
path: /docs/admin/cluster-large/
- title: Building High-Availability Clusters
path: /docs/admin/high-availability/
- title: Accessing Clusters
path: /docs/user-guide/accessing-the-cluster/
- title: Sharing a Cluster
path: /docs/admin/namespaces/
- title: Changing Cluster Size
path: https://github.com/kubernetes/kubernetes/wiki/User-FAQ#how-do-i-change-the-size-of-my-cluster/
- title: Creating a Custom Cluster from Scratch
path: /docs/getting-started-guides/scratch/
- title: Authenticating Across Clusters with kubeconfig
path: /docs/user-guide/kubeconfig-file/
- title: Replication Controller Operations
path: /docs/user-guide/replication-controller/operations/
- title: Resizing a Replication Controller
path: /docs/user-guide/resizing-a-replication-controller/
- title: Service Operations
path: /docs/user-guide/services/operations/
- title: Using Nodes, Pods, and Containers
section:
- title: The Container Environment
path: /docs/user-guide/container-environment/
- title: Running Your First Containers
path: /docs/user-guide/simple-nginx/
- title: Working with Containers
path: /docs/user-guide/production-pods/
- title: Overriding Default Container Behavior
path: /docs/user-guide/containers/
- title: Running Commands in a Container with kubectl exec
path: /docs/user-guide/getting-into-containers/
- title: The Lifecycle of a Pod
path: /docs/user-guide/pod-states/
- title: Creating Single-Container Pods
path: /docs/user-guide/pods/single-container/
- title: Creating Multi-Container Pods
path: /docs/user-guide/pods/multi-container/
- title: Pod Templates
path: /docs/user-guide/pod-templates/
- title: Assigning Pods to Nodes
path: /docs/user-guide/node-selection/
- title: Creating Pods with the Downward API
path: /docs/user-guide/downward-api/
- title: Updating Live Pods
path: /docs/user-guide/update-demo/
- title: Static Pods
path: /docs/admin/static-pods/
- title: Installing a Kubernetes Master Node via Docker
path: /docs/getting-started-guides/docker-multinode/master/
- title: Adding a Kubernetes Worker Node via Docker
path: /docs/getting-started-guides/docker-multinode/worker/
- title: Networking
section:
- title: Configuring Multiple Schedulers
path: /docs/admin/multiple-schedulers/
- title: Networking in Kubernetes
path: /docs/admin/networking/
- title: Creating an External Load Balancer
path: /docs/user-guide/load-balancer/
- title: Using DNS Pods and Services
path: /docs/admin/dns/
- title: Setting Up and Configuring DNS
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/cluster-dns
- title: Deploying DNS
path: /docs/getting-started-guides/docker-multinode/deployDNS/
- title: Connecting Applications
path: /docs/user-guide/connecting-applications/
- title: Creating Servers with External IPs
path: https://github.com/kubernetes/kubernetes/blob/release-1.2/examples/simple-nginx.md
- title: Connect with Proxies
path: /docs/user-guide/connecting-to-applications-proxy/
- title: Connect with Port Forwarding
path: /docs/user-guide/connecting-to-applications-port-forward/
- title: Configuring Your Cloud Provider's Firewalls
path: /docs/user-guide/services-firewalls/
- title: Master <-> Node Communication
path: /docs/admin/master-node-communication/
- title: Network Plugins
path: /docs/admin/network-plugins/
- title: Configuring Kubernetes
section:
- title: Using Configuration Files
path: /docs/user-guide/simple-yaml/
- title: Best Practices for Configuration
path: /docs/user-guide/config-best-practices/
- title: Configuring Containers
path: /docs/user-guide/configuring-containers/
- title: Using ConfigMap
path: /docs/user-guide/configmap/
- title: Sharing Cluster Access with kubeconfig
path: /docs/user-guide/sharing-clusters/
- title: Using Environment Variables
path: /docs/user-guide/environment-guide/
- title: Managing Compute Resources
path: /docs/user-guide/compute-resources/
- title: Using kubectl to Manage Resources
path: /docs/user-guide/working-with-resources/
- title: Applying Resource Quotas and Limits
path: /docs/admin/resourcequota/
- title: Setting Pod CPU and Memory Limits
path: /docs/admin/limitrange/
- title: Static Pods
path: /docs/admin/static-pods/
- title: Configuring Garbage Collection
path: /docs/admin/garbage-collection/
- title: Configuring Kubernetes with Salt
path: /docs/admin/salt/
- title: Configuring Kubernetes Use of etcd
path: /docs/admin/etcd/
- title: Application Management and Deployment
section:
- title: "Managing Applications: Prerequisites"
path: /docs/user-guide/prereqs/
- title: Managing Deployments
path: /docs/user-guide/managing-deployments/
- title: Deploying Applications
path: /docs/user-guide/deploying-applications/
- title: Updating Applications with Rolling Updates
path: /docs/user-guide/rolling-updates/
- title: Launching, Exposing, and Killing Applications
path: /docs/user-guide/quick-start/
- title: Testing and Monitoring
section:
- title: Testing a Kubernetes Cluster
path: /docs/getting-started-guides/docker-multinode/testing/
- title: Simulating Large Test Loads
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/k8petstore
- title: Checking Pod Health
path: /docs/user-guide/liveness/
- title: Using Explorer to Examine the Runtime Environment
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/explorer
- title: Resource Usage Monitoring
path: /docs/user-guide/monitoring/
- title: Logging
path: /docs/getting-started-guides/logging/
- title: Logging with Elasticsearch and Kibana
path: /docs/getting-started-guides/logging-elasticsearch/

View File

@ -24,6 +24,8 @@ toc:
path: /docs/api-reference/v1/operations/
- title: Kubernetes API Definitions
path: /docs/api-reference/v1/definitions/
- title: Kubernetes API Swagger Spec
path: /kubernetes/third_party/swagger-ui/
- title: Extensions API
section:
@ -52,6 +54,8 @@ toc:
path: /docs/user-guide/kubectl-overview/
- title: kubectl for Docker Users
path: /docs/user-guide/docker-cli-to-kubectl/
- title: kubectl Usage Conventions
path: /docs/user-guide/kubectl-conventions/
- title: JSONpath Support
path: /docs/user-guide/jsonpath/
- title: kubectl Cheat Sheet
@ -80,7 +84,7 @@ toc:
path: /docs/user-guide/kubectl/kubectl_config_set-cluster/
- title: kubectl config set-context
path: /docs/user-guide/kubectl/kubectl_config_set-context/
- title: kubectl set-credentials
- title: kubectl config set-credentials
path: /docs/user-guide/kubectl/kubectl_config_set-credentials/
- title: kubectl config set
path: /docs/user-guide/kubectl/kubectl_config_set/
@ -163,20 +167,18 @@ toc:
- title: kubectl stop
path: /docs/user-guide/kubectl/kubectl_stop/
- title: kube-apiserver CLI
path: /docs/admin/kube-apiserver/
- title: kube-proxy CLI
path: /docs/admin/kube-proxy/
- title: kube-scheduler CLI
path: /docs/admin/kube-scheduler/
- title: kubelet CLI
path: /docs/admin/kubelet/
- title: kube-controller-manager CLI
path: /docs/admin/kube-controller-manager/
- title: Kubernetes Components
section:
- title: kube-apiserver
path: /docs/admin/kube-apiserver/
- title: kube-proxy
path: /docs/admin/kube-proxy/
- title: kube-scheduler
path: /docs/admin/kube-scheduler/
- title: kubelet
path: /docs/admin/kubelet/
- title: kube-controller-manager
path: /docs/admin/kube-controller-manager/
- title: Glossary
section:
@ -215,11 +217,13 @@ toc:
- title: Ingress Resources
path: /docs/user-guide/ingress/
- title: Horizontal Pod Autoscaling
path: /docs/user-guide/horizontal-pod-autoscaler/
path: /docs/user-guide/horizontal-pod-autoscaling/
- title: Jobs
path: /docs/user-guide/jobs/
- title: Resource Quotas
path: /docs/admin/resource-quota/
- title: Replica Sets
path: /docs/user-guide/replicasets/
- title: Kubernetes Design Docs
section:

View File

@ -4,59 +4,76 @@ toc:
- title: Samples
path: /docs/samples/
- title: Clustered Application Samples
- title: Storage / Database / KV
section:
- title: Apache Cassandra Database
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/cassandra
- title: Apache Spark
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/spark
- title: Apache Storm
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/storm
- title: Distributed Task Queue
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/celery-rabbitmq
- title: Ceph
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/rbd/
- title: CephFS
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/cephfs/
- title: GlusterFS
path: /https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/glusterfs/
- title: Hazelcast
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/hazelcast
- title: Meteor Applications
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/meteor/
- title: iSCSI
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/iscsi/
- title: MySQL Galera
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/mysql-galera
- title: NFS
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/nfs/
- title: Redis
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/redis/
- title: RethinkDB
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/rethinkdb/
- title: Elasticsearch/Kibana Logging Demonstration
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/logging-demo/
- title: Vitess
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/vitess/
- title: Big Data
section:
- title: Apache Spark
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/spark
- title: Apache Storm
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/storm
- title: Messaging / Queueing
section:
- title: Celery + RabbitMQ
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/celery-rabbitmq
- title: Hazelcast
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/hazelcast
- title: Miscellaneous
section:
- title: Meteor Applications
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/meteor/
- title: Elasticsearch
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/elasticsearch/
- title: OpenShift Origin
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/openshift-origin/
- title: Ceph
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/rbd/
- title: MEAN stack on Google Cloud Platform
path: /docs/getting-started-guides/meanstack/
- title: Selenium
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/selenium/
- title: Persistent Volume Samples
- title: Monitoring and Logging
section:
- title: WordPress on a Kubernetes Persistent Volume
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/mysql-wordpress-pd/
- title: GlusterFS
path: /https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/glusterfs/
- title: iSCSI
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/iscsi/
- title: NFS
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/nfs/
- title: Downward API Volumes
path: /docs/user-guide/downward-api/volume
- title: Elasticsearch/Kibana Logging Demonstration
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/logging-demo/
- title: NewRelic
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/newrelic
- title: Multi-tier Application Samples
- title: Multi-tier Applications
section:
- title: Guestbook - Go Server
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/guestbook-go/
- title: GuestBook - PHP Server
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/guestbook/
- title: MySQL - Phabricator Server
- title: MEAN stack on Google Cloud Platform
path: /docs/getting-started-guides/meanstack/
- title: MySQL + Wordpress
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/mysql-wordpress-pd/
- title: MySQL + Phabricator Server
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/phabricator/
- title: Elasticsearch/Kibana Logging Demo
path: https://github.com/kubernetes/kubernetes.github.io/tree/master/docs/user-guide/logging-demo
- title: ConfigMap Example
path: https://github.com/kubernetes/kubernetes.github.io/tree/master/docs/user-guide/configmap
- title: Nodejs + Mongo
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/nodesjs-mongodb
- title: Petstore
path: https://github.com/kubernetes/kubernetes/tree/release-1.2/examples/k8spetstore/

View File

@ -8,8 +8,6 @@ toc:
section:
- title: Debugging Pods and Replication Controllers
path: /docs/user-guide/debugging-pods-and-replication-controllers/
- title: Web Interface
path: /docs/user-guide/ui/
- title: Application Introspection and Debugging
path: /docs/user-guide/introspection-and-debugging/
- title: Retrieving Logs

View File

@ -1,10 +1,11 @@
{% capture samplecode %}{% include_relative {{include.file}} %}{% endcapture %}
{% if include.k8slink %}{% capture ghlink %}https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}{{include.k8slink}}{% endcapture %}{% endif %}
{% if include.ghlink %}{% capture ghlink %}https://github.com/kubernetes/kubernetes.github.io/blob/master{{include.ghlink}}{% endcapture %}{% endif %}
{% if include.k8slink %}{% capture ghlink %}https://raw.githubusercontent.com/kubernetes/kubernetes/blob/{{page.githubbranch}}{{include.k8slink}}{% endcapture %}{% endif %}
{% if include.ghlink %}{% capture ghlink %}https://raw.githubusercontent.com/kubernetes/kubernetes.github.io/{{page.docsbranch}}{{include.ghlink}}{% endcapture %}{% endif %}
{% capture mysample %}
```{{include.language}}
{{ samplecode | raw | strip }}
```
{: id="{{include.file | handleize}}"}
{% endcapture %}
<table class="includecode"><thead><tr><th>{% if ghlink %}<a href="{{ghlink}}">{% endif %}<code>{{include.file}}</code></a></th></tr></thead>
<table class="includecode"><thead><tr><th>{% if ghlink %}<a href="{{ghlink}}" download="{{include.file}}">{% endif %}<code>{{include.file}}</code></a><img src="/images/copycode.svg" style="max-height:24px" onClick="copyCode('{{include.file | handleize}}')" title="Copy {{include.file}} to clipboard"></th></tr></thead>
<tr><td>{{ mysample | markdownify }}</td></tr></table>

View File

@ -2,14 +2,17 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="http://kubernetes.io{{page.url}}" />
<link rel="shortcut icon" type="image/png" href="/images/favicon.png">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto+Mono' type='text/css'>
<link rel="stylesheet" href="/css/styles.css"/>
<link rel="stylesheet" href="/css/jquery-ui.min.css">
<link rel="stylesheet" href="/css/jquery-ui.min.css">
<link rel="stylesheet" href="/css/sweetalert.css">
<script src="/js/jquery-2.2.0.min.js"></script>
<script src="/js/jquery-ui.min.js"></script>
<script src="/js/jquery-ui.min.js"></script>
<script src="/js/script.js"></script>
<script src="/js/sweetalert.min.js"></script>
<title>Kubernetes - {{ title }}</title>
</head>
<body>
@ -61,4 +64,4 @@
<div class="clear" style="clear: both"></div>
</main>
</nav>
</header>
</header>

View File

@ -0,0 +1,170 @@
{% if concept %}<!-- check for this before going any further; if not present, skip to else at bottom -->
# Overview of {{concept}}s
{% if what_is %}
### What is a {{ concept }}?
{{ what_is }}
{% else %}
### ERROR: You must define a "what_is" block
{: style="color:red" }
This template requires that you explain what this concept is. This explanation will
be displayed under the heading, **What is a {{ concept }}?**
To get rid of this message and take advantage of this template, define the `what_is`
variable and populate it with content.
```liquid
{% raw %}{% capture what_is %}{% endraw %}
A {{ concept }} does x and y and z...(etc, etc, text goes on)
{% raw %}{% endcapture %}{% endraw %}
```
{% endif %}
{% if when_to_use %}
### When to use {{ concept }}s
{{ when_to_use }}
{% else %}
### ERROR: You must define a "when_to_use" block
{: style="color:red" }
This template requires that you explain when to use this object. This explanation will
be displayed under the heading, **When to use {{ concept }}s**
To get rid of this message and take advantage of this template, define the `when_to_use`
variable and populate it with content.
```liquid
{% raw %}{% capture when_to_use %}{% endraw %}
You should use {{ concept }} when...
{% raw %}{% endcapture %}{% endraw %}
```
{% endif %}
{% if when_not_to_use %}
### When not to use {{ concept }}s (alternatives)
{{ when_not_to_use }}
{% else %}
### ERROR: You must define a "when_not_to_use" block
{: style="color:red" }
This template requires that you explain when not to use this object. This explanation will
be displayed under the heading, **When not to use {{ concept }}s (alternatives)**
To get rid of this message and take advantage of this template, define the `when_not_to_use`
block and populate it with content.
```liquid
{% raw %}{% capture when_not_to_use %}{% endraw %}
You should not use {{ concept }} if...
{% raw %}{% endcapture %}{% endraw %}
```
{% endif %}
{% if status %}
### {{ concept }} status
{{ status }}
{% else %}
### ERROR: You must define a "status" block
{: style="color:red" }
This template requires that you explain the current status of support for this object.
This explanation will be displayed under the heading, **{{ concept }} status**.
To get rid of this message and take advantage of this template, define the `status`
block and populate it with content.
```liquid
{% raw %}{% capture status %}{% endraw %}
The current status of {{ concept }}s is...
{% raw %}{% endcapture %}{% endraw %}
```
{% endif %}
{% if required_fields %}
### {{ concept }} spec
#### Required Fields
{{ required_fields }}
{% else %}
### ERROR: You must define a "required_fields" block
{: style="color:red" }
This template requires that you provide a Markdown list of required fields for this
object. This list will be displayed under the heading **Required Fields**.
To get rid of this message and take advantage of this template, define the `required_fields`
block and populate it with content.
```liquid
{% raw %}{% capture required_fields %}
* `kind`: Always `Pod`.
* `apiVersion`: Currently `v1`.
* `metadata`: An object containing:
* `name`: Required if `generateName` is not specified. The name of this pod.
It must be an
[RFC1035](https://www.ietf.org/rfc/rfc1035.txt) compatible value and be
unique within the namespace.
{% endcapture %}{% endraw %}
```
**Note**: You can also define a `common_fields` block that will go under a heading
directly underneath **Required Fields** called **Common Fields**, but it is
not required.
{% endif %}
{% if common_fields %}
#### Common Fields
{{ common_fields }}
{% endif %}
<!-- continuing the "if concept" if/then: -->
{% else %}
### ERROR: You must define a "concept" variable
{: style="color:red" }
This template requires a variable called `concept` that is simply the name of the
concept for which you are giving an overview. This will be displayed in the
headings for the document.
To get rid of this message and take advantage of this template, define `concept`:
```liquid
{% raw %}{% assign concept="Replication Controller" %}{% endraw %}
```
Complete this task, then we'll walk you through preparing the rest of the document.
{% endif %}

View File

@ -0,0 +1,121 @@
{% if page.cards %}<!-- check for this before going any further; if not present, skip to else at bottom -->
<style>
h2, h3, h4 {
border-bottom: 0px !important;
font-size: 22px !important;
padding-bottom: 20px !important;
}
.colContainer {
padding-top:2px;
padding-left: 2px;
overflow: auto;
}
#samples a {
color: #000;
}
.col3rd {
display: block;
float: left;
margin-right: 30px;
margin-bottom: 30px;
overflow: hidden;
}
.col3rd h3, .col2nd h3 {
margin-bottom: 0px !important;
}
.col3rd .button, .col2nd .button {
margin-top: 20px;
border-radius: 2px;
}
.col3rd p, .col2nd p {
margin-left: 2px;
}
.col2nd {
display: block;
width: 400px;
float: left;
margin-right: 30px;
margin-bottom: 30px;
overflow: hidden;
}
.shadowbox {
width: 250px;
display: inline;
float: left;
text-transform: none;
font-weight: bold;
text-overflow: ellipsis;
overflow: hidden;
line-height: 24px;
position: relative;
display: block;
cursor: pointer;
box-shadow: 0 2px 2px rgba(0,0,0,.24),0 0 2px rgba(0,0,0,.12);
border-radius: 5px;
background: #fff;
transition: all .3s;
padding: 16px;
margin: 0 16px 16px 0;
text-decoration: none;
letter-spacing: .01em;
height: 220px;
}
.shadowbox img {
min-width: 100px;
max-width: 100px;
max-height: 50px;
margin-right: 5px;
margin-bottom: 5px;
float: left;
}
</style>
<div class="colContainer">
{% for card in page.cards %}{% if card.title %}
<div class="col3rd shadowbox">
<h3>{{card.title}}</h3>
<p>{% if card.image %}<img src="{{card.image}}">{% endif %}{{card.description}}</p>
</div>
{% endif %}{% endfor %}
</div>
{% else %}
### ERROR: You must define "cards" front-matter YAML
{: style="color:red" }
This template requires that you insert YAML at the top of your document
that defines the "cards" you'd like to display on the page. The cards will
render in clickable boxes.
To get rid of this message and take advantage of this template, define `cards`:
```yaml
---
cards:
- progression: no
- card:
title: Mean Stack
image: /docs/meanstack/image_0.png
description: Lorem ipsum dolor it verberum.
- card:
title: Guestbook + Redis
image: /images/docs/redis.svg
description: Lorem ipsum dolor it verberum.
- card:
title: Cloud Native Cassandra
image: /images/docs/cassandra.svg
description: Lorem ipsum dolor it verberum.
- card:
title: WordPress + MySQL
image: /images/docs/wordpress.svg
description: Lorem ipsum dolor it verberum.
---
```
**Note:** If `progression` is set to `yes` then a "Start Here!" icon will be
placed on the first card and arrows suggesting linear reading will be overlayed
between the other cards, telling the reader that they should explore the content
in a certain order.
{% endif %}

View File

@ -181,7 +181,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonsetlist">v1beta1.DaemonSetList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonsetlist">v1beta1.DaemonSetList</a></p></td>
</tr>
</tbody>
</table>
@ -321,7 +321,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deploymentlist">v1beta1.DeploymentList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deploymentlist">v1beta1.DeploymentList</a></p></td>
</tr>
</tbody>
</table>
@ -461,7 +461,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscalerlist">v1beta1.HorizontalPodAutoscalerList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscalerlist">v1beta1.HorizontalPodAutoscalerList</a></p></td>
</tr>
</tbody>
</table>
@ -601,7 +601,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingresslist">v1beta1.IngressList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingresslist">v1beta1.IngressList</a></p></td>
</tr>
</tbody>
</table>
@ -741,7 +741,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_joblist">v1beta1.JobList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_joblist">v1beta1.JobList</a></p></td>
</tr>
</tbody>
</table>
@ -889,7 +889,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonsetlist">v1beta1.DaemonSetList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonsetlist">v1beta1.DaemonSetList</a></p></td>
</tr>
</tbody>
</table>
@ -1037,7 +1037,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -1119,7 +1119,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1153,7 +1153,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
</tr>
</tbody>
</table>
@ -1285,7 +1285,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
</tr>
</tbody>
</table>
@ -1367,7 +1367,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1409,7 +1409,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
</tr>
</tbody>
</table>
@ -1491,7 +1491,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1533,7 +1533,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -1615,7 +1615,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1657,7 +1657,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
</tr>
</tbody>
</table>
@ -1745,7 +1745,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1787,7 +1787,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_daemonset">v1beta1.DaemonSet</a></p></td>
</tr>
</tbody>
</table>
@ -1935,7 +1935,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deploymentlist">v1beta1.DeploymentList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deploymentlist">v1beta1.DeploymentList</a></p></td>
</tr>
</tbody>
</table>
@ -2083,7 +2083,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -2165,7 +2165,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -2199,7 +2199,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
</tr>
</tbody>
</table>
@ -2331,7 +2331,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
</tr>
</tbody>
</table>
@ -2413,7 +2413,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -2455,7 +2455,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
</tr>
</tbody>
</table>
@ -2537,7 +2537,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -2579,7 +2579,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -2661,7 +2661,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -2703,7 +2703,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
</tr>
</tbody>
</table>
@ -2791,7 +2791,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deploymentrollback">v1beta1.DeploymentRollback</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deploymentrollback">v1beta1.DeploymentRollback</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -2833,7 +2833,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deploymentrollback">v1beta1.DeploymentRollback</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deploymentrollback">v1beta1.DeploymentRollback</a></p></td>
</tr>
</tbody>
</table>
@ -2949,7 +2949,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -3031,7 +3031,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -3073,7 +3073,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -3155,7 +3155,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -3197,7 +3197,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -3285,7 +3285,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -3327,7 +3327,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_deployment">v1beta1.Deployment</a></p></td>
</tr>
</tbody>
</table>
@ -3475,7 +3475,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscalerlist">v1beta1.HorizontalPodAutoscalerList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscalerlist">v1beta1.HorizontalPodAutoscalerList</a></p></td>
</tr>
</tbody>
</table>
@ -3623,7 +3623,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -3705,7 +3705,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -3739,7 +3739,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -3871,7 +3871,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -3953,7 +3953,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -3995,7 +3995,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -4077,7 +4077,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -4119,7 +4119,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -4201,7 +4201,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -4243,7 +4243,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -4331,7 +4331,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -4373,7 +4373,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_horizontalpodautoscaler">v1beta1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -4521,7 +4521,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingresslist">v1beta1.IngressList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingresslist">v1beta1.IngressList</a></p></td>
</tr>
</tbody>
</table>
@ -4669,7 +4669,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -4751,7 +4751,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -4785,7 +4785,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
</tr>
</tbody>
</table>
@ -4917,7 +4917,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
</tr>
</tbody>
</table>
@ -4999,7 +4999,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -5041,7 +5041,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
</tr>
</tbody>
</table>
@ -5123,7 +5123,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -5165,7 +5165,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -5247,7 +5247,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -5289,7 +5289,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
</tr>
</tbody>
</table>
@ -5377,7 +5377,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -5419,7 +5419,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_ingress">v1beta1.Ingress</a></p></td>
</tr>
</tbody>
</table>
@ -5567,7 +5567,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_joblist">v1beta1.JobList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_joblist">v1beta1.JobList</a></p></td>
</tr>
</tbody>
</table>
@ -5715,7 +5715,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -5797,7 +5797,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -5831,7 +5831,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -5963,7 +5963,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -6045,7 +6045,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -6087,7 +6087,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -6169,7 +6169,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -6211,7 +6211,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -6293,7 +6293,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -6335,7 +6335,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -6423,7 +6423,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -6465,7 +6465,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_job">v1beta1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_job">v1beta1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -6613,7 +6613,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicasetlist">v1beta1.ReplicaSetList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicasetlist">v1beta1.ReplicaSetList</a></p></td>
</tr>
</tbody>
</table>
@ -6761,7 +6761,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -6843,7 +6843,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -6877,7 +6877,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
</tr>
</tbody>
</table>
@ -7009,7 +7009,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
</tr>
</tbody>
</table>
@ -7091,7 +7091,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7133,7 +7133,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
</tr>
</tbody>
</table>
@ -7215,7 +7215,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7257,7 +7257,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -7339,7 +7339,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7381,7 +7381,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
</tr>
</tbody>
</table>
@ -7503,7 +7503,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -7585,7 +7585,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7627,7 +7627,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -7709,7 +7709,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7751,7 +7751,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -7839,7 +7839,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -7881,7 +7881,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicaset">v1beta1.ReplicaSet</a></p></td>
</tr>
</tbody>
</table>
@ -7997,7 +7997,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -8079,7 +8079,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -8121,7 +8121,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -8203,7 +8203,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -8245,7 +8245,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_scale">v1beta1.Scale</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_scale">v1beta1.Scale</a></p></td>
</tr>
</tbody>
</table>
@ -8391,7 +8391,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1beta1_replicasetlist">v1beta1.ReplicaSetList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1beta1_replicasetlist">v1beta1.ReplicaSetList</a></p></td>
</tr>
</tbody>
</table>
@ -8531,7 +8531,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -8668,7 +8668,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -8805,7 +8805,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -8942,7 +8942,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9079,7 +9079,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9224,7 +9224,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9377,7 +9377,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9522,7 +9522,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9675,7 +9675,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9820,7 +9820,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -9973,7 +9973,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10118,7 +10118,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10271,7 +10271,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10416,7 +10416,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10569,7 +10569,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10714,7 +10714,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -10867,7 +10867,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -11004,7 +11004,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>

File diff suppressed because it is too large Load Diff

View File

@ -512,7 +512,7 @@ section
background-color: $light-grey
border-left: 3px solid $blue
padding: 7.5px 10px 7.5px 18px
margin-left: -21px
margin-left: -3px
color: $blue
.open-toc
@ -526,10 +526,13 @@ section
overflow-y: auto
.pi-accordion
margin-left: -20px
& > .container:first-child > .item:first-child > .title:first-child
padding-left: 0
font-size: 1.5em
font-weight: 700
.container
padding-left: 20px
& > .container:first-child > .item.yah:first-child > .title:first-child
margin-left: -20px !important
.item
overflow: hidden
@ -546,7 +549,6 @@ section
a.item > .title
color: black
padding-left: 0
&:hover
color: $blue
@ -689,11 +691,10 @@ dd
#docsContent
position: relative
float: right
//width: calc(100% - 400px)
width: 100%
$toc-margin: 15px
$header-clearance: 40px
$header-clearance: $header-height + 20px
* + h2, * + h3, * + h4, * + h5, * + h6
margin-top: 30px
@ -705,12 +706,12 @@ dd
padding-bottom: 10px
border-bottom: 1px solid #cccccc
// Make sure anchor links aren't hidden by the header
&:before
content: ''
display: block
height: 100px
margin-top: -100px
background-color: red
content: " "
margin-top: -$header-clearance
height: $header-clearance
visibility: hidden
h1
@ -845,9 +846,9 @@ dd
white-space: nowrap
text-indent: 50px
overflow: hidden
background: $blue url(/images/pencil.png) no-repeat
background-position: 1px 1px
background-size: auto
background: $blue url(/images/icon-pencil.svg) no-repeat
background-position: 12px 10px
background-size: 29px 29px
#markdown-toc
margin-bottom: 20px

View File

@ -66,6 +66,7 @@ $video-section-height: 550px
#encyclopedia
padding: 50px 50px 20px 20px
clear: both
#docsToc
position: relative
@ -88,6 +89,11 @@ $video-section-height: 550px
main
max-width: $main-max-width
#home
section, header, footer
main
max-width: 1000px
#oceanNodes
main
position: relative
@ -95,7 +101,7 @@ $video-section-height: 550px
&:nth-child(1)
max-width: 1000px
padding-right: 500px
padding-right: 475px
h3, p
text-align: left
@ -105,6 +111,9 @@ $video-section-height: 550px
max-width: 48%
transform: translateY(-50%)
img
max-width: 425px
//.content
// width: 50%
@ -170,30 +179,6 @@ $video-section-height: 550px
div:last-child
float: right
//.social
// position: relative
// margin: 20px 0
//
// a
// float: left
//
// a + a
// margin-left: 10px
//
// label
// float: right
// width: auto
// display: inline-block
// height: 50px
// line-height: 50px
// font-weight: 100
// white-space: nowrap
//
// input
// margin-left: 8px
// max-width: none
#search, #wishField
background-color: transparent
padding: 10px

View File

@ -61,6 +61,7 @@ title: Community
<img src="/images/community_logos/core_os_logo.png">
<img src="/images/community_logos/puppet_logo.png">
<img src="/images/community_logos/sysdig_logo.png">
<img src="/images/community_logos/deis_logo.png">
</div>
</div>
</main>

934
css/sweetalert.css Normal file
View File

@ -0,0 +1,934 @@
body.stop-scrolling {
height: 100%;
overflow: hidden; }
.sweet-overlay {
background-color: black;
/* IE8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
/* IE8 */
background-color: rgba(0, 0, 0, 0.4);
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: none;
z-index: 10000; }
.sweet-alert {
background-color: white;
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
width: 478px;
padding: 17px;
border-radius: 5px;
text-align: left;
position: fixed;
left: 50%;
top: 50%;
margin-left: -256px;
margin-top: -200px;
overflow: hidden;
display: none;
z-index: 99999; }
@media all and (max-width: 540px) {
.sweet-alert {
width: auto;
margin-left: 0;
margin-right: 0;
left: 15px;
right: 15px; } }
.sweet-alert h2 {
color: #575757;
font-size: 30px;
text-align: center;
font-weight: 600;
text-transform: none;
position: relative;
margin: 25px 0;
padding: 0;
line-height: 40px;
display: block; }
.sweet-alert p {
color: #797979;
font-size: 16px;
text-align: left;
font-weight: 300;
position: relative;
text-align: inherit;
float: none;
margin: 0;
padding: 0;
padding-left: 10px !important;
font-family: courier,monospace;
line-height: normal; }
.sweet-alert fieldset {
border: none;
position: relative; }
.sweet-alert .sa-error-container {
background-color: #f1f1f1;
margin-left: -17px;
margin-right: -17px;
overflow: hidden;
padding: 0 10px;
max-height: 0;
webkit-transition: padding 0.15s, max-height 0.15s;
transition: padding 0.15s, max-height 0.15s; }
.sweet-alert .sa-error-container.show {
padding: 10px 0;
max-height: 100px;
webkit-transition: padding 0.2s, max-height 0.2s;
transition: padding 0.25s, max-height 0.25s; }
.sweet-alert .sa-error-container .icon {
display: inline-block;
width: 24px;
height: 24px;
border-radius: 50%;
background-color: #ea7d7d;
color: white;
line-height: 24px;
text-align: center;
margin-right: 3px; }
.sweet-alert .sa-error-container p {
display: inline-block; }
.sweet-alert .sa-input-error {
position: absolute;
top: 29px;
right: 26px;
width: 20px;
height: 20px;
opacity: 0;
-webkit-transform: scale(0.5);
transform: scale(0.5);
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
-webkit-transition: all 0.1s;
transition: all 0.1s; }
.sweet-alert .sa-input-error::before, .sweet-alert .sa-input-error::after {
content: "";
width: 20px;
height: 6px;
background-color: #f06e57;
border-radius: 3px;
position: absolute;
top: 50%;
margin-top: -4px;
left: 50%;
margin-left: -9px; }
.sweet-alert .sa-input-error::before {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg); }
.sweet-alert .sa-input-error::after {
-webkit-transform: rotate(45deg);
transform: rotate(45deg); }
.sweet-alert .sa-input-error.show {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1); }
.sweet-alert input {
width: 100%;
box-sizing: border-box;
border-radius: 3px;
border: 1px solid #d7d7d7;
height: 43px;
margin-top: 10px;
margin-bottom: 17px;
font-size: 18px;
box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.06);
padding: 0 12px;
display: none;
-webkit-transition: all 0.3s;
transition: all 0.3s; }
.sweet-alert input:focus {
outline: none;
box-shadow: 0px 0px 3px #c4e6f5;
border: 1px solid #b4dbed; }
.sweet-alert input:focus::-moz-placeholder {
transition: opacity 0.3s 0.03s ease;
opacity: 0.5; }
.sweet-alert input:focus:-ms-input-placeholder {
transition: opacity 0.3s 0.03s ease;
opacity: 0.5; }
.sweet-alert input:focus::-webkit-input-placeholder {
transition: opacity 0.3s 0.03s ease;
opacity: 0.5; }
.sweet-alert input::-moz-placeholder {
color: #bdbdbd; }
.sweet-alert input:-ms-input-placeholder {
color: #bdbdbd; }
.sweet-alert input::-webkit-input-placeholder {
color: #bdbdbd; }
.sweet-alert.show-input input {
display: block; }
.sweet-alert .sa-confirm-button-container {
display: inline-block;
position: relative; }
.sweet-alert .la-ball-fall {
position: absolute;
left: 50%;
top: 50%;
margin-left: -27px;
margin-top: 4px;
opacity: 0;
visibility: hidden; }
.sweet-alert button {
background-color: #8CD4F5;
color: white;
border: none;
box-shadow: none;
font-size: 17px;
font-weight: 500;
-webkit-border-radius: 4px;
border-radius: 5px;
padding: 10px 32px;
margin: 26px 5px 0 5px;
cursor: pointer; }
.sweet-alert button:focus {
outline: none;
box-shadow: 0 0 2px rgba(128, 179, 235, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.05); }
.sweet-alert button:hover {
background-color: #7ecff4; }
.sweet-alert button:active {
background-color: #5dc2f1; }
.sweet-alert button.cancel {
background-color: #C1C1C1; }
.sweet-alert button.cancel:hover {
background-color: #b9b9b9; }
.sweet-alert button.cancel:active {
background-color: #a8a8a8; }
.sweet-alert button.cancel:focus {
box-shadow: rgba(197, 205, 211, 0.8) 0px 0px 2px, rgba(0, 0, 0, 0.0470588) 0px 0px 0px 1px inset !important; }
.sweet-alert button[disabled] {
opacity: .6;
cursor: default; }
.sweet-alert button.confirm[disabled] {
color: transparent; }
.sweet-alert button.confirm[disabled] ~ .la-ball-fall {
opacity: 1;
visibility: visible;
transition-delay: 0s; }
.sweet-alert button::-moz-focus-inner {
border: 0; }
.sweet-alert[data-has-cancel-button=false] button {
box-shadow: none !important; }
.sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false] {
padding-bottom: 40px; }
.sweet-alert .sa-icon {
width: 80px;
height: 80px;
border: 4px solid gray;
-webkit-border-radius: 40px;
border-radius: 40px;
border-radius: 50%;
margin: 20px auto;
padding: 0;
position: relative;
box-sizing: content-box; }
.sweet-alert .sa-icon.sa-error {
border-color: #F27474; }
.sweet-alert .sa-icon.sa-error .sa-x-mark {
position: relative;
display: block; }
.sweet-alert .sa-icon.sa-error .sa-line {
position: absolute;
height: 5px;
width: 47px;
background-color: #F27474;
display: block;
top: 37px;
border-radius: 2px; }
.sweet-alert .sa-icon.sa-error .sa-line.sa-left {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
left: 17px; }
.sweet-alert .sa-icon.sa-error .sa-line.sa-right {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
right: 16px; }
.sweet-alert .sa-icon.sa-warning {
border-color: #F8BB86; }
.sweet-alert .sa-icon.sa-warning .sa-body {
position: absolute;
width: 5px;
height: 47px;
left: 50%;
top: 10px;
-webkit-border-radius: 2px;
border-radius: 2px;
margin-left: -2px;
background-color: #F8BB86; }
.sweet-alert .sa-icon.sa-warning .sa-dot {
position: absolute;
width: 7px;
height: 7px;
-webkit-border-radius: 50%;
border-radius: 50%;
margin-left: -3px;
left: 50%;
bottom: 10px;
background-color: #F8BB86; }
.sweet-alert .sa-icon.sa-info {
border-color: #C9DAE1; }
.sweet-alert .sa-icon.sa-info::before {
content: "";
position: absolute;
width: 5px;
height: 29px;
left: 50%;
bottom: 17px;
border-radius: 2px;
margin-left: -2px;
background-color: #C9DAE1; }
.sweet-alert .sa-icon.sa-info::after {
content: "";
position: absolute;
width: 7px;
height: 7px;
border-radius: 50%;
margin-left: -3px;
top: 19px;
background-color: #C9DAE1; }
.sweet-alert .sa-icon.sa-success {
border-color: #A5DC86; }
.sweet-alert .sa-icon.sa-success::before, .sweet-alert .sa-icon.sa-success::after {
content: '';
-webkit-border-radius: 40px;
border-radius: 40px;
border-radius: 50%;
position: absolute;
width: 60px;
height: 120px;
background: white;
-webkit-transform: rotate(45deg);
transform: rotate(45deg); }
.sweet-alert .sa-icon.sa-success::before {
-webkit-border-radius: 120px 0 0 120px;
border-radius: 120px 0 0 120px;
top: -7px;
left: -33px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-transform-origin: 60px 60px;
transform-origin: 60px 60px; }
.sweet-alert .sa-icon.sa-success::after {
-webkit-border-radius: 0 120px 120px 0;
border-radius: 0 120px 120px 0;
top: -11px;
left: 30px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-transform-origin: 0px 60px;
transform-origin: 0px 60px; }
.sweet-alert .sa-icon.sa-success .sa-placeholder {
width: 80px;
height: 80px;
border: 4px solid rgba(165, 220, 134, 0.2);
-webkit-border-radius: 40px;
border-radius: 40px;
border-radius: 50%;
box-sizing: content-box;
position: absolute;
left: -4px;
top: -4px;
z-index: 2; }
.sweet-alert .sa-icon.sa-success .sa-fix {
width: 5px;
height: 90px;
background-color: white;
position: absolute;
left: 28px;
top: 8px;
z-index: 1;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg); }
.sweet-alert .sa-icon.sa-success .sa-line {
height: 5px;
background-color: #A5DC86;
display: block;
border-radius: 2px;
position: absolute;
z-index: 2; }
.sweet-alert .sa-icon.sa-success .sa-line.sa-tip {
width: 25px;
left: 14px;
top: 46px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg); }
.sweet-alert .sa-icon.sa-success .sa-line.sa-long {
width: 47px;
right: 8px;
top: 38px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg); }
.sweet-alert .sa-icon.sa-custom {
background-size: contain;
border-radius: 0;
border: none;
background-position: center center;
background-repeat: no-repeat; }
/*
* Animations
*/
@-webkit-keyframes showSweetAlert {
0% {
transform: scale(0.7);
-webkit-transform: scale(0.7); }
45% {
transform: scale(1.05);
-webkit-transform: scale(1.05); }
80% {
transform: scale(0.95);
-webkit-transform: scale(0.95); }
100% {
transform: scale(1);
-webkit-transform: scale(1); } }
@keyframes showSweetAlert {
0% {
transform: scale(0.7);
-webkit-transform: scale(0.7); }
45% {
transform: scale(1.05);
-webkit-transform: scale(1.05); }
80% {
transform: scale(0.95);
-webkit-transform: scale(0.95); }
100% {
transform: scale(1);
-webkit-transform: scale(1); } }
@-webkit-keyframes hideSweetAlert {
0% {
transform: scale(1);
-webkit-transform: scale(1); }
100% {
transform: scale(0.5);
-webkit-transform: scale(0.5); } }
@keyframes hideSweetAlert {
0% {
transform: scale(1);
-webkit-transform: scale(1); }
100% {
transform: scale(0.5);
-webkit-transform: scale(0.5); } }
@-webkit-keyframes slideFromTop {
0% {
top: 0%; }
100% {
top: 50%; } }
@keyframes slideFromTop {
0% {
top: 0%; }
100% {
top: 50%; } }
@-webkit-keyframes slideToTop {
0% {
top: 50%; }
100% {
top: 0%; } }
@keyframes slideToTop {
0% {
top: 50%; }
100% {
top: 0%; } }
@-webkit-keyframes slideFromBottom {
0% {
top: 70%; }
100% {
top: 50%; } }
@keyframes slideFromBottom {
0% {
top: 70%; }
100% {
top: 50%; } }
@-webkit-keyframes slideToBottom {
0% {
top: 50%; }
100% {
top: 70%; } }
@keyframes slideToBottom {
0% {
top: 50%; }
100% {
top: 70%; } }
.showSweetAlert[data-animation=pop] {
-webkit-animation: showSweetAlert 0.3s;
animation: showSweetAlert 0.3s; }
.showSweetAlert[data-animation=none] {
-webkit-animation: none;
animation: none; }
.showSweetAlert[data-animation=slide-from-top] {
-webkit-animation: slideFromTop 0.3s;
animation: slideFromTop 0.3s; }
.showSweetAlert[data-animation=slide-from-bottom] {
-webkit-animation: slideFromBottom 0.3s;
animation: slideFromBottom 0.3s; }
.hideSweetAlert[data-animation=pop] {
-webkit-animation: hideSweetAlert 0.2s;
animation: hideSweetAlert 0.2s; }
.hideSweetAlert[data-animation=none] {
-webkit-animation: none;
animation: none; }
.hideSweetAlert[data-animation=slide-from-top] {
-webkit-animation: slideToTop 0.4s;
animation: slideToTop 0.4s; }
.hideSweetAlert[data-animation=slide-from-bottom] {
-webkit-animation: slideToBottom 0.3s;
animation: slideToBottom 0.3s; }
@-webkit-keyframes animateSuccessTip {
0% {
width: 0;
left: 1px;
top: 19px; }
54% {
width: 0;
left: 1px;
top: 19px; }
70% {
width: 50px;
left: -8px;
top: 37px; }
84% {
width: 17px;
left: 21px;
top: 48px; }
100% {
width: 25px;
left: 14px;
top: 45px; } }
@keyframes animateSuccessTip {
0% {
width: 0;
left: 1px;
top: 19px; }
54% {
width: 0;
left: 1px;
top: 19px; }
70% {
width: 50px;
left: -8px;
top: 37px; }
84% {
width: 17px;
left: 21px;
top: 48px; }
100% {
width: 25px;
left: 14px;
top: 45px; } }
@-webkit-keyframes animateSuccessLong {
0% {
width: 0;
right: 46px;
top: 54px; }
65% {
width: 0;
right: 46px;
top: 54px; }
84% {
width: 55px;
right: 0px;
top: 35px; }
100% {
width: 47px;
right: 8px;
top: 38px; } }
@keyframes animateSuccessLong {
0% {
width: 0;
right: 46px;
top: 54px; }
65% {
width: 0;
right: 46px;
top: 54px; }
84% {
width: 55px;
right: 0px;
top: 35px; }
100% {
width: 47px;
right: 8px;
top: 38px; } }
@-webkit-keyframes rotatePlaceholder {
0% {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg); }
5% {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg); }
12% {
transform: rotate(-405deg);
-webkit-transform: rotate(-405deg); }
100% {
transform: rotate(-405deg);
-webkit-transform: rotate(-405deg); } }
@keyframes rotatePlaceholder {
0% {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg); }
5% {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg); }
12% {
transform: rotate(-405deg);
-webkit-transform: rotate(-405deg); }
100% {
transform: rotate(-405deg);
-webkit-transform: rotate(-405deg); } }
.animateSuccessTip {
-webkit-animation: animateSuccessTip 0.75s;
animation: animateSuccessTip 0.75s; }
.animateSuccessLong {
-webkit-animation: animateSuccessLong 0.75s;
animation: animateSuccessLong 0.75s; }
.sa-icon.sa-success.animate::after {
-webkit-animation: rotatePlaceholder 4.25s ease-in;
animation: rotatePlaceholder 4.25s ease-in; }
@-webkit-keyframes animateErrorIcon {
0% {
transform: rotateX(100deg);
-webkit-transform: rotateX(100deg);
opacity: 0; }
100% {
transform: rotateX(0deg);
-webkit-transform: rotateX(0deg);
opacity: 1; } }
@keyframes animateErrorIcon {
0% {
transform: rotateX(100deg);
-webkit-transform: rotateX(100deg);
opacity: 0; }
100% {
transform: rotateX(0deg);
-webkit-transform: rotateX(0deg);
opacity: 1; } }
.animateErrorIcon {
-webkit-animation: animateErrorIcon 0.5s;
animation: animateErrorIcon 0.5s; }
@-webkit-keyframes animateXMark {
0% {
transform: scale(0.4);
-webkit-transform: scale(0.4);
margin-top: 26px;
opacity: 0; }
50% {
transform: scale(0.4);
-webkit-transform: scale(0.4);
margin-top: 26px;
opacity: 0; }
80% {
transform: scale(1.15);
-webkit-transform: scale(1.15);
margin-top: -6px; }
100% {
transform: scale(1);
-webkit-transform: scale(1);
margin-top: 0;
opacity: 1; } }
@keyframes animateXMark {
0% {
transform: scale(0.4);
-webkit-transform: scale(0.4);
margin-top: 26px;
opacity: 0; }
50% {
transform: scale(0.4);
-webkit-transform: scale(0.4);
margin-top: 26px;
opacity: 0; }
80% {
transform: scale(1.15);
-webkit-transform: scale(1.15);
margin-top: -6px; }
100% {
transform: scale(1);
-webkit-transform: scale(1);
margin-top: 0;
opacity: 1; } }
.animateXMark {
-webkit-animation: animateXMark 0.5s;
animation: animateXMark 0.5s; }
@-webkit-keyframes pulseWarning {
0% {
border-color: #F8D486; }
100% {
border-color: #F8BB86; } }
@keyframes pulseWarning {
0% {
border-color: #F8D486; }
100% {
border-color: #F8BB86; } }
.pulseWarning {
-webkit-animation: pulseWarning 0.75s infinite alternate;
animation: pulseWarning 0.75s infinite alternate; }
@-webkit-keyframes pulseWarningIns {
0% {
background-color: #F8D486; }
100% {
background-color: #F8BB86; } }
@keyframes pulseWarningIns {
0% {
background-color: #F8D486; }
100% {
background-color: #F8BB86; } }
.pulseWarningIns {
-webkit-animation: pulseWarningIns 0.75s infinite alternate;
animation: pulseWarningIns 0.75s infinite alternate; }
@-webkit-keyframes rotate-loading {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(360deg); } }
@keyframes rotate-loading {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(360deg); } }
/* Internet Explorer 9 has some special quirks that are fixed here */
/* The icons are not animated. */
/* This file is automatically merged into sweet-alert.min.js through Gulp */
/* Error icon */
.sweet-alert .sa-icon.sa-error .sa-line.sa-left {
-ms-transform: rotate(45deg) \9; }
.sweet-alert .sa-icon.sa-error .sa-line.sa-right {
-ms-transform: rotate(-45deg) \9; }
/* Success icon */
.sweet-alert .sa-icon.sa-success {
border-color: transparent\9; }
.sweet-alert .sa-icon.sa-success .sa-line.sa-tip {
-ms-transform: rotate(45deg) \9; }
.sweet-alert .sa-icon.sa-success .sa-line.sa-long {
-ms-transform: rotate(-45deg) \9; }
/*!
* Load Awesome v1.1.0 (http://github.danielcardoso.net/load-awesome/)
* Copyright 2015 Daniel Cardoso <@DanielCardoso>
* Licensed under MIT
*/
.la-ball-fall,
.la-ball-fall > div {
position: relative;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.la-ball-fall {
display: block;
font-size: 0;
color: #fff; }
.la-ball-fall.la-dark {
color: #333; }
.la-ball-fall > div {
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor; }
.la-ball-fall {
width: 54px;
height: 18px; }
.la-ball-fall > div {
width: 10px;
height: 10px;
margin: 4px;
border-radius: 100%;
opacity: 0;
-webkit-animation: ball-fall 1s ease-in-out infinite;
-moz-animation: ball-fall 1s ease-in-out infinite;
-o-animation: ball-fall 1s ease-in-out infinite;
animation: ball-fall 1s ease-in-out infinite; }
.la-ball-fall > div:nth-child(1) {
-webkit-animation-delay: -200ms;
-moz-animation-delay: -200ms;
-o-animation-delay: -200ms;
animation-delay: -200ms; }
.la-ball-fall > div:nth-child(2) {
-webkit-animation-delay: -100ms;
-moz-animation-delay: -100ms;
-o-animation-delay: -100ms;
animation-delay: -100ms; }
.la-ball-fall > div:nth-child(3) {
-webkit-animation-delay: 0ms;
-moz-animation-delay: 0ms;
-o-animation-delay: 0ms;
animation-delay: 0ms; }
.la-ball-fall.la-sm {
width: 26px;
height: 8px; }
.la-ball-fall.la-sm > div {
width: 4px;
height: 4px;
margin: 2px; }
.la-ball-fall.la-2x {
width: 108px;
height: 36px; }
.la-ball-fall.la-2x > div {
width: 20px;
height: 20px;
margin: 8px; }
.la-ball-fall.la-3x {
width: 162px;
height: 54px; }
.la-ball-fall.la-3x > div {
width: 30px;
height: 30px;
margin: 12px; }
/*
* Animation
*/
@-webkit-keyframes ball-fall {
0% {
opacity: 0;
-webkit-transform: translateY(-145%);
transform: translateY(-145%); }
10% {
opacity: .5; }
20% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0); }
80% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0); }
90% {
opacity: .5; }
100% {
opacity: 0;
-webkit-transform: translateY(145%);
transform: translateY(145%); } }
@-moz-keyframes ball-fall {
0% {
opacity: 0;
-moz-transform: translateY(-145%);
transform: translateY(-145%); }
10% {
opacity: .5; }
20% {
opacity: 1;
-moz-transform: translateY(0);
transform: translateY(0); }
80% {
opacity: 1;
-moz-transform: translateY(0);
transform: translateY(0); }
90% {
opacity: .5; }
100% {
opacity: 0;
-moz-transform: translateY(145%);
transform: translateY(145%); } }
@-o-keyframes ball-fall {
0% {
opacity: 0;
-o-transform: translateY(-145%);
transform: translateY(-145%); }
10% {
opacity: .5; }
20% {
opacity: 1;
-o-transform: translateY(0);
transform: translateY(0); }
80% {
opacity: 1;
-o-transform: translateY(0);
transform: translateY(0); }
90% {
opacity: .5; }
100% {
opacity: 0;
-o-transform: translateY(145%);
transform: translateY(145%); } }
@keyframes ball-fall {
0% {
opacity: 0;
-webkit-transform: translateY(-145%);
-moz-transform: translateY(-145%);
-o-transform: translateY(-145%);
transform: translateY(-145%); }
10% {
opacity: .5; }
20% {
opacity: 1;
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-o-transform: translateY(0);
transform: translateY(0); }
80% {
opacity: 1;
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-o-transform: translateY(0);
transform: translateY(0); }
90% {
opacity: .5; }
100% {
opacity: 0;
-webkit-transform: translateY(145%);
-moz-transform: translateY(145%);
-o-transform: translateY(145%);
transform: translateY(145%); } }

View File

@ -17,20 +17,23 @@ there is one of these running on a single kubernetes-master node.
By default the Kubernetes APIserver serves HTTP on 2 ports:
1. Localhost Port
- serves HTTP
- default is port 8080, change with `--insecure-port` flag.
- defaults IP is localhost, change with `--insecure-bind-address` flag.
- no authentication or authorization checks in HTTP
- protected by need to have host access
2. Secure Port
- default is port 6443, change with `--secure-port` flag.
- default IP is first non-localhost network interface, change with `--bind-address` flag.
- serves HTTPS. Set cert with `--tls-cert-file` and key with `--tls-private-key-file` flag.
- uses token-file or client-certificate based [authentication](/docs/admin/authentication).
- uses policy-based [authorization](/docs/admin/authorization).
3. Removed: ReadOnly Port
- For security reasons, this had to be removed. Use the [service account](/docs/user-guide/service-accounts) feature instead.
1. `Localhost Port`:
- serves HTTP
- default is port 8080, change with `--insecure-port` flag.
- defaults IP is localhost, change with `--insecure-bind-address` flag.
- no authentication or authorization checks in HTTP
- protected by need to have host access
2. `Secure Port`:
- default is port 6443, change with `--secure-port` flag.
- default IP is first non-localhost network interface, change with `--bind-address` flag.
- serves HTTPS. Set cert with `--tls-cert-file` and key with `--tls-private-key-file` flag.
- uses token-file or client-certificate based [authentication](/docs/admin/authentication).
- uses policy-based [authorization](/docs/admin/authorization).
3. Removed: `ReadOnly Port`
- For security reasons, this had to be removed. Use the [service account](/docs/user-guide/service-accounts) feature instead.
## Proxies and Firewall rules
@ -39,35 +42,31 @@ on the same machine as the apiserver process. The proxy serves HTTPS protected
by Basic Auth on port 443, and proxies to the apiserver on localhost:8080. In
these configurations the secure port is typically set to 6443.
A firewall rule is typically configured to allow external HTTPS access to port 443.
A firewall rule is typically configured to allow external HTTPS access to port
443.
The above are defaults and reflect how Kubernetes is deployed to Google Compute Engine using
kube-up.sh. Other cloud providers may vary.
The above are defaults and reflect how Kubernetes is deployed to Google Compute
Engine using `kube-up.sh.` Other cloud providers may vary.
## Use Cases vs IP:Ports
There are three differently configured serving ports because there are a
variety of uses cases:
There are differently configured serving ports to serve a variety of uses cases:
1. Clients outside of a Kubernetes cluster, such as human running `kubectl`
on desktop machine. Currently, accesses the Localhost Port via a proxy (nginx)
running on the `kubernetes-master` machine. The proxy can use cert-based authentication
or token-based authentication.
on a desktop machine. Currently, accesses the Localhost Port via a proxy (nginx)
running on the `kubernetes-master` machine. The proxy can use cert-based
authentication or token-based authentication.
2. Processes running in Containers on Kubernetes that need to read from
the apiserver. Currently, these can use a [service account](/docs/user-guide/service-accounts).
the apiserver. Currently, these can use a [service account](/docs/user-guide/service-accounts).
3. Scheduler and Controller-manager processes, which need to do read-write
API operations, using service accounts to avoid the need to be co-located.
API operations, using service accounts to avoid the need to be co-located.
4. Kubelets, which need to do read-write API operations and are necessarily
on different machines than the apiserver. Kubelet uses the Secure Port
to get their pods, to find the services that a pod can see, and to
write events. Credentials are distributed to kubelets at cluster
setup time. Kubelet and kube-proxy can use cert-based authentication or token-based
authentication.
on different machines than the apiserver. Kubelet uses the Secure Port
to get their pods, to find the services that a pod can see, and to
write events. Credentials are distributed to kubelets at cluster
setup time. Kubelet and kube-proxy can use cert-based authentication or
token-based authentication.
## Expected changes
- Policy will limit the actions kubelets can do via the authed port.

View File

@ -136,7 +136,13 @@ namespace. In order to enforce integrity of that process, we strongly recommend
Yes.
For Kubernetes 1.0, we strongly recommend running the following set of admission control plug-ins (order matters):
For Kubernetes >= 1.2.0, we strongly recommend running the following set of admission control plug-ins (order matters):
```shell
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota
```
For Kubernetes >= 1.0.0, we strongly recommend running the following set of admission control plug-ins (order matters):
```shell
--admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota

View File

@ -25,6 +25,7 @@ When using token authentication from an http client the apiserver expects an `Au
header with a value of `Bearer SOMETOKEN`.
**OpenID Connect ID Token** is enabled by passing the following options to the apiserver:
- `--oidc-issuer-url` (required) tells the apiserver where to connect to the OpenID provider. Only HTTPS scheme will be accepted.
- `--oidc-client-id` (required) is used by apiserver to verify the audience of the token.
A valid [ID token](http://openid.net/specs/openid-connect-core-1_0.html#IDToken) MUST have this
@ -59,38 +60,47 @@ with a value of `Basic BASE64ENCODED(USER:PASSWORD)`.
**Keystone authentication** is enabled by passing the `--experimental-keystone-url=<AuthURL>`
option to the apiserver during startup. The plugin is implemented in
`plugin/pkg/auth/authenticator/request/keystone/keystone.go`.
`plugin/pkg/auth/authenticator/password/keystone/keystone.go`.
For details on how to use keystone to manage projects and users, refer to the
[Keystone documentation](http://docs.openstack.org/developer/keystone/). Please note that
this plugin is still experimental which means it is subject to changes.
Please refer to the [discussion](https://github.com/kubernetes/kubernetes/pull/11798#issuecomment-129655212)
and the [blueprint](https://github.com/kubernetes/kubernetes/issues/11626) for more details
and the [blueprint](https://github.com/kubernetes/kubernetes/issues/11626) for more details.
## Plugin Development
We plan for the Kubernetes API server to issue tokens
after the user has been (re)authenticated by a *bedrock* authentication
provider external to Kubernetes. We plan to make it easy to develop modules
that interface between Kubernetes and a bedrock authentication provider (e.g.
github.com, google.com, enterprise directory, kerberos, etc.)
We plan for the Kubernetes API server to issue tokens after the user has been
(re)authenticated by a *bedrock* authentication provider external to Kubernetes.
We also plan to make it easy to develop modules that interface between
Kubernetes and a bedrock authentication provider (e.g. github.com, google.com,
enterprise directory, kerberos, etc.)
## APPENDIX
### Creating Certificates
When using client certificate authentication, you can generate certificates manually or
using an existing deployment script.
When using client certificate authentication, you can generate certificates
using an existing deployment script or manually through `easyrsa` or `openssl.``
**Deployment script** is implemented at
`cluster/saltbase/salt/generate-cert/make-ca-cert.sh`.
Execute this script with two parameters. First is the IP address of apiserver, the second is
a list of subject alternate names in the form `IP:<ip-address> or DNS:<dns-name>`.
The script will generate three files:ca.crt, server.crt and server.key.
Finally, add these parameters
`--client-ca-file=/srv/kubernetes/ca.crt`
`--tls-cert-file=/srv/kubernetes/server.cert`
`--tls-private-key-file=/srv/kubernetes/server.key`
into apiserver start parameters.
#### Using an Existing Deployment Script
**Using an existing deployment script** is implemented at
`cluster/saltbase/salt/generate-cert/make-ca-cert.sh`.
Execute this script with two parameters. The first is the IP address
of apiserver. The second is a list of subject alternate names in the form `IP:<ip-address> or DNS:<dns-name>`.
The script will generate three files: `ca.crt`, `server.crt`, and `server.key`.
Finally, add the following parameters into apiserver start parameters:
- `--client-ca-file=/srv/kubernetes/ca.crt`
- `--tls-cert-file=/srv/kubernetes/server.cert`
- `--tls-private-key-file=/srv/kubernetes/server.key`
#### easyrsa
**easyrsa** can be used to manually generate certificates for your cluster.
@ -107,29 +117,34 @@ into apiserver start parameters.
(build-server-full [filename]: Generate a keypair and sign locally for a client or server)
./easyrsa --subject-alt-name="IP:${MASTER_IP}" build-server-full kubernetes-master nopass
1. Copy `pki/ca.crt` `pki/issued/kubernetes-master.crt`
`pki/private/kubernetes-master.key` to your directory.
1. Remember fill the parameters
`--client-ca-file=/yourdirectory/ca.crt`
`--tls-cert-file=/yourdirectory/server.cert`
`--tls-private-key-file=/yourdirectory/server.key`
and add these into apiserver start parameters.
1. Copy `pki/ca.crt`, `pki/issued/kubernetes-master.crt`, and `pki/private/kubernetes-master.key` to your directory.
1. Fill in and add the following parameters into the apiserver start parameters:
--client-ca-file=/yourdirectory/ca.crt
--tls-cert-file=/yourdirectory/server.cert
--tls-private-key-file=/yourdirectory/server.key
#### openssl
**openssl** can also be use to manually generate certificates for your cluster.
1. Generate a ca.key with 2048bit
`openssl genrsa -out ca.key 2048`
1. According to the ca.key generate a ca.crt. (-days set the certificate effective time).
`openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt`
1. Generate a ca.key with 2048bit:
openssl genrsa -out ca.key 2048
1. According to the ca.key generate a ca.crt (use -days to set the certificate effective time):
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
1. Generate a server.key with 2048bit
`openssl genrsa -out server.key 2048`
1. According to the server.key generate a server.csr.
`openssl req -new -key server.key -subj "/CN=${MASTER_IP}" -out server.csr`
1. According to the ca.key, ca.crt and server.csr generate the server.crt.
`openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
-days 10000`
openssl genrsa -out server.key 2048
1. According to the server.key generate a server.csr:
openssl req -new -key server.key -subj "/CN=${MASTER_IP}" -out server.csr
1. According to the ca.key, ca.crt and server.csr generate the server.crt:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000
1. View the certificate.
`openssl x509 -noout -text -in ./server.crt`
Finally, do not forget fill the same parameters and add parameters into apiserver start parameters.
openssl x509 -noout -text -in ./server.crt
Finally, do not forget to fill out and add the same parameters into the apiserver start parameters.

View File

@ -13,31 +13,35 @@ policies. An API call must be allowed by some policy in order to proceed.
The following implementations are available, and are selected by flag:
- `--authorization-mode=AlwaysDeny`
- `--authorization-mode=AlwaysAllow`
- `--authorization-mode=ABAC`
- `--authorization-mode=Webhook`
`AlwaysDeny` blocks all requests (used in tests).
`AlwaysAllow` allows all requests; use if you don't need authorization.
`ABAC` allows for user-configured authorization policy. ABAC stands for Attribute-Based Access Control.
`Webhook` allows for authorization to be driven by a remote service using REST.
- `--authorization-mode=AlwaysDeny` blocks all requests (used in tests).
- `--authorization-mode=AlwaysAllow` allows all requests; use if you don't
need authorization.
- `--authorization-mode=ABAC`allows for user-configured authorization policy.
ABAC stands for
Attribute-Based Access Control.
- `--authorization-mode=Webhook` allows for authorization to be driven by a
remote service using REST.
## ABAC Mode
### Request Attributes
A request has the following attributes that can be considered for authorization:
- user (the user-string which a user was authenticated as).
- group (the list of group names the authenticated user is a member of).
- whether the request is for an API resource.
- the request path.
- allows authorizing access to miscellaneous endpoints like `/api` or `/healthz` (see [kubectl](#kubectl)).
- allows authorizing access to miscellaneous endpoints like `/api` or
`/healthz` (see [kubectl](#kubectl)).
- the request verb.
- API verbs like `get`, `list`, `create`, `update`, `watch`, `delete`, and `deletecollection` are used for API requests
- HTTP verbs like `get`, `post`, `put`, and `delete` are used for non-API requests
- API verbs like `get`, `list`, `create`, `update`, `watch`, `delete`, and
`deletecollection` are used for API requests
- HTTP verbs like `get`, `post`, `put`, and `delete` are used for non-API
requests
- what resource is being accessed (for API requests only)
- the namespace of the object being accessed (for namespaced API requests only)
- the namespace of the object being accessed (for namespaced API requests
only)
- the API group being accessed (for API requests only)
We anticipate adding more attributes to allow finer grained access control and
@ -47,33 +51,33 @@ to assist in policy management.
For mode `ABAC`, also specify `--authorization-policy-file=SOME_FILENAME`.
The file format is [one JSON object per line](http://jsonlines.org/). There should be no enclosing list or map, just
one map per line.
The file format is [one JSON object per line](http://jsonlines.org/). There
should be no enclosing list or map, just one map per line.
Each line is a "policy object". A policy object is a map with the following
properties:
Each line is a "policy object". A policy object is a map with the following properties:
- Versioning properties:
- `apiVersion`, type string; valid values are "abac.authorization.kubernetes.io/v1beta1". Allows versioning and conversion of the policy format.
- `kind`, type string: valid values are "Policy". Allows versioning and conversion of the policy format.
- `spec` property set to a map with the following properties:
- Subject-matching properties:
- `user`, type string; the user-string from `--token-auth-file`. If you specify `user`, it must match the username of the authenticated user. `*` matches all requests.
- `group`, type string; if you specify `group`, it must match one of the groups of the authenticated user. `*` matches all requests.
- `readonly`, type boolean, when true, means that the policy only applies to get, list, and watch operations.
- Resource-matching properties:
- `apiGroup`, type string; an API group, such as `extensions`. `*` matches all API groups.
- `namespace`, type string; a namespace string. `*` matches all resource requests.
- `resource`, type string; a resource, such as `pods`. `*` matches all resource requests.
- Non-resource-matching properties:
- `nonResourcePath`, type string; matches the non-resource request paths (like `/version` and `/apis`). `*` matches all non-resource requests. `/foo/*` matches `/foo/` and all of its subpaths.
An unset property is the same as a property set to the zero value for its type (e.g. empty string, 0, false).
However, unset should be preferred for readability.
An unset property is the same as a property set to the zero value for its type
(e.g. empty string, 0, false). However, unset should be preferred for
readability.
In the future, policies may be expressed in a JSON format, and managed via a REST interface.
In the future, policies may be expressed in a JSON format, and managed via a
REST interface.
### Authorization Algorithm
@ -84,23 +88,32 @@ are set to the zero value of its type (e.g. empty string, 0, false).
A property set to "*" will match any value of the corresponding attribute.
The tuple of attributes is checked for a match against every policy in the policy file.
If at least one line matches the request attributes, then the request is authorized (but may fail later validation).
The tuple of attributes is checked for a match against every policy in the
policy file. If at least one line matches the request attributes, then the
request is authorized (but may fail later validation).
To permit any user to do something, write a policy with the user property set to "*".
To permit a user to do anything, write a policy with the apiGroup, namespace, resource, and nonResourcePath properties set to "*".
To permit any user to do something, write a policy with the user property set to
"*".
To permit a user to do anything, write a policy with the apiGroup, namespace,
resource, and nonResourcePath properties set to "*".
### Kubectl
Kubectl uses the `/api` and `/apis` endpoints of api-server to negotiate client/server versions. To validate objects sent to the API by create/update operations, kubectl queries certain swagger resources. For API version `v1` those would be `/swaggerapi/api/v1` & `/swaggerapi/experimental/v1`.
Kubectl uses the `/api` and `/apis` endpoints of api-server to negotiate
client/server versions. To validate objects sent to the API by create/update
operations, kubectl queries certain swagger resources. For API version `v1`
those would be `/swaggerapi/api/v1` & `/swaggerapi/experimental/v1`.
When using ABAC authorization, those special resources have to be explicitly exposed via the `nonResourcePath` property in a policy (see [examples](#examples) below):
When using ABAC authorization, those special resources have to be explicitly
exposed via the `nonResourcePath` property in a policy (see [examples](#examples) below):
* `/api`, `/api/*`, `/apis`, and `/apis/*` for API version negotiation.
* `/version` for retrieving the server version via `kubectl version`.
* `/swaggerapi/*` for create/update operations.
To inspect the HTTP calls involved in a specific kubectl operation you can turn up the verbosity:
To inspect the HTTP calls involved in a specific kubectl operation you can turn
up the verbosity:
kubectl --v=8 version
@ -116,18 +129,22 @@ To inspect the HTTP calls involved in a specific kubectl operation you can turn
### A quick note on service accounts
A service account automatically generates a user. The user's name is generated according to the naming convention:
A service account automatically generates a user. The user's name is generated
according to the naming convention:
```shell
system:serviceaccount:<namespace>:<serviceaccountname>
```
Creating a new namespace also causes a new service account to be created, of this form:*
Creating a new namespace also causes a new service account to be created, of
this form:*
```shell
system:serviceaccount:<namespace>:default
```
For example, if you wanted to grant the default service account in the kube-system full privilege to the API, you would add this line to your policy file:
For example, if you wanted to grant the default service account in the
kube-system full privilege to the API, you would add this line to your policy
file:
```json
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","user":"system:serviceaccount:kube-system:default","namespace":"*","resource":"*","apiGroup":"*"}
@ -137,13 +154,17 @@ The apiserver will need to be restarted to pickup the new policy lines.
## Webhook Mode
When specified, mode `Webhook` causes Kubernetes to query an outside REST service when determining user privileges.
When specified, mode `Webhook` causes Kubernetes to query an outside REST
service when determining user privileges.
### Configuration File Format
Mode `Webhook` requires a file for HTTP configuration, specify by the `--authorization-webhook-config-file=SOME_FILENAME` flag.
Mode `Webhook` requires a file for HTTP configuration, specify by the
`--authorization-webhook-config-file=SOME_FILENAME` flag.
The configuration file uses the [kubeconfig](/docs/user-guide/kubeconfig-file/) file format. Within the file "users" refers to the API Server webhook and "clusters" refers to the remote service.
The configuration file uses the [kubeconfig](/docs/user-guide/kubeconfig-file/)
file format. Within the file "users" refers to the API Server webhook and
"clusters" refers to the remote service.
A configuration example which uses HTTPS client auth:
@ -173,9 +194,17 @@ contexts:
### Request Payloads
When faced with an authorization decision, the API Server POSTs a JSON serialized api.authorization.v1beta1.SubjectAccessReview object describing the action. This object contains fields describing the user attempting to make the request, and either details about the resource being accessed or requests attributes.
When faced with an authorization decision, the API Server POSTs a JSON
serialized api.authorization.v1beta1.SubjectAccessReview object describing the
action. This object contains fields describing the user attempting to make the
request, and either details about the resource being accessed or requests
attributes.
Note that webhook API objects are subject to the same [versioning compatibility rules](/docs/api/) as other Kubernetes API objects. Implementers should be aware of loser compatibility promises for beta objects and check the "apiVersion" field of the request to ensure correct deserialization. Additionally, the API Server must enable the `authorization.k8s.io/v1beta1` API extensions group (`--runtime-config=authorization.k8s.io/v1beta1=true`).
Note that webhook API objects are subject to the same [versioning compatibility rules](/docs/api/)
as other Kubernetes API objects. Implementers should be aware of loser
compatibility promises for beta objects and check the "apiVersion" field of the
request to ensure correct deserialization. Additionally, the API Server must
enable the `authorization.k8s.io/v1beta1` API extensions group (`--runtime-config=authorization.k8s.io/v1beta1=true`).
An example request body:
@ -199,7 +228,9 @@ An example request body:
}
```
The remote service is expected to fill the SubjectAccessReviewStatus field of the request and respond to either allow or disallow access. The response body's "spec" field is ignored and may be omitted. A permissive response would return:
The remote service is expected to fill the SubjectAccessReviewStatus field of
the request and respond to either allow or disallow access. The response body's
"spec" field is ignored and may be omitted. A permissive response would return:
```json
{
@ -244,9 +275,15 @@ Access to non-resource paths are sent as:
}
```
Non-resource paths include: `/api`, `/apis`, `/metrics`, `/resetMetrics`, `/logs`, `/debug`, `/healthz`, `/swagger-ui/`, `/swaggerapi/`, `/ui`, and `/version.` Clients require access to `/api`, `/api/*/`, `/apis/`, `/apis/*`, `/apis/*/*`, and `/version` to discover what resources and versions are present on the server. Access to other non-resource paths can be disallowed without restricting access to the REST api.
Non-resource paths include: `/api`, `/apis`, `/metrics`, `/resetMetrics`,
`/logs`, `/debug`, `/healthz`, `/swagger-ui/`, `/swaggerapi/`, `/ui`, and
`/version.` Clients require access to `/api`, `/api/*/`, `/apis/`, `/apis/*`,
`/apis/*/*`, and `/version` to discover what resources and versions are present
on the server. Access to other non-resource paths can be disallowed without
restricting access to the REST api.
For further documentation refer to the authorization.v1beta1 API objects and plugin/pkg/auth/authorizer/webhook/webhook.go.
For further documentation refer to the authorization.v1beta1 API objects and
plugin/pkg/auth/authorizer/webhook/webhook.go.
## Plugin Development
@ -267,5 +304,5 @@ Authorization plugin code goes in `pkg/auth/authorizer/$MODULENAME`.
An authorization module can be completely implemented in go, or can call out
to a remote authorization service. Authorization modules can implement
their own caching to reduce the cost of repeated authorization calls with the
same or similar arguments. Developers should then consider the interaction between
caching and revocation of permissions.
same or similar arguments. Developers should then consider the interaction
between caching and revocation of permissions.

View File

@ -68,7 +68,7 @@ Addon objects are created in the "kube-system" namespace.
#### DNS
While the other addons are not strictly required, all Kubernetes
clusters should have [cluster DNS](dns.md), as many examples rely on it.
clusters should have [cluster DNS](/docs/admin/dns/), as many examples rely on it.
Cluster DNS is a DNS server, in addition to the other DNS server(s) in your
environment, which serves DNS records for Kubernetes services.
@ -88,15 +88,15 @@ about containers in a central database, and provides a UI for browsing that data
#### Cluster-level Logging
[Container Logging](/docs/user-guide/monitoring.md) saves container logs
[Container Logging](/docs/user-guide/monitoring) saves container logs
to a central log store with search/browsing interface. There are two
implementations:
* [Cluster-level logging to Google Cloud Logging](
docs/user-guide/logging/#cluster-level-logging-to-google-cloud-logging)
/docs/user-guide/logging/#cluster-level-logging-to-google-cloud-logging)
* [Cluster-level Logging with Elasticsearch and Kibana](
docs/user-guide/logging/#cluster-level-logging-with-elasticsearch-and-kibana)
/docs/getting-started-guides/logging-elasticsearch/)
## Node components
@ -138,4 +138,3 @@ running.
### fluentd
`fluentd` is a daemon which helps provide [cluster-level logging](#cluster-level-logging).

View File

@ -102,7 +102,8 @@ To avoid running into cluster addon resource issues, when creating a cluster wit
* [FluentD with ElasticSearch Plugin](http://releases.k8s.io/{{page.githubbranch}}/cluster/saltbase/salt/fluentd-es/fluentd-es.yaml)
* [FluentD with GCP Plugin](http://releases.k8s.io/{{page.githubbranch}}/cluster/saltbase/salt/fluentd-gcp/fluentd-gcp.yaml)
Heapster's resource limits are set dynamically based on the initial size of your cluster (see [#16185](http://issue.k8s.io/16185) and [#21258](http://issue.k8s.io/21258)). If you find that Heapster is running
Heapster's resource limits are set dynamically based on the initial size of your cluster (see [#16185](http://issue.k8s.io/16185)
and [#22940](http://issue.k8s.io/22940)). If you find that Heapster is running
out of resources, you should adjust the formulas that compute heapster memory request (see those PRs for details).
For directions on how to detect if addon containers are hitting resource limits, see the [Troubleshooting section of Compute Resources](/docs/user-guide/compute-resources/#troubleshooting).

View File

@ -28,9 +28,8 @@ The steps involved are as follows:
* [Setting up master-elected Kubernetes scheduler and controller-manager daemons](#master-elected-components)
Here's what the system should look like when it's finished:
![High availability Kubernetes diagram](/images/docs/ha.svg)
Ready? Let's get started.
![High availability Kubernetes diagram](/images/docs/ha.svg)
## Initial set-up
@ -55,11 +54,11 @@ choices. For example, on systemd-based systems (e.g. RHEL, CentOS), you can run
If you are extending from a standard Kubernetes installation, the `kubelet` binary should already be present on your system. You can run
`which kubelet` to determine if the binary is in fact installed. If it is not installed,
you should install the [kubelet binary](https://storage.googleapis.com/kubernetes-release/release/v0.19.3/bin/linux/amd64/kubelet), the
[kubelet init file](http://releases.k8s.io/{{page.githubbranch}}/cluster/saltbase/salt/kubelet/initd) and [high-availability/default-kubelet](/docs/admin/high-availability/default-kubelet)
[kubelet init file](http://releases.k8s.io/{{page.githubbranch}}/cluster/saltbase/salt/kubelet/initd) and [default-kubelet](/docs/admin/high-availability/default-kubelet)
scripts.
If you are using monit, you should also install the monit daemon (`apt-get install monit`) and the [high-availability/monit-kubelet](/docs/admin/high-availability/monit-kubelet) and
[high-availability/monit-docker](/docs/admin/high-availability/monit-docker) configs.
If you are using monit, you should also install the monit daemon (`apt-get install monit`) and the [monit-kubelet](/docs/admin/high-availability/monit-kubelet) and
[monit-docker](/docs/admin/high-availability/monit-docker) configs.
On systemd systems you `systemctl enable kubelet` and `systemctl enable docker`.
@ -79,7 +78,7 @@ size of the cluster from three to five nodes. If that is still insufficient, yo
### Clustering etcd
The full details of clustering etcd are beyond the scope of this document, lots of details are given on the
[etcd clustering page](https://github.com/coreos/etcd/blob/master/Documentation/clustering.md). This example walks through
[etcd clustering page](https://github.com/coreos/etcd/blob/master/Documentation/op-guide/clustering.md). This example walks through
a simple cluster set up, using etcd's built in discovery to build our cluster.
First, hit the etcd discovery service to create a new token:
@ -94,7 +93,7 @@ The kubelet on each node actively monitors the contents of that directory, and i
server from the definition of the pod specified in `etcd.yaml`.
Note that in `etcd.yaml` you should substitute the token URL you got above for `${DISCOVERY_TOKEN}` on all three machines,
and you should substitute a different name (e.g. `node-1`) for ${NODE_NAME} and the correct IP address
and you should substitute a different name (e.g. `node-1`) for `${NODE_NAME}` and the correct IP address
for `${NODE_IP}` on each machine.

View File

@ -61,7 +61,7 @@ project](/docs/admin/salt).
## Multi-tenant support
* **Resource Quota** ([resource-quota.md](/docs/admin/resource-quota))
* **Resource Quota** ([resourcequota/](/docs/admin/resourcequota/))
## Security

View File

@ -22,7 +22,7 @@ may be too small to be useful, but big enough for the waste to be costly over th
the cluster operator may want to set limits that a pod must consume at least 20% of the memory and cpu of their
average node size in order to provide for more uniform scheduling and to limit waste.
This example demonstrates how limits can be applied to a Kubernetes namespace to control
This example demonstrates how limits can be applied to a Kubernetes [namespace](/docs/admin/namespaces/walkthrough/) to control
min/max resource limits per pod. In addition, this example demonstrates how you can
apply default resource limits to pods in the absence of an end-user specified value.
@ -41,12 +41,17 @@ This example will work in a custom namespace to demonstrate the concepts involve
Let's create a new namespace called limit-example:
```shell
$ kubectl create -f docs/admin/limitrange/namespace.yaml
namespace "limit-example" created
$ kubectl create namespace limit-example
namespace "limit-example" created
```
Note that `kubectl` commands will print the type and name of the resource created or mutated, which can then be used in subsequent commands:
```shell
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 5m
limit-example <none> Active 53s
NAME STATUS AGE
default Active 51s
limit-example Active 45s
```
## Step 2: Apply a limit to the namespace
@ -95,36 +100,45 @@ were previously created in a namespace.
If a resource (cpu or memory) is being restricted by a limit, the user will get an error at time
of creation explaining why.
Let's first spin up a replication controller that creates a single container pod to demonstrate
Let's first spin up a [Deployment](/docs/user-guide/deployments) that creates a single container Pod to demonstrate
how default values are applied to each pod.
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
replicationcontroller "nginx" created
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-aq0mf 1/1 Running 0 35s
$ kubectl get pods nginx-aq0mf --namespace=limit-example -o yaml | grep resources -C 8
deployment "nginx" created
```
```yaml
resourceVersion: "127"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-aq0mf
uid: 51be42a7-7156-11e5-9921-286ed488f785
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
Note that `kubectl run` creates a Deployment named "nginx" on Kubernetes cluster >= v1.2. If you are running older versions, it creates replication controllers instead.
If you want to obtain the old behavior, use `--generator=run/v1` to create replication controllers. See [`kubectl run`](/docs/user-guide/kubectl/kubectl_run/) for more details.
The Deployment manages 1 replica of single container Pod. Let's take a look at the Pod it manages. First, find the name of the Pod:
```shell
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-2040093540-s8vzu 1/1 Running 0 11s
```
Let's print this Pod with yaml output format (using `-o yaml` flag), and then `grep` the `resources` field. Note that your pod name will be different.
``` shell
$ kubectl get pods nginx-2040093540-s8vzu --namespace=limit-example -o yaml | grep resources -C 8
resourceVersion: "57"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-2040093540-ivimu
uid: 67b20741-f53b-11e5-b066-64510658e388
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
```
Note that our nginx container has picked up the namespace default cpu and memory resource *limits* and *requests*.
@ -141,37 +155,39 @@ Let's create a pod that falls within the allowed limit boundaries.
```shell
$ kubectl create -f docs/admin/limitrange/valid-pod.yaml --namespace=limit-example
pod "valid-pod" created
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
```
```yaml
uid: 162a12aa-7157-11e5-9921-286ed488f785
spec:
containers:
- image: gcr.io/google_containers/serve_hostname
imagePullPolicy: IfNotPresent
name: kubernetes-serve-hostname
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "1"
memory: 512Mi
Now look at the Pod's resources field:
```shell
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
uid: 3b1bfd7a-f53c-11e5-b066-64510658e388
spec:
containers:
- image: gcr.io/google_containers/serve_hostname
imagePullPolicy: Always
name: kubernetes-serve-hostname
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "1"
memory: 512Mi
```
Note that this pod specifies explicit resource *limits* and *requests* so it did not pick up the namespace
default values.
Note: The *limits* for CPU resource are not enforced in the default Kubernetes setup on the physical node
Note: The *limits* for CPU resource are enforced in the default Kubernetes setup on the physical node
that runs the container unless the administrator deploys the kubelet with the folllowing flag:
```shell
$ kubelet --help
Usage of kubelet
....
--cpu-cfs-quota[=false]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=true ...
--cpu-cfs-quota[=true]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=false ...
```
## Step 4: Cleanup
@ -182,8 +198,8 @@ To remove the resources used by this example, you can just delete the limit-exam
$ kubectl delete namespace limit-example
namespace "limit-example" deleted
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 20m
NAME STATUS AGE
default Active 12m
```
## Summary
@ -191,4 +207,4 @@ default <none> Active 20m
Cluster operators that want to restrict the amount of resources a single container or pod may consume
are able to define allowable ranges per Kubernetes namespace. In the absence of any explicit assignments,
the Kubernetes system is able to apply default resource *limits* and *requests* if desired in order to
constrain the amount of resource a pod consumes on a node.
constrain the amount of resource a pod consumes on a node.

View File

@ -0,0 +1,156 @@
---
---
Kubernetes ships with a default scheduler that is described [here](/docs/admin/kube-scheduler/).
If the default scheduler does not suit your needs you can implement your own scheduler.
Not just that, you can even run multiple schedulers simultaneously alongside the default
scheduler and instruct Kubernetes what scheduler to use for each of your pods. Let's
learn how to run multiple schedulers in Kubernetes with an example.
A detailed description of how to implement a scheduler is outside the scope of this
document. Please refer to the kube-scheduler implementation in
[plugin/pkg/scheduler](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/plugin/pkg/scheduler)
in the Kubernetes source directory for a canonical example.
### 1. Package the scheduler
Package your scheduler binary into a container image. For the purposes of this example,
let's just use the default scheduler (kube-scheduler) as our second scheduler as well.
Clone the [Kubernetes source code from Github](https://github.com/kubernetes/kubernetes)
and build the source.
```shell
git clone https://github.com/kubernetes/kubernetes.git
cd kubernetes
hack/build-go.sh
```
Create a container image containing the kube-scheduler binary. Here is the `Dockerfile`
to build the image:
```docker
FROM busybox
ADD _output/local/go/bin/kube-scheduler /usr/local/bin/kube-scheduler
```
Save the file as `Dockerfile`, build the image and push it to a registry. This example
pushes the image to
[Google Container Registry (GCR)](https://cloud.google.com/container-registry/).
For more details, please read the GCR
[documentation](https://cloud.google.com/container-registry/docs/).
```shell
docker build -t my-kube-scheduler:1.0 .
gcloud docker push gcr.io/my-gcp-project/my-kube-scheduler:1.0
```
### 2. Define a Kubernetes Deployment for the scheduler
Now that we have our scheduler in a container image, we can just create a pod
config for it and run it in our Kubernetes cluster. But instead of creating a pod
directly in the cluster, let's use a [Deployment](/docs/user-guide/deployments/)
for this example. A [Deployment](/docs/user-guide/deployments/) manages a
[Replica Set](/docs/user-guide/replicasets/) which in turn manages the pods,
thereby making the scheduler resilient to failures. Here is the deployment
config. Save it as `my-scheduler.yaml`:
{% include code.html language="yaml" file="multiple-schedulers/my-scheduler.yaml" ghlink="/docs/admin/multiple-schedulers/my-scheduler.yaml" %}
An important thing to note here is that the name of the scheduler specified as an
argument to the scheduler command in the container spec should be unique. This is the name that is matched against the value of the optional `scheduler.alpha.kubernetes.io/name` annotation on pods, to determine whether this scheduler is responsible for scheduling a particular pod.
Please see the
[kube-scheduler documentation](/docs/admin/kube-scheduler/) for
detailed description of other command line arguments.
### 3. Run the second scheduler in the cluster
In order to run your scheduler in a Kubernetes cluster, just create the deployment
specified in the config above in a Kubernetes cluster:
```shell
kubectl create -f my-scheduler.yaml
```
Verify that the scheduler pod is running:
```shell
$ kubectl get pods --namespace=kube-system
NAME READY STATUS RESTARTS AGE
....
my-scheduler-lnf4s-4744f 1/1 Running 0 2m
...
```
You should see a "Running" my-scheduler pod, in addition to the default kube-scheduler
pod in this list.
### 4. Specify schedulers for pods
Now that our second scheduler is running, let's create some pods, and direct them to be scheduled by either the default scheduler or the one we just deployed. In order to schedule a given pod using a specific scheduler, we specify the name of the
scheduler as an annotation in that pod spec. Let's look at three examples.
1. Pod spec without any scheduler annotation
{% include code.html language="yaml" file="multiple-schedulers/pod1.yaml" ghlink="/docs/admin/multiple-schedulers/pod1.yaml" %}
When no scheduler annotation is supplied, the pod is automatically scheduled using the
default-scheduler.
Save this file as `pod1.yaml` and submit it to the Kubernetes cluster.
```shell
kubectl create -f pod1.yaml
```
2. Pod spec with `default-scheduler` annotation
{% include code.html language="yaml" file="multiple-schedulers/pod2.yaml" ghlink="/docs/admin/multiple-schedulers/pod2.yaml" %}
A scheduler is specified by supplying the scheduler name as a value to the annotation
with key `scheduler.alpha.kubernetes.io/name`. In this case, we supply the name of the
default scheduler which is `default-scheduler`.
Save this file as `pod2.yaml` and submit it to the Kubernetes cluster.
```shell
kubectl create -f pod2.yaml
```
3. Pod spec with `my-scheduler` annotation
{% include code.html language="yaml" file="multiple-schedulers/pod3.yaml" ghlink="/docs/admin/multiple-schedulers/pod3.yaml" %}
In this case, we specify that this pod should be scheduled using the scheduler that we
deployed - `my-scheduler`. Note that the value of the annotation with key
`scheduler.alpha.kubernetes.io/name` should match the name supplied to the scheduler
command as an argument in the deployment config for the scheduler.
Save this file as `pod3.yaml` and submit it to the Kubernetes cluster.
```shell
kubectl create -f pod3.yaml
```
Verify that all three pods are running.
```shell
kubectl get pods
```
### Verifying that the pods were scheduled using the desired schedulers
In order to make it easier to work through these examples, we did not verify that the
pods were actually scheduled using the desired schedulers. We can verify that by
changing the order of pod and deployment config submissions above. If we submit all the
pod configs to a Kubernetes cluster before submitting the scheduler deployment config,
we see that the pod `annotation-second-scheduler` remains in "Pending" state forever
while the other two pods get scheduled. Once we submit the scheduler deployment config
and our new scheduler starts running, the `annotation-second-scheduler` pod gets
scheduled as well.
Alternatively, one could just look at the "Scheduled" entries in the event logs to
verify that the pods were scheduled by the desired schedulers.
```shell
kubectl get events
```

View File

@ -0,0 +1,40 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
component: scheduler
tier: control-plane
name: my-scheduler
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
component: scheduler
tier: control-plane
version: second
spec:
containers:
- command: [/usr/local/bin/kube-scheduler, --address=0.0.0.0,
--scheduler-name=my-scheduler]
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
livenessProbe:
httpGet:
path: /healthz
port: 10251
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10251
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts: []
hostNetwork: false
hostPID: false
volumes: []

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: no-annotation
labels:
name: multischeduler-example
spec:
containers:
- name: pod-with-no-annotation-container
image: gcr.io/google_containers/pause:2.0

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: annotation-default-scheduler
annotations:
scheduler.alpha.kubernetes.io/name: default-scheduler
labels:
name: multischeduler-example
spec:
containers:
- name: pod-with-default-annotation-container
image: gcr.io/google_containers/pause:2.0

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: annotation-second-scheduler
annotations:
scheduler.alpha.kubernetes.io/name: my-scheduler
labels:
name: multischeduler-example
spec:
containers:
- name: pod-with-second-annotation-container
image: gcr.io/google_containers/pause:2.0

View File

@ -0,0 +1,313 @@
---
---
## Introduction
Kubernetes 1.2 adds support for running a single cluster in multiple failure zones
(GCE calls them simply "zones", AWS calls them "availability zones", here we'll refer to them as "zones").
This is a lightweight version of a broader effort for federating multiple
Kubernetes clusters together (sometimes referred to by the affectionate
nickname ["Ubernetes"](https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/federation.md).
Full federation will allow combining separate
Kubernetes clusters running in different regions or clouds. However, many
users simply want to run a more available Kubernetes cluster in multiple zones
of their cloud provider, and this is what the multizone support in 1.2 allows
(we nickname this "Ubernetes Lite").
Multizone support is deliberately limited: a single Kubernetes cluster can run
in multiple zones, but only within the same region (and cloud provider). Only
GCE and AWS are currently supported automatically (though it is easy to
add similar support for other clouds or even bare metal, by simply arranging
for the appropriate labels to be added to nodes and volumes).
* TOC
{:toc}
## Functionality
When nodes are started, the kubelet automatically adds labels to them with
zone information.
Kubernetes will automatically spread the pods in a replication controller
or service across nodes in a single-zone cluster (to reduce the impact of
failures.) With multiple-zone clusters, this spreading behaviour is
extended across zones (to reduce the impact of zone failures.) (This is
achieved via `SelectorSpreadPriority`). This is a best-effort
placement, and so if the zones in your cluster are heterogenous
(e.g. different numbers of nodes, different types of nodes, or
different pod resource requirements), this might prevent perfectly
even spreading of your pods across zones. If desired, you can use
homogenous zones (same number and types of nodes) to reduce the
probability of unequal spreading.
When persistent volumes are created, the `PersistentVolumeLabel`
admission controller automatically adds zone labels to them. The scheduler (via the
`VolumeZonePredicate` predicate) will then ensure that pods that claim a
given volume are only placed into the same zone as that volume, as volumes
cannot be attached across zones.
## Limitations
There are some important limitations of the multizone support:
* We assume that the different zones are located close to each other in the
network, so we don't perform any zone-aware routing. In particular, traffic
that goes via services might cross zones (even if pods in some pods backing that service
exist in the same zone as the client), and this may incur additional latency and cost.
* Volume zone-affinity will only work with a `PersistentVolume`, and will not
work if you directly specify an EBS volume in the pod spec (for example).
* Clusters cannot span clouds or regions (this functionality will require full
federation support).
* Although your nodes are in multiple zones, kube-up currently builds
a single master node by default. While services are highly
available and can tolerate the loss of a zone, the control plane is
located in a single zone. Users that want a highly available control
plane should follow the [high availability](/docs/admin/high-availability) instructions.
## Walkthough
We're now going to walk through setting up and using a multi-zone
cluster on both GCE & AWS. To do so, you bring up a full cluster
(specifying `MULTIZONE=1`), and then you add nodes in additional zones
by running `kube-up` again (specifying `KUBE_USE_EXISTING_MASTER=true`).
### Bringing up your cluster
Create the cluster as normal, but pass MULTIZONE to tell the cluster to manage multiple zones; creating nodes in us-central1-a.
GCE:
```shell
curl -sS https://get.k8s.io | MULTIZONE=1 KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash
```
AWS:
```shell
curl -sS https://get.k8s.io | MULTIZONE=1 KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash
```
This step brings up a cluster as normal, still running in a single zone
(but `MULTIZONE=1` has enabled multi-zone capabilities).
### Nodes are labeled
View the nodes; you can see that they are labeled with zone information.
They are all in `us-central1-a` (GCE) or `us-west-2a` (AWS) so far. The
labels are `failure-domain.beta.kubernetes.io/region` for the region,
and `failure-domain.beta.kubernetes.io/zone` for the zone:
```shell
> kubectl get nodes --show-labels
NAME STATUS AGE LABELS
kubernetes-master Ready,SchedulingDisabled 6m beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9 Ready 6m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready 6m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready 6m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
```
### Add more nodes in a second zone
Let's add another set of nodes to the existing cluster, reusing the
existing master, running in a different zone (us-central1-b or us-west-2b).
We run kube-up again, but by specifying `KUBE_USE_EXISTING_MASTER=1`
kube-up will not create a new master, but will reuse one that was previously
created instead.
GCE:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=1 KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh
```
On AWS we also need to specify the network CIDR for the additional
subnet, along with the master internal IP address:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=1 KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
```
View the nodes again; 3 more nodes should have launched and be tagged
in us-central1-b:
```shell
> kubectl get nodes --show-labels
NAME STATUS AGE LABELS
kubernetes-master Ready,SchedulingDisabled 16m beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-281d Ready 2m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9 Ready 16m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready 16m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready 17m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f Ready 2m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i Ready 2m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-wf8i
```
### Volume affinity
Create a volume (only PersistentVolumes are supported for zone
affinity), using the new dynamic volume creation:
```json
kubectl create -f - <<EOF
{
"kind": "PersistentVolumeClaim",
"apiVersion": "v1",
"metadata": {
"name": "claim1",
"annotations": {
"volume.alpha.kubernetes.io/storage-class": "foo"
}
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "5Gi"
}
}
}
}
EOF
```
The PV is also labeled with the zone & region it was created in. For
version 1.2, dynamic persistent volumes are always created in the zone
of the cluster master (here us-centaral1-a / us-west-2a); this will
be improved in a future version (issue [#23330](https://github.com/kubernetes/kubernetes/issues/23330).)
```shell
> kubectl get pv --show-labels
NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE LABELS
pv-gce-mj4gm 5Gi RWO Bound default/claim1 46s failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a
```
So now we will create a pod that uses the persistent volume claim.
Because GCE PDs / AWS EBS volumes cannot be attached across zones,
this means that this pod can only be created in the same zone as the volume:
```yaml
kubectl create -f - <<EOF
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: claim1
EOF
```
Note that the pod was automatically created in the same zone as the volume, as
cross-zone attachments are not generally permitted by cloud providers:
```shell
> kubectl describe pod mypod | grep Node
Node: kubernetes-minion-9vlv/10.240.0.5
> kubectl get node kubernetes-minion-9vlv --show-labels
NAME STATUS AGE LABELS
kubernetes-minion-9vlv Ready 22m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
```
### Pods are spread across zones
Pods in a replication controller or service are automatically spread
across zones. First, let's launch more nodes in a third zone:
GCE:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=1 KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh
```
AWS:
```shell
KUBE_USE_EXISTING_MASTER=true MULTIZONE=1 KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
```
Verify that you now have nodes in 3 zones:
```shell
kubectl get nodes --show-labels
```
Create the guestbook-go example, which includes an RC of size 3, running a simple web app:
```shell
find kubernetes/examples/guestbook-go/ -name '*.json' | xargs -I {} kubectl create -f {}
```
The pods should be spread across all 3 zones:
```shell
> kubectl describe pod -l app=guestbook | grep Node
Node: kubernetes-minion-9vlv/10.240.0.5
Node: kubernetes-minion-281d/10.240.0.8
Node: kubernetes-minion-olsh/10.240.0.11
> kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d kubernetes-minion-olsh --show-labels
NAME STATUS AGE LABELS
kubernetes-minion-9vlv Ready 34m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d Ready 20m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh Ready 3m beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-f,kubernetes.io/hostname=kubernetes-minion-olsh
```
Load-balancers span all zones in a cluster; the guestbook-go example
includes an example load-balanced service:
```shell
> kubectl describe service guestbook | grep LoadBalancer.Ingress
LoadBalancer Ingress: 130.211.126.21
> ip=130.211.126.21
> curl -s http://${ip}:3000/env | grep HOSTNAME
"HOSTNAME": "guestbook-44sep",
> (for i in `seq 20`; do curl -s http://${ip}:3000/env | grep HOSTNAME; done) | sort | uniq
"HOSTNAME": "guestbook-44sep",
"HOSTNAME": "guestbook-hum5n",
"HOSTNAME": "guestbook-ppm40",
```
The load balancer correctly targets all the pods, even though they are in multiple zones.
### Shutting down the cluster
When you're done, clean up:
GCE:
```shell
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a kubernetes/cluster/kube-down.sh
```
AWS:
```shell
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a kubernetes/cluster/kube-down.sh
```

View File

@ -1,145 +0,0 @@
---
---
A Namespace is a mechanism to partition resources created by users into
a logically named group.
## Motivation
A single cluster should be able to satisfy the needs of multiple users or groups of users (henceforth a 'user community').
Each user community wants to be able to work in isolation from other communities.
Each user community has its own:
1. resources (pods, services, replication controllers, etc.)
2. policies (who can or cannot perform actions in their community)
3. constraints (this community is allowed this much quota, etc.)
A cluster operator may create a Namespace for each unique user community.
The Namespace provides a unique scope for:
1. named resources (to avoid basic naming collisions)
2. delegated management authority to trusted users
3. ability to limit community resource consumption
## Use cases
1. As a cluster operator, I want to support multiple user communities on a single cluster.
2. As a cluster operator, I want to delegate authority to partitions of the cluster to trusted users
in those communities.
3. As a cluster operator, I want to limit the amount of resources each community can consume in order
to limit the impact to other communities using the cluster.
4. As a cluster user, I want to interact with resources that are pertinent to my user community in
isolation of what other user communities are doing on the cluster.
## Usage
Look [here](/docs/admin/namespaces/) for an in depth example of namespaces.
### Viewing namespaces
You can list the current namespaces in a cluster using:
```shell
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
kube-system <none> Active
```
Kubernetes starts with two initial namespaces:
* `default` The default namespace for objects with no other namespace
* `kube-system` The namespace for objects created by the Kubernetes system
You can also get the summary of a specific namespace using:
```shell
$ kubectl get namespaces <name>
```
Or you can get detailed information with:
```shell
$ kubectl describe namespaces <name>
Name: default
Labels: <none>
Status: Active
No resource quota.
Resource Limits
Type Resource Min Max Default
---- -------- --- --- ---
Container cpu - - 100m
```
Note that these details show both resource quota (if present) as well as resource limit ranges.
Resource quota tracks aggregate usage of resources in the *Namespace* and allows cluster operators
to define *Hard* resource usage limits that a *Namespace* may consume.
A limit range defines min/max constraints on the amount of resources a single entity can consume in
a *Namespace*.
See [Admission control: Limit Range](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/admission_control_limit_range.md)
A namespace can be in one of two phases:
* `Active` the namespace is in use
* `Terminating` the namespace is being deleted, and can not be used for new objects
See the [design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#phases) for more details.
### Creating a new namespace
To create a new namespace, first create a new YAML file called `my-namespace.yaml` with the contents:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: <insert-namespace-name-here>
```
Note that the name of your namespace must be a DNS compatible label.
More information on the `finalizers` field can be found in the namespace [design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#finalizers).
Then run:
```shell
$ kubectl create -f ./my-namespace.yaml
```
### Working in namespaces
See [Setting the namespace for a request](/docs/user-guide/namespaces/#setting-the-namespace-for-a-request)
and [Setting the namespace preference](/docs/user-guide/namespaces/#setting-the-namespace-preference).
### Deleting a namespace
You can delete a namespace with
```shell
$ kubectl delete namespaces <insert-some-namespace-name>
```
**WARNING, this deletes _everything_ under the namespace!**
This delete is asynchronous, so for a time you will see the namespace in the `Terminating` state.
## Namespaces and DNS
When you create a [Service](/docs/user-guide/services), it creates a corresponding [DNS entry](/docs/admin/dns).
This entry is of the form `<service-name>.<namespace-name>.svc.cluster.local`, which means
that if a container just uses `<service-name>` it will resolve to the service which
is local to a namespace. This is useful for using the same configuration across
multiple namespaces such as Development, Staging and Production. If you want to reach
across namespaces, you need to use the fully qualified domain name (FQDN).
## Design
Details of the design of namespaces in Kubernetes, including a [detailed example](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#example-openshift-origin-managing-a-kubernetes-namespace)
can be found in the [namespaces design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md)

View File

@ -1,234 +1,140 @@
---
---
Kubernetes _namespaces_ help different projects, teams, or customers to share a Kubernetes cluster.
A Namespace is a mechanism to partition resources created by users into
a logically named group.
It does this by providing the following:
## Motivation
1. A scope for [Names](/docs/user-guide/identifiers).
2. A mechanism to attach authorization and policy to a subsection of the cluster.
A single cluster should be able to satisfy the needs of multiple users or groups of users (henceforth a 'user community').
Use of multiple namespaces is optional.
Each user community wants to be able to work in isolation from other communities.
This example demonstrates how to use Kubernetes namespaces to subdivide your cluster.
Each user community has its own:
### Step Zero: Prerequisites
1. resources (pods, services, replication controllers, etc.)
2. policies (who can or cannot perform actions in their community)
3. constraints (this community is allowed this much quota, etc.)
This example assumes the following:
A cluster operator may create a Namespace for each unique user community.
1. You have an [existing Kubernetes cluster](/docs/getting-started-guides/).
2. You have a basic understanding of Kubernetes _[pods](/docs/user-guide/pods)_, _[services](/docs/user-guide/services)_, and _[replication controllers](/docs/user-guide/replication-controller)_.
The Namespace provides a unique scope for:
### Step One: Understand the default namespace
1. named resources (to avoid basic naming collisions)
2. delegated management authority to trusted users
3. ability to limit community resource consumption
By default, a Kubernetes cluster will instantiate a default namespace when provisioning the cluster to hold the default set of pods,
services, and replication controllers used by the cluster.
## Use cases
Assuming you have a fresh cluster, you can introspect the available namespace's by doing the following:
1. As a cluster operator, I want to support multiple user communities on a single cluster.
2. As a cluster operator, I want to delegate authority to partitions of the cluster to trusted users
in those communities.
3. As a cluster operator, I want to limit the amount of resources each community can consume in order
to limit the impact to other communities using the cluster.
4. As a cluster user, I want to interact with resources that are pertinent to my user community in
isolation of what other user communities are doing on the cluster.
## Viewing namespaces
You can list the current namespaces in a cluster using:
```shell
$ kubectl get namespaces
NAME LABELS
default <none>
NAME LABELS STATUS
default <none> Active
kube-system <none> Active
```
### Step Two: Create new namespaces
Kubernetes starts with two initial namespaces:
* `default` The default namespace for objects with no other namespace
* `kube-system` The namespace for objects created by the Kubernetes system
For this exercise, we will create two additional Kubernetes namespaces to hold our content.
Let's imagine a scenario where an organization is using a shared Kubernetes cluster for development and production use cases.
The development team would like to maintain a space in the cluster where they can get a view on the list of pods, services, and replication controllers
they use to build and run their application. In this space, Kubernetes resources come and go, and the restrictions on who can or cannot modify resources
are relaxed to enable agile development.
The operations team would like to maintain a space in the cluster where they can enforce strict procedures on who can or cannot manipulate the set of
pods, services, and replication controllers that run the production site.
One pattern this organization could follow is to partition the Kubernetes cluster into two namespaces: development and production.
Let's create two new namespaces to hold our work.
Use the file [`namespace-dev.json`](/docs/admin/namespaces/namespace-dev.json) which describes a development namespace:
{% include code.html language="json" file="namespace-dev.json" ghlink="/docs/admin/namespaces/namespace-dev.json" %}
Create the development namespace using kubectl.
You can also get the summary of a specific namespace using:
```shell
$ kubectl create -f docs/admin/namespaces/namespace-dev.json
$ kubectl get namespaces <name>
```
And then lets create the production namespace using kubectl.
Or you can get detailed information with:
```shell
$ kubectl create -f docs/admin/namespaces/namespace-prod.json
$ kubectl describe namespaces <name>
Name: default
Labels: <none>
Status: Active
No resource quota.
Resource Limits
Type Resource Min Max Default
---- -------- --- --- ---
Container cpu - - 100m
```
To be sure things are right, let's list all of the namespaces in our cluster.
Note that these details show both resource quota (if present) as well as resource limit ranges.
```shell
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
development name=development Active
production name=production Active
```
Resource quota tracks aggregate usage of resources in the *Namespace* and allows cluster operators
to define *Hard* resource usage limits that a *Namespace* may consume.
### Step Three: Create pods in each namespace
A limit range defines min/max constraints on the amount of resources a single entity can consume in
a *Namespace*.
A Kubernetes namespace provides the scope for pods, services, and replication controllers in the cluster.
See [Admission control: Limit Range](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/admission_control_limit_range.md)
Users interacting with one namespace do not see the content in another namespace.
A namespace can be in one of two phases:
* `Active` the namespace is in use
* `Terminating` the namespace is being deleted, and can not be used for new objects
To demonstrate this, let's spin up a simple replication controller and pod in the development namespace.
See the [design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#phases) for more details.
We first check what is the current context:
## Creating a new namespace
To create a new namespace, first create a new YAML file called `my-namespace.yaml` with the contents:
```yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://130.211.122.180
name: lithe-cocoa-92103_kubernetes
contexts:
- context:
cluster: lithe-cocoa-92103_kubernetes
user: lithe-cocoa-92103_kubernetes
name: lithe-cocoa-92103_kubernetes
current-context: lithe-cocoa-92103_kubernetes
kind: Config
preferences: {}
users:
- name: lithe-cocoa-92103_kubernetes
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
token: 65rZW78y8HbwXXtSXuUw9DbP4FLjHi4b
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
password: h5M0FtUUIflBSdI7
username: admin
kind: Namespace
metadata:
name: <insert-namespace-name-here>
```
The next step is to define a context for the kubectl client to work in each namespace. The value of "cluster" and "user" fields are copied from the current context.
Note that the name of your namespace must be a DNS compatible label.
More information on the `finalizers` field can be found in the namespace [design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#finalizers).
Then run:
```shell
$ kubectl config set-context dev --namespace=development --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
$ kubectl config set-context prod --namespace=production --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
$ kubectl create -f ./my-namespace.yaml
```
The above commands provided two request contexts you can alternate against depending on what namespace you
wish to work against.
## Working in namespaces
Let's switch to operate in the development namespace.
See [Setting the namespace for a request](/docs/user-guide/namespaces/#setting-the-namespace-for-a-request)
and [Setting the namespace preference](/docs/user-guide/namespaces/#setting-the-namespace-preference).
## Deleting a namespace
You can delete a namespace with
```shell
$ kubectl config use-context dev
$ kubectl delete namespaces <insert-some-namespace-name>
```
You can verify your current context by doing the following:
**WARNING, this deletes _everything_ under the namespace!**
```shell
$ kubectl config view
```
This delete is asynchronous, so for a time you will see the namespace in the `Terminating` state.
```yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://130.211.122.180
name: lithe-cocoa-92103_kubernetes
contexts:
- context:
cluster: lithe-cocoa-92103_kubernetes
namespace: development
user: lithe-cocoa-92103_kubernetes
name: dev
- context:
cluster: lithe-cocoa-92103_kubernetes
user: lithe-cocoa-92103_kubernetes
name: lithe-cocoa-92103_kubernetes
- context:
cluster: lithe-cocoa-92103_kubernetes
namespace: production
user: lithe-cocoa-92103_kubernetes
name: prod
current-context: dev
kind: Config
preferences: {}
users:
- name: lithe-cocoa-92103_kubernetes
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
token: 65rZW78y8HbwXXtSXuUw9DbP4FLjHi4b
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
password: h5M0FtUUIflBSdI7
username: admin
```
## Namespaces and DNS
At this point, all requests we make to the Kubernetes cluster from the command line are scoped to the development namespace.
When you create a [Service](/docs/user-guide/services), it creates a corresponding [DNS entry](/docs/admin/dns).
This entry is of the form `<service-name>.<namespace-name>.svc.cluster.local`, which means
that if a container just uses `<service-name>` it will resolve to the service which
is local to a namespace. This is useful for using the same configuration across
multiple namespaces such as Development, Staging and Production. If you want to reach
across namespaces, you need to use the fully qualified domain name (FQDN).
Let's create some content.
## Design
```shell
$ kubectl run snowflake --image=kubernetes/serve_hostname --replicas=2
```
We have just created a replication controller whose replica size is 2 that is running the pod called snowflake with a basic container that just serves the hostname.
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
snowflake snowflake kubernetes/serve_hostname run=snowflake 2
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
snowflake-8w0qn 1/1 Running 0 22s
snowflake-jrpzb 1/1 Running 0 22s
```
And this is great, developers are able to do what they want, and they do not have to worry about affecting content in the production namespace.
Let's switch to the production namespace and show how resources in one namespace are hidden from the other.
```shell
$ kubectl config use-context prod
```
The production namespace should be empty.
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
```
Production likes to run cattle, so let's create some cattle pods.
```shell
$ kubectl run cattle --image=kubernetes/serve_hostname --replicas=5
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
cattle cattle kubernetes/serve_hostname run=cattle 5
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cattle-97rva 1/1 Running 0 12s
cattle-i9ojn 1/1 Running 0 12s
cattle-qj3yv 1/1 Running 0 12s
cattle-yc7vn 1/1 Running 0 12s
cattle-zz7ea 1/1 Running 0 12s
```
At this point, it should be clear that the resources users create in one namespace are hidden from the other namespace.
As the policy support in Kubernetes evolves, we will extend this scenario to show how you can provide different
authorization rules for each namespace.
Details of the design of namespaces in Kubernetes, including a [detailed example](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md#example-openshift-origin-managing-a-kubernetes-namespace)
can be found in the [namespaces design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md)

View File

@ -0,0 +1,200 @@
---
---
Kubernetes _namespaces_ help different projects, teams, or customers to share a Kubernetes cluster.
It does this by providing the following:
1. A scope for [Names](/docs/user-guide/identifiers/).
2. A mechanism to attach authorization and policy to a subsection of the cluster.
Use of multiple namespaces is optional.
This example demonstrates how to use Kubernetes namespaces to subdivide your cluster.
### Step Zero: Prerequisites
This example assumes the following:
1. You have an [existing Kubernetes cluster](/docs/getting-started-guides/).
2. You have a basic understanding of Kubernetes _[Pods](/docs/user-guide/pods/)_, _[Services](/docs/user-guide/services/)_, and _[Deployments](/docs/user-guide/deployments/)_.
### Step One: Understand the default namespace
By default, a Kubernetes cluster will instantiate a default namespace when provisioning the cluster to hold the default set of Pods,
Services, and Deployments used by the cluster.
Assuming you have a fresh cluster, you can introspect the available namespace's by doing the following:
```shell
$ kubectl get namespaces
NAME STATUS AGE
default Active 13m
```
### Step Two: Create new namespaces
For this exercise, we will create two additional Kubernetes namespaces to hold our content.
Let's imagine a scenario where an organization is using a shared Kubernetes cluster for development and production use cases.
The development team would like to maintain a space in the cluster where they can get a view on the list of Pods, Services, and Deployments
they use to build and run their application. In this space, Kubernetes resources come and go, and the restrictions on who can or cannot modify resources
are relaxed to enable agile development.
The operations team would like to maintain a space in the cluster where they can enforce strict procedures on who can or cannot manipulate the set of
Pods, Services, and Deployments that run the production site.
One pattern this organization could follow is to partition the Kubernetes cluster into two namespaces: development and production.
Let's create two new namespaces to hold our work.
Use the file [`namespace-dev.json`](/docs/admin/namespaces/namespace-dev.json) which describes a development namespace:
{% include code.html language="json" file="namespace-dev.json" ghlink="/docs/admin/namespaces/namespace-dev.json" %}
Create the development namespace using kubectl.
```shell
$ kubectl create -f docs/admin/namespaces/namespace-dev.json
```
And then lets create the production namespace using kubectl.
```shell
$ kubectl create -f docs/admin/namespaces/namespace-prod.json
```
To be sure things are right, let's list all of the namespaces in our cluster.
```shell
$ kubectl get namespaces --show-labels
NAME STATUS AGE LABELS
default Active 32m <none>
development Active 29s name=development
production Active 23s name=production
```
### Step Three: Create pods in each namespace
A Kubernetes namespace provides the scope for Pods, Services, and Deployments in the cluster.
Users interacting with one namespace do not see the content in another namespace.
To demonstrate this, let's spin up a simple Deployment and Pods in the development namespace.
We first check what is the current context:
```shell
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://130.211.122.180
name: lithe-cocoa-92103_kubernetes
contexts:
- context:
cluster: lithe-cocoa-92103_kubernetes
user: lithe-cocoa-92103_kubernetes
name: lithe-cocoa-92103_kubernetes
current-context: lithe-cocoa-92103_kubernetes
kind: Config
preferences: {}
users:
- name: lithe-cocoa-92103_kubernetes
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
token: 65rZW78y8HbwXXtSXuUw9DbP4FLjHi4b
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
password: h5M0FtUUIflBSdI7
username: admin
$ kubectl config current-context
lithe-cocoa-92103_kubernetes
```
The next step is to define a context for the kubectl client to work in each namespace. The value of "cluster" and "user" fields are copied from the current context.
```shell
$ kubectl config set-context dev --namespace=development --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
$ kubectl config set-context prod --namespace=production --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
```
The above commands provided two request contexts you can alternate against depending on what namespace you
wish to work against.
Let's switch to operate in the development namespace.
```shell
$ kubectl config use-context dev
```
You can verify your current context by doing the following:
```shell
$ kubectl config current-context
dev
```
At this point, all requests we make to the Kubernetes cluster from the command line are scoped to the development namespace.
Let's create some content.
```shell
$ kubectl run snowflake --image=kubernetes/serve_hostname --replicas=2
```
We have just created a deployment whose replica size is 2 that is running the pod called snowflake with a basic container that just serves the hostname.
Note that `kubectl run` creates deployments only on kubernetes cluster >= v1.2. If you are running older versions, it creates replication controllers instead.
If you want to obtain the old behavior, use `--generator=run/v1` to create replication controllers. See [`kubectl run`](/docs/user-guide/kubectl/kubectl_run/) for more details.
```shell
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
snowflake 2 2 2 2 2m
$ kubectl get pods -l run=snowflake
NAME READY STATUS RESTARTS AGE
snowflake-3968820950-9dgr8 1/1 Running 0 2m
snowflake-3968820950-vgc4n 1/1 Running 0 2m
```
And this is great, developers are able to do what they want, and they do not have to worry about affecting content in the production namespace.
Let's switch to the production namespace and show how resources in one namespace are hidden from the other.
```shell
$ kubectl config use-context prod
```
The production namespace should be empty, and the following commands should return nothing.
```shell
$ kubectl get deployment
$ kubectl get pods
```
Production likes to run cattle, so let's create some cattle pods.
```shell
$ kubectl run cattle --image=kubernetes/serve_hostname --replicas=5
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
cattle 5 5 5 5 10s
kubectl get pods -l run=cattle
NAME READY STATUS RESTARTS AGE
cattle-2263376956-41xy6 1/1 Running 0 34s
cattle-2263376956-kw466 1/1 Running 0 34s
cattle-2263376956-n4v97 1/1 Running 0 34s
cattle-2263376956-p5p3i 1/1 Running 0 34s
cattle-2263376956-sxpth 1/1 Running 0 34s
```
At this point, it should be clear that the resources users create in one namespace are hidden from the other namespace.
As the policy support in Kubernetes evolves, we will extend this scenario to show how you can provide different
authorization rules for each namespace.

View File

@ -154,6 +154,15 @@ Follow the "With Linux Bridge devices" section of [this very nice
tutorial](http://blog.oddbit.com/2014/08/11/four-ways-to-connect-a-docker/) from
Lars Kellogg-Stedman.
### Weave Net from Weaveworks
[Weave Net](https://www.weave.works/documentation/net-1-5-0-introducing-weave/) is a
resilient and simple to use network for Kubernetes and its hosted applications.
Weave Net runs as a [CNI plug-in](https://www.weave.works/documentation/net-1-5-0-cni-plugin/)
or stand-alone. In either version, it doesnt require any configuration or extra code
to run, and in both cases, the network provides one IP address per pod - as is standard for Kubernetes.
### Flannel
[Flannel](https://github.com/coreos/flannel#flannel) is a very simple overlay
@ -167,10 +176,6 @@ people have reported success with Flannel and Kubernetes.
complicated way to build an overlay network. This is endorsed by several of the
"Big Shops" for networking.
### Weave
[Weave](https://github.com/zettio/weave) is yet another way to build an overlay
network, primarily aiming at Docker integration.
### Calico
@ -179,7 +184,11 @@ IPs.
### Romana
[Romana](https://romana.io) is an open source software defined networking (SDN) solution that lets you deploy Kubernetes without an overlay network.
[Romana](http://romana.io) is an open source software defined networking (SDN) solution that lets you deploy Kubernetes without an overlay network.
### Contiv
[Contiv](https://github.com/contiv/netplugin) provides configurable networking (native l3 using BGP, overlay using vxlan, classic l2, or Cisco-SDN/ACI) for various use cases. [Contiv](http://contiv.io) is all open sourced.
## Other reading

View File

@ -1,154 +0,0 @@
---
---
When several users or teams share a cluster with a fixed number of nodes,
there is a concern that one team could use more than its fair share of resources.
Resource quotas are a tool for administrators to address this concern. Resource quotas
work like this:
- Different teams work in different namespaces. Currently this is voluntary, but
support for making this mandatory via ACLs is planned.
- The administrator creates a Resource Quota for each namespace.
- Users put compute resource requests on their pods. The sum of all resource requests across
all pods in the same namespace must not exceed any hard resource limit in any Resource Quota
document for the namespace. Note that we used to verify Resource Quota by taking the sum of
resource limits of the pods, but this was altered to use resource requests. Backwards compatibility
for those pods previously created is preserved because pods that only specify a resource limit have
their resource requests defaulted to match their defined limits. The user is only charged for the
resources they request in the Resource Quota versus their limits because the request is the minimum
amount of resource guaranteed by the cluster during scheduling. For more information on over commit,
see [compute-resources](/docs/user-guide/compute-resources).
- If creating a pod would cause the namespace to exceed any of the limits specified in the
the Resource Quota for that namespace, then the request will fail with HTTP status
code `403 FORBIDDEN`.
- If quota is enabled in a namespace and the user does not specify *requests* on the pod for each
of the resources for which quota is enabled, then the POST of the pod will fail with HTTP
status code `403 FORBIDDEN`. Hint: Use the LimitRange admission controller to force default
values of *limits* (then resource *requests* would be equal to *limits* by default, see
[admission controller](/docs/admin/admission-controllers)) before the quota is checked to avoid this problem.
Examples of policies that could be created using namespaces and quotas are:
- In a cluster with a capacity of 32 GiB RAM, and 16 cores, let team A use 20 Gib and 10 cores,
let B use 10GiB and 4 cores, and hold 2GiB and 2 cores in reserve for future allocation.
- Limit the "testing" namespace to using 1 core and 1GiB RAM. Let the "production" namespace
use any amount.
In the case where the total capacity of the cluster is less than the sum of the quotas of the namespaces,
there may be contention for resources. This is handled on a first-come-first-served basis.
Neither contention nor changes to quota will affect already-running pods.
## Enabling Resource Quota
Resource Quota support is enabled by default for many Kubernetes distributions. It is
enabled when the apiserver `--admission-control=` flag has `ResourceQuota` as
one of its arguments.
Resource Quota is enforced in a particular namespace when there is a
`ResourceQuota` object in that namespace. There should be at most one
`ResourceQuota` object in a namespace.
## Compute Resource Quota
The total sum of [compute resources](/docs/user-guide/compute-resources) requested by pods
in a namespace can be limited. The following compute resource types are supported:
| ResourceName | Description |
| ------------ | ----------- |
| cpu | Total cpu requests of containers |
| memory | Total memory requests of containers
For example, `cpu` quota sums up the `resources.requests.cpu` fields of every
container of every pod in the namespace, and enforces a maximum on that sum.
## Object Count Quota
The number of objects of a given type can be restricted. The following types
are supported:
| ResourceName | Description |
| ------------ | ----------- |
| pods | Total number of pods |
| services | Total number of services |
| replicationcontrollers | Total number of replication controllers |
| resourcequotas | Total number of [resource quotas](/docs/admin/admission-controllers/#resourcequota) |
| secrets | Total number of secrets |
| persistentvolumeclaims | Total number of [persistent volume claims](/docs/user-guide/persistent-volumes/#persistentvolumeclaims) |
For example, `pods` quota counts and enforces a maximum on the number of `pods`
created in a single namespace.
You might want to set a pods quota on a namespace
to avoid the case where a user creates many small pods and exhausts the cluster's
supply of Pod IPs.
## Viewing and Setting Quotas
Kubectl supports creating, updating, and viewing quotas:
```shell
$ kubectl namespace myspace
$ cat <<EOF > quota.json
{
"apiVersion": "v1",
"kind": "ResourceQuota",
"metadata": {
"name": "quota"
},
"spec": {
"hard": {
"memory": "1Gi",
"cpu": "20",
"pods": "10",
"services": "5",
"replicationcontrollers":"20",
"resourcequotas":"1"
}
}
}
EOF
$ kubectl create -f ./quota.json
$ kubectl get quota
NAME
quota
$ kubectl describe quota quota
Name: quota
Resource Used Hard
-------- ---- ----
cpu 0m 20
memory 0 1Gi
pods 5 10
replicationcontrollers 5 20
resourcequotas 1 1
services 3 5
```
## Quota and Cluster Capacity
Resource Quota objects are independent of the Cluster Capacity. They are
expressed in absolute units. So, if you add nodes to your cluster, this does *not*
automatically give each namespace the ability to consume more resources.
Sometimes more complex policies may be desired, such as:
- proportionally divide total cluster resources among several teams.
- allow each tenant to grow resource usage as needed, but have a generous
limit to prevent accidental resource exhaustion.
- detect demand from one namespace, add nodes, and increase quota.
Such policies could be implemented using ResourceQuota as a building-block, by
writing a 'controller' which watches the quota usage and adjusts the quota
hard limits of each namespace according to other signals.
Note that resource quota divides up aggregate cluster resources, but it creates no
restrictions around nodes: pods from several namespaces may run on the same node.
## Example
See a [detailed example for how to use resource quota](/docs/admin/resourcequota/).
## Read More
See [ResourceQuota design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/admission_control_resource_quota.md) for more information.

View File

@ -1,156 +1,154 @@
---
---
This example demonstrates how [resource quota](/docs/admin/admission-controllers/#resourcequota) and
[limitsranger](/docs/admin/admission-controllers/#limitranger) can be applied to a Kubernetes namespace.
When several users or teams share a cluster with a fixed number of nodes,
there is a concern that one team could use more than its fair share of resources.
Resource quotas are a tool for administrators to address this concern. Resource quotas
work like this:
- Different teams work in different namespaces. Currently this is voluntary, but
support for making this mandatory via ACLs is planned.
- The administrator creates a Resource Quota for each namespace.
- Users put compute resource requests on their pods. The sum of all resource requests across
all pods in the same namespace must not exceed any hard resource limit in any Resource Quota
document for the namespace. Note that we used to verify Resource Quota by taking the sum of
resource limits of the pods, but this was altered to use resource requests. Backwards compatibility
for those pods previously created is preserved because pods that only specify a resource limit have
their resource requests defaulted to match their defined limits. The user is only charged for the
resources they request in the Resource Quota versus their limits because the request is the minimum
amount of resource guaranteed by the cluster during scheduling. For more information on over commit,
see [compute-resources](/docs/user-guide/compute-resources).
- If creating a pod would cause the namespace to exceed any of the limits specified in the
the Resource Quota for that namespace, then the request will fail with HTTP status
code `403 FORBIDDEN`.
- If quota is enabled in a namespace and the user does not specify *requests* on the pod for each
of the resources for which quota is enabled, then the POST of the pod will fail with HTTP
status code `403 FORBIDDEN`. Hint: Use the LimitRange admission controller to force default
values of *limits* (then resource *requests* would be equal to *limits* by default, see
[admission controller](/docs/admin/admission-controllers)) before the quota is checked to avoid this problem.
Examples of policies that could be created using namespaces and quotas are:
- In a cluster with a capacity of 32 GiB RAM, and 16 cores, let team A use 20 Gib and 10 cores,
let B use 10GiB and 4 cores, and hold 2GiB and 2 cores in reserve for future allocation.
- Limit the "testing" namespace to using 1 core and 1GiB RAM. Let the "production" namespace
use any amount.
In the case where the total capacity of the cluster is less than the sum of the quotas of the namespaces,
there may be contention for resources. This is handled on a first-come-first-served basis.
Neither contention nor changes to quota will affect already-running pods.
## Enabling Resource Quota
Resource Quota support is enabled by default for many Kubernetes distributions. It is
enabled when the apiserver `--admission-control=` flag has `ResourceQuota` as
one of its arguments.
Resource Quota is enforced in a particular namespace when there is a
`ResourceQuota` object in that namespace. There should be at most one
`ResourceQuota` object in a namespace.
## Compute Resource Quota
The total sum of [compute resources](/docs/user-guide/compute-resources) requested by pods
in a namespace can be limited. The following compute resource types are supported:
| ResourceName | Description |
| ------------ | ----------- |
| cpu | Total cpu requests of containers |
| memory | Total memory requests of containers
For example, `cpu` quota sums up the `resources.requests.cpu` fields of every
container of every pod in the namespace, and enforces a maximum on that sum.
## Object Count Quota
The number of objects of a given type can be restricted. The following types
are supported:
| ResourceName | Description |
| ------------ | ----------- |
| pods | Total number of pods |
| services | Total number of services |
| replicationcontrollers | Total number of replication controllers |
| resourcequotas | Total number of [resource quotas](/docs/admin/admission-controllers/#resourcequota) |
| secrets | Total number of secrets |
| persistentvolumeclaims | Total number of [persistent volume claims](/docs/user-guide/persistent-volumes/#persistentvolumeclaims) |
For example, `pods` quota counts and enforces a maximum on the number of `pods`
created in a single namespace.
You might want to set a pods quota on a namespace
to avoid the case where a user creates many small pods and exhausts the cluster's
supply of Pod IPs.
## Viewing and Setting Quotas
Kubectl supports creating, updating, and viewing quotas:
```shell
$ kubectl namespace myspace
$ cat <<EOF > quota.json
{
"apiVersion": "v1",
"kind": "ResourceQuota",
"metadata": {
"name": "quota"
},
"spec": {
"hard": {
"memory": "1Gi",
"cpu": "20",
"pods": "10",
"services": "5",
"replicationcontrollers":"20",
"resourcequotas":"1"
}
}
}
EOF
$ kubectl create -f ./quota.json
$ kubectl get quota
NAME
quota
$ kubectl describe quota quota
Name: quota
Resource Used Hard
-------- ---- ----
cpu 0m 20
memory 0 1Gi
pods 5 10
replicationcontrollers 5 20
resourcequotas 1 1
services 3 5
```
## Quota and Cluster Capacity
Resource Quota objects are independent of the Cluster Capacity. They are
expressed in absolute units. So, if you add nodes to your cluster, this does *not*
automatically give each namespace the ability to consume more resources.
Sometimes more complex policies may be desired, such as:
- proportionally divide total cluster resources among several teams.
- allow each tenant to grow resource usage as needed, but have a generous
limit to prevent accidental resource exhaustion.
- detect demand from one namespace, add nodes, and increase quota.
Such policies could be implemented using ResourceQuota as a building-block, by
writing a 'controller' which watches the quota usage and adjusts the quota
hard limits of each namespace according to other signals.
Note that resource quota divides up aggregate cluster resources, but it creates no
restrictions around nodes: pods from several namespaces may run on the same node.
## Example
See a [detailed example for how to use resource quota](/docs/admin/resourcequota/walkthrough/).
## Read More
See [ResourceQuota design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/admission_control_resource_quota.md) for more information.
This example assumes you have a functional Kubernetes setup.
## Step 1: Create a namespace
This example will work in a custom namespace to demonstrate the concepts involved.
Let's create a new namespace called quota-example:
```shell
$ kubectl create -f docs/admin/resourcequota/namespace.yaml
namespace "quota-example" created
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 2m
quota-example <none> Active 39s
```
## Step 2: Apply a quota to the namespace
By default, a pod will run with unbounded CPU and memory requests/limits. This means that any pod in the
system will be able to consume as much CPU and memory on the node that executes the pod.
Users may want to restrict how much of the cluster resources a given namespace may consume
across all of its pods in order to manage cluster usage. To do this, a user applies a quota to
a namespace. A quota lets the user set hard limits on the total amount of node resources (cpu, memory)
and API resources (pods, services, etc.) that a namespace may consume. In term of resources, Kubernetes
checks the total resource *requests*, not resource *limits* of all containers/pods in the namespace.
Let's create a simple quota in our namespace:
```shell
$ kubectl create -f docs/admin/resourcequota/quota.yaml --namespace=quota-example
resourcequota "quota" created
```
Once your quota is applied to a namespace, the system will restrict any creation of content
in the namespace until the quota usage has been calculated. This should happen quickly.
You can describe your current quota usage to see what resources are being consumed in your
namespace.
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
Resource Used Hard
-------- ---- ----
cpu 0 20
memory 0 1Gi
persistentvolumeclaims 0 10
pods 0 10
replicationcontrollers 0 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
## Step 3: Applying default resource requests and limits
Pod authors rarely specify resource requests and limits for their pods.
Since we applied a quota to our project, let's see what happens when an end-user creates a pod that has unbounded
cpu and memory by creating an nginx container.
To demonstrate, lets create a replication controller that runs nginx:
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
replicationcontroller "nginx" created
```
Now let's look at the pods that were created.
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
```
What happened? I have no pods! Let's describe the replication controller to get a view of what is happening.
```shell
kubectl describe rc nginx --namespace=quota-example
Name: nginx
Namespace: quota-example
Image(s): nginx
Selector: run=nginx
Labels: run=nginx
Replicas: 0 current / 1 desired
Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
42s 11s 3 {replication-controller } FailedCreate Error creating: Pod "nginx-" is forbidden: Must make a non-zero request for memory since it is tracked by quota.
```
The Kubernetes API server is rejecting the replication controllers requests to create a pod because our pods
do not specify any memory usage *request*.
So let's set some default values for the amount of cpu and memory a pod can consume:
```shell
$ kubectl create -f docs/admin/resourcequota/limits.yaml --namespace=quota-example
limitrange "limits" created
$ kubectl describe limits limits --namespace=quota-example
Name: limits
Namespace: quota-example
Type Resource Min Max Request Limit Limit/Request
---- -------- --- --- ------- ----- -------------
Container memory - - 256Mi 512Mi -
Container cpu - - 100m 200m -
```
Now any time a pod is created in this namespace, if it has not specified any resource request/limit, the default
amount of cpu and memory per container will be applied, and the request will be used as part of admission control.
Now that we have applied default resource *request* for our namespace, our replication controller should be able to
create its pods.
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-fca65 1/1 Running 0 1m
```
And if we print out our quota usage in the namespace:
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
Resource Used Hard
-------- ---- ----
cpu 100m 20
memory 256Mi 1Gi
persistentvolumeclaims 0 10
pods 1 10
replicationcontrollers 1 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
You can now see the pod that was created is consuming explicit amounts of resources (specified by resource *request*), and the usage is being tracked by the Kubernetes system properly.
## Summary
Actions that consume node resources for cpu and memory can be subject to hard quota limits defined by the namespace quota. The resource consumption is measured by resource *request* in pod specification.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to meet your end goal.

View File

@ -0,0 +1,164 @@
---
---
This example demonstrates how [resource quota](/docs/admin/admission-controllers/#resourcequota) and
[limitsranger](/docs/admin/admission-controllers/#limitranger) can be applied to a Kubernetes namespace.
See [ResourceQuota design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/admission_control_resource_quota.md) for more information.
This example assumes you have a functional Kubernetes setup.
## Step 1: Create a namespace
This example will work in a custom namespace to demonstrate the concepts involved.
Let's create a new namespace called quota-example:
```shell
$ kubectl create namespace quota-example
namespace "quota-example" created
```
Note that `kubectl` commands will print the type and name of the resource created or mutated, which can then be used in subsequent commands:
```shell
$ kubectl get namespaces
NAME STATUS AGE
default Active 50m
quota-example Active 2s
```
## Step 2: Apply a quota to the namespace
By default, a pod will run with unbounded CPU and memory requests/limits. This means that any pod in the
system will be able to consume as much CPU and memory on the node that executes the pod.
Users may want to restrict how much of the cluster resources a given namespace may consume
across all of its pods in order to manage cluster usage. To do this, a user applies a quota to
a namespace. A quota lets the user set hard limits on the total amount of node resources (cpu, memory)
and API resources (pods, services, etc.) that a namespace may consume. In term of resources, Kubernetes
checks the total resource *requests*, not resource *limits* of all containers/pods in the namespace.
Let's create a simple quota in our namespace:
```shell
$ kubectl create -f docs/admin/resourcequota/quota.yaml --namespace=quota-example
resourcequota "quota" created
```
Once your quota is applied to a namespace, the system will restrict any creation of content
in the namespace until the quota usage has been calculated. This should happen quickly.
You can describe your current quota usage to see what resources are being consumed in your
namespace.
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
Resource Used Hard
-------- ---- ----
cpu 0 20
memory 0 1Gi
persistentvolumeclaims 0 10
pods 0 10
replicationcontrollers 0 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
## Step 3: Applying default resource requests and limits
Pod authors rarely specify resource requests and limits for their pods.
Since we applied a quota to our project, let's see what happens when an end-user creates a pod that has unbounded
cpu and memory by creating an nginx container.
To demonstrate, lets create a Deployment that runs nginx:
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
deployment "nginx" created
```
This creates a Deployment "nginx" with its underlying resource, a ReplicaSet, which handles the creation and deletion of Pod replicas. Now let's look at the pods that were created.
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
```
What happened? I have no pods! Let's describe the ReplicaSet managed by the nginx Deployment to get a view of what is happening.
Note that `kubectl describe rs` works only on kubernetes cluster >= v1.2. If you are running older versions, use `kubectl describe rc` instead.
If you want to obtain the old behavior, use `--generator=run/v1` to create replication controllers. See [`kubectl run`](/docs/user-guide/kubectl/kubectl_run/) for more details.
```shell
$ kubectl describe rs -l run=nginx --namespace=quota-example
Name: nginx-2040093540
Namespace: quota-example
Image(s): nginx
Selector: pod-template-hash=2040093540,run=nginx
Labels: pod-template-hash=2040093540,run=nginx
Replicas: 0 current / 1 desired
Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
48s 26s 4 {replicaset-controller } Warning FailedCreate Error creating: pods "nginx-2040093540-" is forbidden: Failed quota: quota: must specify cpu,memory
```
The Kubernetes API server is rejecting the ReplicaSet requests to create a pod because our pods
do not specify any memory usage *request*.
So let's set some default values for the amount of cpu and memory a pod can consume:
```shell
$ kubectl create -f docs/admin/resourcequota/limits.yaml --namespace=quota-example
limitrange "limits" created
$ kubectl describe limits limits --namespace=quota-example
Name: limits
Namespace: quota-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu - - 100m 200m -
Container memory - - 256Mi 512Mi -
```
Now any time a pod is created in this namespace, if it has not specified any resource request/limit, the default
amount of cpu and memory per container will be applied, and the request will be used as part of admission control.
Now that we have applied default resource *request* for our namespace, our Deployment should be able to
create its pods.
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-2040093540-miohp 1/1 Running 0 5s
```
And if we print out our quota usage in the namespace:
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
Resource Used Hard
-------- ---- ----
cpu 100m 20
memory 256Mi 1Gi
persistentvolumeclaims 0 10
pods 1 10
replicationcontrollers 1 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
You can now see the pod that was created is consuming explicit amounts of resources (specified by resource *request*), and the usage is being tracked by the Kubernetes system properly.
## Summary
Actions that consume node resources for cpu and memory can be subject to hard quota limits defined by the namespace quota. The resource consumption is measured by resource *request* in pod specification.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to meet your end goal.

View File

@ -184,7 +184,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscalerlist">v1.HorizontalPodAutoscalerList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscalerlist">v1.HorizontalPodAutoscalerList</a></p></td>
</tr>
</tbody>
</table>
@ -332,7 +332,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscalerlist">v1.HorizontalPodAutoscalerList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscalerlist">v1.HorizontalPodAutoscalerList</a></p></td>
</tr>
</tbody>
</table>
@ -480,7 +480,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -562,7 +562,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -596,7 +596,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -728,7 +728,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -810,7 +810,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -852,7 +852,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -934,7 +934,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -976,7 +976,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -1058,7 +1058,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1100,7 +1100,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -1188,7 +1188,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1230,7 +1230,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_horizontalpodautoscaler">v1.HorizontalPodAutoscaler</a></p></td>
</tr>
</tbody>
</table>
@ -1370,7 +1370,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -1515,7 +1515,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -1668,7 +1668,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>

View File

@ -184,7 +184,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_joblist">v1.JobList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_joblist">v1.JobList</a></p></td>
</tr>
</tbody>
</table>
@ -332,7 +332,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_joblist">v1.JobList</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_joblist">v1.JobList</a></p></td>
</tr>
</tbody>
</table>
@ -480,7 +480,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -562,7 +562,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -596,7 +596,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -728,7 +728,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -810,7 +810,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -852,7 +852,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -934,7 +934,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_deleteoptions">v1.DeleteOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -976,7 +976,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_status">unversioned.Status</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_status">unversioned.Status</a></p></td>
</tr>
</tbody>
</table>
@ -1058,7 +1058,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_unversioned_patch">unversioned.Patch</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1100,7 +1100,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -1188,7 +1188,7 @@
<td class="tableblock halign-left valign-top"><p class="tableblock">body</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
@ -1230,7 +1230,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_v1_job">v1.Job</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_v1_job">v1.Job</a></p></td>
</tr>
</tbody>
</table>
@ -1370,7 +1370,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -1515,7 +1515,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -1668,7 +1668,7 @@
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">200</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">success</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="definitions.html#_json_watchevent">json.WatchEvent</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../definitions#_json_watchevent">json.WatchEvent</a></p></td>
</tr>
</tbody>
</table>
@ -1714,4 +1714,4 @@ Last updated 2016-03-14 21:55:47 UTC
</div>
</div>
</body>
</html>
</html>

View File

@ -5,8 +5,6 @@ Primary system and API concepts are documented in the [User guide](/docs/user-gu
Overall API conventions are described in the [API conventions doc](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/devel/api-conventions.md).
Complete API details are documented via [Swagger](http://swagger.io/). The Kubernetes apiserver (aka "master") exports an API that can be used to retrieve the [Swagger spec](https://github.com/swagger-api/swagger-spec/tree/master/schemas/v1.2) for the Kubernetes API, by default at `/swaggerapi`, and a UI you can use to browse the API documentation at `/swagger-ui`. We also periodically update a [statically generated UI](http://kubernetes.io/third_party/swagger-ui/).
Remote access to the API is discussed in the [access doc](/docs/admin/accessing-the-api).
The Kubernetes API also serves as the foundation for the declarative configuration schema for the system. The [Kubectl](/docs/user-guide/kubectl/kubectl) command-line tool can be used to create, update, delete, and get API objects.
@ -21,6 +19,12 @@ In our experience, any system that is successful needs to grow and change as new
What constitutes a compatible change and how to change the API are detailed by the [API change document](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/devel/api_changes.md).
## API Swagger definitions
Complete API details are documented using [Swagger v1.2](http://swagger.io/). The Kubernetes apiserver (aka "master") exposes an API that can be used to retrieve the Swagger Kubernetes API spec, by default at located at `/swaggerapi`, and a UI to browse the API documentation at `/swagger-ui`.
We also host a version of the [latest API documentation UI](http://kubernetes.io/kubernetes/third_party/swagger-ui/). This is updated with the latest release, so if you are using a different version of Kubernetes you will want to use the spec from your apiserver.
## API versioning
To make it easier to eliminate fields or restructure resource representations, Kubernetes supports

View File

@ -0,0 +1,334 @@
---
---
* TOC
{: toc}
These scripts handle the creation, deletion and expansion of kubernetes clusters on CenturyLink Cloud.
You can accomplish all these tasks with a single command. We have made the Ansible playbooks used to perform these tasks available [here](https://github.com/CenturyLinkCloud/adm-kubernetes-on-clc/blob/master/ansible/README.md).
## Find Help
If you run into any problems or want help with anything, we are here to help. Reach out to use via any of the following ways:
- Submit a github issue
- Send an email to kubernetes AT ctl DOT io
- Visit http://info.ctl.io/kubernetes
## Clusters of VMs or Physical Servers, your choice.
- We support Kubernetes clusters on both Virtual Machines or Physical Servers. If you want to use physical servers for the worker nodes (minions), simple use the --minion_type=bareMetal flag.
- For more information on physical servers, visit: [https://www.ctl.io/bare-metal/](https://www.ctl.io/bare-metal/))
- Physical serves are only available in the VA1 and GB3 data centers.
- VMs are available in all 13 of our public cloud locations
## Requirements
The requirements to run this script are:
- A linux administrative host (tested on ubuntu and OSX)
- python 2 (tested on 2.7.11)
- pip (installed with python as of 2.7.9)
- git
- A CenturyLink Cloud account with rights to create new hosts
- An active VPN connection to the CenturyLink Cloud from your linux host
## Script Installation
After you have all the requirements met, please follow these instructions to install this script.
1) Clone this repository and cd into it.
```shell
git clone https://github.com/CenturyLinkCloud/adm-kubernetes-on-clc
```
2) Install all requirements, including
* Ansible
* CenturyLink Cloud SDK
* Ansible Modules
```shell
sudo pip install -r ansible/requirements.txt
```
3) Create the credentials file from the template and use it to set your ENV variables
```shell
cp ansible/credentials.sh.template ansible/credentials.sh
vi ansible/credentials.sh
source ansible/credentials.sh
```
4) Grant your machine access to the CenturyLink Cloud network by using a VM inside the network or [ configuring a VPN connection to the CenturyLink Cloud network.](https://www.ctl.io/knowledge-base/network/how-to-configure-client-vpn/)
#### Script Installation Example: Ubuntu 14 Walkthrough
If you use an ubuntu 14, for your convenience we have provided a step by step
guide to install the requirements and install the script.
```shell
# system
apt-get update
apt-get install -y git python python-crypto
curl -O https://bootstrap.pypa.io/get-pip.py
python get-pip.py
# installing this repository
mkdir -p ~home/k8s-on-clc
cd ~home/k8s-on-clc
git clone https://github.com/CenturyLinkCloud/adm-kubernetes-on-clc.git
cd adm-kubernetes-on-clc/
pip install -r requirements.txt
# getting started
cd ansible
cp credentials.sh.template credentials.sh; vi credentials.sh
source credentials.sh
```
## Cluster Creation
To create a new Kubernetes cluster, simply run the kube-up.sh script. A complete
list of script options and some examples are listed below.
```shell
CLC_CLUSTER_NAME=[name of kubernetes cluster]
cd ./adm-kubernetes-on-clc
bash kube-up.sh -c="$CLC_CLUSTER_NAME"
```
It takes about 15 minutes to create the cluster. Once the script completes, it
will output some commands that will help you setup kubectl on your machine to
point to the new cluster.
When the cluster creation is complete, the configuration files for it are stored
locally on your administrative host, in the following directory
```shell
> CLC_CLUSTER_HOME=$HOME/.clc_kube/$CLC_CLUSTER_NAME/
```
#### Cluster Creation: Script Options
```shell
Usage: kube-up.sh [OPTIONS]
Create servers in the CenturyLinkCloud environment and initialize a Kubernetes cluster
Environment variables CLC_V2_API_USERNAME and CLC_V2_API_PASSWD must be set in
order to access the CenturyLinkCloud API
All options (both short and long form) require arguments, and must include "="
between option name and option value.
-h (--help) display this help and exit
-c= (--clc_cluster_name=) set the name of the cluster, as used in CLC group names
-t= (--minion_type=) standard -> VM (default), bareMetal -> physical]
-d= (--datacenter=) VA1 (default)
-m= (--minion_count=) number of kubernetes minion nodes
-mem= (--vm_memory=) number of GB ram for each minion
-cpu= (--vm_cpu=) number of virtual cps for each minion node
-phyid= (--server_conf_id=) physical server configuration id, one of
physical_server_20_core_conf_id
physical_server_12_core_conf_id
physical_server_4_core_conf_id (default)
-etcd_separate_cluster=yes create a separate cluster of three etcd nodes,
otherwise run etcd on the master node
```
## Cluster Expansion
To expand an existing Kubernetes cluster, run the ```add-kube-node.sh```
script. A complete list of script options and some examples are listed [[below]](####Cluster Expansion: Script Options).
This script must be run from the same host that created the cluster (or a host
that has the cluster artifact files stored in ```~/.clc_kube/$cluster_name```).
```shell
cd ./adm-kubernetes-on-clc
bash add-kube-node.sh -c="name_of_kubernetes_cluster" -m=2
```
#### Cluster Expansion: Script Options
```shell
Usage: add-kube-node.sh [OPTIONS]
Create servers in the CenturyLinkCloud environment and add to an
existing CLC kubernetes cluster
Environment variables CLC_V2_API_USERNAME and CLC_V2_API_PASSWD must be set in
order to access the CenturyLinkCloud API
-h (--help) display this help and exit
-c= (--clc_cluster_name=) set the name of the cluster, as used in CLC group names
-m= (--minion_count=) number of kubernetes minion nodes to add
```
## Cluster Deletion
There are two ways to delete an existing cluster:
1) Use our python script:
```shell
python delete_cluster.py --cluster=clc_cluster_name --datacenter=DC1
```
2) Use the CenturyLink Cloud UI. To delete a cluster, log into the CenturyLink
Cloud control portal and delete the parent server group that contains the
Kubernetes Cluster. We hope to add a scripted option to do this soon.
## Examples
Create a cluster with name of k8s_1, 1 master node and 3 worker minions (on physical machines), in VA1
```shell
bash kube-up.sh --clc_cluster_name=k8s_1 --minion_type=bareMetal --minion_count=3 --datacenter=VA1
```
Create a cluster with name of k8s_2, an ha etcd cluster on 3 VMs and 6 worker minions (on VMs), in VA1
```shell
bash kube-up.sh --clc_cluster_name=k8s_2 --minion_type=standard --minion_count=6 --datacenter=VA1 --etcd_separate_cluster=yes
```
Create a cluster with name of k8s_3, 1 master node, and 10 worker minions (on VMs) with higher mem/cpu, in UC1:
```shell
bash kube-up.sh --clc_cluster_name=k8s_3 --minion_type=standard --minion_count=10 --datacenter=VA1 -mem=6 -cpu=4
```
## Cluster Features and Architecture
We configue the Kubernetes cluster with the following features:
* KubeDNS: DNS resolution and service discovery
* Heapster/InfluxDB: For metric collection. Needed for Grafana and auto-scaling.
* Grafana: Kubernetes/Docker metric dashboard
* KubeUI: Simple web interface to view kubernetes state
* Kube Dashboard: New web interface to interact with your cluster
We use the following to create the kubernetes cluster:
* Kubernetes 1.1.7
* Unbuntu 14.04
* Flannel 0.5.4
* Docker 1.9.1-0~trusty
* Etcd 2.2.2
## Optional add-ons
* Logging: We offer an integrated centralized logging ELK platform so that all
Kubernetes and docker logs get sent to the ELK stack. To install the ELK stack
and configure Kubernetes to send logs to it, follow [the log
aggregation documentation](https://github.com/CenturyLinkCloud/adm-kubernetes-on-clc/blob/master/log_aggregration.md). Note: We don't install this by default as
the footprint isn't trivial.
## Cluster management
The most widely used tool for managing a kubernetes cluster is the command-line
utility ```kubectl```. If you do not already have a copy of this binary on your
administrative machine, you may run the script ```install_kubectl.sh``` which will
download it and install it in ```/usr/bin/local```.
The script requires that the environment variable ```CLC_CLUSTER_NAME``` be defined
```install_kubectl.sh``` also writes a configuration file which will embed the necessary
authentication certificates for the particular cluster. The configuration file is
written to the ```${CLC_CLUSTER_HOME}/kube``` directory
```shell
export KUBECONFIG=${CLC_CLUSTER_HOME}/kube/config
kubectl version
kubectl cluster-info
```
### Accessing the cluster programmatically
It's possible to use the locally-stored client certificates to access the api server. For example, you may want to use any of the [Kubernetes API client libraries](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/client-libraries.md) to program against your Kubernetes cluster in the programming language of your choice.
To demostrate how to use these locally stored certificates, we provide the folowing example of using ```curl``` to communicate to the master api server via https:
```shell
curl \
--cacert ${CLC_CLUSTER_HOME}/pki/ca.crt \
--key ${CLC_CLUSTER_HOME}/pki/kubecfg.key \
--cert ${CLC_CLUSTER_HOME}/pki/kubecfg.crt https://${MASTER_IP}:6443
```
But please note, this *does not* work out of the box with the ```curl``` binary
distributed with OSX.
### Accessing the cluster with a browser
We install two UIs on Kubernetes. The orginal KubeUI and [the newer kube
dashboard](/docs/user-guide/ui/). When you create a cluster, the script should output URLs for these
interfaces like this:
KubeUI is running at ```https://${MASTER_IP}:6443/api/v1/proxy/namespaces/kube-system/services/kube-ui```
kubernetes-dashboard is running at ```https://${MASTER_IP}:6443/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard```
Note on Authentication to the UIs: The cluster is set up to use basic
authentication for the user _admin_. Hitting the url at
```https://${MASTER_IP}:6443``` will require accepting the self-signed certificate
from the apiserver, and then presenting the admin password written to file at:
```> _${CLC_CLUSTER_HOME}/kube/admin_password.txt_```
### Configuration files
Various configuration files are written into the home directory *CLC_CLUSTER_HOME* under
```.clc_kube/${CLC_CLUSTER_NAME}``` in several subdirectories. You can use these files
to access the cluster from machines other than where you created the cluster from.
* ```config/```: Ansible variable files containing parameters describing the master and minion hosts
* ```hosts/```: hosts files listing access information for the ansible playbooks
* ```kube/```: ```kubectl``` configuration files, and the basic-authentication password for admin access to the Kubernetes API
* ```pki/```: public key infrastructure files enabling TLS communication in the cluster
* ```ssh/```: SSH keys for root access to the hosts
## ```kubectl``` usage examples
There are a great many features of _kubectl_. Here are a few examples
List existing nodes, pods, services and more, in all namespaces, or in just one:
```shell
kubectl get nodes
kubectl get --all-namespaces services
kubectl get --namespace=kube-system replicationcontrollers
```
The Kubernetes API server exposes services on web URLs, which are protected by requiring
client certificates. If you run a kubectl proxy locally, ```kubectl``` will provide
the necessary certificates and serve locally over http.
```shell
kubectl proxy -p 8001
```
Then, you can access urls like ```http://127.0.0.1:8001/api/v1/proxy/namespaces/kube-system/services/kube-ui/``` without the need for client certificates in your browser.
## What Kubernetes features do not work on CenturyLink Cloud
These are the known items that don't work on CenturyLink cloud but do work on other cloud providers:
- At this time, there is no support services of the type [LoadBalancer](/docs/user-guide/load-balancer/). We are actively working on this and hope to publish the changes sometime around April 2016.
- At this time, there is no support for persistent storage volumes provided by
CenturyLink Cloud. However, customers can bring their own persistent storage
offering. We ourselves use Gluster.
## Ansible Files
If you want more information about our Ansible files, please [read this file](https://github.com/CenturyLinkCloud/adm-kubernetes-on-clc/blob/master/ansible/README.md)

View File

@ -68,7 +68,7 @@ Check the tasks and templates in `roles/k8s` if you want to modify anything.
Once the playbook as finished, it will print out the IP of the Kubernetes master:
TASK: [k8s | debug msg='k8s master IP is {{ k8s_master.default_ip }}'] ********
TASK: [k8s | debug msg='k8s master IP is {% raw %}{{ k8s_master.default_ip }}{% endraw %}'] ********
SSH to it using the key that was created and using the _core_ user and you can list the machines in your cluster:
@ -77,4 +77,4 @@ SSH to it using the key that was created and using the _core_ user and you can l
MACHINE IP METADATA
a017c422... <node #1 IP> role=node
ad13bf84... <master IP> role=master
e9af8293... <node #2 IP> role=node
e9af8293... <node #2 IP> role=node

View File

@ -26,7 +26,7 @@ $ sed -e "s/{{ pillar\['dns_replicas'\] }}/${DNS_REPLICAS}/g;s/{{ pillar\['dns_d
# If the kube-system namespace isn't already created, create it
$ kubectl get ns
$ kubectl create -f ./kube-system.yaml
$ kubectl create namespace kube-system
$ kubectl create -f ./skydns.yaml{% endraw %}
```

View File

@ -2,7 +2,7 @@
---
_Note_:
These instructions are somewhat significantly more advanced than the [single node](docker.md) instructions. If you are
These instructions are somewhat significantly more advanced than the [single node](/docs/getting-started-guides/docker) instructions. If you are
interested in just starting to explore Kubernetes, we recommend that you start there.
* TOC
@ -35,7 +35,7 @@ it is still useful to use containers for deployment and management, so we create
You can specify the version on every node before install:
```shell
export K8S_VERSION=<your_k8s_version (e.g. 1.2.0-alpha.7)>
export K8S_VERSION=<your_k8s_version (e.g. 1.2.0)>
export ETCD_VERSION=<your_etcd_version (e.g. 2.2.1)>
export FLANNEL_VERSION=<your_flannel_version (e.g. 0.5.5)>
export FLANNEL_IFACE=<flannel_interface (defaults to eth0)>

View File

@ -3,13 +3,13 @@
We'll begin by setting up the master node. For the purposes of illustration, we'll assume that the IP of this machine
is `${MASTER_IP}`. We'll need to run several versioned Kubernetes components, so we'll assume that the version we want
to run is `${K8S_VERSION}`, which should hold a released version of Kubernetes >= "1.2.0-alpha.7"
to run is `${K8S_VERSION}`, which should hold a released version of Kubernetes >= "1.2.1"
Enviroinment variables used:
Environment variables used:
```shell
export MASTER_IP=<the_master_ip_here>
export K8S_VERSION=<your_k8s_version (e.g. 1.2.0-alpha.7)>
export K8S_VERSION=<your_k8s_version (e.g. 1.2.1)>
export ETCD_VERSION=<your_etcd_version (e.g. 2.2.1)>
export FLANNEL_VERSION=<your_flannel_version (e.g. 0.5.5)>
export FLANNEL_IFACE=<flannel_interface (defaults to eth0)>
@ -114,6 +114,7 @@ sudo docker -H unix:///var/run/docker-bootstrap.sock run -d \
--privileged \
-v /dev/net:/dev/net \
quay.io/coreos/flannel:${FLANNEL_VERSION} \
/opt/bin/flanneld \
--ip-masq=${FLANNEL_IPMASQ} \
--iface=${FLANNEL_IFACE}
```

View File

@ -26,8 +26,8 @@ if ( ! ps -ef | grep "/usr/bin/docker" | grep -v 'grep' &> /dev/null ); then
fi
# Make sure k8s version env is properly set
K8S_VERSION=${K8S_VERSION:-"1.2.0-alpha.7"}
ETCD_VERSION=${ETCD_VERSION:-"2.2.1"}
K8S_VERSION=${K8S_VERSION:-"1.2.2}
ETCD_VERSION=${ETCD_VERSION:-"2.3.1"}
FLANNEL_VERSION=${FLANNEL_VERSION:-"0.5.5"}
FLANNEL_IPMASQ=${FLANNEL_IPMASQ:-"true"}
FLANNEL_IFACE=${FLANNEL_IFACE:-"eth0"}
@ -176,7 +176,7 @@ start_k8s(){
;;
centos)
DOCKER_CONF="/etc/sysconfig/docker"
echo "OPTIONS=\"\$OPTIONS --mtu=${FLANNEL_MTU} --bip=${FLANNEL_SUBNET}\"" | tee -a ${DOCKER_CONF}
sed -i "/^OPTIONS=/ s|\( --mtu=.*\)\?'$| --mtu=${FLANNEL_MTU} --bip=${FLANNEL_SUBNET}'|" ${DOCKER_CONF}
if ! command_exists ifconfig; then
yum -y -q install net-tools
fi

View File

@ -149,7 +149,7 @@ start_k8s() {
case "${lsb_dist}" in
centos)
DOCKER_CONF="/etc/sysconfig/docker"
echo "OPTIONS=\"\$OPTIONS --mtu=${FLANNEL_MTU} --bip=${FLANNEL_SUBNET}\"" | tee -a ${DOCKER_CONF}
sed -i "/^OPTIONS=/ s|\( --mtu=.*\)\?'$| --mtu=${FLANNEL_MTU} --bip=${FLANNEL_SUBNET}'|" ${DOCKER_CONF}
if ! command_exists ifconfig; then
yum -y -q install net-tools
fi

View File

@ -13,79 +13,98 @@ Here's a diagram of what the final result will look like:
## Prerequisites
1. You need to have docker installed on one machine.
2. Decide what Kubernetes version to use. Set the `${K8S_VERSION}` variable to
a released version of Kubernetes >= "1.2.0-alpha.7"
2. Decide what Kubernetes version to use. Set the `${K8S_VERSION}` variable to
a released version of Kubernetes >= "v1.2.0". If you'd like to use the current stable version of Kubernetes, run the following:
```sh
export K8S_VERSION=$(curl -sS https://storage.googleapis.com/kubernetes-release/release/stable.txt)
```
and for the latest available version (including unstable releases):
```sh
export K8S_VERSION=$(curl -sS https://storage.googleapis.com/kubernetes-release/release/latest.txt)
```
### Run it
```shell
docker run \
export ARCH=amd64
docker run -d \
--volume=/:/rootfs:ro \
--volume=/sys:/sys:ro \
--volume=/sys:/sys:rw \
--volume=/var/lib/docker/:/var/lib/docker:rw \
--volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
--volume=/var/run:/var/run:rw \
--net=host \
--pid=host \
--privileged=true \
-d \
gcr.io/google_containers/hyperkube-amd64:v${K8S_VERSION} \
--privileged \
gcr.io/google_containers/hyperkube-${ARCH}:${K8S_VERSION} \
/hyperkube kubelet \
--containerized \
--hostname-override="127.0.0.1" \
--address="0.0.0.0" \
--hostname-override=127.0.0.1 \
--api-servers=http://localhost:8080 \
--config=/etc/kubernetes/manifests \
--cluster-dns=10.0.0.10 \
--cluster-domain=cluster.local \
--allow-privileged=true --v=2
--allow-privileged --v=2
```
> Note that `--cluster-dns` and `--cluster-domain` is used to deploy dns, feel free to discard them if dns is not needed.
> If you would like to mount an external device as a volume, add `--volume=/dev:/dev` to the command above. It may however, cause some problems described in [#18230](https://github.com/kubernetes/kubernetes/issues/18230)
> Architectures other than `amd64` are experimental and sometimes unstable, but feel free to try them out! Valid values: `arm`, `arm64` and `ppc64le`. ARM is available with Kubernetes version `v1.3.0-alpha.2` and higher. ARM 64-bit and PowerPC 64 little-endian are available with `v1.3.0-alpha.3` and higher. Track progress on multi-arch support [here](https://github.com/kubernetes/kubernetes/issues/17981)
This actually runs the kubelet, which in turn runs a [pod](/docs/user-guide/pods/) that contains the other master components.
** **SECURITY WARNING** ** services exposed via Kubernetes using Hyperkube are available on the host node's public network interface / IP address. Because of this, this guide is not suitable for any host node/server that is directly internet accessible. Refer to [#21735](https://github.com/kubernetes/kubernetes/issues/21735) for addtional info.
### Download `kubectl`
At this point you should have a running Kubernetes cluster. You can test this
by downloading the kubectl binary for `${K8S_VERSION}` (look at the URL in the
following links) and make it available by editing your PATH environment
variable.
([OS X/amd64](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/darwin/amd64/kubectl))
([OS X/386](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/darwin/386/kubectl))
([linux/amd64](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/amd64/kubectl))
([linux/386](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/386/kubectl))
([linux/arm](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/arm/kubectl))
At this point you should have a running Kubernetes cluster. You can test it out
by downloading the kubectl binary for `${K8S_VERSION}` (in this example: `{{page.version}}.0`).
For example, OS X:
```shell
$ wget http://storage.googleapis.com/kubernetes-release/release/v${K8S_VERSION}/bin/darwin/amd64/kubectl
$ chmod 755 kubectl
$ PATH=$PATH:`pwd`
Downloads:
- `linux/amd64`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/amd64/kubectl
- `linux/386`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/386/kubectl
- `linux/arm`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/arm/kubectl
- `linux/arm64`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/arm64/kubectl
- `linux/ppc64le`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/ppc64le/kubectl
- `OS X/amd64`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/darwin/amd64/kubectl
- `OS X/386`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/darwin/386/kubectl
- `windows/amd64`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/windows/amd64/kubectl.exe
- `windows/386`: http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/windows/386/kubectl.exe
The generic download path is:
```
http://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/${GOOS}/${GOARCH}/${K8S_BINARY}
```
Linux:
An example install with `linux/amd64`:
```shell
$ wget http://storage.googleapis.com/kubernetes-release/release/v${K8S_VERSION}/bin/linux/amd64/kubectl
$ chmod 755 kubectl
$ PATH=$PATH:`pwd`
```
curl -sSL "http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0/bin/linux/amd64/kubectl" > /usr/bin/kubectl
chmod +x /usr/bin/kubectl
```
Create configuration:
On OS X, to make the API server accessible locally, setup a ssh tunnel.
```shell
$ kubectl config set-cluster test-doc --server=http://localhost:8080
$ kubectl config set-context test-doc --cluster=test-doc
$ kubectl config use-context test-doc
docker-machine ssh `docker-machine active` -N -L 8080:localhost:8080
```
For Max OS X users instead of `localhost` you will have to use IP address of your docker machine,
which you can find by running `docker-machine env <machinename>` (see [documentation](https://docs.docker.com/machine/reference/env/)
for details).
Setting up a ssh tunnel is applicable to remote docker hosts as well.
(Optional) Create kubernetes cluster configuration:
```shell
kubectl config set-cluster test-doc --server=http://localhost:8080
kubectl config set-context test-doc --cluster=test-doc
kubectl config use-context test-doc
```
### Test it out
@ -98,8 +117,8 @@ kubectl get nodes
This should print:
```shell
NAME LABELS STATUS
127.0.0.1 kubernetes.io/hostname=127.0.0.1 Ready
NAME STATUS AGE
127.0.0.1 Ready 1h
```
### Run an application
@ -108,7 +127,7 @@ NAME LABELS STATUS
kubectl run nginx --image=nginx --port=80
```
Now run `docker ps` you should see nginx running. You may need to wait a few minutes for the image to get pulled.
Now run `docker ps` you should see nginx running. You may need to wait a few minutes for the image to get pulled.
### Expose it as a service
@ -116,66 +135,77 @@ Now run `docker ps` you should see nginx running. You may need to wait a few mi
kubectl expose deployment nginx --port=80
```
Run the following command to obtain the IP of this service we just created. There are two IPs, the first one is internal (CLUSTER_IP), and the second one is the external load-balanced IP (if a LoadBalancer is configured)
Run the following command to obtain the cluster local IP of this service we just created:
```shell
kubectl get svc nginx
```
```shell{% raw %}
ip=$(kubectl get svc nginx --template={{.spec.clusterIP}})
echo $ip
{% endraw %}```
Alternatively, you can obtain only the first IP (CLUSTER_IP) by running:
Hit the webserver with this IP:
```shell
```shell{% raw %}
kubectl get svc nginx --template={{.spec.clusterIP}}
```
{% endraw %}```
Hit the webserver with the first IP (CLUSTER_IP):
On OS X, since docker is running inside a VM, run the following command instead:
```shell
curl <insert-cluster-ip-here>
docker-machine ssh `docker-machine active` curl $ip
```
Note that you will need run this curl command on your boot2docker VM if you are running on OS X.
## Deploy a DNS
See [here](/docs/getting-started-guides/docker-multinode/deployDNS/) for instructions.
### A note on turning down your cluster
### Turning down your cluster
Many of these containers run under the management of the `kubelet` binary, which attempts to keep containers running, even if they fail. So, in order to turn down
the cluster, you need to first kill the kubelet container, and then any other containers.
1. Delete all the containers including the kubelet:
You may use `docker kill $(docker ps -aq)`, note this removes _all_ containers running under Docker, so use with caution.
Many of these containers run under the management of the `kubelet` binary, which attempts to keep containers running, even if they fail.
So, in order to turn down the cluster, you need to first kill the kubelet container, and then any other containers.
You may use `docker rm -f $(docker ps -aq)`, note this removes _all_ containers running under Docker, so use with caution.
2. Cleanup the filesystem:
On OS X, first ssh into the docker VM:
```shell
docker-machine ssh `docker-machine active`
```
```shell
sudo umount `cat /proc/mounts | grep /var/lib/kubelet | awk '{print $2}'`
sudo rm -rf /var/lib/kubelet
```
### Troubleshooting
#### Node is in `NotReady` state
If you see your node as `NotReady` it's possible that your OS does not have memcg and swap enabled.
If you see your node as `NotReady` it's possible that your OS does not have memcg enabled.
1. Your kernel should support memory and swap accounting. Ensure that the
1. Your kernel should support memory accounting. Ensure that the
following configs are turned on in your linux kernel:
```shell
CONFIG_RESOURCE_COUNTERS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_MEMCG_SWAP_ENABLED=y
CONFIG_MEMCG_KMEM=y
```
```shell
CONFIG_RESOURCE_COUNTERS=y
CONFIG_MEMCG=y
```
2. Enable the memory and swap accounting in the kernel, at boot, as command line
2. Enable the memory accounting in the kernel, at boot, as command line
parameters as follows:
```shell
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
```
```shell
GRUB_CMDLINE_LINUX="cgroup_enable=memory=1"
```
NOTE: The above is specifically for GRUB2.
You can check the command line parameters passed to your kernel by looking at the
output of /proc/cmdline:
NOTE: The above is specifically for GRUB2.
You can check the command line parameters passed to your kernel by looking at the
output of /proc/cmdline:
```shell
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-3.18.4-aufs root=/dev/sda5 ro cgroup_enable=memory swapaccount=1
```
```shell
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-3.18.4-aufs root=/dev/sda5 ro cgroup_enable=memory=1
```

View File

@ -32,8 +32,8 @@ But their size and availability is limited to that of a single machine.
The local-machine solutions are:
- [Local Docker-based](/docs/getting-started-guides/docker) (recommended starting point)
- [Vagrant](/docs/getting-started-guides/vagrant) (works on any platform with Vagrant: Linux, MacOS, or Windows.)
- [No-VM local cluster](/docs/getting-started-guides/locally) (Linux only)
- [Vagrant](/docs/getting-started-guides/vagrant)
### Hosted Solutions
@ -49,6 +49,7 @@ few commands, and have active community support.
- [GCE](/docs/getting-started-guides/gce)
- [AWS](/docs/getting-started-guides/aws)
- [Azure](/docs/getting-started-guides/coreos/azure/)
- [CenturyLink Cloud](/docs/getting-started-guides/clc)
### Custom Solutions
@ -82,6 +83,7 @@ These solutions are combinations of cloud provider and OS not covered by the abo
- [Vmware](/docs/getting-started-guides/coreos) (uses CoreOS and flannel)
- [libvirt-coreos.md](/docs/getting-started-guides/libvirt-coreos) (uses CoreOS)
- [oVirt](/docs/getting-started-guides/ovirt)
- [OpenStack Heat](/docs/getting-started-guides/openstack-heat) (uses CentOS and flannel)
- [libvirt](/docs/getting-started-guides/fedora/flannel_multi_node_cluster) (uses Fedora and flannel)
- [KVM](/docs/getting-started-guides/fedora/flannel_multi_node_cluster) (uses Fedora and flannel)
@ -112,11 +114,10 @@ Here are all the solutions mentioned above in table form.
IaaS Provider | Config. Mgmt | OS | Networking | Docs | Conforms | Support Level
-------------------- | ------------ | ------ | ---------- | --------------------------------------------- | ---------| ----------------------------
GKE | | | GCE | [docs](https://cloud.google.com/container-engine) | ['œ“][3] | Commercial
Vagrant | Saltstack | Fedora | flannel | [docs](/docs/getting-started-guides/vagrant) | ['œ“][2] | Project
GCE | Saltstack | Debian | GCE | [docs](/docs/getting-started-guides/gce) | ['œ“][1] | Project
Azure | CoreOS | CoreOS | Weave | [docs](/docs/getting-started-guides/coreos/azure/) | | Community ([@errordeveloper](https://github.com/errordeveloper), [@squillace](https://github.com/squillace), [@chanezon](https://github.com/chanezon), [@crossorigin](https://github.com/crossorigin))
Docker Single Node | custom | N/A | local | [docs](/docs/getting-started-guides/docker) | | Project ([@brendandburns](https://github.com/brendandburns))
Docker Multi Node | Flannel | N/A | local | [docs](/docs/getting-started-guides/docker-multinode) | | Project ([@brendandburns](https://github.com/brendandburns))
Docker Multi Node | custom | N/A | flannel | [docs](/docs/getting-started-guides/docker-multinode) | | Project ([@brendandburns](https://github.com/brendandburns))
Bare-metal | Ansible | Fedora | flannel | [docs](/docs/getting-started-guides/fedora/fedora_ansible_config) | | Project
Bare-metal | custom | Fedora | _none_ | [docs](/docs/getting-started-guides/fedora/fedora_manual_config) | | Project
Bare-metal | custom | Fedora | flannel | [docs](/docs/getting-started-guides/fedora/flannel_multi_node_cluster) | | Community ([@aveshagarwal](https://github.com/aveshagarwal))
@ -141,6 +142,7 @@ Bare-metal | custom | Ubuntu | Calico | [docs](/docs/gettin
Bare-metal | custom | Ubuntu | flannel | [docs](/docs/getting-started-guides/ubuntu) | | Community ([@resouer](https://github.com/resouer), [@WIZARD-CXY](https://github.com/WIZARD-CXY))
libvirt/KVM | CoreOS | CoreOS | libvirt/KVM | [docs](/docs/getting-started-guides/libvirt-coreos) | | Community ([@lhuard1A](https://github.com/lhuard1A))
oVirt | | | | [docs](/docs/getting-started-guides/ovirt) | | Community ([@simon3z](https://github.com/simon3z))
OpenStack Heat | Saltstack | CentOS | Neutron + flannel hostgw | [docs](/docs/getting-started-guides/openstack-heat) | | Community ([@FujitsuEnablingSoftwareTechnologyGmbH](https://github.com/FujitsuEnablingSoftwareTechnologyGmbH))
Rackspace | CoreOS | CoreOS | flannel | [docs](/docs/getting-started-guides/rackspace) | | Community ([@doublerr](https://github.com/doublerr))
any | any | any | any | [docs](/docs/getting-started-guides/scratch) | | Community ([@erictune](https://github.com/erictune))

View File

@ -3,9 +3,15 @@
[Juju](https://jujucharms.com/docs/stable/about-juju) makes it easy to deploy
Kubernetes by provisioning, installing and configuring all the systems in
the cluster. Once deployed the cluster can easily scale up with one command
the cluster. Once deployed the cluster can easily scale up with one command
to increase the cluster size.
The Juju Kubernetes work is curated by a very small group of community members.
Let us know how we are doing. If you find any problems please open an
[issue at the kubernetes project](https://github.com/kubernetes/kubernetes/issues)
and tag the issue with "juju" so we can find them.
* TOC
{:toc}
@ -13,48 +19,57 @@ to increase the cluster size.
> Note: If you're running kube-up, on Ubuntu - all of the dependencies
> will be handled for you. You may safely skip to the section:
> [Launch Kubernetes Cluster](#launch-kubernetes-cluster)
> [Launch a Kubernetes Cluster](#launch-a-kubernetes-cluster)
### On Ubuntu
[Install the Juju client](https://jujucharms.com/get-started) on your
local Ubuntu system:
[Install the Juju client](https://jujucharms.com/get-started)
> This documentation focuses on the Juju 2.0 release which will be
> promoted to stable during the April 2016 release cycle.
To paraphrase, on your local Ubuntu system:
```shell
sudo add-apt-repository ppa:juju/stable
sudo add-apt-repository ppa:juju/devel
sudo apt-get update
sudo apt-get install juju-core juju-quickstart
sudo apt-get install juju2
```
If you are using another distro/platform - please consult the
[getting started guide](https://jujucharms.com/get-started) to install the
Juju dependencies for your platform.
### With Docker
If you are not using Ubuntu or prefer the isolation of Docker, you may
run the following:
```shell
mkdir ~/.juju
sudo docker run -v ~/.juju:/home/ubuntu/.juju -ti jujusolutions/jujubox:latest
```
At this point from either path you will have access to the `juju
quickstart` command.
To set up the credentials for your chosen cloud run:
> While this is a common target, the charmbox flavors of images are
> unofficial, and should be treated as experimental. If you encounter any issues
> turning up the Kubernetes cluster with charmbox, please file a bug on the
> [charmbox issue tracker](https://github.com/juju-solutions/charmbox/issues).
```shell
juju quickstart --constraints="mem=3.75G" -i
mkdir ~/.juju2
sudo docker run -v ~/.juju2:/home/ubuntu/.local/share/juju -ti jujusolutions/charmbox:devel
```
> The `constraints` flag is optional, it changes the size of virtual machines
> that Juju will generate when it requests a new machine. Larger machines
> will run faster but cost more money than smaller machines.
### Configure Juju to point a cloud
Follow the dialogue and choose `save` and `use`. Quickstart will now
bootstrap the juju root node and setup the juju web based user
interface.
At this point you have access to the Juju client. Before you can deploy a
cluster you have to configure the credentials for the Juju cloud provider.
Juju [supports a wide variety of public clouds](#Cloud-compatibility) to set
up the credentials for your chosen cloud see the
[cloud setup page](https://jujucharms.com/docs/devel/getting-started#2.-choose-a-cloud).
## Launch Kubernetes cluster
After configuration is complete test your setup with a `juju bootstrap`
command:
`juju bootstrap $cloudname $cloudtype` you are ready to launch the
Kubernetes cluster.
## Launch a Kubernetes cluster
You will need to export the `KUBERNETES_PROVIDER` environment variable before
bringing up the cluster.
@ -64,44 +79,50 @@ export KUBERNETES_PROVIDER=juju
cluster/kube-up.sh
```
If this is your first time running the `kube-up.sh` script, it will install
the required dependencies to get started with Juju, additionally it will
launch a curses based configuration utility allowing you to select your cloud
provider and enter the proper access credentials.
Next it will deploy the kubernetes master, etcd, 2 nodes with flannel based
Software Defined Networking (SDN) so containers on different hosts can
communicate with each other.
If this is your first time running the `kube-up.sh` script, it will attempt to
install the required dependencies to get started with Juju.
Next it will deploy two nodes of Kubernetes, 1 unit of etcd, and network
the units so containers on different hosts can communicate with each other.
## Exploring the cluster
The `juju status` command provides information about each unit in the cluster:
```shell
$ juju status --format=oneline
- docker/0: 52.4.92.78 (started)
- flannel-docker/0: 52.4.92.78 (started)
- kubernetes/0: 52.4.92.78 (started)
- docker/1: 52.6.104.142 (started)
- flannel-docker/1: 52.6.104.142 (started)
- kubernetes/1: 52.6.104.142 (started)
- etcd/0: 52.5.216.210 (started) 4001/tcp
- juju-gui/0: 52.5.205.174 (started) 80/tcp, 443/tcp
- kubernetes-master/0: 52.6.19.238 (started) 8080/tcp
```
$ juju status
You can use `juju ssh` to access any of the units:
... (omitted for brevity)
```shell
juju ssh kubernetes-master/0
[Units]
ID WORKLOAD-STATE AGENT-STATE VERSION MACHINE PORTS PUBLIC-ADDRESS MESSAGE
etcd/0 active idle 2.0-beta2 1 54.146.50.29 Etcd leader running
kubernetes/0 active idle 2.0-beta2 2 6443/tcp,8088/tcp 54.205.204.227 Kubernetes follower running
kubernetes/1 active idle 2.0-beta2 3 6443/tcp,8088/tcp 54.145.57.114 Kubernetes leader running
... (omitted for brevity)
```
## Run some containers!
`kubectl` is available on the Kubernetes master node. We'll ssh in to
launch some containers, but one could use `kubectl` locally by setting
`KUBERNETES_MASTER` to point at the ip address of "kubernetes-master/0".
The `kubectl` file, the TLS certificates along with the configuration are
all available on the Kubernetes leader unit. Fetch the kubectl package so you
can run commands on the new Kuberntetes cluster.
Use the `juju status` command to figure out which Kubernetes unit is the leader
and copy the file from the leader:
```shell
juju scp kubernetes/1:kubectl_package.tar.gz .
tar xvfz kubectl_package.tar.gz
kubectl --kubeconfig config get pods
```
If you are not on a Linux amd64 host system, you will need to find or build a
kubectl binary package for your architecture.
Put the config file in the home directory so you don't have to specify it on
the command line each time. The default location is `${HOME}/.kube/config`.
No pods will be available before starting a container:
@ -139,21 +160,20 @@ We'll follow the aws-coreos example. Create a pod manifest: `pod.json`
}
```
Create the pod with kubectl:
Create the pod with kubectl:
```shell
kubectl create -f pod.json
```
Get info on the pod:
Get info on the pod:
```shell
kubectl get pods
```
To test the hello app, we need to locate which node is hosting
the container. Better tooling for using Juju to introspect container
is in the works but we can use `juju run` and `juju status` to find
the container. We can use `juju run` and `juju status` commands to find
our hello app.
Exit out of our ssh session and run:
@ -166,7 +186,8 @@ CONTAINER IDIMAGE COMMAND CREATED STATUS PORTS NAMES
02beb61339d8quay.io/kelseyhightower/hello:latest /hello About an hour ago Up About an hourk8s_hello....
```
We see "kubernetes/1" has our container, we can open port 80:
We see "kubernetes/1" has our container, expose the kubernetes charm and open
port 80:
```shell
juju run --unit kubernetes/1 "open-port 80"
@ -175,55 +196,65 @@ sudo apt-get install curl
curl $(juju status --format=oneline kubernetes/1 | cut -d' ' -f3)
```
Finally delete the pod:
Finally delete the pod:
```shell
juju ssh kubernetes-master/0
juju ssh kubernetes/0
kubectl delete pods hello
```
## Scale up cluster
Want larger Kubernetes nodes? It is easy to request different sizes of cloud
resources from Juju by using **constraints**. You can increase the amount of
CPU or memory (RAM) in any of the systems requested by Juju. This allows you
to fine tune th Kubernetes cluster to fit your workload. Use flags on the
bootstrap command or as a separate `juju constraints` command. Look to the
[Juju documentation for machine constraints](https://jujucharms.com/docs/devel/charms-constraints)
details.
## Scale out cluster
We can add node units like so:
Need more clusters? Juju makes it easy to add units of a charm:
```shell
juju add-unit docker # creates unit docker/2, kubernetes/2, docker-flannel/2
juju add-unit kubernetes
```
## Launch the "k8petstore" example app
The [k8petstore example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/k8petstore/) is available as a
[juju action](https://jujucharms.com/docs/devel/actions).
Or multiple units at one time:
```shell
juju action do kubernetes-master/0
juju add-unit -n3 kubernetes
```
> Note: this example includes curl statements to exercise the app, which
> automatically generates "petstore" transactions written to redis, and allows
> you to visualize the throughput in your browser.
## Tear down cluster
We recommend that you use the `kube-down.sh` command when you are done using
the cluster, as it properly brings down the cloud and removes some of the
build directories.
```shell
./kube-down.sh
```
or destroy your current Juju environment (using the `juju env` command):
Alternately if you want stop the servers you can destroy your current Juju
environment. Use the `juju env` command to get the current environment name:
```shell
juju destroy-environment --force `juju env`
juju kill-controller `juju env`
```
## More Info
The Kubernetes charms and bundles can be found in the `kubernetes` project on
github.com:
Juju works with charms and bundles to deploy solutions. The code that stands up
a Kubernetes cluster is done in the charm code. The charm is built from using
a layered approach to keep the code smaller and more focused on the operations
of Kubernetes.
- [Bundle Repository](http://releases.k8s.io/{{page.githubbranch}}/cluster/juju/bundles)
* [Kubernetes master charm](https://releases.k8s.io/{{page.githubbranch}}/cluster/juju/charms/trusty/kubernetes-master)
* [Kubernetes node charm](https://releases.k8s.io/{{page.githubbranch}}/cluster/juju/charms/trusty/kubernetes)
The Kubernetes layer and bundles can be found in the `kubernetes`
project on github.com:
- [Bundle location](https://github.com/kubernetes/kubernetes/tree/master/cluster/juju/bundles)
- [Kubernetes charm layer location](https://github.com/kubernetes/kubernetes/tree/master/cluster/juju/layers/kubernetes)
- [More about Juju](https://jujucharms.com)
@ -241,8 +272,6 @@ works with [Amazon Web Service](https://jujucharms.com/docs/stable/config-aws),
[Vagrant](https://jujucharms.com/docs/stable/config-vagrant), and
[Vmware vSphere](https://jujucharms.com/docs/stable/config-vmware).
If you do not see your favorite cloud provider listed many clouds can be
configured for [manual provisioning](https://jujucharms.com/docs/stable/config-manual).
The Kubernetes bundle has been tested on GCE and AWS and found to work with
version 1.0.0.
If you do not see your favorite cloud provider listed many clouds with ssh
access can be configured for
[manual provisioning](https://jujucharms.com/docs/stable/config-manual).

View File

@ -117,6 +117,32 @@ setfacl -m g:kvm:--x ~
By default, the libvirt-coreos setup will create a single Kubernetes master and 3 Kubernetes nodes. Because the VM drives use Copy-on-Write and because of memory ballooning and KSM, there is a lot of resource over-allocation.
There is both an automated way and a manual, customizable way of setting up libvert Kubernetes clusters on CoreOS.
#### Automated setup
There is an automated setup script on https://get.k8s.io that will download the tarball for Kubernetes and spawn a Kubernetes cluster on a local CoreOS instances that the script creates. To run this script, use wget or curl with the KUBERNETES_PROVIDER environment variable set to libvirt-coreos:
```shell
export KUBERNETES_PROVIDER=libvirt-coreos; wget -q -O - https://get.k8s.io | bash
```
Here is the curl version of this command:
```shell
export KUBERNETES_PROVIDER=libvirt-coreos; curl -sS https://get.k8s.io | bash`
```
This script downloads and unpacks the tarball, then spawns a Kubernetes cluster on CoreOS instances with the following characteristics:
- Total of 4 KVM/QEMU instances
- 1 instance acting as a Kubernetes master node
- 3 instances acting as minion nodes
If you'd like to run this cluster with customized settings, follow the manual setup instructions.
#### Manual setup
To start your local cluster, open a shell and run:
```shell
@ -135,6 +161,8 @@ The `KUBE_PUSH` environment variable may be set to specify which Kubernetes bina
* `release` (default if `KUBE_PUSH` is not set) will deploy the binaries of `_output/release-tars/kubernetes-server-….tar.gz`. This is built with `make release` or `make release-skip-tests`.
* `local` will deploy the binaries of `_output/local/go/bin`. These are built with `make`.
### Management
You can check that your machines are there and running with:
```shell
@ -233,7 +261,7 @@ On Arch:
pacman -S qemu libvirt
```
On Ubuntu 14.04.1:
On Ubuntu 14.04:
```shell
aptitude install qemu-system-x86 libvirt-bin
@ -255,7 +283,7 @@ On Arch:
systemctl start libvirtd
```
On Ubuntu 14.04.1:
On Ubuntu 14.04:
```shell
service libvirt-bin start
@ -291,4 +319,4 @@ usermod -a -G libvirtd $USER
#### error: Out of memory initializing network (virsh net-create...)
Ensure libvirtd has been restarted since ebtables was installed.
Ensure libvirtd has been restarted since ebtables was installed.

View File

@ -8,12 +8,12 @@
#### Linux
Not running Linux? Consider running Linux in a local virtual machine with [Vagrant](/docs/getting-started-guides/vagrant), or on a cloud provider like [Google Compute Engine](/docs/getting-started-guides/gce)
Not running Linux? Consider running Linux in a local virtual machine with [vagrant](https://www.vagrantup.com/), or on a cloud provider like [Google Compute Engine](/docs/getting-started-guides/gce)
#### Docker
At least [Docker](https://docs.docker.com/installation/#installation)
1.3+. Ensure the Docker daemon is running and can be contacted (try `docker
1.8.3+. Ensure the Docker daemon is running and can be contacted (try `docker
ps`). Some of the Kubernetes components need to run as root, which normally
works fine with docker.
@ -27,7 +27,8 @@ You need [go](https://golang.org/doc/install) at least 1.3+ in your path, please
### Starting the cluster
In a separate tab of your terminal, run the following (since one needs sudo access to start/stop Kubernetes daemons, it is easier to run the entire script as root):
First, you need to [download Kubernetes](/docs/getting-started-guides/binary_release/). Then open a separate tab of your terminal
and run the following (since one needs sudo access to start/stop Kubernetes daemons, it is easier to run the entire script as root):
```shell
cd kubernetes
@ -50,7 +51,7 @@ You can now use any of the cluster/kubectl.sh commands to interact with your loc
```shell
cluster/kubectl.sh get pods
cluster/kubectl.sh get services
cluster/kubectl.sh get replicationcontrollers
cluster/kubectl.sh get deployments
cluster/kubectl.sh run my-nginx --image=nginx --replicas=2 --port=80
## begin wait for provision to complete, you can monitor the docker pull by opening a new terminal
@ -64,7 +65,7 @@ cluster/kubectl.sh run my-nginx --image=nginx --replicas=2 --port=80
## introspect Kubernetes!
cluster/kubectl.sh get pods
cluster/kubectl.sh get services
cluster/kubectl.sh get replicationcontrollers
cluster/kubectl.sh get deployments
```
### Running a user defined pod
@ -81,7 +82,7 @@ cluster/kubectl.sh create -f docs/user-guide/pod.yaml
Congratulations!
### Troubleshooting
### FAQs
#### I cannot reach service IPs on the network.
@ -95,10 +96,6 @@ docker installation, this may conflict with IPs for containers. If you find
containers running with IPs in this range, edit hack/local-cluster-up.sh and
change the service-cluster-ip-range flag to something else.
#### I cannot create a replication controller with replica size greater than 1! What gives?
You are running a single node setup. This has the limitation of only supporting a single replica of a given pod. If you are interested in running with larger replica sizes, we encourage you to try the local vagrant setup or one of the cloud providers.
#### I changed Kubernetes code, how do I run it?
```shell
@ -109,8 +106,13 @@ hack/local-up-cluster.sh
#### kubectl claims to start a container but `get pods` and `docker ps` don't show it.
One or more of the KUbernetes daemons might've crashed. Tail the logs of each in /tmp.
One or more of the Kubernetes daemons might've crashed. Tail the [logs](/docs/admin/cluster-troubleshooting/#looking-at-logs) of each in /tmp.
```shell
$ ls /tmp/kube*.log
$ tail -f /tmp/kube-apiserver.log
```
#### The pods fail to connect to the services by host names
The local-up-cluster.sh script doesn't start a DNS service. Similar situation can be found [here](http://issue.k8s.io/6667). You can start a manually. Related documents can be found [here](https://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns#how-do-i-configure-it)
The local-up-cluster.sh script doesn't start a DNS service. Similar situation can be found [here](http://issue.k8s.io/6667). You can start a manually. Related documents can be found [here](https://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns#how-do-i-configure-it)

View File

@ -161,6 +161,6 @@ $ cat 21\:00\:00_21\:59\:59_S0.json | jq '.structPayload.log'
...
```
This page has touched briefly on the underlying mechanisms that support gathering cluster level logs on a Kubernetes deployment. The approach here only works for gathering the standard output and standard error output of the processes running in the pod's containers. To gather other logs that are stored in files one can use a sidecar container to gather the required files as described at the page [Collecting log files within containers with Fluentd](http://releases.k8s.io/{{page.githubbranch}}/contrib/logging/fluentd-sidecar-gcp/README.md) and sending them to the Google Cloud Logging service.
This page has touched briefly on the underlying mechanisms that support gathering cluster level logs on a Kubernetes deployment. The approach here only works for gathering the standard output and standard error output of the processes running in the pod's containers. To gather other logs that are stored in files one can use a sidecar container to gather the required files as described at the page [Collecting log files within containers with Fluentd](https://github.com/kubernetes/contrib/blob/master/logging/fluentd-sidecar-gcp/README.md) and sending them to the Google Cloud Logging service.
Some of the material in this section also appears in the blog article [Cluster Level Logging with Kubernetes](http://blog.kubernetes.io/2015/06/cluster-level-logging-with-kubernetes)
Some of the material in this section also appears in the blog article [Cluster Level Logging with Kubernetes](http://blog.kubernetes.io/2015/06/cluster-level-logging-with-kubernetes.html)

View File

@ -3,7 +3,7 @@
**By: Sandeep Dinesh** - _July 29, 2015_
![image](/images/docs/meanstack/image_0.png)
![image](/images/docs/meanstack/image_0.png)
In [a recent post](http://blog.sandeepdinesh.com/2015/07/running-mean-web-application-in-docker.html), I talked about running a MEAN stack with [Docker Containers.](http://docker.com/)
@ -14,7 +14,7 @@ Thankfully, there is a system we can use to manage our containers in a cluster e
* TOC
{:toc}
## The Basics of Using Kubernetes
## The Basics of Using Kubernetes
Before we jump in and start kubeing it up, its important to understand some of the fundamentals of Kubernetes.
@ -34,7 +34,7 @@ Instead, you have to build a custom container that has the code already inside i
To do this, you need to use more Docker. Make sure you have the latest version installed for the rest of this tutorial.
Getting the code:
Getting the code:
Before starting, lets get some code to run. You can follow along on your personal machine or a Linux VM in the cloud. I recommend using Linux or a Linux VM; running Docker on Mac and Windows is outside the scope of this tutorial.
@ -53,7 +53,7 @@ First, you need a `Dockerfile`. This is basically the list of instructions Docke
Here is the `Dockerfile` for the web server:
```shell
FROM node:0.10.40
FROM node:4.4
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
@ -65,14 +65,14 @@ CMD ["node", "app.js"]
A `Dockerfile` is pretty self explanatory, and this one is dead simple.
First, it uses the official Node.js image as the base image.
First, it uses the official Node.js LTS image as the base image.
Then, it creates a folder to store the code, `cd`s into that directory, copies the code in, and installs the dependencies with npm.
Finally, it specifies the command Docker should run when the container starts, which is to start the app.
## Step 2: Building our Container
## Step 2: Building our Container
Right now, the directory should look like this:
@ -410,11 +410,11 @@ web-controller-xxxx 1/1 Running 0 1m
## Step 9: Accessing the App
At this point, everything is up and running. The architecture looks something like this:
At this point, everything is up and running. The architecture looks something like this:
![image](/images/docs/meanstack/image_5.png)
![image](/images/docs/meanstack/MEANstack_architecture.svg){: style="max-width:25%"}
By default, port 80 should be open on the load balancer. In order to find the IP address of our app, run this command:
By default, port 80 should be open on the load balancer. In order to find the IP address of our app, run this command:
```shell
$ gcloud compute forwarding-rules list
@ -441,4 +441,3 @@ By using Container Engine and Kubernetes, we have a very robust, container based
Hopefully I can do some more posts about advanced Kubernetes topics such as changing the cluster size and number of Node.js web server replicas, using different environments (dev, staging, prod) on the same cluster, and doing rolling updates.
Thanks to [Mark Mandel](https://medium.com/@markmandel), [Aja Hammerly](https://medium.com/@thagomizer), and [Jack Wilber](https://medium.com/@jack.g.wilber). [Some rights reserved](http://creativecommons.org/licenses/by/4.0/) by the author.

View File

@ -229,23 +229,23 @@ Note that we have passed these two values already as parameter to the apiserver
A template for an replication controller spinning up the pod with the 3 containers can be found at [cluster/addons/dns/skydns-rc.yaml.in][11] in the repository. The following steps are necessary in order to get a valid replication controller yaml file:
- replace `{{ pillar['dns_replicas'] }}` with `1`
- replace `{{ pillar['dns_domain'] }}` with `cluster.local.`
- replace `{% raw %}{{ pillar['dns_replicas'] }}{% endraw %}` with `1`
- replace `{% raw %}{{ pillar['dns_domain'] }}{% endraw %}` with `cluster.local.`
- add `--kube_master_url=${KUBERNETES_MASTER}` parameter to the kube2sky container command.
In addition the service template at [cluster/addons/dns/skydns-svc.yaml.in][12] needs the following replacement:
- `{{ pillar['dns_server'] }}` with `10.10.10.10`.
- `{% raw %}{{ pillar['dns_server'] }}{% endraw %}` with `10.10.10.10`.
To do this automatically:
```shell
```shell{% raw %}
sed -e "s/{{ pillar\['dns_replicas'\] }}/1/g;"\
"s,\(command = \"/kube2sky\"\),\\1\\"$'\n'" - --kube_master_url=${KUBERNETES_MASTER},;"\
"s/{{ pillar\['dns_domain'\] }}/cluster.local/g" \
cluster/addons/dns/skydns-rc.yaml.in > skydns-rc.yaml
sed -e "s/{{ pillar\['dns_server'\] }}/10.10.10.10/g" \
cluster/addons/dns/skydns-svc.yaml.in > skydns-svc.yaml
cluster/addons/dns/skydns-svc.yaml.in > skydns-svc.yaml{% endraw %}
```
Now the kube-dns pod and service are ready to be launched:
@ -326,4 +326,4 @@ Future work will add instructions to this guide to enable support for Kubernetes
[10]: http://open.mesosphere.com/getting-started/cloud/google/mesosphere/#vpn-setup
[11]: https://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/skydns-rc.yaml.in
[12]: https://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/skydns-svc.yaml.in
[13]: https://releases.k8s.io/{{page.githubbranch}}/contrib/mesos/README.md
[13]: https://releases.k8s.io/{{page.githubbranch}}/contrib/mesos/README.md

View File

@ -0,0 +1,239 @@
---
---
* TOC
{:toc}
## Getting started with OpenStack
This guide will take you through the steps of deploying Kubernetes to Openstack using `kube-up.sh`. The primary mechanisms for this are [OpenStack Heat](https://wiki.openstack.org/wiki/Heat) and the [SaltStack](https://github.com/kubernetes/kubernetes/tree/master/cluster/saltbase) distributed with Kubernetes.
The default OS is CentOS 7, this has not been tested on other operating systems.
This guide assumes you have access to a working OpenStack cluster with the following features:
- Nova
- Neutron
- Swift
- Glance
- Heat
- DNS resolution of instance names
By default this provider provisions 4 m1.medium instances. If you do not have resources available, please see the [Set additional configuration values](#set-additional-configuration-values) section for information on reducing the footprint of your cluster.
## Pre-Requisites
If you already have the required versions of the OpenStack CLI tools installed and configured, you can move on to the [Starting a cluster](#starting-a-cluster) section.
#### Install OpenStack CLI tools
```sh
sudo pip install -U --force 'python-openstackclient==2.4.0'
sudo pip install -U --force 'python-swiftclient==3.0.0'
sudo pip install -U --force 'python-glanceclient==2.0.0'
sudo pip install -U --force 'python-novaclient==3.4.0'
```
#### Configure Openstack CLI tools
Please talk to your local OpenStack administrator for an `openrc.sh` file.
Once you have that file, source it into your environment by typing
```sh
. ~/path/to/openrc.sh
```
This provider will consume the [correct variables](http://docs.openstack.org/user-guide/common/cli_set_environment_variables_using_openstack_rc.html) to talk to OpenStack and turn-up the Kubernetes cluster.
Otherwise, you must set the following appropriately:
```sh
export OS_USERNAME=username
export OS_PASSWORD=password
export OS_TENANT_NAME=projectName
export OS_AUTH_URL=https://identityHost:portNumber/v2.0
export OS_TENANT_ID=tenantIDString
export OS_REGION_NAME=regionName
```
#### Set additional configuration values
In addition, here are some commonly changed variables specific to this provider, with example values. Under most circumstances you will not have to change these. Please see the files in the next section for a full list of options.
```sh
export STACK_NAME=KubernetesStack
export NUMBER_OF_MINIONS=3
export MAX_NUMBER_OF_MINIONS=3
export MASTER_FLAVOR=m1.small
export MINION_FLAVOR=m1.small
export EXTERNAL_NETWORK=public
export DNS_SERVER=8.8.8.8
export IMAGE_URL_PATH=http://cloud.centos.org/centos/7/images
export IMAGE_FILE=CentOS-7-x86_64-GenericCloud-1510.qcow2
export SWIFT_SERVER_URL=http://192.168.123.100:8080
export ENABLE_PROXY=false
```
#### Manually overriding configuration values
If you do not have your environment variables set, or do not want them consumed, modify the variables in the following files under `cluster/openstack-heat`:
- **[config-default.sh](http://releases.k8s.io/{{page.githubbranch}}/cluster/openstack-heat/config-default.sh)** Sets all parameters needed for heat template.
- **[config-image.sh](http://releases.k8s.io/{{page.githubbranch}}/cluster/openstack-heat/config-image.sh)** Sets parameters needed to download and create new OpenStack image via glance.
- **[openrc-default.sh](http://releases.k8s.io/{{page.githubbranch}}/cluster/openstack-heat/openrc-default.sh)** Sets environment variables for communicating to OpenStack. These are consumed by the cli tools (heat, glance, swift, nova).
- **[openrc-swift.sh](http://releases.k8s.io/{{page.githubbranch}}/cluster/openstack-heat/openrc-swift.sh)** Some OpenStack setups require the use of seperate swift credentials. Put those credentials in this file.
Please see the contents of these files for documentation regarding each variable's function.
## Starting a cluster
Once you've installed the OpenStack CLI tools and have set your OpenStack environment variables, issue this command:
```sh
export KUBERNETES_PROVIDER=openstack-heat; curl -sS https://get.k8s.io | bash
```
Alternatively, you can download a [Kubernetes release](https://github.com/kubernetes/kubernetes/releases) and extract the archive. To start your cluster, open a shell and run:
```sh
cd kubernetes # Or whichever path you have extracted the release to
KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
Or, if you are working from a checkout of the Kubernetes code base, and want to build/test from source:
```sh
cd kubernetes # Or whatever your checkout root directory is called
make clean
make quick-release
KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
## Inspect your cluster
Once kube-up is finished, your cluster should be running:
```console
./cluster/kubectl.sh get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-1 Healthy {"health": "true"}
etcd-0 Healthy {"health": "true"}
```
You can also list the nodes in your cluster:
```console
./cluster/kubectl.sh get nodes
NAME STATUS AGE
kubernetesstack-node-ojszyjtr Ready 42m
kubernetesstack-node-tzotzcbp Ready 46m
kubernetesstack-node-uah8pkju Ready 47m
```
Being a new cluster, there will be no pods or replication controllers in the default namespace:
```console
./cluster/kubectl.sh get pods
./cluster/kubectl.sh get replicationcontrollers
```
You are now ready to create Kubernetes objects.
## Using your cluster
For a simple test, issue the following command:
```sh
./cluster/kubectl.sh run nginx --image=nginx --generator=run-pod/v1
```
Soon, you should have a running nginx pod:
```console
./cluster/kubectl.sh get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 5m
```
Once the nginx pod is running, use the port-forward command to set up a proxy from your machine to the pod.
```sh
./cluster/kubectl.sh port-forward nginx 8888:80
```
You should now see nginx on [http://localhost:8888]().
For more complex examples please see the [examples directory](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/).
## Administering your cluster with Openstack
You can manage the nodes in your cluster using the OpenStack CLI Tools.
First, set your environment variables:
```sh
. cluster/openstack-heat/config-default.sh
. cluster/openstack-heat/openrc-default.sh
```
To get all information about your cluster, use heat:
```sh
heat stack-show $STACK_NAME
```
To see a list of nodes, use nova:
```sh
nova list --name=$STACK_NAME
```
See the [OpenStack CLI Reference](http://docs.openstack.org/cli-reference/) for more details.
## SSHing to your nodes
Your public key was added during the cluster turn-up, so you can easily ssh to them for troubleshooting purposes.
```sh
ssh minion@IP_ADDRESS
```
## Cluster deployment customization examples
You may find the need to modify environment variables to change the behaviour of kube-up. Here are some common scenarios:
#### Proxy configuration
If you are behind a proxy, and have your local environment variables setup, you can use these variables to setup your Kubernetes cluster:
```sh
ENABLE_PROXY=true KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
#### Setting different Swift URL
Some deployments differ from the default Swift URL:
```sh
SWIFT_SERVER_URL="http://10.100.0.100:8080" KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
#### Public network name.
Sometimes the name of the public network differs from the default `public`:
```sh
EXTERNAL_NETWORK="network_external" KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
#### Spinning up additional clusters.
You may want to spin up another cluster within your OpenStack project. Use the `$STACK_NAME` variable to accomplish this.
```sh
STACK_NAME=k8s-cluster-2 KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-up.sh
```
For more configuration examples, please browse the files mentioned in the [Configuration](#set-additional-configuration-values) section.
## Tearing down your cluster
To bring down your cluster, issue the following command:
```sh
KUBERNETES_PROVIDER=openstack-heat ./cluster/kube-down.sh
```
If you have changed the default `$STACK_NAME`, you must specify the name. Note that this will not remove any Cinder volumes created by Kubernetes.

View File

@ -22,8 +22,8 @@ must be running on the node.
rkt uses the [Container Network Interface (CNI)](https://github.com/appc/cni)
to manage container networking. By default, all pods attempt to join a network
called `rkt.kubernetes.io`, which is currently defined [in `rkt.go`]
(https://github.com/kubernetes/kubernetes/blob/v1.2.0-alpha.6/pkg/kubelet/rkt/rkt.go#L91).
called `rkt.kubernetes.io`, which is currently defined [in
`rkt.go`](https://github.com/kubernetes/kubernetes/blob/v1.2.0-alpha.6/pkg/kubelet/rkt/rkt.go#L91).
In order for pods to get correct IP addresses, the CNI config file must be
edited to add this `rkt.kubernetes.io` network:
@ -216,4 +216,4 @@ where `$UUID` is the rkt pod's UUID, which you can find via `rkt list --full`, a
##### Check Kubernetes events, logs.
Besides above tricks, Kubernetes also provides us handy tools for debugging the pods. More information can be found [here](/docs/user-guide/application-troubleshooting)
Besides above tricks, Kubernetes also provides us handy tools for debugging the pods. More information can be found [here](/docs/user-guide/application-troubleshooting)

View File

@ -368,7 +368,7 @@ Then you need to configure your kubelet with flag:
### kubelet
All nodes should run kubelet. See [Selecting Binaries](#selecting-binaries).
All nodes should run kubelet. See [Software Binaries](#software-binaries).
Arguments to consider:
@ -796,17 +796,17 @@ Notes for setting up each cluster service are given below:
* Cluster DNS:
* required for many kubernetes examples
* [Setup instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/)
* [Admin Guide](/admin/dns/)
* [Admin Guide](/docs/admin/dns/)
* Cluster-level Logging
* Multiple implementations with different storage backends and UIs.
* [Elasticsearch Backend Setup Instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-elasticsearch/)
* [Google Cloud Logging Backend Setup Instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-gcp/).
* Both require running fluentd on each node.
* [User Guide](/user-guide/logging/)
* [User Guide](/docs/user-guide/logging/)
* Container Resource Monitoring
* [Setup instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-monitoring/)
* GUI
* [Setup instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/kube-ui/)
* [Setup instructions](https://github.com/kubernetes/kube-ui)
cluster.
## Troubleshooting

View File

@ -8,9 +8,9 @@ Running Kubernetes with Vagrant (and VirtualBox) is an easy way to run/test/deve
### Prerequisites
1. Install latest version >= 1.7.4 of vagrant from http://www.vagrantup.com/downloads.html
1. Install latest version >= 1.7.4 of [Vagrant](http://www.vagrantup.com/downloads.html)
2. Install one of:
1. The latest version of Virtual Box from https://www.virtualbox.org/wiki/Downloads
1. The latest version of [Virtual Box](https://www.virtualbox.org/wiki/Downloads)
2. [VMWare Fusion](https://www.vmware.com/products/fusion/) version 5 or greater as well as the appropriate [Vagrant VMWare Fusion provider](https://www.vagrantup.com/vmware)
3. [VMWare Workstation](https://www.vmware.com/products/workstation/) version 9 or greater as well as the [Vagrant VMWare Workstation provider](https://www.vagrantup.com/vmware)
4. [Parallels Desktop](https://www.parallels.com/products/desktop/) version 9 or greater as well as the [Vagrant Parallels provider](https://parallels.github.io/vagrant-parallels/)
@ -20,14 +20,14 @@ Running Kubernetes with Vagrant (and VirtualBox) is an easy way to run/test/deve
Setting up a cluster is as simple as running:
```shell
```sh
export KUBERNETES_PROVIDER=vagrant
curl -sS https://get.k8s.io | bash
```
Alternatively, you can download [Kubernetes release](https://github.com/kubernetes/kubernetes/releases) and extract the archive. To start your local cluster, open a shell and run:
```shell
```sh
cd kubernetes
export KUBERNETES_PROVIDER=vagrant
@ -42,7 +42,7 @@ Vagrant will provision each machine in the cluster with all the necessary compon
If you installed more than one Vagrant provider, Kubernetes will usually pick the appropriate one. However, you can override which one Kubernetes will use by setting the [`VAGRANT_DEFAULT_PROVIDER`](https://docs.vagrantup.com/v2/providers/default.html) environment variable:
```shell
```sh
export VAGRANT_DEFAULT_PROVIDER=parallels
export KUBERNETES_PROVIDER=vagrant
./cluster/kube-up.sh
@ -52,14 +52,14 @@ By default, each VM in the cluster is running Fedora.
To access the master or any node:
```shell
```sh
vagrant ssh master
vagrant ssh node-1
```
If you are running more than one node, you can access the others by:
```shell
```sh
vagrant ssh node-2
vagrant ssh node-3
```
@ -70,7 +70,7 @@ The master node instantiates the Kubernetes master components as pods on the mac
To view the service status and/or logs on the kubernetes-master:
```shell
```console
[vagrant@kubernetes-master ~] $ vagrant ssh master
[vagrant@kubernetes-master ~] $ sudo su
@ -87,7 +87,7 @@ To view the service status and/or logs on the kubernetes-master:
To view the services on any of the nodes:
```shell
```console
[vagrant@kubernetes-master ~] $ vagrant ssh node-1
[vagrant@kubernetes-master ~] $ sudo su
@ -104,20 +104,20 @@ With your Kubernetes cluster up, you can manage the nodes in your cluster with t
To push updates to new Kubernetes code after making source changes:
```shell
```sh
./cluster/kube-push.sh
```
To stop and then restart the cluster:
```shell
```sh
vagrant halt
./cluster/kube-up.sh
```
To destroy the cluster:
```shell
```sh
vagrant destroy
```
@ -125,7 +125,7 @@ Once your Vagrant machines are up and provisioned, the first thing to do is to c
You may need to build the binaries first, you can do this with `make`
```shell
```console
$ ./cluster/kubectl.sh get nodes
NAME LABELS
@ -138,7 +138,7 @@ NAME LABELS
When using the vagrant provider in Kubernetes, the `cluster/kubectl.sh` script will cache your credentials in a `~/.kubernetes_vagrant_auth` file so you will not be prompted for them in the future.
```shell
```sh
cat ~/.kubernetes_vagrant_auth
```
@ -153,7 +153,7 @@ cat ~/.kubernetes_vagrant_auth
You should now be set to use the `cluster/kubectl.sh` script. For example try to list the nodes that you have started with:
```shell
```sh
./cluster/kubectl.sh get nodes
```
@ -161,7 +161,7 @@ You should now be set to use the `cluster/kubectl.sh` script. For example try to
Your cluster is running, you can list the nodes in your cluster:
```shell
```sh
$ ./cluster/kubectl.sh get nodes
NAME LABELS
@ -175,7 +175,7 @@ Now start running some containers!
You can now use any of the `cluster/kube-*.sh` commands to interact with your VM machines.
Before starting a container there will be no pods, services and replication controllers.
```shell
```sh
$ ./cluster/kubectl.sh get pods
NAME READY STATUS RESTARTS AGE
@ -188,13 +188,13 @@ CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
Start a container running nginx with a replication controller and three replicas
```shell
```sh
$ ./cluster/kubectl.sh run my-nginx --image=nginx --replicas=3 --port=80
```
When listing the pods, you will see that three containers have been started and are in Waiting state:
```shell
```sh
$ ./cluster/kubectl.sh get pods
NAME READY STATUS RESTARTS AGE
my-nginx-5kq0g 0/1 Pending 0 10s
@ -204,7 +204,7 @@ my-nginx-xql4j 0/1 Pending 0 10s
You need to wait for the provisioning to complete, you can monitor the nodes by doing:
```shell
```sh
$ vagrant ssh node-1 -c 'sudo docker images'
kubernetes-node-1:
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
@ -215,7 +215,7 @@ kubernetes-node-1:
Once the docker image for nginx has been downloaded, the container will start and you can list it:
```shell
```sh
$ vagrant ssh node-1 -c 'sudo docker ps'
kubernetes-node-1:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
@ -227,7 +227,7 @@ kubernetes-node-1:
Going back to listing the pods, services and replicationcontrollers, you now have:
```shell
```sh
$ ./cluster/kubectl.sh get pods
NAME READY STATUS RESTARTS AGE
my-nginx-5kq0g 1/1 Running 0 1m
@ -243,10 +243,10 @@ my-nginx my-nginx nginx run=my-nginx 3 1m
```
We did not start any services, hence there are none listed. But we see three replicas displayed properly.
Check the [guestbook](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/guestbook/) application to learn how to create a service.
Learn about [running your first containers](../user-guide/simple-nginx/) application to learn how to create a service.
You can already play with scaling the replicas with:
```shell
```sh
$ ./cluster/kubectl.sh scale rc my-nginx --replicas=2
$ ./cluster/kubectl.sh get pods
NAME READY STATUS RESTARTS AGE
@ -256,13 +256,13 @@ my-nginx-gr3hh 1/1 Running 0 2m
Congratulations!
### Troubleshooting
## Troubleshooting
#### I keep downloading the same (large) box all the time!
By default the Vagrantfile will download the box from S3. You can change this (and cache the box locally) by providing a name and an alternate URL when calling `kube-up.sh`
```shell
```sh
export KUBERNETES_BOX_NAME=choose_your_own_name_for_your_kuber_box
export KUBERNETES_BOX_URL=path_of_your_kuber_box
export KUBERNETES_PROVIDER=vagrant
@ -273,7 +273,7 @@ export KUBERNETES_PROVIDER=vagrant
During provision of the cluster, you may see the following message:
```shell
```sh
Validating node-1
.............
Waiting for each node to be registered with cloud provider
@ -284,7 +284,7 @@ Some users have reported VPNs may prevent traffic from being routed to the host
To debug, first verify that the master is binding to the proper IP address:
```
```sh
$ vagrant ssh master
$ ifconfig | grep eth1 -C 2
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.245.1.2 netmask
@ -310,13 +310,13 @@ If you do see a network, but are still unable to ping the machine, check if your
You probably have an incorrect ~/.kubernetes_vagrant_auth file for the cluster you are attempting to contact.
```shell
```sh
rm ~/.kubernetes_vagrant_auth
```
After using kubectl.sh make sure that the correct credentials are set:
```shell
```sh
cat ~/.kubernetes_vagrant_auth
```
@ -331,10 +331,6 @@ cat ~/.kubernetes_vagrant_auth
If this is your first time creating the cluster, the kubelet on each node schedules a number of docker pull requests to fetch prerequisite images. This can take some time and as a result may delay your initial pod getting provisioned.
#### I want to make changes to Kubernetes code!
To set up a vagrant cluster for hacking, follow the [vagrant developer guide](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/devel/developer-guides/vagrant.md).
#### I have brought Vagrant up but the nodes cannot validate!
Log on to one of the nodes (`vagrant ssh node-1`) and inspect the salt minion log (`sudo cat /var/log/salt/minion`).
@ -343,7 +339,7 @@ Log on to one of the nodes (`vagrant ssh node-1`) and inspect the salt minion lo
You can control the number of nodes that are instantiated via the environment variable `NUM_NODES` on your host machine. If you plan to work with replicas, we strongly encourage you to work with enough nodes to satisfy your largest intended replica size. If you do not plan to work with replicas, you can save some system resources by running with a single node. You do this, by setting `NUM_NODES` to 1 like so:
```shell
```sh
export NUM_NODES=1
```
@ -352,39 +348,17 @@ export NUM_NODES=1
You can control the memory allotted to virtual machines with the `KUBERNETES_MEMORY` environment variable.
Just set it to the number of megabytes you would like the machines to have. For example:
```shell
```sh
export KUBERNETES_MEMORY=2048
```
If you need more granular control, you can set the amount of memory for the master and nodes independently. For example:
```shell
```sh
export KUBERNETES_MASTER_MEMORY=1536
export KUBERNETES_NODE_MEMORY=2048
```
#### I want to set proxy settings for my Kubernetes cluster boot strapping!
If you are behind a proxy, you need to install the Vagrant proxy plugin and set the proxy settings:
```shell
vagrant plugin install vagrant-proxyconf
export KUBERNETES_HTTP_PROXY=http://username:password@proxyaddr:proxyport
export KUBERNETES_HTTPS_PROXY=https://username:password@proxyaddr:proxyport
```
You can also specify addresses that bypass the proxy, for example:
```shell
export KUBERNETES_NO_PROXY=127.0.0.1
```
If you are using sudo to make Kubernetes build, use the `-E` flag to pass in the environment variables. For example, if running `make quick-release`, use:
```shell
sudo -E make quick-release
```
#### I ran vagrant suspend and nothing works!
`vagrant suspend` seems to mess up the network. This is not supported at this time.
@ -393,6 +367,6 @@ sudo -E make quick-release
You can ensure that vagrant uses nfs to sync folders with virtual machines by setting the KUBERNETES_VAGRANT_USE_NFS environment variable to 'true'. nfs is faster than virtualbox or vmware's 'shared folders' and does not require guest additions. See the [vagrant docs](http://docs.vagrantup.com/v2/synced-folders/nfs.html) for details on configuring nfs on the host. This setting will have no effect on the libvirt provider, which uses nfs by default. For example:
```shell
```sh
export KUBERNETES_VAGRANT_USE_NFS=true
```

View File

@ -26,10 +26,20 @@ Remember the project ID; it will be referred to later in this codelab as `PROJEC
Next, [enable billing](https://console.developers.google.com/billing) in the Developers Console in order to use Google Cloud resources and [enable the Container Engine API](https://console.developers.google.com/project/_/kubernetes/list).
New users of Google Cloud Platform recieve a [$300 free trial](https://console.developers.google.com/billing/freetrial?hl=en). Running through this codelab shouldnt cost you more than a few dollars of that trial. Google Container Engine pricing is documented [here](https://cloud.google.com/container-engine/docs/#pricing).
New users of Google Cloud Platform receive a [$300 free trial](https://console.developers.google.com/billing/freetrial?hl=en). Running through this codelab shouldnt cost you more than a few dollars of that trial. Google Container Engine pricing is documented [here](https://cloud.google.com/container-engine/pricing).
Next, make sure you [download Node.js](https://nodejs.org/en/download/).
Then install [Docker](https://docs.docker.com/engine/installation/), and [Google Cloud SDK](https://cloud.google.com/sdk/).
Finally, after Google Cloud SDK installs, run the following command to install [`kubectl`](http://kubernetes.io/docs/user-guide/kubectl-overview/):
```shell
gcloud components install kubectl
```
You're all set up with an environment that can build container images, run Node apps, run Kubernetes clusters locally, and deploy Kubernetes clusters to Google Container Engine. Let's begin!
## Create your Node.js application
The first step is to write the application. Save this code in a folder called "`hellonode/`" with the filename `server.js`:
@ -60,18 +70,18 @@ Now lets package this application in a Docker container.
## Create a Docker container image
Next, create a file, also within `helloworld/` named `Dockerfile`. A Dockerfile describes the image that you want to build. Docker container images can extend from other existing images so for this image, we'll extend from an existing Node image.
Next, create a file, also within `hellonode/` named `Dockerfile`. A Dockerfile describes the image that you want to build. Docker container images can extend from other existing images so for this image, we'll extend from an existing Node image.
#### Dockerfile
```conf
FROM node:0.12
FROM node:4.4
EXPOSE 8080
COPY server.js .
CMD node server.js
```
This "recipe" for the Docker image will start from the Node 0.12 image found on the Docker registry, expose port 8080, copy our `server.js` file to the image and start the Node server.
This "recipe" for the Docker image will start from the official Node.js LTS image found on the Docker registry, expose port 8080, copy our `server.js` file to the image and start the Node server.
Now build an image of your container by running `docker build`, tagging the image with the Google Container Registry repo for your `PROJECT_ID`:
@ -83,14 +93,14 @@ Now there is a trusted source for getting an image of your containerized app.
Let's try your image out with Docker:
```shell
docker run -d -p 8080:8080 gcr.io/PROJECT_ID/hello-node:v1
$ docker run -d -p 8080:8080 gcr.io/PROJECT_ID/hello-node:v1
325301e6b2bffd1d0049c621866831316d653c0b25a496d04ce0ec6854cb7998
```
Visit your app in the browser, or use `curl` or `wget` if youd like :
```shell
curl http://localhost:8080
$ curl http://localhost:8080
Hello World!
```
@ -101,7 +111,7 @@ docker ps
CONTAINER ID IMAGE COMMAND
2c66d0efcbd4 gcr.io/PROJECT_ID/hello-node:v1 "/bin/sh -c 'node
$ docker stop 2c66d0efcbd4
docker stop 2c66d0efcbd4
2c66d0efcbd4
```
@ -115,90 +125,140 @@ If all goes well, you should be able to see the container image listed in the co
![image](/images/hellonode/image_10.png)
## Create your cluster
A cluster consists of a master API server and a set of worker VMs called nodes.
A cluster consists of a master API server and a set of worker VMs called nodes.
Create a cluster via the Console: *Compute > Container Engine > Container Clusters > New container cluster*. Leave all the options default, and you should get a Kubernetes cluster with three nodes, ready to receive your container image.
Create a cluster via the Console: *Compute > Container Engine > Container Clusters > New container cluster*. Set the name to 'hello-world', leaving all other options default. You should get a Kubernetes cluster with three nodes, ready to receive your container image.
![image](/images/hellonode/image_11.png)
Its now time to deploy your own containerized application to the Kubernetes cluster! Please ensure that you have [configured](https://cloud.google.com/container-engine/docs/before-you-begin#optional_set_gcloud_defaults) `kubectl` to use the cluster you just created.
Its now time to deploy your own containerized application to the Kubernetes cluster! Please ensure that you have [configured](https://cloud.google.com/container-engine/docs/clusters/operations#configuring_kubectl) `kubectl` to use the cluster you just created:
```shell
$ gcloud container clusters get-credentials hello-world
```
**The rest of this document requires both the kubernetes client and server version to be 1.2. Run `kubectl version` to see your current versions.** For 1.1 see [this document](https://github.com/kubernetes/kubernetes.github.io/blob/release-1.1/docs/hellonode.md).
## Create your pod
A kubernetes **pod** is a group of containers, tied together for the purposes of administration and networking. It can contain a single container or multiple.
A kubernetes **[pod](/docs/user-guide/pods/)** is a group of containers, tied together for the purposes of administration and networking. It can contain a single container or multiple.
Create a pod with the `kubectl run` command:
```shell
kubectl run hello-node \
--image=gcr.io/PROJECT_ID/hello-node:v1 \
--port=8080
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
hello-node hello-node gcr.io/..../hello-node:v1 run=hello-node 1
$ kubectl run hello-node --image=gcr.io/PROJECT_ID/hello-node:v1 --port=8080
deployment "hello-node" created
```
Now is probably a good time to run through some of the following interesting kubectl commands (none of these will change the state of the cluster, full documentation is available [here](https://cloud.google.com/container-engine/docs/kubectl/)):
As shown in the output, the `kubectl run` created a **[deployment](/docs/user-guide/deployments/)** object. Deployments are the recommended way for managing creation and scaling of pods. In this example, a new deployment manages a single pod replica running the *hello-node:v1* image.
To view the deployment we just created run:
```shell
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 1 1 1 1 3m
```
To view the pod created by the deployment run:
```shell
$ kubectl get pods
$ kubectl logs
$ kubectl cluster-info
$ kubectl config view
$ kubectl get events
NAME READY STATUS RESTARTS AGE
hello-node-714049816-ztzrb 1/1 Running 0 6m
```
To view the stdout / stderr from a pod (hello-node image has no output, so logs will be empty in this case) run:
```shell
kubectl logs <POD-NAME>
```
To view metadata about the cluster run:
```shell
kubectl cluster-info
```
To view cluster events run:
```shell
kubectl get events
```
To view the kubectl configuration run:
```shell
kubectl config view
```
Full documentation for kubectl commands is available **[here](/docs/user-guide/kubectl-overview/)**:
At this point you should have our container running under the control of Kubernetes but we still have to make it accessible to the outside world.
## Allow external traffic
By default, the pod is only accessible by its internal IP within the Kubernetes cluster. In order to make the `hello-node` container accessible from outside the kubernetes virtual network, you have to expose the pod as a kubernetes service.
By default, the pod is only accessible by its internal IP within the Kubernetes cluster. In order to make the `hello-node` container accessible from outside the kubernetes virtual network, you have to expose the pod as a kubernetes **[service](/docs/user-guide/services/)**.
From our development machine we can expose the pod with the `kubectl` expose command and the `--type="LoadBalancer"` flag which creates an external IP to accept traffic:
From our development machine we can expose the pod to the public internet using the `kubectl expose` command combined with the `--type="LoadBalancer"` flag. The flag is needed for the creation of an externally accessible ip:
```shell
kubectl expose rc hello-node --type="LoadBalancer"
kubectl expose deployment hello-node --type="LoadBalancer"
```
The flag used in this command specifies that well be using the load-balancer provided by the underlying infrastructure (in this case the [Compute Engine load balancer](https://cloud.google.com/compute/docs/load-balancing/)). The `rc` refers to the Kubernetes "replication controller" -- which is a Kubernetes service which controls load balancing and scaling behavior for your cluster.
**If this fails, make sure your client and server are both version 1.2. See the [Create your cluster](#create-your-cluster) section for details.**
The flag used in this command specifies that well be using the load-balancer provided by the underlying infrastructure (in this case the [Compute Engine load balancer](https://cloud.google.com/compute/docs/load-balancing/)). Note that we expose the deployment, and not the pod directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but we will add more replicas later).
The Kubernetes master creates the load balancer and related Compute Engine forwarding rules, target pools, and firewall rules to make the service fully accessible from outside of Google Cloud Platform.
To find the publicly-accessible IP address, ask `kubectl` to describe the `hello-node` cluster service:
To find the ip addresses associated with the service run:
```shell
kubectl get services hello-node
$ kubectl get services hello-node
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
hello-node 10.3.246.12 23.251.159.72 8080/TCP run=hello-node 53s
hello-node 10.3.246.12 8080/TCP run=hello-node 23s
```
Note there are 2 IP addresses listed, both serving port 8080. One is the internal IP that is only visible inside your cloud virtual network; the other is the external load-balanced IP. In this example, the external IP address is 23.251.159.72. Traffic to the load-balanced IP will be load balanced to the three nodes you provisioned when initially creating the cluster!
The `EXTERNAL_IP` may take several minutes to become available and visible. If the `EXTERNAL_IP` is missing, wait a few minutes and try again.
You should now be able to reach the service by pointing your browser to this address: http://<EXTERNAL_IP>**:8080**
```shell
$ kubectl get services hello-node
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
hello-node 10.3.246.12 23.251.159.72 8080/TCP run=hello-node 2m
```
Note there are 2 IP addresses listed, both serving port 8080. `CLUSTER_IP` is only visible inside your cloud virtual network. `EXTERNAL_IP` is externally accessible. In this example, the external IP address is 23.251.159.72.
You should now be able to reach the service by pointing your browser to this address: http://EXTERNAL_IP**:8080** or running `curl http://EXTERNAL_IP:8080`
![image](/images/hellonode/image_12.png)
## Scale up your website
One of the powerful features offered by Kubernetes is how easy it is to scale your application. Suppose you suddenly need more capacity for your application; you can simply tell the replication controller to manage a new number of replicas for your pod:
One of the powerful features offered by Kubernetes is how easy it is to scale your application. Suppose you suddenly need more capacity for your application; you can simply tell the deployment to manage a new number of replicas for your pod:
```shell
kubectl scale rc hello-node --replicas=4
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-node-6uzt8 1/1 Running 0 8m
hello-node-gxhty 1/1 Running 0 34s
hello-node-z2odh 1/1 Running 0 34s
kubectl scale deployment hello-node --replicas=4
```
You now have four replicas of your application, each running independently on the cluster with the load balancer you created earlier and serving traffic to all of them.
You now have four replicas of your application, each running independently on the cluster with the load balancer you created earlier and serving traffic to all of them.
```shell
kubectl get rc hello-node
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
hello-node hello-node gcr.io/..../hello-node:v1 run=hello-node 3
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 4 4 4 3 40m
```
```shell
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-node-714049816-g4azy 1/1 Running 0 1m
hello-node-714049816-rk0u6 1/1 Running 0 1m
hello-node-714049816-sh812 1/1 Running 0 1m
hello-node-714049816-ztzrb 1/1 Running 0 41m
```
Note the **declarative approach** here - rather than starting or stopping new instances you declare how many instances you want to be running. Kubernetes reconciliation loops simply make sure the reality matches what you requested and take action if needed.
@ -221,76 +281,116 @@ First, lets modify the application. On the development machine, edit server.j
We can now build and publish a new container image to the registry with an incremented tag:
```shell
docker build -t gcr.io/PROJECT_ID/hello-node:v2 .
docker push gcr.io/PROJECT_ID/hello-node:v2
docker build -t gcr.io/PROJECT_ID/hello-node:v2 .
gcloud docker push gcr.io/PROJECT_ID/hello-node:v2
```
Building and pushing this updated image should be much quicker as we take full advantage of the Docker cache.
Were now ready for kubernetes to smoothly update our replication controller to the new version of the application:
Were now ready for kubernetes to smoothly update our deployment to the new version of the application. In order to change
the image label for our running container, we will need to edit the existing *hello-node deployment* and change the image from
`gcr.io/PROJECT_ID/hello-node:v1` to `gcr.io/PROJECT_ID/hello-node:v2`. To do this, we will use the `kubectl edit` command.
This will open up a text editor displaying the full deployment yaml configuration. It isn't necessary to understand the full yaml config
right now, instead just understand that by updating the `spec.template.spec.containers.image` field in the config we are telling
the deployment to update the pods to use the new image.
```shell
kubectl rolling-update hello-node \
--image=gcr.io/PROJECT_ID/hello-node:v2 \
--update-period=2s
Creating hello-node-324d23dd3e0e2474d6b76dc599abb519
At beginning of loop: hello-node replicas: 2, hello-node-324d23dd3e0e2474d6b76dc599abb519 replicas: 1
...
At end of loop: hello-node replicas: 0, hello-node-324d23dd3e0e2474d6b76dc599abb519 replicas: 3
Update succeeded. Deleting old controller: hello-node
Renaming hello-node-324d23dd3e0e2474d6b76dc599abb519 to hello-node
hello-node
kubectl edit deployment hello-node
```
You should see in the standard output how the rolling update actually works:
```yaml
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: 2016-03-24T17:55:28Z
generation: 3
labels:
run: hello-node
name: hello-node
namespace: default
resourceVersion: "151017"
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/hello-node
uid: 981fe302-f1e9-11e5-9a78-42010af00005
spec:
replicas: 4
selector:
matchLabels:
run: hello-node
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: hello-node
spec:
containers:
- image: gcr.io/PROJECT_ID/hello-node:v1 # Update this line
imagePullPolicy: IfNotPresent
name: hello-node
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
dnsPolicy: ClusterFirst
restartPolicy: Always
securityContext: {}
terminationGracePeriodSeconds: 30
```
1. A new replication controller is created based on the new image
After making the change save and close the file.
2. The replica count on the new and old controllers is increased/decreased by one respectively until the desired number of replicas is reached
```
deployment "hello-node" edited
```
3. The original replication controller is deleted.
This updates the deployment with the new image, causing new pods to be created with the new image and old pods to be deleted.
While this is happening, the users of the services should not see any interruption. After a little while they will start accessing the new version of your application. You can find more details on rolling updates in [this documentation](https://cloud.google.com/container-engine/docs/rolling-updates).
```
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hello-node 4 5 4 3 1h
```
While this is happening, the users of the services should not see any interruption. After a little while they will start accessing the new version of your application. You can find more details in the [deployment documentation](/docs/user-guide/deployments/).
Hopefully with these deployment, scaling and update features youll agree that once youve setup your environment (your GKE/Kubernetes cluster here), Kubernetes is here to help you focus on the application rather than the infrastructure.
## Observe the Kubernetes Graphical dashboard (optional)
## Observe the Kubernetes Web UI (optional)
While logged into your development machine, execute the following commands:
With Kubernetes 1.2, a graphical web user interface (dashboard) has been introduced. It is enabled by default for 1.2 clusters.
This user interface allows you to get started quickly and enables some of the functionality found in the CLI as a more approachable and discoverable way of interacting with the system.
```shell
kubectl config view | grep "password"
password: vUYwC5ATJMWa6goh
$ kubectl cluster-info
...
KubeUI is running at https://<ip-address>/api/v1/proxy/namespaces/kube-system/services/kube-ui
...
```
Enjoy the Kubernetes graphical dashboard and use it for deploying containerized applications, as well as for monitoring and managing your clusters!
Navigate to the URL that is shown under after KubeUI is running at and log in with username "admin" and the password retrieved above and enjoy the Kubernetes graphical dashboard!
![image](/images/docs/ui-dashboard-cards-menu.png)
![image](/images/hellonode/image_14.png)
Learn more about the web interface by taking the [Dashboard tour](/docs/user-guide/ui/).
## That's it! Time to tear it down
That's it for the demo! So you don't leave this all running and incur charges, let's learn how to tear things down.
That's it for the demo! So you don't leave this all running and incur charges, let's learn how to tear things down.
First, delete the Service, which also deletes your external load balancer:
Delete the Deployment (which also deletes the running pods) and Service (which also deletes your external load balancer):
```shell
kubectl delete services hello-node
```
Delete the running pods:
```shell
kubectl delete rc hello-node
kubectl delete service,deployment hello-node
```
Delete your cluster:
```shell
gcloud container clusters delete hello-world
$ gcloud container clusters delete hello-world
Waiting for cluster deletion...done.
name: operation-xxxxxxxxxxxxxxxx
operationType: deleteCluster
@ -304,7 +404,7 @@ This deletes the Google Compute Engine instances that are running the cluster.
Finally delete the Docker registry storage bucket hosting your image(s) :
```shell
gsutil ls
$ gsutil ls
gs://artifacts.<PROJECT_ID>.appspot.com/
$ gsutil rm -r gs://artifacts.<PROJECT_ID>.appspot.com/
Removing gs://artifacts.<PROJECT_ID>.appspot.com/...

View File

@ -19,7 +19,7 @@ In the reference section, you can find reference documentation for Kubernetes AP
## Glossary
Explore the glossary of essential Kubernetes concepts. Some good starting points are the entries for [Pods](/docs/user-guide/pods/), [Nodes](/docs/user-guide/pods/), [Services](/docs/user-guide/services/), and [Replication Controllers](/docs/user-guide/replication-controller/).
Explore the glossary of essential Kubernetes concepts. Some good starting points are the entries for [Pods](/docs/user-guide/pods/), [Nodes](/docs/admin/nodes/), [Services](/docs/user-guide/services/), and [Replication Controllers](/docs/user-guide/replication-controller/).
## Design Docs

View File

@ -1,13 +1,6 @@
---
---
We have a wide variety of samples to choose from:
* "Clustered Application Samples" and "Persistent Volume Samples" provide some
examples that show how to implement some popular software packages such as OpenShift, Ceph, Cassandra, and WordPress. These guides
try to serve as canonical walkthroughs that help you use familiar packages with Kubernetes.
* "Mulit-tier Application Samples" are generally of a more contrived and instructional nature, highlighting key concepts that
you'll encounter when developing with Kubernetes, and teaching some principles of building Kubernetes applications.
We have a wide variety of samples to choose from.
## Recently updated samples

View File

@ -0,0 +1,3 @@
---
---
{% include templates/concept-overview.md %}

View File

@ -0,0 +1,3 @@
---
---
{% include templates/landing-page.md %}

View File

@ -0,0 +1,32 @@
---
---
{% assign concept="Replication Controller" %}
{% capture what_is %}
A Replication Controller does x and y and z...(etc, etc, text goes on)
{% endcapture %}
{% capture when_to_use %}
You should use Replication Controller when...
{% endcapture %}
{% capture when_not_to_use %}
You should not use Replication Controller if...
{% endcapture %}
{% capture status %}
The current status of Replication Controllers is...
{% endcapture %}
{% capture required_fields %}
* `kind`: Always `Pod`.
* `apiVersion`: Currently `v1`.
* `metadata`: An object containing:
* `name`: Required if `generateName` is not specified. The name of this pod.
It must be an
[RFC1035](https://www.ietf.org/rfc/rfc1035.txt) compatible value and be
unique within the namespace.
{% endcapture %}
{% include templates/concept-overview.md %}

View File

@ -0,0 +1,19 @@
---
---
# Template Demos
This page demonstrates new doc templates being worked on.
Click the headings to see the source of the template in GitHub.
## [Concept Overviews](https://github.com/kubernetes/kubernetes.github.io/blob/master/_includes/templates/concept-overview.md)
- [Blank page that is trying to use template](blank/)
- [Partially filled out page](partial/)
- [Completely filled out page](filledout/)
## [Landing Pages](https://github.com/kubernetes/kubernetes.github.io/blob/master/_includes/templates/landing-page.md)
- [Blank](blanklanding/)
- [Filled Out](landingpage/)

View File

@ -0,0 +1,53 @@
---
cards:
- progression: no
- card:
title: Mean Stack
image: /images/docs/meanstack/image_0.png
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Guestbook + Redis
image: /images/docs/redis.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Cassandra
image: /images/docs/cassandra.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: WordPress + MySQL
image: /images/docs/wordpress.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Mean Stack
image: /images/docs/meanstack/image_0.png
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Guestbook + Redis
image: /images/docs/redis.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Cassandra
image: /images/docs/cassandra.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: WordPress + MySQL
image: /images/docs/wordpress.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Mean Stack
image: /images/docs/meanstack/image_0.png
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Guestbook + Redis
image: /images/docs/redis.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: Cassandra
image: /images/docs/cassandra.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
- card:
title: WordPress + MySQL
image: /images/docs/wordpress.svg
description: Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum. Lorem ipsum dolor it verberum.
---
{% include templates/landing-page.md %}

View File

@ -0,0 +1,6 @@
---
---
{% assign concept="Replication Controller" %}
{% include templates/concept-overview.md %}

View File

@ -169,7 +169,7 @@ You have several options for connecting to nodes, pods and services from outside
access to ports on the node IP, or for debugging.
- Proxies may cause problems for some web applications.
- Only works for HTTP/HTTPS.
- Described [here](#discovering-builtin-services).
- Described [here](#manually-constructing-apiserver-proxy-urls).
- Access from a node or pod in the cluster.
- Run a pod, and then connect to a shell in it using [kubectl exec](/docs/user-guide/kubectl/kubectl_exec).
Connect to other nodes, pods, and services from that shell.
@ -275,4 +275,4 @@ There are several different proxies you may encounter when using Kubernetes:
- implementation varies by cloud provider.
Kubernetes users will typically not need to worry about anything other than the first two types. The cluster admin
will typically ensure that the latter types are setup correctly.
will typically ensure that the latter types are setup correctly.

View File

@ -22,14 +22,17 @@ server.
## Resource Requests and Limits of Pod and Container
Each container of a Pod can optionally specify `spec.container[].resources.limits.cpu` and/or
`spec.container[].resources.limits.memory` and/or `spec.container[].resources.requests.cpu`
and/or `spec.container[].resources.requests.memory`.
Each container of a pod can optionally specify one or more of the following:
* `spec.container[].resources.limits.cpu`
* `spec.container[].resources.limits.memory`
* `spec.container[].resources.requests.cpu`
* `spec.container[].resources.requests.memory`.
Specifying resource requests and/or limits is optional. In some clusters, unset limits or requests
may be replaced with default values when a pod is created or updated. The default value depends on
how the cluster is configured. If value of requests is not specified, they are set to be equal
to limits by default. Please note that resource limits must be greater than or equal to resource
how the cluster is configured. If the requests values are not specified, they are set to be equal
to the limits values by default. Please note that limits must always be greater than or equal to
requests.
Although requests/limits can only be specified on individual containers, it is convenient to talk
@ -171,7 +174,7 @@ Here you can see from the `Allocated resources` section that that a pod which as
Looking at the `Pods` section, you can see which pods are taking up space on the node.
The [resource quota](/docs/admin/resource-quota) feature can be configured
The [resource quota](/docs/admin/resourcequota/) feature can be configured
to limit the total amount of resources that can be consumed. If used in conjunction
with namespaces, it can prevent one team from hogging all the resources.
@ -222,10 +225,10 @@ The `Restart Count: 5` indicates that the `simmemleak` container in this pod wa
You can call `get pod` with the `-o go-template=...` option to fetch the status of previously terminated containers:
```shell
```shell{% raw %}
[13:59:01] $ ./cluster/kubectl.sh get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-60xbc
Container Name: simmemleak
LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]
LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]]{% endraw %}
```
We can see that this container was terminated because `reason:OOM Killed`, where *OOM* stands for Out Of Memory.
@ -246,4 +249,4 @@ Currently, one unit of CPU means different things on different cloud providers,
machine types within the same cloud providers. For example, on AWS, the capacity of a node
is reported in [ECUs](http://aws.amazon.com/ec2/faqs/), while in GCE it is reported in logical
cores. We plan to revise the definition of the cpu resource to allow for more consistency
across providers and platforms.
across providers and platforms.

View File

@ -79,7 +79,7 @@ This document is meant to highlight and consolidate in one place configuration b
controller 'version names'. A desired state of an object is described by a Deployment, and if
changes to that spec are _applied_, the deployment controller changes the actual state to the
desired state at a controlled rate. (Deployment objects are currently part of the [`extensions`
API Group](/docs/api/#api-groups), and are not enabled by default.)
API Group](/docs/api/#api-groups).)
- You can manipulate labels for debugging. Because Kubernetes replication controllers and services
match to pods using labels, this allows you to remove a pod from being considered by a
@ -100,6 +100,9 @@ This document is meant to highlight and consolidate in one place configuration b
address this by ensuring that any updates to an image bump the image tag as well (e.g.
`myimage:v2`), and ensuring that your configs point to the correct version.
**Note:** you should avoid using `:latest` tag when deploying containers in production, because this makes it hard
to track which version of the image is running and hard to roll back.
## Using kubectl
- Use `kubectl create -f <directory>` where possible. This looks for config objects in all `.yaml`, `.yml`, and `.json` files in `<directory>` and passes them to `create`.
@ -108,6 +111,6 @@ This document is meant to highlight and consolidate in one place configuration b
- Use kubectl bulk operations (via files and/or labels) for get and delete. See [label selectors](/docs/user-guide/labels/#label-selectors) and [using labels effectively](/docs/user-guide/managing-deployments/#using-labels-effectively).
- Use `kubectl run` and `expose` to quickly create and expose single container replication controllers. See the [quick start guide](/docs/user-guide/quick-start/) for an example.
- Use `kubectl run` and `expose` to quickly create and expose single container Deployments. See the [quick start guide](/docs/user-guide/quick-start/) for an example.

View File

@ -22,8 +22,8 @@ You can use `kubectl` to see information about the ConfigMap:
```shell
$ kubectl get configmap
NAME DATA
test-secret 2
NAME DATA AGE
test-configmap 2 6s
$ kubectl describe configMap test-configmap
Name: test-configmap
@ -39,7 +39,7 @@ data-2: 7 bytes
View the values of the keys with `kubectl get`:
```shell
$ cluster/kubectl.sh get configmaps test-configmap -o yaml
$ kubectl get configmaps test-configmap -o yaml
apiVersion: v1
data:
data-1: value-1
@ -66,23 +66,24 @@ $ kubectl create -f docs/user-guide/configmap/env-pod.yaml
This pod runs the `env` command to display the environment of the container:
```shell
$ kubectl logs secret-test-pod
$ kubectl logs config-env-test-pod | grep KUBE_CONFIG
KUBE_CONFIG_1=value-1
KUBE_CONFIG_2=value-2
```
## Step Three: Create a pod that sets the command line using ConfigMap
Use the [`command-pod.yaml`](env-pod.yaml) file to create a Pod with a container
Use the [`command-pod.yaml`](command-pod.yaml) file to create a Pod with a container
whose command is injected with the keys of a ConfigMap
```shell
$ kubectl create -f docs/user-guide/configmap/env-pod.yaml
$ kubectl create -f docs/user-guide/configmap/command-pod.yaml
```
This pod runs an `echo` command to display the keys:
```shell
$ kubectl logs config-cmd-test-pod
value-1 value-2
```
@ -97,5 +98,6 @@ $ kubectl create -f docs/user-guide/configmap/volume-pod.yaml
This pod runs a `cat` command to print the value of one of the keys in the volume:
```shell
$ kubectl logs config-volume-test-pod
value-1
```
```

View File

@ -91,7 +91,7 @@ content of the file.
Let's take a look at the ConfigMap that this command created:
```shell
$ cluster/kubectl.sh describe configmaps game-config
$ kubectl describe configmaps game-config
Name: game-config
Namespace: default
Labels: <none>
@ -147,7 +147,7 @@ following command yields equivalent results to the above example:
```shell
$ kubectl create configmap game-config-2 --from-file=docs/user-guide/configmap/kubectl/game.properties --from-file=docs/user-guide/configmap/kubectl/ui.properties
$ cluster/kubectl.sh get configmaps game-config-2 -o yaml
$ kubectl get configmaps game-config-2 -o yaml
```
```yaml
@ -237,7 +237,7 @@ metadata:
### Use-Case: Consume ConfigMap in environment variables
ConfigMaps can be used to populate the value of command line arguments. As an example, consider
ConfigMaps can be used to populate environment variables. As an example, consider
the following ConfigMap:
```yaml
@ -267,13 +267,13 @@ spec:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-configmap
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: data-1
key: special.type
restartPolicy: Never
```
@ -318,13 +318,13 @@ spec:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-configmap
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: data-1
key: special.type
restartPolicy: Never
```
@ -427,25 +427,23 @@ ConfigMap instance with it:
```shell
$ kubectl create configmap example-redis-config --from-file=docs/user-guide/configmap/redis/redis-config
$ kubectl get configmap redis-config -o yaml
$ kubectl get configmap example-redis-config -o yaml
```
```yaml
{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"name": "example-redis-config",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/configmaps/example-redis-config",
"uid": "07fd0419-d97b-11e5-b443-68f728db1985",
"resourceVersion": "15",
"creationTimestamp": "2016-02-22T15:43:34Z"
},
"data": {
"redis-config": "maxmemory 2mb\nmaxmemory-policy allkeys-lru\n"
}
}
apiVersion: v1
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
creationTimestamp: 2016-03-30T18:14:41Z
name: example-redis-config
namespace: default
resourceVersion: "24686"
selfLink: /api/v1/namespaces/default/configmaps/example-redis-config
uid: 460a2b6e-f6a3-11e5-8ae5-42010af00002
```
Now, let's create a pod that uses this config:

View File

@ -117,7 +117,7 @@ The `READY` column shows how many containers in the pod are running.
Almost immediately after it starts running, this command will terminate. `kubectl` shows that the container is no longer running and displays the exit status:
```shell
$ kubectl get pods
$ kubectl get pods --show-all
NAME READY STATUS RESTARTS AGE
hello-world 0/1 ExitCode:0 0 15s
```

View File

@ -18,41 +18,24 @@ This guide uses a simple nginx server to demonstrate proof of concept. The same
We did this in a previous example, but lets do it once again and focus on the networking perspective. Create an nginx pod, and note that it has a container port specification:
```yaml
$ cat nginxrc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
```
{% include code.html language="yaml" file="run-my-nginx.yaml" ghlink="/docs/user-guide/run-my-nginx.yaml" %}
This makes it accessible from any node in your cluster. Check the nodes the pod is running on:
```shell
$ kubectl create -f ./nginxrc.yaml
$ kubectl get pods -l app=nginx -o wide
my-nginx-6isf4 1/1 Running 0 2h e2e-test-beeps-node-93ly
my-nginx-t26zt 1/1 Running 0 2h e2e-test-beeps-node-93ly
$ kubectl create -f ./run-my-nginx.yaml
$ kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s kubernetes-minion-ljyd
```
Check your pods' IPs:
```shell
$ kubectl get pods -l app=nginx -o json | grep podIP
"podIP": "10.245.0.15",
"podIP": "10.245.0.14",
$ kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.244.3.4
podIP: 10.244.2.5
```
You should be able to ssh into any node in your cluster and curl both IPs. Note that the containers are *not* using port 80 on the node, nor are there any special NAT rules to route traffic to the pod. This means you can run multiple nginx pods on the same node all using the same containerPort and access them from any other pod or node in your cluster using IP. Like Docker, ports can still be published to the host node's interface(s), but the need for this is radically diminished because of the networking model.
@ -61,59 +44,51 @@ You can read more about [how we achieve this](/docs/admin/networking/#how-to-ach
## Creating a Service
So we have pods running nginx in a flat, cluster wide, address space. In theory, you could talk to these pods directly, but what happens when a node dies? The pods die with it, and the replication controller will create new ones, with different IPs. This is the problem a Service solves.
So we have pods running nginx in a flat, cluster wide, address space. In theory, you could talk to these pods directly, but what happens when a node dies? The pods die with it, and the Deployment will create new ones, with different IPs. This is the problem a Service solves.
A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.
You can create a Service for your 2 nginx replicas with the following yaml:
You can create a Service for your 2 nginx replicas with `kubectl expose`:
```yaml
$ cat nginxsvc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginxsvc
labels:
app: nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
app: nginx
```shell
$ kubectl expose deployment/my-nginx
service "my-nginx" exposed
```
This is equivalent to `kubectl create -f` the following yaml:
{% include code.html language="yaml" file="nginx-svc.yaml" ghlink="/docs/user-guide/nginx-svc.yaml" %}
This specification will create a Service which targets TCP port 80 on any Pod with the `app=nginx` label, and expose it on an abstracted Service port (`targetPort`: is the port the container accepts traffic on, `port`: is the abstracted Service port, which can be any port other pods use to access the Service). View [service API object](/docs/api-reference/v1/definitions/#_v1_service) to see the list of supported fields in service definition.
Check your Service:
```shell
$ kubectl get svc
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
kubernetes 10.179.240.1 <none> 443/TCP <none> 8d
nginxsvc 10.179.252.126 122.222.183.144 80/TCP,81/TCP,82/TCP run=nginx2 11m
$ kubectl get svc my-nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx 10.0.162.149 <none> 80/TCP 21s
```
As mentioned previously, a Service is backed by a group of pods. These pods are exposed through `endpoints`. The Service's selector will be evaluated continuously and the results will be POSTed to an Endpoints object also named `nginxsvc`. When a pod dies, it is automatically removed from the endpoints, and new pods matching the Service's selector will automatically get added to the endpoints. Check the endpoints, and note that the IPs are the same as the pods created in the first step:
As mentioned previously, a Service is backed by a group of pods. These pods are exposed through `endpoints`. The Service's selector will be evaluated continuously and the results will be POSTed to an Endpoints object also named `my-nginx`. When a pod dies, it is automatically removed from the endpoints, and new pods matching the Service's selector will automatically get added to the endpoints. Check the endpoints, and note that the IPs are the same as the pods created in the first step:
```shell
$ kubectl describe svc nginxsvc
Name: nginxsvc
$ kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: app=nginx
Selector: app=nginx
Labels: run=my-nginx
Selector: run=my-nginx
Type: ClusterIP
IP: 10.0.116.146
Port: <unnamed> 80/TCP
Endpoints: 10.245.0.14:80,10.245.0.15:80
IP: 10.0.162.149
Port: <unset> 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
No events.
$ kubectl get ep
NAME ENDPOINTS
nginxsvc 10.245.0.14:80,10.245.0.15:80
$ kubectl get ep my-nginx
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
```
You should now be able to curl the nginx Service on `10.0.116.146:80` from any node in your cluster. Note that the Service IP is completely virtual, it never hits the wire, if you're curious about how this works you can read more about the [service proxy](/docs/user-guide/services/#virtual-ips-and-service-proxies).
You should now be able to curl the nginx Service on `<CLUSTER-IP>:<PORT>` from any node in your cluster. Note that the Service IP is completely virtual, it never hits the wire, if you're curious about how this works you can read more about the [service proxy](/docs/user-guide/services/#virtual-ips-and-service-proxies).
## Accessing the Service
@ -121,28 +96,35 @@ Kubernetes supports 2 primary modes of finding a Service - environment variables
### Environment Variables
When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service. This introduces an ordering problem. To see why, inspect the environment of your running nginx pods:
When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service. This introduces an ordering problem. To see why, inspect the environment of your running nginx pods (your pod name will be different):
```shell
$ kubectl exec my-nginx-6isf4 -- printenv | grep SERVICE
$ kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
```
Note there's no mention of your Service. This is because you created the replicas before the Service. Another disadvantage of doing this is that the scheduler might put both pods on the same machine, which will take your entire Service down if it dies. We can do this the right way by killing the 2 pods and waiting for the replication controller to recreate them. This time around the Service exists *before* the replicas. This will given you scheduler level Service spreading of your pods (provided all your nodes have equal capacity), as well as the right environment variables:
Note there's no mention of your Service. This is because you created the replicas before the Service. Another disadvantage of doing this is that the scheduler might put both pods on the same machine, which will take your entire Service down if it dies. We can do this the right way by killing the 2 pods and waiting for the Deployment to recreate them. This time around the Service exists *before* the replicas. This will given you scheduler level Service spreading of your pods (provided all your nodes have equal capacity), as well as the right environment variables:
```shell
$ kubectl scale rc my-nginx --replicas=0; kubectl scale rc my-nginx --replicas=2;
$ kubectl get pods -l app=nginx -o wide
NAME READY STATUS RESTARTS AGE NODE
my-nginx-5j8ok 1/1 Running 0 2m node1
my-nginx-90vaf 1/1 Running 0 2m node2
$ kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
$ kubectl exec my-nginx-5j8ok -- printenv | grep SERVICE
$ kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s kubernetes-minion-905m
```
You may notice that the pods have different names, since they are killed and recreated.
```shell
$ kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
NGINXSVC_SERVICE_HOST=10.0.116.146
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
NGINXSVC_SERVICE_PORT=80
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443
```
### DNS
@ -151,43 +133,27 @@ Kubernetes offers a DNS cluster addon Service that uses skydns to automatically
```shell
$ kubectl get services kube-dns --namespace=kube-system
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
kube-dns 10.179.240.10 <none> 53/UDP,53/TCP k8s-app=kube-dns 8d
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns 10.0.0.10 <none> 53/UDP,53/TCP 8m
```
If it isn't running, you can [enable it](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/README.md#how-do-i-configure-it). The rest of this section will assume you have a Service with a long lived IP (nginxsvc), and a dns server that has assigned a name to that IP (the kube-dns cluster addon), so you can talk to the Service from any pod in your cluster using standard methods (e.g. gethostbyname). Let's create another pod to test this:
```yaml
$ cat curlpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: curlpod
spec:
containers:
- image: radial/busyboxplus:curl
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: curlcontainer
restartPolicy: Always
```
And perform a lookup of the nginx Service
If it isn't running, you can [enable it](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/README.md#how-do-i-configure-it). The rest of this section will assume you have a Service with a long lived IP (my-nginx), and a dns server that has assigned a name to that IP (the kube-dns cluster addon), so you can talk to the Service from any pod in your cluster using standard methods (e.g. gethostbyname). Let's run another curl application to test this:
```shell
$ kubectl create -f ./curlpod.yaml
default/curlpod
$ kubectl get pods curlpod
NAME READY STATUS RESTARTS AGE
curlpod 1/1 Running 0 18s
$ kubectl run curl --image=radial/busyboxplus:curl -i --tty
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
```
$ kubectl exec curlpod -- nslookup nginxsvc
Then, hit enter and run `nslookup my-nginx`:
```shell
[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: nginxsvc
Address 1: 10.0.116.146
Name: my-nginx
Address 1: 10.0.162.149
```
## Securing the Service
@ -212,73 +178,27 @@ nginxsecret Opaque 2
Now modify your nginx replicas to start a https server using the certificate in the secret, and the Service, to expose both ports (80 and 443):
```yaml
$ cat nginx-app.yaml
apiVersion: v1
kind: Service
metadata:
name: nginxsvc
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
name: http
- port: 443
protocol: TCP
name: https
selector:
app: nginx
---
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: nginxhttps
image: bprashanth/nginxhttps:1.0
ports:
- containerPort: 443
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
```
{% include code.html language="yaml" file="nginx-secure-app.yaml" ghlink="/docs/user-guide/nginx-secure-app" %}
Noteworthy points about the nginx-app manifest:
Noteworthy points about the nginx-secure-app manifest:
- It contains both rc and service specification in the same file
- The [nginx server](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/https-nginx/default.conf) serves http traffic on port 80 and https traffic on 443, and nginx Service exposes both ports.
- Each container has access to the keys through a volume mounted at /etc/nginx/ssl. This is setup *before* the nginx server is started.
```shell
$ kubectl apply -f ./nginx-secure-app.yaml
$ kubectl delete rc,svc -l app=nginx; kubectl create -f ./nginx-app.yaml
replicationcontrollers/my-nginx
services/nginxsvc
services/nginxsvc
replicationcontrollers/my-nginx
service "my-nginx" configured
deployment "my-nginx" configured
```
At this point you can reach the nginx server from any node.
```shell
$ kubectl get pods -o json | grep -i podip
"podIP": "10.1.0.80",
node $ curl -k https://10.1.0.80
$ kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
```
@ -287,41 +207,15 @@ Note how we supplied the `-k` parameter to curl in the last step, this is becaus
so we have to tell curl to ignore the CName mismatch. By creating a Service we linked the CName used in the certificate with the actual DNS name used by pods during Service lookup.
Lets test this from a pod (the same secret is being reused for simplicity, the pod only needs nginx.crt to access the Service):
```shell
$ cat curlpod.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: curlrc
spec:
replicas: 1
template:
metadata:
labels:
app: curlpod
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: curlpod
command:
- sh
- -c
- while true; do sleep 1; done
image: radial/busyboxplus:curl
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
{% include code.html language="yaml" file="curlpod.yaml" ghlink="/docs/user-guide/curlpod.yaml" %}
```shell
$ kubectl create -f ./curlpod.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
curlpod 1/1 Running 0 2m
my-nginx-7006w 1/1 Running 0 24m
$ kubectl exec curlpod -- curl https://nginxsvc --cacert /etc/nginx/ssl/nginx.crt
$ kubectl exec curlpod -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
...
<title>Welcome to nginx!</title>
...
@ -332,62 +226,62 @@ $ kubectl exec curlpod -- curl https://nginxsvc --cacert /etc/nginx/ssl/nginx.cr
For some parts of your applications you may want to expose a Service onto an external IP address. Kubernetes supports two ways of doing this: NodePorts and LoadBalancers. The Service created in the last section already used `NodePort`, so your nginx https replica is ready to serve traffic on the internet if your node has a public IP.
```shell
$ kubectl get svc nginxsvc -o json | grep -i nodeport -C 5
{
"name": "http",
"protocol": "TCP",
"port": 80,
"targetPort": 80,
"nodePort": 32188
},
{
"name": "https",
"protocol": "TCP",
"port": 443,
"targetPort": 443,
"nodePort": 30645
}
$ kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
ports:
- name: http
nodePort: 31704
port: 8080
protocol: TCP
targetPort: 80
- name: https
nodePort: 32453
port: 443
protocol: TCP
targetPort: 443
selector:
run: my-nginx
$ kubectl get nodes -o json | grep ExternalIP -C 2
{
"type": "ExternalIP",
"address": "104.197.63.17"
}
$ kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
},
{
"type": "ExternalIP",
"address": "104.154.89.170"
}
$ curl https://104.197.63.17:30645 -k
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>
```
Lets now recreate the Service to use a cloud load balancer, just change the `Type` of Service in the nginx-app.yaml from `NodePort` to `LoadBalancer`:
Lets now recreate the Service to use a cloud load balancer, just change the `Type` of `my-nginx` Service from `NodePort` to `LoadBalancer`:
```shell
$ kubectl delete rc,svc -l app=nginx
$ kubectl create -f ./nginx-app.yaml
$ kubectl get svc nginxsvc
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
nginxsvc 10.179.252.126 162.222.184.144 80/TCP,81/TCP,82/TCP run=nginx2 13m
$ kubectl edit svc my-nginx
$ kubectl get svc my-nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx 10.0.162.149 162.222.184.144 80/TCP,81/TCP,82/TCP 21s
$ curl https://162.22.184.144 -k
$ curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
```
The IP address in the `EXTERNAL_IP` column is the one that is available on the public internet. The `CLUSTER_IP` is only available inside your
The IP address in the `EXTERNAL-IP` column is the one that is available on the public internet. The `CLUSTER-IP` is only available inside your
cluster/private cloud network.
Note that on AWS, type `LoadBalancer` creates an ELB, which uses a (long)
hostname, not an IP. It's too long to fit in the standard `kubectl get svc`
output, in fact, so you'll need to do `kubectl describe service nginxsvc` to
output, in fact, so you'll need to do `kubectl describe service my-nginx` to
see it. You'll see something like this:
```shell
> kubectl describe service nginxsvc
$ kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...

View File

@ -1,46 +1,46 @@
---
---
---
---
kubectl port-forward forwards connections to a local port to a port on a pod. Its man page is available [here](/docs/user-guide/kubectl/kubectl_port-forward). Compared to [kubectl proxy](/docs/user-guide/accessing-the-cluster/#using-kubectl-proxy), `kubectl port-forward` is more generic as it can forward TCP traffic while `kubectl proxy` can only forward HTTP traffic. This guide demonstrates how to use `kubectl port-forward` to connect to a Redis database, which may be useful for database debugging.
## Creating a Redis master
```shell
```shell
$ kubectl create examples/redis/redis-master.yaml
pods/redis-master
```
```
wait until the Redis master pod is Running and Ready,
```shell
```shell
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-master 2/2 Running 0 41s
```
```
## Connecting to the Redis master[a]
The Redis master is listening on port 6397, to verify this,
The Redis master is listening on port 6379, to verify this,
```shell
```shell{% raw %}
$ kubectl get pods redis-master -t='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
6379
```
6379{% endraw %}
```
then we forward the port 6379 on the local workstation to the port 6379 of pod redis-master,
```shell
```shell
$ kubectl port-forward redis-master 6379:6379
I0710 14:43:38.274550 3655 portforward.go:225] Forwarding from 127.0.0.1:6379 -> 6379
I0710 14:43:38.274797 3655 portforward.go:225] Forwarding from [::1]:6379 -> 6379
```
```
To verify the connection is successful, we run a redis-cli on the local workstation,
```shell
```shell
$ redis-cli
127.0.0.1:6379> ping
PONG
```
Now one can debug the database from the local workstation.
```
Now one can debug the database from the local workstation.

View File

@ -48,7 +48,7 @@ There are currently two container hooks that are surfaced to containers:
*PostStart*
This hook is sent immediately after a container is created.  It notifies the container that it has been created.  No parameters are passed to the handler.
This hook is sent immediately after a container is created.  It notifies the container that it has been created.  No parameters are passed to the handler. It is NOT guaranteed that the hook will execute before the container entrypoint.
*PreStop*

View File

@ -0,0 +1,25 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: curl-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: curlpod
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: curlpod
command:
- sh
- -c
- while true; do sleep 1; done
image: radial/busyboxplus:curl
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume

View File

@ -45,7 +45,7 @@ case you can try several things:
kubectl get nodes -o yaml | grep '\sname\|cpu\|memory'
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, cap: .status.capacity}'
The [resource quota](/docs/admin/resource-quota/)
The [resource quota](/docs/admin/resourcequota/)
feature can be configured to limit the total amount of
resources that can be consumed. If used in conjunction with namespaces, it can
prevent one team from hogging all the resources.

View File

@ -3,7 +3,7 @@
An issue that comes up rather frequently for new installations of Kubernetes is
that `Services` are not working properly. You've run all your `Pod`s and
`ReplicationController`s, but you get no response when you try to access them.
`Deployment`s, but you get no response when you try to access them.
This document will hopefully help you to figure out what's going wrong.
* TOC
@ -40,37 +40,27 @@ OUTPUT
## Running commands in a Pod
For many steps here you will want to see what a `Pod` running in the cluster
sees. Kubernetes does not directly support interactive `Pod`s (yet), but you can
approximate it:
sees. You can start a busybox `Pod` and run commands in it:
```shell
$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: busybox-sleep
spec:
containers:
- name: busybox
image: busybox
args:
- sleep
- "1000000"
EOF
pods/busybox-sleep
$ kubectl run -i --tty busybox --image=busybox --generator="run-pod/v1"
Waiting for pod default/busybox to be running, status is Pending, pod ready: false
Hit enter for command prompt
/ #
```
Now, when you need to run a command (even an interactive shell) in a `Pod`-like
context, use:
If you already have a running `Pod`, run a command in it using:
```shell
$ kubectl exec busybox-sleep -- <COMMAND>
$ kubectl exec <POD-NAME> -c <CONTAINER-NAME> -- <COMMAND>
```
or
or run an interactive shell with:
```shell
$ kubectl exec -ti busybox-sleep sh
$ kubectl exec -ti <POD-NAME> -c <CONTAINER-NAME> sh
/ #
```
@ -85,16 +75,16 @@ $ kubectl run hostnames --image=gcr.io/google_containers/serve_hostname \
--labels=app=hostnames \
--port=9376 \
--replicas=3
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
hostnames hostnames gcr.io/google_containers/serve_hostname app=hostnames 3
deployment "hostnames" created
```
Note that this is the same as if you had started the `ReplicationController` with
`kubectl` commands will print the type and name of the resource created or mutated, which can then be used in subsequent commands.
Note that this is the same as if you had started the `Deployment` with
the following YAML:
```yaml
apiVersion: v1
kind: ReplicationController
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hostnames
spec:
@ -118,10 +108,10 @@ Confirm your `Pod`s are running:
```shell
$ kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-0uton 1/1 Running 0 12s
hostnames-bvc05 1/1 Running 0 12s
hostnames-yp2kp 1/1 Running 0 12s
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 2m
hostnames-632524106-ly40y 1/1 Running 0 2m
hostnames-632524106-tlaok 1/1 Running 0 2m
```
## Does the Service exist?
@ -156,7 +146,7 @@ So we have a culprit, let's create the `Service`. As before, this is for the
walk-through - you can use your own `Service`'s details here.
```shell
$ kubectl expose rc hostnames --port=80 --target-port=9376
$ kubectl expose deployment hostnames --port=80 --target-port=9376
service "hostnames" exposed
```
@ -164,8 +154,8 @@ And read it back, just to be sure:
```shell
$ kubectl get svc hostnames
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
hostnames 10.0.0.1 <none> 80/TCP run=hostnames 1h
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hostnames 10.0.0.226 <none> 80/TCP 5s
```
As before, this is the same as if you had started the `Service` with YAML:
@ -580,4 +570,4 @@ Contact us on
## More information
Visit [troubleshooting document](/docs/troubleshooting/) for more information.
Visit [troubleshooting document](/docs/troubleshooting/) for more information.

View File

@ -84,9 +84,9 @@ my-nginx 2 2 2 2 2m my-nginx
More importantly, the pod template's labels are used to create a [`selector`](/docs/user-guide/labels/#label-selectors) that will match pods carrying those labels. You can see this field by requesting it using the [Go template output format of `kubectl get`](/docs/user-guide/kubectl/kubectl_get):
```shell
```shell{% raw %}
$ kubectl get deployment/my-nginx -o template --template="{{.spec.selector}}"
map[matchLabels:map[run:my-nginx]]
map[matchLabels:map[run:my-nginx]]{% endraw %}
```
You could also specify the `selector` explicitly, such as if you wanted to specify labels in the pod template that you didn't want to select on, but you should ensure that the selector will match the labels of the pods created from the pod template, and that it won't match pods created by other Deployments. The most straightforward way to ensure the latter is to create a unique label value for the Deployment, and to specify it in both the pod template's labels and in the selector's

View File

@ -6,23 +6,24 @@
## What is a _Deployment_?
A _Deployment_ provides declarative updates for Pods and ReplicaSets.
You only need to describe the desired state in a Deployment object, and the deployment
A _Deployment_ provides declarative updates for [Pods](/docs/user-guide/pods/) and [Replica Sets](/docs/user-guide/replicasets/) (the next-generation Replication Controller).
You only need to describe the desired state in a Deployment object, and the Deployment
controller will change the actual state to the desired state at a controlled rate for you.
You can define Deployments to create new resources, or replace existing ones
by new ones.
A typical use case is:
* Create a Deployment to bring up a replica set and pods.
* Later, update that Deployment to recreate the pods (for example, to use a new image).
* Create a Deployment to bring up a Replica Set and Pods.
* Check the status of a Deployment to see if it succeeds or not.
* Later, update that Deployment to recreate the Pods (for example, to use a new image).
* Rollback to an earlier Deployment revision if the current Deployment isn't stable.
* Pause and resume a Deployment.
## Creating a Deployment
Here is an example Deployment. It creates a replica set to
bring up 3 nginx pods.
Here is an example Deployment. It creates a Replica Set to
bring up 3 nginx Pods.
{% include code.html language="yaml" file="nginx-deployment.yaml" ghlink="/docs/user-guide/nginx-deployment.yaml" %}
@ -53,7 +54,7 @@ NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s
```
This indicates that the Deployment has created all three replicas, and all replicas are up-to-date (contains the latest pod template) and available (pod status is ready for at least deployment's `.spec.minReadySeconds`). Running `kubectl get rs` and `kubectl get pods` will show the replica set (RS) and pods created.
This indicates that the Deployment has created all three replicas, and all replicas are up-to-date (contains the latest pod template) and available (pod status is ready for at least Deployment's `.spec.minReadySeconds`). Running `kubectl get rs` and `kubectl get pods` will show the Replica Set (RS) and Pods created.
```shell
$ kubectl get rs
@ -61,7 +62,7 @@ NAME DESIRED CURRENT AGE
nginx-deployment-2035384211 3 3 18s
```
You may notice that the name of the replica set is always `<the name of the Deployment>-<hash value of the pod template>`.
You may notice that the name of the Replica Set is always `<the name of the Deployment>-<hash value of the pod template>`.
```shell
$ kubectl get pods --show-labels
@ -71,13 +72,43 @@ nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
```
The created replica set will ensure that there are three nginx pods at all times.
The created Replica Set will ensure that there are three nginx Pods at all times.
## The Status of a Deployment
After creating or updating a Deployment, you would want to confirm whether it succeeded or not. The best way to do this is through checking its status.
To verify if the above Deployment succeeded or not, first compare the `.metadata.generation` and `.status.observedGeneration` of the Deployment:
```shell
$ kubectl get deployment/nginx-deployment -o yaml | grep [Gg]eneration
generation: 2
observedGeneration: 2
```
When `observedGeneration` >= `generation`, the Deployment controller has observed current Deployment; if not, wait for a few more seconds.
Once the above condition is met, check the Deployment's up-to-date replicas (`.status.updatedReplicas`) and see if it matches the desired replicas (`.spec.replicas`):
```shell
$ kubectl get deployment/nginx-deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 9m
```
Additionally, if you set `.spec.minReadySeconds`, you would also want to check if the available replicas (`.status.availableReplicas`) matches the desired replicas too.
**Note:** It's impossible to know whether a Deployment will ever succeed, so one has to timeout and give up at some point.
## Updating a Deployment
Suppose that we now want to update the nginx pods to start using the `nginx:1.9.1` image
Suppose that we now want to update the nginx Pods to start using the `nginx:1.9.1` image
instead of the `nginx:1.7.9` image.
For this, we update our deployment file as follows:
**Note:** a Deployment's rollout is triggered if and only if the Deployment's pod template (i.e. `.spec.template`) is changed,
e.g. updating labels or container images of the template. Other updates, such as scaling the Deployment, will not trigger a rollout.
First, we update our Deployment configuration as follows:
{% include code.html language="yaml" file="new-nginx-deployment.yaml" ghlink="/docs/user-guide/new-nginx-deployment.yaml" %}
@ -103,9 +134,9 @@ NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 0 3 20s
```
The 0 number of up-to-date replicas indicates that the deployment hasn't updated the replicas to the latest configuration. The current replicas indicates the total replicas (3 with old configuration and 0 with new configuration) this Deployment manages, and the available replicas indicates the number of current replicas that are available.
The 0 number of up-to-date replicas indicates that the Deployment hasn't updated the replicas to the latest configuration. The current replicas indicates the total replicas (3 with old configuration and 0 with new configuration) this Deployment manages, and the available replicas indicates the number of current replicas that are available.
The Deployment will update all the pods in a few seconds.
The Deployment will update all the Pods in a few seconds.
```shell
$ kubectl get deployments
@ -113,7 +144,7 @@ NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 36s
```
We can run `kubectl get rs` to see that the Deployment updated the pods by creating a new replica set and scaling it up to 3 replicas, as well as scaling down the old replica set to 0 replicas.
We can run `kubectl get rs` to see that the Deployment updated the Pods by creating a new Replica Set and scaling it up to 3 replicas, as well as scaling down the old Replica Set to 0 replicas.
```shell
$ kubectl get rs
@ -122,7 +153,7 @@ nginx-deployment-1564180365 3 3 6s
nginx-deployment-2035384211 0 0 36s
```
Running `get pods` should now show only the new pods:
Running `get pods` should now show only the new Pods:
```shell
$ kubectl get pods
@ -132,17 +163,17 @@ nginx-deployment-1564180365-nacti 1/1 Running 0 14s
nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
```
Next time we want to update these pods, we only need to update and re-apply the Deployment again.
Next time we want to update these Pods, we only need to update and re-apply the Deployment again.
Deployment can ensure that only a certain number of pods may be down while they are being updated. By
default, it ensures that at least 1 less than the desired number of pods are
Deployment can ensure that only a certain number of Pods may be down while they are being updated. By
default, it ensures that at least 1 less than the desired number of Pods are
up (1 max unavailable).
Deployment can also ensure that only a certain number of pods may be created above the desired number of pods. By default, it ensures that at most 1 more than the desired number of pods are up (1 max surge).
Deployment can also ensure that only a certain number of Pods may be created above the desired number of Pods. By default, it ensures that at most 1 more than the desired number of Pods are up (1 max surge).
For example, if you look at the above deployment closely, you will see that
it first created a new pod, then deleted some old pods and created new ones. It
does not kill old pods until a sufficient number of new pods have come up, and does not create new pods until a sufficient number of old pods have been killed. It makes sure that number of available pods is at least 2 and the number of total pods is at most 4.
For example, if you look at the above Deployment closely, you will see that
it first created a new Pod, then deleted some old Pods and created new ones. It
does not kill old Pods until a sufficient number of new Pods have come up, and does not create new Pods until a sufficient number of old Pods have been killed. It makes sure that number of available Pods is at least 2 and the number of total Pods is at most 4.
```shell
$ kubectl describe deployments
@ -168,34 +199,41 @@ Events:
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
```
Here we see that when we first created the Deployment, it created a replica set (nginx-deployment-2035384211) and scaled it up to 3 replicas directly.
When we updated the Deployment, it created a new replica set (nginx-deployment-1564180365) and scaled it up to 1 and then scaled down the old replica set to 2, so that at least 2 pods were available and at most 4 pods were created at all times.
It then continued scaling up and down the new and the old replica set, with the same rolling update strategy. Finally, we'll have 3 available replicas in the new replica set, and the old replica set is scaled down to 0.
Here we see that when we first created the Deployment, it created a Replica Set (nginx-deployment-2035384211) and scaled it up to 3 replicas directly.
When we updated the Deployment, it created a new Replica Set (nginx-deployment-1564180365) and scaled it up to 1 and then scaled down the old Replica Set to 2, so that at least 2 Pods were available and at most 4 Pods were created at all times.
It then continued scaling up and down the new and the old Replica Set, with the same rolling update strategy. Finally, we'll have 3 available replicas in the new Replica Set, and the old Replica Set is scaled down to 0.
### Multiple Updates
Each time a new deployment object is observed by the deployment controller, a replica set is
created to bring up the desired pods if there is no existing replica set doing so.
Existing replica set controlling pods whose labels match `.spec.selector` but whose
Each time a new deployment object is observed by the deployment controller, a Replica Set is
created to bring up the desired Pods if there is no existing Replica Set doing so.
Existing Replica Set controlling Pods whose labels match `.spec.selector` but whose
template does not match `.spec.template` are scaled down.
Eventually, the new replica set will be scaled to `.spec.replicas` and all old replica sets will
Eventually, the new Replica Set will be scaled to `.spec.replicas` and all old Replica Sets will
be scaled to 0.
If you update a Deployment while an existing deployment is in progress,
the Deployment will create a new replica set as per the update and start scaling that up, and
will roll the replica set that it was scaling up previously -- it will add it to its list of old replica sets and will
the Deployment will create a new Replica Set as per the update and start scaling that up, and
will roll the Replica Set that it was scaling up previously -- it will add it to its list of old Replica Sets and will
start scaling it down.
For example, suppose you create a Deployment to create 5 replicas of `nginx:1.7.9`,
but then updates the Deployment to create 5 replicas of `nginx:1.9.1`, when only 3
replicas of `nginx:1.7.9` had been created. In that case, Deployment will immediately start
killing the 3 `nginx:1.7.9` pods that it had created, and will start creating
`nginx:1.9.1` pods. It will not wait for 5 replicas of `nginx:1.7.9` to be created
killing the 3 `nginx:1.7.9` Pods that it had created, and will start creating
`nginx:1.9.1` Pods. It will not wait for 5 replicas of `nginx:1.7.9` to be created
before changing course.
## Rolling Back a Deployment
Sometimes we may want to rollback a Deployment; for example, when the Deployment is not stable, such as crash looping.
Sometimes you may want to rollback a Deployment; for example, when the Deployment is not stable, such as crash looping.
By default, all of the Deployment's rollout history is kept in the system so that you can rollback anytime you want
(you can change that by specifying [revision history limit](/docs/user-guide/deployments/#revision-history-limit)).
**Note:** a Deployment's revision is created when a Deployment's rollout is triggered. This means that the new revision is created
if and only if the Deployment's pod template (i.e. `.spec.template`) is changed, e.g. updating labels or container images of the template.
Other updates, such as scaling the Deployment, will not create a Deployment revision -- so that we can facilitate simultaneous manual- or
auto-scaling. This implies that when you rollback to an earlier revision, only the Deployment's pod template part will be rolled back.
Suppose that we made a typo while updating the Deployment, by putting the image name as `nginx:1.91` instead of `nginx:1.9.1`:
@ -216,7 +254,7 @@ nginx-deployment-2035384211 0 0 36s
nginx-deployment-3066724191 2 2 6s
```
Looking at the pods created, you will see that the 2 pods created by new replica set are stuck in an image pull loop.
Looking at the Pods created, you will see that the 2 Pods created by new Replica Set are stuck in an image pull loop.
```shell
$ kubectl get pods
@ -227,7 +265,7 @@ nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
nginx-deployment-3066724191-eocby 0/1 ImagePullBackOff 0 6s
```
Note that the Deployment controller will stop the bad rollout automatically, and will stop scaling up the new replica set.
Note that the Deployment controller will stop the bad rollout automatically, and will stop scaling up the new Replica Set.
```shell
$ kubectl describe deployment
@ -258,6 +296,8 @@ Events:
To fix this, we need to rollback to a previous revision of Deployment that is stable.
### Checking Rollout History of a Deployment
First, check the revisions of this deployment:
```shell
@ -282,6 +322,8 @@ Image(s): nginx:1.9.1
No volumes.
```
### Rolling Back to a Previous Revision
Now we've decided to undo the current rollout and rollback to the previous revision:
```shell
@ -296,6 +338,8 @@ $ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back
```
For more details about rollout related commands, read [`kubectl rollout`](/docs/user-guide/kubectl/kubectl_rollout/).
The Deployment is now rolled back to a previous stable revision. As you can see, a `DeploymentRollback` event for rolling back to revision 2 is generated from Deployment controller.
```shell
@ -344,7 +388,7 @@ deployment "nginx-deployment" paused
Note that any current state of the Deployment will continue its function, but new updates to the Deployment will not have an effect as long as the Deployment is paused.
The Deployment was still in progress when we paused it, so the actions of scaling up and down replica sets are paused too.
The Deployment was still in progress when we paused it, so the actions of scaling up and down Replica Sets are paused too.
```shell
$ kubectl get rs
@ -373,6 +417,13 @@ nginx-deployment-3066724191 0 0 1h
Note: A paused Deployment cannot be scaled at this moment, and we will add this feature in 1.3 release, see [issue #20853](https://github.com/kubernetes/kubernetes/issues/20853). You cannot rollback a paused Deployment either, and you should resume a Deployment first before doing a rollback.
## Use Cases
### Canary Deployment
If you want to roll out releases to a subset of users or servers using the Deployment, you can create multiple Deployments, one for each release,
following the canary pattern described in [managing resources](/docs/user-guide/managing-deployments/#canary-deployments).
## Writing a Deployment Spec
As with all other Kubernetes configs, a Deployment needs `apiVersion`, `kind`, and
@ -386,36 +437,48 @@ A Deployment also needs a [`.spec` section](https://github.com/kubernetes/kubern
The `.spec.template` is the only required field of the `.spec`.
The `.spec.template` is a [pod template](/docs/user-guide/replication-controller/#pod-template). It has exactly
the same schema as a [pod](/docs/user-guide/pods), except it is nested and does not have an
the same schema as a [Pod](/docs/user-guide/pods), except it is nested and does not have an
`apiVersion` or `kind`.
In addition to required fields for a Pod, a pod template in a Deployment must specify appropriate
labels (i.e. don't overlap with other controllers, see [selector](#selector)) and an appropriate restart policy.
Only a [`.spec.template.spec.restartPolicy`](/docs/user-guide/pod-states/) equal to `Always` is allowed, which is the default
if not specified.
### Replicas
`.spec.replicas` is an optional field that specifies the number of desired pods. It defaults
`.spec.replicas` is an optional field that specifies the number of desired Pods. It defaults
to 1.
### Selector
`.spec.selector` is an optional field that specifies label selectors for pods
targeted by this deployment. Deployment kills some of these pods, if their
template is different than `.spec.template` or if the total number of such pods
exceeds `.spec.replicas`. It will bring up new pods with `.spec.template` if
number of pods are less than the desired number.
`.spec.selector` is an optional field that specifies a [label selector](/docs/user-guide/labels/#label-selectors) for the Pods
targeted by this deployment.
If specified, `.spec.selector` must match `.spec.template.metadata.labels`, or it will
be rejected by the API. If `.spec.selector` is unspecified, `.spec.selector.matchLabels` will be defaulted to
`.spec.template.metadata.labels`.
Deployment may kill Pods whose labels match the selector, in the case that their
template is different than `.spec.template` or if the total number of such Pods
exceeds `.spec.replicas`. It will bring up new Pods with `.spec.template` if
number of Pods are less than the desired number.
### Strategy
`.spec.strategy` specifies the strategy used to replace old pods by new ones.
`.spec.strategy` specifies the strategy used to replace old Pods by new ones.
`.spec.strategy.type` can be "Recreate" or "RollingUpdate". "RollingUpdate" is
the default value.
#### Recreate Deployment
All existing pods are killed before new ones are created when
All existing Pods are killed before new ones are created when
`.spec.strategy.type==Recreate`.
#### Rolling Update Deployment
The Deployment updates pods in a [rolling update](/docs/user-guide/update-demo/) fashion
The Deployment updates Pods in a [rolling update](/docs/user-guide/update-demo/) fashion
when `.spec.strategy.type==RollingUpdate`.
You can specify `maxUnavailable` and `maxSurge` to control
the rolling update process.
@ -423,42 +486,42 @@ the rolling update process.
##### Max Unavailable
`.spec.strategy.rollingUpdate.maxUnavailable` is an optional field that specifies the
maximum number of pods that can be unavailable during the update process.
The value can be an absolute number (e.g. 5) or a percentage of desired pods
maximum number of Pods that can be unavailable during the update process.
The value can be an absolute number (e.g. 5) or a percentage of desired Pods
(e.g. 10%).
The absolute number is calculated from percentage by rounding up.
This can not be 0 if `.spec.strategy.rollingUpdate.maxSurge` is 0.
By default, a fixed value of 1 is used.
For example, when this value is set to 30%, the old replica set can be scaled down to
70% of desired pods immediately when the rolling update starts. Once new pods are
ready, old replica set can be scaled down further, followed by scaling up the new replica set,
ensuring that the total number of pods available at all times during the
update is at least 70% of the desired pods.
For example, when this value is set to 30%, the old Replica Set can be scaled down to
70% of desired Pods immediately when the rolling update starts. Once new Pods are
ready, old Replica Set can be scaled down further, followed by scaling up the new Replica Set,
ensuring that the total number of Pods available at all times during the
update is at least 70% of the desired Pods.
##### Max Surge
`.spec.strategy.rollingUpdate.maxSurge` is an optional field that specifies the
maximum number of pods that can be created above the desired number of pods.
Value can be an absolute number (e.g. 5) or a percentage of desired pods
maximum number of Pods that can be created above the desired number of Pods.
Value can be an absolute number (e.g. 5) or a percentage of desired Pods
(e.g. 10%).
This can not be 0 if `MaxUnavailable` is 0.
The absolute number is calculated from percentage by rounding up.
By default, a value of 1 is used.
For example, when this value is set to 30%, the new replica set can be scaled up immediately when
the rolling update starts, such that the total number of old and new pods do not exceed
130% of desired pods. Once old pods have been killed,
the new replica set can be scaled up further, ensuring that the total number of pods running
at any time during the update is at most 130% of desired pods.
For example, when this value is set to 30%, the new Replica Set can be scaled up immediately when
the rolling update starts, such that the total number of old and new Pods do not exceed
130% of desired Pods. Once old Pods have been killed,
the new Replica Set can be scaled up further, ensuring that the total number of Pods running
at any time during the update is at most 130% of desired Pods.
### Min Ready Seconds
`.spec.minReadySeconds` is an optional field that specifies the
minimum number of seconds for which a newly created pod should be ready
minimum number of seconds for which a newly created Pod should be ready
without any of its containers crashing, for it to be considered available.
This defaults to 0 (the pod will be considered available as soon as it is ready).
To learn more about when a pod is considered ready, see [Container Probes](/docs/user-guide/pod-states/#container-probes).
This defaults to 0 (the Pod will be considered available as soon as it is ready).
To learn more about when a Pod is considered ready, see [Container Probes](/docs/user-guide/pod-states/#container-probes).
### Rollback To
@ -470,7 +533,7 @@ To learn more about when a pod is considered ready, see [Container Probes](/docs
### Revision History Limit
`.spec.revisionHistoryLimit` is an optional field that specifies the number of old replica sets to retain to allow rollback. All old replica sets will be kept by default, if this field is not set. The configuration of each Deployment revision is stored in its replica sets; therefore, once an old replica set is deleted, you lose the ability to rollback to that revision of Deployment.
`.spec.revisionHistoryLimit` is an optional field that specifies the number of old Replica Sets to retain to allow rollback. All old Replica Sets will be kept by default, if this field is not set. The configuration of each Deployment revision is stored in its Replica Sets; therefore, once an old Replica Set is deleted, you lose the ability to rollback to that revision of Deployment.
### Paused
@ -480,5 +543,5 @@ To learn more about when a pod is considered ready, see [Container Probes](/docs
### kubectl rolling update
[Kubectl rolling update](/docs/user-guide/kubectl/kubectl_rolling-update) updates pods and replication controllers in a similar fashion.
But deployments is recommended, since it's declarative and is server side, and has more features, such as rolling back to any previous revision even after the rolling update is done. Also, replica sets supersede replication controllers.
[Kubectl rolling update](/docs/user-guide/kubectl/kubectl_rolling-update) updates Pods and Replication Controllers in a similar fashion.
But Deployments are recommended, since they are declarative, server side, and have additional features, such as rolling back to any previous revision even after the rolling update is done.

View File

@ -8,7 +8,7 @@ In this doc, we introduce the Kubernetes command line for interacting with the a
#### docker run
How do I run an nginx container and expose it to the world? Checkout [kubectl run](/docs/user-guide/kubectl/kubectl_run).
How do I run an nginx Deployment and expose it to the world? Checkout [kubectl run](/docs/user-guide/kubectl/kubectl_run).
With docker:
@ -25,12 +25,20 @@ With kubectl:
```shell
# start the pod running nginx
$ kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster"
replicationcontroller "nginx-app" created
# expose a port through with a service
$ kubectl expose rc nginx-app --port=80 --name=nginx-http
deployment "nginx-app" created
```
With kubectl, we create a [replication controller](/docs/user-guide/replication-controller) which will make sure that N pods are running nginx (where N is the number of replicas stated in the spec, which defaults to 1). We also create a [service](/docs/user-guide/services) with a selector that matches the replication controller's selector. See the [Quick start](/docs/user-guide/quick-start) for more information.
`kubectl run` creates a Deployment named "nginx" on Kubernetes cluster >= v1.2. If you are running older versions, it creates replication controllers instead.
If you want to obtain the old behavior, use `--generator=run/v1` to create replication controllers. See [`kubectl run`](/docs/user-guide/kubectl/kubectl_run/) for more details.
Note that `kubectl` commands will print the type and name of the resource created or mutated, which can then be used in subsequent commands. Now, we can expose a new Service with the deployment created above:
```shell
# expose a port through with a service
$ kubectl expose deployment nginx-app --port=80 --name=nginx-http
service "nginx-http" exposed
```
With kubectl, we create a [Deployment](/docs/user-guide/deployments) which will make sure that N pods are running nginx (where N is the number of replicas stated in the spec, which defaults to 1). We also create a [service](/docs/user-guide/services) with a selector that matches the Deployment's selector. See the [Quick start](/docs/user-guide/quick-start) for more information.
By default images are run in the background, similar to `docker run -d ...`, if you want to run things in the foreground, use:
@ -40,8 +48,8 @@ kubectl run [-i] [--tty] --attach <name> --image=<image>
Unlike `docker run ...`, if `--attach` is specified, we attach to `stdin`, `stdout` and `stderr`, there is no ability to control which streams are attached (`docker -a ...`).
Because we start a replication controller for your container, it will be restarted if you terminate the attached process (e.g. `ctrl-c`), this is different than `docker run -it`.
To destroy the replication controller (and it's pods) you need to run `kubectl delete rc <name>`
Because we start a Deployment for your container, it will be restarted if you terminate the attached process (e.g. `ctrl-c`), this is different than `docker run -it`.
To destroy the Deployment (and its pods) you need to run `kubectl delete deployment <name>`
#### docker ps
@ -180,20 +188,19 @@ a9ec34d98787
With kubectl:
```shell
$ kubectl get rc nginx-app
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
nginx-app nginx-app nginx run=nginx-app 1
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-app-aualv 1/1 Running 0 16s
$ kubectl delete rc nginx-app
NAME READY STATUS RESTARTS AGE
nginx-app-aualv 1/1 Running 0 16s
$ kubectl get po
NAME READY STATUS RESTARTS AGE
$ kubectl get deployment nginx-app
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-app 1 1 1 1 2m
$ kubectl get po -l run=nginx-app
NAME READY STATUS RESTARTS AGE
nginx-app-2883164633-aklf7 1/1 Running 0 2m
$ kubectl delete deployment nginx-app
deployment "nginx-app" deleted
$ kubectl get po -l run=nginx-app
# Return nothing
```
Notice that we don't delete the pod directly. With kubectl we want to delete the replication controller that owns the pod. If we delete the pod directly, the replication controller will recreate the pod.
Notice that we don't delete the pod directly. With kubectl we want to delete the Deployment that owns the pod. If we delete the pod directly, the Deployment will recreate the pod.
#### docker login
@ -263,4 +270,4 @@ KubeUI is running at https://108.59.85.141/api/v1/proxy/namespaces/kube-system/s
Grafana is running at https://108.59.85.141/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana
Heapster is running at https://108.59.85.141/api/v1/proxy/namespaces/kube-system/services/monitoring-heapster
InfluxDB is running at https://108.59.85.141/api/v1/proxy/namespaces/kube-system/services/monitoring-influxdb
```
```

View File

@ -52,7 +52,7 @@ environment variable they want.
This is an example of a pod that consumes its name and namespace via the
downward API:
{% include code.html language="yaml" file="downward-api/dapi-pod.yaml" ghlink="/docs/user-guide/downward-api/dapi-pod.yaml" %}
{% include code.html language="yaml" file="dapi-pod.yaml" ghlink="/docs/user-guide/downward-api/dapi-pod.yaml" %}
### Downward API volume
@ -86,7 +86,7 @@ In future, it will be possible to specify a specific annotation or label.
This is an example of a pod that consumes its labels and annotations via the downward API volume, labels and annotations are dumped in `/etc/labels` and in `/etc/annotations`, respectively:
{% include code.html language="yaml" file="downward-api/volume/dapi-volume.yaml" ghlink="/docs/user-guide/downward-api/volume/dapi-volume.yaml" %}
{% include code.html language="yaml" file="volume/dapi-volume.yaml" ghlink="/docs/user-guide/downward-api/volume/dapi-volume.yaml" %}
Some more thorough examples:

View File

@ -1,5 +1,5 @@
---
---
---
---
This example demonstrates running pods, replication controllers, and
services. It shows two types of pods: frontend and backend, with
@ -23,15 +23,15 @@ for your platform.
## Optional: Build your own containers
The code for the containers is under
[containers/](/docs/user-guide/environment-guide/containers/)
[containers/](/docs/user-guide/containers/)
## Get everything running
```shell
kubectl create -f ./backend-rc.yaml
kubectl create -f ./backend-srv.yaml
kubectl create -f ./show-rc.yaml
kubectl create -f ./show-srv.yaml
```shell
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
@ -46,7 +46,7 @@ your service.
Run `curl <public ip>:80` to query the service. You should get
something like this back:
```shell
```shell
Pod Name: show-rc-xxu6i
Pod Namespace: default
USER_VAR: important information
@ -66,8 +66,8 @@ 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](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/namespaces.md) are retrieved from the
[Downward API](/docs/user-guide/downward-api). Next, `USER_VAR` is the name of
@ -86,8 +86,8 @@ service. This results in a different backend pod servicing each
request as well.
## Cleanup
```shell
kubectl delete rc,service -l type=show-type
kubectl delete rc,service -l type=backend-type
```
kubectl delete rc,service -l type=backend-type
```

View File

@ -1,83 +0,0 @@
---
---
This document describes the current state of Horizontal Pod Autoscaler in Kubernetes.
## What is Horizontal Pod Autoscaler?
Horizontal pod autoscaling allows to automatically scale the number of pods
in a replication controller, deployment or replica set based on observed CPU utilization.
The autoscaler is implemented as a Kubernetes API resource and a controller.
The resource describes behavior of the controller.
The controller periodically adjusts the number of replicas in a replication controller or deployment
to match the observed average CPU utilization to the target specified by user.
## How does Horizontal Pod Autoscaler work?
![Horizontal Pod Autoscaler diagram](/images/docs/horizontal-pod-autoscaler.svg)
The autoscaler is implemented as a control loop.
It periodically queries CPU utilization for the pods it targets.
(The period of the autoscaler is controlled by `--horizontal-pod-autoscaler-sync-period` flag of controller manager.
The default value is 30 seconds).
Then, it compares the arithmetic mean of the pods' CPU utilization with the target and adjust the number of replicas if needed.
CPU utilization is the recent CPU usage of a pod divided by the sum of CPU requested by the pod's containers.
Please note that if some of the pod's containers do not have CPU request set,
CPU utilization for the pod will not be defined and the autoscaler will not take any action.
Further details of the autoscaling algorithm are given [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#autoscaling-algorithm).
Autoscaler uses heapster to collect CPU utilization.
Therefore, it is required to deploy heapster monitoring in your cluster for autoscaling to work.
Autoscaler accesses corresponding replication controller, deployment or replica set by scale sub-resource.
Scale is an interface which allows to dynamically set the number of replicas and to learn the current state of them.
More details on scale sub-resource can be found [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#scale-subresource).
## API Object
Horizontal pod autoscaler is a top-level resource in the Kubernetes REST API.
In Kubernetes 1.2 HPA was graduated from beta to stable (more details about [api versioning](/docs/api/#api-versioning)) with compatibility between versions.
The stable version is available in `autoscaling/v1` api group whereas the beta vesion is available in `extensions/v1beta1` api group as before.
The transition plan is to depracate beta verion of HPA in Kubernetes 1.3 and get it rid off completely in Kubernetes 1.4.
**Warning!** Please have in mind that all Kubernetes components still use HPA in version `extensions/v1beta1` in Kubernetes 1.2.
More details about the API object can be found at
[HorizontalPodAutoscaler Object](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#horizontalpodautoscaler-object).
## Support for horizontal pod autoscaler in kubectl
Horizontal pod autoscaler, like every API resource, is supported in a standard way by `kubectl`.
We can create a new autoscaler using `kubectl create` command.
We can list autoscalers by `kubectl get hpa` and get detailed description by `kubectl describe hpa`.
Finally, we can delete an autoscaler using `kubectl delete hpa`.
In addition, there is a special `kubectl autoscale` command that allows for easy creation of horizontal pod autoscaler.
For instance, executing `kubectl autoscale rc foo --min=2 --max=5 --cpu-percent=80`
will create an autoscaler for replication controller *foo*, with target CPU utilization set to `80%`
and the number of replicas between 2 and 5.
The detailed documentation of `kubectl autoscale` can be found [here](/docs/user-guide/kubectl/kubectl_autoscale).
## Autoscaling during rolling update
Currently in Kubernetes, it is possible to perform a rolling update by managing replication controllers directly,
or by using the deployment object, which manages the underlying replication controllers for you.
Horizontal pod autoscaler only supports the latter approach: the horizontal pod autoscaler is bound to the deployment object,
it sets the size for the deployment object, and the deployment is responsible for setting sizes of underlying replication controllers.
Horizontal pod autoscaler does not work with rolling update using direct manipulation of replication controllers,
i.e. you cannot bind a horizontal pod autoscaler to a replication controller and do rolling update (e.g. using `kubectl rolling-update`).
The reason this doesn't work is that when rolling update creates a new replication controller,
the horizontal pod autoscaler will not be bound to the new replication controller.
## Further reading
* Design documentation: [Horizontal Pod Autoscaling](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md).
* Manual of autoscale command in kubectl: [kubectl autoscale](/docs/user-guide/kubectl/kubectl_autoscale).
* Usage example of [Horizontal Pod Autoscaler](/docs/user-guide/horizontal-pod-autoscaling/).

View File

@ -1,147 +1,83 @@
---
---
This document describes the current state of Horizontal Pod Autoscaler in Kubernetes.
## What is Horizontal Pod Autoscaler?
Horizontal pod autoscaling allows to automatically scale the number of pods
in a replication controller, deployment or replica set based on observed CPU utilization.
In the future also other metrics will be supported.
In this document we explain how this feature works by walking you through an example of enabling horizontal pod autoscaling for the php-apache server.
The autoscaler is implemented as a Kubernetes API resource and a controller.
The resource describes behavior of the controller.
The controller periodically adjusts the number of replicas in a replication controller or deployment
to match the observed average CPU utilization to the target specified by user.
## Prerequisites
This example requires a running Kubernetes cluster and kubectl in the version at least 1.2.
[Heapster](https://github.com/kubernetes/heapster) monitoring needs to be deployed in the cluster
as horizontal pod autoscaler uses it to collect metrics
(if you followed [getting started on GCE guide](/docs/getting-started-guides/gce),
heapster monitoring will be turned-on by default).
## How does Horizontal Pod Autoscaler work?
## Step One: Run & expose php-apache server
![Horizontal Pod Autoscaler diagram](/images/docs/horizontal-pod-autoscaler.svg)
To demonstrate horizontal pod autoscaler we will use a custom docker image based on php-apache server.
The image can be found [here](/docs/user-guide/horizontal-pod-autoscaling/image).
It defines [index.php](/docs/user-guide/horizontal-pod-autoscaling/image/index.php) page which performs some CPU intensive computations.
The autoscaler is implemented as a control loop.
It periodically queries CPU utilization for the pods it targets.
(The period of the autoscaler is controlled by `--horizontal-pod-autoscaler-sync-period` flag of controller manager.
The default value is 30 seconds).
Then, it compares the arithmetic mean of the pods' CPU utilization with the target and adjust the number of replicas if needed.
First, we will start a deployment running the image and expose it as a service:
CPU utilization is the recent CPU usage of a pod divided by the sum of CPU requested by the pod's containers.
Please note that if some of the pod's containers do not have CPU request set,
CPU utilization for the pod will not be defined and the autoscaler will not take any action.
Further details of the autoscaling algorithm are given [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#autoscaling-algorithm).
```shell
$ kubectl run php-apache --image=gcr.io/google_containers/hpa-example --requests=cpu=200m --expose --port=80
service "php-apache" created
deployment "php-apache" created
```
Autoscaler uses heapster to collect CPU utilization.
Therefore, it is required to deploy heapster monitoring in your cluster for autoscaling to work.
## Step Two: Create horizontal pod autoscaler
Autoscaler accesses corresponding replication controller, deployment or replica set by scale sub-resource.
Scale is an interface which allows to dynamically set the number of replicas and to learn the current state of them.
More details on scale sub-resource can be found [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#scale-subresource).
Now that the server is running, we will create the autoscaler using
[kubectl autoscale](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/user-guide/kubectl/kubectl_autoscale.md).
The following command will create a horizontal pod autoscaler that maintains between 1 and 10 replicas of the Pods
controlled by the php-apache deployment we created in the first step of these instructions.
Roughly speaking, the horizontal autoscaler will increase and decrease the number of replicas
(via the deployment) to maintain an average CPU utilization across all Pods of 50%
(since each pod requests 200 milli-cores by [kubectl run](#kubectl-run), this means average CPU usage of 100 milli-cores).
See [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#autoscaling-algorithm) for more details on the algorithm.
```shell
$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
deployment "php-apache" autoscaled
```
## API Object
We may check the current status of autoscaler by running:
Horizontal pod autoscaler is a top-level resource in the Kubernetes REST API.
In Kubernetes 1.2 HPA was graduated from beta to stable (more details about [api versioning](/docs/api/#api-versioning)) with compatibility between versions.
The stable version is available in `autoscaling/v1` api group whereas the beta vesion is available in `extensions/v1beta1` api group as before.
The transition plan is to depracate beta version of HPA in Kubernetes 1.3 and get it rid off completely in Kubernetes 1.4.
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 0% 1 10 18s
**Warning!** Please have in mind that all Kubernetes components still use HPA in version `extensions/v1beta1` in Kubernetes 1.2.
```
More details about the API object can be found at
[HorizontalPodAutoscaler Object](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#horizontalpodautoscaler-object).
Please note that the current CPU consumption is 0% as we are not sending any requests to the server
(the ``CURRENT`` column shows the average across all the pods controlled by the corresponding deployment).
## Support for horizontal pod autoscaler in kubectl
## Step Three: Increase load
Horizontal pod autoscaler, like every API resource, is supported in a standard way by `kubectl`.
We can create a new autoscaler using `kubectl create` command.
We can list autoscalers by `kubectl get hpa` and get detailed description by `kubectl describe hpa`.
Finally, we can delete an autoscaler using `kubectl delete hpa`.
Now, we will see how the autoscaler reacts on the increased load on the server.
We will start a container with `busybox` image and an infinite loop of queries to our server inside (please run it in a different terminal):
In addition, there is a special `kubectl autoscale` command that allows for easy creation of horizontal pod autoscaler.
For instance, executing `kubectl autoscale rc foo --min=2 --max=5 --cpu-percent=80`
will create an autoscaler for replication controller *foo*, with target CPU utilization set to `80%`
and the number of replicas between 2 and 5.
The detailed documentation of `kubectl autoscale` can be found [here](/docs/user-guide/kubectl/kubectl_autoscale).
```shell
$ kubectl run -i --tty load-generator --image=busybox /bin/sh
Hit enter for command prompt
## Autoscaling during rolling update
$ while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
```
Currently in Kubernetes, it is possible to perform a rolling update by managing replication controllers directly,
or by using the deployment object, which manages the underlying replication controllers for you.
Horizontal pod autoscaler only supports the latter approach: the horizontal pod autoscaler is bound to the deployment object,
it sets the size for the deployment object, and the deployment is responsible for setting sizes of underlying replication controllers.
We may examine, how CPU load was increased by executing (it usually takes 1 minute):
Horizontal pod autoscaler does not work with rolling update using direct manipulation of replication controllers,
i.e. you cannot bind a horizontal pod autoscaler to a replication controller and do rolling update (e.g. using `kubectl rolling-update`).
The reason this doesn't work is that when rolling update creates a new replication controller,
the horizontal pod autoscaler will not be bound to the new replication controller.
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 305% 1 10 3m
```
## Further reading
In the case presented here, it bumped CPU consumption to 305% of the request.
As a result, the deployment was resized to 7 replicas:
```shell
$ kubectl get deployment php-apache
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
php-apache 7 7 7 7 19m
```
**Warning!** Sometimes it may take few steps to stabilize the number of replicas.
Since the amount of load is not controlled in any way it may happen that the final number of replicas will
differ from this example.
## Step Four: Stop load
We will finish our example by stopping the user load.
In the terminal where we created container with `busybox` image we will terminate
infinite ``while`` loop by sending `SIGINT` signal,
which can be done using `<Ctrl> + C` combination.
Then we will verify the result state:
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 0% 1 10 11m
$ kubectl get deployment php-apache
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
php-apache 1 1 1 1 27m
```
As we see, in the presented case CPU utilization dropped to 0, and the number of replicas dropped to 1.
**Warning!** Sometimes dropping number of replicas may take few steps.
## Appendix: Other possible scenarios
### Creating the autoscaler from a .yaml file
Instead of using `kubectl autoscale` command we can use the [hpa-php-apache.yaml](/docs/user-guide/horizontal-pod-autoscaling/hpa-php-apache.yaml) file, which looks like this:
```yaml
apiVersion: extensions/v1beta1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleRef:
kind: Deployment
name: php-apache
subresource: scale
minReplicas: 1
maxReplicas: 10
cpuUtilization:
targetPercentage: 50
```
We will create the autoscaler by executing the following command:
```shell
$ kubectl create -f docs/user-guide/horizontal-pod-autoscaling/hpa-php-apache.yaml
horizontalpodautoscaler "php-apache" created
```
* Design documentation: [Horizontal Pod Autoscaling](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md).
* Manual of autoscale command in kubectl: [kubectl autoscale](/docs/user-guide/kubectl/kubectl_autoscale).
* Usage example of [Horizontal Pod Autoscaler](/docs/user-guide/horizontal-pod-autoscaling/).

View File

@ -0,0 +1,147 @@
---
---
Horizontal pod autoscaling allows to automatically scale the number of pods
in a replication controller, deployment or replica set based on observed CPU utilization.
In the future also other metrics will be supported.
In this document we explain how this feature works by walking you through an example of enabling horizontal pod autoscaling for the php-apache server.
## Prerequisites
This example requires a running Kubernetes cluster and kubectl in the version at least 1.2.
[Heapster](https://github.com/kubernetes/heapster) monitoring needs to be deployed in the cluster
as horizontal pod autoscaler uses it to collect metrics
(if you followed [getting started on GCE guide](/docs/getting-started-guides/gce),
heapster monitoring will be turned-on by default).
## Step One: Run & expose php-apache server
To demonstrate horizontal pod autoscaler we will use a custom docker image based on php-apache server.
The image can be found [here](/docs/user-guide/horizontal-pod-autoscaling/image).
It defines [index.php](/docs/user-guide/horizontal-pod-autoscaling/image/index.php) page which performs some CPU intensive computations.
First, we will start a deployment running the image and expose it as a service:
```shell
$ kubectl run php-apache --image=gcr.io/google_containers/hpa-example --requests=cpu=200m --expose --port=80
service "php-apache" created
deployment "php-apache" created
```
## Step Two: Create horizontal pod autoscaler
Now that the server is running, we will create the autoscaler using
[kubectl autoscale](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/user-guide/kubectl/kubectl_autoscale.md).
The following command will create a horizontal pod autoscaler that maintains between 1 and 10 replicas of the Pods
controlled by the php-apache deployment we created in the first step of these instructions.
Roughly speaking, the horizontal autoscaler will increase and decrease the number of replicas
(via the deployment) to maintain an average CPU utilization across all Pods of 50%
(since each pod requests 200 milli-cores by [kubectl run](#kubectl-run), this means average CPU usage of 100 milli-cores).
See [here](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/horizontal-pod-autoscaler.md#autoscaling-algorithm) for more details on the algorithm.
```shell
$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
deployment "php-apache" autoscaled
```
We may check the current status of autoscaler by running:
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 0% 1 10 18s
```
Please note that the current CPU consumption is 0% as we are not sending any requests to the server
(the ``CURRENT`` column shows the average across all the pods controlled by the corresponding deployment).
## Step Three: Increase load
Now, we will see how the autoscaler reacts on the increased load on the server.
We will start a container with `busybox` image and an infinite loop of queries to our server inside (please run it in a different terminal):
```shell
$ kubectl run -i --tty load-generator --image=busybox /bin/sh
Hit enter for command prompt
$ while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
```
We may examine, how CPU load was increased by executing (it usually takes 1 minute):
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 305% 1 10 3m
```
In the case presented here, it bumped CPU consumption to 305% of the request.
As a result, the deployment was resized to 7 replicas:
```shell
$ kubectl get deployment php-apache
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
php-apache 7 7 7 7 19m
```
**Warning!** Sometimes it may take few steps to stabilize the number of replicas.
Since the amount of load is not controlled in any way it may happen that the final number of replicas will
differ from this example.
## Step Four: Stop load
We will finish our example by stopping the user load.
In the terminal where we created container with `busybox` image we will terminate
infinite ``while`` loop by sending `SIGINT` signal,
which can be done using `<Ctrl> + C` combination.
Then we will verify the result state:
```shell
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
php-apache Deployment/php-apache/scale 50% 0% 1 10 11m
$ kubectl get deployment php-apache
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
php-apache 1 1 1 1 27m
```
As we see, in the presented case CPU utilization dropped to 0, and the number of replicas dropped to 1.
**Warning!** Sometimes dropping number of replicas may take few steps.
## Appendix: Other possible scenarios
### Creating the autoscaler from a .yaml file
Instead of using `kubectl autoscale` command we can use the [hpa-php-apache.yaml](/docs/user-guide/horizontal-pod-autoscaling/hpa-php-apache.yaml) file, which looks like this:
```yaml
apiVersion: extensions/v1beta1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleRef:
kind: Deployment
name: php-apache
subresource: scale
minReplicas: 1
maxReplicas: 10
cpuUtilization:
targetPercentage: 50
```
We will create the autoscaler by executing the following command:
```shell
$ kubectl create -f docs/user-guide/horizontal-pod-autoscaling/hpa-php-apache.yaml
horizontalpodautoscaler "php-apache" created
```

View File

@ -21,6 +21,8 @@ your image.
If you did not specify tag of your image, it will be assumed as `:latest`, with
pull image policy of `Always` correspondingly.
Note that you should avoid using `:latest` tag, see [Best Practices for Configuration](/docs/user-guide/config-best-practices/#container-images) for more information.
## Using a Private Registry
Private registries may require keys to read images from them.
@ -66,9 +68,15 @@ in the Pod definition.
All users of the cluster who can create pods will be able to run pods that use any of the
images in the ECR registry.
The kubelet will fetch and periodically refresh ECR credentials. It needs the
`ecr:GetAuthorizationToken` permission to do this.
The kubelet will fetch and periodically refresh ECR credentials. It needs the following permissions to do this:
- `ecr:GetAuthorizationToken`
- `ecr:BatchCheckLayerAvailability`
- `ecr:GetDownloadUrlForLayer`
- `ecr:GetRepositoryPolicy`
- `ecr:DescribeRepositories`
- `ecr:ListImages`
- `ecr:BatchGetImage`
### Configuring Nodes to Authenticate to a Private Repository

View File

@ -39,12 +39,25 @@ It can be configured to give services externally-reachable urls, load balance tr
## Prerequisites
Before you start using the Ingress resource, there are a few things you should understand:
Before you start using the Ingress resource, there are a few things you should understand. The Ingress is a beta resource, not available in any Kubernetes release prior to 1.1. You need an Ingress controller to satisfy an Ingress, simply creating the resource will have no effect.
* The Ingress is a beta resource, not available in any Kubernetes release prior to 1.1.
* You need an Ingress controller to satisfy an Ingress. Simply creating the resource will have no effect.
* On GCE/GKE there should be a [L7 cluster addon](https://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-loadbalancing/glbc/README.md#prerequisites), on other platforms you either need to write your own or [deploy an existing controller](https://github.com/kubernetes/contrib/tree/master/ingress) as a pod.
* The resource currently does not support HTTPS, but will do so before it leaves beta.
On GCE/GKE there should be a [L7 cluster addon](https://github.com/kubernetes/contrib/blob/master/ingress/controllers/gce/README.md), deployed into the `kube-system` namespace:
```shell
$ kubectl get pods --namespace=kube-system -l name=glbc
NAME READY STATUS RESTARTS AGE
l7-lb-controller-v0.6.0-chnan 2/2 Running 0 1d
```
Make sure you review the [beta limitations](https://github.com/kubernetes/contrib/tree/master/ingress/controllers/gce/BETA_LIMITATIONS.md) of this controller. In particular, you need to create a single firewall-rule on your cloudprovider, to allow health checks. On GKE this would be:
```shell
$ gcloud compute firewall-rules create allow-130-211-0-0-22 \
--source-ranges 130.211.0.0/22 \
--allow tcp:30000-32767
```
In environments other than GCE/GKE, you need to [deploy a controller](https://github.com/kubernetes/contrib/tree/master/ingress/controllers) as a pod.
## The Ingress Resource
@ -202,7 +215,7 @@ metadata:
name: no-rules-map
spec:
tls:
secretName: testsecret
- secretName: testsecret
backend:
serviceName: s1
servicePort: 80

View File

@ -10,13 +10,13 @@ your pods. But there are a number of ways to get even more information about you
## Using `kubectl describe pod` to fetch details about pods
For this example we'll use a ReplicationController to create two pods, similar to the earlier example.
For this example we'll use a Deployment to create two pods, similar to the earlier example.
```yaml
apiVersion: v1
kind: ReplicationController
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
name: nginx-deployment
spec:
replicas: 2
template:
@ -35,53 +35,67 @@ spec:
- containerPort: 80
```
Copy this to a file *./my-nginx-dep.yaml*
```shell
$ kubectl create -f ./my-nginx-rc.yaml
replicationcontrollers/my-nginx
$ kubectl create -f ./my-nginx-dep.yaml
deployment "nginx-deployment" created
```
```shell
$ kubectl get pods
NAME READY REASON RESTARTS AGE
my-nginx-gy1ij 1/1 Running 0 1m
my-nginx-yv5cn 1/1 Running 0 1m
NAME READY STATUS RESTARTS AGE
nginx-deployment-1006230814-6winp 1/1 Running 0 11s
nginx-deployment-1006230814-fmgu3 1/1 Running 0 11s
```
We can retrieve a lot more information about each of these pods using `kubectl describe pod`. For example:
```shell
$ kubectl describe pod my-nginx-gy1ij
Name: my-nginx-gy1ij
Image(s): nginx
Node: kubernetes-node-y3vk/10.240.154.168
Labels: app=nginx
Status: Running
Reason:
Message:
IP: 10.244.1.4
Replication Controllers: my-nginx (2/2 replicas created)
$ kubectl describe pod nginx-deployment-1006230814-6winp
Name: nginx-deployment-1006230814-6winp
Namespace: default
Node: kubernetes-node-wul5/10.240.0.9
Start Time: Thu, 24 Mar 2016 01:39:49 +0000
Labels: app=nginx,pod-template-hash=1006230814
Status: Running
IP: 10.244.0.6
Controllers: ReplicaSet/nginx-deployment-1006230814
Containers:
nginx:
Image: nginx
Container ID: docker://90315cc9f513c724e9957a4788d3e625a078de84750f244a40f97ae355eb1149
Image: nginx
Image ID: docker://6f62f48c4e55d700cf3eb1b5e33fa051802986b77b874cc351cce539e5163707
Port: 80/TCP
QoS Tier:
cpu: Guaranteed
memory: Guaranteed
Limits:
cpu: 500m
cpu: 500m
memory: 128Mi
Requests:
memory: 128Mi
cpu: 500m
State: Running
Started: Thu, 09 Jul 2015 15:33:07 -0700
Started: Thu, 24 Mar 2016 01:39:51 +0000
Ready: True
Restart Count: 0
Environment Variables:
Conditions:
Type Status
Ready True
Volumes:
default-token-4bcbi:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4bcbi
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
Thu, 09 Jul 2015 15:32:58 -0700 Thu, 09 Jul 2015 15:32:58 -0700 1 {scheduler } scheduled Successfully assigned my-nginx-gy1ij to kubernetes-node-y3vk
Thu, 09 Jul 2015 15:32:58 -0700 Thu, 09 Jul 2015 15:32:58 -0700 1 {kubelet kubernetes-node-y3vk} implicitly required container POD pulled Pod container image "gcr.io/google_containers/pause:0.8.0" already present on machine
Thu, 09 Jul 2015 15:32:58 -0700 Thu, 09 Jul 2015 15:32:58 -0700 1 {kubelet kubernetes-node-y3vk} implicitly required container POD created Created with docker id cd1644065066
Thu, 09 Jul 2015 15:32:58 -0700 Thu, 09 Jul 2015 15:32:58 -0700 1 {kubelet kubernetes-node-y3vk} implicitly required container POD started Started with docker id cd1644065066
Thu, 09 Jul 2015 15:33:06 -0700 Thu, 09 Jul 2015 15:33:06 -0700 1 {kubelet kubernetes-node-y3vk} spec.containers{nginx} pulled Successfully pulled image "nginx"
Thu, 09 Jul 2015 15:33:06 -0700 Thu, 09 Jul 2015 15:33:06 -0700 1 {kubelet kubernetes-node-y3vk} spec.containers{nginx} created Created with docker id 56d7a7b14dac
Thu, 09 Jul 2015 15:33:07 -0700 Thu, 09 Jul 2015 15:33:07 -0700 1 {kubelet kubernetes-node-y3vk} spec.containers{nginx} started Started with docker id 56d7a7b14dac
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
54s 54s 1 {default-scheduler } Normal Scheduled Successfully assigned nginx-deployment-1006230814-6winp to kubernetes-node-wul5
54s 54s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Pulling pulling image "nginx"
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Pulled Successfully pulled image "nginx"
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Created Created container with docker id 90315cc9f513
53s 53s 1 {kubelet kubernetes-node-wul5} spec.containers{nginx} Normal Started Started container with docker id 90315cc9f513
```
Here you can see configuration information about the container(s) and Pod (labels, resource requirements, etc.), as well as status information about the container(s) and Pod (state, readiness, restart count, events, etc.)
@ -98,48 +112,59 @@ Lastly, you see a log of recent events related to your Pod. The system compresse
## Example: debugging Pending Pods
A common scenario that you can detect using events is when you've created a Pod that won't fit on any node. For example, the Pod might request more resources than are free on any node, or it might specify a label selector that doesn't match any nodes. Let's say we created the previous Replication Controller with 5 replicas (instead of 2) and requesting 600 millicores instead of 500, on a four-node cluster where each (virtual) machine has 1 CPU. In that case one of the Pods will not be able to schedule. (Note that because of the cluster addon pods such as fluentd, skydns, etc., that run on each node, if we requested 1000 millicores then none of the Pods would be able to schedule.)
A common scenario that you can detect using events is when you've created a Pod that won't fit on any node. For example, the Pod might request more resources than are free on any node, or it might specify a label selector that doesn't match any nodes. Let's say we created the previous Deployment with 5 replicas (instead of 2) and requesting 600 millicores instead of 500, on a four-node cluster where each (virtual) machine has 1 CPU. In that case one of the Pods will not be able to schedule. (Note that because of the cluster addon pods such as fluentd, skydns, etc., that run on each node, if we requested 1000 millicores then none of the Pods would be able to schedule.)
```shell
$ kubectl get pods
NAME READY REASON RESTARTS AGE
my-nginx-9unp9 0/1 Pending 0 8s
my-nginx-b7zs9 0/1 Running 0 8s
my-nginx-i595c 0/1 Running 0 8s
my-nginx-iichp 0/1 Running 0 8s
my-nginx-tc2j9 0/1 Running 0 8s
NAME READY STATUS RESTARTS AGE
nginx-deployment-1006230814-6winp 1/1 Running 0 7m
nginx-deployment-1006230814-fmgu3 1/1 Running 0 7m
nginx-deployment-1370807587-6ekbw 1/1 Running 0 1m
nginx-deployment-1370807587-fg172 0/1 Pending 0 1m
nginx-deployment-1370807587-fz9sd 0/1 Pending 0 1m
```
To find out why the my-nginx-9unp9 pod is not running, we can use `kubectl describe pod` on the pending Pod and look at its events:
To find out why the nginx-deployment-1370807587-fz9sd pod is not running, we can use `kubectl describe pod` on the pending Pod and look at its events:
```shell
$ kubectl describe pod my-nginx-9unp9
Name: my-nginx-9unp9
Image(s): nginx
Node: /
Labels: app=nginx
Status: Pending
Reason:
Message:
IP:
Replication Controllers: my-nginx (5/5 replicas created)
Containers:
nginx:
Image: nginx
Limits:
cpu: 600m
memory: 128Mi
State: Waiting
Ready: False
Restart Count: 0
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
Thu, 09 Jul 2015 23:56:21 -0700 Fri, 10 Jul 2015 00:01:30 -0700 21 {scheduler } failedScheduling Failed for reason PodFitsResources and possibly others
$ kubectl describe pod nginx-deployment-1370807587-fz9sd
Name: nginx-deployment-1370807587-fz9sd
Namespace: default
Node: /
Labels: app=nginx,pod-template-hash=1370807587
Status: Pending
IP:
Controllers: ReplicaSet/nginx-deployment-1370807587
Containers:
nginx:
Image: nginx
Port: 80/TCP
QoS Tier:
memory: Guaranteed
cpu: Guaranteed
Limits:
cpu: 1
memory: 128Mi
Requests:
cpu: 1
memory: 128Mi
Environment Variables:
Volumes:
default-token-4bcbi:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4bcbi
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 48s 7 {default-scheduler } Warning FailedScheduling pod (nginx-deployment-1370807587-fz9sd) failed to fit in any node
fit failure on node (kubernetes-node-6ta5): Node didn't have enough resource: CPU, requested: 1000, used: 1420, capacity: 2000
fit failure on node (kubernetes-node-wul5): Node didn't have enough resource: CPU, requested: 1000, used: 1100, capacity: 2000
```
Here you can see the event generated by the scheduler saying that the Pod failed to schedule for reason `PodFitsResources` (and possibly others). `PodFitsResources` means there were not enough resources for the Pod on any of the nodes. Due to the way the event is generated, there may be other reasons as well, hence "and possibly others."
Here you can see the event generated by the scheduler saying that the Pod failed to schedule for reason `FailedScheduling` (and possibly others). The message tells us that there were not enough resources for the Pod on any of the nodes.
To correct this situation, you can use `kubectl scale` to update your Replication Controller to specify four or fewer replicas. (Or you could just leave the one Pod pending, which is harmless.)
To correct this situation, you can use `kubectl scale` to update your Deployment to specify four or fewer replicas. (Or you could just leave the one Pod pending, which is harmless.)
Events such as the ones you saw at the end of `kubectl describe pod` are persisted in etcd and provide high-level information on what is happening in the cluster. To list all events you can use
@ -158,65 +183,75 @@ To see events from all namespaces, you can use the `--all-namespaces` argument.
In addition to `kubectl describe pod`, another way to get extra information about a pod (beyond what is provided by `kubectl get pod`) is to pass the `-o yaml` output format flag to `kubectl get pod`. This will give you, in YAML format, even more information than `kubectl describe pod`--essentially all of the information the system has about the Pod. Here you will see things like annotations (which are key-value metadata without the label restrictions, that is used internally by Kubernetes system components), restart policy, ports, and volumes.
```yaml
$ kubectl get pod my-nginx-i595c -o yaml
$kubectl get pod nginx-deployment-1006230814-6winp -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubernetes.io/created-by: '{"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"default","name":"my-nginx","uid":"c555c14f-26d0-11e5-99cb-42010af00e4b","apiVersion":"v1","resourceVersion":"26174"}}'
creationTimestamp: 2015-07-10T06:56:21Z
generateName: my-nginx-
kubernetes.io/created-by: |
{"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"default","name":"nginx-deployment-1006230814","uid":"4c84c175-f161-11e5-9a78-42010af00005","apiVersion":"extensions","resourceVersion":"133434"}}
creationTimestamp: 2016-03-24T01:39:50Z
generateName: nginx-deployment-1006230814-
labels:
app: nginx
name: my-nginx-i595c
pod-template-hash: "1006230814"
name: nginx-deployment-1006230814-6winp
namespace: default
resourceVersion: "26243"
selfLink: /api/v1/namespaces/default/pods/my-nginx-i595c
uid: c558e44b-26d0-11e5-99cb-42010af00e4b
resourceVersion: "133447"
selfLink: /api/v1/namespaces/default/pods/nginx-deployment-1006230814-6winp
uid: 4c879808-f161-11e5-9a78-42010af00005
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources:
limits:
cpu: 600m
cpu: 500m
memory: 128Mi
requests:
cpu: 500m
memory: 128Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-zkhkk
name: default-token-4bcbi
readOnly: true
dnsPolicy: ClusterFirst
nodeName: kubernetes-node-u619
nodeName: kubernetes-node-wul5
restartPolicy: Always
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
volumes:
- name: default-token-zkhkk
- name: default-token-4bcbi
secret:
secretName: default-token-zkhkk
secretName: default-token-4bcbi
status:
conditions:
- status: "True"
- lastProbeTime: null
lastTransitionTime: 2016-03-24T01:39:51Z
status: "True"
type: Ready
containerStatuses:
- containerID: docker://9506ace0eb91fbc31aef1d249e0d1d6d6ef5ebafc60424319aad5b12e3a4e6a9
- containerID: docker://90315cc9f513c724e9957a4788d3e625a078de84750f244a40f97ae355eb1149
image: nginx
imageID: docker://319d2015d149943ff4d2a20ddea7d7e5ce06a64bbab1792334c0d3273bbbff1e
imageID: docker://6f62f48c4e55d700cf3eb1b5e33fa051802986b77b874cc351cce539e5163707
lastState: {}
name: nginx
ready: true
restartCount: 0
state:
running:
startedAt: 2015-07-10T06:56:28Z
hostIP: 10.240.112.234
startedAt: 2016-03-24T01:39:51Z
hostIP: 10.240.0.9
phase: Running
podIP: 10.244.3.4
startTime: 2015-07-10T06:56:21Z
podIP: 10.244.0.6
startTime: 2016-03-24T01:39:49Z
```
## Example: debugging a down/unreachable node

View File

@ -181,6 +181,45 @@ sometimes be started twice.
If you do specify `.spec.parallelism` and `.spec.completions` both greater than 1, then there may be
multiple pods running at once. Therefore, your pods must also be tolerant of concurrency.
## Job Termination and Cleanup
When a Job completes, no more Pods are created, but the Pods are not deleted either. Since they are terminated,
they don't show up with `kubectl get pods`, but they will show up with `kubectl get pods -a`. Keeping them around
allows you to still view the logs of completed pods to check for errors, warnings, or other diagnostic output.
The job object also remains after it is completed so that you can view its status. It is up to the user to delete
old jobs after noting their status. Delete the job with `kubectl` (e.g. `kubectl delete jobs/pi` or `kubectl delete -f ./job.yaml`). When you delete the job using `kubectl`, all the pods it created are deleted too.
If a Job's pods are failing repeatedly, the Job will keep creating new pods forever, by default.
Retrying forever can be a useful pattern. If an external dependency of the Job's
pods is missing (for example an input file on a networked storage volume is not present), then the
Job will keep trying Pods, and when you later resolve the external dependency (for example, creating
the missing file) the Job will then complete without any further action.
However, if you prefer not to retry forever, you can set a deadline on the job. Do this by setting the
`spec.activeDeadlineSeconds` field of the job to a number of seconds. The job will have status with
`reason: DeadlineExceeded`. No more pods will be created, and existing pods will be deleted.
```yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-timeout
spec:
activeDeadlineSeconds: 100
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
```
Note that both the Job Spec and the Pod Template Spec within the Job have a field with the same name.
Set the one on the Job.
## Job Patterns
The Job object can be used to support reliable parallel execution of Pods. The Job object is not
@ -214,7 +253,7 @@ The pattern names are also links to examples and more detailed description.
| -------------------------------------------------------------------------- |:-----------------:|:---------------------------:|:-------------------:|:-------------------:|
| [Job Template Expansion](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/job/expansions/README.md) | | | ✓ | ✓ |
| [Queue with Pod Per Work Item](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/job/work-queue-1/README.md) | ✓ | | sometimes | ✓ |
| [Queue with Variable Pod Count](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/job/work-queue-2/README.md) | | ✓ | ✓ | | ✓ |
| [Queue with Variable Pod Count](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/job/work-queue-2/README.md) | ✓ | ✓ | | ✓ |
| Single Job with Static Work Assignment | ✓ | | ✓ | |
When you specify completions with `.spec.completions`, each Pod created by the Job controller
@ -333,5 +372,4 @@ object, but complete control over what pods are created and how work is assigned
## Future work
Support for creating Jobs at specified times/dates (i.e. cron) is expected in the next minor
release.
Support for creating Jobs at specified times/dates (i.e. cron) is expected in [1.3](https://github.com/kubernetes/kubernetes/pull/11980).

View File

@ -105,7 +105,7 @@ after kubeconfig is loaded/merged. Available credentials are `client-certificate
`client-key`, `token`, and `username/password`. `username/password` and `token`
are mutually exclusive, but client certs and keys can be combined with them.
You can add or modify `user` entries using
[`kubectl config set-credentials`](kubectl/kubectl_config_set-credentials.md).
[`kubectl config set-credentials`](/docs/user-guide/kubectl/kubectl_config_set-credentials).
#### context
@ -118,13 +118,13 @@ contexts:
name: federal-context
```
A `context` defines a named [`cluster`](#cluster),[`user`](#user),[`namespace`](namespaces.md) tuple
A `context` defines a named [`cluster`](#cluster),[`user`](#user),[`namespace`](/docs/user-guide/namespaces) tuple
which is used to send requests to the specified cluster using the provided authentication info and
namespace. Each of the three is optional; it is valid to specify a context with only one of `cluster`,
`user`,`namespace`, or to specify none. Unspecified values, or named values that don't have corresponding
entries in the loaded kubeconfig (e.g. if the context specified a `pink-user` for the above kubeconfig file)
will be replaced with the default. See [Loading and merging rules](#loading-and-merging) below for override/merge behavior.
You can add or modify `context` entries with [`kubectl config set-conext`](kubectl/kubectl_config_set-context.md).
You can add or modify `context` entries with [`kubectl config set-context`](/docs/user-guide/kubectl/kubectl_config_set-context).
#### current-context
@ -135,7 +135,7 @@ current-context: federal-context
`current-context` is the nickname or 'key' for the cluster,user,namespace tuple that kubectl
will use by default when loading config from this file. You can override any of the values in kubectl
from the commandline, by passing `--context=CONTEXT`, `--cluster=CLUSTER`, `--user=USER`, and/or `--namespace=NAMESPACE` respectively.
You can change the `current-context` with [`kubectl config use-context`](kubectl/kubectl_config_use-context.md).
You can change the `current-context` with [`kubectl config use-context`](/docs/user-guide/kubectl/kubectl_config_use-context).
#### miscellaneous
@ -156,7 +156,7 @@ be edited manually.
`kubectl config view` will display the current kubeconfig settings. By default
it will show you all loaded kubeconfig settings; you can filter the view to just
the settings relevant to the `current-context` by passing `--minify`. See
[`kubectl config view`](kubectl/kubectl_config_view.md) for other options.
[`kubectl config view`](/docs/user-guide/kubectl/kubectl_config_view) for other options.
## Building your own kubeconfig file

View File

@ -0,0 +1,30 @@
---
---
* TOC
{:toc}
## Using `kubectl` in Reusable Scripts
If you need stable output in a script, you should:
* Request one of the machine-oriented output forms, such as `-o name`, `-o json`, `-o yaml`, `-o go-template`, or `-o jsonpath`
* Specify `--output-version`, since those output forms (other than `-o name`) output the resource using a particular API version
* Specify `--generator` to pin to a specific behavior forever, if using generator-based commands (such as `kubectl run` or `kubectl expose`)
* Don't rely on context, preferences, or other implicit state
## Best Practices
### `kubectl run`
In order for `kubectl run` to satisfy infrastructure as code:
* Always tag your image with a version-specific tag and don't move that tag to a new version. For example, use `:v1234`, `v1.2.3`, `r03062016-1-4`, rather than `:latest` (see [Best Practices for Configuration](/docs/user-guide/config-best-practices/#container-images) for more information.)
* If the image is lightly parameterized, capture the parameters in a checked-in script, or at least use `--record`, to annotate the created objects with the command line.
* If the image is heavily parameterized, definitely check in the script.
* If features are needed that are not expressible via `kubectl run` flags, switch to configuration files checked into source control.
* Pin to a specific generator version, such as `kubectl run --generator=deployment/v1beta1`
### `kubectl apply`
* To use `kubectl apply` to update resources, always create resources initially with `kubectl apply` or with `--save-config`. See [managing resources with kubectl apply](/docs/user-guide/managing-deployments/#kubectl-apply) for the reason behind it.

View File

@ -269,4 +269,4 @@ $ kubectl logs -f <pod-name>
## Next steps
Start using the [kubectl](/docs/user-guide/kubectl/kubectl) commands.
Start using the [kubectl](/docs/user-guide/kubectl/kubectl) commands.

View File

@ -45,37 +45,37 @@ kubectl
### SEE ALSO
* [kubectl annotate](kubectl_annotate/) - Update the annotations on a resource
* [kubectl api-versions](kubectl_api-versions/) - Print the supported API versions on the server, in the form of "group/version".
* [kubectl apply](kubectl_apply/) - Apply a configuration to a resource by filename or stdin
* [kubectl attach](kubectl_attach/) - Attach to a running container.
* [kubectl autoscale](kubectl_autoscale/) - Auto-scale a deployment or replication controller
* [kubectl cluster-info](kubectl_cluster-info/) - Display cluster info
* [kubectl config](kubectl_config/) - config modifies kubeconfig files
* [kubectl convert](kubectl_convert/) - Convert config files between different API versions
* [kubectl cordon](kubectl_cordon/) - Mark node as unschedulable
* [kubectl create](kubectl_create/) - Create a resource by filename or stdin
* [kubectl delete](kubectl_delete/) - Delete resources by filenames, stdin, resources and names, or by resources and label selector.
* [kubectl describe](kubectl_describe/) - Show details of a specific resource or group of resources
* [kubectl drain](kubectl_drain/) - Drain node in preparation for maintenance
* [kubectl edit](kubectl_edit/) - Edit a resource on the server
* [kubectl exec](kubectl_exec/) - Execute a command in a container.
* [kubectl explain](kubectl_explain/) - Documentation of resources.
* [kubectl expose](kubectl_expose/) - Take a replication controller, service or pod and expose it as a new Kubernetes Service
* [kubectl get](kubectl_get/) - Display one or many resources
* [kubectl label](kubectl_label/) - Update the labels on a resource
* [kubectl logs](kubectl_logs/) - Print the logs for a container in a pod.
* [kubectl namespace](kubectl_namespace/) - SUPERSEDED: Set and view the current Kubernetes namespace
* [kubectl patch](kubectl_patch/) - Update field(s) of a resource using strategic merge patch.
* [kubectl port-forward](kubectl_port-forward/) - Forward one or more local ports to a pod.
* [kubectl proxy](kubectl_proxy/) - Run a proxy to the Kubernetes API server
* [kubectl replace](kubectl_replace/) - Replace a resource by filename or stdin.
* [kubectl rolling-update](kubectl_rolling-update/) - Perform a rolling update of the given ReplicationController.
* [kubectl rollout](kubectl_rollout/) - rollout manages a deployment
* [kubectl run](kubectl_run/) - Run a particular image on the cluster.
* [kubectl scale](kubectl_scale/) - Set a new size for a Replication Controller, Job, or Deployment.
* [kubectl uncordon](kubectl_uncordon/) - Mark node as schedulable
* [kubectl version](kubectl_version/) - Print the client and server version information.
* [kubectl annotate](/docs/user-guide/kubectl/kubectl_annotate/) - Update the annotations on a resource
* [kubectl api-versions](/docs/user-guide/kubectl/kubectl_api-versions/) - Print the supported API versions on the server, in the form of "group/version".
* [kubectl apply](/docs/user-guide/kubectl/kubectl_apply/) - Apply a configuration to a resource by filename or stdin
* [kubectl attach](/docs/user-guide/kubectl/kubectl_attach/) - Attach to a running container.
* [kubectl autoscale](/docs/user-guide/kubectl/kubectl_autoscale/) - Auto-scale a deployment or replication controller
* [kubectl cluster-info](/docs/user-guide/kubectl/kubectl_cluster-info/) - Display cluster info
* [kubectl config](/docs/user-guide/kubectl/kubectl_config/) - config modifies kubeconfig files
* [kubectl convert](/docs/user-guide/kubectl/kubectl_convert/) - Convert config files between different API versions
* [kubectl cordon](/docs/user-guide/kubectl/kubectl_cordon/) - Mark node as unschedulable
* [kubectl create](/docs/user-guide/kubectl/kubectl_create/) - Create a resource by filename or stdin
* [kubectl delete](/docs/user-guide/kubectl/kubectl_delete/) - Delete resources by filenames, stdin, resources and names, or by resources and label selector.
* [kubectl describe](/docs/user-guide/kubectl/kubectl_describe/) - Show details of a specific resource or group of resources
* [kubectl drain](/docs/user-guide/kubectl/kubectl_drain/) - Drain node in preparation for maintenance
* [kubectl edit](/docs/user-guide/kubectl/kubectl_edit/) - Edit a resource on the server
* [kubectl exec](/docs/user-guide/kubectl/kubectl_exec/) - Execute a command in a container.
* [kubectl explain](/docs/user-guide/kubectl/kubectl_explain/) - Documentation of resources.
* [kubectl expose](/docs/user-guide/kubectl/kubectl_expose/) - Take a replication controller, service or pod and expose it as a new Kubernetes Service
* [kubectl get](/docs/user-guide/kubectl/kubectl_get/) - Display one or many resources
* [kubectl label](/docs/user-guide/kubectl/kubectl_label/) - Update the labels on a resource
* [kubectl logs](/docs/user-guide/kubectl/kubectl_logs/) - Print the logs for a container in a pod.
* [kubectl namespace](/docs/user-guide/kubectl/kubectl_namespace/) - SUPERSEDED: Set and view the current Kubernetes namespace
* [kubectl patch](/docs/user-guide/kubectl/kubectl_patch/) - Update field(s) of a resource using strategic merge patch.
* [kubectl port-forward](/docs/user-guide/kubectl/kubectl_port-forward/) - Forward one or more local ports to a pod.
* [kubectl proxy](/docs/user-guide/kubectl/kubectl_proxy/) - Run a proxy to the Kubernetes API server
* [kubectl replace](/docs/user-guide/kubectl/kubectl_replace/) - Replace a resource by filename or stdin.
* [kubectl rolling-update](/docs/user-guide/kubectl/kubectl_rolling-update/) - Perform a rolling update of the given ReplicationController.
* [kubectl rollout](/docs/user-guide/kubectl/kubectl_rollout/) - rollout manages a deployment
* [kubectl run](/docs/user-guide/kubectl/kubectl_run/) - Run a particular image on the cluster.
* [kubectl scale](/docs/user-guide/kubectl/kubectl_scale/) - Set a new size for a Replication Controller, Job, or Deployment.
* [kubectl uncordon](/docs/user-guide/kubectl/kubectl_uncordon/) - Mark node as schedulable
* [kubectl version](/docs/user-guide/kubectl/kubectl_version/) - Print the client and server version information.
###### Auto generated by spf13/cobra on 2-Mar-2016

View File

@ -95,6 +95,6 @@ kubectl annotate pods foo description-
### SEE ALSO
* [kubectl](kubectl/) - kubectl controls the Kubernetes cluster manager
* [kubectl](/docs/user-guide/kubectl/kubectl/) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 11-Mar-2016

View File

@ -42,6 +42,6 @@ kubectl api-versions
### SEE ALSO
* [kubectl](kubectl/) - kubectl controls the Kubernetes cluster manager
* [kubectl](/docs/user-guide/kubectl/kubectl/) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 2-Mar-2016

Some files were not shown because too many files have changed in this diff Show More