Merge branch 'master' into release-1.13

This commit is contained in:
Jim Angel
2019-03-16 17:14:47 -05:00
908 changed files with 37407 additions and 8650 deletions
+2
View File
@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
# This is the directory for English source content.
# Teams and members are visible at https://github.com/orgs/kubernetes/teams.
+3 -3
View File
@@ -8,7 +8,7 @@ cid: home
{{< blocks/section id="oceanNodes" >}}
{{% blocks/feature image="flower" %}}
### [Kubernetes]({{< relref "/docs/concepts/overview/what-is-kubernetes" >}}) is an open-source system for automating deployment, scaling, and management of containerized applications.
### [Kubernetes (K8s)]({{< relref "/docs/concepts/overview/what-is-kubernetes" >}}) is an open-source system for automating deployment, scaling, and management of containerized applications.
It groups containers that make up an application into logical units for easy management and discovery. Kubernetes builds upon [15 years of experience of running production workloads at Google](http://queue.acm.org/detail.cfm?id=2898444), combined with best-of-breed ideas and practices from the community.
{{% /blocks/feature %}}
@@ -44,12 +44,12 @@ Kubernetes is open source giving you the freedom to take advantage of on-premise
<br>
<br>
<br>
<a href="https://www.lfasiallc.com/events/kubecon-cloudnativecon-china-2018/" button id="desktopKCButton">Attend KubeCon in Shanghai on Nov. 13-15, 2018</a>
<a href="https://events.linuxfoundation.org/events/kubecon-cloudnativecon-europe-2019" button id="desktopKCButton">Attend KubeCon in Barcelona on May 20-23, 2019</a>
<br>
<br>
<br>
<br>
<a href="https://events.linuxfoundation.org/events/kubecon-cloudnativecon-north-america-2018/" button id="desktopKCButton">Attend KubeCon in Seattle on Dec. 11-13, 2018</a>
<a href="https://www.lfasiallc.com/events/kubecon-cloudnativecon-china-2019" button id="desktopKCButton">Attend KubeCon in Shanghai on June 24-26, 2019</a>
</div>
<div id="videoPlayer">
<iframe data-url="https://www.youtube.com/embed/H06qrNmGqyE?autoplay=1" frameborder="0" allowfullscreen></iframe>
+2
View File
@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
# Owned by Kubernetes Blog reviewers.
options:
no_parent_owners: false
@@ -37,11 +37,11 @@ Every week the Kubernetes contributing community meet virtually over Google Hang
* additional status - additive, backward compatible
* elimination of phase - won't make it for v1
* Service discussion - Public IPs
* with public ips as it exists we can't go to v1
* with public IPs as it exists we can't go to v1
* Tim has been developing a mitigation if we can't get Justin's overhaul in (but hopefully we will)
* Justin's fix will describe public IPs in a much better way
* The general problem is it's too flexible and you can do things that are scary, the mitigation is to restrict public ip usage to specific use cases -- validated public ips would be copied to status, which is what kube-proxy would use
* public ips used for -
* The general problem is it's too flexible and you can do things that are scary, the mitigation is to restrict public ip usage to specific use cases -- validated public IPs would be copied to status, which is what kube-proxy would use
* public IPs used for -
* binding to nodes / node
* request a specific load balancer IP (GCE only)
* emulate multi-port services -- now we support multi-port services, so no longer necessary
@@ -27,7 +27,7 @@ E2E issues and LGTM process
* Question/concern to work out is securing Jenkins. Short term conclusion: Will look at pushing Jenkins logs into GCS bucket. Lavalamp will follow up with Jeff Grafton.
* Longer term solution may be a merge queue, where e2e runs for each merge (as opposed to multiple merges). This exists in Openshift today.
* Longer term solution may be a merge queue, where e2e runs for each merge (as opposed to multiple merges). This exists in OpenShift today.
Cluster Upgrades for Kubernetes as final v1 feature
@@ -131,7 +131,7 @@ Cluster Federation is a control plane of cluster federation in Kubernetes. It of
![Screen Shot 2016-07-07 at 1.46.55 PM.png](https://lh6.googleusercontent.com/jJjQ6wbYYG1y7rS7SXFNj1dsLrTEBbiOB9TfrkJAqayHVzBZwLguxMB6HLObCgpVGLKF7xdPd3wfdvQzB2a7Cq6cuqqXRRl3L5OfVPwKB34BxdpRUc1g7EgOdEkILH9E4sAfzHyb)
Each Kubernetes cluster exposes an API endpoint and gets registered to Cluster Federation as a part of Federation object. Then using Cluster Federation API, you can create federated services. Those objects are comprised of multiple equivalent underlying Kubernetes resources. Assuming that the 3 clusters on the picture above belong to the same Federation object, each Service created via Cluster Federation, will get equivalent service created in each of the clusters. Besides that, a Cluster Federation service will get publicly resolvable DNS name resolvable to Kuberentes services public ip addresses (DNS record gets programmed to a one of the public DNS providers below):
Each Kubernetes cluster exposes an API endpoint and gets registered to Cluster Federation as a part of Federation object. Then using Cluster Federation API, you can create federated services. Those objects are comprised of multiple equivalent underlying Kubernetes resources. Assuming that the 3 clusters on the picture above belong to the same Federation object, each Service created via Cluster Federation, will get equivalent service created in each of the clusters. Besides that, a Cluster Federation service will get publicly resolvable DNS name resolvable to Kubernetes services public ip addresses (DNS record gets programmed to a one of the public DNS providers below):
@@ -4,6 +4,8 @@ date: 2016-08-31
slug: security-best-practices-kubernetes-deployment
url: /blog/2016/08/Security-Best-Practices-Kubernetes-Deployment
---
_Note: some of the recommendations in this post are no longer current. Current cluster hardening options are described in this [documentation](https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/)._
_Editors note: todays post is by Amir Jerbi and Michael Cherny of Aqua Security, describing security best practices for Kubernetes deployments, based on data theyve collected from various use-cases seen in both on-premises and cloud deployments._
Kubernetes provides many controls that can greatly improve your application security. Configuring them requires intimate knowledge with Kubernetes and the deployments security requirements. The best practices we highlight here are aligned to the container lifecycle: build, ship and run, and are specifically tailored to Kubernetes deployments. We adopted these best practices in [our own SaaS deployment](http://blog.aquasec.com/running-a-security-service-in-google-cloud-real-world-example) that runs Kubernetes on Google Cloud Platform.
@@ -18,7 +18,7 @@ We see kompose as a terrific way to expose Kubernetes principles to Docker users
Over the summer, Kompose has found a new gear with help from Tomas Kral and Suraj Deshmukh from Red Hat, and Janet Kuo from Google. Together with our own lead kompose developer Nguyen An-Tu they are making kompose even more exciting. We proposed Kompose to the Kubernetes Incubator within the SIG-apps and we received approval from the general Kubernetes community; you can now find kompose in the [Kubernetes Incubator](https://github.com/kubernetes-incubator/kompose).
Kompose now supports Docker-compose v2 format, persistent volume claims have been added recently, as well as multiple container per pods. It can also be used to target Openshift deployments, by specifying a different provider than the default Kubernetes. Kompose is also now available in Fedora packages and we look forward to see it in CentOS distributions in the coming weeks.
Kompose now supports Docker-compose v2 format, persistent volume claims have been added recently, as well as multiple container per pods. It can also be used to target OpenShift deployments, by specifying a different provider than the default Kubernetes. Kompose is also now available in Fedora packages and we look forward to see it in CentOS distributions in the coming weeks.
kompose is a single Golang binary that you build or install from the [release on GitHub](https://github.com/kubernetes-incubator/kompose). Lets skip the build instructions and dive straight into an example.
@@ -19,7 +19,7 @@ I was able to run more processes on a single physical server than I could using
To orchestrate container deployment, we are using[Armada infrastructure](https://console.bluemix.net/containers-kubernetes/launch), a Kubernetes implementation by IBM for automating deployment, scaling, and operations of application containers across clusters of hosts, providing container-centric infrastructure.
To orchestrate container deployment, we are using [IBM Cloud Kubernetes Service infrastructure](https://cloud.ibm.com/containers-kubernetes/landing), a Kubernetes implementation by IBM for automating deployment, scaling, and operations of application containers across clusters of hosts, providing container-centric infrastructure.
@@ -39,7 +39,7 @@ Here is a snapshot of Watson Care Manager, running inside a Kubernetes cluster:
Before deploying an app, a user must create a worker node cluster. I can create a cluster using the kubectl cli commands or create it from[a Bluemix](http://bluemix.net/) dashboard.
Before deploying an app, a user must create a worker node cluster. I can create a cluster using the kubectl cli commands or create it from the [IBM Cloud](https://cloud.ibm.com/) dashboard.
@@ -107,16 +107,16 @@ If needed, run a rolling update to update the existing pod.
Deploying the application in Armada:
Deploying the application in IBM Cloud Kubernetes Service:
Provision a cluster in Armada with \<x\> worker nodes. Create Kubernetes controllers for deploying the containers in worker nodes, the Armada infrastructure pulls the Docker images from IBM Bluemix Docker registry to create containers. We tried deploying an application container and running a logmet agent (see Reading and displaying logs using logmet container, below) inside the containers that forwards the application logs to an IBM cloud logging service. As part of the process, YAML files are used to create a controller resource for the UrbanCode Deploy (UCD). UCD agent is deployed as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) controller, which is used to connect to the UCD server. The whole process of deployment of application happens in UCD. To support the application for public access, we created a service resource to interact between pods and access container services. For storage support, we created persistent volume claims and mounted the volume for the containers.
Provision a cluster in IBM Cloud Kubernetes Service with \<x\> worker nodes. Create Kubernetes controllers for deploying the containers in worker nodes, the IBM Cloud Kubernetes Service infrastructure pulls the Docker images from IBM Cloud Container Registry to create containers. We tried deploying an application container and running a logmet agent (see Reading and displaying logs using logmet container, below) inside the containers that forwards the application logs to an IBM Cloud logging service. As part of the process, YAML files are used to create a controller resource for the UrbanCode Deploy (UCD). UCD agent is deployed as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) controller, which is used to connect to the UCD server. The whole process of deployment of application happens in UCD. To support the application for public access, we created a service resource to interact between pods and access container services. For storage support, we created persistent volume claims and mounted the volume for the containers.
| ![](https://lh6.googleusercontent.com/iFKlbBX8rjWTuygIfjImdxP8R7xXuvaaoDwldEIC3VRL03XIehxagz8uePpXllYMSxoyai5a6N-0NB4aTGK9fwwd8leFyfypxtbmaWBK-b2Kh9awcA76-_82F7ZZl7lgbf0gyFN7) |
| UCD: IBM UrbanCode Deploy is a tool for automating application deployments through your environments. Armada: Kubernetes implementation of IBM. WH Docker Registry: Docker Private image registry. Common agent containers: We expect to configure our services to use the WHC mandatory agents. We deployed all ion containers. |
| UCD: IBM UrbanCode Deploy is a tool for automating application deployments through your environments. IBM Cloud Kubernetes Service: Kubernetes implementation of IBM. WH Docker Registry: Docker Private image registry. Common agent containers: We expect to configure our services to use the WHC mandatory agents. We deployed all ion containers. |
@@ -142,7 +142,7 @@ Exposing services with Ingress:
To expose our services to outside the cluster, we used Ingress. In Armada, if we create a paid cluster, an Ingress controller is automatically installed for us to use. We were able to access services through Ingress by creating a YAML resource file that specifies the service path.
To expose our services to outside the cluster, we used Ingress. In IBM Cloud Kubernetes Service, if we create a paid cluster, an Ingress controller is automatically installed for us to use. We were able to access services through Ingress by creating a YAML resource file that specifies the service path.
@@ -94,7 +94,7 @@ If youd like to try out Kubeflow, we have a number of options for you:
1. You can use sample walkthroughs hosted on [Katacoda](https://www.katacoda.com/kubeflow)
2. You can follow a guided tutorial with existing models from the [examples repository](https://github.com/kubeflow/examples). These include the [Github Issue Summarization](https://github.com/kubeflow/examples/tree/master/github_issue_summarization), [MNIST](https://github.com/kubeflow/examples/tree/master/mnist) and [Reinforcement Learning with Agents](https://github.com/kubeflow/examples/tree/master/agents).
3. You can start a cluster on your own and try your own model. Any Kubernetes conformant cluster will support Kubeflow including those from contributors [Caicloud](https://www.prnewswire.com/news-releases/caicloud-releases-its-kubernetes-based-cluster-as-a-service-product-claas-20-and-the-first-tensorflow-as-a-service-taas-11-while-closing-6m-series-a-funding-300418071.html), [Canonical](https://jujucharms.com/canonical-kubernetes/), [Google](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-container-cluster), [Heptio](https://heptio.com/products/kubernetes-subscription/), [Mesosphere](https://github.com/mesosphere/dcos-kubernetes-quickstart), [Microsoft](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough), [IBM](https://console.bluemix.net/docs/containers/cs_tutorials.html#cs_cluster_tutorial), [Red Hat/Openshift ](https://docs.openshift.com/container-platform/3.3/install_config/install/quick_install.html#install-config-install-quick-install)and [Weaveworks](https://www.weave.works/product/cloud/).
3. You can start a cluster on your own and try your own model. Any Kubernetes conformant cluster will support Kubeflow including those from contributors [Caicloud](https://www.prnewswire.com/news-releases/caicloud-releases-its-kubernetes-based-cluster-as-a-service-product-claas-20-and-the-first-tensorflow-as-a-service-taas-11-while-closing-6m-series-a-funding-300418071.html), [Canonical](https://jujucharms.com/canonical-kubernetes/), [Google](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-container-cluster), [Heptio](https://heptio.com/products/kubernetes-subscription/), [Mesosphere](https://github.com/mesosphere/dcos-kubernetes-quickstart), [Microsoft](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough), [IBM](https://cloud.ibm.com/docs/containers?topic=containers-cs_cluster_tutorial#cs_cluster_tutorial), [Red Hat/Openshift ](https://docs.openshift.com/container-platform/3.3/install_config/install/quick_install.html#install-config-install-quick-install)and [Weaveworks](https://www.weave.works/product/cloud/).
There were also a number of sessions at KubeCon + CloudNativeCon EU 2018 covering Kubeflow. The links to the talks are here; the associated videos will be posted in the coming days.
@@ -109,7 +109,7 @@ For a detailed list of changes in the containerd 1.1 release, please see the rel
To setup a Kubernetes cluster using containerd as the container runtime:
* For a production quality cluster on GCE brought up with kube-up.sh, see [here](https://github.com/containerd/cri/blob/v1.0.0/docs/kube-up.md).
* For a multi-node cluster installer and bring up steps using ansible and kubeadm, see [here](https://github.com/containerd/cri/blob/v1.0.0/contrib/ansible/README.md).
* For a multi-node cluster installer and bring up steps using Ansible and kubeadm, see [here](https://github.com/containerd/cri/blob/v1.0.0/contrib/ansible/README.md).
* For creating a cluster from scratch on Google Cloud, see [Kubernetes the Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way).
* For a custom installation from release tarball, see [here](https://github.com/containerd/cri/blob/v1.0.0/docs/installation.md).
* To install using LinuxKit on a local VM, see [here](https://github.com/linuxkit/linuxkit/tree/master/projects/kubernetes).
@@ -0,0 +1,172 @@
---
layout: blog
title: 'gRPC Load Balancing on Kubernetes without Tears'
date: 2018-11-07
---
**Author**: William Morgan (Buoyant)
Many new gRPC users are surprised to find that Kubernetes's default load
balancing often doesn't work out of the box with gRPC. For example, here's what
happens when you take a [simple gRPC Node.js microservices
app](https://github.com/sourishkrout/nodevoto) and deploy it on Kubernetes:
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0116-c4d86100-afc1-4a08-a01c-16da391756dd.34.36.png)
While the `voting` service displayed here has several pods, it's clear from
Kubernetes's CPU graphs that only one of the pods is actually doing any
work&mdash;because only one of the pods is receiving any traffic. Why?
In this blog post, we describe why this happens, and how you can easily fix it
by adding gRPC load balancing to any Kubernetes app with
[Linkerd](https://linkerd.io), a [CNCF](https://cncf.io) service mesh and service sidecar.
# Why does gRPC need special load balancing?
First, let's understand why we need to do something special for gRPC.
gRPC is an increasingly common choice for application developers. Compared to
alternative protocols such as JSON-over-HTTP, gRPC can provide some significant
benefits, including dramatically lower (de)serialization costs, automatic type
checking, formalized APIs, and less TCP management overhead.
However, gRPC also breaks the standard connection-level load balancing,
including what's provided by Kubernetes. This is because gRPC is built on
HTTP/2, and HTTP/2 is designed to have a single long-lived TCP connection,
across which all requests are *multiplexed*&mdash;meaning multiple requests can be
active on the same connection at any point in time. Normally, this is great, as
it reduces the overhead of connection management. However, it also means that
(as you might imagine) connection-level balancing isn't very useful. Once the
connection is established, there's no more balancing to be done. All requests
will get pinned to a single destination pod, as shown below:
![](/images/blog/grpc-load-balancing-with-linkerd/Mono-8d2e53ef-b133-4aa0-9551-7e36a880c553.png)
# Why doesn't this affect HTTP/1.1?
The reason why this problem doesn't occur in HTTP/1.1, which also has the
concept of long-lived connections, is because HTTP/1.1 has several features
that naturally result in cycling of TCP connections. Because of this,
connection-level balancing is "good enough", and for most HTTP/1.1 apps we
don't need to do anything more.
To understand why, let's take a deeper look at HTTP/1.1. In contrast to HTTP/2,
HTTP/1.1 cannot multiplex requests. Only one HTTP request can be active at a
time per TCP connection. The client makes a request, e.g. `GET /foo`, and then
waits until the server responds. While that request-response cycle is
happening, no other requests can be issued on that connection.
Usually, we want lots of requests happening in parallel. Therefore, to have
concurrent HTTP/1.1 requests, we need to make multiple HTTP/1.1 connections,
and issue our requests across all of them. Additionally, long-lived HTTP/1.1
connections typically expire after some time, and are torn down by the client
(or server). These two factors combined mean that HTTP/1.1 requests typically
cycle across multiple TCP connections, and so connection-level balancing works.
# So how do we load balance gRPC?
Now back to gRPC. Since we can't balance at the connection level, in order to
do gRPC load balancing, we need to shift from connection balancing to *request*
balancing. In other words, we need to open an HTTP/2 connection to each
destination, and balance *requests* across these connections, as shown below:
![](/images/blog/grpc-load-balancing-with-linkerd/Stereo-09aff9d7-1c98-4a0a-9184-9998ed83a531.png)
In network terms, this means we need to make decisions at L5/L7 rather than
L3/L4, i.e. we need to understand the protocol sent over the TCP connections.
How do we accomplish this? There are a couple options. First, our application
code could manually maintain its own load balancing pool of destinations, and
we could configure our gRPC client to [use this load balancing
pool](https://godoc.org/google.golang.org/grpc/balancer). This approach gives
us the most control, but it can be very complex in environments like Kubernetes
where the pool changes over time as Kubernetes reschedules pods. Our
application would have to watch the Kubernetes API and keep itself up to date
with the pods.
Alternatively, in Kubernetes, we could deploy our app as [headless
services](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services).
In this case, Kubernetes [will create multiple A
records](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services)
in the DNS entry for the service. If our gRPC client is sufficiently advanced,
it can automatically maintain the load balancing pool from those DNS entries.
But this approach restricts us to certain gRPC clients, and it's rarely
possible to only use headless services.
Finally, we can take a third approach: use a lightweight proxy.
# gRPC load balancing on Kubernetes with Linkerd
[Linkerd](https://linkerd.io) is a [CNCF](https://cncf.io)-hosted *service
mesh* for Kubernetes. Most relevant to our purposes, Linkerd also functions as
a *service sidecar*, where it can be applied to a single service&mdash;even without
cluster-wide permissions. What this means is that when we add Linkerd to our
service, it adds a tiny, ultra-fast proxy to each pod, and these proxies watch
the Kubernetes API and do gRPC load balancing automatically. Our deployment
then looks like this:
![](/images/blog/grpc-load-balancing-with-linkerd/Linkerd-8df1031c-cdd1-4164-8e91-00f2d941e93f.io.png)
Using Linkerd has a couple advantages. First, it works with services written in
any language, with any gRPC client, and any deployment model (headless or not).
Because Linkerd's proxies are completely transparent, they auto-detect HTTP/2
and HTTP/1.x and do L7 load balancing, and they pass through all other traffic
as pure TCP. This means that everything will *just work.*
Second, Linkerd's load balancing is very sophisticated. Not only does Linkerd
maintain a watch on the Kubernetes API and automatically update the load
balancing pool as pods get rescheduled, Linkerd uses an *exponentially-weighted
moving average* of response latencies to automatically send requests to the
fastest pods. If one pod is slowing down, even momentarily, Linkerd will shift
traffic away from it. This can reduce end-to-end tail latencies.
Finally, Linkerd's Rust-based proxies are incredibly fast and small. They
introduce <1ms of p99 latency and require <10mb of RSS per pod, meaning that
the impact on system performance will be negligible.
# gRPC Load Balancing in 60 seconds
Linkerd is very easy to try. Just follow the steps in the [Linkerd Getting
Started Instructions](https://linkerd.io/2/getting-started/)&mdash;install the
CLI on your laptop, install the control plane on your cluster, and "mesh" your
service (inject the proxies into each pod). You'll have Linkerd running on your
service in no time, and should see proper gRPC balancing immediately.
Let's take a look at our sample `voting` service again, this time after
installing Linkerd:
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0116-24b8ee81-144c-4eac-b73d-871bbf0ea22e.57.42.png)
As we can see, the CPU graphs for all pods are active, indicating that all pods
are now taking traffic&mdash;without having to change a line of code. Voila,
gRPC load balancing as if by magic!
Linkerd also gives us built-in traffic-level dashboards, so we don't even need
to guess what's happening from CPU charts any more. Here's a Linkerd graph
that's showing the success rate, request volume, and latency percentiles of
each pod:
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0212-15ed0448-5424-4e47-9828-20032de868b5.08.38.png)
We can see that each pod is getting around 5 RPS. We can also see that, while
we've solved our load balancing problem, we still have some work to do on our
success rate for this service. (The demo app is built with an intentional
failure&mdash;as an exercise to the reader, see if you can figure it out by
using the Linkerd dashboard!)
# Wrapping it up
If you're interested in a dead simple way to add gRPC load balancing to your
Kubernetes services, regardless of what language it's written in, what gRPC
client you're using, or how it's deployed, you can use Linkerd to add gRPC load
balancing in a few commands.
There's a lot more to Linkerd, including security, reliability, and debugging
and diagnostics features, but those are topics for future blog posts.
Want to learn more? Wed love to have you join our rapidly-growing community!
Linkerd is a [CNCF](https://cncf.io) project, [hosted on
GitHub](https://github.com/linkerd/linkerd2), and has a thriving community
on [Slack](https://slack.linkerd.io), [Twitter](https://twitter.com/linkerd),
and the [mailing lists](https://lists.cncf.io/g/cncf-linkerd-users). Come and
join the fun!
@@ -0,0 +1,41 @@
---
layout: blog
title: 'New Contributor Workshop Shanghai'
date: 2018-12-05
---
**Authors**: Josh Berkus (Red Hat), Yang Li (The Plant), Puja Abbassi (Giant Swarm), XiangPeng Zhao (ZTE)
{{< figure src="/images/blog/2018-12-05-new-contributor-shanghai/attendees.png" caption="Kubecon Shanghai New Contributor Summit attendees. Photo by Jerry Zhang" >}}
We recently completed our first New Contributor Summit in China, at the first KubeCon in China. It was very exciting to see all of the Chinese and Asian developers (plus a few folks from around the world) interested in becoming contributors. Over the course of a long day, they learned how, why, and where to contribute to Kubernetes, created pull requests, attended a panel of current contributors, and got their CLAs signed.
This was our second New Contributor Workshop (NCW), building on the one created and led by SIG Contributor Experience members in Copenhagen. Because of the audience, it was held in both Chinese and English, taking advantage of the superb simultaneous interpretation services the CNCF sponsored. Likewise, the NCW team included both English and Chinese-speaking members of the community: Yang Li, XiangPeng Zhao, Puja Abbassi, Noah Abrahams, Tim Pepper, Zach Corleissen, Sen Lu, and Josh Berkus. In addition to presenting and helping students, the bilingual members of the team translated all of the slides into Chinese. Fifty-one students attended.
{{< figure src="/images/blog/2018-12-05-new-contributor-shanghai/noahabrahams.png" caption="Noah Abrahams explains Kubernetes communications channels. Photo by Jerry Zhang" >}}
The NCW takes participants through the stages of contributing to Kubernetes, starting from deciding where to contribute, followed by an introduction to the SIG system and our repository structure. We also have "guest speakers" from Docs and Test Infrastructure who cover contributing in those areas. We finally wind up with some hands-on exercises in filing issues and creating and approving PRs.
Those hands-on exercises use a repository known as [the contributor playground](https://github.com/kubernetes-sigs/contributor-playground), created by SIG Contributor Experience as a place for new contributors to try out performing various actions on a Kubernetes repo. It has modified Prow and Tide automation, uses Owners files like in the real repositories. This lets students learn how the mechanics of contributing to our repositories work without disrupting normal development.
{{< figure src="/images/blog/2018-12-05-new-contributor-shanghai/yangli.png" caption="Yang Li talks about getting your PRs reviewed. Photo by Josh Berkus" >}}
Both the "Great Firewall" and the language barrier prevent contributing Kubernetes from China from being straightforward. What's more, because open source business models are not mature in China, the time for employees work on open source projects is limited.
Chinese engineers are eager to participate in the development of Kubernetes, but many of them don't know where to start since Kubernetes is such a large project. With this workshop, we hope to help those who want to contribute, whether they wish to fix some bugs they encountered, improve or localize documentation, or they need to work with Kubernetes at their work. We are glad to see more and more Chinese contributors joining the community in the past few years, and we hope to see more of them in the future.
"I have been participating in the Kubernetes community for about three years," said XiangPeng Zhao. "In the community, I notice that more and more Chinese developers are showing their interest in contributing to Kubernetes. However, it's not easy to start contributing to such a project. I tried my best to help those who I met in the community, but I think there might still be some new contributors leaving the community due to not knowing where to get help when in trouble. Fortunately, the community initiated NCW at KubeCon Copenhagen and held a second one at KubeCon Shanghai. I was so excited to be invited by Josh Berkus to help organize this workshop. During the workshop, I met community friends in person, mentored attendees in the exercises, and so on. All of this was a memorable experience for me. I also learned a lot as a contributor who already has years of contributing experience. I wish I had attended such a workshop when I started contributing to Kubernetes years ago."
{{< figure src="/images/blog/2018-12-05-new-contributor-shanghai/panel.png" caption="Panel of contributors. Photo by Jerry Zhang" >}}
The workshop ended with a panel of current contributors, featuring Lucas Käldström, Janet Kuo, Da Ma, Pengfei Ni, Zefeng Wang, and Chao Xu. The panel aimed to give both new and current contributors a look behind the scenes on the day-to-day of some of the most active contributors and maintainers, both from China and around the world. Panelists talked about where to begin your contributor's journey, but also how to interact with reviewers and maintainers. They further touched upon the main issues of contributing from China and gave attendees an outlook into exciting features they can look forward to in upcoming releases of Kubernetes.
After the workshop, Xiang Peng Zhao chatted with some attendees on WeChat and Twitter about their experiences. They were very glad to have attended the NCW and had some suggestions on improving the workshop. One attendee, Mohammad, said, "I had a great time at the workshop and learned a lot about the entire process of k8s for a contributor." Another attendee, Jie Jia, said, "The workshop was wonderful. It systematically explained how to contribute to Kubernetes. The attendee could understand the process even if s/he knew nothing about that before. For those who were already contributors, they could also learn something new. Furthermore, I could make new friends from inside or outside of China in the workshop. It was awesome!"
SIG Contributor Experience will continue to run New Contributor Workshops at each upcoming Kubecon, including Seattle, Barcelona, and the return to Shanghai in June 2019. If you failed to get into one this year, register for one at a future Kubecon. And, when you meet an NCW attendee, make sure to welcome them to the community.
Links:
* English versions of the slides: [PDF](https://gist.github.com/jberkus/889be25c234b01761ce44eccff816380#file-kubernetes-shanghai-english-pdf) or [Google Docs with speaker notes](https://docs.google.com/presentation/d/1l5f_iAFsKg50LFq3N80KbZKUIEL_tyCaUoWPzSxColo/edit?usp=sharing)
* Chinese version of the slides: [PDF](https://gist.github.com/jberkus/889be25c234b01761ce44eccff816380#file-kubernetes-shanghai-cihinese-pdf)
* [Contributor playground](https://github.com/kubernetes-sigs/contributor-playground)
@@ -0,0 +1,95 @@
---
layout: blog
title: Kubernetes Federation Evolution
date: 2018-12-12
---
**Authors**: Irfan Ur Rehman (Huawei), Paul Morie (RedHat) and Shashidhara T D (Huawei)
Kubernetes provides great primitives for deploying applications to a cluster: it can be as simple as `kubectl create -f app.yaml`. Deploy apps across multiple clusters has never been that simple. How should app workloads be distributed? Should the app resources be replicated into all clusters, replicated into selected clusters, or partitioned into clusters? How is access to the clusters managed? What happens if some of the resources that a user wants to distribute pre-exist, in some or all of the clusters, in some form?
In SIG Multicluster, our journey has revealed that there are multiple possible models to solve these problems and there probably is no single best-fit, all-scenario solution. [Federation](https://kubernetes.io/docs/concepts/cluster-administration/federation/), however, is the single biggest Kubernetes open source sub-project, and has seen the maximum interest and contribution from the community in this problem space. The project initially reused the Kubernetes API to do away with any added usage complexity for an existing Kubernetes user. This approach was not viable, because of the problems summarised below:
* Difficulties in re-implementing the Kubernetes API at the cluster level, as federation-specific extensions were stored in annotations.
* Limited flexibility in federated types, placement and reconciliation, due to 1:1 emulation of the Kubernetes API.
* No settled path to GA, and general confusion on API maturity; for example, Deployments are GA in Kubernetes but not even Beta in Federation v1.
The ideas have evolved further with a federation-specific API architecture and a community effort which now continues as Federation v2.
# Conceptual Overview
Because Federation attempts to address a complex set of problems, it pays to break the different parts of those problems down. Lets take a look at the different high-level areas involved:
{{< figure src="/images/blog/2018-12-11-Kubernetes-Federation-Evolution/concepts.png" caption="Kubernetes Federation v2 Concepts" >}}
## Federating arbitrary resources
One of the main goals of Federation is to be able to define the APIs and API groups which encompass basic tenets needed to federate any given Kubernetes resource. This is crucial, due to the popularity of CustomResourceDefinitions as a way to extend Kubernetes with new APIs.
The workgroup arrived at a common definition of the federation API and API groups as _'a mechanism that distributes “normal” Kubernetes API resources into different clusters'_. The distribution in its most simple form could be imagined as ***simple propagation*** of this _'normal Kubernetes API resource'_ across the federated clusters. A thoughtful reader can certainly discern more complicated mechanisms, other than this simple propagation of the Kubernetes resources.
During the journey of defining building blocks of the federation APIs, one of the near term goals also evolved as _'to be able to create a simple federation a.k.a. simple propagation of any Kubernetes resource or a CRD, writing almost zero code'_. What ensued further was a core API group defining the building blocks as a `Template` resource, a `Placement` resource and an `Override` resource per given Kubernetes resource, a `TypeConfig` to specify sync or no sync for the given resource and associated controller(s) to carry out the sync. More details follow [in the next section](#federating-resources-the-details). Further sections will also talk about being able to follow a layered behaviour with higher-level federation APIs consuming the behaviour of these core building blocks, and users being able to consume whole or part of the API and associated controllers. Lastly, this architecture also allows the users to write additional controllers or replace the available reference controllers with their own, to carry out desired behaviour.
The ability to _'easily federate arbitrary Kubernetes resources'_, and a decoupled API, divided into building blocks APIs, higher level APIs and possible user intended types, presented such that different users can consume parts and write controllers composing solutions specific to them, makes a compelling case for Federation v2.
## Federating resources: the details
Fundamentally, federation must be configured with two types of information:
* Which API types federation should handle
* Which clusters federation should target for distributing those resources.
For each API type that federation handles, different parts of the declared state live in different API resources:
* A `Template` type holds the base specification of the resource - for example, a type called `FederatedReplicaSet` holds the base specification of a `ReplicaSet` that should be distributed to the targeted clusters
* A `Placement` type holds the specification of the clusters the resource should be distributed to - for example, a type called `FederatedReplicaSetPlacement` holds information about which clusters `FederatedReplicaSets` should be distributed to
* An optional `Overrides` type holds the specification of how the `Template` resource should be varied in some clusters - for example, a type called `FederatedReplicaSetOverrides` holds information about how a `FederatedReplicaSet` should be varied in certain clusters.
These types are all associated by name - meaning that for a particular Template resource with name `foo`, the Placement and Override information for that resource are contained by the Override and Placement resources with the name `foo` and in the same namespace as the Template.
## Higher-level behaviour
The architecture of the v2 API allows higher-level APIs to be constructed using the mechanics provided by the core API types (`Template`, `Placement` and `Override`), and associated controllers, for a given resource. In the community we uncovered a few use cases and implemented the higher-level APIs and associated controllers useful for those cases. Some of these types described in further sections also provide an useful reference to anybody interested in solving more complex use cases, building on top of the mechanics already available with the v2 API.
### ReplicaSchedulingPreference
`ReplicaSchedulingPreference` provides an automated mechanism of distributing and maintaining total number of replicas for Deployment or ReplicaSet-based federated workloads into federated clusters. This is based on high-level user preferences given by the user. These preferences include the semantics of _weighted distribution_ and _limits_ (min and max) for distributing the replicas. These also include semantics to allow redistribution of replicas dynamically in case some replica Pods remain unscheduled in some clusters, for example due to insufficient resources in that cluster.
More details can be found at the [user guide for ReplicaSchedulingPreferences](https://github.com/kubernetes-sigs/federation-v2/blob/master/docs/userguide.md#replicaschedulingpreference).
### Federated services & cross-cluster service discovery
Kubernetes Services are very useful in constructing a microservices architecture. There is a clear desire to deploy services across cluster, zone, region and cloud boundaries. Services that span clusters provide geographic distribution, enable hybrid and multi-cloud scenarios and improve the level of high availability beyond single cluster deployments. Customers who want their services to span one or more (possibly remote) clusters, need them to be reachable in a consistent manner from both within and outside their clusters.
Federated `Service`, at its core, contains a `Template` (a definition of a Kubernetes Service), a `Placement` (which clusters to be deployed into), an `Override` (optional variation in particular clusters) and a `ServiceDNSRecord` (specifying details on how to discover it).
Note: The federated service has to be of type `LoadBalancer` in order for it to be discoverable across clusters.
#### Discovering a federated service from Pods inside your federated clusters
By default, Kubernetes clusters come preconfigured with a cluster-local DNS server, as well as an intelligently constructed DNS search path, which together ensure that DNS queries like `myservice`, `myservice.mynamespace`, or `some-other-service.other-namespace`, issued by software running inside Pods, are automatically expanded and resolved correctly to the appropriate IP of Services running in the local cluster.
With the introduction of federated services and cross-cluster service discovery, this concept is extended to cover Kubernetes Services running in any other cluster across your cluster federation, globally. To take advantage of this extended range, you use a slightly different DNS name (e.g. `myservice.mynamespace.myfederation`) to resolve federated services. Using a different DNS name also avoids having your existing applications accidentally traversing cross-zone or cross-region networks and you incurring perhaps unwanted network charges or latency, without you explicitly opting in to this behavior.
Lets consider an example, using a service named `nginx`.
A Pod in a cluster in the `us-central1-a` availability zone needs to contact our `nginx` service. Rather than use the services traditional cluster-local DNS name (`nginx.mynamespace`, which is automatically expanded to `nginx.mynamespace.svc.cluster.local`) it can now use the services federated DNS name, which is `nginx.mynamespace.myfederation`. This will be automatically expanded and resolved to the closest healthy shard of my `nginx` service, wherever in the world that may be. If a healthy shard exists in the local cluster, that services cluster-local IP address will be returned (by the cluster-local DNS). This is exactly equivalent to non-federated service resolution.
If the Service does not exist in the local cluster (or it exists but has no healthy backend pods), the DNS query is automatically expanded to `nginx.mynamespace.myfederation.svc.us-central1-a.us-central1.example.com`. Behind the scenes, this finds the external IP of one of the shards closest to my availability zone. This expansion is performed automatically by the cluster-local DNS server, which returns the associated CNAME record. This results in a traversal of the hierarchy of DNS records, and ends up at one of the external IPs of the federated service nearby.
It is also possible to target service shards in availability zones and regions other than the ones local to a Pod by specifying the appropriate DNS names explicitly, and not relying on automatic DNS expansion. For example, `nginx.mynamespace.myfederation.svc.europe-west1.example.com`will resolve to all of the currently healthy service shards in Europe, even if the Pod issuing the lookup is located in the U.S., and irrespective of whether or not there are healthy shards of the service in the U.S. This is useful for remote monitoring and other similar applications.
#### Discovering a federated service from other clients outside your federated clusters
For external clients, automatic DNS expansion described is not currently possible. External clients need to specify one of the fully qualified DNS names of the federated service, be that a zonal, regional or global name. For convenience reasons, it is often a good idea to manually configure additional static CNAME records in your service, for example:
| SHORT NAME | CNAME |
|-------------------|-------------------------------------------------------------|
| eu.nginx.acme.com | nginx.mynamespace.myfederation.svc.europe-west1.example.com |
| us.nginx.acme.com | nginx.mynamespace.myfederation.svc.us-central1.example.com |
| nginx.acme.com | nginx.mynamespace.myfederation.svc.example.com |
That way, your clients can always use the short form on the left, and always be automatically routed to the closest healthy shard on their home continent. All of the required failover is handled for you automatically by Kubernetes cluster federation.
As further reading, a more elaborate example for users is available in the [Multi-Cluster Service DNS with ExternalDNS guide](https://github.com/kubernetes-sigs/federation-v2/blob/master/docs/servicedns-with-externaldns.md).
# Try it yourself
To get started with Federation v2, please refer to the [user guide](https://github.com/kubernetes-sigs/federation-v2/blob/master/docs/userguide.md). Deployment can be accomplished with a [Helm chart](https://github.com/kubernetes-sigs/federation-v2/blob/master/charts/federation-v2/README.md), and once the control plane is available, the [user guides example](https://github.com/kubernetes-sigs/federation-v2/blob/master/docs/userguide.md#example) can be used to get some hands-on experience with using Federation V2.
Federation v2 can be deployed in both _cluster-scoped_ and _namespace-scoped_ configurations. A cluster-scoped deployment will require cluster-admin privileges to both host and member clusters, and may be a good fit for evaluating federation on clusters that are not running critical workloads. Namespace-scoped deployment requires access to only a single namespace on host and member clusters, and is a better fit for evaluating federation on clusters running workloads. Most of the user guide refers to cluster-scoped deployment, with the [namespaced federation](https://github.com/kubernetes-sigs/federation-v2/blob/master/docs/userguide.md#namespaced-federation) section documenting how use of a namespaced deployment differs. The same cluster can host multiple federations, and clusters can be part of multiple federations when using namespaced federation.
# Next Steps
As we noted in the beginning of this post, the multicluster problem space is extremely broad. It can be difficult to know exactly how to handle such broad problem spaces without concrete pieces of software to frame those conversations around. Our hope in the Federation working group is that Federation v2 can be a concrete artifact to frame discussions around. We would love to know experiences that folks have had in this problem space, how they feel about Federation v2, and what use-cases theyre interested in exploring in the future.
Please feel welcome to join us at the [sig-multicluster slack channel](https://kubernetes.slack.com/messages/C09R1PJR3) or at [Federation working group meetings](https://docs.google.com/document/d/1FQx0BPlkkl1Bn0c9ocVBxYIKojpmrS1CFP5h0DI68AE/edit) on Wednesdays at 07:30 PST.
@@ -0,0 +1,57 @@
---
layout: blog
title: 'etcd: Current status and future roadmap'
date: 2018-12-11
---
**Author**: Gyuho Lee (Amazon Container OSS Team, @gyuho), Joe Betz (Google Cloud, @jpbetz)
etcd is a distributed key value store that provides a reliable way to manage the coordination state of distributed systems. etcd was first announced in June 2013 by CoreOS (part of Red Hat as of 2018). Since its adoption in Kubernetes in 2014, etcd has become a fundamental part of the Kubernetes cluster management software design, and the etcd community has grown exponentially. etcd is now being used in production environments of multiple companies, including large cloud provider environments such as AWS, Google Cloud Platform, Azure, and other on-premises Kubernetes implementations. CNCF currently has [32 conformant Kubernetes platforms and distributions](https://www.cncf.io/announcement/2017/11/13/cloud-native-computing-foundation-launches-certified-kubernetes-program-32-conformant-distributions-platforms/), all of which use etcd as the datastore.
In this blog post, well review some of the milestones achieved in latest etcd releases, and go over the future roadmap for etcd. Share your thoughts and feedback on features you consider important on the mailing list: etcd-dev@googlegroups.com.
## etcd, 2013
In June 2014, Kubernetes was released with etcd as a backing storage for all master states. Kubernetes v0.4 used etcd v0.2 API, which was in an alpha stage at the time. As Kubernetes reached the v1.0 milestone in 2015, etcd stabilized its v2.0 API. The widespread adoption of Kubernetes led to a dramatic increase in the scalability requirements for etcd. To handle large number of workloads and the growing requirements on scale, etcd released v3.0 API in June 2016. Kubernetes v1.13 finally [dropped support for etcd v2.0 API](https://github.com/kubernetes/enhancements/issues/622) and adopted the etcd v3.0 API. The table below gives a visual snapshot of the release cycles of etcd and Kubernetes.
| | etcd | Kubernetes |
|---|---|---|
| Initial Commit | June 2, 2013 | June 1, 2014 |
| First Stable Release | January 28, 2015 (v2.0.0) | July 13, 2015 (v1.0.0) |
| Latest Release | October 10, 2018 (v3.3.10) | December 3, 2018 (v1.13.0) |
## etcd v3.1, early 2017
etcd v3.1 features provide better read performance and better availability during version upgrades. Given the high use of etcd in production even to this day, these features were very useful for users. It implements Raft read index, which bypasses [Raft WAL](https://godoc.org/github.com/etcd-io/etcd/wal) disk writes for linearizable reads. The follower requests read index from the leader. Responses from the leader indicate whether a follower has advanced as much as the leader. When the follower's logs are up-to-date, quorum read is served locally without going through the full Raft protocol. Thus, no disk write is required for read requests. etcd v3.1 introduces automatic leadership transfer. When etcd leader receives an interrupt signal, it automatically transfers its leadership to a follower. This provides higher availability when the cluster adds or loses a member.
## etcd v3.2 (summer 2017)
etcd v3.2 focuses on stability. Its client was shipped in Kubernetes v1.10, v1.11, and v1.12. The etcd team still actively maintains the branch by backporting all the bug fixes. This release introduces gRPC proxy to support, watch, and coalesce all watch event broadcasts into one gRPC stream. These event broadcasts can go up to one million events per second.
etcd v3.2 also introduces changes such as `“snapshot-count”` default value from 10,000 to 100,000. With higher snapshot count, etcd server holds Raft entries in-memory for longer periods before compacting the old ones. etcd v3.2 default configuration shows higher memory usage, while giving more time for slow followers to catch up. It is a trade-off between less frequent snapshot sends and higher memory usage. Users can employ lower `etcd --snapshot-count` value to reduce the memory usage or higher `“snapshot-count”` value to increase the availability of slow followers.
Another new feature backported to etcd v3.2.19 was `etcd --initial-election-tick-advance` flag. By default, a rejoining follower fast-forwards election ticks to speed up its initial cluster bootstrap. For example, the starting follower node only waits 200ms instead of full election timeout 1-second before starting an election. Ideally, within the 200ms, it receives a leader heartbeat and immediately joins the cluster as a follower. However, if network partition happens, heartbeat may drop and thus leadership election will be triggered. A vote request from a partitioned node is quite disruptive. If it contains a higher Raft term, current leader is forced to step down. With “initial-election-tick-advance” set to false, a rejoining node has [more chance to receive leader heartbeats](https://github.com/etcd-io/etcd/pull/9591) before disrupting the cluster.
## etcd v3.3 (early 2018)
etcd v3.3 continues the theme of stability. Its client is included in [Kubernetes v1.13](https://github.com/kubernetes/kubernetes/pull/69322). Previously, etcd client carelessly retried on network disconnects without any backoff or failover logic. The client was often stuck with a partitioned node, [affecting several production users](https://github.com/etcd-io/etcd/issues/7321). v3.3 client balancer now maintains a list of unhealthy endpoints using gRPC health checking protocol, making more efficient retries and failover in the face of transient disconnects and [network partitions](https://github.com/etcd-io/etcd/issues/8711). This was backported to etcd v3.2 and also [included in Kubernetes v1.10 API server](https://github.com/kubernetes/kubernetes/pull/57480). etcd v3.3 also provides more predictable database size. etcd used to maintain a separate freelist DB to track pages that were no longer in use and freed after transactions, so that following transactions can reuse them. However, it turns out persisting freelist demands high disk space and introduces high latency for Kubernetes workloads. Especially when there were frequent snapshots with lots of read transactions, etcd database size quickly grew from 16 MB to 4 GB. etcd v3.3 disables freelist sync and rebuilds the freelist on restart. The overhead is so small that it is unnoticeable to most users. See ["database space exceeded" issue](https://github.com/etcd-io/etcd/issues/8009) for more information on this.
## etcd v3.4 and beyond
etcd v3.4 focuses on improving the operational experience. It adds [Raft pre-vote feature](https://github.com/etcd-io/etcd/pull/9352) to improve the robustness of leadership election. When a node becomes isolated (e.g. network partition), this member will start an election requesting votes with increased Raft terms. When a leader receives a vote request with a higher term, it steps down to a follower. With pre-vote, Raft runs an additional election phase to check if the candidate can get enough votes to win an election. The isolated follower's vote request is rejected because it does not contain the latest log entries.
etcd v3.4 adds a [Raft learner](https://etcd.readthedocs.io/en/latest/server-learner.html#server-learner) that joins the cluster as a non-voting member that still receives all the updates from leader. Adding a learner node does not increase the size of quorum and hence improves the cluster availability during membership reconfiguration. It only serves as a standby node until it gets promoted to a voting member. Moreover, to handle unexpected upgrade failures, v3.4 introduces [etcd downgrade](https://groups.google.com/forum/?hl=en#!topic/etcd-dev/Hq6zru44L74) feature.
etcd v3 storage uses multi-version concurrency control model to preserve key updates as event history. Kubernetes runs compaction to discard the event history that is no longer needed, and reclaims the storage space. etcd v3.4 will improve this storage compact operation, boost backend [concurrency for large read transactions](https://github.com/etcd-io/etcd/pull/9384), and [optimize storage commit interval](https://github.com/etcd-io/etcd/pull/10283) for Kubernetes use-case.
To further improve etcd client load balancer, the v3.4 balancer was rewritten to leverage the newly introduced gRPC load balancing API. By leveraging gPRC, the etcd client load balancer codebase was substantially simplified while retaining feature parity with the v3.3 implementation and improving overall load balancing by round-robining requests across healthy endpoints. See [Client Architecture](https://etcd.readthedocs.io/en/latest/client-architecture.html#client-architecture) for more details.
Additionally, etcd maintainers will continue to make improvements to Kubernetes test frameworks: kubemark integration for scalability tests, Kubernetes API server conformance tests with etcd to provide release recommends and version skew policy, specifying conformance testing requirements for each cloud provider, etc.
## etcd Joins CNCF
etcd now has a new home at [etcd-io](https://github.com/etcd-io) and [joined CNCF as an incubating project](https://www.cncf.io/blog/2018/12/11/cncf-to-host-etcd/).
The synergistic efforts with Kubernetes have driven the evolution of etcd. Without community feedback and contribution, etcd could not have achieved its maturity and reliability. Were looking forward to continuing the growth of etcd as an open source project and are excited to work with the Kubernetes and the wider CNCF community.
Finally, wed like to thank all contributors with special thanks to [Xiang Li](https://github.com/xiang90) for his leadership in etcd and Kubernetes.
@@ -0,0 +1,99 @@
---
layout: blog
title: 'APIServer dry-run and kubectl diff'
date: 2019-01-14
---
**Author**: Antoine Pelisse (Google Cloud, @apelisse)
Declarative configuration management, also known as configuration-as-code, is
one of the key strengths of Kubernetes. It allows users to commit the desired state of
the cluster, and to keep track of the different versions, improve auditing and
automation through CI/CD pipelines. The [Apply working-group](https://groups.google.com/forum/#!forum/kubernetes-wg-apply)
is working on fixing some of the gaps, and is happy to announce that Kubernetes
1.13 promoted server-side dry-run and `kubectl diff` to beta. These
two features are big improvements for the Kubernetes declarative model.
## Challenges
A few pieces are still missing in order to have a seamless declarative
experience with Kubernetes, and we tried to address some of these:
- While compilers and linters do a good job to detect errors in pull-requests
for code, a good validation is missing for Kubernetes configuration files.
The existing solution is to run `kubectl apply --dry-run`, but this runs a
*local* dry-run that doesn't talk to the server: it doesn't have server
validation and doesn't go through validating admission controllers. As an
example, Custom resource names are only validated on the server so a local
dry-run won't help.
- It can be difficult to know how your object is going to be applied by the
server for multiple reasons:
- Defaulting will set some fields to potentially unexpected values,
- Mutating webhooks might set fields or clobber/change some values.
- Patch and merges can have surprising effects and result in unexpected
objects. For example, it can be hard to know how lists are going to be
ordered once merged.
The working group has tried to address these problems.
## APIServer dry-run
[APIServer dry-run](https://kubernetes.io/docs/reference/using-api/api-concepts/#dry-run) was implemented to address these two problems:
- it allows individual requests to the apiserver to be marked as "dry-run",
- the apiserver guarantees that dry-run requests won't be persisted to storage,
- the request is still processed as typical request: the fields are
defaulted, the object is validated, it goes through the validation admission
chain, and through the mutating admission chain, and then the final object is
returned to the user as it normally would, without being persisted.
While dynamic admission controllers are not supposed to have side-effects on
each request, dry-run requests are only processed if all admission controllers
explicitly announce that they don't have any dry-run side-effects.
### How to enable it
Server-side dry-run is enabled through a feature-gate. Now that the feature is
Beta in 1.13, it should be enabled by default, but still can be enabled/disabled
using `kube-apiserver --feature-gates DryRun=true`.
If you have dynamic admission controllers, you might have to fix them to:
- Remove any side-effects when the dry-run parameter is specified on the webhook request,
- Specify in the [`sideEffects`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#webhook-v1beta1-admissionregistration)
field of the `admissionregistration.k8s.io/v1beta1.Webhook` object to indicate that the object doesn't
have side-effects on dry-run (or at all).
### How to use it
You can trigger the feature from kubectl by using `kubectl apply
--server-dry-run`, which will decorate the request with the dryRun flag
and return the object as it would have been applied, or an error if it would
have failed.
## Kubectl diff
APIServer dry-run is convenient because it lets you see how the object would be
processed, but it can be hard to identify exactly what changed if the object is
big. `kubectl diff` does exactly what you want by showing the differences between
the current "live" object and the new "dry-run" object. It makes it very
convenient to focus on only the changes that are made to the object, how the
server has merged these and how the mutating webhooks affects the output.
### How to use it
`kubectl diff` is meant to be as similar as possible to `kubectl apply`:
`kubectl diff -f some-resources.yaml` will show a diff for the resources in the yaml file. One can even use the diff program of their choice by using the KUBECTL_EXTERNAL_DIFF environment variable, for example:
```
KUBECTL_EXTERNAL_DIFF=meld kubectl diff -f some-resources.yaml
```
## What's next
The working group is still busy trying to improve some of these things:
- Server-side apply is trying to improve the apply scenario, by adding owner
semantics to fields! It's also going to improve support for CRDs and unions!
- Some kubectl apply features are missing from diff and could be useful, like the ability
to filter by label, or to display pruned resources.
- Eventually, kubectl diff will use server-side apply!
@@ -0,0 +1,208 @@
---
title: Container Storage Interface (CSI) for Kubernetes GA
date: 2019-01-15
slug: container-storage-interface-ga
---
![Kubernetes Logo](/images/blog-logging/2018-04-10-container-storage-interface-beta/csi-kubernetes.png)
![CSI Logo](/images/blog-logging/2018-04-10-container-storage-interface-beta/csi-logo.png)
**Author:** Saad Ali, Senior Software Engineer, Google
The Kubernetes implementation of the [Container Storage Interface](https://github.com/container-storage-interface/spec/blob/master/spec.md) (CSI) has been promoted to GA in the Kubernetes v1.13 release. Support for CSI was [introduced as alpha](http://blog.kubernetes.io/2018/01/introducing-container-storage-interface.html) in Kubernetes v1.9 release, and [promoted to beta](https://kubernetes.io/blog/2018/04/10/container-storage-interface-beta/) in the Kubernetes v1.10 release.
The GA milestone indicates that Kubernetes users may depend on the feature and its API without fear of backwards incompatible changes in future causing regressions. GA features are protected by the [Kubernetes deprecation policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/).
## Why CSI?
Although prior to CSI Kubernetes provided a powerful volume plugin system, it was challenging to add support for new volume plugins to Kubernetes: volume plugins were “in-tree” meaning their code was part of the core Kubernetes code and shipped with the core Kubernetes binaries—vendors wanting to add support for their storage system to Kubernetes (or even fix a bug in an existing volume plugin) were forced to align with the Kubernetes release process. In addition, third-party storage code caused reliability and security issues in core Kubernetes binaries and the code was often difficult (and in some cases impossible) for Kubernetes maintainers to test and maintain.
CSI was developed as a standard for exposing arbitrary block and file storage storage systems to containerized workloads on Container Orchestration Systems (COs) like Kubernetes. With the adoption of the Container Storage Interface, the Kubernetes volume layer becomes truly extensible. Using CSI, third-party storage providers can write and deploy plugins exposing new storage systems in Kubernetes without ever having to touch the core Kubernetes code. This gives Kubernetes users more options for storage and makes the system more secure and reliable.
## Whats new?
With the promotion to GA, the Kubernetes implementation of CSI introduces the following changes:
- Kubernetes is now compatible with CSI spec [v1.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) and [v0.3](https://github.com/container-storage-interface/spec/releases/tag/v0.3.0) (instead of CSI spec [v0.2](https://github.com/container-storage-interface/spec/releases/tag/v0.2.0)).
- There were breaking changes between CSI spec v0.3.0 and v1.0.0, but Kubernetes v1.13 supports both versions so either version will work with Kubernetes v1.13.
- Please note that with the release of the CSI 1.0 API, support for CSI drivers using 0.3 and older releases of the CSI API is deprecated, and is planned to be removed in Kubernetes v1.15.
- There were no breaking changes between CSI spec v0.2 and v0.3, so v0.2 drivers should also work with Kubernetes v1.10.0+.
- There were breaking changes between the CSI spec v0.1 and v0.2, so very old drivers implementing CSI 0.1 must be updated to be at least 0.2 compatible before use with Kubernetes v1.10.0+.
- The Kubernetes `VolumeAttachment` object (introduced in v1.9 in the storage v1alpha1 group, and added to the v1beta1 group in v1.10) has been added to the storage v1 group in v1.13.
- The Kubernetes `CSIPersistentVolumeSource` volume type has been promoted to GA.
- The [Kubelet device plugin registration mechanism](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#device-plugin-registration), which is the means by which kubelet discovers new CSI drivers, has been promoted to GA in Kubernetes v1.13.
## How to deploy a CSI driver?
Kubernetes users interested in how to deploy or manage an existing CSI driver on Kubernetes should look at the documentation provided by the author of the CSI driver.
## How to use a CSI volume?
Assuming a CSI storage plugin is already deployed on a Kubernetes cluster, users can use CSI volumes through the familiar Kubernetes storage API objects: `PersistentVolumeClaims`, `PersistentVolumes`, and `StorageClasses`. Documented [here](https://kubernetes.io/docs/concepts/storage/volumes/#csi).
Although the Kubernetes implementation of CSI is a GA feature in Kubernetes v1.13, it may require the following flag:
- API server binary and kubelet binaries:
- `--allow-privileged=true`
- Most CSI plugins will require bidirectional mount propagation, which can only be enabled for privileged pods. Privileged pods are only permitted on clusters where this flag has been set to true (this is the default in some environments like GCE, GKE, and kubeadm).
### Dynamic Provisioning
You can enable automatic creation/deletion of volumes for CSI Storage plugins that support dynamic provisioning by creating a `StorageClass` pointing to the CSI plugin.
The following StorageClass, for example, enables dynamic creation of “`fast-storage`” volumes by a CSI volume plugin called “`csi-driver.example.com`”.
```
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast-storage
provisioner: csi-driver.example.com
parameters:
type: pd-ssd
csi.storage.k8s.io/provisioner-secret-name: mysecret
csi.storage.k8s.io/provisioner-secret-namespace: mynamespace
```
New for GA, the [CSI external-provisioner](https://github.com/kubernetes-csi/external-provisioner) (v1.0.1+) reserves the parameter keys prefixed with `csi.storage.k8s.io/`. If the keys do not correspond to a set of known keys the values are simply ignored (and not passed to the CSI driver). The older secret parameter keys (`csiProvisionerSecretName`, `csiProvisionerSecretNamespace`, etc.) are also supported by CSI external-provisioner v1.0.1 but are deprecated and may be removed in future releases of the CSI external-provisioner.
Dynamic provisioning is triggered by the creation of a `PersistentVolumeClaim` object. The following `PersistentVolumeClaim`, for example, triggers dynamic provisioning using the `StorageClass` above.
```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-request-for-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: fast-storage
```
When volume provisioning is invoked, the parameter type: `pd-ssd` and the secret any referenced secret(s) are passed to the CSI plugin `csi-driver.example.com` via a `CreateVolume` call. In response, the external volume plugin provisions a new volume and then automatically create a `PersistentVolume` object to represent the new volume. Kubernetes then binds the new `PersistentVolume` object to the `PersistentVolumeClaim`, making it ready to use.
If the `fast-storage StorageClass` is marked as “default”, there is no need to include the `storageClassName` in the `PersistentVolumeClaim`, it will be used by default.
### Pre-Provisioned Volumes
You can always expose a pre-existing volume in Kubernetes by manually creating a PersistentVolume object to represent the existing volume. The following `PersistentVolume`, for example, exposes a volume with the name “`existingVolumeName`” belonging to a CSI storage plugin called “`csi-driver.example.com`”.
```
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-manually-created-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
csi:
driver: csi-driver.example.com
volumeHandle: existingVolumeName
readOnly: false
fsType: ext4
volumeAttributes:
foo: bar
controllerPublishSecretRef:
name: mysecret1
namespace: mynamespace
nodeStageSecretRef:
name: mysecret2
namespace: mynamespace
nodePublishSecretRef
name: mysecret3
namespace: mynamespace
```
### Attaching and Mounting
You can reference a `PersistentVolumeClaim` that is bound to a CSI volume in any pod or pod template.
```
kind: Pod
apiVersion: v1
metadata:
name: my-pod
spec:
containers:
- name: my-frontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: my-csi-volume
volumes:
- name: my-csi-volume
persistentVolumeClaim:
claimName: my-request-for-storage
```
When the pod referencing a CSI volume is scheduled, Kubernetes will trigger the appropriate operations against the external CSI plugin (`ControllerPublishVolume`, `NodeStageVolume`, `NodePublishVolume`, etc.) to ensure the specified volume is attached, mounted, and ready to use by the containers in the pod.
For more details please see the CSI implementation [design doc](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md) and [documentation](https://kubernetes.io/docs/concepts/storage/volumes/#csi).
## How to write a CSI Driver?
The [kubernetes-csi](https://kubernetes-csi.github.io/) site details how to develop, deploy, and test a CSI driver on Kubernetes. In general, CSI Drivers should be deployed on Kubernetes along with the following sidecar (helper) containers:
- [external-attacher](https://github.com/kubernetes-csi/external-attacher)
- Watches Kubernetes `VolumeAttachment` objects and triggers `ControllerPublish` and `ControllerUnpublish` operations against a CSI endpoint.
- [external-provisioner](https://github.com/kubernetes-csi/external-provisioner)
- Watches Kubernetes `PersistentVolumeClaim` objects and triggers `CreateVolume` and `DeleteVolume` operations against a CSI endpoint.
- [node-driver-registrar](https://github.com/kubernetes-csi/node-driver-registrar)
- Registers the CSI driver with kubelet using the [Kubelet device plugin mechanism](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/#device-plugin-registration).
- [cluster-driver-registrar](https://github.com/kubernetes-csi/cluster-driver-registrar) (Alpha)
- Registers a CSI Driver with the Kubernetes cluster by creating a `CSIDriver` object which enables the driver to customize how Kubernetes interacts with it.
- [external-snapshotter](https://github.com/kubernetes-csi/external-snapshotter) (Alpha)
- Watches Kubernetes `VolumeSnapshot` CRD objects and triggers `CreateSnapshot` and `DeleteSnapshot` operations against a CSI endpoint.
- [livenessprobe](https://github.com/kubernetes-csi/livenessprobe)
- May be included in a CSI plugin pod to enable the [Kubernetes Liveness Probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/) mechanism.
Storage vendors can build Kubernetes deployments for their plugins using these components, while leaving their CSI driver completely unaware of Kubernetes.
## List of CSI Drivers
CSI drivers are developed and maintained by third parties. You can find a non-definitive list of CSI drivers [here](https://kubernetes-csi.github.io/docs/Drivers.html).
## What about in-tree volume plugins?
There is a plan to migrate most of the persistent, remote in-tree volume plugins to CSI. For more details see [design doc](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/csi-migration.md).
## Limitations of GA
The GA implementation of CSI has the following limitations:
- Ephemeral local volumes must create a PVC (pod inline referencing of CSI volumes is not supported).
## Whats next?
- Work on moving Kubernetes CSI features that are still alpha to beta:
- Raw block volumes
- Topology awareness (the ability for Kubernetes to understand and influence where a CSI volume is provisioned (zone, regions, etc.).
- Features depending on CSI CRDs (e.g. “Skip attach” and “Pod info on mount”).
- Volume Snapshots
- Work on completing support for local ephemeral volumes.
- Work on migrating remote persistent in-tree volume plugins to CSI.
## How to get involved?
The Kubernetes Slack channel [wg-csi](https://kubernetes.slack.com/messages/C8EJ01Z46/details/) and the Google group [kubernetes-sig-storage-wg-csi](https://groups.google.com/forum/#!forum/kubernetes-sig-storage-wg-csi) along with any of the standard [SIG storage communication channels](https://github.com/kubernetes/community/blob/master/sig-storage/README.md#contact) are all great mediums to reach out to the SIG Storage team.
This project, like all of Kubernetes, is the result of hard work by many contributors from diverse backgrounds working together. We offer a huge thank you to the new contributors who stepped up this quarter to help the project reach GA:
- Saad Ali ([saad-ali](https://github.com/saad-ali))
- Michelle Au ([msau42](https://github.com/msau42))
- Serguei Bezverkhi ([sbezverk](https://github.com/sbezverk))
- Masaki Kimura ([mkimuram](https://github.com/mkimuram))
- Patrick Ohly ([pohly](https://github.com/pohly))
- Luis Pabón ([lpabon](https://github.com/lpabon))
- Jan Šafránek ([jsafrane](https://github.com/jsafrane))
- Vladimir Vivien ([vladimirvivien](https://github.com/vladimirvivien))
- Cheng Xing ([verult](https://github.com/verult))
- Xing Yang ([xing-yang](https://github.com/xing-yang))
- David Zhu ([davidz627](https://github.com/davidz627))
If youre interested in getting involved with the design and development of CSI or any part of the Kubernetes Storage system, join the [Kubernetes Storage Special Interest Group](https://github.com/kubernetes/community/tree/master/sig-storage) (SIG). Were rapidly growing and always welcome new contributors.
@@ -0,0 +1,170 @@
---
title: Update on Volume Snapshot Alpha for Kubernetes
date: 2019-01-17
---
**Authors:** Jing Xu (Google), Xing Yang (Huawei), Saad Ali (Google)
Volume snapshotting support was introduced in Kubernetes v1.12 as an alpha feature. In Kubernetes v1.13, it remains an alpha feature, but a few enhancements were added and some breaking changes were made. This post summarizes the changes.
## Breaking Changes
[CSI spec v1.0](https://github.com/container-storage-interface/spec/releases/tag/v1.0.0) introduced a few breaking changes to the volume snapshot feature. CSI driver maintainers should be aware of these changes as they upgrade their drivers to support v1.0.
## SnapshotStatus replaced with Boolean ReadyToUse
CSI v0.3.0, defined a `SnapshotStatus` enum in `CreateSnapshotResponse` which indicates whether the snapshot is `READY`, `UPLOADING`, or `ERROR_UPLOADING`. In CSI v1.0, `SnapshotStatus` has been removed from `CreateSnapshotResponse` and replaced with a `boolean ReadyToUse`. A `ReadyToUse` value of `true` indicates that post snapshot processing (such as uploading) is complete and the snapshot is ready to be used as a source to create a volume.
Storage systems that need to do post snapshot processing (such as uploading after the snapshot is cut) should return a successful `CreateSnapshotResponse` with the `ReadyToUse` field set to `false` as soon as the snapshot has been taken. This indicates that the Container Orchestration System (CO) can resume any workload that was quiesced for the snapshot to be taken. The CO can then repeatedly call `CreateSnapshot` until the `ReadyToUse` field is set to `true` or the call returns an error indicating a problem in processing. The CSI `ListSnapshot` call could be used along with `snapshot_id` filtering to determine if the snapshot is ready to use, but is not recommended because it provides no way to detect errors during processing (the `ReadyToUse` field simply remains `false` indefinitely).
The [v1.x.x releases](https://github.com/kubernetes-csi/external-snapshotter/releases/tag/v1.0.1) of the CSI external-snapshotter sidecar container already handle this change by calling `CreateSnapshot` instead of `ListSnapshots` to check if a snapshot is ready to use. When upgrading their drivers to CSI 1.0, driver maintainers should use the appropriate 1.0 compatible sidecar container.
To be consistent with the change in the CSI spec, the `Ready` field in the `VolumeSnapshot` API object has been renamed to `ReadyToUse`. This change is visible to the user when running `kubectl describe volumesnapshot` to view the details of a snapshot.
## Timestamp Data Type
The creation time of a snapshot is available to Kubernetes admins as part of the `VolumeSnapshotContent` API object. This field is populated using the `creation_time` field in the CSI `CreateSnapshotResponse`. In CSI v1.0, this `creation_time` field type was changed to [`.google.protobuf.Timestamp`](https://godoc.org/github.com/golang/protobuf/ptypes/timestamp) instead of `int64`. When upgrading drivers to CSI 1.0, driver maintainers must make changes accordingly. The [v1.x.x releases](https://github.com/kubernetes-csi/external-snapshotter/releases/tag/v1.0.1) of the CSI external-snapshotter sidecar container has been updated to handle this change.
## Deprecations
The following `VolumeSnapshotClass` parameters are deprecated and will be removed in a future release. They will be replaced with parameters listed in the `Replacement` section below.
Deprecated
Replacement
csiSnapshotterSecretName
csi.storage.k8s.io/snapshotter-secret-name
csiSnapshotterSecretNameSpace
csi.storage.k8s.io/snapshotter-secret-namespace
## New Features
### SnapshotContent Deletion/Retain Policy
As described in the [initial blog post announcing the snapshot alpha](https://kubernetes.io/blog/2018/10/09/introducing-volume-snapshot-alpha-for-kubernetes/), the Kubernetes snapshot APIs are similar to the PV/PVC APIs: just like a volume is represented by a bound PVC and PV pair, a snapshot is represented by a bound `VolumeSnapshot` and `VolumeSnapshotContent` pair.
With PV/PVC pairs, when a user is done with a volume, they can delete the PVC. And the reclaim policy on the PV determines what happens to the PV (whether it is also deleted or retained).
In the initial alpha release, snapshots did not support the ability to specify a reclaim policy. Instead when a snapshot object was deleted it always resulted in the snapshot being deleted. In Kubernetes v1.13, a snapshot content `DeletionPolicy` was added. It enables an admin to configure what what happens to a `VolumeSnapshotContent` after the `VolumeSnapshot` object it is bound to is deleted. The `DeletionPolicy` of a volume snapshot can either be `Retain` or `Delete`. If the value is not specified, the default depends on whether the `SnapshotContent` object was created via static binding or dynamic provisioning.
### Retain
The `Retain` policy allows for manual reclamation of the resource. If a `VolumeSnapshotContent` is statically created and bound, the default `DeletionPolicy` is `Retain`. When the `VolumeSnapshot` is deleted, the `VolumeSnapshotContent` continues to exist and the `VolumeSnapshotContent` is considered “released”. But it is not available for binding to other `VolumeSnapshot` objects because it contains data. It is up to an administrator to decide how to handle the remaining API object and resource cleanup.
### Delete
A `Delete` policy enables automatic deletion of the bound `VolumeSnapshotContent` object from Kubernetes and the associated storage asset in the external infrastructure (such as an AWS EBS snapshot or GCE PD snapshot, etc.). Snapshots that are dynamically provisioned inherit the deletion policy of their [`VolumeSnapshotClass`](https://kubernetes.io/docs/concepts/storage/volume-snapshot-classes/), which defaults to `Delete`. The administrator should configure the `VolumeSnapshotClass` with the desired retention policy. The policy may be changed for individual `VolumeSnapshotContent` after it is created by patching the object.
The following example demonstrates how to check the deletion policy of a dynamically provisioned `VolumeSnapshotContent`.
```
$ kubectl create -f ./examples/kubernetes/demo-defaultsnapshotclass.yaml
$ kubectl create -f ./examples/kubernetes/demo-snapshot.yaml
$ kubectl get volumesnapshots demo-snapshot-podpvc -o yaml
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
metadata:
creationTimestamp: "2018-11-27T23:57:09Z"
...
spec:
snapshotClassName: default-snapshot-class
snapshotContentName: snapcontent-26cd0db3-f2a0-11e8-8be6-42010a800002
source:
apiGroup: null
kind: PersistentVolumeClaim
name: podpvc
status:
$ kubectl get volumesnapshotcontent snapcontent-26cd0db3-f2a0-11e8-8be6-42010a800002 -o yaml
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotContent
spec:
csiVolumeSnapshotSource:
creationTime: 1546469777852000000
driver: pd.csi.storage.gke.io
restoreSize: 6442450944
snapshotHandle: projects/jing-k8s-dev/global/snapshots/snapshot-26cd0db3-f2a0-11e8-8be6-42010a800002
deletionPolicy: Delete
persistentVolumeRef:
apiVersion: v1
kind: PersistentVolume
name: pvc-853622a4-f28b-11e8-8be6-42010a800002
resourceVersion: "21117"
uid: ae400e9f-f28b-11e8-8be6-42010a800002
snapshotClassName: default-snapshot-class
volumeSnapshotRef:
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshot
name: demo-snapshot-podpvc
namespace: default
resourceVersion: "6948065"
uid: 26cd0db3-f2a0-11e8-8be6-42010a800002
```
User can change the deletion policy by using patch:
```
$ kubectl patch volumesnapshotcontent snapcontent-26cd0db3-f2a0-11e8-8be6-42010a800002 -p '{"spec":{"deletionPolicy":"Retain"}}' --type=merge
$ kubectl get volumesnapshotcontent snapcontent-26cd0db3-f2a0-11e8-8be6-42010a800002 -o yaml
apiVersion: snapshot.storage.k8s.io/v1alpha1
kind: VolumeSnapshotContent
...
spec:
csiVolumeSnapshotSource:
...
deletionPolicy: Retain
persistentVolumeRef:
apiVersion: v1
kind: PersistentVolume
name: pvc-853622a4-f28b-11e8-8be6-42010a800002
...
```
## Snapshot Object in Use Protection
The purpose of the Snapshot Object in Use Protection feature is to ensure that in-use snapshot API objects are not removed from the system (as this may result in data loss). There are two cases that require “in-use” protection:
1. If a volume snapshot is in active use by a persistent volume claim as a source to create a volume.
2. If a `VolumeSnapshotContent` API object is bound to a VolumeSnapshot API object, the content object is considered in use.
If a user deletes a `VolumeSnapshot` API object in active use by a PVC, the `VolumeSnapshot` object is not removed immediately. Instead, removal of the `VolumeSnapshot` object is postponed until the `VolumeSnapshot` is no longer actively used by any PVCs. Similarly, if an admin deletes a `VolumeSnapshotContent` that is bound to a `VolumeSnapshot`, the `VolumeSnapshotContent` is not removed immediately. Instead, the `VolumeSnapshotContent` removal is postponed until the `VolumeSnapshotContent` is not bound to the `VolumeSnapshot` object.
## Which volume plugins support Kubernetes Snapshots?
Snapshots are only supported for CSI drivers (not for in-tree or Flexvolume). To use the Kubernetes snapshots feature, ensure that a CSI Driver that implements snapshots is deployed on your cluster.
As of the publishing of this blog post, the following CSI drivers support snapshots:
- [GCE Persistent Disk CSI Driver](https://github.com/kubernetes-sigs/gcp-compute-persistent-disk-csi-driver)
- [OpenSDS CSI Driver](https://github.com/opensds/nbp/tree/master/csi/server)
- [Ceph RBD CSI Driver](https://github.com/ceph/ceph-csi/tree/master/pkg/rbd)
- [Portworx CSI Driver](https://github.com/libopenstorage/openstorage/tree/master/csi)
- [GlusterFS CSI Driver](https://github.com/gluster/gluster-csi-driver)
- [Digital Ocean CSI Driver](https://github.com/digitalocean/csi-digitalocean)
- [Ember CSI Driver](https://github.com/embercsi/ember-csi)
- [Cinder CSI Driver](https://github.com/kubernetes/cloud-provider-openstack/tree/master/pkg/csi/cinder)
- [Datera CSI Driver](https://github.com/Datera/datera-csi)
- [NexentaStor CSI Driver](https://github.com/Nexenta/nexentastor-csi-driver)
Snapshot support for other [drivers](https://kubernetes-csi.github.io/docs/Drivers.html) is pending, and should be available soon. Read the “Container Storage Interface (CSI) for Kubernetes GA” blog post to learn more about CSI and how to deploy CSI drivers.
## Whats next?
Depending on feedback and adoption, the Kubernetes team plans to push the CSI Snapshot implementation to beta in either 1.15 or 1.16. Some of the features we are interested in supporting include consistency groups, application consistent snapshots, workload quiescing, in-place restores, and more.
## How can I learn more?
The code repository for snapshot APIs and controller is here: https://github.com/kubernetes-csi/external-snapshotter
Check out additional documentation on the snapshot feature here: http://k8s.io/docs/concepts/storage/volume-snapshots and https://kubernetes-csi.github.io/docs/
## How do I get involved?
This project, like all of Kubernetes, is the result of hard work by many contributors from diverse backgrounds working together.
Special thanks to all the contributors that helped add CSI v1.0 support and improve the snapshot feature in this release, including Saad Ali ([saadali](https://github.com/saadali)), Michelle Au ([msau42](https://github.com/msau42)), Deep Debroy ([ddebroy](https://github.com/ddebroy)), James DeFelice ([jdef](https://github.com/jdef)), John Griffith ([j-griffith](https://github.com/j-griffith)), Julian Hjortshoj ([julian-hj](https://github.com/julian-hj)), Tim Hockin ([thockin](https://github.com/thockin)), Patrick Ohly ([pohly](https://github.com/pohly)), Luis Pabon ([lpabon](https://github.com/lpabon)), Cheng Xing ([verult](https://github.com/verult)), Jing Xu ([jingxu97](https://github.com/jingxu97)), Shiwei Xu ([wackxu](https://github.com/wackxu)), Xing Yang ([xing-yang](https://github.com/xing-yang)), Jie Yu ([jieyu](https://github.com/jieyu)), David Zhu ([davidz627](https://github.com/davidz627)).
Those interested in getting involved with the design and development of CSI or any part of the Kubernetes Storage system, join the [Kubernetes Storage Special Interest Group](https://github.com/kubernetes/community/tree/master/sig-storage) (SIG). Were rapidly growing and always welcome new contributors.
We also hold regular [SIG-Storage Snapshot Working Group meetings](https://docs.google.com/document/d/1qdfvAj5O-tTAZzqJyz3B-yczLLxOiQd-XKpJmTEMazs/edit?usp=sharing). New attendees are welcome to join for design and development discussions.
@@ -0,0 +1,70 @@
---
title: Poseidon-Firmament Scheduler Flow Network Graph Based Scheduler
date: 2019-02-06
---
**Authors:** Deepak Vij (Huawei), Shivram Shrivastava (Huawei)
## Introduction
Cluster Management systems such as Mesos, Google Borg, Kubernetes etc. in a cloud scale datacenter environment (also termed as ***Datacenter-as-a-Computer*** or ***Warehouse-Scale Computing - WSC***) typically manage application workloads by performing tasks such as tracking machine live-ness, starting, monitoring, terminating workloads and more importantly using a **Cluster Scheduler** to decide on workload placements.
A **Cluster Scheduler** essentially performs the scheduling of workloads to compute resources combining the global placement of work across the WSC environment makes the “warehouse-scale computer” more efficient, increases utilization, and saves energy. **Cluster Scheduler** examples are Google Borg, Kubernetes, Firmament, Mesos, Tarcil, Quasar, Quincy, Swarm, YARN, Nomad, Sparrow, Apollo etc.
In this blog post, we briefly describe the novel Firmament flow network graph based scheduling approach ([OSDI paper](https://www.usenix.org/conference/osdi16/technical-sessions/presentation/gog)) in Kubernetes. We specifically describe the Firmament Scheduler and how it integrates with the Kubernetes cluster manager using Poseidon as the integration glue. We have seen extremely impressive scheduling throughput performance benchmarking numbers with this novel scheduling approach. Originally, Firmament Scheduler was conceptualized, designed and implemented by University of Cambridge researchers, [Malte Schwarzkopf](http://www.malteschwarzkopf.de/) & [Ionel Gog](http://ionelgog.org/).
## Poseidon-Firmament Scheduler How It Works
At a very high level, [Poseidon-Firmament scheduler](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/) augments the current Kubernetes scheduling capabilities by incorporating novel flow network graph based scheduling capabilities alongside the default Kubernetes Scheduler. It models the scheduling problem as a constraint-based optimization over a flow network graph by reducing scheduling to a min-cost max-flow optimization problem. Due to the inherent rescheduling capabilities, the new scheduler enables a globally optimal scheduling environment that constantly keeps refining the workloads placements dynamically.
## Key Advantages
Flow graph scheduling based [Poseidon-Firmament scheduler](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/) provides the following key advantages:
* Workloads (pods) are bulk scheduled to enable scheduling decisions at massive scale.
* Based on the extensive performance test results, Poseidon-Firmament scales much better than Kubernetes default scheduler as the number of nodes increase in a cluster. This is due to the fact that Poseidon-Firmament is able to amortize more and more work across workloads.
* Poseidon-Firmament Scheduler outperforms the Kubernetes default scheduler by a wide margin when it comes to throughput performance numbers for scenarios where compute resource requirements are somewhat uniform across jobs (Replicasets/Deployments/Jobs). Poseidon-Firmament scheduler end-to-end throughput performance numbers, including bind time, consistently get better as the number of nodes in a cluster increase. For example, for a 2,700 node cluster (shown in the graphs [here](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/benchmark/README.md)), Poseidon-Firmament scheduler achieves a 7X or greater end-to-end throughput than the Kubernetes default scheduler, which includes bind time.
* Availability of complex rule constraints.
* Scheduling in Poseidon-Firmament is very dynamic; it keeps cluster resources in a global optimal state during every scheduling run.
* Highly efficient resource utilizations.
## Firmament Flow Network Graph An Overview
Firmament scheduler runs a min-cost flow algorithm over the flow network to find an optimal flow, from which it extracts the implied workload (pod placements). A flow network is a directed graph whose arcs carry flow from source nodes (i.e. pod nodes) to a sink node. A cost and capacity associated with each arc constrain the flow, and specify preferential routes for it.
Figure 1 below shows an example of a flow network for a cluster with two tasks (workloads or pods) and four machines (nodes) each workload on the left hand side, is a source of one unit of flow. All such flow must be drained into the sink node (S) for a feasible solution to the optimization problem.
{{<figure width="600" src="/images/blog/2019-02-03-poseidon-firmament-scheduler/example-of-a-flow-network.png" caption="Figure 1. Example of a Flow Network">}}
## Poseidon Mediation Layer An Overview
Poseidon is a service that acts as the integration glue for the Firmament scheduler with Kubernetes. It augments the current Kubernetes scheduling capabilities by incorporating new flow network graph based Firmament scheduling capabilities alongside the default Kubernetes Scheduler; multiple schedulers running simultaneously. Figure 2 below describes the high level overall design as far as how Poseidon integration glue works in conjunction with the underlying Firmament flow network graph based scheduler.
{{<figure width="600" src="/images/blog/2019-02-03-poseidon-firmament-scheduler/firmament-kubernetes-integration-overview.png" caption="Figure 2. Firmament Kubernetes Integration Overview">}}
As part of the Kubernetes multiple schedulers support, each new pod is typically scheduled by the default scheduler, but Kubernetes can be instructed to use another scheduler by specifying the name of another custom scheduler (in our case, [Poseidon-Firmament](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/)) at the time of pod deployment. In this case, the default scheduler will ignore that Pod and allow Poseidon scheduler to schedule the Pod to a relevant node.
{{< note >}}
For details about the design of this project see the [design document](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/design/README.md).
{{< /note >}}
## Possible Use Case Scenarios When To Use It
[Poseidon-Firmament scheduler](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/) enables extremely high throughput scheduling environment at scale due to its bulk scheduling approach superiority versus K8s pod-at-a-time approach. In our extensive tests, we have observed substantial throughput benefits as long as resource requirements (CPU/Memory) for incoming Pods is uniform across jobs (Replicasets/Deployments/Jobs), mainly due to efficient amortization of work across jobs.
Although, [Poseidon-Firmament scheduler](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/) is capable of scheduling various types of workloads (service, batch, etc.), following are the few use cases where it excels the most:
1. For “Big Data/AI” jobs consisting of a large number of tasks, throughput benefits are tremendous.
2. Substantial throughput benefits also for service or batch job scenarios where workload resource requirements are uniform across jobs (Replicasets/Deplyments/Jobs).
## Current Project Stage
Currently Poseidon-Firmament project is an incubation project. Alpha Release is available at https://github.com/kubernetes-sigs/poseidon.
@@ -0,0 +1,96 @@
---
title: Runc and CVE-2019-5736
date: 2019-02-11
---
This morning [a container escape vulnerability in runc was announced](https://www.openwall.com/lists/oss-security/2019/02/11/2). We wanted to provide some guidance to Kubernetes users to ensure everyone is safe and secure.
## What Is Runc?
Very briefly, runc is the low-level tool which does the heavy lifting of spawning a Linux container. Other tools like Docker, Containerd, and CRI-O sit on top of runc to deal with things like data formatting and serialization, but runc is at the heart of all of these systems.
Kubernetes in turn sits on top of those tools, and so while no part of Kubernetes itself is vulnerable, most Kubernetes installations are using runc under the hood.
### What Is The Vulnerability?
While full details are still embargoed to give people time to patch, the rough version is that when running a process as root (UID 0) inside a container, that process can exploit a bug in runc to gain root privileges on the host running the container. This then allows them unlimited access to the server as well as any other containers on that server.
If the process inside the container is either trusted (something you know is not hostile) or is not running as UID 0, then the vulnerability does not apply. It can also be prevented by SELinux, if an appropriate policy has been applied. RedHat Enterprise Linux and CentOS both include appropriate SELinux permissions with their packages and so are believed to be unaffected if SELinux is enabled.
The most common source of risk is attacker-controller container images, such as unvetted images from public repositories.
### What Should I Do?
As with all security issues, the two main options are to mitigate the vulnerability or upgrade your version of runc to one that includes the fix.
As the exploit requires UID 0 within the container, a direct mitigation is to ensure all your containers are running as a non-0 user. This can be set within the container image, or via your pod specification:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: run-as-uid-1000
spec:
securityContext:
runAsUser: 1000
# ...
```
This can also be enforced globally using a PodSecurityPolicy:
```yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: non-root
spec:
privileged: false
allowPrivilegeEscalation: false
runAsUser:
# Require the container to run without root privileges.
rule: 'MustRunAsNonRoot'
```
Setting a policy like this is highly encouraged given the overall risks of running as UID 0 inside a container.
Another potential mitigation is to ensure all your container images are vetted and trusted. This can be accomplished by building all your images yourself, or by vetting the contents of an image and then pinning to the image version hash (`image: external/someimage@sha256:7832659873hacdef`).
Upgrading runc can generally be accomplished by upgrading the package `runc` for your distribution or by upgrading your OS image if using immutable images. This is a list of known safe versions for various distributions and platforms:
* Ubuntu - [`runc 1.0.0~rc4+dfsg1-6ubuntu0.18.10.1`](https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-5736.html)
* Debian - [`runc 1.0.0~rc6+dfsg1-2`](https://security-tracker.debian.org/tracker/CVE-2019-5736)
* RedHat Enterprise Linux - [`docker 1.13.1-91.git07f3374.el7`](https://access.redhat.com/security/vulnerabilities/runcescape) (if SELinux is disabled)
* Amazon Linux - [`docker 18.06.1ce-7.25.amzn1.x86_64`](https://alas.aws.amazon.com/ALAS-2019-1156.html)
* CoreOS - Stable: [`1967.5.0`](https://coreos.com/releases/#1967.5.0) / Beta: [`2023.2.0`](https://coreos.com/releases/#2023.2.0) / Alpha: [`2051.0.0`](https://coreos.com/releases/#2051.0.0)
* Kops Debian - [in progress](https://github.com/kubernetes/kops/pull/6460) (see [advisory](https://github.com/kubernetes/kops/blob/master/docs/advisories/cve_2019_5736.md) for how to address until Kops Debian is patched)
* Docker - [`18.09.2`](https://github.com/docker/docker-ce/releases/tag/v18.09.2)
Some platforms have also posted more specific instructions:
#### Google Container Engine (GKE)
Google has issued a [security bulletin](https://cloud.google.com/kubernetes-engine/docs/security-bulletins#february-11-2019-runc) with more detailed information but in short, if you are using the default GKE node image then you are safe. If you are using an Ubuntu node image then you will need to mitigate or upgrade to an image with a fixed version of runc.
#### Amazon Elastic Container Service for Kubernetes (EKS)
Amazon has also issued a [security bulletin](https://aws.amazon.com/security/security-bulletins/AWS-2019-002/) with more detailed information. All EKS users should mitigate the issue or upgrade to a new node image.
#### Azure Kubernetes Service (AKS)
Microsoft has issued a [security bulletin](https://azure.microsoft.com/en-us/updates/cve-2019-5736-and-runc-vulnerability/) with detailed information on mitigating the issue. Microsoft recommends all AKS users to upgrade their cluster to mitigate the issue.
#### Kops
Kops has issued an [advisory](https://github.com/kubernetes/kops/blob/master/docs/advisories/cve_2019_5736.md) with detailed information on mitigating this issue.
### Docker
We don't have specific confirmation that Docker for Mac and Docker for Windows are vulnerable, however it seems likely. Docker has released a fix in [version 18.09.2](https://github.com/docker/docker-ce/releases/tag/v18.09.2) and it is recommended you upgrade to it. This also applies to other deploy systems using Docker under the hood.
If you are unable to upgrade Docker, the Rancher team has provided backports of the fix for many older versions at [github.com/rancher/runc-cve](https://github.com/rancher/runc-cve).
## Getting More Information
If you have any further questions about how this vulnerability impacts Kubernetes, please join us at [discuss.kubernetes.io](https://discuss.kubernetes.io/).
If you would like to get in contact with the [runc team](https://github.com/opencontainers/org/blob/master/README.md#communications), you can reach them on [Google Groups](https://groups.google.com/a/opencontainers.org/forum/#!forum/dev) or `#opencontainers` on Freenode IRC.
@@ -0,0 +1,107 @@
---
title: Building a Kubernetes Edge (Ingress) Control Plane for Envoy v2
date: 2019-02-12
slug: building-a-kubernetes-edge-control-plane-for-envoy-v2
---
**Author:**
Daniel Bryant, Product Architect, Datawire;
Flynn, Ambassador Lead Developer, Datawire;
Richard Li, CEO and Co-founder, Datawire
Kubernetes has become the de facto runtime for container-based microservice applications, but this orchestration framework alone does not provide all of the infrastructure necessary for running a distributed system. Microservices typically communicate through Layer 7 protocols such as HTTP, gRPC, or WebSockets, and therefore having the ability to make routing decisions, manipulate protocol metadata, and observe at this layer is vital. However, traditional load balancers and edge proxies have predominantly focused on L3/4 traffic. This is where the [Envoy Proxy](https://www.envoyproxy.io/) comes into play.
Envoy proxy was designed as a [universal data plane](https://blog.envoyproxy.io/the-universal-data-plane-api-d15cec7a) from the ground-up by the Lyft Engineering team for today's distributed, L7-centric world, with broad support for L7 protocols, a real-time API for managing its configuration, first-class observability, and high performance within a small memory footprint. However, Envoy's vast feature set and flexibility of operation also makes its configuration highly complicated -- this is evident from looking at its rich but verbose [control plane](https://blog.envoyproxy.io/service-mesh-data-plane-vs-control-plane-2774e720f7fc) syntax.
With the open source [Ambassador API Gateway](https://www.getambassador.io), we wanted to tackle the challenge of creating a new control plane that focuses on the use case of deploying Envoy as an forward-facing edge proxy within a Kubernetes cluster, in a way that is idiomatic to Kubernetes operators. In this article, we'll walk through two major iterations of the Ambassador design, and how we integrated Ambassador with Kubernetes.
## Ambassador pre-2019: Envoy v1 APIs, Jinja Template Files, and Hot Restarts
Ambassador itself is deployed within a container as a Kubernetes service, and uses annotations added to Kubernetes Services as its [core configuration model](https://www.getambassador.io/reference/configuration). This approach [enables application developers to manage routing](https://www.getambassador.io/concepts/developers) as part of the Kubernetes service definition. We explicitly decided to go down this route because of [limitations](https://blog.getambassador.io/kubernetes-ingress-nodeport-load-balancers-and-ingress-controllers-6e29f1c44f2d) in the current [Ingress API spec](https://kubernetes.io/docs/concepts/services-networking/ingress/), and we liked the simplicity of extending Kubernetes services, rather than introducing another custom resource type. An example of an Ambassador annotation can be seen here:
```
kind: Service
apiVersion: v1
metadata:
name: my-service
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v0
kind: Mapping
name: my_service_mapping
prefix: /my-service/
service: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
```
Translating this simple Ambassador annotation config into valid [Envoy v1](https://www.envoyproxy.io/docs/envoy/v1.6.0/configuration/overview/v1_overview) config was not a trivial task. By design, Ambassador's configuration isn't based on the same conceptual model as Envoy's configuration -- we deliberately wanted to aggregate and simplify operations and config. Therefore, translating between one set of concepts to the other involves a fair amount of logic within Ambassador.
In this first iteration of Ambassador we created a Python-based service that watched the Kubernetes API for changes to Service objects. When new or updated Ambassador annotations were detected, these were translated from the Ambassador syntax into an intermediate representation (IR) which embodied our core configuration model and concepts. Next, Ambassador translated this IR into a representative Envoy configuration which was saved as a file within pods associated with the running Ambassador k8s Service. Ambassador then "hot-restarted" the Envoy process running within the Ambassador pods, which triggered the loading of the new configuration.
There were many benefits with this initial implementation. The mechanics involved were fundamentally simple, the transformation of Ambassador config into Envoy config was reliable, and the file-based hot restart integration with Envoy was dependable.
However, there were also notable challenges with this version of Ambassador. First, although the hot restart was effective for the majority of our customers' use cases, it was not very fast, and some customers (particularly those with huge application deployments) found it was limiting the frequency with which they could change their configuration. Hot restart can also drop connections, especially long-lived connections like WebSockets or gRPC streams.
More crucially, though, the first implementation of the IR allowed rapid prototyping but was primitive enough that it proved very difficult to make substantial changes. While this was a pain point from the beginning, it became a critical issue as Envoy shifted to the [Envoy v2 API](https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/v2_overview). It was clear that the v2 API would offer Ambassador many benefits -- as Matt Klein outlined in his blog post, "[The universal data plane API](https://blog.envoyproxy.io/the-universal-data-plane-api-d15cec7a)" -- including access to new features and a solution to the connection-drop problem noted above, but it was also clear that the existing IR implementation was not capable of making the leap.
## Ambassador >= v0.50: Envoy v2 APIs (ADS), Testing with KAT, and Golang
In consultation with the [Ambassador community](http://d6e.co/slack), the [Datawire](www.datawire.io) team undertook a redesign of the internals of Ambassador in 2018. This was driven by two key goals. First, we wanted to integrate Envoy's v2 configuration format, which would enable the support of features such as [SNI](https://www.getambassador.io/user-guide/sni/), [rate limiting](https://www.getambassador.io/user-guide/rate-limiting) and [gRPC authentication APIs](https://www.getambassador.io/user-guide/auth-tutorial). Second, we also wanted to do much more robust semantic validation of Envoy configuration due to its increasing complexity (particularly when operating with large-scale application deployments).
### Initial stages
We started by restructuring the Ambassador internals more along the lines of a multipass compiler. The class hierarchy was made to more closely mirror the separation of concerns between the Ambassador configuration resources, the IR, and the Envoy configuration resources. Core parts of Ambassador were also redesigned to facilitate contributions from the community outside Datawire. We decided to take this approach for several reasons. First, Envoy Proxy is a very fast moving project, and we realized that we needed an approach where a seemingly minor Envoy configuration change didn't result in days of reengineering within Ambassador. In addition, we wanted to be able to provide semantic verification of configuration.
As we started working more closely with Envoy v2, a testing challenge was quickly identified. As more and more features were being supported in Ambassador, more and more bugs appeared in Ambassador's handling of less common but completely valid combinations of features. This drove to creation of a new testing requirement that meant Ambassador's test suite needed to be reworked to automatically manage many combinations of features, rather than relying on humans to write each test individually. Moreover, we wanted the test suite to be fast in order to maximize engineering productivity.
Thus, as part of the Ambassador rearchitecture, we introduced the [Kubernetes Acceptance Test (KAT)](https://github.com/datawire/ambassador/tree/master/kat) framework. KAT is an extensible test framework that:
1. Deploys a bunch of services (along with Ambassador) to a Kubernetes cluster
1. Run a series of verification queries against the spun up APIs
1. Perform a bunch of assertions on those query results
KAT is designed for performance -- it batches test setup upfront, and then runs all the queries in step 3 asynchronously with a high performance client. The traffic driver in KAT runs locally using [Telepresence](https://www.telepresence.io), which makes it easier to debug issues.
### Introducing Golang to the Ambassador Stack
With the KAT test framework in place, we quickly ran into some issues with Envoy v2 configuration and hot restart, which presented the opportunity to switch to use Envoys Aggregated Discovery Service (ADS) APIs instead of hot restart. This completely eliminated the requirement for restart on configuration changes, which we found could lead to dropped connection under high loads or long-lived connections.
However, we faced an interesting question as we considered the move to the ADS. The ADS is not as simple as one might expect: there are explicit ordering dependencies when sending updates to Envoy. The Envoy project has reference implementations of the ordering logic, but only in Go and Java, where Ambassador was primarily in Python. We agonized a bit, and decided that the simplest way forward was to accept the polyglot nature of our world, and do our ADS implementation in Go.
We also found, with KAT, that our testing had reached the point where Pythons performance with many network connections was a limitation, so we took advantage of Go here, as well, writing KATs querying and backend services primarily in Go. After all, whats another Golang dependency when youve already taken the plunge?
With a new test framework, new IR generating valid Envoy v2 configuration, and the ADS, we thought we were done with the major architectural changes in Ambassador 0.50. Alas, we hit one more issue. On the Azure Kubernetes Service, Ambassador annotation changes were no longer being detected.
Working with the highly-responsive AKS engineering team, we were able to identify the issue -- namely, the Kubernetes API server in AKS is exposed through a chain of proxies, requiring clients to be updating to understand how to connect using the FQDN of the API server, which is provided through a mutating webhook in AKS. Unfortunately, support for this feature was not available in the official Kubernetes Python client, so this was the third spot where we chose to switch to Go instead of Python.
This raises the interesting question of, “why not ditch all the Python code, and just rewrite Ambassador entirely in Go?” Its a valid question. The main concern with a rewrite is that Ambassador and Envoy operate at different conceptual levels rather than simply expressing the same concepts with different syntax. Being certain that weve expressed the conceptual bridges in a new language is not a trivial challenge, and not something to undertake without already having really excellent test coverage in place
At this point, we use Go to coverage very specific, well-contained functions that can be verified for correctness much more easily that we could verify a complete Golang rewrite. In the future, who knows? But for 0.50.0, this functional split let us both take advantage of Golangs strengths, while letting us retain more confidence about all the changes already in 0.50.
## Lessons Learned
We've learned a lot in the process of building [Ambassador 0.50](https://blog.getambassador.io/ambassador-0-50-ga-release-notes-sni-new-authservice-and-envoy-v2-support-3b30a4d04c81). Some of our key takeaways:
* Kubernetes and Envoy are very powerful frameworks, but they are also extremely fast moving targets -- there is sometimes no substitute for reading the source code and talking to the maintainers (who are fortunately all quite accessible!)
* The best supported libraries in the Kubernetes / Envoy ecosystem are written in Go. While we love Python, we have had to adopt Go so that we're not forced to maintain too many components ourselves.
* Redesigning a test harness is sometimes necessary to move your software forward.
* The real cost in redesigning a test harness is often in porting your old tests to the new harness implementation.
* Designing (and implementing) an effective control plane for the edge proxy use case has been challenging, and the feedback from the open source community around Kubernetes, Envoy and Ambassador has been extremely useful.
Migrating Ambassador to the Envoy v2 configuration and ADS APIs was a long and difficult journey that required lots of architecture and design discussions and plenty of coding, but early feedback from results have been positive. [Ambassador 0.50 is available now](https://blog.getambassador.io/announcing-ambassador-0-50-8dffab5b05e0), so you can take it for a test run and share your feedback with the community on our [Slack channel](http://d6e.co/slack) or on [Twitter](https://www.twitter.com/getambassadorio).
@@ -0,0 +1,67 @@
---
title: Automate Operations on your Cluster with OperatorHub.io
date: 2019-02-28
---
**Author:**
Diane Mueller, Director of Community Development, Cloud Platforms, Red Hat
One of the important challenges facing developers and Kubernetes administrators has been a lack of ability to quickly find common services that are operationally ready for Kubernetes. Typically, the presence of an Operator for a specific service - a pattern that was introduced in 2016 and has gained momentum - is a good signal for the operational readiness of the service on Kubernetes. However, there has to date not existed a registry of Operators to simplify the discovery of such services.
To help address this challenge, today Red Hat is launching OperatorHub.io in collaboration with AWS, Google Cloud and Microsoft. OperatorHub.io enables developers and Kubernetes administrators to find and install curated Operator-backed services with a base level of documentation, active maintainership by communities or vendors, basic testing, and packaging for optimized life-cycle management on Kubernetes.
The Operators currently in OperatorHub.io are just the start. We invite the Kubernetes community to join us in building a vibrant community for Operators by developing, packaging, and publishing Operators on OperatorHub.io.
## What does OperatorHub.io provide?
OperatorHub.io is designed to address the needs of both Kubernetes developers and users. For the former it provides a common registry where they can publish their Operators alongside with descriptions, relevant details like version, image, code repository and have them be readily packaged for installation. They can also update already published Operators to new versions when they are released.
Users get the ability to discover and download Operators at a central location, that has content which has been screened for the previously mentioned criteria and scanned for known vulnerabilities. In addition, developers can guide users of their Operators with prescriptive examples of the `CustomResources` that they introduce to interact with the application.
## What is an Operator?
Operators were first introduced in 2016 by CoreOS and have been used by Red Hat and the Kubernetes community as a way to package, deploy and manage a Kubernetes-native application. A Kubernetes-native application is an application that is both deployed on Kubernetes and managed using the Kubernetes APIs and well-known tooling, like kubectl.
An Operator is implemented as a custom controller that watches for certain Kubernetes resources to appear, be modified or deleted. These are typically `CustomResourceDefinitions` that the Operator “owns.” In the spec properties of these objects the user declares the desired state of the application or the operation. The Operators reconciliation loop will pick these up and perform the required actions to achieve the desired state. For example, the intent to create a highly available etcd cluster could be expressed by creating an new resource of type `EtcdCluster`:
```
apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
name: "my-etcd-cluster"
spec:
size: 3
version: "3.3.12"
```
The `EtcdOperator` would be responsible for creating a 3-node etcd cluster running version v3.3.12 as a result. Similarly, an object of type `EtcdBackup` could be defined to express the intent to create a consistent backup of the etcd database to an S3 bucket.
## How do I create and run an Operator?
One way to get started is with the [Operator Framework](https://github.com/operator-framework), an open source toolkit that provides an SDK, lifecycle management, metering and monitoring capabilities. It enables developers to build, test, and package Operators. Operators can be implemented in several programming and automation languages, including Go, Helm, and Ansible, all three of which are supported directly by the SDK.
If you are interested in creating your own Operator, we recommend checking out the Operator Framework to [get started](https://github.com/operator-framework/getting-started).
Operators vary in where they fall along [the capability spectrum](https://github.com/operator-framework/operator-sdk/blob/master/doc/images/operator-maturity-model.png) ranging from basic functionality to having specific operational logic for an application to automate advanced scenarios like backup, restore or tuning. Beyond basic installation, advanced Operators are designed to handle upgrades more seamlessly and react to failures automatically. Currently, Operators on OperatorHub.io span the maturity spectrum, but we anticipate their continuing maturation over time.
While Operators on OperatorHub.io dont need to be implemented using the SDK, they are packaged for deployment through the [Operator Lifecycle Manager](https://github.com/operator-framework/operator-lifecycle-manager) (OLM). The format mainly consists of a YAML manifest referred to as `[ClusterServiceVersion]`(https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Documentation/design/building-your-csv.md) which provides information about the `CustomResourceDefinitions` the Operator owns or requires, which RBAC definition it needs, where the image is stored, etc. This file is usually accompanied by additional YAML files which define the Operators own CRDs. This information is processed by OLM at the time a user requests to install an Operator to provide dependency resolution and automation.
## What does listing of an Operator on OperatorHub.io mean?
To be listed, Operators must successfully show cluster lifecycle features, be packaged as a CSV to be maintained through OLM, and have acceptable documentation for its intended users.
Some examples of Operators that are currently listed on OperatorHub.io include: Amazon Web Services Operator, Couchbase Autonomous Operator, CrunchyDatas PostgreSQL, etcd Operator, Jaeger Operator for Kubernetes, Kubernetes Federation Operator, MongoDB Enterprise Operator, Percona MySQL Operator, PlanetScales Vitess Operator, Prometheus Operator, and Redis Operator.
## Want to add your Operator to OperatorHub.io? Follow these steps
If you have an existing Operator, follow the [contribution guide](https://www.operatorhub.io/contribute) using a fork of the [community-operators](https://github.com/operator-framework/community-operators/) repository. Each contribution contains the CSV, all of the `CustomResourceDefinitions`, access control rules and references to the container image needed to install and run your Operator, plus other info like a description of its features and supported Kubernetes versions. A complete example, including multiple versions of the Operator, can be found with the [EtcdOperator](https://github.com/operator-framework/community-operators/tree/master/community-operators/etcd).
After testing out your Operator on your own cluster, submit a PR to the [community repository](https://github.com/operator-framework/community-operators) with all of YAML files following [this directory structure](https://github.com/operator-framework/community-operators#adding-your-operator). Subsequent versions of the Operator can be published in the same way. At first this will be reviewed manually, but automation is on the way. After its merged by the maintainers, it will show up on OperatorHub.io along with its documentation and a convenient installation method.
## Want to learn more?
- Attend one of the upcoming Kubernetes Operator Framework hands-on workshops at [ScaleX](https://www.socallinuxexpo.org/scale/17x/presentations/workshop-kubernetes-operator-framework) in Pasadena on March 7 and at the [OpenShift Commons Gathering on Operating at Scale in Santa Clara on March 11](https://commons.openshift.org/gatherings/Santa_Clara_2019.html)
- Listen to this [OpenShift Commons Briefing on “The State of Operators” with Daniel Messer and Diane Mueller](https://www.youtube.com/watch?v=GgEKEYH9MMM&feature=youtu.be)
- Join in on the online conversations in the community [Kubernetes-Operator Slack Channel](https://kubernetes.slack.com/messages/CAW0GV7A5) and the [Operator Framework Google Group](https://groups.google.com/forum/#!forum/operator-framework)
- Finally, read up on how to add your Operator to OperatorHub.io: https://operatorhub.io/contribute
@@ -0,0 +1,131 @@
---
title: Raw Block Volume support to Beta
date: 2019-03-07
---
**Authors:**
Ben Swartzlander (NetApp), Saad Ali (Google)
Kubernetes v1.13 moves raw block volume support to beta. This feature allows persistent volumes to be exposed inside containers as a block device instead of as a mounted file system.
## What are block devices?
Block devices enable random access to data in fixed-size blocks. Hard drives, SSDs, and CD-ROMs drives are all examples of block devices.
Typically persistent storage is implemented in a layered maner with a file system (like ext4) on top of a block device (like a spinning disk or SSD). Applications then read and write files instead of operating on blocks. The operating systems take care of reading and writing files, using the specified filesystem, to the underlying device as blocks.
It's worth noting that while whole disks are block devices, so are disk partitions, and so are LUNs from a storage area network (SAN) device.
## Why add raw block volumes to kubernetes?
There are some specialized applications that require direct access to a block device because, for example, the file system layer introduces unneeded overhead. The most common case is databases, which prefer to organize their data directly on the underlying storage. Raw block devices are also commonly used by any software which itself implements some kind of storage service (software defined storage systems).
From a programmer's perspective, a block device is a very large array of bytes, usually with some minimum granularity for reads and writes, often 512 bytes, but frequently 4K or larger.
As it becomes more common to run database software and storage infrastructure software inside of Kubernetes, the need for raw block device support in Kubernetes becomes more important.
## Which volume plugins support raw blocks?
As of the publishing of this blog, the following in-tree volumes types support raw blocks:
- AWS EBS
- Azure Disk
- Cinder
- Fibre Channel
- GCE PD
- iSCSI
- Local volumes
- RBD (Ceph)
- Vsphere
Out-of-tree [CSI volume drivers](https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/) may also support raw block volumes. Kubernetes CSI support for raw block volumes is currently alpha. See documentation [here](https://kubernetes-csi.github.io/docs/raw-block.html).
## Kubernetes raw block volume API
Raw block volumes share a lot in common with ordinary volumes. Both are requested by creating `PersistentVolumeClaim` objects which bind to `PersistentVolume` objects, and are attached to Pods in Kubernetes by including them in the volumes array of the `PodSpec`.
There are 2 important differences however. First, to request a raw block `PersistentVolumeClaim`, you must set `volumeMode = "Block"` in the `PersistentVolumeClaimSpec`. Leaving `volumeMode` blank is the same as specifying `volumeMode = "Filesystem"` which results in the traditional behavior. `PersistentVolumes` also have a `volumeMode` field in their `PersistentVolumeSpec`, and `"Block"` type PVCs can only bind to `"Block"` type PVs and `"Filesystem"` PVCs can only bind to `"Filesystem"` PVs.
Secondly, when using a raw block volume in your Pods, you must specify a `VolumeDevice` in the Container portion of the `PodSpec` rather than a `VolumeMount`. `VolumeDevices` have `devicePaths` instead of `mountPaths`, and inside the container, applications will see a device at that path instead of a mounted file system.
Applications open, read, and write to the device node inside the container just like they would interact with any block device on a system in a non-containerized or virtualized context.
## Creating a new raw block PVC
First, ensure that the provisioner associated with the storage class you choose is one that support raw blocks. Then create the PVC.
```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteMany
volumeMode: Block
storageClassName: my-sc
resources:
requests:
storage: 1Gi
```
## Using a raw block PVC
When you use the PVC in a pod definition, you get to choose the device path for the block device rather than the mount path for the file system.
```
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: busybox
command:
- sleep
- “3600”
volumeDevices:
- devicePath: /dev/block
name: my-volume
imagePullPolicy: IfNotPresent
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: my-pvc
```
## As a storage vendor, how do I add support for raw block devices to my CSI plugin?
Raw block support for CSI plugins is still alpha, but support can be added today. The [CSI specification](https://github.com/container-storage-interface/spec/blob/master/spec.md) details how to handle requests for volume that have the `BlockVolume` capability instead of the `MountVolume` capability. CSI plugins can support both kinds of volumes, or one or the other. For more details see [documentation here](https://kubernetes-csi.github.io/docs/raw-block.html).
## Issues/gotchas
Because block devices are actually devices, its possible to do low-level actions on them from inside containers that wouldnt be possible with file system volumes. For example, block devices that are actually SCSI disks support sending SCSI commands to the device using Linux ioctls.
By default, Linux wont allow containers to send SCSI commands to disks from inside containers though. In order to do so, you must grant the `SYS_RAWIO` capability to the container security context to allow this. See documentation [here](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container).
Also, while Kubernetes is guaranteed to deliver a block device to the container, theres no guarantee that its actually a SCSI disk or any other kind of disk for that matter. The user must either ensure that the desired disk type is used with his pods, or only deploy applications that can handle a variety of block device types.
## How can I learn more?
Check out additional documentation on the snapshot feature here: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#raw-block-volume-support
How do I get involved?
Join the Kubernetes storage SIG and the CSI community and help us add more great features and improve existing ones like raw block storage!
https://github.com/kubernetes/community/tree/master/sig-storage
https://github.com/container-storage-interface/community/blob/master/README.md
Special thanks to all the contributors who helped add block volume support to Kubernetes including:
- Ben Swartzlander (https://github.com/bswartz)
- Brad Childs (https://github.com/childsb)
- Erin Boyd (https://github.com/erinboyd)
- Masaki Kimura (https://github.com/mkimuram)
- Matthew Wong (https://github.com/wongma7)
- Michelle Au (https://github.com/msau42)
- Mitsuhiro Tanino (https://github.com/mtanino)
- Saad Ali (https://github.com/saad-ali)
@@ -0,0 +1,253 @@
---
layout: blog
title: Kubernetes Setup Using Ansible and Vagrant
date: 2019-03-15
---
**Author:** Naresh L J (Infosys)
## Objective
This blog post describes the steps required to setup a multi node Kubernetes cluster for development purposes. This setup provides a production-like cluster that can be setup on your local machine.
## Why do we require multi node cluster setup?
Multi node Kubernetes clusters offer a production-like environment which has various advantages. Even though Minikube provides an excellent platform for getting started, it doesn't provide the opportunity to work with multi node clusters which can help solve problems or bugs that are related to application design and architecture. For instance, Ops can reproduce an issue in a multi node cluster environment, Testers can deploy multiple versions of an application for executing test cases and verifying changes. These benefits enable teams to resolve issues faster which make the more agile.
## Why use Vagrant and Ansible?
Vagrant is a tool that will allow us to create a virtual environment easily and it eliminates pitfalls that cause the works-on-my-machine phenomenon. It can be used with multiple providers such as Oracle VirtualBox, VMware, Docker, and so on. It allows us to create a disposable environment by making use of configuration files.
Ansible is an infrastructure automation engine that automates software configuration management. It is agentless and allows us to use SSH keys for connecting to remote machines. Ansible playbooks are written in yaml and offer inventory management in simple text files.
### Prerequisites
- Vagrant should be installed on your machine. Installation binaries can be found [here](https://www.vagrantup.com/downloads.html).
- Oracle VirtualBox can be used as a Vagrant provider or make use of similar providers as described in Vagrant's official [documentation](https://www.vagrantup.com/docs/providers/).
- Ansible should be installed in your machine. Refer to the [Ansible installation guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) for platform specific installation.
## Setup overview
We will be setting up a Kubernetes cluster that will consist of one master and two worker nodes. All the nodes will run Ubuntu Xenial 64-bit OS and Ansible playbooks will be used for provisioning.
#### Step 1: Creating a Vagrantfile
Use the text editor of your choice and create a file with named `Vagrantfile`, inserting the code below. The value of N denotes the number of nodes present in the cluster, it can be modified accordingly. In the below example, we are setting the value of N as 2.
```ruby
IMAGE_NAME = "bento/ubuntu-16.04"
N = 2
Vagrant.configure("2") do |config|
config.ssh.insert_key = false
config.vm.provider "virtualbox" do |v|
v.memory = 1024
v.cpus = 2
end
config.vm.define "k8s-master" do |master|
master.vm.box = IMAGE_NAME
master.vm.network "private_network", ip: "192.168.50.10"
master.vm.hostname = "k8s-master"
master.vm.provision "ansible" do |ansible|
ansible.playbook = "kubernetes-setup/master-playbook.yml"
end
end
(1..N).each do |i|
config.vm.define "node-#{i}" do |node|
node.vm.box = IMAGE_NAME
node.vm.network "private_network", ip: "192.168.50.#{i + 10}"
node.vm.hostname = "node-#{i}"
node.vm.provision "ansible" do |ansible|
ansible.playbook = "kubernetes-setup/node-playbook.yml"
end
end
end
```
### Step 2: Create an Ansible playbook for Kubernetes master.
Create a directory named `kubernetes-setup` in the same directory as the `Vagrantfile`. Create two files named `master-playbook.yml` and `node-playbook.yml` in the directory `kubernetes-setup`.
In the file `master-playbook.yml`, add the code below.
#### Step 2.1: Install Docker and its dependent components.
We will be installing the following packages, and then adding a user named “vagrant” to the “docker” group.
- docker-ce
- docker-ce-cli
- containerd.io
```yaml
---
- hosts: all
become: true
tasks:
- name: Install packages that allow apt to be used over HTTPS
apt:
name: "{{ packages }}"
state: present
update_cache: yes
vars:
packages:
- apt-transport-https
- ca-certificates
- curl
- gnupg-agent
- software-properties-common
- name: Add an apt signing key for Docker
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add apt repository for stable version
apt_repository:
repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable
state: present
- name: Install docker and its dependecies
apt:
name: "{{ packages }}"
state: present
update_cache: yes
vars:
packages:
- docker-ce
- docker-ce-cli
- containerd.io
notify:
- docker status
- name: Add vagrant user to docker group
user:
name: vagrant
group: docker
```
#### Step 2.2: Kubelet will not start if the system has swap enabled, so we are disabling swap using the below code.
```yaml
- name: Remove swapfile from /etc/fstab
mount:
name: "{{ item }}"
fstype: swap
state: absent
with_items:
- swap
- none
- name: Disable swap
command: swapoff -a
when: ansible_swaptotal_mb > 0
```
#### Step 2.3: Installing kubelet, kubeadm and kubectl using the below code.
```yaml
- name: Add an apt signing key for Kubernetes
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
state: present
- name: Adding apt repository for Kubernetes
apt_repository:
repo: deb https://apt.kubernetes.io/ kubernetes-xenial main
state: present
filename: kubernetes.list
- name: Install Kubernetes binaries
apt:
name: "{{ packages }}"
state: present
update_cache: yes
vars:
packages:
- kubelet
- kubeadm
- kubectl
```
#### Step 2.3: Initialize the Kubernetes cluster with kubeadm using the below code (applicable only on master node).
```yaml
- name: Initialize the Kubernetes cluster using kubeadm
command: kubeadm init --apiserver-advertise-address="192.168.50.10" --apiserver-cert-extra-sans="192.168.50.10" --node-name k8s-master --pod-network-cidr=192.168.0.0/16
```
#### Step 2.4: Setup the kube config file for the vagrant user to access the Kubernetes cluster using the below code.
```yaml
- name: Setup kubeconfig for vagrant user
command: "{{ item }}"
with_items:
- mkdir -p /home/vagrant/.kube
- cp -i /etc/kubernetes/admin.conf /home/vagrant/.kube/config
- chown vagrant:vagrant /home/vagrant/.kube/config
```
#### Step 2.5: Setup the container networking provider and the network policy engine using the below code.
```yaml
- name: Install calico pod network
become: false
command: kubectl create -f https://docs.projectcalico.org/v3.4/getting-started/kubernetes/installation/hosted/calico.yaml
```
#### Step 2.6: Generate kube join command for joining the node to the Kubernetes cluster and store the command in the file named `join-command`.
```yaml
- name: Generate join command
command: kubeadm token create --print-join-command
register: join_command
- name: Copy join command to local file
local_action: copy content="{{ join_command.stdout_lines[0] }}" dest="./join-command"
```
#### Step 2.7: Setup a handler for checking Docker daemon using the below code.
```yaml
handlers:
- name: docker status
service: name=docker state=started
```
#### Step 3: Create the Ansible playbook for Kubernetes node.
Create a file named `node-playbook.yml` in the directory `kubernetes-setup`.
Add the code below into `node-playbook.yml`
#### Step 3.1: Start adding the code from Steps 2.1 till 2.3.
#### Step 3.2: Join the nodes to the Kubernetes cluster using below code.
```yaml
- name: Copy the join command to server location
copy: src=join-command dest=/tmp/join-command.sh mode=0777
- name: Join the node to cluster
command: sh /tmp/join-command.sh
```
#### Step 3.3: Add the code from step 2.7 to finish this playbook.
#### Step 4: Upon completing the Vagrantfile and playbooks follow the below steps.
```shell
$ cd /path/to/Vagrantfile
$ vagrant up
```
Upon completion of all the above steps, the Kubernetes cluster should be up and running.
We can login to the master or worker nodes using Vagrant as follows:
```shell
$ ## Accessing master
$ vagrant ssh k8s-master
vagrant@k8s-master:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 18m v1.13.3
node-1 Ready <none> 12m v1.13.3
node-2 Ready <none> 6m22s v1.13.3
$ ## Accessing nodes
$ vagrant ssh node-1
$ vagrant ssh node-2
```
+2
View File
@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
# Owned by Kubernetes Blog reviewers.
options:
no_parent_owners: false
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,86 @@
---
title: NetEase Case Study
case_study_styles: true
cid: caseStudies
css: /css/style_case_studies.css
---
<div class="banner1" style="background-image: url('/images/CaseStudy_netease_banner1.jpg')">
<h1> CASE STUDY:<img src="/images/netease_logo.png" class="header_logo" style="width:22%;margin-bottom:-1%"><br> <div class="subhead" style="margin-top:1%"> How NetEase Leverages Kubernetes to Support Internet Business Worldwide</div></h1>
</div>
<div class="details" style="font-size:1em">
Company &nbsp;<b>NetEase</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Location &nbsp;<b>Hangzhou, China</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Industry &nbsp;<b>Internet technology</b>
</div>
<hr>
<section class="section1">
<div class="cols">
<div class="col1" style="margin-left:-1.5% !important">
<h2>Challenge</h2>
Its gaming business is one of the largest in the world, but thats not all that <a href="https://netease-na.com/">NetEase</a> provides to Chinese consumers. The company also operates e-commerce, advertising, music streaming, online education, and email platforms; the last of which serves almost a billion users with free email services through sites like <a href="https://www.163.com/">163.com</a>. In 2015, the NetEase Cloud team providing the infrastructure for all of these systems realized that their R&D process was slowing down developers. “Our users needed to prepare all of the infrastructure by themselves,” says Feng Changjian, Architect for NetEase Cloud and Container Service. “We were eager to provide the infrastructure and tools for our users automatically via serverless container service.”
<br><br>
<h2>Solution</h2>
After considering building its own orchestration solution, NetEase decided to base its private cloud platform on <a href="https://kubernetes.io/">Kubernetes</a>. The fact that the technology came out of Google gave the team confidence that it could keep up with NetEases scale. “After our 2-to-3-month evaluation, we believed it could satisfy our needs,” says Feng. The team started working with Kubernetes in 2015, before it was even 1.0. Today, the NetEase internal cloud platform—which also leverages the CNCF projects <a href="https://prometheus.io/">Prometheus</a>, <a href="https://www.envoyproxy.io/">Envoy</a>, <a href="https://goharbor.io/">Harbor</a>, <a href="https://grpc.io/">gRPC</a>, and <a href="https://helm.sh/">Helm</a>—runs 10,000 nodes in a production cluster and can support up to 30,000 nodes in a cluster. Based on its learnings from its internal platform, the company introduced a Kubernetes-based cloud and microservices-oriented PaaS product, <a href="https://landscape.cncf.io/selected=netease-qingzhou-microservice">NetEase Qingzhou Microservice</a>, to outside customers.
<br><br>
<h2>Impact</h2>
The NetEase team reports that Kubernetes has increased R&D efficiency by more than 100%. Deployment efficiency has improved by 280%. “In the past, if we wanted to do upgrades, we needed to work with other teams, even in other departments,” says Feng. “We needed special staff to prepare everything, so it took about half an hour. Now we can do it in only 5 minutes.” The new platform also allows for mixed deployments using GPU and CPU resources. “Before, if we put all the resources toward the GPU, we wont have spare resources for the CPU. But now we have improvements thanks to the mixed deployments,” he says. Those improvements have also brought an increase in resource utilization.
</div>
</div>
</section>
<div class="banner2">
<div class="banner2text">
"The system can support 30,000 nodes in a single cluster. In production, we have gotten the data of 10,000 nodes in a single cluster. The whole internal system is using this system for development, test, and production."<br style="height:25px"><span style="font-size:14px;letter-spacing:2px;text-transform:uppercase;margin-top:5% !important;"><br>— Zeng Yuxing, Architect, NetEase</span>
</div>
</div>
<section class="section2">
<div class="fullcol">
<h2>Its gaming business is the <a href="https://newzoo.com/insights/rankings/top-25-companies-game-revenues/">fifth-largest</a> in the world, but thats not all that <a href="https://netease-na.com/">NetEase</a> provides consumers.</h2>The company also operates e-commerce, advertising, music streaming, online education, and email platforms in China; the last of which serves almost a billion users with free email services through popular sites like <a href="https://www.163.com/">163.com</a> and <a href="https://www.126.com/">126.com</a>. With that kind of scale, the NetEase Cloud team providing the infrastructure for all of these systems realized in 2015 that their R&D process was making it hard for developers to keep up with demand. “Our users needed to prepare all of the infrastructure by themselves,” says Feng Changjian, Architect for NetEase Cloud and Container Service. “We were eager to provide the infrastructure and tools for our users automatically via serverless container service.”<br><br>
After considering building its own orchestration solution, NetEase decided to base its private cloud platform on <a href="https://kubernetes.io/">Kubernetes</a>. The fact that the technology came out of Google gave the team confidence that it could keep up with NetEases scale. “After our 2-to-3-month evaluation, we believed it could satisfy our needs,” says Feng.
</div>
</section>
<div class="banner3" style="background-image: url('/images/CaseStudy_netease_banner3.jpg')">
<div class="banner3text">
"We leveraged the programmability of Kubernetes so that we can build a platform to satisfy the needs of our internal customers for upgrades and deployment."
<br style="height:25px"><span style="font-size:14px;letter-spacing:2px;text-transform:uppercase;margin-top:5% !important;"><br>- Feng Changjian, Architect for NetEase Cloud and Container Service, NetEase</span>
</div>
</div>
<section class="section3">
<div class="fullcol">
The team started adopting Kubernetes in 2015, before it was even 1.0, because it was relatively easy to use and enabled DevOps at the company. “We abandoned some of the concepts of Kubernetes; we only wanted to use the standardized framework,” says Feng. “We leveraged the programmability of Kubernetes so that we can build a platform to satisfy the needs of our internal customers for upgrades and deployment.”<br><br>
The team first focused on building the container platform to manage resources better, and then turned their attention to improving its support of microservices by adding internal systems such as monitoring. That has meant integrating the CNCF projects <a href="https://prometheus.io/">Prometheus</a>, <a href="https://www.envoyproxy.io/">Envoy</a>, <a href="https://goharbor.io/">Harbor</a>, <a href="https://grpc.io/">gRPC</a>, and <a href="https://helm.sh/">Helm</a>. “We are trying to provide a simplified and standardized process, so our users and customers can leverage our best practices,” says Feng.<br><br>
And the team is continuing to make improvements. For example, the e-commerce part of the business needs to leverage mixed deployments, which in the past required using two separate platforms: the infrastructure-as-a-service platform and the Kubernetes platform. More recently, NetEase has created a cross-platform application that enables using both with one-command deployment.
</div>
</section>
<div class="banner4" style="background-image: url('/images/CaseStudy_netease_banner4.jpg')">
<div class="banner4text">
"As long as a company has a mature team and enough developers, I think Kubernetes is a very good technology that can help them."
<span style="font-size:14px;letter-spacing:2px;text-transform:uppercase;margin-top:5% !important;"><br><br>- Li Lanqing, Kubernetes Developer, NetEase</span>
</div>
</div>
</div>
<section class="section5" style="padding:0px !important">
<div class="fullcol">
Today, the NetEase internal cloud platform “can support 30,000 nodes in a single cluster,” says Architect Zeng Yuxing. “In production, we have gotten the data of 10,000 nodes in a single cluster. The whole internal system is using this system for development, test, and production.” <br><br>
The NetEase team reports that Kubernetes has increased R&D efficiency by more than 100%. Deployment efficiency has improved by 280%. “In the past, if we wanted to do upgrades, we needed to work with other teams, even in other departments,” says Feng. “We needed special staff to prepare everything, so it took about half an hour. Now we can do it in only 5 minutes.” The new platform also allows for mixed deployments using GPU and CPU resources. “Before, if we put all the resources toward the GPU, we wont have spare resources for the CPU. But now we have improvements thanks to the mixed deployments.” Those improvements have also brought an increase in resource utilization.
</div>
<div class="banner5">
<div class="banner5text">
"By engaging with this community, we can gain some experience from it and we can also benefit from it. We can see what are the concerns and the challenges faced by the community, so we can get involved."<span style="font-size:14px;letter-spacing:2px;text-transform:uppercase;margin-top:5% !important;"><br><br>- Li Lanqing, Kubernetes Developer, NetEase</span>
</div>
</div>
<div class="fullcol">
Based on the results and learnings from using its internal platform, the company introduced a Kubernetes-based cloud and microservices-oriented PaaS product, <a href="https://landscape.cncf.io/selected=netease-qingzhou-microservice">NetEase Qingzhou Microservice</a>, to outside customers. “The idea is that we can find the problems encountered by our game and e-commerce and cloud music providers, so we can integrate their experiences and provide a platform to satisfy the needs of our users,” says Zeng. <br><br>
With or without the use of the NetEase product, the team encourages other companies to try Kubernetes. “As long as a company has a mature team and enough developers, I think Kubernetes is a very good technology that can help them,” says Kubernetes developer Li Lanqing.<br><br>
As an end user as well as a vendor, NetEase has become more involved in the community, learning from other companies and sharing what theyve done. The team has been contributing to the Harbor and Envoy projects, providing feedback as the technologies are being tested at NetEase scale. “We are a team focusing on addressing the challenges of microservices architecture,” says Feng. “By engaging with this community, we can gain some experience from it and we can also benefit from it. We can see what are the concerns and the challenges faced by the community, so we can get involved.”
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+2 -3
View File
@@ -17,12 +17,11 @@ If you notice that this is out of date, please
If you notice a violation of the Code of Conduct at an event or meeting, in
Slack, or in another communication mechanism, reach out to
the [Kubernetes Code of Conduct Committee](https://github.com/kubernetes/community/tree/master/committee-code-of-conduct) <conduct@kubernetes.io>.
the <a href="https://git.k8s.io/community/committee-code-of-conduct">Kubernetes Code of Conduct Committee</a>.
You can reach us by email at <a href="mailto:conduct@kubernetes.io">conduct@kubernetes.io</a>.
Your anonymity will be protected.
<div class="cncf_coc_container">
{{< include "/static/cncf-code-of-conduct.md" >}}
</div>
</div>
@@ -255,6 +255,8 @@ The following cloud providers have implemented CCMs:
* [Azure](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/azure)
* [GCE](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/gce)
* [AWS](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/aws)
* [BaiduCloud](https://github.com/baidu/cloud-provider-baiducloud)
* [Linode](https://github.com/linode/linode-cloud-controller-manager)
## Cluster Administration
@@ -77,7 +77,7 @@ To verify this connection, use the `--kubelet-certificate-authority` flag to
provide the apiserver with a root certificate bundle to use to verify the
kubelet's serving certificate.
If that is not possible, use [SSH tunneling](/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)
If that is not possible, use [SSH tunneling](/docs/concepts/architecture/master-node-communication/#ssh-tunnels)
between the apiserver and kubelet if required to avoid connecting over an
untrusted or public network.
@@ -95,4 +95,15 @@ connection will be encrypted, it will not provide any guarantees of integrity.
These connections **are not currently safe** to run over untrusted and/or
public networks.
### SSH Tunnels
Kubernetes supports SSH tunnels to protect the Master -> Cluster communication
paths. In this configuration, the apiserver initiates an SSH tunnel to each node
in the cluster (connecting to the ssh server listening on port 22) and passes
all traffic destined for a kubelet, node, pod, or service through the tunnel.
This tunnel ensures that the traffic is not exposed outside of the network in
which the nodes are running.
SSH tunnels are currently deprecated so you shouldn't opt to use them unless you know what you are doing. A replacement for this communication channel is being designed.
{{% /capture %}}
+3 -22
View File
@@ -74,7 +74,7 @@ the `Terminating` or `Unknown` state. In cases where Kubernetes cannot deduce fr
permanently left a cluster, the cluster administrator may need to delete the node object by hand. Deleting the node object from
Kubernetes causes all the Pod objects running on the node to be deleted from the apiserver, and frees up their names.
In version 1.12, `TaintNodesByCondition` feature is promoted to betaso node lifecycle controller automatically creates
In version 1.12, `TaintNodesByCondition` feature is promoted to beta, so node lifecycle controller automatically creates
[taints](/docs/concepts/configuration/taint-and-toleration/) that represent conditions.
Similarly the scheduler ignores conditions when considering a Node; instead
it looks at the Node's taints and a Pod's tolerations.
@@ -272,27 +272,8 @@ The Kubernetes scheduler ensures that there are enough resources for all the pod
checks that the sum of the requests of containers on the node is no greater than the node capacity. It
includes all containers started by the kubelet, but not containers started directly by the [container runtime](/docs/concepts/overview/components/#node-components) nor any process running outside of the containers.
If you want to explicitly reserve resources for non-pod processes, you can create a placeholder
pod. Use the following template:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-reserver
spec:
containers:
- name: sleep-forever
image: k8s.gcr.io/pause:0.8.0
resources:
requests:
cpu: 100m
memory: 100Mi
```
Set the `cpu` and `memory` values to the amount of resources you want to reserve.
Place the file in the manifest directory (`--config=DIR` flag of kubelet). Do this
on each kubelet where you want to reserve resources.
If you want to explicitly reserve resources for non-Pod processes, follow this tutorial to
[reserve resources for system daemons](/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved).
## API Object
@@ -26,10 +26,11 @@ Add-ons in each section are sorted alphabetically - the ordering does not imply
* [Cilium](https://github.com/cilium/cilium) is a L3 network and network policy plugin that can enforce HTTP/API/L7 policies transparently. Both routing and overlay/encapsulation mode are supported.
* [CNI-Genie](https://github.com/Huawei-PaaS/CNI-Genie) enables Kubernetes to seamlessly connect to a choice of CNI plugins, such as Calico, Canal, Flannel, Romana, or Weave.
* [Contiv](http://contiv.github.io) provides configurable networking (native L3 using BGP, overlay using vxlan, classic L2, and Cisco-SDN/ACI) for various use cases and a rich policy framework. Contiv project is fully [open sourced](http://github.com/contiv). The [installer](http://github.com/contiv/install) provides both kubeadm and non-kubeadm based installation options.
* [Contrail](http://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/), based on [Tungsten Fabric](https://tungsten.io), is a open source, multi-cloud network virtualization and policy management platform. Contrail and Tungsten Fabric are integrated with orchestration systems such as Kubernetes, OpenShift, OpenStack and Mesos, and provide isolation modes for virtual machines, containers/pods and bare metal workloads.
* [Flannel](https://github.com/coreos/flannel/blob/master/Documentation/kubernetes.md) is an overlay network provider that can be used with Kubernetes.
* [Knitter](https://github.com/ZTE/Knitter/) is a network solution supporting multiple networking in Kubernetes.
* [Multus](https://github.com/Intel-Corp/multus-cni) is a Multi plugin for multiple network support in Kubernetes to support all CNI plugins (e.g. Calico, Cilium, Contiv, Flannel), in addition to SRIOV, DPDK, OVS-DPDK and VPP based workloads in Kubernetes.
* [NSX-T](https://docs.vmware.com/en/VMware-NSX-T/2.0/nsxt_20_ncp_kubernetes.pdf) Container Plug-in (NCP) provides integration between VMware NSX-T and container orchestrators such as Kubernetes, as well as integration between NSX-T and container-based CaaS/PaaS platforms such as Pivotal Container Service (PKS) and Openshift.
* [NSX-T](https://docs.vmware.com/en/VMware-NSX-T/2.0/nsxt_20_ncp_kubernetes.pdf) Container Plug-in (NCP) provides integration between VMware NSX-T and container orchestrators such as Kubernetes, as well as integration between NSX-T and container-based CaaS/PaaS platforms such as Pivotal Container Service (PKS) and OpenShift.
* [Nuage](https://github.com/nuagenetworks/nuage-kubernetes/blob/v5.1.1-1/docs/kubernetes-1-installation.rst) is an SDN platform that provides policy-based networking between Kubernetes Pods and non-Kubernetes environments with visibility and security monitoring.
* [Romana](http://romana.io) is a Layer 3 networking solution for pod networks that also supports the [NetworkPolicy API](/docs/concepts/services-networking/network-policies/). Kubeadm add-on installation details available [here](https://github.com/romana/romana/tree/master/containerize).
* [Weave Net](https://www.weave.works/docs/net/latest/kube-addon/) provides networking and network policy, will carry on working on both sides of a network partition, and does not require an external database.
@@ -183,7 +183,7 @@ Finally, add the same parameters into the API server start parameters.
../cfssl gencert -initca ca-csr.json | ../cfssljson -bare ca
1. Create a JSON config file for generating keys and certificates for the API
server as shown below. Be sure to replace the values in angle brackets with
server, for example, `server-csr.json`. Be sure to replace the values in angle brackets with
real values you want to use. The `MASTER_CLUSTER_IP` is the service cluster
IP for the API server as described in previous subsection.
The sample below also assumes that you are using `cluster.local` as the default
@@ -231,8 +231,11 @@ refresh the local list for valid certificates.
On each client, perform the following operations:
```bash
$ sudo cp ca.crt /usr/local/share/ca-certificates/kubernetes.crt
$ sudo update-ca-certificates
sudo cp ca.crt /usr/local/share/ca-certificates/kubernetes.crt
sudo update-ca-certificates
```
```
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....
@@ -251,11 +251,11 @@ file:
monitor for the Neutron load balancer. Valid values are `true` and `false`.
The default is `false`. When `true` is specified then `monitor-delay`,
`monitor-timeout`, and `monitor-max-retries` must also be set.
* `monitor-delay` (Optional): The time, in seconds, between sending probes to
members of the load balancer.
* `monitor-timeout` (Optional): Maximum number of seconds for a monitor to wait
* `monitor-delay` (Optional): The time between sending probes to
members of the load balancer. Ensure that you specify a valid time unit. The valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
* `monitor-timeout` (Optional): Maximum time for a monitor to wait
for a ping reply before it times out. The value must be less than the delay
value.
value. Ensure that you specify a valid time unit. The valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
* `monitor-max-retries` (Optional): Number of permissible ping failures before
changing the load balancer member's status to INACTIVE. Must be a number
between 1 and 10.
@@ -367,14 +367,21 @@ The `--hostname-override` parameter is ignored by the VSphere cloud provider.
## IBM Cloud Kubernetes Service
### Compute nodes
By using the IBM Cloud Kubernetes Service provider, you can create clusters with a mixture of virtual and physical (bare metal) nodes in a single zone or across multiple zones in a region. For more information, see [Planning your cluster and worker node setup](https://console.bluemix.net/docs/containers/cs_clusters_planning.html#plan_clusters).
By using the IBM Cloud Kubernetes Service provider, you can create clusters with a mixture of virtual and physical (bare metal) nodes in a single zone or across multiple zones in a region. For more information, see [Planning your cluster and worker node setup](https://cloud.ibm.com/docs/containers?topic=containers-plan_clusters#plan_clusters).
The name of the Kubernetes Node object is the private IP address of the IBM Cloud Kubernetes Service worker node instance.
### Networking
The IBM Cloud Kubernetes Service provider provides VLANs for quality network performance and network isolation for nodes. You can set up custom firewalls and Calico network policies to add an extra layer of security for your cluster, or connect your cluster to your on-prem data center via VPN. For more information, see [Planning in-cluster and private networking](https://console.bluemix.net/docs/containers/cs_network_cluster.html#planning).
The IBM Cloud Kubernetes Service provider provides VLANs for quality network performance and network isolation for nodes. You can set up custom firewalls and Calico network policies to add an extra layer of security for your cluster, or connect your cluster to your on-prem data center via VPN. For more information, see [Planning in-cluster and private networking](https://cloud.ibm.com/docs/containers?topic=containers-cs_network_cluster#cs_network_cluster).
To expose apps to the public or within the cluster, you can leverage NodePort, LoadBalancer, or Ingress services. You can also customize the Ingress application load balancer with annotations. For more information, see [Planning to expose your apps with external networking](https://console.bluemix.net/docs/containers/cs_network_planning.html#planning).
To expose apps to the public or within the cluster, you can leverage NodePort, LoadBalancer, or Ingress services. You can also customize the Ingress application load balancer with annotations. For more information, see [Planning to expose your apps with external networking](https://cloud.ibm.com/docs/containers?topic=containers-cs_network_planning#cs_network_planning).
### Storage
The IBM Cloud Kubernetes Service provider leverages Kubernetes-native persistent volumes to enable users to mount file, block, and cloud object storage to their apps. You can also use database-as-a-service and third-party add-ons for persistent storage of your data. For more information, see [Planning highly available persistent storage](https://console.bluemix.net/docs/containers/cs_storage_planning.html#storage_planning).
The IBM Cloud Kubernetes Service provider leverages Kubernetes-native persistent volumes to enable users to mount file, block, and cloud object storage to their apps. You can also use database-as-a-service and third-party add-ons for persistent storage of your data. For more information, see [Planning highly available persistent storage](https://cloud.ibm.com/docs/containers?topic=containers-storage_planning#storage_planning).
## Baidu Cloud Container Engine
### Node Name
The Baidu cloud provider uses the private IP address of the node (as determined by the kubelet or overridden with `--hostname-override`) as the name of the Kubernetes Node object.
Note that the Kubernetes Node name must match the Baidu VM private IP.
@@ -6,7 +6,9 @@ weight: 80
{{% capture overview %}}
{{< include "federation-current-state.md" >}}
{{< deprecationfilewarning >}}
{{< include "federation-deprecation-warning-note.md" >}}
{{< /deprecationfilewarning >}}
This page explains why and how to manage multiple Kubernetes clusters using
federation.
@@ -35,14 +35,14 @@ a container that writes some text to standard output once per second.
To run this pod, use the following command:
```shell
$ kubectl create -f https://k8s.io/examples/debug/counter-pod.yaml
kubectl create -f https://k8s.io/examples/debug/counter-pod.yaml
pod/counter created
```
To fetch the logs, use the `kubectl logs` command, as follows:
```shell
$ kubectl logs counter
kubectl logs counter
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
@@ -76,8 +76,7 @@ and the former approach is used in any other environment. In both cases, by
default rotation is configured to take place when log file exceeds 10MB.
As an example, you can find detailed information about how `kube-up.sh` sets
up logging for COS image on GCP in the corresponding [script]
[cosConfigureHelper].
up logging for COS image on GCP in the corresponding [script][cosConfigureHelper].
When you run [`kubectl logs`](/docs/reference/generated/kubectl/kubectl-commands#logs) as in
the basic logging example, the kubelet on the node handles the request and
@@ -89,9 +88,9 @@ only the contents of the latest log file will be available through
`kubectl logs`. E.g. if there's a 10MB file, `logrotate` performs
the rotation and there are two files, one 10MB in size and one empty,
`kubectl logs` will return an empty response.
{{< /note >}}
[cosConfigureHelper]: https://github.com/kubernetes/kubernetes/blob/{{< param "githubbranch" >}}/cluster/gce/gci/configure-helper.sh
{{< /note >}}
### System component logs
@@ -104,7 +103,7 @@ that do not run in a container. For example:
On machines with systemd, the kubelet and container runtime write to journald. If
systemd is not present, they write to `.log` files in the `/var/log` directory.
System components inside containers always write to the `/var/log` directory,
bypassing the default logging mechanism. They use the [glog][glog]
bypassing the default logging mechanism. They use the [klog][klog]
logging library. You can find the conventions for logging severity for those
components in the [development docs on logging](https://git.k8s.io/community/contributors/devel/logging.md).
@@ -113,7 +112,7 @@ directory should be rotated. In Kubernetes clusters brought up by
the `kube-up.sh` script, those logs are configured to be rotated by
the `logrotate` tool daily or once the size exceeds 100MB.
[glog]: https://godoc.org/github.com/golang/glog
[klog]: https://github.com/kubernetes/klog
## Cluster-level logging architectures
@@ -179,7 +178,9 @@ Now when you run this pod, you can access each log stream separately by
running the following commands:
```shell
$ kubectl logs counter count-log-1
kubectl logs counter count-log-1
```
```
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
@@ -187,7 +188,9 @@ $ kubectl logs counter count-log-1
```
```shell
$ kubectl logs counter count-log-2
kubectl logs counter count-log-2
```
```
Mon Jan 1 00:00:00 UTC 2001 INFO 0
Mon Jan 1 00:00:01 UTC 2001 INFO 1
Mon Jan 1 00:00:02 UTC 2001 INFO 2
@@ -26,7 +26,10 @@ Many applications require multiple resources to be created, such as a Deployment
Multiple resources can be created the same way as a single resource:
```shell
$ kubectl create -f https://k8s.io/examples/application/nginx-app.yaml
kubectl create -f https://k8s.io/examples/application/nginx-app.yaml
```
```shell
service/my-nginx-svc created
deployment.apps/my-nginx created
```
@@ -36,13 +39,13 @@ The resources will be created in the order they appear in the file. Therefore, i
`kubectl create` also accepts multiple `-f` arguments:
```shell
$ kubectl create -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
kubectl create -f https://k8s.io/examples/application/nginx/nginx-svc.yaml -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
```
And a directory can be specified rather than or in addition to individual files:
```shell
$ kubectl create -f https://k8s.io/examples/application/nginx/
kubectl create -f https://k8s.io/examples/application/nginx/
```
`kubectl` will read any files with suffixes `.yaml`, `.yml`, or `.json`.
@@ -52,7 +55,10 @@ It is a recommended practice to put resources related to the same microservice o
A URL can also be specified as a configuration source, which is handy for deploying directly from configuration files checked into github:
```shell
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/nginx/nginx-deployment.yaml
kubectl create -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/nginx/nginx-deployment.yaml
```
```shell
deployment.apps/my-nginx created
```
@@ -61,7 +67,10 @@ deployment.apps/my-nginx created
Resource creation isn't the only operation that `kubectl` can perform in bulk. It can also extract resource names from configuration files in order to perform other operations, in particular to delete the same resources you created:
```shell
$ kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
```
```shell
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
```
@@ -69,13 +78,16 @@ service "my-nginx-svc" deleted
In the case of just two resources, it's also easy to specify both on the command line using the resource/name syntax:
```shell
$ kubectl delete deployments/my-nginx services/my-nginx-svc
kubectl delete deployments/my-nginx services/my-nginx-svc
```
For larger numbers of resources, you'll find it easier to specify the selector (label query) specified using `-l` or `--selector`, to filter resources by their labels:
```shell
$ kubectl delete deployment,services -l app=nginx
kubectl delete deployment,services -l app=nginx
```
```shell
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
```
@@ -83,7 +95,10 @@ service "my-nginx-svc" deleted
Because `kubectl` outputs resource names in the same syntax it accepts, it's easy to chain operations using `$()` or `xargs`:
```shell
$ kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
```
```shell
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
```
@@ -108,14 +123,20 @@ project/k8s/development
By default, performing a bulk operation on `project/k8s/development` will stop at the first level of the directory, not processing any subdirectories. If we had tried to create the resources in this directory using the following command, we would have encountered an error:
```shell
$ kubectl create -f project/k8s/development
kubectl create -f project/k8s/development
```
```shell
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
```
Instead, specify the `--recursive` or `-R` flag with the `--filename,-f` flag as such:
```shell
$ kubectl create -f project/k8s/development --recursive
kubectl create -f project/k8s/development --recursive
```
```shell
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
@@ -126,7 +147,10 @@ The `--recursive` flag works with any operation that accepts the `--filename,-f`
The `--recursive` flag also works when multiple `-f` arguments are provided:
```shell
$ kubectl create -f project/k8s/namespaces -f project/k8s/development --recursive
kubectl create -f project/k8s/namespaces -f project/k8s/development --recursive
```
```shell
namespace/development created
namespace/staging created
configmap/my-config created
@@ -169,8 +193,11 @@ and
The labels allow us to slice and dice our resources along any dimension specified by a label:
```shell
$ kubectl create -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
$ kubectl get pods -Lapp -Ltier -Lrole
kubectl create -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
```
```shell
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <none>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <none>
@@ -180,7 +207,12 @@ guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestboo
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <none> <none>
my-nginx-o0ef1 1/1 Running 0 29m nginx <none> <none>
$ kubectl get pods -lapp=guestbook,role=slave
```
```shell
kubectl get pods -lapp=guestbook,role=slave
```
```shell
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
@@ -240,7 +272,10 @@ Sometimes existing pods and other resources need to be relabeled before creating
For example, if you want to label all your nginx pods as frontend tier, simply run:
```shell
$ kubectl label pods -l app=nginx tier=fe
kubectl label pods -l app=nginx tier=fe
```
```shell
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled
@@ -250,7 +285,9 @@ This first filters all pods with the label "app=nginx", and then labels them wit
To see the pods you just labeled, run:
```shell
$ kubectl get pods -l app=nginx -L tier
kubectl get pods -l app=nginx -L tier
```
```shell
NAME READY STATUS RESTARTS AGE TIER
my-nginx-2035384211-j5fhi 1/1 Running 0 23m fe
my-nginx-2035384211-u2c7e 1/1 Running 0 23m fe
@@ -266,8 +303,10 @@ For more information, please see [labels](/docs/concepts/overview/working-with-o
Sometimes you would want to attach annotations to resources. Annotations are arbitrary non-identifying metadata for retrieval by API clients such as tools, libraries, etc. This can be done with `kubectl annotate`. For example:
```shell
$ kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
$ kubectl get pods my-nginx-v4-9gw19 -o yaml
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
```
```shell
apiversion: v1
kind: pod
metadata:
@@ -283,14 +322,18 @@ For more information, please see [annotations](/docs/concepts/overview/working-w
When load on your application grows or shrinks, it's easy to scale with `kubectl`. For instance, to decrease the number of nginx replicas from 3 to 1, do:
```shell
$ kubectl scale deployment/my-nginx --replicas=1
kubectl scale deployment/my-nginx --replicas=1
```
```shell
deployment.extensions/my-nginx scaled
```
Now you only have one pod managed by the deployment.
```shell
$ kubectl get pods -l app=nginx
kubectl get pods -l app=nginx
```
```shell
NAME READY STATUS RESTARTS AGE
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
```
@@ -298,7 +341,9 @@ my-nginx-2035384211-j5fhi 1/1 Running 0 30m
To have the system automatically choose the number of nginx replicas as needed, ranging from 1 to 3, do:
```shell
$ kubectl autoscale deployment/my-nginx --min=1 --max=3
kubectl autoscale deployment/my-nginx --min=1 --max=3
```
```shell
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
```
@@ -320,7 +365,9 @@ Then, you can use [`kubectl apply`](/docs/reference/generated/kubectl/kubectl-co
This command will compare the version of the configuration that you're pushing with the previous version and apply the changes you've made, without overwriting any automated changes to properties you haven't specified.
```shell
$ kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
```
```shell
deployment.apps/my-nginx configured
```
@@ -339,18 +386,20 @@ To use apply, always create resource initially with either `kubectl apply` or `k
Alternatively, you may also update resources with `kubectl edit`:
```shell
$ kubectl edit deployment/my-nginx
kubectl edit deployment/my-nginx
```
This is equivalent to first `get` the resource, edit it in text editor, and then `apply` the resource with the updated version:
```shell
$ kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
$ vi /tmp/nginx.yaml
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# do some edit, and then save the file
$ kubectl apply -f /tmp/nginx.yaml
kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured
$ rm /tmp/nginx.yaml
rm /tmp/nginx.yaml
```
This allows you to do more significant changes more easily. Note that you can specify the editor with your `EDITOR` or `KUBE_EDITOR` environment variables.
@@ -370,7 +419,9 @@ and
In some cases, you may need to update resource fields that cannot be updated once initialized, or you may just want to make a recursive change immediately, such as to fix broken pods created by a Deployment. To change such fields, use `replace --force`, which deletes and re-creates the resource. In this case, you can simply modify your original configuration file:
```shell
$ kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
```
```shell
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
```
@@ -385,14 +436,16 @@ you should read [how to use `kubectl rolling-update`](/docs/tasks/run-applicatio
Let's say you were running version 1.7.9 of nginx:
```shell
$ kubectl run my-nginx --image=nginx:1.7.9 --replicas=3
kubectl run my-nginx --image=nginx:1.7.9 --replicas=3
```
```shell
deployment.apps/my-nginx created
```
To update to version 1.9.1, simply change `.spec.template.spec.containers[0].image` from `nginx:1.7.9` to `nginx:1.9.1`, with the kubectl commands we learned above.
```shell
$ kubectl edit deployment/my-nginx
kubectl edit deployment/my-nginx
```
That's it! The Deployment will declaratively update the deployed nginx application progressively behind the scene. It ensures that only a certain number of old replicas may be down while they are being updated, and only a certain number of new replicas may be created above the desired number of pods. To learn more details about it, visit [Deployment page](/docs/concepts/workloads/controllers/deployment/).
@@ -7,8 +7,9 @@ weight: 50
---
{{% capture overview %}}
Kubernetes approaches networking somewhat differently than Docker does by
default. There are 4 distinct networking problems to solve:
Networking is a central part of Kubernetes, but it can be challenging to
understand exactly how it is expected to work. There are 4 distinct networking
problems to address:
1. Highly-coupled container-to-container communications: this is solved by
[pods](/docs/concepts/workloads/pods/pod/) and `localhost` communications.
@@ -21,80 +22,56 @@ default. There are 4 distinct networking problems to solve:
{{% capture body %}}
Kubernetes assumes that pods can communicate with other pods, regardless of
which host they land on. Every pod gets its own IP address so you do not
need to explicitly create links between pods and you almost never need to deal
with mapping container ports to host ports. This creates a clean,
backwards-compatible model where pods can be treated much like VMs or physical
hosts from the perspectives of port allocation, naming, service discovery, load
balancing, application configuration, and migration.
Kubernetes is all about sharing machines between applications. Typically,
sharing machines requires ensuring that two applications do not try to use the
same ports. Coordinating ports across multiple developers is very difficult to
do at scale and exposes users to cluster-level issues outside of their control.
There are requirements imposed on how you set up your cluster networking to
achieve this.
## Docker model
Before discussing the Kubernetes approach to networking, it is worthwhile to
review the "normal" way that networking works with Docker. By default, Docker
uses host-private networking. It creates a virtual bridge, called `docker0` by
default, and allocates a subnet from one of the private address blocks defined
in [RFC1918](https://tools.ietf.org/html/rfc1918) for that bridge. For each
container that Docker creates, it allocates a virtual Ethernet device (called
`veth`) which is attached to the bridge. The veth is mapped to appear as `eth0`
in the container, using Linux namespaces. The in-container `eth0` interface is
given an IP address from the bridge's address range.
The result is that Docker containers can talk to other containers only if they
are on the same machine (and thus the same virtual bridge). Containers on
different machines can not reach each other - in fact they may end up with the
exact same network ranges and IP addresses.
In order for Docker containers to communicate across nodes, there must
be allocated ports on the machines own IP address, which are then
forwarded or proxied to the containers. This obviously means that
containers must either coordinate which ports they use very carefully
or ports must be allocated dynamically.
## Kubernetes model
Coordinating ports across multiple developers is very difficult to do at
scale and exposes users to cluster-level issues outside of their control.
Dynamic port allocation brings a lot of complications to the system - every
application has to take ports as flags, the API servers have to know how to
insert dynamic port numbers into configuration blocks, services have to know
how to find each other, etc. Rather than deal with this, Kubernetes takes a
different approach.
## The Kubernetes network model
Every `Pod` gets its own IP address. This means you do not need to explicitly
create links between `Pods` and you almost never need to deal with mapping
container ports to host ports. This creates a clean, backwards-compatible
model where `Pods` can be treated much like VMs or physical hosts from the
perspectives of port allocation, naming, service discovery, load balancing,
application configuration, and migration.
Kubernetes imposes the following fundamental requirements on any networking
implementation (barring any intentional network segmentation policies):
* all containers can communicate with all other containers without NAT
* all nodes can communicate with all containers (and vice-versa) without NAT
* the IP that a container sees itself as is the same IP that others see it as
* pods on a node can communicate with all pods on all nodes without NAT
* agents on a node (e.g. system daemons, kubelet) can communicate with all
pods on that node
What this means in practice is that you can not just take two computers
running Docker and expect Kubernetes to work. You must ensure that the
fundamental requirements are met.
Note: For those platforms that support `Pods` running in the host network (e.g.
Linux):
* pods in the host network of a node can communicate with all pods on all
nodes without NAT
This model is not only less complex overall, but it is principally compatible
with the desire for Kubernetes to enable low-friction porting of apps from VMs
to containers. If your job previously ran in a VM, your VM had an IP and could
talk to other VMs in your project. This is the same basic model.
Until now this document has talked about containers. In reality, Kubernetes
applies IP addresses at the `Pod` scope - containers within a `Pod` share their
network namespaces - including their IP address. This means that containers
within a `Pod` can all reach each other's ports on `localhost`. This does imply
that containers within a `Pod` must coordinate port usage, but this is no
different than processes in a VM. This is called the "IP-per-pod" model. This
is implemented, using Docker, as a "pod container" which holds the network namespace
open while "app containers" (the things the user specified) join that namespace
with Docker's `--net=container:<id>` function.
Kubernetes IP addresses exist at the `Pod` scope - containers within a `Pod`
share their network namespaces - including their IP address. This means that
containers within a `Pod` can all reach each other's ports on `localhost`. This
also means that containers within a `Pod` must coordinate port usage, but this
is no different than processes in a VM. This is called the "IP-per-pod" model.
As with Docker, it is possible to request host ports, but this is reduced to a
very niche operation. In this case a port will be allocated on the host `Node`
and traffic will be forwarded to the `Pod`. The `Pod` itself is blind to the
existence or non-existence of host ports.
How this is implemented is a detail of the particular container runtime in use.
It is possible to request ports on the `Node` itself which forward to your `Pod`
(called host ports), but this is a very niche operation. How that forwarding is
implemented is also a detail of the container runtime. The `Pod` itself is
blind to the existence or non-existence of host ports.
## How to implement the Kubernetes networking model
@@ -125,7 +102,7 @@ Details on how the AOS system works can be accessed here: http://www.apstra.com/
[Big Cloud Fabric](https://www.bigswitch.com/container-network-automation) is a cloud native networking architecture, designed to run Kubernetes in private cloud/on-premises environments. Using unified physical & virtual SDN, Big Cloud Fabric tackles inherent container networking problems such as load balancing, visibility, troubleshooting, security policies & container traffic monitoring.
With the help of the Big Cloud Fabric's virtual pod multi-tenant architecture, container orchestration systems such as Kubernetes, RedHat Openshift, Mesosphere DC/OS & Docker Swarm will be natively integrated along side with VM orchestration systems such as VMware, OpenStack & Nutanix. Customers will be able to securely inter-connect any number of these clusters and enable inter-tenant communication between them if needed.
With the help of the Big Cloud Fabric's virtual pod multi-tenant architecture, container orchestration systems such as Kubernetes, RedHat OpenShift, Mesosphere DC/OS & Docker Swarm will be natively integrated along side with VM orchestration systems such as VMware, OpenStack & Nutanix. Customers will be able to securely inter-connect any number of these clusters and enable inter-tenant communication between them if needed.
BCF was recognized by Gartner as a visionary in the latest [Magic Quadrant](http://go.bigswitch.com/17GatedDocuments-MagicQuadrantforDataCenterNetworking_Reg.html). One of the BCF Kubernetes on-premises deployments (which includes Kubernetes, DC/OS & VMware running on multiple DCs across different geographic regions) is also referenced [here](https://portworx.com/architects-corner-kubernetes-satya-komala-nio/).
@@ -143,13 +120,29 @@ addressing.
CNI-Genie also supports [assigning multiple IP addresses to a pod](https://github.com/Huawei-PaaS/CNI-Genie/blob/master/docs/multiple-ips/README.md#feature-2-extension-cni-genie-multiple-ip-addresses-per-pod), each from a different CNI plugin.
### cni-ipvlan-vpc-k8s
[cni-ipvlan-vpc-k8s](https://github.com/lyft/cni-ipvlan-vpc-k8s) contains a set
of CNI and IPAM plugins to provide a simple, host-local, low latency, high
throughput, and compliant networking stack for Kubernetes within Amazon Virtual
Private Cloud (VPC) environments by making use of Amazon Elastic Network
Interfaces (ENI) and binding AWS-managed IPs into Pods using the Linux kernel's
IPvlan driver in L2 mode.
The plugins are designed to be straightforward to configure and deploy within a
VPC. Kubelets boot and then self-configure and scale their IP usage as needed
without requiring the often recommended complexities of administering overlay
networks, BGP, disabling source/destination checks, or adjusting VPC route
tables to provide per-instance subnets to each host (which is limited to 50-100
entries per VPC). In short, cni-ipvlan-vpc-k8s significantly reduces the
network complexity required to deploy Kubernetes at scale within AWS.
### 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.
### Contrail
### Contrail / Tungsten Fabric
[Contrail](http://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/), based on [OpenContrail](http://www.opencontrail.org), is a truly open, multi-cloud network virtualization and policy management platform. Contrail / OpenContrail is integrated with various orchestration systems such as Kubernetes, OpenShift, OpenStack and Mesos, and provides different isolation modes for virtual machines, containers/pods and bare metal workloads.
[Contrail](http://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/), based on [Tungsten Fabric](https://tungsten.io), is a truly open, multi-cloud network virtualization and policy management platform. Contrail and Tungsten Fabric are integrated with various orchestration systems such as Kubernetes, OpenShift, OpenStack and Mesos, and provide different isolation modes for virtual machines, containers/pods and bare metal workloads.
### DANM
@@ -246,7 +239,7 @@ Multus supports all [reference plugins](https://github.com/containernetworking/p
[VMware NSX-T](https://docs.vmware.com/en/VMware-NSX-T/index.html) is a network virtualization and security platform. NSX-T can provide network virtualization for a multi-cloud and multi-hypervisor environment and is focused on emerging application frameworks and architectures that have heterogeneous endpoints and technology stacks. In addition to vSphere hypervisors, these environments include other hypervisors such as KVM, containers, and bare metal.
[NSX-T Container Plug-in (NCP)](https://docs.vmware.com/en/VMware-NSX-T/2.0/nsxt_20_ncp_kubernetes.pdf) provides integration between NSX-T and container orchestrators such as Kubernetes, as well as integration between NSX-T and container-based CaaS/PaaS platforms such as Pivotal Container Service (PKS) and Openshift.
[NSX-T Container Plug-in (NCP)](https://docs.vmware.com/en/VMware-NSX-T/2.0/nsxt_20_ncp_kubernetes.pdf) provides integration between NSX-T and container orchestrators such as Kubernetes, as well as integration between NSX-T and container-based CaaS/PaaS platforms such as Pivotal Container Service (PKS) and OpenShift.
### Nuage Networks VCS (Virtualized Cloud Services)
@@ -272,9 +265,9 @@ at [ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes).
[Project Calico](http://docs.projectcalico.org/) is an open source container networking provider and network policy engine.
Calico provides a highly scalable networking and network policy solution for connecting Kubernetes pods based on the same IP networking principles as the internet. Calico can be deployed without encapsulation or overlays to provide high-performance, high-scale data center networking. Calico also provides fine-grained, intent based network security policy for Kubernetes pods via its distributed firewall.
Calico provides a highly scalable networking and network policy solution for connecting Kubernetes pods based on the same IP networking principles as the internet, for both Linux (open source) and Windows (proprietary - available from [Tigera](https://www.tigera.io/essentials/)). Calico can be deployed without encapsulation or overlays to provide high-performance, high-scale data center networking. Calico also provides fine-grained, intent based network security policy for Kubernetes pods via its distributed firewall.
Calico can also be run in policy enforcement mode in conjunction with other networking solutions such as Flannel, aka [canal](https://github.com/tigera/canal), or native GCE networking.
Calico can also be run in policy enforcement mode in conjunction with other networking solutions such as Flannel, aka [canal](https://github.com/tigera/canal), or native GCE, AWS or Azure networking.
### Romana
@@ -12,7 +12,7 @@ weight: 30
{{% capture overview %}}
You can constrain a [pod](/docs/concepts/workloads/pods/pod/) to only be able to run on particular [nodes](/docs/concepts/architecture/nodes/) or to prefer to
run on particular nodes. There are several ways to do this, and they all use
run on particular nodes. There are several ways to do this, and the recommended approaches all use
[label selectors](/docs/concepts/overview/working-with-objects/labels/) to make the selection.
Generally such constraints are unnecessary, as the scheduler will automatically do a reasonable placement
(e.g. spread your pods across nodes, not place the pod on a node with insufficient free resources, etc.)
@@ -29,7 +29,7 @@ repo here](https://github.com/kubernetes/website/tree/{{< param "docsbranch" >}}
## nodeSelector
`nodeSelector` is the simplest form of constraint.
`nodeSelector` is the simplest recommended form of node selection constraint.
`nodeSelector` is a field of PodSpec. It specifies a map of key-value pairs. For the pod to be eligible
to run on a node, the node must have each of the indicated key-value pairs as labels (it can have
additional labels as well). The most common usage is one key-value pair.
@@ -46,7 +46,7 @@ Run `kubectl get nodes` to get the names of your cluster's nodes. Pick out the o
If this fails with an "invalid command" error, you're likely using an older version of kubectl that doesn't have the `label` command. In that case, see the [previous version](https://github.com/kubernetes/kubernetes/blob/a053dbc313572ed60d89dae9821ecab8bfd676dc/examples/node-selection/README.md) of this guide for instructions on how to manually set labels on a node.
You can verify that it worked by re-running `kubectl get nodes --show-labels` and checking that the node now has a label.
You can verify that it worked by re-running `kubectl get nodes --show-labels` and checking that the node now has a label. You can also use `kubectl describe node "nodename"` to see the full list of labels of the given node.
### Step Two: Add a nodeSelector field to your pod configuration
@@ -362,6 +362,41 @@ For more information on inter-pod affinity/anti-affinity, see the
You may want to check [Taints](/docs/concepts/configuration/taint-and-toleration/)
as well, which allow a *node* to *repel* a set of pods.
## nodeName
`nodeName` is the simplest form of node selection constraint, but due
to its limitations it is typically not used. `nodeName` is a field of
PodSpec. If it is non-empty, the scheduler ignores the pod and the
kubelet running on the named node tries to run the pod. Thus, if
`nodeName` is provided in the PodSpec, it takes precedence over the
above methods for node selection.
Some of the limitations of using `nodeName` to select nodes are:
- If the named node does not exist, the pod will not be run, and in
some cases may be automatically deleted.
- If the named node does not have the resources to accommodate the
pod, the pod will fail and its reason will indicate why,
e.g. OutOfmemory or OutOfcpu.
- Node names in cloud environments are not always predictable or
stable.
Here is an example of a pod config file using the `nodeName` field:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
```
The above pod will run on the node kube-01.
{{% /capture %}}
{{% capture whatsnext %}}
@@ -189,7 +189,9 @@ unscheduled until a place can be found. An event is produced each time the
scheduler fails to find a place for the Pod, like this:
```shell
$ kubectl describe pod frontend | grep -A 3 Events
kubectl describe pod frontend | grep -A 3 Events
```
```
Events:
FirstSeen LastSeen Count From Subobject PathReason Message
36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others
@@ -210,7 +212,9 @@ You can check node capacities and amounts allocated with the
`kubectl describe nodes` command. For example:
```shell
$ kubectl describe nodes e2e-test-minion-group-4lw4
kubectl describe nodes e2e-test-minion-group-4lw4
```
```
Name: e2e-test-minion-group-4lw4
[ ... lines removed for clarity ...]
Capacity:
@@ -260,7 +264,9 @@ whether a Container is being killed because it is hitting a resource limit, call
`kubectl describe pod` on the Pod of interest:
```shell
[12:54:41] $ kubectl describe pod simmemleak-hra99
kubectl describe pod simmemleak-hra99
```
```
Name: simmemleak-hra99
Namespace: default
Image(s): saadali/simmemleak
@@ -304,7 +310,9 @@ You can call `kubectl get pod` with the `-o go-template=...` option to fetch the
of previously terminated Containers:
```shell
[13:59:01] $ kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99
kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99
```
```
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]]
```
@@ -103,7 +103,7 @@ Here are the rules that `kubectl` uses when it merges kubeconfig files:
1. Determine the context to use based on the first hit in this chain:
1. Use the `--context` command-line flag if it exits.
1. Use the `--context` command-line flag if it exists.
1. Use the `current-context` from the merged kubeconfig files.
An empty context is allowed at this point.
@@ -202,7 +202,7 @@ Node is found that satisfies all the specified requirements of the Pod,
preemption logic is triggered for the pending Pod. Let's call the pending Pod P.
Preemption logic tries to find a Node where removal of one or more Pods with
lower priority than P would enable P to be scheduled on that Node. If such a
Node is found, one or more lower priority Pods get deleted from the Node. After
Node is found, one or more lower priority Pods get evicted from the Node. After
the Pods are gone, P can be scheduled on the Node.
### User exposed information
@@ -322,7 +322,7 @@ When a Pod is preempted, there will be events recorded for the preempted Pod.
Preemption should happen only when a cluster does not have enough resources for
a Pod. In such cases, preemption happens only when the priority of the pending
Pod (preemptor) is higher than the victim Pods. Preemption must not happen when
there is no pending Pod, or when the pending Pods have equal or higher priority
there is no pending Pod, or when the pending Pods have equal or lower priority
than the victims. If preemption happens in such scenarios, please file an issue.
#### Pods are preempted, but the preemptor is not scheduled
@@ -364,11 +364,11 @@ Pod priority and
[QoS](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/resource-qos.md)
are two orthogonal features with few interactions and no default restrictions on
setting the priority of a Pod based on its QoS classes. The scheduler's
preemption logic does consider QoS when choosing preemption targets. Preemption
considers Pod priority and attempts to choose a set of targets with the lowest
priority. Higher-priority Pods are considered for preemption only if the removal
of the lowest priority Pods is not sufficient to allow the scheduler to schedule
the preemptor Pod, or if the lowest priority Pods are protected by
preemption logic does not consider QoS when choosing preemption targets.
Preemption considers Pod priority and attempts to choose a set of targets with
the lowest priority. Higher-priority Pods are considered for preemption only if
the removal of the lowest priority Pods is not sufficient to allow the scheduler
to schedule the preemptor Pod, or if the lowest priority Pods are protected by
`PodDisruptionBudget`.
The only component that considers both QoS and Pod priority is
+106 -55
View File
@@ -13,10 +13,10 @@ weight: 50
{{% capture overview %}}
Objects of type `secret` are intended to hold sensitive information, such as
passwords, OAuth tokens, and ssh keys. Putting this information in a `secret`
is safer and more flexible than putting it verbatim in a `pod` definition or in
a docker image. See [Secrets design document](https://git.k8s.io/community/contributors/design-proposals/auth/secrets.md) for more information.
Kubernetes `secret` objects let you store and manage sensitive information, such
as passwords, OAuth tokens, and ssh keys. Putting this information in a `secret`
is safer and more flexible than putting it verbatim in a
{{< glossary_tooltip term_id="pod" >}} definition or in a {{< glossary_tooltip text="container image" term_id="image" >}}. See [Secrets design document](https://git.k8s.io/community/contributors/design-proposals/auth/secrets.md) for more information.
{{% /capture %}}
@@ -32,7 +32,8 @@ more control over how it is used, and reduces the risk of accidental exposure.
Users can create secrets, and the system also creates some secrets.
To use a secret, a pod needs to reference the secret.
A secret can be used with a pod in two ways: as files in a [volume](/docs/concepts/storage/volumes/) mounted on one or more of
A secret can be used with a pod in two ways: as files in a
{{< glossary_tooltip text="volume" term_id="volume" >}} mounted on one or more of
its containers, or used by kubelet when pulling images for the pod.
### Built-in Secrets
@@ -60,8 +61,8 @@ username and password that the pods should use is in the files
```shell
# Create files needed for rest of example.
$ echo -n 'admin' > ./username.txt
$ echo -n '1f2d1e2e67df' > ./password.txt
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
```
The `kubectl create secret` command
@@ -69,18 +70,25 @@ packages these files into a Secret and creates
the object on the Apiserver.
```shell
$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
```
```
secret "db-user-pass" created
```
You can check that the secret was created like this:
```shell
$ kubectl get secrets
kubectl get secrets
```
```
NAME TYPE DATA AGE
db-user-pass Opaque 2 51s
$ kubectl describe secrets/db-user-pass
```
```shell
kubectl describe secrets/db-user-pass
```
```
Name: db-user-pass
Namespace: default
Labels: <none>
@@ -94,11 +102,14 @@ password.txt: 12 bytes
username.txt: 5 bytes
```
Note that neither `get` nor `describe` shows the contents of the file by default.
This is to protect the secret from being exposed accidentally to someone looking
{{< note >}}
`kubectl get` and `kubectl describe` avoid showing the contents of a secret by
default.
This is to protect the secret from being exposed accidentally to an onlooker,
or from being stored in a terminal log.
{{< /note >}}
See [decoding a secret](#decoding-a-secret) for how to see the contents.
See [decoding a secret](#decoding-a-secret) for how to see the contents of a secret.
#### Creating a Secret Manually
@@ -135,7 +146,9 @@ data:
Now create the Secret using [`kubectl create`](/docs/reference/generated/kubectl/kubectl-commands#create):
```shell
$ kubectl create -f ./secret.yaml
kubectl create -f ./secret.yaml
```
```
secret "mysecret" created
```
@@ -246,7 +259,9 @@ the option `-w 0` to `base64` commands or the pipeline `base64 | tr -d '\n'` if
Secrets can be retrieved via the `kubectl get secret` command. For example, to retrieve the secret created in the previous section:
```shell
$ kubectl get secret mysecret -o yaml
kubectl get secret mysecret -o yaml
```
```
apiVersion: v1
data:
username: YWRtaW4=
@@ -265,14 +280,17 @@ type: Opaque
Decode the password field:
```shell
$ echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
```
```
1f2d1e2e67df
```
### Using Secrets
Secrets can be mounted as data volumes or be exposed as environment variables to
be used by a container in a pod. They can also be used by other parts of the
Secrets can be mounted as data volumes or be exposed as
{{< glossary_tooltip text="environment variables" term_id="container-env-variables" >}}
to be used by a container in a pod. They can also be used by other parts of the
system, without being directly exposed to the pod. For example, they can hold
credentials that other parts of the system should use to interact with external
systems on your behalf.
@@ -424,12 +442,22 @@ This is the result of commands
executed inside the container from the example above:
```shell
$ ls /etc/foo/
ls /etc/foo/
```
```
username
password
$ cat /etc/foo/username
```
```shell
cat /etc/foo/username
```
```
admin
$ cat /etc/foo/password
```
```shell
cat /etc/foo/password
```
```
1f2d1e2e67df
```
@@ -458,7 +486,8 @@ Secret updates.
#### Using Secrets as Environment Variables
To use a secret in an environment variable in a pod:
To use a secret in an {{< glossary_tooltip text="environment variable" term_id="container-env-variables" >}}
in a pod:
1. Create a secret or use an existing one. Multiple pods can reference the same secret.
1. Modify your Pod definition in each container that you wish to consume the value of a secret key to add an environment variable for each secret key you wish to consume. The environment variable that consumes the secret key should populate the secret's name and key in `env[].valueFrom.secretKeyRef`.
@@ -496,9 +525,15 @@ normal environment variables containing the base-64 decoded values of the secret
This is the result of commands executed inside the container from the example above:
```shell
$ echo $SECRET_USERNAME
echo $SECRET_USERNAME
```
```
admin
$ echo $SECRET_PASSWORD
```
```shell
echo $SECRET_PASSWORD
```
```
1f2d1e2e67df
```
@@ -534,10 +569,10 @@ Secret volume sources are validated to ensure that the specified object
reference actually points to an object of type `Secret`. Therefore, a secret
needs to be created before any pods that depend on it.
Secret API objects reside in a namespace. They can only be referenced by pods
in that same namespace.
Secret API objects reside in a {{< glossary_tooltip text="namespace" term_id="namespace" >}}.
They can only be referenced by pods in that same namespace.
Individual secrets are limited to 1MB in size. This is to discourage creation
Individual secrets are limited to 1MiB in size. This is to discourage creation
of very large secrets which would exhaust apiserver and kubelet memory.
However, creation of many smaller secrets could also exhaust memory. More
comprehensive limits on memory usage due to secrets is a planned feature.
@@ -549,8 +584,8 @@ controller. It does not include pods created via the kubelets
not common ways to create pods.)
Secrets must be created before they are consumed in pods as environment
variables unless they are marked as optional. References to Secrets that do not exist will prevent
the pod from starting.
variables unless they are marked as optional. References to Secrets that do
not exist will prevent the pod from starting.
References via `secretKeyRef` to keys that do not exist in a named Secret
will prevent the pod from starting.
@@ -563,7 +598,9 @@ invalid keys that were skipped. The example shows a pod which refers to the
default/mysecret that contains 2 invalid keys, 1badkey and 2alsobad.
```shell
$ kubectl get events
kubectl get events
```
```
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names.
```
@@ -586,7 +623,10 @@ start until all the pod's volumes are mounted.
Create a secret containing some ssh keys:
```shell
$ kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa
```
```
--from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
```
{{< caution >}}
@@ -636,9 +676,18 @@ credentials.
Make the secrets:
```shell
$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
kubectl create secret generic prod-db-secret --from-literal=username=produser
--from-literal=password=Y4nys7f11
```
```
secret "prod-db-secret" created
$ kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
```
```shell
kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
```
```
secret "test-db-secret" created
```
{{< note >}}
@@ -821,6 +870,7 @@ be available in future releases of Kubernetes.
## Security Properties
### Protections
Because `secret` objects can be created independently of the `pods` that use
@@ -829,51 +879,52 @@ creating, viewing, and editing pods. The system can also take additional
precautions with `secret` objects, such as avoiding writing them to disk where
possible.
A secret is only sent to a node if a pod on that node requires it. It is not
written to disk. It is stored in a tmpfs. It is deleted once the pod that
depends on it is deleted.
On most Kubernetes-project-maintained distributions, communication between user
to the apiserver, and from apiserver to the kubelets, is protected by SSL/TLS.
Secrets are protected when transmitted over these channels.
Secret data on nodes is stored in tmpfs volumes and thus does not come to rest
on the node.
A secret is only sent to a node if a pod on that node requires it.
Kubelet stores the secret into a `tmpfs` so that the secret is not written
to disk storage. Once the Pod that depends on the secret is deleted, kubelet
will delete its local copy of the secret data as well.
There may be secrets for several pods on the same node. However, only the
secrets that a pod requests are potentially visible within its containers.
Therefore, one Pod does not have access to the secrets of another pod.
Therefore, one Pod does not have access to the secrets of another Pod.
There may be several containers in a pod. However, each container in a pod has
to request the secret volume in its `volumeMounts` for it to be visible within
the container. This can be used to construct useful [security partitions at the
Pod level](#use-case-secret-visible-to-one-container-in-a-pod).
On most Kubernetes-project-maintained distributions, communication between user
to the apiserver, and from apiserver to the kubelets, is protected by SSL/TLS.
Secrets are protected when transmitted over these channels.
{{< feature-state for_k8s_version="v1.13" state="beta" >}}
You can enable [encryption at rest](/docs/tasks/administer-cluster/encrypt-data/)
for secret data, so that the secrets are not stored in the clear into {{< glossary_tooltip term_id="etcd" >}}.
### Risks
- In the API server secret data is stored as plaintext in etcd; therefore:
- In the API server secret data is stored in {{< glossary_tooltip term_id="etcd" >}};
therefore:
- Administrators should enable encryption at rest for cluster data (requires v1.13 or later)
- Administrators should limit access to etcd to admin users
- Secret data in the API server is at rest on the disk that etcd uses; admins may want to wipe/shred disks
used by etcd when no longer in use
- Administrators may want to wipe/shred disks used by etcd when no longer in use
- If running etcd in a cluster, administrators should make sure to use SSL/TLS
for etcd peer-to-peer communication.
- If you configure the secret through a manifest (JSON or YAML) file which has
the secret data encoded as base64, sharing this file or checking it in to a
source repository means the secret is compromised. Base64 encoding is not an
source repository means the secret is compromised. Base64 encoding is _not_ an
encryption method and is considered the same as plain text.
- Applications still need to protect the value of secret after reading it from the volume,
such as not accidentally logging it or transmitting it to an untrusted party.
- A user who can create a pod that uses a secret can also see the value of that secret. Even
if apiserver policy does not allow that user to read the secret object, the user could
run a pod which exposes the secret.
- If multiple replicas of etcd are run, then the secrets will be shared between them.
By default, etcd does not secure peer-to-peer communication with SSL/TLS, though this can be configured.
- Currently, anyone with root on any node can read any secret from the apiserver,
- Currently, anyone with root on any node can read _any_ secret from the apiserver,
by impersonating the kubelet. It is a planned feature to only send secrets to
nodes that actually require them, to restrict the impact of a root exploit on a
single node.
{{< note >}}
As of 1.7 [encryption of secret data at rest is supported](/docs/tasks/administer-cluster/encrypt-data/).
{{< /note >}}
{{% capture whatsnext %}}
@@ -191,7 +191,7 @@ on the special hardware nodes. This will make sure that these special hardware
nodes are dedicated for pods requesting such hardware and you don't have to
manually add tolerations to your pods.
* **Taint based Evictions (alpha feature)**: A per-pod-configurable eviction behavior
* **Taint based Evictions (beta feature)**: A per-pod-configurable eviction behavior
when there are node problems, which is described in the next section.
## Taint based Evictions
@@ -279,7 +279,7 @@ which matches the behavior when this feature is disabled.
In version 1.12, `TaintNodesByCondition` feature is promoted to beta, so node lifecycle controller automatically creates taints corresponding to
Node conditions.
Similarly the scheduler does not check Node conditions; instead the scheduler checks taints. This assures that Node conditions don't affect what's scheduled onto the Node. The user can choose to ignore some of the Node's problems (represented as Node conditions) by adding appropriate Pod tolerations.
Note that `TaintNodesByCondition` only taints nodes with `NoSchedule` effect. `NoExecute` effect is controlled by `TaintBasedEviction` which is an alpha feature and disabled by default.
Note that `TaintNodesByCondition` only taints nodes with `NoSchedule` effect. `NoExecute` effect is controlled by `TaintBasedEviction` which is a beta feature and enabled by default since version 1.13.
Starting in Kubernetes 1.8, the DaemonSet controller automatically adds the
following `NoSchedule` tolerations to all daemons, to prevent DaemonSets from
@@ -36,7 +36,7 @@ No parameters are passed to the handler.
`PreStop`
This hook is called immediately before a container is terminated.
This hook is called immediately before a container is terminated due to an API request or management event such as liveness probe failure, preemption, resource contention and others. A call to the preStop hook fails if the container is already in terminated or completed state.
It is blocking, meaning it is synchronous,
so it must complete before the call to delete the container can be sent.
No parameters are passed to the handler.
@@ -99,17 +99,17 @@ Here is some example output of events from running this command:
```
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
```
{{% /capture %}}
+19 -36
View File
@@ -149,9 +149,9 @@ Once you have those variables filled in you can
### Using IBM Cloud Container Registry
IBM Cloud Container Registry provides a multi-tenant private image registry that you can use to safely store and share your Docker images. By default, images in your private registry are scanned by the integrated Vulnerability Advisor to detect security issues and potential vulnerabilities. Users in your IBM Cloud account can access your images, or you can create a token to grant access to registry namespaces.
To install the IBM Cloud Container Registry CLI plug-in and create a namespace for your images, see [Getting started with IBM Cloud Container Registry](https://console.bluemix.net/docs/services/Registry/index.html#index).
To install the IBM Cloud Container Registry CLI plug-in and create a namespace for your images, see [Getting started with IBM Cloud Container Registry](https://cloud.ibm.com/docs/services/Registry?topic=registry-index#index).
You can use the IBM Cloud Container Registry to deploy containers from [IBM Cloud public images](https://console.bluemix.net/docs/services/RegistryImages/index.html#ibm_images) and your private images into the `default` namespace of your IBM Cloud Kubernetes Service cluster. To deploy a container into other namespaces, or to use an image from a different IBM Cloud Container Registry region or IBM Cloud account, create a Kubernetes `imagePullSecret`. For more information, see [Building containers from images](https://console.bluemix.net/docs/containers/cs_images.html#images).
You can use the IBM Cloud Container Registry to deploy containers from [IBM Cloud public images](https://cloud.ibm.com/docs/services/Registry?topic=registry-public_images#public_images) and your private images into the `default` namespace of your IBM Cloud Kubernetes Service cluster. To deploy a container into other namespaces, or to use an image from a different IBM Cloud Container Registry region or IBM Cloud account, create a Kubernetes `imagePullSecret`. For more information, see [Building containers from images](https://cloud.ibm.com/docs/containers?topic=containers-images#images).
### Configuring Nodes to Authenticate to a Private Registry
@@ -170,6 +170,11 @@ will not work reliably on GCE, and any other cloud provider that does automatic
node replacement.
{{< /note >}}
{{< note >}}
Kubernetes as of now only supports the `auths` and `HttpHeaders` section of docker config. This means credential helpers (`credHelpers` or `credsStore`) are not supported.
{{< /note >}}
Docker stores keys for private registries in the `$HOME/.dockercfg` or `$HOME/.docker/config.json` file. If you put the same file
in the search paths list below, kubelet uses it as the credential provider when pulling images.
@@ -278,42 +283,17 @@ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGIS
secret/myregistrykey created.
```
If you need access to multiple registries, you can create one secret for each registry.
Kubelet will merge any `imagePullSecrets` into a single virtual `.docker/config.json`
when pulling images for your Pods.
If you already have a Docker credentials file then, rather than using the above
command, you can import the credentials file as a Kubernetes secret.
[Create a Secret based on existing Docker credentials](/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials) explains how to set this up.
This is particularly useful if you are using multiple private container
registries, as `kubectl create secret docker-registry` creates a Secret that will
only work with a single private registry.
{{< note >}}
Pods can only reference image pull secrets in their own namespace,
so this process needs to be done one time per namespace.
##### Bypassing kubectl create secrets
If for some reason you need multiple items in a single `.docker/config.json` or need
control not given by the above command, then you can [create a secret using
json or yaml](/docs/user-guide/secrets/#creating-a-secret-manually).
Be sure to:
- set the name of the data item to `.dockerconfigjson`
- base64 encode the docker file and paste that string, unbroken
as the value for field `data[".dockerconfigjson"]`
- set `type` to `kubernetes.io/dockerconfigjson`
Example:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
```
If you get the error message `error: no objects passed to create`, it may mean the base64 encoded string is invalid.
If you get an error message like `Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...`, it means
the data was successfully un-base64 encoded, but could not be parsed as a `.docker/config.json` file.
{{< /note >}}
#### Referring to an imagePullSecrets on a Pod
@@ -355,7 +335,7 @@ common use cases and suggested solutions.
1. Cluster running some proprietary images which should be hidden to those outside the company, but
visible to all cluster users.
- Use a hosted private [Docker registry](https://docs.docker.com/registry/).
- It may be hosted on the [Docker Hub](https://hub.docker.com/account/signup/), or elsewhere.
- It may be hosted on the [Docker Hub](https://hub.docker.com/signup), or elsewhere.
- Manually configure .docker/config.json on each node as described above.
- Or, run an internal private registry behind your firewall with open read access.
- No Kubernetes configuration is required.
@@ -372,3 +352,6 @@ common use cases and suggested solutions.
- The tenant adds that secret to imagePullSecrets of each namespace.
{{% /capture %}}
If you need access to multiple registries, you can create one secret for each registry.
Kubelet will merge any `imagePullSecrets` into a single virtual `.docker/config.json`
@@ -9,40 +9,48 @@ weight: 20
{{% capture overview %}}
This page explains *custom resources*, which are extensions of the Kubernetes
API, including when to add a custom resource to your Kubernetes cluster and when
to use a standalone service. It describes the two methods for adding custom
resources and how to choose between them.
*Custom resources* are extensions of the Kubernetes API. This page discusses when to add a custom
resource to your Kubernetes cluster and when to use a standalone service. It describes the two
methods for adding custom resources and how to choose between them.
{{% /capture %}}
{{% capture body %}}
## Custom resources
A *resource* is an endpoint in the [Kubernetes API](/docs/reference/using-api/api-overview/) that stores a collection of [API objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/) of a certain kind. For example, the built-in *pods* resource contains a collection of Pod objects.
A *resource* is an endpoint in the [Kubernetes API](/docs/reference/using-api/api-overview/) that stores a collection of
[API objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/) of a certain kind. For example, the built-in *pods* resource contains a collection of Pod objects.
A *custom resource* is an extension of the Kubernetes API that is not necessarily available on every
Kubernetes cluster.
In other words, it represents a customization of a particular Kubernetes installation.
A *custom resource* is an extension of the Kubernetes API that is not necessarily available in a default
Kubernetes installation. It represents a customization of a particular Kubernetes installation. However,
many core Kubernetes functions are now built using custom resources, making Kubernetes more modular.
Custom resources can appear and disappear in a running cluster through dynamic registration,
and cluster admins can update custom resources independently of the cluster itself.
Once a custom resource is installed, users can create and access its objects with
[kubectl](/docs/user-guide/kubectl-overview/), just as they do for built-in resources like *pods*.
Once a custom resource is installed, users can create and access its objects using
[kubectl](/docs/user-guide/kubectl-overview/), just as they do for built-in resources like
*Pods*.
### Custom controllers
## Custom controllers
On their own, custom resources simply let you store and retrieve structured data.
It is only when combined with a *controller* that they become a true declarative API.
When you combine a custom resource with a *custom controller*, custom resources
provide a true _declarative API_.
A [declarative API](/docs/concepts/overview/working-with-objects/kubernetes-objects/#understanding-kubernetes-objects)
allows you to _declare_ or specify the desired state of your resource and tries
to match the actual state to this desired state.
Here, the controller interprets the structured data as a record of the user's
desired state, and continually takes action to achieve and maintain this state.
allows you to _declare_ or specify the desired state of your resource and tries to
keep the current state of Kubernetes objects in sync with the desired state.
The controller interprets the structured data as a record of the user's
desired state, and continually maintains this state.
A *custom controller* is a controller that users can deploy and update on a running cluster, independently of the cluster's own lifecycle. Custom controllers can work with any kind of resource, but they are especially effective when combined with custom resources. The [Operator](https://coreos.com/blog/introducing-operators.html) pattern is one example of such a combination. It allows developers to encode domain knowledge for specific applications into an extension of the Kubernetes API.
You can deploy and update a custom controller on a running cluster, independently
of the cluster's own lifecycle. Custom controllers can work with any kind of resource,
but they are especially effective when combined with custom resources. The
[Operator pattern](https://coreos.com/blog/introducing-operators.html) combines custom
resources and custom controllers. You can use custom controllers to encode domain knowledge
for specific applications into an extension of the Kubernetes API.
### Should I add a custom resource to my Kubernetes Cluster?
## Should I add a custom resource to my Kubernetes Cluster?
When creating a new API, consider whether to [aggregate your API with the Kubernetes cluster APIs](/docs/concepts/api-extension/apiserver-aggregation/) or let your API stand alone.
@@ -56,7 +64,7 @@ When creating a new API, consider whether to [aggregate your API with the Kubern
| Your resources are naturally scoped to a cluster or to namespaces of a cluster. | Cluster or namespace scoped resources are a poor fit; you need control over the specifics of resource paths. |
| You want to reuse [Kubernetes API support features](#common-features). | You don't need those features. |
#### Declarative APIs
### Declarative APIs
In a Declarative API, typically:
@@ -80,7 +88,7 @@ Signs that your API might not be declarative include:
- The API is not easily modeled as objects.
- You chose to represent pending operations with an operation ID or an operation object.
### Should I use a configMap or a custom resource?
## Should I use a configMap or a custom resource?
Use a ConfigMap if any of the following apply:
@@ -126,13 +134,9 @@ This frees you from writing your own API server to handle the custom resource,
but the generic nature of the implementation means you have less flexibility than with
[API server aggregation](#api-server-aggregation).
Refer to the [Custom Controller example, which uses Custom Resources](https://github.com/kubernetes/sample-controller)
for a demonstration of how to register a new custom resource, work with instances of your new resource type,
and setup a controller to handle events.
{{< note >}}
CRD is the successor to the deprecated *ThirdPartyResource* (TPR) API, and is available as of Kubernetes 1.7.
{{< /note >}}
Refer to the [custom controller example](https://github.com/kubernetes/sample-controller)
for an example of how to register a new custom resource, work with instances of your new resource type,
and use a controller to handle events.
## API server aggregation
@@ -143,7 +147,7 @@ implementations for your custom resources by writing and deploying your own stan
The main API server delegates requests to you for the custom resources that you handle,
making them available to all of its clients.
### Choosing a method for adding custom resources
## Choosing a method for adding custom resources
CRDs are easier to use. Aggregated APIs are more flexible. Choose the method that best meets your needs.
@@ -152,7 +156,7 @@ Typically, CRDs are a good fit if:
* You have a handful of fields
* You are using the resource within your company, or as part of a small open-source project (as opposed to a commercial product)
#### Comparing ease of use
### Comparing ease of use
CRDs are easier to create than Aggregated APIs.
@@ -181,7 +185,7 @@ Aggregated APIs offer more advanced API features and customization of other feat
| Protocol Buffers | The new resource supports clients that want to use Protocol Buffers | No | Yes |
| OpenAPI Schema | Is there an OpenAPI (swagger) schema for the types that can be dynamically fetched from the server? Is the user protected from misspelling field names by ensuring only allowed fields are set? Are types enforced (in other words, don't put an `int` in a `string` field?) | No, but planned | Yes |
#### Common Features
### Common Features
When you create a custom resource, either via a CRDs or an AA, you get many features for your API, compared to implementing it outside the Kubernetes platform:
@@ -0,0 +1,117 @@
---
title: Poseidon-Firmament - An alternate scheduler
content_template: templates/concept
weight: 80
---
{{% capture overview %}}
**Current release of Poseidon-Firmament scheduler is an <code> alpha </code> release.**
Poseidon-Firmament scheduler is an alternate scheduler that can be deployed alongside the default Kubernetes scheduler.
{{% /capture %}}
{{% capture body %}}
## Introduction
Poseidon is a service that acts as the integration glue for the [Firmament scheduler](https://github.com/Huawei-PaaS/firmament) with Kubernetes. Poseidon-Firmament scheduler augments the current Kubernetes scheduling capabilities. It incorporates novel flow network graph based scheduling capabilities alongside the default Kubernetes Scheduler. Firmament scheduler models workloads and clusters as flow networks and runs min-cost flow optimizations over these networks to make scheduling decisions.
It models the scheduling problem as a constraint-based optimization over a flow network graph. This is achieved by reducing scheduling to a min-cost max-flow optimization problem. The Poseidon-Firmament scheduler dynamically refines the workload placements.
Poseidon-Firmament scheduler runs alongside the default Kubernetes Scheduler as an alternate scheduler, so multiple schedulers run simultaneously.
## Key Advantages
### Flow graph scheduling based Poseidon-Firmament scheduler provides the following key advantages:
- Workloads (pods) are bulk scheduled to enable scheduling at massive scale..
- Based on the extensive performance test results, Poseidon-Firmament scales much better than the Kubernetes default scheduler as the number of nodes increase in a cluster. This is due to the fact that Poseidon-Firmament is able to amortize more and more work across workloads.
- Poseidon-Firmament Scheduler outperforms the Kubernetes default scheduler by a wide margin when it comes to throughput performance numbers for scenarios where compute resource requirements are somewhat uniform across jobs (Replicasets/Deployments/Jobs). Poseidon-Firmament scheduler end-to-end throughput performance numbers, including bind time, consistently get better as the number of nodes in a cluster increase. For example, for a 2,700 node cluster (shown in the graphs [here](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/benchmark/README.md)), Poseidon-Firmament scheduler achieves a 7X or greater end-to-end throughput than the Kubernetes default scheduler, which includes bind time.
- Availability of complex rule constraints.
- Scheduling in Poseidon-Firmament is dynamic; it keeps cluster resources in a global optimal state during every scheduling run.
- Highly efficient resource utilizations.
## Poseidon-Firmament Scheduler - How it works
As part of the Kubernetes multiple schedulers support, each new pod is typically scheduled by the default scheduler. Kubernetes can be instructed to use another scheduler by specifying the name of another custom scheduler (“poseidon” in our case) in the **schedulerName** field of the PodSpec at the time of pod creation. In this case, the default scheduler will ignore that Pod and allow Poseidon scheduler to schedule the Pod on a relevant node.
```yaml
apiVersion: v1
kind: Pod
...
spec:
schedulerName: poseidon
```
{{< note >}}
For details about the design of this project see the [design document](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/design/README.md).
{{< /note >}}
## Possible Use Case Scenarios - When to use it
As mentioned earlier, Poseidon-Firmament scheduler enables an extremely high throughput scheduling environment at scale due to its bulk scheduling approach versus Kubernetes pod-at-a-time approach. In our extensive tests, we have observed substantial throughput benefits as long as resource requirements (CPU/Memory) for incoming Pods are uniform across jobs (Replicasets/Deployments/Jobs), mainly due to efficient amortization of work across jobs.
Although, Poseidon-Firmament scheduler is capable of scheduling various types of workloads, such as service, batch, etc., the following are a few use cases where it excels the most:
1. For “Big Data/AI” jobs consisting of large number of tasks, throughput benefits are tremendous.
2. Service or batch jobs where workload resource requirements are uniform across jobs (Replicasets/Deployments/Jobs).
## Current Project Stage
- **Alpha Release - Incubation repo.** at https://github.com/kubernetes-sigs/poseidon.
- Currently, Poseidon-Firmament scheduler **does not provide support for high availability**, our implementation assumes that the scheduler cannot fail. The [design document](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/design/README.md) describes possible ways to enable high availability, but we leave this to future work.
- We are **not aware of any production deployment** of Poseidon-Firmament scheduler at this time.
- Poseidon-Firmament is supported from Kubernetes release 1.6 and works with all subsequent releases.
- Release process for Poseidon and Firmament repos are in lock step. The current Poseidon release can be found [here](https://github.com/kubernetes-sigs/poseidon/releases) and the corresponding Firmament release can be found [here](https://github.com/Huawei-PaaS/firmament/releases).
## Features Comparison Matrix
|Feature|Kubernetes Default Scheduler|Poseidon-Firmament Scheduler|Notes|
|--- |--- |--- |--- |
|Node Affinity/Anti-Affinity|Y|Y||
|Pod Affinity/Anti-Affinity - including support for pod anti-affinity symmetry|Y|Y|Currently, the default scheduler outperforms the Poseidon-Firmament scheduler pod affinity/anti-affinity functionality. We are working towards resolving this.|
|Taints & Tolerations|Y|Y||
|Baseline Scheduling capability in accordance to available compute resources (CPU & Memory) on a node|Y|Y**|Not all Predicates & Priorities are supported at this time.|
|Extreme Throughput at scale|Y**|Y|Bulk scheduling approach scales or increases workload placement. Substantial throughput benefits using Firmament scheduler as long as resource requirements (CPU/Memory) for incoming Pods is uniform across Replicasets/Deployments/Jobs. This is mainly due to efficient amortization of work across Replicasets/Deployments/Jobs . 1) For “Big Data/AI” jobs consisting of large no. of tasks, throughput benefits are tremendous. 2) Substantial throughput benefits also for service or batch job scenarios where workload resource requirements are uniform across Replicasets/Deployments/Jobs.|
|Optimal Scheduling|Pod-by-Pod scheduler, processes one pod at a time (may result into sub-optimal scheduling)|Bulk Scheduling (Optimal scheduling)|Pod-by-Pod Kubernetes default scheduler may assign tasks to a sub-optimal machine. By contrast, Firmament considers all unscheduled tasks at the same time together with their soft and hard constraints.|
|Colocation Interference Avoidance|N|N**|Planned in Poseidon-Firmament.|
|Priority Pre-emption|Y|N**|Partially exists in Poseidon-Firmament versus extensive support in Kubernetes default scheduler.|
|Inherent Re-Scheduling|N|Y**|Poseidon-Firmament scheduler supports workload re-scheduling. In each scheduling run it considers all the pods, including running pods, and as a result can migrate or evict pods a globally optimal scheduling environment.|
|Gang Scheduling|N|Y||
|Support for Pre-bound Persistence Volume Scheduling|Y|Y||
|Support for Local Volume & Dynamic Persistence Volume Binding Scheduling|Y|N**|Planned.|
|High Availability|Y|N**|Planned.|
|Real-time metrics based scheduling|N|Y**|Initially supported using Heapster (now deprecated) for placing pods using actual cluster utilization statistics rather than reservations. Plans to switch over to "metric server".|
|Support for Max-Pod per node|Y|Y|Poseidon-Firmament scheduler seamlessly co-exists with Kubernetes default scheduler.|
|Support for Ephemeral Storage, in addition to CPU/Memory|Y|Y||
## Installation
For in-cluster installation of Poseidon, please start at the [Installation instructions](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/install/README.md).
## Development
For developers, please refer to the [Developer Setup instructions](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/devel/README.md).
## Latest Throughput Performance Testing Results
Pod-by-pod schedulers, such as the Kubernetes default scheduler, typically process one pod at a time. These schedulers have the following crucial drawbacks:
1. The scheduler commits to a pod placement early and restricts the choices for other pods that wait to be placed.
2. There is limited opportunities for amortizing work across pods because they are considered for placement individually.
These downsides of pod-by-pod schedulers are addressed by batching or bulk scheduling in Poseidon-Firmament scheduler. Processing several pods in a batch allows the scheduler to jointly consider their placement, and thus to find the best trade-off for the whole batch instead of one pod. At the same time it amortizes work across pods resulting in much higher throughput.
{{< note >}}
Please refer to the [latest benchmark results](https://github.com/kubernetes-sigs/poseidon/blob/master/docs/benchmark/README.md) for detailed throughput performance comparison test results between Poseidon-Firmament scheduler and the Kubernetes default scheduler.
{{< /note >}}
{{% /capture %}}
@@ -4,6 +4,9 @@ reviewers:
title: Kubernetes Components
content_template: templates/concept
weight: 20
card:
name: concepts
weight: 20
---
{{% capture overview %}}
@@ -52,7 +55,7 @@ These controllers include:
cloud-controller-manager runs cloud-provider-specific controller loops only. You must disable these controller loops in the kube-controller-manager. You can disable the controller loops by setting the `--cloud-provider` flag to `external` when starting the kube-controller-manager.
cloud-controller-manager allows cloud vendors code and the Kubernetes core to evolve independent of each other. In prior releases, the core Kubernetes code was dependent upon cloud-provider-specific code for functionality. In future releases, code specific to cloud vendors should be maintained by the cloud vendor themselves, and linked to cloud-controller-manager while running Kubernetes.
cloud-controller-manager allows cloud vendors code and the Kubernetes code to evolve independent of each other. In prior releases, the core Kubernetes code was dependent upon cloud-provider-specific code for functionality. In future releases, code specific to cloud vendors should be maintained by the cloud vendor themselves, and linked to cloud-controller-manager while running Kubernetes.
The following controllers have cloud provider dependencies:
@@ -76,7 +79,8 @@ network rules on the host and performing connection forwarding.
### Container Runtime
The container runtime is the software that is responsible for running containers. Kubernetes supports several runtimes: [Docker](http://www.docker.com), [rkt](https://coreos.com/rkt/), [runc](https://github.com/opencontainers/runc) and any OCI [runtime-spec](https://github.com/opencontainers/runtime-spec) implementation.
The container runtime is the software that is responsible for running containers.
Kubernetes supports several runtimes: [Docker](http://www.docker.com), [containerd](https://containerd.io), [cri-o](https://cri-o.io/), [rktlet](https://github.com/kubernetes-incubator/rktlet) and any implementation of the [Kubernetes CRI (Container Runtime Interface)](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md).
## Addons
@@ -4,6 +4,9 @@ reviewers:
title: The Kubernetes API
content_template: templates/concept
weight: 30
card:
name: concepts
weight: 30
---
{{% capture overview %}}
@@ -33,17 +36,19 @@ What constitutes a compatible change and how to change the API are detailed by t
## OpenAPI and Swagger definitions
Complete API details are documented using [Swagger v1.2](http://swagger.io/) and [OpenAPI](https://www.openapis.org/). The Kubernetes apiserver (aka "master") exposes an API that can be used to retrieve the Swagger v1.2 Kubernetes API spec located at `/swaggerapi`.
Complete API details are documented using [OpenAPI](https://www.openapis.org/).
Starting with Kubernetes 1.10, OpenAPI spec is served in a single `/openapi/v2` endpoint. The format-separated endpoints (`/swagger.json`, `/swagger-2.0.0.json`, `/swagger-2.0.0.pb-v1`, `/swagger-2.0.0.pb-v1.gz`) are deprecated and will get removed in Kubernetes 1.14.
Requested format is specified by setting HTTP headers:
Starting with Kubernetes 1.10, the Kubernetes API server serves an OpenAPI spec via the `/openapi/v2` endpoint.
The requested format is specified by setting HTTP headers:
Header | Possible Values
------ | ---------------
Accept | `application/json`, `application/com.github.proto-openapi.spec.v2@v1.0+protobuf` (the default content-type is `application/json` for `*/*` or not passing this header)
Accept-Encoding | `gzip` (not passing this header is acceptable)
Prior to 1.14, format-separated endpoints (`/swagger.json`, `/swagger-2.0.0.json`, `/swagger-2.0.0.pb-v1`, `/swagger-2.0.0.pb-v1.gz`)
serve the OpenAPI spec in different formats. These endpoints are deprecated, and will be removed in Kubernetes 1.14.
**Examples of getting OpenAPI spec**:
Before 1.10 | Starting with Kubernetes 1.10
@@ -52,9 +57,12 @@ GET /swagger.json | GET /openapi/v2 **Accept**: application/json
GET /swagger-2.0.0.pb-v1 | GET /openapi/v2 **Accept**: application/com.github.proto-openapi.spec.v2@v1.0+protobuf
GET /swagger-2.0.0.pb-v1.gz | GET /openapi/v2 **Accept**: application/com.github.proto-openapi.spec.v2@v1.0+protobuf **Accept-Encoding**: gzip
Kubernetes implements an alternative Protobuf based serialization format for the API that is primarily intended for intra-cluster communication, documented in the [design proposal](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/protobuf.md) and the IDL files for each schema are located in the Go packages that define the API objects.
Prior to 1.14, the Kubernetes apiserver also exposes an API that can be used to retrieve
the [Swagger v1.2](http://swagger.io/) Kubernetes API spec at `/swaggerapi`.
This endpoint is deprecated, and will be removed in Kubernetes 1.14.
## API versioning
To make it easier to eliminate fields or restructure resource representations, Kubernetes supports
@@ -125,9 +133,9 @@ to pick up the `--runtime-config` changes.
## Enabling resources in the groups
DaemonSets, Deployments, HorizontalPodAutoscalers, Ingress, Jobs and ReplicaSets are enabled by default.
DaemonSets, Deployments, HorizontalPodAutoscalers, Ingresses, Jobs and ReplicaSets are enabled by default.
Other extensions resources can be enabled by setting `--runtime-config` on
apiserver. `--runtime-config` accepts comma separated values. For example: to disable deployments and ingress, set
`--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingress=false`
`--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingresses=false`
{{% /capture %}}
@@ -73,7 +73,7 @@ Run `kubectl diff` to print the object that will be created:
kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml
```
{{< note >}}
**Note:** `diff` uses [server-side dry-run](/docs/reference/using-api/api-concepts/#dry-run), which needs to be enabled on `kube-apiserver`.
`diff` uses [server-side dry-run](/docs/reference/using-api/api-concepts/#dry-run), which needs to be enabled on `kube-apiserver`.
{{< /note >}}
Create the object using `kubectl apply`:
@@ -625,7 +625,7 @@ Add, delete, or update individual elements. This does not preserve ordering.
This merge strategy uses a special tag on each field called a `patchMergeKey`. The
`patchMergeKey` is defined for each field in the Kubernetes source code:
[types.go](https://git.k8s.io/api/core/v1/types.go#L2565)
[types.go](https://github.com/kubernetes/api/blob/d04500c8c3dda9c980b668c57abc2ca61efcf5c4/core/v1/types.go#L2747)
When merging a list of maps, the field specified as the `patchMergeKey` for a given element
is used like a map key for that element.
@@ -700,7 +700,7 @@ As of Kubernetes 1.5, merging lists of primitive elements is not supported.
{{< note >}}
Which of the above strategies is chosen for a given field is controlled by
the `patchStrategy` tag in [types.go](https://git.k8s.io/api/core/v1/types.go#L2565)
the `patchStrategy` tag in [types.go](https://github.com/kubernetes/api/blob/d04500c8c3dda9c980b668c57abc2ca61efcf5c4/core/v1/types.go#L2748)
If no `patchStrategy` is specified for a field of type list, then
the list is replaced.
{{< /note >}}
@@ -73,7 +73,7 @@ that must be set:
The `kubectl` command also supports update commands driven by an aspect of the object.
Setting this aspect may set different fields for different object types:
- `set` <field>: Set an aspect of an object.
- `set` `<field>`: Set an aspect of an object.
{{< note >}}
In Kubernetes version 1.5, not every verb-driven command has an associated aspect-driven command.
@@ -160,5 +160,3 @@ kubectl create --edit -f /tmp/srv.yaml
- [Kubectl Command Reference](/docs/reference/generated/kubectl/kubectl/)
- [Kubernetes API Reference](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/)
{{% /capture %}}
@@ -5,6 +5,9 @@ reviewers:
title: What is Kubernetes?
content_template: templates/concept
weight: 10
card:
name: concepts
weight: 10
---
{{% capture overview %}}
@@ -53,11 +53,22 @@ Here are some examples of information that could be recorded in annotations:
* Phone or pager numbers of persons responsible, or directory entries that
specify where that information can be found, such as a team web site.
* Directives from the end-user to the implementations to modify behavior or
engage non-standard features.
Instead of using annotations, you could store this type of information in an
external database or directory, but that would make it much harder to produce
shared client libraries and tools for deployment, management, introspection,
and the like.
## Syntax and character set
_Annotations_ are key/value pairs. Valid annotation keys have two segments: an optional prefix and name, separated by a slash (`/`). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (`.`), not longer than 253 characters in total, followed by a slash (`/`).
If the prefix is omitted, the annotation Key is presumed to be private to the user. Automated system components (e.g. `kube-scheduler`, `kube-controller-manager`, `kube-apiserver`, `kubectl`, or other third-party automation) which add annotations to end-user objects must specify a prefix.
The `kubernetes.io/` and `k8s.io/` prefixes are reserved for Kubernetes core components.
{{% /capture %}}
{{% capture whatsnext %}}
@@ -12,15 +12,15 @@ _Field selectors_ let you [select Kubernetes resources](/docs/concepts/overview/
This `kubectl` command selects all Pods for which the value of the [`status.phase`](/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase) field is `Running`:
```shell
$ kubectl get pods --field-selector status.phase=Running
kubectl get pods --field-selector status.phase=Running
```
{{< note >}}
Field selectors are essentially resource *filters*. By default, no selectors/filters are applied, meaning that all resources of the specified type are selected. This makes the following `kubectl` queries equivalent:
```shell
$ kubectl get pods
$ kubectl get pods --field-selector ""
kubectl get pods
kubectl get pods --field-selector ""
```
{{< /note >}}
@@ -29,7 +29,9 @@ $ kubectl get pods --field-selector ""
Supported field selectors vary by Kubernetes resource type. All resource types support the `metadata.name` and `metadata.namespace` fields. Using unsupported field selectors produces an error. For example:
```shell
$ kubectl get ingress --field-selector foo.bar=baz
kubectl get ingress --field-selector foo.bar=baz
```
```
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
```
@@ -38,7 +40,7 @@ Error from server (BadRequest): Unable to find "ingresses" that match label sele
You can use the `=`, `==`, and `!=` operators with field selectors (`=` and `==` mean the same thing). This `kubectl` command, for example, selects all Kubernetes Services that aren't in the `default` namespace:
```shell
$ kubectl get services --field-selector metadata.namespace!=default
kubectl get services --field-selector metadata.namespace!=default
```
## Chained selectors
@@ -46,7 +48,7 @@ $ kubectl get services --field-selector metadata.namespace!=default
As with [label](/docs/concepts/overview/working-with-objects/labels) and other selectors, field selectors can be chained together as a comma-separated list. This `kubectl` command selects all Pods for which the `status.phase` does not equal `Running` and the `spec.restartPolicy` field equals `Always`:
```shell
$ kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
```
## Multiple resource types
@@ -54,5 +56,5 @@ $ kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Alw
You use field selectors across multiple resource types. This `kubectl` command selects all Statefulsets and Services that are not in the `default` namespace:
```shell
$ kubectl get statefulsets,services --field-selector metadata.namespace!=default
kubectl get statefulsets,services --field-selector metadata.namespace!=default
```
@@ -2,6 +2,9 @@
title: Understanding Kubernetes Objects
content_template: templates/concept
weight: 10
card:
name: concepts
weight: 40
---
{{% capture overview %}}
@@ -28,7 +31,7 @@ Every Kubernetes object includes two nested object fields that govern the object
For example, a Kubernetes Deployment is an object that can represent an application running on your cluster. When you create the Deployment, you might set the Deployment spec to specify that you want three replicas of the application to be running. The Kubernetes system reads the Deployment spec and starts three instances of your desired application--updating the status to match your spec. If any of those instances should fail (a status change), the Kubernetes system responds to the difference between spec and status by making a correction--in this case, starting a replacement instance.
For more information on the object spec, status, and metadata, see the [Kubernetes API Conventions](https://git.k8s.io/community/contributors/devel/api-conventions.md).
For more information on the object spec, status, and metadata, see the [Kubernetes API Conventions](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md).
### Describing a Kubernetes Object
@@ -43,7 +46,7 @@ One way to create a Deployment using a `.yaml` file like the one above is to use
in the `kubectl` command-line interface, passing the `.yaml` file as an argument. Here's an example:
```shell
$ kubectl create -f https://k8s.io/examples/application/deployment.yaml --record
kubectl create -f https://k8s.io/examples/application/deployment.yaml --record
```
The output is similar to this:
@@ -10,8 +10,8 @@ weight: 40
_Labels_ are key/value pairs that are attached to objects, such as pods.
Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but do not directly imply semantics to the core system.
Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time.
Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time.
Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
```json
"metadata": {
@@ -22,7 +22,7 @@ Each object can have a set of key/value labels defined. Each Key must be unique
}
```
We'll eventually index and reverse-index labels for efficient queries and watches, use them to sort and group in UIs and CLIs, etc. We don't want to pollute labels with non-identifying, especially large and/or structured, data. Non-identifying information should be recorded using [annotations](/docs/concepts/overview/working-with-objects/annotations/).
Labels allow for efficient queries and watches and are ideal for use in UIs and CLIs. Non-identifying information should be recorded using [annotations](/docs/concepts/overview/working-with-objects/annotations/).
{{% /capture %}}
@@ -47,8 +47,11 @@ These are just examples of commonly used labels; you are free to develop your ow
## Syntax and character set
_Labels_ are key/value pairs. Valid label keys have two segments: an optional prefix and name, separated by a slash (`/`). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (`.`), not longer than 253 characters in total, followed by a slash (`/`).
If the prefix is omitted, the label Key is presumed to be private to the user. Automated system components (e.g. `kube-scheduler`, `kube-controller-manager`, `kube-apiserver`, `kubectl`, or other third-party automation) which add labels to end-user objects must specify a prefix. The `kubernetes.io/` prefix is reserved for Kubernetes core components.
_Labels_ are key/value pairs. Valid label keys have two segments: an optional prefix and name, separated by a slash (`/`). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (`.`), not longer than 253 characters in total, followed by a slash (`/`).
If the prefix is omitted, the label Key is presumed to be private to the user. Automated system components (e.g. `kube-scheduler`, `kube-controller-manager`, `kube-apiserver`, `kubectl`, or other third-party automation) which add labels to end-user objects must specify a prefix.
The `kubernetes.io/` and `k8s.io/` prefixes are reserved for Kubernetes core components.
Valid label values must be 63 characters or less and must be empty or begin and end with an alphanumeric character (`[a-z0-9A-Z]`) with dashes (`-`), underscores (`_`), dots (`.`), and alphanumerics between.
@@ -61,12 +64,12 @@ Via a _label selector_, the client/user can identify a set of objects. The label
The API currently supports two types of selectors: _equality-based_ and _set-based_.
A label selector can be made of multiple _requirements_ which are comma-separated. In the case of multiple requirements, all must be satisfied so the comma separator acts as a logical _AND_ (`&&`) operator.
An empty label selector (that is, one with zero requirements) selects every object in the collection.
A null label selector (which is only possible for optional selector fields) selects no objects.
The semantics of empty or non-specified selectors are dependent on the context,
and API types that use selectors should document the validity and meaning of
them.
{{< note >}}
The label selectors of two controllers must not overlap within a namespace, otherwise they will fight with each other.
For some API types, such as ReplicaSets, the label selectors of two instances must not overlap within a namespace, or the controller can see that as conflicting instructions and fail to determine how many replicas should be present.
{{< /note >}}
### _Equality-based_ requirement
@@ -136,25 +139,25 @@ LIST and WATCH operations may specify label selectors to filter the sets of obje
Both label selector styles can be used to list or watch resources via a REST client. For example, targeting `apiserver` with `kubectl` and using _equality-based_ one may write:
```shell
$ kubectl get pods -l environment=production,tier=frontend
kubectl get pods -l environment=production,tier=frontend
```
or using _set-based_ requirements:
```shell
$ kubectl get pods -l 'environment in (production),tier in (frontend)'
kubectl get pods -l 'environment in (production),tier in (frontend)'
```
As already mentioned _set-based_ requirements are more expressive.  For instance, they can implement the _OR_ operator on values:
```shell
$ kubectl get pods -l 'environment in (production, qa)'
kubectl get pods -l 'environment in (production, qa)'
```
or restricting negative matching via _exists_ operator:
```shell
$ kubectl get pods -l 'environment,environment notin (frontend)'
kubectl get pods -l 'environment,environment notin (frontend)'
```
### Set references in API objects
@@ -46,7 +46,9 @@ for namespaces](/docs/admin/namespaces).
You can list the current namespaces in a cluster using:
```shell
$ kubectl get namespaces
kubectl get namespaces
```
```
NAME STATUS AGE
default Active 1d
kube-system Active 1d
@@ -66,8 +68,8 @@ To temporarily set the namespace for a request, use the `--namespace` flag.
For example:
```shell
$ kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
$ kubectl --namespace=<insert-namespace-name-here> get pods
kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods
```
### Setting the namespace preference
@@ -76,9 +78,9 @@ You can permanently save the namespace for all subsequent kubectl commands in th
context.
```shell
$ kubectl config set-context $(kubectl config current-context) --namespace=<insert-namespace-name-here>
kubectl config set-context $(kubectl config current-context) --namespace=<insert-namespace-name-here>
# Validate it
$ kubectl config view | grep namespace:
kubectl config view | grep namespace:
```
## Namespaces and DNS
@@ -101,10 +103,10 @@ To see which Kubernetes resources are and aren't in a namespace:
```shell
# In a namespace
$ kubectl api-resources --namespaced=true
kubectl api-resources --namespaced=true
# Not in a namespace
$ kubectl api-resources --namespaced=false
kubectl api-resources --namespaced=false
```
{{% /capture %}}
@@ -41,7 +41,7 @@ administrator to control the following:
| Restricting escalation to root privileges | [`allowPrivilegeEscalation`, `defaultAllowPrivilegeEscalation`](#privilege-escalation) |
| Linux capabilities | [`defaultAddCapabilities`, `requiredDropCapabilities`, `allowedCapabilities`](#capabilities) |
| The SELinux context of the container | [`seLinux`](#selinux) |
| The Allowed Proc Mount types for the container | [`allowedProcMountTypes`](#allowedProcMountTypes) |
| The Allowed Proc Mount types for the container | [`allowedProcMountTypes`](#allowedprocmounttypes) |
| The AppArmor profile used by containers | [annotations](#apparmor) |
| The seccomp profile used by containers | [annotations](#seccomp) |
| The sysctl profile used by containers | [annotations](#sysctl) |
@@ -336,7 +336,6 @@ pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s
pause-7774d79b5-qrgcb 1/1 Running 0 2s
^C
```
### Clean up
@@ -465,7 +464,7 @@ Please make sure [`volumes`](#volumes-and-file-systems) field contains the
For example:
```yaml
apiVersion: extensions/v1beta1
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: allow-flex-volumes
@@ -610,6 +609,6 @@ default cannot be changed.
### Sysctl
Controlled via annotations on the PodSecurityPolicy. Refer to the [Sysctl documentation](
/docs/concepts/cluster-administration/sysctl-cluster/#podsecuritypolicy-annotations).
/docs/concepts/cluster-administration/sysctl-cluster/#podsecuritypolicy).
{{% /capture %}}
@@ -551,10 +551,10 @@ plugins:
kind: Configuration
limitedResources:
- resource: pods
matchScopes:
- operator : In
scopeName: PriorityClass
values: ["cluster-services"]
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
```
Now, "cluster-services" pods will be allowed in only those namespaces where a quota object with a matching `scopeSelector` is present.
@@ -562,8 +562,8 @@ For example:
```yaml
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
```
@@ -19,7 +19,7 @@ Modification not using HostAliases is not suggested because the file is managed
## Default Hosts File Content
Lets start an Nginx Pod which is assigned a Pod IP:
Let's start an Nginx Pod which is assigned a Pod IP:
```shell
kubectl run nginx --image nginx --generator=run-pod/v1
@@ -107,10 +107,8 @@ fe00::2 ip6-allrouters
10.200.0.5 hostaliases-pod
# Entries added by HostAliases.
127.0.0.1 foo.local
127.0.0.1 bar.local
10.1.2.3 foo.remote
10.1.2.3 bar.remote
127.0.0.1 foo.local bar.local
10.1.2.3 foo.remote bar.remote
```
With the additional entries specified at the bottom.
@@ -17,7 +17,7 @@ Now that you have a continuously running, replicated application you can expose
By default, Docker uses host-private networking, so containers can talk to other containers only if they are on the same machine. In order for Docker containers to communicate across nodes, there must be allocated ports on the machines own IP address, which are then forwarded or proxied to the containers. This obviously means that containers must either coordinate which ports they use very carefully or ports must be allocated dynamically.
Coordinating ports across multiple developers is very difficult to do at scale and exposes users to cluster-level issues outside of their control. Kubernetes assumes that pods can communicate with other pods, regardless of which host they land on. We give every pod its own cluster-private-IP address so you do not need to explicitly create links between pods or mapping container ports to host ports. This means that containers within a Pod can all reach each other's ports on localhost, and all pods in a cluster can see each other without NAT. The rest of this document will elaborate on how you can run reliable services on such a networking model.
Coordinating ports across multiple developers is very difficult to do at scale and exposes users to cluster-level issues outside of their control. Kubernetes assumes that pods can communicate with other pods, regardless of which host they land on. We give every pod its own cluster-private-IP address so you do not need to explicitly create links between pods or map container ports to host ports. This means that containers within a Pod can all reach each other's ports on localhost, and all pods in a cluster can see each other without NAT. The rest of this document will elaborate on how you can run reliable services on such a networking model.
This guide uses a simple nginx server to demonstrate proof of concept. The same principles are embodied in a more complete [Jenkins CI application](https://kubernetes.io/blog/2015/07/strong-simple-ssl-for-kubernetes).
@@ -35,8 +35,10 @@ Create an nginx Pod, and note that it has a container port specification:
This makes it accessible from any node in your cluster. Check the nodes the Pod is running on:
```shell
$ kubectl create -f ./run-my-nginx.yaml
$ kubectl get pods -l run=my-nginx -o wide
kubectl create -f ./run-my-nginx.yaml
kubectl get pods -l run=my-nginx -o wide
```
```
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
@@ -45,7 +47,7 @@ my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5
Check your pods' IPs:
```shell
$ kubectl get pods -l run=my-nginx -o yaml | grep podIP
kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.244.3.4
podIP: 10.244.2.5
```
@@ -63,7 +65,9 @@ A Kubernetes Service is an abstraction which defines a logical set of Pods runni
You can create a Service for your 2 nginx replicas with `kubectl expose`:
```shell
$ kubectl expose deployment/my-nginx
kubectl expose deployment/my-nginx
```
```
service/my-nginx exposed
```
@@ -81,7 +85,9 @@ API object to see the list of supported fields in service definition.
Check your Service:
```shell
$ kubectl get svc my-nginx
kubectl get svc my-nginx
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
```
@@ -95,7 +101,9 @@ Check the endpoints, and note that the IPs are the same as the Pods created in
the first step:
```shell
$ kubectl describe svc my-nginx
kubectl describe svc my-nginx
```
```
Name: my-nginx
Namespace: default
Labels: run=my-nginx
@@ -107,8 +115,11 @@ Port: <unset> 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
Events: <none>
$ kubectl get ep my-nginx
```
```shell
kubectl get ep my-nginx
```
```
NAME ENDPOINTS AGE
my-nginx 10.244.2.5:80,10.244.3.4:80 1m
```
@@ -131,7 +142,9 @@ 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-3800858182-jr4a2 -- 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
@@ -147,9 +160,11 @@ replicas. This will give you scheduler-level Service spreading of your Pods
variables:
```shell
$ kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
$ kubectl get pods -l run=my-nginx -o wide
kubectl get pods -l run=my-nginx -o wide
```
```
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
@@ -158,7 +173,9 @@ my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8
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
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
```
```
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
@@ -171,19 +188,23 @@ KUBERNETES_SERVICE_PORT_HTTPS=443
Kubernetes offers a DNS cluster addon Service that automatically assigns dns names to other Services. You can check if it's running on your cluster:
```shell
$ kubectl get services kube-dns --namespace=kube-system
kubectl get services kube-dns --namespace=kube-system
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
```
If it isn't running, you can [enable it](http://releases.k8s.io/{{< param "githubbranch" >}}/cluster/addons/dns/README.md#how-do-i-configure-it).
If it isn't running, you can [enable it](http://releases.k8s.io/{{< param "githubbranch" >}}/cluster/addons/dns/kube-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 CoreDNS
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 run curl --image=radial/busyboxplus:curl -i --tty
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
```
@@ -210,10 +231,16 @@ Till now we have only accessed the nginx server from within the cluster. Before
You can acquire all these from the [nginx https example](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/https-nginx/). This requires having go and make tools installed. If you don't want to install those, then follow the manual steps later. In short:
```shell
$ make keys secret KEY=/tmp/nginx.key CERT=/tmp/nginx.crt SECRET=/tmp/secret.json
$ kubectl create -f /tmp/secret.json
make keys secret KEY=/tmp/nginx.key CERT=/tmp/nginx.crt SECRET=/tmp/secret.json
kubectl create -f /tmp/secret.json
```
```
secret/nginxsecret created
$ kubectl get secrets
```
```shell
kubectl get secrets
```
```
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
@@ -242,8 +269,10 @@ data:
Now create the secrets using the file:
```shell
$ kubectl create -f nginxsecrets.yaml
$ kubectl get secrets
kubectl create -f nginxsecrets.yaml
kubectl get secrets
```
```
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret Opaque 2 1m
@@ -263,13 +292,13 @@ Noteworthy points about the nginx-secure-app manifest:
This is setup *before* the nginx server is started.
```shell
$ kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
```
At this point you can reach the nginx server from any node.
```shell
$ kubectl get pods -o yaml | grep -i podip
kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
node $ curl -k https://10.244.3.5
...
@@ -283,11 +312,15 @@ Let's test this from a pod (the same secret is being reused for simplicity, the
{{< codenew file="service/networking/curlpod.yaml" >}}
```shell
$ kubectl create -f ./curlpod.yaml
$ kubectl get pods -l app=curlpod
kubectl create -f ./curlpod.yaml
kubectl get pods -l app=curlpod
```
```
NAME READY STATUS RESTARTS AGE
curl-deployment-1515033274-1410r 1/1 Running 0 1m
$ kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
```
```shell
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/nginx.crt
...
<title>Welcome to nginx!</title>
...
@@ -302,7 +335,7 @@ so your nginx HTTPS replica is ready to serve traffic on the internet if your
node has a public IP.
```shell
$ kubectl get svc my-nginx -o yaml | grep nodePort -C 5
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
@@ -319,8 +352,9 @@ spec:
targetPort: 443
selector:
run: my-nginx
$ kubectl get nodes -o yaml | grep ExternalIP -C 1
```
```shell
kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
@@ -338,12 +372,15 @@ $ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
Let's now recreate the Service to use a cloud load balancer, just change the `Type` of `my-nginx` Service from `NodePort` to `LoadBalancer`:
```shell
$ kubectl edit svc my-nginx
$ kubectl get svc my-nginx
kubectl edit svc my-nginx
kubectl get svc my-nginx
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 162.222.184.144 80/TCP,81/TCP,82/TCP 21s
$ curl https://<EXTERNAL-IP> -k
```
```
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
```
@@ -357,7 +394,7 @@ 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 my-nginx
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
@@ -251,7 +251,7 @@ options ndots:2 edns0
For IPv6 setup, search path and name server should be setup like this:
```
$ kubectl exec -it busybox -- cat /etc/resolv.conf
$ kubectl exec -it dns-example -- cat /etc/resolv.conf
nameserver fd00:79:30::a
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
@@ -0,0 +1,74 @@
---
title: Ingress Controllers
reviewers:
content_template: templates/concept
weight: 40
---
{{% capture overview %}}
In order for the Ingress resource to work, the cluster must have an ingress controller running.
Unlike other types of controllers which run as part of the `kube-controller-manager` binary, Ingress controllers
are not started automatically with a cluster. Use this page to choose the ingress controller implementation
that best fits your cluster.
Kubernetes as a project currently supports and maintains [GCE](https://git.k8s.io/ingress-gce/README.md) and
[nginx](https://git.k8s.io/ingress-nginx/README.md) controllers.
{{% /capture %}}
{{% capture body %}}
## Additional controllers
* [Ambassador](https://www.getambassador.io/) API Gateway is an [Envoy](https://www.envoyproxy.io) based ingress
controller with [community](https://www.getambassador.io/docs) or
[commercial](https://www.getambassador.io/pro/) support from [Datawire](https://www.datawire.io/).
* [AppsCode Inc.](https://appscode.com) offers support and maintenance for the most widely used [HAProxy](http://www.haproxy.org/) based ingress controller [Voyager](https://appscode.com/products/voyager).
* [Contour](https://github.com/heptio/contour) is an [Envoy](https://www.envoyproxy.io) based ingress controller
provided and supported by Heptio.
* Citrix provides an [Ingress Controller](https://github.com/citrix/citrix-k8s-ingress-controller) for its hardware (MPX), virtualized (VPX) and [free containerized (CPX) ADC](https://www.citrix.com/products/citrix-adc/cpx-express.html) for [baremetal](https://github.com/citrix/citrix-k8s-ingress-controller/tree/master/deployment/baremetal) and [cloud](https://github.com/citrix/citrix-k8s-ingress-controller/tree/master/deployment) deployments.
* F5 Networks provides [support and maintenance](https://support.f5.com/csp/article/K86859508)
for the [F5 BIG-IP Controller for Kubernetes](http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest).
* [Gloo](https://gloo.solo.io) is an open-source ingress controller based on [Envoy](https://www.envoyproxy.io) which offers API Gateway functionality with enterprise support from [solo.io](https://www.solo.io).
* [HAProxy](http://www.haproxy.org/) based ingress controller
[jcmoraisjr/haproxy-ingress](https://github.com/jcmoraisjr/haproxy-ingress) which is mentioned on the blog post
[HAProxy Ingress Controller for Kubernetes](https://www.haproxy.com/blog/haproxy_ingress_controller_for_kubernetes/).
[HAProxy Technologies](https://www.haproxy.com/) offers support and maintenance for HAProxy Enterprise and
the ingress controller [jcmoraisjr/haproxy-ingress](https://github.com/jcmoraisjr/haproxy-ingress).
* [Istio](https://istio.io/) based ingress controller
[Control Ingress Traffic](https://istio.io/docs/tasks/traffic-management/ingress/).
* [Kong](https://konghq.com/) offers [community](https://discuss.konghq.com/c/kubernetes) or
[commercial](https://konghq.com/kong-enterprise/) support and maintenance for the
[Kong Ingress Controller for Kubernetes](https://github.com/Kong/kubernetes-ingress-controller).
* [NGINX, Inc.](https://www.nginx.com/) offers support and maintenance for the
[NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx/kubernetes-ingress-controller).
* [Traefik](https://github.com/containous/traefik) is a fully featured ingress controller
([Let's Encrypt](https://letsencrypt.org), secrets, http2, websocket), and it also comes with commercial
support by [Containous](https://containo.us/services).
## Using multiple Ingress controllers
You may deploy [any number of ingress controllers](https://git.k8s.io/ingress-nginx/docs/user-guide/multiple-ingress.md#multiple-ingress-controllers)
within a cluster. When you create an ingress, you should annotate each ingress with the appropriate
[`ingress.class`](https://git.k8s.io/ingress-gce/docs/faq/README.md#how-do-i-run-multiple-ingress-controllers-in-the-same-cluster)
to indicate which ingress controller should be used if more than one exists within your cluster.
If you do not define a class, your cloud provider may use a default ingress provider.
Ideally, all ingress controllers should fulfill this specification, but the various ingress
controllers operate slightly differently.
{{< note >}}
Make sure you review your ingress controller's documentation to understand the caveats of choosing it.
{{< /note >}}
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about [Ingress](/docs/concepts/services-networking/ingress/).
* [Set up Ingress on Minikube with the NGINX Controller](/docs/tasks/access-application-cluster/ingress-minikube).
{{% /capture %}}
@@ -25,7 +25,7 @@ For the sake of clarity, this guide defines the following terms:
Ingress, added in Kubernetes v1.1, exposes HTTP and HTTPS routes from outside the cluster to
{{< link text="services" url="/docs/concepts/services-networking/service/" >}} within the cluster.
Traffic routing is controlled by rules defined on the ingress resource.
Traffic routing is controlled by rules defined on the Ingress resource.
```none
internet
@@ -35,9 +35,9 @@ Traffic routing is controlled by rules defined on the ingress resource.
[ Services ]
```
An ingress can be configured to give services externally-reachable URLs, load balance traffic, terminate SSL, and offer name based virtual hosting. An [ingress controller](#ingress-controllers) is responsible for fulfilling the ingress, usually with a loadbalancer, though it may also configure your edge router or additional frontends to help handle the traffic.
An Ingress can be configured to give services externally-reachable URLs, load balance traffic, terminate SSL, and offer name based virtual hosting. An [Ingress controller](/docs/concepts/services-networking/ingress-controllers) is responsible for fulfilling the Ingress, usually with a loadbalancer, though it may also configure your edge router or additional frontends to help handle the traffic.
An ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically
An Ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically
uses a service of type [Service.Type=NodePort](/docs/concepts/services-networking/service/#nodeport) or
[Service.Type=LoadBalancer](/docs/concepts/services-networking/service/#loadbalancer).
@@ -45,50 +45,19 @@ uses a service of type [Service.Type=NodePort](/docs/concepts/services-networkin
{{< feature-state for_k8s_version="v1.1" state="beta" >}}
Before you start using an ingress, there are a few things you should understand. The ingress is a beta resource. You will need an ingress controller to satisfy an ingress, simply creating the resource will have no effect.
Before you start using an Ingress, there are a few things you should understand. The Ingress is a beta resource.
GCE/Google Kubernetes Engine deploys an [ingress controller](#ingress-controllers) on the master. Review the
{{< note >}}
You must have an [Ingress controller](/docs/concepts/services-networking/ingress-controllers) to satisfy an Ingress. Only creating an Ingress resource has no effect.
{{< /note >}}
GCE/Google Kubernetes Engine deploys an Ingress controller on the master. Review the
[beta limitations](https://github.com/kubernetes/ingress-gce/blob/master/BETA_LIMITATIONS.md#glbc-beta-limitations)
of this controller if you are using GCE/GKE.
In environments other than GCE/Google Kubernetes Engine, you may need to
[deploy an ingress controller](https://kubernetes.github.io/ingress-nginx/deploy/). There are a number of
[ingress controller](#ingress-controllers) you may choose from.
## Ingress controllers
In order for the ingress resource to work, the cluster must have an ingress controller running. This is unlike other types of controllers, which run as part of the `kube-controller-manager` binary, and are typically started automatically with a cluster. Choose the ingress controller implementation that best fits your cluster.
* Kubernetes as a project currently supports and maintains [GCE](https://git.k8s.io/ingress-gce/README.md) and
[nginx](https://git.k8s.io/ingress-nginx/README.md) controllers.
Additional controllers include:
* [Contour](https://github.com/heptio/contour) is an [Envoy](https://www.envoyproxy.io) based ingress controller
provided and supported by Heptio.
* F5 Networks provides [support and maintenance](https://support.f5.com/csp/article/K86859508)
for the [F5 BIG-IP Controller for Kubernetes](http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest).
* [HAProxy](http://www.haproxy.org/) based ingress controller
[jcmoraisjr/haproxy-ingress](https://github.com/jcmoraisjr/haproxy-ingress) which is mentioned on the blog post
[HAProxy Ingress Controller for Kubernetes](https://www.haproxy.com/blog/haproxy_ingress_controller_for_kubernetes/).
[HAProxy Technologies](https://www.haproxy.com/) offers support and maintenance for HAProxy Enterprise and
the ingress controller [jcmoraisjr/haproxy-ingress](https://github.com/jcmoraisjr/haproxy-ingress).
* [Istio](https://istio.io/) based ingress controller
[Control Ingress Traffic](https://istio.io/docs/tasks/traffic-management/ingress/).
* [Kong](https://konghq.com/) offers [community](https://discuss.konghq.com/c/kubernetes) or
[commercial](https://konghq.com/api-customer-success/) support and maintenance for the
[Kong Ingress Controllerfor Kubernetes](https://konghq.com/blog/kubernetes-ingress-controller-for-kong/).
* [NGINX, Inc.](https://www.nginx.com/) offers support and maintenance for the
[NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx/kubernetes-ingress-controller).
* [Traefik](https://github.com/containous/traefik) is a fully featured ingress controller
([Let's Encrypt](https://letsencrypt.org), secrets, http2, websocket), and it also comes with commercial
support by [Containous](https://containo.us/services).
You may deploy [any number of ingress controllers](https://git.k8s.io/ingress-nginx/docs/user-guide/multiple-ingress.md#multiple-ingress-controllers) within a cluster.
When you create an ingress, you should annotate each ingress with the appropriate
[`ingress-class`](https://git.k8s.io/ingress-gce/examples/PREREQUISITES.md#ingress-class) to indicate which ingress
controller should be used if more than one exists within your cluster.
If you do not define a class, your cloud provider may use a default ingress provider.
[ingress controllers](/docs/concepts/services-networking/ingress-controllers) you may choose from.
### Before you begin
@@ -120,14 +89,14 @@ spec:
servicePort: 80
```
As with all other Kubernetes resources, an ingress needs `apiVersion`, `kind`, and `metadata` fields.
As with all other Kubernetes resources, an Ingress needs `apiVersion`, `kind`, and `metadata` fields.
For general information about working with config files, see [deploying applications](/docs/tasks/run-application/run-stateless-application-deployment/), [configuring containers](/docs/tasks/configure-pod-container/configure-pod-configmap/), [managing resources](/docs/concepts/cluster-administration/manage-deployment/).
Ingress frequently uses annotations to configure some options depending on the ingress controller, an example of which
Ingress frequently uses annotations to configure some options depending on the Ingress controller, an example of which
is the [rewrite-target annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md).
Different [ingress controller](#ingress-controllers) support different annotations. Review the documentation for
your choice of ingress controller to learn which annotations are supported.
Different [Ingress controller](/docs/concepts/services-networking/ingress-controllers) support different annotations. Review the documentation for
your choice of Ingress controller to learn which annotations are supported.
The ingress [spec](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status)
The Ingress [spec](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status)
has all the information needed to configure a loadbalancer or proxy server. Most importantly, it
contains a list of rules matched against all incoming requests. Ingress resource only supports rules
for directing HTTP traffic.
@@ -144,18 +113,17 @@ Each http rule contains the following information:
loadbalancer will direct traffic to the referenced service.
* A backend is a combination of service and port names as described in the
[services doc](/docs/concepts/services-networking/service/). HTTP (and HTTPS) requests to the
ingress matching the host and path of the rule will be sent to the listed backend.
Ingress matching the host and path of the rule will be sent to the listed backend.
A default backend is often configured in an ingress controller that will service any requests that do not
A default backend is often configured in an Ingress controller that will service any requests that do not
match a path in the spec.
### Default Backend
An ingress with no rules sends all traffic to a single default backend. The default
backend is typically a configuration option of the [ingress controller](#ingress-controllers)
and is not specified in your ingress resources.
An Ingress with no rules sends all traffic to a single default backend. The default
backend is typically a configuration option of the [Ingress controller](/docs/concepts/services-networking/ingress-controllers) and is not specified in your Ingress resources.
If none of the hosts or paths match the HTTP request in the ingress objects, the traffic is
If none of the hosts or paths match the HTTP request in the Ingress objects, the traffic is
routed to your default backend.
## Types of Ingress
@@ -163,7 +131,7 @@ routed to your default backend.
### Single Service Ingress
There are existing Kubernetes concepts that allow you to expose a single Service
(see [alternatives](#alternatives)). You can also do this with an ingress by specifying a
(see [alternatives](#alternatives)). You can also do this with an Ingress by specifying a
*default backend* with no rules.
{{< codenew file="service/networking/ingress.yaml" >}}
@@ -179,8 +147,8 @@ NAME HOSTS ADDRESS PORTS AGE
test-ingress * 107.178.254.228 80 59s
```
Where `107.178.254.228` is the IP allocated by the ingress controller to satisfy
this ingress.
Where `107.178.254.228` is the IP allocated by the Ingress controller to satisfy
this Ingress.
{{< note >}}
Ingress controllers and load balancers may take a minute or two to allocate an IP address.
@@ -190,7 +158,7 @@ Until that time you will often see the address listed as `<pending>`.
### Simple fanout
A fanout configuration routes traffic from a single IP address to more than one service,
based on the HTTP URI being requested. An ingress allows you to keep the number of loadbalancers
based on the HTTP URI being requested. An Ingress allows you to keep the number of loadbalancers
down to a minimum. For example, a setup like:
```shell
@@ -198,7 +166,7 @@ foo.bar.com -> 178.91.123.132 -> / foo service1:4200
/ bar service2:8080
```
would require an ingress such as:
would require an Ingress such as:
```yaml
apiVersion: extensions/v1beta1
@@ -222,7 +190,7 @@ spec:
servicePort: 8080
```
When you create the ingress with `kubectl create -f`:
When you create the Ingress with `kubectl create -f`:
```shell
kubectl describe ingress simple-fanout-example
@@ -247,13 +215,13 @@ Events:
Normal ADD 22s loadbalancer-controller default/test
```
The ingress controller will provision an implementation specific loadbalancer
that satisfies the ingress, as long as the services (`s1`, `s2`) exist.
When it has done so, you will see the address of the loadbalancer at the
The Ingress controller provisions an implementation specific loadbalancer
that satisfies the Ingress, as long as the services (`s1`, `s2`) exist.
When it has done so, you can see the address of the loadbalancer at the
Address field.
{{< note >}}
Depending on the [ingress controller](#ingress-controllers) you are using, you may need to
Depending on the [Ingress controller](/docs/concepts/services-networking/ingress-controllers) you are using, you may need to
create a default-http-backend [Service](/docs/concepts/services-networking/service/).
{{< /note >}}
@@ -267,7 +235,7 @@ foo.bar.com --| |-> foo.bar.com s1:80
bar.foo.com --| |-> bar.foo.com s2:80
```
The following ingress tells the backing loadbalancer to route requests based on
The following Ingress tells the backing loadbalancer to route requests based on
the [Host header](https://tools.ietf.org/html/rfc7230#section-5.4).
```yaml
@@ -291,10 +259,10 @@ spec:
servicePort: 80
```
If you create an ingress resource without any hosts defined in the rules, then any
web traffic to the IP address of your ingress controller can be matched without a name based
virtual host being required. For example, the following ingress resource will route traffic
requested for `first.bar.com` to `service1`, `second.bar.com` to `service2`, and any traffic
If you create an Ingress resource without any hosts defined in the rules, then any
web traffic to the IP address of your Ingress controller can be matched without a name based
virtual host being required. For example, the following Ingress resource will route traffic
requested for `first.bar.com` to `service1`, `second.foo.com` to `service2`, and any traffic
to the IP address without a hostname defined in request (that is, without a request header being
presented) to `service3`.
@@ -326,12 +294,12 @@ spec:
### TLS
You can secure an ingress by specifying a [secret](/docs/concepts/configuration/secret)
that contains a TLS private key and certificate. Currently the ingress only
You can secure an Ingress by specifying a [secret](/docs/concepts/configuration/secret)
that contains a TLS private key and certificate. Currently the Ingress only
supports a single TLS port, 443, and assumes TLS termination. If the TLS
configuration section in an ingress specifies different hosts, they will be
configuration section in an Ingress specifies different hosts, they will be
multiplexed on the same port according to the hostname specified through the
SNI TLS extension (provided the ingress controller supports SNI). The TLS secret
SNI TLS extension (provided the Ingress controller supports SNI). The TLS secret
must contain keys named `tls.crt` and `tls.key` that contain the certificate
and private key to use for TLS, e.g.:
@@ -344,10 +312,10 @@ kind: Secret
metadata:
name: testsecret-tls
namespace: default
type: Opaque
type: kubernetes.io/tls
```
Referencing this secret in an ingress will tell the ingress controller to
Referencing this secret in an Ingress will tell the Ingress controller to
secure the channel from the client to the loadbalancer using TLS. You need to make
sure the TLS secret you created came from a certificate that contains a CN
for `sslexample.foo.com`.
@@ -373,24 +341,24 @@ spec:
```
{{< note >}}
There is a gap between TLS features supported by various ingress
There is a gap between TLS features supported by various Ingress
controllers. Please refer to documentation on
[nginx](https://git.k8s.io/ingress-nginx/README.md#https),
[GCE](https://git.k8s.io/ingress-gce/README.md#frontend-https), or any other
platform specific ingress controller to understand how TLS works in your environment.
platform specific Ingress controller to understand how TLS works in your environment.
{{< /note >}}
### Loadbalancing
An ingress controller is bootstrapped with some load balancing policy settings
that it applies to all ingress, such as the load balancing algorithm, backend
An Ingress controller is bootstrapped with some load balancing policy settings
that it applies to all Ingress, such as the load balancing algorithm, backend
weight scheme, and others. More advanced load balancing concepts
(e.g. persistent sessions, dynamic weights) are not yet exposed through the
ingress. You can still get these features through the
Ingress. You can still get these features through the
[service loadbalancer](https://github.com/kubernetes/ingress-nginx).
It's also worth noting that even though health checks are not exposed directly
through the ingress, there exist parallel concepts in Kubernetes such as
through the Ingress, there exist parallel concepts in Kubernetes such as
[readiness probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/)
which allow you to achieve the same end result. Please review the controller
specific docs to see how they handle health checks (
@@ -399,7 +367,7 @@ specific docs to see how they handle health checks (
## Updating an Ingress
To update an existing ingress to add a new Host, you can update it by editing the resource:
To update an existing Ingress to add a new Host, you can update it by editing the resource:
```shell
kubectl describe ingress test
@@ -450,7 +418,7 @@ spec:
```
Saving the yaml will update the resource in the API server, which should tell the
ingress controller to reconfigure the loadbalancer.
Ingress controller to reconfigure the loadbalancer.
```shell
kubectl describe ingress test
@@ -476,25 +444,24 @@ Events:
Normal ADD 45s loadbalancer-controller default/test
```
You can achieve the same by invoking `kubectl replace -f` on a modified ingress yaml file.
You can achieve the same by invoking `kubectl replace -f` on a modified Ingress yaml file.
## Failing across availability zones
Techniques for spreading traffic across failure domains differs between cloud providers.
Please check the documentation of the relevant [ingress controller](#ingress-controllers) for
details. You can also refer to the [federation documentation](/docs/concepts/cluster-administration/federation/)
for details on deploying ingress in a federated cluster.
Please check the documentation of the relevant [Ingress controller](/docs/concepts/services-networking/ingress-controllers) for details. You can also refer to the [federation documentation](/docs/concepts/cluster-administration/federation/)
for details on deploying Ingress in a federated cluster.
## Future Work
Track [SIG Network](https://github.com/kubernetes/community/tree/master/sig-network)
for more details on the evolution of the ingress and related resources. You may also track the
[ingress repository](https://github.com/kubernetes/ingress/tree/master) for more details on the
evolution of various ingress controllers.
[Ingress repository](https://github.com/kubernetes/ingress/tree/master) for more details on the
evolution of various Ingress controllers.
## Alternatives
You can expose a Service in multiple ways that don't directly involve the ingress resource:
You can expose a Service in multiple ways that don't directly involve the Ingress resource:
* Use [Service.Type=LoadBalancer](/docs/concepts/services-networking/service/#loadbalancer)
* Use [Service.Type=NodePort](/docs/concepts/services-networking/service/#nodeport)
@@ -503,6 +470,5 @@ You can expose a Service in multiple ways that don't directly involve the ingres
{{% /capture %}}
{{% capture whatsnext %}}
* [Set up Ingress on Minikube with the NGINX Controller](/docs/tasks/access-application-cluster/ingress-minikube)
{{% /capture %}}
@@ -92,11 +92,12 @@ __egress__: Each `NetworkPolicy` may include a list of whitelist `egress` rules.
So, the example NetworkPolicy:
1. isolates "role=db" pods in the "default" namespace for both ingress and egress traffic (if they weren't already isolated)
2. allows connections to TCP port 6379 of "role=db" pods in the "default" namespace from:
2. (Ingress rules) allows connections to all pods in the default namespace with the label “role=db” on TCP port 6379 from:
* any pod in the "default" namespace with the label "role=frontend"
* any pod in a namespace with the label "project=myproject"
* IP addresses in the ranges 172.17.0.0172.17.0.255 and 172.17.2.0172.17.255.255 (ie, all of 172.17.0.0/16 except 172.17.1.0/24)
3. allows connections from any pod in the "default" namespace with the label "role=db" to CIDR 10.0.0.0/24 on TCP port 5978
3. (Egress rules) allows connections from any pod in the "default" namespace with the label "role=db" to CIDR 10.0.0.0/24 on TCP port 5978
See the [Declare Network Policy](/docs/tasks/administer-cluster/declare-network-policy/) walkthrough for further examples.
@@ -191,6 +192,8 @@ spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress
```
### Default deny all egress traffic
@@ -264,4 +267,3 @@ The CNI plugin has to support SCTP as `protocol` value in `NetworkPolicy`.
- See more [Recipes](https://github.com/ahmetb/kubernetes-network-policy-recipes) for common scenarios enabled by the NetworkPolicy resource.
{{% /capture %}}
@@ -83,12 +83,9 @@ deploying and evolving your `Services`. For example, you can change the port
number that pods expose in the next version of your backend software, without
breaking clients.
Kubernetes `Services` support `TCP`, `UDP` and `SCTP` for protocols. The default
is `TCP`.
{{< note >}}
SCTP support is an alpha feature since Kubernetes 1.12
{{< /note >}}
`TCP` is the default protocol for services, and you can also use any other
[supported protocol](#protocol-support). At the moment, you can only set a
single `port` and `protocol` for a Service.
### Services without selectors
@@ -519,6 +516,16 @@ metadata:
[...]
```
{{% /tab %}}
{{% tab name="Baidu Cloud" %}}
```yaml
[...]
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/cce-load-balancer-internal-vpc: "true"
[...]
```
{{% /tab %}}
{{< /tabs >}}
@@ -758,13 +765,10 @@ for supported instance types.
### Type ExternalName {#externalname}
{{< note >}}
ExternalName Services are available only with `kube-dns` version 1.7 and later.
{{< /note >}}
Services of type ExternalName map a service to a DNS name, not to a typical selector such as
`my-service` or `cassandra`. You specify these services with the `spec.externalName` parameter.
Services of type ExternalName map a service to a DNS name (specified using
the `spec.externalName` parameter) rather than to a typical selector like
`my-service` or `cassandra`. This Service definition, for example, would map
This Service definition, for example, maps
the `my-service` Service in the `prod` namespace to `my.database.example.com`:
```yaml
@@ -777,6 +781,10 @@ spec:
type: ExternalName
externalName: my.database.example.com
```
{{< note >}}
ExternalName accepts an IPv4 address string, but as a DNS name comprised of digits, not as an IP address. ExternalNames that resemble IPv4 addresses are not resolved by CoreDNS or ingress-nginx because ExternalName
is intended to specify a canonical DNS name. To hardcode an IP address, consider headless services.
{{< /note >}}
When looking up the host `my-service.prod.svc.cluster.local`, the cluster DNS service
will return a `CNAME` record with the value `my.database.example.com`. Accessing
@@ -933,29 +941,74 @@ Service is a top-level resource in the Kubernetes REST API. More details about t
API object can be found at:
[Service API object](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core).
## SCTP support
## Supported protocols {#protocol-support}
### TCP
{{< feature-state for_k8s_version="v1.0" state="stable" >}}
You can use TCP for any kind of service, and it's the default network protocol.
### UDP
{{< feature-state for_k8s_version="v1.0" state="stable" >}}
You can use UDP for most services. For type=LoadBalancer services, UDP support
depends on the cloud provider offering this facility.
### HTTP
{{< feature-state for_k8s_version="v1.1" state="stable" >}}
If your cloud provider supports it, you can use a Service in LoadBalancer mode
to set up external HTTP / HTTPS reverse proxying, forwarded to the Endpoints
of the Service.
{{< note >}}
You can also use {{< glossary_tooltip term_id="ingress" >}} in place of Service
to expose HTTP / HTTPS services.
{{< /note >}}
### PROXY protocol
{{< feature-state for_k8s_version="v1.1" state="stable" >}}
If your cloud provider supports it (eg, [AWS](https://kubernetes.io/docs/concepts/cluster-administration/cloud-providers/#aws)),
you can use a Service in LoadBalancer mode to configure a load balancer outside
of Kubernetes itself, that will forward connections prefixed with
[PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt).
The load balancer will send an initial series of octets describing the
incoming connection, similar to this example
```
PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
```
followed by the data from the client.
### SCTP
{{< feature-state for_k8s_version="v1.12" state="alpha" >}}
Kubernetes supports SCTP as a `protocol` value in `Service`, `Endpoint`, `NetworkPolicy` and `Pod` definitions as an alpha feature. To enable this feature, the cluster administrator needs to enable the `SCTPSupport` feature gate on the apiserver, for example, `“--feature-gates=SCTPSupport=true,...”`. When the feature gate is enabled, users can set the `protocol` field of a `Service`, `Endpoint`, `NetworkPolicy` and `Pod` to `SCTP`. Kubernetes sets up the network accordingly for the SCTP associations, just like it does for TCP connections.
### Warnings
#### Warnings {#caveat-sctp-overview}
#### The support of multihomed SCTP associations
##### Support for multihomed SCTP associations {#caveat-sctp-multihomed}
The support of multihomed SCTP associations requires that the CNI plugin can support the assignment of multiple interfaces and IP addresses to a `Pod`.
NAT for multihomed SCTP associations requires special logic in the corresponding kernel modules.
#### Service with type=LoadBalancer
##### Service with type=LoadBalancer {#caveat-sctp-loadbalancer-service-type}
A `Service` with `type` LoadBalancer and `protocol` SCTP can be created only if the cloud provider's load balancer implementation supports SCTP as a protocol. Otherwise the `Service` creation request is rejected. The current set of cloud load balancer providers (`Azure`, `AWS`, `CloudStack`, `GCE`, `OpenStack`) do not support SCTP.
#### Windows
##### Windows {#caveat-sctp-windows-os}
SCTP is not supported on Windows based nodes.
#### Userspace kube-proxy
##### Userspace kube-proxy {#caveat-sctp-kube-proxy-userspace}
The kube-proxy does not support the management of SCTP associations when it is in userspace mode.
@@ -309,9 +309,7 @@ Currently, storage size is the only resource that can be set or requested. Futu
### Volume Mode
{{< feature-state for_k8s_version="v1.9" state="alpha" >}}
To enable this feature, enable the `BlockVolume` feature gate on the apiserver, controller-manager and the kubelet.
{{< feature-state for_k8s_version="v1.13" state="beta" >}}
Prior to Kubernetes 1.9, all volume plugins created a filesystem on the persistent volume.
Now, you can set the value of `volumeMode` to `raw` to use a raw block device, or `filesystem`
@@ -461,7 +459,7 @@ Claims use the same conventions as volumes when requesting storage with specific
### Volume Modes
Claims use the same convention as volumes to indicates the consumption of the volume as either a filesystem or block device.
Claims use the same convention as volumes to indicate the consumption of the volume as either a filesystem or block device.
### Resources
@@ -548,10 +546,7 @@ spec:
## Raw Block Volume Support
{{< feature-state for_k8s_version="v1.9" state="alpha" >}}
To enable support for raw block volumes, enable the `BlockVolume` feature gate on the
apiserver, controller-manager and the kubelet.
{{< feature-state for_k8s_version="v1.13" state="beta" >}}
The following volume plugins support raw block volumes, including dynamic provisioning where
applicable.
@@ -153,7 +153,7 @@ The following plugins support `WaitForFirstConsumer` with pre-created Persistent
### Allowed Topologies
When a cluster operactor specifies the `WaitForFirstConsumer` volume binding mode, it is no longer necessary
When a cluster operator specifies the `WaitForFirstConsumer` volume binding mode, it is no longer necessary
to restrict provisioning to specific topologies in most situations. However,
if still required, `allowedTopologies` can be specified.
@@ -627,13 +627,13 @@ parameters:
```
* `fs`: filesystem to be laid out: [none/xfs/ext4] (default: `ext4`).
* `fs`: filesystem to be laid out: `none/xfs/ext4` (default: `ext4`).
* `block_size`: block size in Kbytes (default: `32`).
* `repl`: number of synchronous replicas to be provided in the form of
replication factor [1..3] (default: `1`) A string is expected here i.e.
replication factor `1..3` (default: `1`) A string is expected here i.e.
`"1"` and not `1`.
* `io_priority`: determines whether the volume will be created from higher
performance or a lower priority storage [high/medium/low] (default: `low`).
performance or a lower priority storage `high/medium/low` (default: `low`).
* `snap_interval`: clock/time interval in minutes for when to trigger snapshots.
Snapshots are incremental based on difference with the prior snapshot, 0
disables snaps (default: `0`). A string is expected here i.e.
@@ -644,7 +644,7 @@ parameters:
* `ephemeral`: specifies whether the volume should be cleaned-up after unmount
or should be persistent. `emptyDir` use case can set this value to true and
`persistent volumes` use case such as for databases like Cassandra should set
to false, [true/false] (default `false`). A string is expected here i.e.
to false, `true/false` (default `false`). A string is expected here i.e.
`"true"` and not `true`.
### ScaleIO
+11 -9
View File
@@ -75,6 +75,7 @@ Kubernetes supports several types of Volumes:
* [downwardAPI](#downwardapi)
* [emptyDir](#emptydir)
* [fc (fibre channel)](#fc)
* [flexVolume](#flexVolume)
* [flocker](#flocker)
* [gcePersistentDisk](#gcepersistentdisk)
* [gitRepo (deprecated)](#gitrepo)
@@ -789,9 +790,8 @@ receive updates for those volume sources.
### portworxVolume {#portworxvolume}
A `portworxVolume` is an elastic block storage layer that runs hyperconverged with
Kubernetes. Portworx fingerprints storage in a server, tiers based on capabilities,
and aggregates capacity across multiple servers. Portworx runs in-guest in virtual
machines or on bare metal Linux nodes.
Kubernetes. [Portworx](https://portworx.com/use-case/kubernetes-storage/) fingerprints storage in a server, tiers based on capabilities,
and aggregates capacity across multiple servers. Portworx runs in-guest in virtual machines or on bare metal Linux nodes.
A `portworxVolume` can be dynamically created through Kubernetes or it can also
be pre-provisioned and referenced inside a Kubernetes Pod.
@@ -834,7 +834,9 @@ You must have your own Quobyte setup running with the volumes
created before you can use it.
{{< /caution >}}
See the [Quobyte example](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/volumes/quobyte) for more details.
Quobyte supports the {{< glossary_tooltip text="Container Storage Interface" term_id="csi" >}}.
CSI is the recommended plugin to use Quobyte volumes inside Kubernetes. Quobyte's
GitHub project has [instructions](https://github.com/quobyte/quobyte-csi#quobyte-csi) for deploying Quobyte using CSI, along with examples.
### rbd {#rbd}
@@ -1149,12 +1151,12 @@ CSI support was introduced as alpha in Kubernetes v1.9, moved to beta in
Kubernetes v1.10, and is GA in Kubernetes v1.13.
{{< note >}}
**Note:** Support for CSI spec versions 0.2 and 0.3 are deprecated in Kubernetes
Support for CSI spec versions 0.2 and 0.3 are deprecated in Kubernetes
v1.13 and will be removed in a future release.
{{< /note >}}
{{< note >}}
**Note:** CSI drivers may not be compatible across all Kubernetes releases.
CSI drivers may not be compatible across all Kubernetes releases.
Please check the specific CSI driver's documentation for supported
deployments steps for each Kubernetes release and a compatibility matrix.
{{< /note >}}
@@ -1237,7 +1239,7 @@ Learn how to
For more information on how to develop a CSI driver, refer to the [kubernetes-csi
documentation](https://kubernetes-csi.github.io/docs/)
### Flexvolume
### Flexvolume {#flexVolume}
Flexvolume is an out-of-tree plugin interface that has existed in Kubernetes
since version 1.2 (before CSI). It uses an exec-based model to interface with
@@ -1305,8 +1307,8 @@ MountFlags=shared
```
Or, remove `MountFlags=slave` if present. Then restart the Docker daemon:
```shell
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
sudo systemctl daemon-reload
sudo systemctl restart docker
```
@@ -16,7 +16,7 @@ One CronJob object is like one line of a _crontab_ (cron table) file. It runs a
on a given schedule, written in [Cron](https://en.wikipedia.org/wiki/Cron) format.
{{< note >}}
All **CronJob** `schedule:` times are denoted in UTC.
All **CronJob** `schedule:` times are based the timezone of the master where the job is initiated.
{{< /note >}}
For instructions on creating and working with cron jobs, and for an example of a spec file for a cron job, see [Running automated tasks with cron jobs](/docs/tasks/job/automated-tasks-with-cron-jobs).
@@ -46,11 +46,13 @@ It is important to note that if the `startingDeadlineSeconds` field is set (not
A CronJob is counted as missed if it has failed to be created at its scheduled time. For example, If `concurrencyPolicy` is set to `Forbid` and a CronJob was attempted to be scheduled when there was a previous schedule still running, then it would count as missed.
For example, suppose a cron job is set to start at exactly `08:30:00` and its
`startingDeadlineSeconds` is set to 10, if the CronJob controller happens to
be down from `08:29:00` to `08:42:00`, the job will not start.
Set a longer `startingDeadlineSeconds` if starting later is better than not
starting at all.
For example, suppose a CronJob is set to schedule a new Job every one minute beginning at `08:30:00`, and its
`startingDeadlineSeconds` field is not set. The default for this field is `100` seconds. If the CronJob controller happens to
be down from `08:29:00` to `10:21:00`, the job will not start as the number of missed jobs which missed their schedule is greater than 100.
To illustrate this concept further, suppose a CronJob is set to schedule a new Job every one minute beginning at `08:30:00`, and its
`startingDeadlineSeconds` is set to 200 seconds. If the CronJob controller happens to
be down for the same period as the previous example (`08:29:00` to `10:21:00`,) the Job will still start at 10:22:00. This happens as the controller now checks how many missed schedules happened in the last 200 seconds (ie, 3 missed schedules), rather than from the last scheduled time until now.
The Cronjob is only responsible for creating Jobs that match its schedule, and
the Job in turn is responsible for the management of the Pods it represents.
@@ -21,7 +21,7 @@ Some typical uses of a DaemonSet are:
- running a cluster storage daemon, such as `glusterd`, `ceph`, on each node.
- running a logs collection daemon on every node, such as `fluentd` or `logstash`.
- running a node monitoring daemon on every node, such as [Prometheus Node Exporter](
https://github.com/prometheus/node_exporter), `collectd`, [Dynatrace OneAgent](https://www.dynatrace.com/technologies/kubernetes-monitoring/), Datadog agent, New Relic agent, Ganglia `gmond` or Instana agent.
https://github.com/prometheus/node_exporter), `collectd`, [Dynatrace OneAgent](https://www.dynatrace.com/technologies/kubernetes-monitoring/), [AppDynamics Agent](https://docs.appdynamics.com/display/CLOUD/Container+Visibility+with+Kubernetes), [Datadog agent](https://docs.datadoghq.com/agent/kubernetes/daemonset_setup/), [New Relic agent](https://docs.newrelic.com/docs/integrations/kubernetes-integration/installation/kubernetes-installation-configuration), Ganglia `gmond` or Instana agent.
In a simple case, one DaemonSet, covering all nodes, would be used for each type of daemon.
A more complex setup might use multiple DaemonSets for a single type of daemon, but with
@@ -40,7 +40,6 @@ The following are typical use cases for Deployments:
* [Use the status of the Deployment](#deployment-status) as an indicator that a rollout has stuck.
* [Clean up older ReplicaSets](#clean-up-policy) that you don't need anymore.
## Creating a Deployment
The following is an example of a Deployment. It creates a ReplicaSet to bring up three `nginx` Pods:
@@ -55,9 +54,9 @@ In this example:
In this case, you simply select a label that is defined in the Pod template (`app: nginx`).
However, more sophisticated selection rules are possible,
as long as the Pod template itself satisfies the rule.
{{< note >}}
`matchLabels` is a map of {key,value} pairs. A single {key,value} in the `matchLabels` map
`matchLabels` is a map of {key,value} pairs. A single {key,value} in the `matchLabels` map
is equivalent to an element of `matchExpressions`, whose key field is "key", the operator is "In",
and the values array contains only "value". The requirements are ANDed.
{{< /note >}}
@@ -66,9 +65,9 @@ In this example:
* The Pods are labeled `app: nginx`using the `labels` field.
* The Pod template's specification, or `.template.spec` field, indicates that
the Pods run one container, `nginx`, which runs the `nginx`
[Docker Hub](https://hub.docker.com/) image at version 1.15.4.
[Docker Hub](https://hub.docker.com/) image at version 1.7.9.
* Create one container and name it `nginx` using the `name` field.
* Run the `nginx` image at version `1.15.4`.
* Run the `nginx` image at version `1.7.9`.
* Open port `80` so that the container can send and accept traffic.
To create this Deployment, run the following command:
@@ -128,18 +127,19 @@ To see the ReplicaSet (`rs`) created by the deployment, run `kubectl get rs`:
```shell
NAME DESIRED CURRENT READY AGE
nginx-deployment-2035384211 3 3 3 18s
nginx-deployment-75675f5897 3 3 3 18s
```
Notice that the name of the ReplicaSet is always formatted as `[DEPLOYMENT-NAME]-[POD-TEMPLATE-HASH-VALUE]`. The hash value is automatically generated when the Deployment is created.
Notice that the name of the ReplicaSet is always formatted as `[DEPLOYMENT-NAME]-[RANDOM-STRING]`. The random string is
randomly generated and uses the pod-template-hash as a seed.
To see the labels automatically generated for each pod, run `kubectl get pods --show-labels`. The following output is returned:
```shell
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-2035384211-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
```
The created ReplicaSet ensures that there are three `nginx` Pods running at all times.
@@ -171,21 +171,27 @@ Suppose that you now want to update the nginx Pods to use the `nginx:1.9.1` imag
instead of the `nginx:1.7.9` image.
```shell
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1 --record
deployment.apps/nginx-deployment image updated
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
```
```
image updated
```
Alternatively, you can `edit` the Deployment and change `.spec.template.spec.containers[0].image` from `nginx:1.7.9` to `nginx:1.9.1`:
```shell
$ kubectl edit deployment.v1.apps/nginx-deployment
kubectl edit deployment.v1.apps/nginx-deployment
```
```
deployment.apps/nginx-deployment edited
```
To see the rollout status, run:
```shell
$ kubectl rollout status deployment.v1.apps/nginx-deployment
kubectl rollout status deployment.v1.apps/nginx-deployment
```
```
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment.apps/nginx-deployment successfully rolled out
```
@@ -193,7 +199,9 @@ deployment.apps/nginx-deployment successfully rolled out
After the rollout succeeds, you may want to `get` the Deployment:
```shell
$ kubectl get deployments
kubectl get deployments
```
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 36s
```
@@ -206,7 +214,9 @@ You can run `kubectl get rs` to see that the Deployment updated the Pods by crea
up to 3 replicas, as well as scaling down the old ReplicaSet to 0 replicas.
```shell
$ kubectl get rs
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 6s
nginx-deployment-2035384211 0 0 0 36s
@@ -215,7 +225,9 @@ nginx-deployment-2035384211 0 0 0 36s
Running `get pods` should now show only the new Pods:
```shell
$ kubectl get pods
kubectl get pods
```
```
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-khku8 1/1 Running 0 14s
nginx-deployment-1564180365-nacti 1/1 Running 0 14s
@@ -236,7 +248,9 @@ new Pods have come up, and does not create new Pods until a sufficient number of
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
kubectl describe deployments
```
```
Name: nginx-deployment
Namespace: default
CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000
@@ -337,14 +351,18 @@ rolled back.
Suppose that you made a typo while updating the Deployment, by putting the image name as `nginx:1.91` instead of `nginx:1.9.1`:
```shell
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.91 --record=true
```
```
deployment.apps/nginx-deployment image updated
```
The rollout will be stuck.
```shell
$ kubectl rollout status deployment.v1.apps/nginx-deployment
kubectl rollout status deployment.v1.apps/nginx-deployment
```
```
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
```
@@ -354,7 +372,9 @@ Press Ctrl-C to stop the above rollout status watch. For more information on stu
You will see that the number of old replicas (nginx-deployment-1564180365 and nginx-deployment-2035384211) is 2, and new replicas (nginx-deployment-3066724191) is 1.
```shell
$ kubectl get rs
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 25s
nginx-deployment-2035384211 0 0 0 36s
@@ -364,7 +384,9 @@ nginx-deployment-3066724191 1 1 0 6s
Looking at the Pods created, you will see that 1 Pod created by new ReplicaSet is stuck in an image pull loop.
```shell
$ kubectl get pods
kubectl get pods
```
```
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
@@ -379,7 +401,9 @@ Kubernetes by default sets the value to 25%.
{{< /note >}}
```shell
$ kubectl describe deployment
kubectl describe deployment
```
```
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
@@ -426,7 +450,9 @@ To fix this, you need to rollback to a previous revision of Deployment that is s
First, check the revisions of this deployment:
```shell
$ kubectl rollout history deployment.v1.apps/nginx-deployment
kubectl rollout history deployment.v1.apps/nginx-deployment
```
```
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 kubectl create --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml --record=true
@@ -442,7 +468,9 @@ REVISION CHANGE-CAUSE
To further see the details of each revision, run:
```shell
$ kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
kubectl rollout history deployment.v1.apps/nginx-deployment --revision=2
```
```
deployments "nginx-deployment" revision 2
Labels: app=nginx
pod-template-hash=1159050644
@@ -463,14 +491,18 @@ deployments "nginx-deployment" revision 2
Now you've decided to undo the current rollout and rollback to the previous revision:
```shell
$ kubectl rollout undo deployment.v1.apps/nginx-deployment
kubectl rollout undo deployment.v1.apps/nginx-deployment
```
```
deployment.apps/nginx-deployment
```
Alternatively, you can rollback to a specific revision by specify that in `--to-revision`:
Alternatively, you can rollback to a specific revision by specifying it with `--to-revision`:
```shell
$ kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
```
```
deployment.apps/nginx-deployment
```
@@ -480,11 +512,17 @@ The Deployment is now rolled back to a previous stable revision. As you can see,
for rolling back to revision 2 is generated from Deployment controller.
```shell
$ kubectl get deployment nginx-deployment
kubectl get deployment nginx-deployment
```
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 30m
```
$ kubectl describe deployment nginx-deployment
```shell
kubectl describe deployment nginx-deployment
```
```
Name: nginx-deployment
Namespace: default
CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500
@@ -533,7 +571,9 @@ Events:
You can scale a Deployment by using the following command:
```shell
$ kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
```
```
deployment.apps/nginx-deployment scaled
```
@@ -542,7 +582,9 @@ in your cluster, you can setup an autoscaler for your Deployment and choose the
Pods you want to run based on the CPU utilization of your existing Pods.
```shell
$ kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
kubectl autoscale deployment.v1.apps/nginx-deployment --min=10 --max=15 --cpu-percent=80
```
```
deployment.apps/nginx-deployment scaled
```
@@ -556,7 +598,9 @@ ReplicaSets (ReplicaSets with Pods) in order to mitigate risk. This is called *p
For example, you are running a Deployment with 10 replicas, [maxSurge](#max-surge)=3, and [maxUnavailable](#max-unavailable)=2.
```shell
$ kubectl get deploy
kubectl get deploy
```
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
```
@@ -564,7 +608,9 @@ nginx-deployment 10 10 10 10 50s
You update to a new image which happens to be unresolvable from inside the cluster.
```shell
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:sometag
```
```
deployment.apps/nginx-deployment image updated
```
@@ -572,7 +618,9 @@ The image update starts a new rollout with ReplicaSet nginx-deployment-198919819
`maxUnavailable` requirement that you mentioned above.
```shell
$ kubectl get rs
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m
@@ -590,10 +638,17 @@ new ReplicaSet. The rollout process should eventually move all replicas to the n
the new replicas become healthy.
```shell
$ kubectl get deploy
kubectl get deploy
```
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
$ kubectl get rs
```
```shell
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
@@ -607,10 +662,16 @@ apply multiple fixes in between pausing and resuming without triggering unnecess
For example, with a Deployment that was just created:
```shell
$ kubectl get deploy
kubectl get deploy
```
```
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 1m
$ kubectl get rs
```
```shell
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 1m
```
@@ -618,26 +679,36 @@ nginx-2142116321 3 3 3 1m
Pause by running the following command:
```shell
$ kubectl rollout pause deployment.v1.apps/nginx-deployment
kubectl rollout pause deployment.v1.apps/nginx-deployment
```
```
deployment.apps/nginx-deployment paused
```
Then update the image of the Deployment:
```shell
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.9.1
```
```
deployment.apps/nginx-deployment image updated
```
Notice that no new rollout started:
```shell
$ kubectl rollout history deployment.v1.apps/nginx-deployment
kubectl rollout history deployment.v1.apps/nginx-deployment
```
```
deployments "nginx"
REVISION CHANGE-CAUSE
1 <none>
```
$ kubectl get rs
```shell
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 2m
```
@@ -645,7 +716,9 @@ nginx-2142116321 3 3 3 2m
You can make as many updates as you wish, for example, update the resources that will be used:
```shell
$ kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
```
```
deployment.apps/nginx-deployment resource requirements updated
```
@@ -655,9 +728,18 @@ the Deployment will not have any effect as long as the Deployment is paused.
Eventually, resume the Deployment and observe a new ReplicaSet coming up with all the new updates:
```shell
$ kubectl rollout resume deployment.v1.apps/nginx-deployment
kubectl rollout resume deployment.v1.apps/nginx-deployment
```
```
deployment.apps/nginx-deployment resumed
$ kubectl get rs -w
```
```shell
kubectl get rs -w
```
```
NAME DESIRED CURRENT READY AGE
nginx-2142116321 2 2 2 2m
nginx-3926361531 2 2 0 6s
@@ -673,8 +755,12 @@ nginx-2142116321 0 1 1 2m
nginx-2142116321 0 1 1 2m
nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 20s
^C
$ kubectl get rs
```
```shell
kubectl get rs
```
```
NAME DESIRED CURRENT READY AGE
nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 28s
@@ -713,7 +799,9 @@ You can check if a Deployment has completed by using `kubectl rollout status`. I
successfully, `kubectl rollout status` returns a zero exit code.
```shell
$ kubectl rollout status deployment.v1.apps/nginx-deployment
kubectl rollout status deployment.v1.apps/nginx-deployment
```
```
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment.apps/nginx-deployment successfully rolled out
$ echo $?
@@ -741,7 +829,9 @@ The following `kubectl` command sets the spec with `progressDeadlineSeconds` to
lack of progress for a Deployment after 10 minutes:
```shell
$ kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
kubectl patch deployment.v1.apps/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
```
```
deployment.apps/nginx-deployment patched
```
Once the deadline has been exceeded, the Deployment controller adds a DeploymentCondition with the following
@@ -770,7 +860,9 @@ due to any other kind of error that can be treated as transient. For example, le
insufficient quota. If you describe the Deployment you will notice the following section:
```shell
$ kubectl describe deployment nginx-deployment
kubectl describe deployment nginx-deployment
```
```
<...>
Conditions:
Type Status Reason
@@ -846,7 +938,9 @@ You can check if a Deployment has failed to progress by using `kubectl rollout s
returns a non-zero exit code if the Deployment has exceeded the progression deadline.
```shell
$ kubectl rollout status deployment.v1.apps/nginx-deployment
kubectl rollout status deployment.v1.apps/nginx-deployment
```
```
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
@@ -988,15 +1082,12 @@ Field `.spec.rollbackTo` has been deprecated in API versions `extensions/v1beta1
### Revision History Limit
A Deployment's revision history is stored in the replica sets it controls.
A Deployment's revision history is stored in the ReplicaSets it controls.
`.spec.revisionHistoryLimit` is an optional field that specifies the number of old ReplicaSets to retain
to allow rollback. Its ideal value depends on the frequency and stability of new Deployments. All old
ReplicaSets will be kept by default, consuming resources in `etcd` and crowding the output of `kubectl get rs`,
if this field is not set. The configuration of each Deployment revision is stored in its ReplicaSets;
therefore, once an old ReplicaSet is deleted, you lose the ability to rollback to that revision of Deployment.
to allow rollback. These old ReplicaSets consume resources in `etcd` and crowd the output of `kubectl get rs`. The configuration of each Deployment revision is stored in its ReplicaSets; therefore, once an old ReplicaSet is deleted, you lose the ability to rollback to that revision of Deployment. By default, 10 old ReplicaSets will be kept, however its ideal value depends on the frequency and stability of new Deployments.
More specifically, setting this field to zero means that all old ReplicaSets with 0 replica will be cleaned up.
More specifically, setting this field to zero means that all old ReplicaSets with 0 replicas will be cleaned up.
In this case, a new Deployment rollout cannot be undone, since its revision history is cleaned up.
### Paused
@@ -1015,5 +1106,3 @@ in a similar fashion. But Deployments are recommended, since they are declarativ
additional features, such as rolling back to any previous revision even after the rolling update is done.
{{% /capture %}}
@@ -60,6 +60,14 @@ metadata:
...
```
{{< note >}}
Cross-namespace owner references is disallowed by design. This means:
1) Namespace-scoped dependents can only specify owners in the same namespace,
and owners that are cluster-scoped.
2) Cluster-scoped dependents can only specify cluster-scoped owners, but not
namespace-scoped owners.
{{< /note >}}
## Controlling how the garbage collector deletes dependents
When you delete an object, you can specify whether the object's dependents are
@@ -13,16 +13,16 @@ weight: 70
{{% capture overview %}}
A _job_ creates one or more pods and ensures that a specified number of them successfully terminate.
As pods successfully complete, the _job_ tracks the successful completions. When a specified number
of successful completions is reached, the job itself is complete. Deleting a Job will cleanup the
pods it created.
A Job creates one or more Pods and ensures that a specified number of them successfully terminate.
As pods successfully complete, the Job tracks the successful completions. When a specified number
of successful completions is reached, the task (ie, Job) is complete. Deleting a Job will clean up
the Pods it created.
A simple case is to create one Job object in order to reliably run one Pod to completion.
The Job object will start a new Pod if the first pod fails or is deleted (for example
The Job object will start a new Pod if the first Pod fails or is deleted (for example
due to a node hardware failure or a node reboot).
A Job can also be used to run multiple pods in parallel.
You can also use a Job to run multiple Pods in parallel.
{{% /capture %}}
@@ -36,17 +36,21 @@ It takes around 10s to complete.
{{< codenew file="controllers/job.yaml" >}}
Run the example job by downloading the example file and then running this command:
You can run the example with this command:
```shell
$ kubectl create -f https://k8s.io/examples/controllers/job.yaml
kubectl create -f https://k8s.io/examples/controllers/job.yaml
```
```
job "pi" created
```
Check on the status of the job using this command:
Check on the status of the Job with `kubectl`:
```shell
$ kubectl describe jobs/pi
kubectl describe jobs/pi
```
```
Name: pi
Namespace: default
Selector: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
@@ -78,18 +82,20 @@ Events:
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: pi-dtn4q
```
To view completed pods of a job, use `kubectl get pods`.
To view completed Pods of a Job, use `kubectl get pods`.
To list all the pods that belong to a job in a machine readable form, you can use a command like this:
To list all the Pods that belong to a Job in a machine readable form, you can use a command like this:
```shell
$ pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath={.items..metadata.name})
$ echo $pods
pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods
```
```
pi-aiw0a
```
Here, the selector is the same as the selector for the job. The `--output=jsonpath` option specifies an expression
that just gets the name from each pod in the returned list.
Here, the selector is the same as the selector for the Job. The `--output=jsonpath` option specifies an expression
that just gets the name from each Pod in the returned list.
View the standard output of one of the pods:
@@ -102,7 +108,7 @@ $ kubectl logs $pods
As with all other Kubernetes config, a Job needs `apiVersion`, `kind`, and `metadata` fields.
A Job also needs a [`.spec` section](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status).
A Job also needs a [`.spec` section](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
### Pod Template
@@ -110,7 +116,7 @@ The `.spec.template` is the only required field of the `.spec`.
The `.spec.template` is a [pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly 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 job must specify appropriate
In addition to required fields for a Pod, a pod template in a Job must specify appropriate
labels (see [pod selector](#pod-selector)) and an appropriate restart policy.
Only a [`RestartPolicy`](/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy) equal to `Never` or `OnFailure` is allowed.
@@ -123,31 +129,30 @@ See section [specifying your own pod selector](#specifying-your-own-pod-selector
### Parallel Jobs
There are three main types of jobs:
There are three main types of task suitable to run as a Job:
1. Non-parallel Jobs
- normally only one pod is started, unless the pod fails.
- job is complete as soon as Pod terminates successfully.
- normally, only one Pod is started, unless the Pod fails.
- the Job is complete as soon as its Pod terminates successfully.
1. Parallel Jobs with a *fixed completion count*:
- specify a non-zero positive value for `.spec.completions`.
- the job is complete when there is one successful pod for each value in the range 1 to `.spec.completions`.
- **not implemented yet:** Each pod passed a different index in the range 1 to `.spec.completions`.
- the Job represents the overall task, and is complete when there is one successful Pod for each value in the range 1 to `.spec.completions`.
- **not implemented yet:** Each Pod is passed a different index in the range 1 to `.spec.completions`.
1. Parallel Jobs with a *work queue*:
 - do not specify `.spec.completions`, default to `.spec.parallelism`.
 - the pods must coordinate with themselves or an external service to determine what each should work on.
- each pod is independently capable of determining whether or not all its peers are done, thus the entire Job is done.
- when _any_ pod terminates with success, no new pods are created.
- once at least one pod has terminated with success and all pods are terminated, then the job is completed with success.
- once any pod has exited with success, no other pod should still be doing any work or writing any output. They should all be
in the process of exiting.
- do not specify `.spec.completions`, default to `.spec.parallelism`.
- the Pods must coordinate amongst themselves or an external service to determine what each should work on. For example, a Pod might fetch a batch of up to N items from the work queue.
- each Pod is independently capable of determining whether or not all its peers are done, and thus that the entire Job is done.
- when _any_ Pod from the Job terminates with success, no new Pods are created.
- once at least one Pod has terminated with success and all Pods are terminated, then the Job is completed with success.
- once any Pod has exited with success, no other Pod should still be doing any work for this task or writing any output. They should all be in the process of exiting.
For a Non-parallel job, you can leave both `.spec.completions` and `.spec.parallelism` unset. When both are
For a _non-parallel_ Job, you can leave both `.spec.completions` and `.spec.parallelism` unset. When both are
unset, both are defaulted to 1.
For a Fixed Completion Count job, you should set `.spec.completions` to the number of completions needed.
For a _fixed completion count_ Job, you should set `.spec.completions` to the number of completions needed.
You can set `.spec.parallelism`, or leave it unset and it will default to 1.
For a Work Queue Job, you must leave `.spec.completions` unset, and set `.spec.parallelism` to
For a _work queue_ Job, you must leave `.spec.completions` unset, and set `.spec.parallelism` to
a non-negative integer.
For more information about how to make use of the different types of job, see the [job patterns](#job-patterns) section.
@@ -162,28 +167,28 @@ If it is specified as 0, then the Job is effectively paused until it is increase
Actual parallelism (number of pods running at any instant) may be more or less than requested
parallelism, for a variety of reasons:
- For Fixed Completion Count jobs, the actual number of pods running in parallel will not exceed the number of
- For _fixed completion count_ Jobs, the actual number of pods running in parallel will not exceed the number of
remaining completions. Higher values of `.spec.parallelism` are effectively ignored.
- For work queue jobs, no new pods are started after any pod has succeeded -- remaining pods are allowed to complete, however.
- For _work queue_ Jobs, no new Pods are started after any Pod has succeeded -- remaining Pods are allowed to complete, however.
- If the controller has not had time to react.
- If the controller failed to create pods for any reason (lack of ResourceQuota, lack of permission, etc.),
- If the controller failed to create Pods for any reason (lack of `ResourceQuota`, lack of permission, etc.),
then there may be fewer pods than requested.
- The controller may throttle new pod creation due to excessive previous pod failures in the same Job.
- When a pod is gracefully shutdown, it takes time to stop.
- The controller may throttle new Pod creation due to excessive previous pod failures in the same Job.
- When a Pod is gracefully shut down, it takes time to stop.
## Handling Pod and Container Failures
A Container in a Pod may fail for a number of reasons, such as because the process in it exited with
a non-zero exit code, or the Container was killed for exceeding a memory limit, etc. If this
A container in a Pod may fail for a number of reasons, such as because the process in it exited with
a non-zero exit code, or the container was killed for exceeding a memory limit, etc. If this
happens, and the `.spec.template.spec.restartPolicy = "OnFailure"`, then the Pod stays
on the node, but the Container is re-run. Therefore, your program needs to handle the case when it is
on the node, but the container is re-run. Therefore, your program needs to handle the case when it is
restarted locally, or else specify `.spec.template.spec.restartPolicy = "Never"`.
See [pods-states](/docs/concepts/workloads/pods/pod-lifecycle/#example-states) for more information on `restartPolicy`.
See [pod lifecycle](/docs/concepts/workloads/pods/pod-lifecycle/#example-states) for more information on `restartPolicy`.
An entire Pod can also fail, for a number of reasons, such as when the pod is kicked off the node
(node is upgraded, rebooted, deleted, etc.), or if a container of the Pod fails and the
`.spec.template.spec.restartPolicy = "Never"`. When a Pod fails, then the Job controller
starts a new Pod. Therefore, your program needs to handle the case when it is restarted in a new
starts a new Pod. This means that your application needs to handle the case when it is restarted in a new
pod. In particular, it needs to handle temporary files, locks, incomplete output and the like
caused by previous runs.
@@ -194,7 +199,7 @@ 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.
### Pod Backoff failure policy
### Pod backoff failure policy
There are situations where you want to fail a Job after some amount of retries
due to a logical error in configuration etc.
@@ -221,8 +226,7 @@ By default, a Job will run uninterrupted unless a Pod fails, at which point the
Do this by setting the `.spec.activeDeadlineSeconds` field of the Job to a number of seconds.
The `activeDeadlineSeconds` applies to the duration of the job, no matter how many Pods are created.
Once a Job reaches `activeDeadlineSeconds`, the Job and all of its Pods are terminated.
The result is that the job has a status with `reason: DeadlineExceeded`.
Once a Job reaches `activeDeadlineSeconds`, all of its Pods are terminated and the Job status will become `type: Failed` with `reason: DeadlineExceeded`.
Note that a Job's `.spec.activeDeadlineSeconds` takes precedence over its `.spec.backoffLimit`. Therefore, a Job that is retrying one or more failed Pods will not deploy additional Pods once it reaches the time limit specified by `activeDeadlineSeconds`, even if the `backoffLimit` is not yet reached.
@@ -245,7 +249,7 @@ spec:
restartPolicy: Never
```
Note that both the Job Spec and the [Pod Template Spec](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#detailed-behavior) within the Job have an `activeDeadlineSeconds` field. Ensure that you set this field at the proper level.
Note that both the Job spec and the [Pod template spec](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#detailed-behavior) within the Job have an `activeDeadlineSeconds` field. Ensure that you set this field at the proper level.
## Clean Up Finished Jobs Automatically
@@ -317,7 +321,7 @@ The tradeoffs are:
- One Job object for each work item, vs. a single Job object for all work items. The latter is
better for large numbers of work items. The former creates some overhead for the user and for the
system to manage large numbers of Job objects.
- Number of pods created equals number of work items, vs. each pod can process multiple work items.
- Number of pods created equals number of work items, vs. each Pod can process multiple work items.
The former typically requires less modification to existing code and containers. The latter
is better for large numbers of work items, for similar reasons to the previous bullet.
- Several approaches use a work queue. This requires running a queue service,
@@ -337,7 +341,7 @@ The pattern names are also links to examples and more detailed description.
When you specify completions with `.spec.completions`, each Pod created by the Job controller
has an identical [`spec`](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status). This means that
all pods will have the same command line and the same
all pods for a task will have the same command line and the same
image, the same volumes, and (almost) the same environment variables. These patterns
are different ways to arrange for pods to work on different things.
@@ -356,29 +360,29 @@ Here, `W` is the number of work items.
### Specifying your own pod selector
Normally, when you create a job object, you do not specify `.spec.selector`.
The system defaulting logic adds this field when the job is created.
Normally, when you create a Job object, you do not specify `.spec.selector`.
The system defaulting logic adds this field when the Job is created.
It picks a selector value that will not overlap with any other jobs.
However, in some cases, you might need to override this automatically set selector.
To do this, you can specify the `.spec.selector` of the job.
To do this, you can specify the `.spec.selector` of the Job.
Be very careful when doing this. If you specify a label selector which is not
unique to the pods of that job, and which matches unrelated pods, then pods of the unrelated
job may be deleted, or this job may count other pods as completing it, or one or both
of the jobs may refuse to create pods or run to completion. If a non-unique selector is
chosen, then other controllers (e.g. ReplicationController) and their pods may behave
unique to the pods of that Job, and which matches unrelated Pods, then pods of the unrelated
job may be deleted, or this Job may count other Pods as completing it, or one or both
Jobs may refuse to create Pods or run to completion. If a non-unique selector is
chosen, then other controllers (e.g. ReplicationController) and their Pods may behave
in unpredictable ways too. Kubernetes will not stop you from making a mistake when
specifying `.spec.selector`.
Here is an example of a case when you might want to use this feature.
Say job `old` is already running. You want existing pods
to keep running, but you want the rest of the pods it creates
to use a different pod template and for the job to have a new name.
You cannot update the job because these fields are not updatable.
Therefore, you delete job `old` but leave its pods
running, using `kubectl delete jobs/old --cascade=false`.
Say Job `old` is already running. You want existing Pods
to keep running, but you want the rest of the Pods it creates
to use a different pod template and for the Job to have a new name.
You cannot update the Job because these fields are not updatable.
Therefore, you delete Job `old` but _leave its pods
running_, using `kubectl delete jobs/old --cascade=false`.
Before deleting it, you make a note of what selector it uses:
```
@@ -393,11 +397,11 @@ spec:
...
```
Then you create a new job with name `new` and you explicitly specify the same selector.
Since the existing pods have label `job-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002`,
they are controlled by job `new` as well.
Then you create a new Job with name `new` and you explicitly specify the same selector.
Since the existing Pods have label `job-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002`,
they are controlled by Job `new` as well.
You need to specify `manualSelector: true` in the new job since you are not using
You need to specify `manualSelector: true` in the new Job since you are not using
the selector that the system normally generates for you automatically.
```
@@ -421,25 +425,25 @@ mismatch.
### Bare Pods
When the node that a pod is running on reboots or fails, the pod is terminated
and will not be restarted. However, a Job will create new pods to replace terminated ones.
For this reason, we recommend that you use a job rather than a bare pod, even if your application
requires only a single pod.
When the node that a Pod is running on reboots or fails, the pod is terminated
and will not be restarted. However, a Job will create new Pods to replace terminated ones.
For this reason, we recommend that you use a Job rather than a bare Pod, even if your application
requires only a single Pod.
### Replication Controller
Jobs are complementary to [Replication Controllers](/docs/user-guide/replication-controller).
A Replication Controller manages pods which are not expected to terminate (e.g. web servers), and a Job
manages pods that are expected to terminate (e.g. batch jobs).
A Replication Controller manages Pods which are not expected to terminate (e.g. web servers), and a Job
manages Pods that are expected to terminate (e.g. batch tasks).
As discussed in [Pod Lifecycle](/docs/concepts/workloads/pods/pod-lifecycle/), `Job` is *only* appropriate for pods with
`RestartPolicy` equal to `OnFailure` or `Never`. (Note: If `RestartPolicy` is not set, the default
value is `Always`.)
As discussed in [Pod Lifecycle](/docs/concepts/workloads/pods/pod-lifecycle/), `Job` is *only* appropriate
for pods with `RestartPolicy` equal to `OnFailure` or `Never`.
(Note: If `RestartPolicy` is not set, the default value is `Always`.)
### Single Job starts Controller Pod
Another pattern is for a single Job to create a pod which then creates other pods, acting as a sort
of custom controller for those pods. This allows the most flexibility, but may be somewhat
Another pattern is for a single Job to create a Pod which then creates other Pods, acting as a sort
of custom controller for those Pods. This allows the most flexibility, but may be somewhat
complicated to get started with and offers less integration with Kubernetes.
One example of this pattern would be a Job which starts a Pod which runs a script that in turn
@@ -447,10 +451,10 @@ starts a Spark master controller (see [spark example](https://github.com/kuberne
driver, and then cleans up.
An advantage of this approach is that the overall process gets the completion guarantee of a Job
object, but complete control over what pods are created and how work is assigned to them.
object, but complete control over what Pods are created and how work is assigned to them.
## Cron Jobs
## Cron Jobs {#cron-jobs}
Support for creating Jobs at specified times/dates (i.e. cron) is available in Kubernetes [1.4](https://github.com/kubernetes/kubernetes/pull/11980). More information is available in the [cron job documents](/docs/concepts/workloads/controllers/cron-jobs/)
You can use a [`CronJob`](/docs/concepts/workloads/controllers/cron-jobs/) to create a Job that will run at specified times/dates, similar to the Unix tool `cron`.
{{% /capture %}}
@@ -10,39 +10,36 @@ weight: 10
{{% capture overview %}}
ReplicaSet is the next-generation Replication Controller. The only difference
between a _ReplicaSet_ and a
[_Replication Controller_](/docs/concepts/workloads/controllers/replicationcontroller/) right now is
the selector support. ReplicaSet supports the new set-based selector requirements
as described in the [labels user guide](/docs/concepts/overview/working-with-objects/labels/#label-selectors)
whereas a Replication Controller only supports equality-based selector requirements.
A ReplicaSet's purpose is to maintain a stable set of replica Pods running at any given time. As such, it is often
used to guarantee the availability of a specified number of identical Pods.
{{% /capture %}}
{{% capture body %}}
## How to use a ReplicaSet
## How a ReplicaSet works
Most [`kubectl`](/docs/user-guide/kubectl/) commands that support
Replication Controllers also support ReplicaSets. One exception is the
[`rolling-update`](/docs/reference/generated/kubectl/kubectl-commands#rolling-update) command. If
you want the rolling update functionality please consider using Deployments
instead. Also, the
[`rolling-update`](/docs/reference/generated/kubectl/kubectl-commands#rolling-update) command is
imperative whereas Deployments are declarative, so we recommend using Deployments
through the [`rollout`](/docs/reference/generated/kubectl/kubectl-commands#rollout) command.
A ReplicaSet is defined with fields, including a selector that specifies how to identify Pods it can acquire, a number
of replicas indicating how many Pods it should be maintaining, and a pod template specifying the data of new Pods
it should create to meet the number of replicas criteria. A ReplicaSet then fulfills its purpose by creating
and deleting Pods as needed to reach the desired number. When a ReplicaSet needs to create new Pods, it uses its Pod
template.
While ReplicaSets can be used independently, today it's mainly used by
[Deployments](/docs/concepts/workloads/controllers/deployment/) as a mechanism to orchestrate pod
creation, deletion and updates. When you use Deployments you don't have to worry
about managing the ReplicaSets that they create. Deployments own and manage
their ReplicaSets.
The link a ReplicaSet has to its Pods is via the Pods' [metadata.ownerReferences](/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents)
field, which specifies what resource the current object is owned by. All Pods acquired by a ReplicaSet have their owning
ReplicaSet's identifying information within their ownerReferences field. It's through this link that the ReplicaSet
knows of the state of the Pods it is maintaining and plans accordingly.
A ReplicaSet identifies new Pods to acquire by using its selector. If there is a Pod that has no OwnerReference or the
OwnerReference is not a controller and it matches a ReplicaSet's selector, it will be immediately acquired by said
ReplicaSet.
## When to use a ReplicaSet
A ReplicaSet ensures that a specified number of pod replicas are running at any given
time. However, a Deployment is a higher-level concept that manages ReplicaSets and
provides declarative updates to pods along with a lot of other useful features.
provides declarative updates to Pods along with a lot of other useful features.
Therefore, we recommend using Deployments instead of directly using ReplicaSets, unless
you require custom update orchestration or don't require updates at all.
@@ -53,13 +50,31 @@ use a Deployment instead, and define your application in the spec section.
{{< codenew file="controllers/frontend.yaml" >}}
Saving this manifest into `frontend.yaml` and submitting it to a Kubernetes cluster should
create the defined ReplicaSet and the pods that it manages.
Saving this manifest into `frontend.yaml` and submitting it to a Kubernetes cluster will
create the defined ReplicaSet and the Pods that it manages.
```shell
$ kubectl create -f http://k8s.io/examples/controllers/frontend.yaml
replicaset.apps/frontend created
$ kubectl describe rs/frontend
kubectl create -f http://k8s.io/examples/controllers/frontend.yaml
```
You can then get the current ReplicaSets deployed:
```shell
kubectl get rs
```
And see the frontend one you created:
```shell
NAME DESIRED CURRENT READY AGE
frontend 3 3 3 6s
```
You can also check on the state of the replicaset:
```shell
kubectl describe rs/frontend
```
And you will see output similar to:
```shell
Name: frontend
Namespace: default
Selector: tier=frontend,tier in (frontend)
@@ -88,66 +103,150 @@ Events:
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
$ kubectl get pods
```
And lastly you can check for the Pods brought up:
```shell
kubectl get Pods
```
You should see Pod information similar to:
```shell
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
```
## Writing a ReplicaSet Spec
You can also verify that the owner reference of these pods is set to the frontend ReplicaSet.
To do this, get the yaml of one of the Pods running:
```shell
kubectl get pods frontend-9si5l -o yaml
```
As with all other Kubernetes API objects, a ReplicaSet needs the `apiVersion`, `kind`, and `metadata` fields. For
general information about working with manifests, see [object management using kubectl](/docs/concepts/overview/object-management-kubectl/overview/).
The output will look similar to this, with the frontend ReplicaSet's info set in the metadata's ownerReferences field:
```shell
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: 2019-01-31T17:20:41Z
generateName: frontend-
labels:
tier: frontend
name: frontend-9si5l
namespace: default
ownerReferences:
- apiVersion: extensions/v1beta1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: frontend
uid: 892a2330-257c-11e9-aecd-025000000001
...
```
## Non-Template Pod acquisitions
While you can create bare Pods with no problems, it is strongly recommended to make sure that the bare Pods do not have
labels which match the selector of one of your ReplicaSets. The reason for this is because a ReplicaSet is not limited
to owning Pods specified by its template-- it can acquire other Pods in the manner specified in the previous sections.
Take the previous frontend ReplicaSet example, and the Pods specified in the following manifest:
{{< codenew file="pods/pod-rs.yaml" >}}
As those Pods do not have a Controller (or any object) as their owner reference and match the selector of the frontend
ReplicaSet, they will immediately be acquired by it.
Suppose you create the Pods after the frontend ReplicaSet has been deployed and has set up its initial Pod replicas to
fulfill its replica count requirement:
```shell
kubectl create -f http://k8s.io/examples/pods/pod-rs.yaml
```
The new Pods will be acquired by the ReplicaSet, and then immediately terminated as the ReplicaSet would be over
its desired count.
Fetching the Pods:
```shell
kubectl get Pods
```
The output shows that the new Pods are either already terminated, or in the process of being terminated:
```shell
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
pod2 0/1 Terminating 0 4s
```
If you create the Pods first:
```shell
kubectl create -f http://k8s.io/examples/pods/pod-rs.yaml
```
And then create the ReplicaSet however:
```shell
kubectl create -f http://k8s.io/examples/controllers/frontend.yaml
```
You shall see that the ReplicaSet has acquired the Pods and has only created new ones according to its spec until the
number of its new Pods and the original matches its desired count. As fetching the Pods:
```shell
kubectl get Pods
```
Will reveal in its output:
```shell
NAME READY STATUS RESTARTS AGE
frontend-pxj4r 1/1 Running 0 5s
pod1 1/1 Running 0 13s
pod2 1/1 Running 0 13s
```
In this manner, a ReplicaSet can own a non-homogenous set of Pods
## Writing a ReplicaSet manifest
As with all other Kubernetes API objects, a ReplicaSet needs the `apiVersion`, `kind`, and `metadata` fields.
For ReplicaSets, the kind is always just ReplicaSet.
In Kubernetes 1.9 the API version `apps/v1` on the ReplicaSet kind is the current version and is enabled by default. The API version `apps/v1beta2` is deprecated.
Refer to the first lines of the `frontend.yaml` example for guidance.
A ReplicaSet also needs a [`.spec` section](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status).
### Pod Template
The `.spec.template` is the only required field of the `.spec`. The `.spec.template` is a
[pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly the same schema as a
[pod](/docs/concepts/workloads/pods/pod/), except that it is nested and does not have an `apiVersion` or `kind`.
The `.spec.template` is a [pod template](/docs/concepts/workloads/Pods/pod-overview/#pod-templates) which is also
required to have labels in place. In our `frontend.yaml` example we had one label: `tier: frontend`.
Be careful not to overlap with the selectors of other controllers, lest they try to adopt this Pod.
In addition to required fields of a pod, a pod template in a ReplicaSet must specify appropriate
labels and an appropriate restart policy.
For labels, make sure to not overlap with other controllers. For more information, see [pod selector](#pod-selector).
For [restart policy](/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy), the only allowed value for `.spec.template.spec.restartPolicy` is `Always`, which is the default.
For local container restarts, ReplicaSet delegates to an agent on the node,
for example the [Kubelet](/docs/admin/kubelet/) or Docker.
For the template's [restart policy](/docs/concepts/workloads/Pods/pod-lifecycle/#restart-policy) field,
`.spec.template.spec.restartPolicy`, the only allowed value is `Always`, which is the default.
### Pod Selector
The `.spec.selector` field is a [label selector](/docs/concepts/overview/working-with-objects/labels/). A ReplicaSet
manages all the pods with labels that match the selector. It does not distinguish
between pods that it created or deleted and pods that another person or process created or
deleted. This allows the ReplicaSet to be replaced without affecting the running pods.
The `.spec.selector` field is a [label selector](/docs/concepts/overview/working-with-objects/labels/). As discussed
[earlier](#how-a-replicaset-works) these are the labels used to identify potential Pods to acquire. In our
`frontend.yaml` example, the selector was:
```shell
matchLabels:
tier: frontend
```
The `.spec.template.metadata.labels` must match the `.spec.selector`, or it will
In the ReplicaSet, `.spec.template.metadata.labels` must match `spec.selector`, or it will
be rejected by the API.
In Kubernetes 1.9 the API version `apps/v1` on the ReplicaSet kind is the current version and is enabled by default. The API version `apps/v1beta2` is deprecated.
Also you should not normally create any pods whose labels match this selector, either directly, with
another ReplicaSet, or with another controller such as a Deployment. If you do so, the ReplicaSet thinks that it
created the other pods. Kubernetes does not stop you from doing this.
If you do end up with multiple controllers that have overlapping selectors, you
will have to manage the deletion yourself.
### Labels on a ReplicaSet
The ReplicaSet can itself have labels (`.metadata.labels`). Typically, you
would set these the same as the `.spec.template.metadata.labels`. However, they are allowed to be
different, and the `.metadata.labels` do not affect the behavior of the ReplicaSet.
{{< note >}}
For 2 ReplicaSets specifying the same `.spec.selector` but different `.spec.template.metadata.labels` and `.spec.template.spec` fields, each ReplicaSet ignores the Pods created by the other ReplicaSet.
{{< /note >}}
### Replicas
You can specify how many pods should run concurrently by setting `.spec.replicas`. The number running at any time may be higher
or lower, such as if the replicas were just increased or decreased, or if a pod is gracefully
shut down, and a replacement starts early.
You can specify how many Pods should run concurrently by setting `.spec.replicas`. The ReplicaSet will create/delete
its Pods to match this number.
If you do not specify `.spec.replicas`, then it defaults to 1.
@@ -157,7 +256,9 @@ If you do not specify `.spec.replicas`, then it defaults to 1.
To delete a ReplicaSet and all of its Pods, use [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete). The [Garbage collector](/docs/concepts/workloads/controllers/garbage-collection/) automatically deletes all of the dependent Pods by default.
When using the REST API or the `client-go` library, you must set `propagationPolicy` to `Background` or `Foreground` in delete option. e.g. :
When using the REST API or the `client-go` library, you must set `propagationPolicy` to `Background` or `Foreground` in
the -d option.
For example:
```shell
kubectl proxy --port=8080
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
@@ -167,8 +268,9 @@ curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/repli
### Deleting just a ReplicaSet
You can delete a ReplicaSet without affecting any of its pods using [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete) with the `--cascade=false` option.
When using the REST API or the `client-go` library, you must set `propagationPolicy` to `Orphan`, e.g. :
You can delete a ReplicaSet without affecting any of its Pods using [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete) with the `--cascade=false` option.
When using the REST API or the `client-go` library, you must set `propagationPolicy` to `Orphan`.
For example:
```shell
kubectl proxy --port=8080
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
@@ -177,22 +279,22 @@ curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/repli
```
Once the original is deleted, you can create a new ReplicaSet to replace it. As long
as the old and new `.spec.selector` are the same, then the new one will adopt the old pods.
However, it will not make any effort to make existing pods match a new, different pod template.
To update pods to a new spec in a controlled way, use a [rolling update](#rolling-updates).
as the old and new `.spec.selector` are the same, then the new one will adopt the old Pods.
However, it will not make any effort to make existing Pods match a new, different pod template.
To update Pods to a new spec in a controlled way, use a [rolling update](#rolling-updates).
### Isolating pods from a ReplicaSet
### Isolating Pods from a ReplicaSet
Pods may be removed from a ReplicaSet's target set by changing their labels. This technique may be used to remove pods
You can remove Pods from a ReplicaSet by changing their labels. This technique may be used to remove Pods
from service for debugging, data recovery, etc. Pods that are removed in this way will be replaced automatically (
assuming that the number of replicas is not also changed).
assuming that the number of replicas is not also changed).
### Scaling a ReplicaSet
A ReplicaSet can be easily scaled up or down by simply updating the `.spec.replicas` field. The ReplicaSet controller
ensures that a desired number of pods with a matching label selector are available and operational.
ensures that a desired number of Pods with a matching label selector are available and operational.
### ReplicaSet as an Horizontal Pod Autoscaler Target
### ReplicaSet as a Horizontal Pod Autoscaler Target
A ReplicaSet can also be a target for
[Horizontal Pod Autoscalers (HPA)](/docs/tasks/run-application/horizontal-pod-autoscale/). That is,
@@ -203,7 +305,7 @@ the ReplicaSet we created in the previous example.
Saving this manifest into `hpa-rs.yaml` and submitting it to a Kubernetes cluster should
create the defined HPA that autoscales the target ReplicaSet depending on the CPU usage
of the replicated pods.
of the replicated Pods.
```shell
kubectl create -f https://k8s.io/examples/controllers/hpa-rs.yaml
@@ -213,34 +315,40 @@ Alternatively, you can use the `kubectl autoscale` command to accomplish the sam
(and it's easier!)
```shell
kubectl autoscale rs frontend
kubectl autoscale rs frontend --max=10
```
## Alternatives to ReplicaSet
### Deployment (Recommended)
### Deployment (recommended)
[`Deployment`](/docs/concepts/workloads/controllers/deployment/) is a higher-level API object that updates its underlying ReplicaSets and their Pods
in a similar fashion as `kubectl rolling-update`. Deployments are recommended if you want this rolling update functionality,
because unlike `kubectl rolling-update`, they are declarative, server-side, and have additional features. For more information on running a stateless
application using a Deployment, please read [Run a Stateless Application Using a Deployment](/docs/tasks/run-application/run-stateless-application-deployment/).
[`Deployment`](/docs/concepts/workloads/controllers/deployment/) is an object which can own ReplicaSets and update
them and their Pods via declarative, server-side rolling updates.
While ReplicaSets can be used independently, today they're mainly used by Deployments as a mechanism to orchestrate Pod
creation, deletion and updates. When you use Deployments you dont have to worry about managing the ReplicaSets that
they create. Deployments own and manage their ReplicaSets.
As such, it is recommended to use Deployments when you want ReplicaSets.
### Bare Pods
Unlike the case where a user directly created pods, a ReplicaSet replaces pods that are deleted or terminated for any reason, such as in the case of node failure or disruptive node maintenance, such as a kernel upgrade. For this reason, we recommend that you use a ReplicaSet even if your application requires only a single pod. Think of it similarly to a process supervisor, only it supervises multiple pods across multiple nodes instead of individual processes on a single node. A ReplicaSet delegates local container restarts to some agent on the node (for example, Kubelet or Docker).
Unlike the case where a user directly created Pods, a ReplicaSet replaces Pods that are deleted or terminated for any reason, such as in the case of node failure or disruptive node maintenance, such as a kernel upgrade. For this reason, we recommend that you use a ReplicaSet even if your application requires only a single Pod. Think of it similarly to a process supervisor, only it supervises multiple Pods across multiple nodes instead of individual processes on a single node. A ReplicaSet delegates local container restarts to some agent on the node (for example, Kubelet or Docker).
### Job
Use a [`Job`](/docs/concepts/jobs/run-to-completion-finite-workloads/) instead of a ReplicaSet for pods that are expected to terminate on their own
Use a [`Job`](/docs/concepts/jobs/run-to-completion-finite-workloads/) instead of a ReplicaSet for Pods that are expected to terminate on their own
(that is, batch jobs).
### DaemonSet
Use a [`DaemonSet`](/docs/concepts/workloads/controllers/daemonset/) instead of a ReplicaSet for pods that provide a
machine-level function, such as machine monitoring or machine logging. These pods have a lifetime that is tied
to a machine lifetime: the pod needs to be running on the machine before other pods start, and are
Use a [`DaemonSet`](/docs/concepts/workloads/controllers/daemonset/) instead of a ReplicaSet for Pods that provide a
machine-level function, such as machine monitoring or machine logging. These Pods have a lifetime that is tied
to a machine lifetime: the Pod needs to be running on the machine before other Pods start, and are
safe to terminate when the machine is otherwise ready to be rebooted/shutdown.
### ReplicationController
ReplicaSets are the successors to [_ReplicationControllers_](/docs/concepts/workloads/controllers/replicationcontroller/).
The two serve the same purpose, and behave similarly, except that a ReplicationController does not support set-based
selector requirements as described in the [labels user guide](/docs/concepts/overview/working-with-objects/labels/#label-selectors).
As such, ReplicaSets are preferred over ReplicationControllers
{{% /capture %}}
@@ -55,14 +55,18 @@ This example ReplicationController config runs three copies of the nginx web ser
Run the example job by downloading the example file and then running this command:
```shell
$ kubectl create -f https://k8s.io/examples/controllers/replication.yaml
kubectl create -f https://k8s.io/examples/controllers/replication.yaml
```
```
replicationcontroller/nginx created
```
Check on the status of the ReplicationController using this command:
```shell
$ kubectl describe replicationcontrollers/nginx
kubectl describe replicationcontrollers/nginx
```
```
Name: nginx
Namespace: default
Selector: app=nginx
@@ -97,8 +101,10 @@ Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
To list all the pods that belong to the ReplicationController in a machine readable form, you can use a command like this:
```shell
$ pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
```
```
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
```
@@ -134,6 +134,10 @@ As each Pod is created, it gets a matching DNS subdomain, taking the form:
`$(podname).$(governing service domain)`, where the governing service is defined
by the `serviceName` field on the StatefulSet.
As mentioned in the [limitations](#limitations) section, you are responsible for
creating the [Headless Service](/docs/concepts/services-networking/service/#headless-services)
responsible for the network identity of the pods.
Here are some examples of choices for Cluster Domain, Service name,
StatefulSet name, and how that affects the DNS names for the StatefulSet's Pods.
@@ -63,6 +63,11 @@ Ask your cluster administrator or consult your cloud provider or distribution do
to determine if any sources of voluntary disruptions are enabled for your cluster.
If none are enabled, you can skip creating Pod Disruption Budgets.
{{< caution >}}
Not all voluntary disruptions are constrained by Pod Disruption Budgets. For example,
deleting deployments or pods bypasses Pod Disruption Budgets.
{{< /caution >}}
## Dealing with Disruptions
Here are some ways to mitigate involuntary disruptions:
@@ -102,7 +107,7 @@ percentage of the total.
Cluster managers and hosting providers should use tools which
respect Pod Disruption Budgets by calling the [Eviction API](/docs/tasks/administer-cluster/safely-drain-node/#the-eviction-api)
instead of directly deleting pods. Examples are the `kubectl drain` command
instead of directly deleting pods or deployments. Examples are the `kubectl drain` command
and the Kubernetes-on-GCE cluster upgrade script (`cluster/gce/upgrade.sh`).
When a cluster administrator wants to drain a node
@@ -83,7 +83,7 @@ Here are some ideas for how to use Init Containers:
* Register this Pod with a remote server from the downward API with a command like:
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
`curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'`
* Wait for some time before starting the app Container with a command like `sleep 60`.
* Clone a git repository into a volume.
@@ -180,12 +180,24 @@ spec:
This Pod can be started and debugged with the following commands:
```shell
$ kubectl create -f myapp.yaml
kubectl create -f myapp.yaml
```
```
pod/myapp-pod created
$ kubectl get -f myapp.yaml
```
```shell
kubectl get -f myapp.yaml
```
```
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
$ kubectl describe -f myapp.yaml
```
```shell
kubectl describe -f myapp.yaml
```
```
Name: myapp-pod
Namespace: default
[...]
@@ -218,18 +230,25 @@ Events:
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
$ kubectl logs myapp-pod -c init-mydb # Inspect the second init container
```
```shell
kubectl logs myapp-pod -c init-myservice # Inspect the first init container
kubectl logs myapp-pod -c init-mydb # Inspect the second init container
```
Once we start the `mydb` and `myservice` services, we can see the Init Containers
complete and the `myapp-pod` is created:
```shell
$ kubectl create -f services.yaml
kubectl create -f services.yaml
```
```
service/myservice created
service/mydb created
$ kubectl get -f myapp.yaml
```
```shell
kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
```
@@ -39,6 +39,9 @@ Value | Description
`Succeeded` | All Containers in the Pod have terminated in success, and will not be restarted.
`Failed` | All Containers in the Pod have terminated, and at least one Container has terminated in failure. That is, the Container either exited with non-zero status or was terminated by the system.
`Unknown` | For some reason the state of the Pod could not be obtained, typically due to an error in communicating with the host of the Pod.
`Completed` | The pod has run to completion as there's nothing to keep it running eg. Completed Jobs.
`CrashLoopBackOff` | This means that one of the containers in the pod has exited unexpectedly, and perhaps with a non-zero error code even after restarting due to [restart policy](#restart-policy).
## Pod conditions
@@ -130,7 +133,6 @@ specify a readiness probe. In this case, the readiness probe might be the same
as the liveness probe, but the existence of the readiness probe in the spec means
that the Pod will start without receiving any traffic and only start receiving
traffic after the probe starts succeeding.
If your Container needs to work on loading large data, configuration files, or migrations during startup, specify a readiness probe.
If you want your Container to be able to take itself down for maintenance, you
@@ -155,13 +157,47 @@ and
Note that the information reported as Pod status depends on the current
[ContainerState](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#containerstatus-v1-core).
## Container States
Once Pod is assigned to a node by scheduler, kubelet starts creating containers using container runtime.There are three possible states of containers: Waiting, Running and Terminated. To check state of container, you can use `kubectl describe pod [POD_NAME]`. State is displayed for each container within that Pod.
* `Waiting`: Default state of container. If container is not in either Running or Terminated state, it is in Waiting state. A container in Waiting state still runs its required operations, like pulling images, applying Secrets, etc. Along with this state, a message and reason about the state are displayed to provide more information.
```yaml
...
State: Waiting
Reason: ErrImagePull
...
```
* `Running`: Indicates that the container is executing without issues. Once a container enters into Running, `postStart` hook (if any) is executed. This state also displays the time when the container entered Running state.
```yaml
...
State: Running
Started: Wed, 30 Jan 2019 16:46:38 +0530
...
```
* `Terminated`: Indicates that the container completed its execution and has stopped running.A container enters into this when it has successfully completed execution or when it has failed for some reason. Regardless, a reason and exit code is displayed, as well as the container's start and finish time. Before a container enters into Terminated, `preStop` hook (if any) is executed.
```yaml
...
State: Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 30 Jan 2019 11:45:26 +0530
Finished: Wed, 30 Jan 2019 11:45:26 +0530
...
```
## Pod readiness gate
{{< feature-state for_k8s_version="v1.12" state="beta" >}}
In order to add extensibility to Pod readiness by enabling the injection of
extra feedbacks or signals into `PodStatus`, Kubernetes 1.11 introduced a
feature named [Pod ready++](https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md).
feature named [Pod ready++](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md).
You can use the new field `ReadinessGate` in the `PodSpec` to specify additional
conditions to be evaluated for Pod readiness. If Kubernetes cannot find such a
condition in the `status.conditions` field of a Pod, the status of the condition
@@ -4,6 +4,9 @@ reviewers:
title: Pod Overview
content_template: templates/concept
weight: 10
card:
name: concepts
weight: 60
---
{{% capture overview %}}
@@ -101,5 +104,5 @@ Rather than specifying the current desired state of all replicas, pod templates
{{% capture whatsnext %}}
* Learn more about Pod behavior:
* [Pod Termination](/docs/concepts/workloads/pods/pod/#termination-of-pods)
* Other Pod Topics
* [Pod Lifecycle](../pod-lifecycle)
{{% /capture %}}
@@ -173,8 +173,8 @@ An example flow:
1. The Pod in the API server is updated with the time beyond which the Pod is considered "dead" along with the grace period.
1. Pod shows up as "Terminating" when listed in client commands
1. (simultaneous with 3) When the Kubelet sees that a Pod has been marked as terminating because the time in 2 has been set, it begins the pod shutdown process.
1. If the pod has defined a [preStop hook](/docs/concepts/containers/container-lifecycle-hooks/#hook-details), it is invoked inside of the pod. If the `preStop` hook is still running after the grace period expires, step 2 is then invoked with a small (2 second) extended grace period.
1. The processes in the Pod are sent the TERM signal.
1. If one of the Pod's containers has defined a [preStop hook](/docs/concepts/containers/container-lifecycle-hooks/#hook-details), it is invoked inside of the container. If the `preStop` hook is still running after the grace period expires, step 2 is then invoked with a small (2 second) extended grace period.
1. The container is sent the TERM signal. Note that not all containers in the Pod will receive the TERM signal at the same time and may each require a `preStop` hook if the order in which they shut down matters.
1. (simultaneous with 3) Pod is removed from endpoints list for service, and are no longer considered part of the set of running pods for replication controllers. Pods that shutdown slowly cannot continue to serve traffic as load balancers (like the service proxy) remove them from their rotations.
1. When the grace period expires, any processes still running in the Pod are killed with SIGKILL.
1. The Kubelet will finish deleting the Pod on the API server by setting grace period 0 (immediate deletion). The Pod disappears from the API and is no longer visible from the client.
@@ -191,7 +191,7 @@ Force deletions can be potentially dangerous for some pods and should be perform
From Kubernetes v1.1, any container in a pod can enable privileged mode, using the `privileged` flag on the `SecurityContext` of the container spec. This is useful for containers that want to use linux capabilities like manipulating the network stack and accessing devices. Processes within the container get almost the same privileges that are available to processes outside a container. With privileged mode, it should be easier to write network and volume plugins as separate pods that don't need to be compiled into the kubelet.
If the master is running Kubernetes v1.1 or higher, and the nodes are running a version lower than v1.1, then new privileged pods will be accepted by api-server, but will not be launched. They will be pending state.
If the master is running Kubernetes v1.1 or higher, and the nodes are running a version lower than v1.1, then new privileged pods will be accepted by api-server, but will not be launched. They will be in pending state.
If user calls `kubectl describe pod FooPodName`, user can see the reason why the pod is in pending state. The events table in the describe command output will say:
`Error validating pod "FooPodName"."FooPodNamespace" from api, ignoring: spec.containers[0].securityContext.privileged: forbidden '<*>(0xc2089d3248)true'`
@@ -68,10 +68,14 @@ In order to use Pod Presets in your cluster you must ensure the following:
1. You have enabled the API type `settings.k8s.io/v1alpha1/podpreset`. For
example, this can be done by including `settings.k8s.io/v1alpha1=true` in
the `--runtime-config` option for the API server.
the `--runtime-config` option for the API server. In minikube add this flag
`--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true` while
starting the cluster.
1. You have enabled the admission controller `PodPreset`. One way to doing this
is to include `PodPreset` in the `--enable-admission-plugins` option value specified
for the API server.
for the API server. In minikube add this flag
`--extra-config=apiserver.enable-admission-plugins=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset`
while starting the cluster.
1. You have defined your Pod Presets by creating `PodPreset` objects in the
namespace you will use.
+18
View File
@@ -38,6 +38,24 @@ for weekly rotations. The PR wrangler's duties include:
[Intermediate contributing](/docs/contribute/intermediate/) for guidelines
about how SIG Docs uses metadata.
### Helpful Github queries for wranglers
The following queries are helpful when wrangling. After working through these three queries, the remaining list of PRs to be
reviewed is usually small. These queries specifically exclude localization PRs, and only include the `master` branch (except for the last one).
- [No CLA, not eligible to merge](https://github.com/kubernetes/website/pulls?q=is%3Aopen+is%3Apr+label%3A%22cncf-cla%3A+no%22+-label%3Ado-not-merge+label%3Alanguage%2Fen):
Remind the contributor to sign the CLA. If they've already been reminded by both the bot and a human, close
the PR and remind them that they can open it after signing the CLA.
**We can't even review PRs whose authors have not signed the CLA!**
- [Needs LGTM](https://github.com/kubernetes/website/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+-label%3Ado-not-merge+label%3Alanguage%2Fen+-label%3Algtm+):
If it needs technical review, loop in one of the reviewers suggested by the bot. If it needs docs review
or copy-editing, either suggest changes or add a copyedit commit to the PR to move it along.
- [Has LGTM, needs docs approval](https://github.com/kubernetes/website/pulls?q=is%3Aopen+is%3Apr+-label%3Ado-not-merge+label%3Alanguage%2Fen+label%3Algtm):
See if you can figure out what needs to happen for the PR to be merged.
- [Not against master](https://github.com/kubernetes/website/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+-label%3Ado-not-merge+label%3Alanguage%2Fen+-base%3Amaster): If it's against a `dev-` branch, it's for an upcoming release.
Make sure the [release meister](https://github.com/kubernetes/sig-release/tree/master/release-team) knows about it.
If it's against an old branch, help the PR author figure out whether it's targeted against the best branch.
## Propose improvements
SIG Docs
+25 -18
View File
@@ -3,6 +3,9 @@ title: Intermediate contributing
slug: intermediate
content_template: templates/concept
weight: 20
card:
name: contribute
weight: 50
---
{{% capture overview %}}
@@ -487,23 +490,8 @@ Slack channel or the
### View your changes locally
If you aren't ready to create a pull request but you want to see what your
changes look like, you can use the `hugo` command to stage the changes locally.
1. Install Hugo version {{< hugoVersion >}} or later.
2. In a terminal, go to the root directory of your clone of the Kubernetes
docs, and enter this command:
```bash
hugo server
```
3. In your browsers address bar, enter `localhost:1313`.
4. To stop the local Hugo instance, go back to the terminal and type `Ctrl+C`
or just close the terminal window.
Alternatively, you can build the Kubernetes docs using Docker.
changes look like, you can build and run a docker image to generate all the documentation and
serve it locally.
1. Build the image locally:
@@ -518,7 +506,26 @@ Alternatively, you can build the Kubernetes docs using Docker.
```
3. In your browser's address bar, enter `localhost:1313`. Hugo will watch the
filesystem for changes and rebuild the site as needed.
filesystem for changes and rebuild the site as needed.
4. To stop the local Hugo instance, go back to the terminal and type `Ctrl+C`
or just close the terminal window.
Alternatively, you can install and use the `hugo` command on your development machine:
1. [Install Hugo](https://gohugo.io/getting-started/installing/) version {{< hugoVersion >}} or later.
2. In a terminal, go to the root directory of your clone of the Kubernetes
docs, and enter this command:
```bash
hugo server
```
3. In your browsers address bar, enter `localhost:1313`.
4. To stop the local Hugo instance, go back to the terminal and type `Ctrl+C`
or just close the terminal window.
## Triage and categorize issues
+8 -12
View File
@@ -5,29 +5,25 @@ approvers:
- chenopis
- zacharysarah
- zparnold
card:
name: contribute
weight: 30
title: Translating the docs
---
{{% capture overview %}}
Documentation for Kubernetes is available in multiple languages:
- English
- Chinese
- Japanese
- Korean
We encourage you to add new [localizations](https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/)!
Documentation for Kubernetes is available in multiple languages. We encourage you to add new [localizations](https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/)!
{{% /capture %}}
{{% capture body %}}
## Getting started
Localizations must meet some requirements for workflow (*how* to localize) and output (*what* to localize).
Localizations must meet some requirements for workflow (*how* to localize) and output (*what* to localize) before publishing.
To add a new localization of the Kubernetes documentation, you'll need to update the website by modifying the [site configuration](#modify-the-site-configuration) and [directory structure](#add-a-new-localization-directory). Then you can start [translating documents](#translating-documents)!
To add a new localization of the Kubernetes documentation, you'll need to update the website by modifying the [site configuration](#modify-the-site-configuration) and [directory structure](#add-a-new-localization-directory). Then you can start [translating documents](#translating-documents)!
{{< note >}}
For an example localization-related [pull request](../create-pull-request), see [this pull request](https://github.com/kubernetes/website/pull/8636) to the [Kubernetes website repo](https://github.com/kubernetes/website) adding Korean localization to the Kubernetes docs.
@@ -209,7 +205,7 @@ SIG Docs welcomes [upstream contributions and corrections](/docs/contribute/inte
{{% capture whatsnext %}}
Once a l10n meets requirements for workflow and minimum output, SIG docs will:
Once a localization meets requirements for workflow and minimum output, SIG docs will:
- Enable language selection on the website
- Publicize the localization's availability through [Cloud Native Computing Foundation](https://www.cncf.io/) (CNCF) channels, including the [Kubernetes blog](https://kubernetes.io/blog/).
@@ -1,6 +1,9 @@
---
title: Participating in SIG Docs
content_template: templates/concept
card:
name: contribute
weight: 40
---
{{% capture overview %}}
+9 -5
View File
@@ -3,6 +3,9 @@ title: Start contributing
slug: start
content_template: templates/concept
weight: 10
card:
name: contribute
weight: 10
---
{{% capture overview %}}
@@ -79,7 +82,7 @@ Anyone with a Github account can file an issue (bug report) against the
Kubernetes documentation. If you see something wrong, even if you have no idea
how to fix it, [file an issue](#how-to-file-an-issue). The exception to this
rule is a tiny bug like a typo that you intend to fix yourself. In that case,
you can instead [fix it](#fix-it) without filing a bug first.
you can instead [fix it](#improve-existing-content) without filing a bug first.
### How to file an issue
@@ -133,10 +136,11 @@ The SIG Docs team communicates using the following mechanisms:
introduce yourself!
- [Join the `kubernetes-sig-docs` mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-docs),
where broader discussions take place and official decisions are recorded.
- Participate in the weekly SIG Docs video meeting, which is announced on the
Slack channel and the mailing list. Currently, these meetings take place on
Zoom, so you'll need to download the [Zoom client](https://zoom.us/download)
or dial in using a phone.
- Participate in the [weekly SIG Docs](https://github.com/kubernetes/community/tree/master/sig-docs) video meeting, which is announced on the Slack channel and the mailing list. Currently, these meetings take place on Zoom, so you'll need to download the [Zoom client](https://zoom.us/download) or dial in using a phone.
{{< note >}}
You can also check the SIG Docs weekly meeting on the [Kubernetes community meetings calendar](https://calendar.google.com/calendar/embed?src=cgnt364vd8s86hr2phapfjc6uk%40group.calendar.google.com&ctz=America/Los_Angeles).
{{< /note >}}
## Improve existing content
@@ -108,7 +108,6 @@ Another widely used example is the `includes` bundle. It sets `headless: true` i
en/includes
├── default-storage-class-prereqs.md
├── federated-task-tutorial-prereqs.md
├── federation-content-moved.md
├── index.md
├── partner-script.js
├── partner-style.css
@@ -2,6 +2,9 @@
title: Using Page Templates
content_template: templates/concept
weight: 30
card:
name: contribute
weight: 30
---
{{% capture overview %}}
@@ -65,17 +68,13 @@ To write a new concept page, create a Markdown file in a subdirectory of the
{{%/* /capture */%}}
```
- Within each section, write your content. Use the following guidelines:
- Use a minimum of H2 headings (with two leading `#` characters). The sections
themselves are titled automatically by the template.
- For `overview`, use a paragraph to set context for the entire topic.
- For `body`, explain the concept using free-form Markdown.
- For `whatsnext`, give a bullet list of up to 5 topics the reader might be
interested in reading next.
- Fill each section with content. Follow these guidelines:
- Organize content with H2 and H3 headings.
- For `overview`, set the topic's context with a single paragraph.
- For `body`, explain the concept.
- For `whatsnext`, provide a bulleted list of topics (5 maximum) to learn more about the concept.
An example of a published topic that uses the concept template is
[Annotations](/docs/concepts/overview/working-with-objects/annotations/). The
page you are currently reading also uses the concept template.
[Annotations](/docs/concepts/overview/working-with-objects/annotations/) is a published example of the concept template. This page also uses the concept template.
## Task template
@@ -3,6 +3,10 @@ title: Documentation Style Guide
linktitle: Style guide
content_template: templates/concept
weight: 10
card:
name: contribute
weight: 20
title: Documentation Style Guide
---
{{% capture overview %}}
@@ -106,8 +110,13 @@ document, use the backtick (`).
<tr><th>Do</th><th>Don't</th></tr>
<tr><td>The <code>kubectl run</code> command creates a Deployment.</td><td>The "kubectl run" command creates a Deployment.</td></tr>
<tr><td>For declarative management, use <code>kubectl apply</code>.</td><td>For declarative management, use "kubectl apply".</td></tr>
<tr><td>Enclose code samples with triple backticks. <code>(```)</code></td><td>Enclose code samples with any other syntax.</td></tr>
</table>
{{< note >}}
The website supports syntax highlighting for code samples, but specifying a language is optional.
{{< /note >}}
### Use code style for object field names
<table>
@@ -318,7 +327,7 @@ Shortcodes inside include statements will break the build. You must insert them
```
{{</* note */>}}
{{</* include "federation-current-state.md" */>}}
{{</* include "task-tutorial-prereqs.md" */>}}
{{</* /note */>}}
```
@@ -116,7 +116,7 @@
'body': '{{< toc >}}'
'Insert code from file':
'prefix': 'codefile'
'body': '{{< code file="$1" >}}'
'body': '{{< codenew file="$1" >}}'
'Insert feature state':
'prefix': 'fstate'
'body': '{{< feature-state for_k8s_version="$1" state="$2" >}}'
@@ -223,4 +223,4 @@
${7:"next-steps-or-delete"}
{{% /capture %}}
"""
@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- errordeveloper
@@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- aveshagarwal
- eparis
@@ -65,8 +65,7 @@ KUBE_MASTER="--master=http://fed-master:8080"
systemctl mask firewalld.service
systemctl stop firewalld.service
systemctl disable iptables.service
systemctl stop iptables.service
systemctl disable --now iptables.service
```
**Configure the Kubernetes services on the master.**
@@ -97,8 +96,7 @@ ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
```shell
for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl enable --now $SERVICES
systemctl status $SERVICES
done
```
@@ -146,8 +144,7 @@ current-context: kubelet-context
```shell
for SERVICES in kube-proxy kubelet docker; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl enable --now $SERVICES
systemctl status $SERVICES
done
```
@@ -51,7 +51,7 @@ These are more in-depth guides for users choosing to run Kubernetes in productio
- [Decommissioning](/docs/getting-started-guides/ubuntu/decommissioning/)
- [Operational Considerations](/docs/getting-started-guides/ubuntu/operational-considerations/)
- [Glossary](/docs/getting-started-guides/ubuntu/glossary/)
- [Authenticating with LDAP](https://www.ubuntu.com/kubernetes/docs/ldap)
## Third-party Product Integrations
@@ -73,5 +73,3 @@ We're normally following the following Slack channels:
and we monitor the Kubernetes mailing lists.
{{% /capture %}}
@@ -18,6 +18,15 @@ sudo snap install conjure-up --classic
sudo usermod -a -G lxd $(whoami)
```
If you have never run or configured lxd before, you will need to run the following
command to set up the default storage pool and the network bridge required:
```
sudo lxd init
```
If a bridge named `lxdbr0` already exists, you can tell the init config tool to use it.
Note: If conjure-up asks you to "Setup an IPv6 subnet" with LXD, answer NO. IPv6 with Juju/LXD is currently unsupported.
If you already have a bridge configured, e.g. `lxdbr0`, [disable IPv6 on the bridge](https://docs.conjure-up.io/stable/en/troubleshoot#common-problems), otherwise you won't be able to choose it.
{{% /capture %}}

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