Merge pull request #26488 from ChandaniM123/merged-master-dev-1.21

Merged master into dev 1.21 - 2/12/21
This commit is contained in:
Kubernetes Prow Robot
2021-02-13 00:41:04 -08:00
committed by GitHub
106 changed files with 4555 additions and 2103 deletions
@@ -45,7 +45,7 @@ kubectl apply -f https://k8s.io/examples/application/nginx/
`kubectl` will read any files with suffixes `.yaml`, `.yml`, or `.json`.
It is a recommended practice to put resources related to the same microservice or application tier into the same file, and to group all of the files associated with your application in the same directory. If the tiers of your application bind to each other using DNS, then you can then simply deploy all of the components of your stack en masse.
It is a recommended practice to put resources related to the same microservice or application tier into the same file, and to group all of the files associated with your application in the same directory. If the tiers of your application bind to each other using DNS, you can deploy all of the components of your stack together.
A URL can also be specified as a configuration source, which is handy for deploying directly from configuration files checked into github:
@@ -265,7 +265,7 @@ For a more concrete example, check the [tutorial of deploying Ghost](https://git
## Updating labels
Sometimes existing pods and other resources need to be relabeled before creating new resources. This can be done with `kubectl label`.
For example, if you want to label all your nginx pods as frontend tier, simply run:
For example, if you want to label all your nginx pods as frontend tier, run:
```shell
kubectl label pods -l app=nginx tier=fe
@@ -411,7 +411,7 @@ and
## Disruptive updates
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:
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 modify your original configuration file:
```shell
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
@@ -448,7 +448,7 @@ kubectl scale deployment my-nginx --current-replicas=1 --replicas=3
deployment.apps/my-nginx scaled
```
To update to version 1.16.1, simply change `.spec.template.spec.containers[0].image` from `nginx:1.14.2` to `nginx:1.16.1`, with the kubectl commands we learned above.
To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2` to `nginx:1.16.1` using the previous kubectl commands.
```shell
kubectl edit deployment/my-nginx
@@ -225,7 +225,7 @@ The kubelet checks whether the mounted ConfigMap is fresh on every periodic sync
However, the kubelet uses its local cache for getting the current value of the ConfigMap.
The type of the cache is configurable using the `ConfigMapAndSecretChangeDetectionStrategy` field in
the [KubeletConfiguration struct](https://github.com/kubernetes/kubernetes/blob/{{< param "docsbranch" >}}/staging/src/k8s.io/kubelet/config/v1beta1/types.go).
A ConfigMap can be either propagated by watch (default), ttl-based, or simply redirecting
A ConfigMap can be either propagated by watch (default), ttl-based, or by redirecting
all requests directly to the API server.
As a result, the total delay from the moment when the ConfigMap is updated to the moment
when new keys are projected to the Pod can be as long as the kubelet sync period + cache
@@ -669,7 +669,7 @@ The kubelet checks whether the mounted secret is fresh on every periodic sync.
However, the kubelet uses its local cache for getting the current value of the Secret.
The type of the cache is configurable using the `ConfigMapAndSecretChangeDetectionStrategy` field in
the [KubeletConfiguration struct](https://github.com/kubernetes/kubernetes/blob/{{< param "docsbranch" >}}/staging/src/k8s.io/kubelet/config/v1beta1/types.go).
A Secret can be either propagated by watch (default), ttl-based, or simply redirecting
A Secret can be either propagated by watch (default), ttl-based, or by redirecting
all requests directly to the API server.
As a result, the total delay from the moment when the Secret is updated to the moment
when new keys are projected to the Pod can be as long as the kubelet sync period + cache
@@ -36,10 +36,13 @@ No parameters are passed to the handler.
`PreStop`
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 signal to stop the container can be sent.
No parameters are passed to the handler.
This hook is called immediately before a container is terminated due to an API request or management
event such as a liveness/startup probe failure, preemption, resource contention and others. A call
to the `PreStop` hook fails if the container is already in a terminated or completed state and the
hook must complete before the TERM signal to stop the container can be sent. The Pod's termination
grace period countdown begins before the `PreStop` hook is executed, so regardless of the outcome of
the handler, the container will eventually terminate within the Pod's termination grace period. No
parameters are passed to the handler.
A more detailed description of the termination behavior can be found in
[Termination of Pods](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination).
@@ -65,19 +68,15 @@ the Container ENTRYPOINT and hook fire asynchronously.
However, if the hook takes too long to run or hangs,
the Container cannot reach a `running` state.
`PreStop` hooks are not executed asynchronously from the signal
to stop the Container; the hook must complete its execution before
the signal can be sent.
If a `PreStop` hook hangs during execution,
the Pod's phase will be `Terminating` and remain there until the Pod is
killed after its `terminationGracePeriodSeconds` expires.
This grace period applies to the total time it takes for both
the `PreStop` hook to execute and for the Container to stop normally.
If, for example, `terminationGracePeriodSeconds` is 60, and the hook
takes 55 seconds to complete, and the Container takes 10 seconds to stop
normally after receiving the signal, then the Container will be killed
before it can stop normally, since `terminationGracePeriodSeconds` is
less than the total time (55+10) it takes for these two things to happen.
`PreStop` hooks are not executed asynchronously from the signal to stop the Container; the hook must
complete its execution before the TERM signal can be sent. If a `PreStop` hook hangs during
execution, the Pod's phase will be `Terminating` and remain there until the Pod is killed after its
`terminationGracePeriodSeconds` expires. This grace period applies to the total time it takes for
both the `PreStop` hook to execute and for the Container to stop normally. If, for example,
`terminationGracePeriodSeconds` is 60, and the hook takes 55 seconds to complete, and the Container
takes 10 seconds to stop normally after receiving the signal, then the Container will be killed
before it can stop normally, since `terminationGracePeriodSeconds` is less than the total time
(55+10) it takes for these two things to happen.
If either a `PostStart` or `PreStop` hook fails,
it kills the Container.
@@ -31,7 +31,7 @@ Once a custom resource is installed, users can create and access its objects usi
## Custom controllers
On their own, custom resources simply let you store and retrieve structured data.
On their own, custom resources let you store and retrieve structured data.
When you combine a custom resource with a *custom controller*, custom resources
provide a true _declarative API_.
@@ -120,7 +120,7 @@ Kubernetes provides two ways to add custom resources to your cluster:
Kubernetes provides these two options to meet the needs of different users, so that neither ease of use nor flexibility is compromised.
Aggregated APIs are subordinate API servers that sit behind the primary API server, which acts as a proxy. This arrangement is called [API Aggregation](/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) (AA). To users, it simply appears that the Kubernetes API is extended.
Aggregated APIs are subordinate API servers that sit behind the primary API server, which acts as a proxy. This arrangement is called [API Aggregation](/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) (AA). To users, the Kubernetes API appears extended.
CRDs allow users to create new types of resources without adding another API server. You do not need to understand API Aggregation to use CRDs.
@@ -24,7 +24,7 @@ Network plugins in Kubernetes come in a few flavors:
The kubelet has a single default network plugin, and a default network common to the entire cluster. It probes for plugins when it starts up, remembers what it finds, and executes the selected plugin at appropriate times in the pod lifecycle (this is only true for Docker, as CRI manages its own CNI plugins). There are two Kubelet command line parameters to keep in mind when using plugins:
* `cni-bin-dir`: Kubelet probes this directory for plugins on startup
* `network-plugin`: The network plugin to use from `cni-bin-dir`. It must match the name reported by a plugin probed from the plugin directory. For CNI plugins, this is simply "cni".
* `network-plugin`: The network plugin to use from `cni-bin-dir`. It must match the name reported by a plugin probed from the plugin directory. For CNI plugins, this is `cni`.
## Network Plugin Requirements
@@ -26,7 +26,7 @@ Fortunately, there is a cloud provider that offers message queuing as a managed
A cluster operator can setup Service Catalog and use it to communicate with the cloud provider's service broker to provision an instance of the message queuing service and make it available to the application within the Kubernetes cluster.
The application developer therefore does not need to be concerned with the implementation details or management of the message queue.
The application can simply use it as a service.
The application can access the message queue as a service.
## Architecture
@@ -98,7 +98,7 @@ For both equality-based and set-based conditions there is no logical _OR_ (`||`)
### _Equality-based_ requirement
_Equality-_ or _inequality-based_ requirements allow filtering by label keys and values. Matching objects must satisfy all of the specified label constraints, though they may have additional labels as well.
Three kinds of operators are admitted `=`,`==`,`!=`. The first two represent _equality_ (and are simply synonyms), while the latter represents _inequality_. For example:
Three kinds of operators are admitted `=`,`==`,`!=`. The first two represent _equality_ (and are synonyms), while the latter represents _inequality_. For example:
```
environment = production
@@ -197,7 +197,7 @@ alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n
### Create a policy and a pod
Define the example PodSecurityPolicy object in a file. This is a policy that
simply prevents the creation of privileged pods.
prevents the creation of privileged pods.
The name of a PodSecurityPolicy object must be a valid
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
@@ -610,17 +610,28 @@ plugins:
values: ["cluster-services"]
```
Now, "cluster-services" pods will be allowed in only those namespaces where a quota object with a matching `scopeSelector` is present.
For example:
Then, create a resource quota object in the `kube-system` namespace:
```yaml
scopeSelector:
matchExpressions:
- scopeName: PriorityClass
operator: In
values: ["cluster-services"]
{{< codenew file="policy/priority-class-resourcequota.yaml" >}}
```shell
$ kubectl apply -f https://k8s.io/examples/policy/priority-class-resourcequota.yaml -n kube-system
```
```
resourcequota/pods-cluster-services created
```
In this case, a pod creation will be allowed if:
1. the Pod's `priorityClassName` is not specified.
1. the Pod's `priorityClassName` is specified to a value other than `cluster-services`.
1. the Pod's `priorityClassName` is set to `cluster-services`, it is to be created
in the `kube-system` namespace, and it has passed the resource quota check.
A Pod creation request is rejected if its `priorityClassName` is set to `cluster-services`
and it is to be created in a namespace other than `kube-system`.
## {{% heading "whatsnext" %}}
- See [ResourceQuota design doc](https://git.k8s.io/community/contributors/design-proposals/resource-management/admission_control_resource_quota.md) for more information.
@@ -261,7 +261,7 @@ for performance and security reasons, there are some constraints on topologyKey:
and `preferredDuringSchedulingIgnoredDuringExecution`.
2. For pod anti-affinity, empty `topologyKey` is also not allowed in both `requiredDuringSchedulingIgnoredDuringExecution`
and `preferredDuringSchedulingIgnoredDuringExecution`.
3. For `requiredDuringSchedulingIgnoredDuringExecution` pod anti-affinity, the admission controller `LimitPodHardAntiAffinityTopology` was introduced to limit `topologyKey` to `kubernetes.io/hostname`. If you want to make it available for custom topologies, you may modify the admission controller, or simply disable it.
3. For `requiredDuringSchedulingIgnoredDuringExecution` pod anti-affinity, the admission controller `LimitPodHardAntiAffinityTopology` was introduced to limit `topologyKey` to `kubernetes.io/hostname`. If you want to make it available for custom topologies, you may modify the admission controller, or disable it.
4. Except for the above cases, the `topologyKey` can be any legal label-key.
In addition to `labelSelector` and `topologyKey`, you can optionally specify a list `namespaces`
@@ -107,7 +107,7 @@ value being calculated based on the cluster size. There is also a hardcoded
minimum value of 50 nodes.
{{< note >}}In clusters with less than 50 feasible nodes, the scheduler still
checks all the nodes, simply because there are not enough feasible nodes to stop
checks all the nodes because there are not enough feasible nodes to stop
the scheduler's search early.
In a small cluster, if you set a low value for `percentageOfNodesToScore`, your
@@ -183,7 +183,7 @@ the three things:
{{< note >}}
While any plugin can access the list of "waiting" Pods and approve them
(see [`FrameworkHandle`](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20180409-scheduling-framework.md#frameworkhandle)), we expect only the permit
(see [`FrameworkHandle`](https://git.k8s.io/enhancements/keps/sig-scheduling/624-scheduling-framework#frameworkhandle)), we expect only the permit
plugins to approve binding of reserved Pods that are in "waiting" state. Once a Pod
is approved, it is sent to the [PreBind](#pre-bind) phase.
{{< /note >}}
@@ -120,6 +120,7 @@ Area of Concern for Containers | Recommendation |
Container Vulnerability Scanning and OS Dependency Security | As part of an image build step, you should scan your containers for known vulnerabilities.
Image Signing and Enforcement | Sign container images to maintain a system of trust for the content of your containers.
Disallow privileged users | When constructing containers, consult your documentation for how to create users inside of the containers that have the least level of operating system privilege necessary in order to carry out the goal of the container.
Use container runtime with stronger isolation | Select [container runtime classes](/docs/concepts/containers/runtime-class/) that provider stronger isolation
## Code
@@ -152,3 +153,4 @@ Learn about related Kubernetes security topics:
* [Data encryption in transit](/docs/tasks/tls/managing-tls-in-a-cluster/) for the control plane
* [Data encryption at rest](/docs/tasks/administer-cluster/encrypt-data/)
* [Secrets in Kubernetes](/docs/concepts/configuration/secret/)
* [Runtime class](/docs/concepts/containers/runtime-class)
@@ -25,9 +25,9 @@ assigned a DNS name. By default, a client Pod's DNS search list will
include the Pod's own namespace and the cluster's default domain. This is best
illustrated by example:
Assume a Service named `foo` in the Kubernetes namespace `bar`. A Pod running
in namespace `bar` can look up this service by simply doing a DNS query for
`foo`. A Pod running in namespace `quux` can look up this service by doing a
Assume a Service named `foo` in the Kubernetes namespace `bar`. A Pod running
in namespace `bar` can look up this service by querying a DNS service for
`foo`. A Pod running in namespace `quux` can look up this service by doing a
DNS query for `foo.bar`.
The following sections detail the supported record types and layout that is
@@ -163,7 +163,7 @@ status:
loadBalancer: {}
```
1. When dual-stack is enabled on a cluster, existing [headless Services](/docs/concepts/services-networking/service/#headless-services) with selectors are configured by the control plane to set `.spec.ipFamilyPolicy` to `SingleStack` and set `.spec.ipFamilies` to the address family of the first service cluster IP range (configured via the `--service-cluster-ip-range` flag to the kube-controller-manager) even though `.spec.ClusterIP` is set to `None`.
1. When dual-stack is enabled on a cluster, existing [headless Services](/docs/concepts/services-networking/service/#headless-services) with selectors are configured by the control plane to set `.spec.ipFamilyPolicy` to `SingleStack` and set `.spec.ipFamilies` to the address family of the first service cluster IP range (configured via the `--service-cluster-ip-range` flag to the kube-apiserver) even though `.spec.ClusterIP` is set to `None`.
{{< codenew file="service/networking/dual-stack-default-svc.yaml" >}}
@@ -430,7 +430,7 @@ Services by their DNS name.
For example, if you have a Service called `my-service` in a Kubernetes
namespace `my-ns`, the control plane and the DNS Service acting together
create a DNS record for `my-service.my-ns`. Pods in the `my-ns` namespace
should be able to find it by simply doing a name lookup for `my-service`
should be able to find the service by doing a name lookup for `my-service`
(`my-service.my-ns` would also work).
Pods in other namespaces must qualify the name as `my-service.my-ns`. These names
@@ -463,7 +463,7 @@ selectors defined:
For headless Services that define selectors, the endpoints controller creates
`Endpoints` records in the API, and modifies the DNS configuration to return
records (addresses) that point directly to the `Pods` backing the `Service`.
A records (IP addresses) that point directly to the `Pods` backing the `Service`.
### Without selectors
@@ -1163,7 +1163,7 @@ rule kicks in, and redirects the packets to the proxy's own port.
The "Service proxy" chooses a backend, and starts proxying traffic from the client to the backend.
This means that Service owners can choose any port they want without risk of
collision. Clients can simply connect to an IP and port, without being aware
collision. Clients can connect to an IP and port, without being aware
of which Pods they are actually accessing.
#### iptables
@@ -487,7 +487,7 @@ The following volume types support mount options:
* VsphereVolume
* iSCSI
Mount options are not validated, so mount will simply fail if one is invalid.
Mount options are not validated. If a mount option is invalid, the mount fails.
In the past, the annotation `volume.beta.kubernetes.io/mount-options` was used instead
of the `mountOptions` attribute. This annotation is still working; however,
@@ -149,7 +149,7 @@ mount options specified in the `mountOptions` field of the class.
If the volume plugin does not support mount options but mount options are
specified, provisioning will fail. Mount options are not validated on either
the class or PV, so mount of the PV will simply fail if one is invalid.
the class or PV. If a mount option is invalid, the PV mount fails.
### Volume Binding Mode
@@ -24,7 +24,7 @@ The {{< glossary_tooltip text="CSI" term_id="csi" >}} Volume Cloning feature add
A Clone is defined as a duplicate of an existing Kubernetes Volume that can be consumed as any standard Volume would be. The only difference is that upon provisioning, rather than creating a "new" empty Volume, the back end device creates an exact duplicate of the specified Volume.
The implementation of cloning, from the perspective of the Kubernetes API, simply adds the ability to specify an existing PVC as a dataSource during new PVC creation. The source PVC must be bound and available (not in use).
The implementation of cloning, from the perspective of the Kubernetes API, adds the ability to specify an existing PVC as a dataSource during new PVC creation. The source PVC must be bound and available (not in use).
Users need to be aware of the following when using this feature:
@@ -106,6 +106,8 @@ spec:
fsType: ext4
```
If the EBS volume is partitioned, you can supply the optional field `partition: "<partition number>"` to specify which parition to mount on.
#### AWS EBS CSI migration
{{< feature-state for_k8s_version="v1.17" state="beta" >}}
@@ -90,6 +90,11 @@ If `startingDeadlineSeconds` is set to a large value or left unset (the default)
and if `concurrencyPolicy` is set to `Allow`, the jobs will always run
at least once.
{{< caution >}}
If `startingDeadlineSeconds` is set to a value less than 10 seconds, the CronJob may not be scheduled. This is because the CronJob controller checks things every 10 seconds.
{{< /caution >}}
For every CronJob, the CronJob {{< glossary_tooltip term_id="controller" >}} checks how many schedules it missed in the duration from its last scheduled time until now. If there are more than 100 missed schedules, then it does not start the job and logs the error
````
@@ -128,4 +133,3 @@ documents the format of CronJob `schedule` fields.
For instructions on creating and working with cron jobs, and for an example of CronJob
manifest, see [Running automated tasks with cron jobs](/docs/tasks/job/automated-tasks-with-cron-jobs).
@@ -47,7 +47,7 @@ In this example:
* A Deployment named `nginx-deployment` is created, indicated by the `.metadata.name` field.
* The Deployment creates three replicated Pods, indicated by the `.spec.replicas` field.
* The `.spec.selector` field defines how the Deployment finds which Pods to manage.
In this case, you simply select a label that is defined in the Pod template (`app: nginx`).
In this case, you 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.
@@ -171,13 +171,15 @@ Follow the steps given below to update your Deployment:
```shell
kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
```
or simply use the following command:
or use the following command:
```shell
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
```
The output is similar to this:
The output is similar to:
```
deployment.apps/nginx-deployment image updated
```
@@ -188,7 +190,8 @@ Follow the steps given below to update your Deployment:
kubectl edit deployment.v1.apps/nginx-deployment
```
The output is similar to this:
The output is similar to:
```
deployment.apps/nginx-deployment edited
```
@@ -200,10 +203,13 @@ Follow the steps given below to update your Deployment:
```
The output is similar to this:
```
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
```
or
```
deployment "nginx-deployment" successfully rolled out
```
@@ -212,10 +218,11 @@ Get more details on your updated Deployment:
* After the rollout succeeds, you can view the Deployment by running `kubectl get deployments`.
The output is similar to this:
```
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 36s
```
```ini
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 36s
```
* Run `kubectl get rs` to see that the Deployment updated the Pods by creating a new ReplicaSet and scaling it
up to 3 replicas, as well as scaling down the old ReplicaSet to 0 replicas.
@@ -180,16 +180,16 @@ delete`](/docs/reference/generated/kubectl/kubectl-commands#delete). Kubectl wi
for it to delete each pod before deleting the ReplicationController itself. If this kubectl
command is interrupted, it can be restarted.
When using the REST API or go client library, you need to do the steps explicitly (scale replicas to
When using the REST API or Go client library, you need to do the steps explicitly (scale replicas to
0, wait for pod deletions, then delete the ReplicationController).
### Deleting just a ReplicationController
### Deleting only a ReplicationController
You can delete a ReplicationController without affecting any of its pods.
Using kubectl, specify the `--cascade=false` option to [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete).
When using the REST API or go client library, simply delete the ReplicationController object.
When using the REST API or Go client library, you can delete the ReplicationController object.
Once the original is deleted, you can create a new ReplicationController to replace it. As long
as the old and new `.spec.selector` are the same, then the new one will adopt the old pods.
@@ -240,7 +240,7 @@ Pods created by a ReplicationController are intended to be fungible and semantic
## Responsibilities of the ReplicationController
The ReplicationController simply ensures that the desired number of pods matches its label selector and are operational. Currently, only terminated pods are excluded from its count. In the future, [readiness](https://issue.k8s.io/620) and other information available from the system may be taken into account, we may add more controls over the replacement policy, and we plan to emit events that could be used by external clients to implement arbitrarily sophisticated replacement and/or scale-down policies.
The ReplicationController ensures that the desired number of pods matches its label selector and are operational. Currently, only terminated pods are excluded from its count. In the future, [readiness](https://issue.k8s.io/620) and other information available from the system may be taken into account, we may add more controls over the replacement policy, and we plan to emit events that could be used by external clients to implement arbitrarily sophisticated replacement and/or scale-down policies.
The ReplicationController is forever constrained to this narrow responsibility. It itself will not perform readiness nor liveness probes. Rather than performing auto-scaling, it is intended to be controlled by an external auto-scaler (as discussed in [#492](https://issue.k8s.io/492)), which would change its `replicas` field. We will not add scheduling policies (for example, [spreading](https://issue.k8s.io/367#issuecomment-48428019)) to the ReplicationController. Nor should it verify that the pods controlled match the currently specified template, as that would obstruct auto-sizing and other automated processes. Similarly, completion deadlines, ordering dependencies, configuration expansion, and other features belong elsewhere. We even plan to factor out the mechanism for bulk pod creation ([#170](https://issue.k8s.io/170)).
@@ -103,7 +103,7 @@ the ephemeral container to add as an `EphemeralContainers` list:
"apiVersion": "v1",
"kind": "EphemeralContainers",
"metadata": {
"name": "example-pod"
"name": "example-pod"
},
"ephemeralContainers": [{
"command": [
@@ -52,7 +52,7 @@ Members can:
{{< note >}}
Using `/lgtm` triggers automation. If you want to provide non-binding
approval, simply commenting "LGTM" works too!
approval, commenting "LGTM" works too!
{{< /note >}}
- Use the `/hold` comment to block merging for a pull request
+14 -11
View File
@@ -44,22 +44,25 @@ The English-language documentation uses U.S. English spelling and grammar.
### Use upper camel case for API objects
When you refer specifically to interacting with an API object, use [UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case), also known as Pascal Case. When you are generally discussing an API object, use [sentence-style capitalization](https://docs.microsoft.com/en-us/style-guide/text-formatting/using-type/use-sentence-style-capitalization).
When you refer specifically to interacting with an API object, use [UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case), also known as Pascal case. You may see different capitalization, such as "configMap", in the [API Reference](/docs/reference/kubernetes-api/). When writing general documentation, it's better to use upper camel case, calling it "ConfigMap" instead.
When you are generally discussing an API object, use [sentence-style capitalization](https://docs.microsoft.com/en-us/style-guide/text-formatting/using-type/use-sentence-style-capitalization).
You may use the word "resource", "API", or "object" to clarify a Kubernetes resource type in a sentence.
Don't split the API object name into separate words. For example, use
PodTemplateList, not Pod Template List.
Refer to API objects without saying "object," unless omitting "object"
leads to an awkward construction.
The following examples focus on capitalization. Review the related guidance on [Code Style](#code-style-inline-code) for more information on formatting API objects.
{{< table caption = "Do and Don't - API objects" >}}
{{< table caption = "Do and Don't - Use Pascal case for API objects" >}}
Do | Don't
:--| :-----
The pod has two containers. | The Pod has two containers.
The HorizontalPodAutoscaler is responsible for ... | The HorizontalPodAutoscaler object is responsible for ...
A PodList is a list of pods. | A Pod List is a list of pods.
The two ContainerPorts ... | The two ContainerPort objects ...
The two ContainerStateTerminated objects ... | The two ContainerStateTerminateds ...
The HorizontalPodAutoscaler resource is responsible for ... | The Horizontal pod autoscaler is responsible for ...
A PodList object is a list of pods. | A Pod List object is a list of pods.
The Volume object contains a `hostPath` field. | The volume object contains a hostPath field.
Every ConfigMap object is part of a namespace. | Every configMap object is part of a namespace.
For managing confidential data, consider using the Secret API. | For managing confidential data, consider using the secret API.
{{< /table >}}
@@ -113,12 +116,12 @@ The copy is called a "fork". | The copy is called a "fork."
## Inline code formatting
### Use code style for inline code, commands, and API objects
### Use code style for inline code, commands, and API objects {#code-style-inline-code}
For inline code in an HTML document, use the `<code>` tag. In a Markdown
document, use the backtick (`` ` ``).
{{< table caption = "Do and Don't - Use code style for inline code and commands" >}}
{{< table caption = "Do and Don't - Use code style for inline code, commands, and API objects" >}}
Do | Don't
:--| :-----
The `kubectl run` command creates a `Pod`. | The "kubectl run" command creates a pod.
@@ -116,7 +116,7 @@ Rejects all requests. AlwaysDeny is DEPRECATED as it has no real meaning.
This admission controller modifies every new Pod to force the image pull policy to Always. This is useful in a
multitenant cluster so that users can be assured that their private images can only be used by those
who have the credentials to pull them. Without this admission controller, once an image has been pulled to a
node, any pod from any user can use it simply by knowing the image's name (assuming the Pod is
node, any pod from any user can use it by knowing the image's name (assuming the Pod is
scheduled onto the right node), without any authorization check against the image. When this admission controller
is enabled, images are always pulled prior to starting containers, which means valid credentials are
required.
@@ -206,7 +206,7 @@ spec:
Service account bearer tokens are perfectly valid to use outside the cluster and
can be used to create identities for long standing jobs that wish to talk to the
Kubernetes API. To manually create a service account, simply use the `kubectl
Kubernetes API. To manually create a service account, use the `kubectl
create serviceaccount (NAME)` command. This creates a service account in the
current namespace and an associated secret.
@@ -420,12 +420,12 @@ users:
refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq
name: oidc
```
Once your `id_token` expires, `kubectl` will attempt to refresh your `id_token` using your `refresh_token` and `client_secret` storing the new values for the `refresh_token` and `id_token` in your `.kube/config`.
Once your `id_token` expires, `kubectl` will attempt to refresh your `id_token` using your `refresh_token` and `client_secret` storing the new values for the `refresh_token` and `id_token` in your `.kube/config`.
##### Option 2 - Use the `--token` Option
The `kubectl` command lets you pass in a token using the `--token` option. Simply copy and paste the `id_token` into this option:
The `kubectl` command lets you pass in a token using the `--token` option. Copy and paste the `id_token` into this option:
```bash
kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodes
@@ -635,8 +635,8 @@ Each feature gate is designed for enabling/disabling a specific feature:
- `KubeletCredentialProviders`: Enable kubelet exec credential providers for image pull credentials.
- `KubeletPluginsWatcher`: Enable probe-based plugin watcher utility to enable kubelet
to discover plugins such as [CSI volume drivers](/docs/concepts/storage/volumes/#csi).
- `KubeletPodResources`: Enable the kubelet's pod resources GRPC endpoint. See
[Support Device Monitoring](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/compute-device-assignment.md)
- `KubeletPodResources`: Enable the kubelet's pod resources gRPC endpoint. See
[Support Device Monitoring](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/606-compute-device-assignment/README.md)
for more details.
- `LegacyNodeRoleBehavior`: When disabled, legacy behavior in service load balancers and
node disruption will ignore the `node-role.kubernetes.io/master` label in favor of the
@@ -16,10 +16,10 @@ min-kubernetes-server-version: 1.16
## Introduction
Server Side Apply helps users and controllers manage their resources via
declarative configurations. It allows them to create and/or modify their
Server Side Apply helps users and controllers manage their resources through
declarative configurations. Clients can create and modify their
[objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/)
declaratively, simply by sending their fully specified intent.
declaratively by sending their fully specified intent.
A fully specified intent is a partial object that only includes the fields and
values for which the user has an opinion. That intent either creates a new
@@ -420,7 +420,7 @@ Start CRI-O:
```shell
sudo systemctl daemon-reload
sudo systemctl start crio
sudo systemctl enable crio --now
```
Refer to the [CRI-O installation guide](https://github.com/cri-o/cri-o/blob/master/install.md)
@@ -434,7 +434,7 @@ Now remove the node:
kubectl delete node <node name>
```
If you wish to start over simply run `kubeadm init` or `kubeadm join` with the
If you wish to start over, run `kubeadm init` or `kubeadm join` with the
appropriate arguments.
### Clean up the control plane
@@ -308,13 +308,6 @@ or `/etc/default/kubelet`(`/etc/sysconfig/kubelet` for RPMs), please remove it a
(stored in `/var/lib/kubelet/config.yaml` by default).
{{< /note >}}
Restarting the kubelet is required:
```bash
sudo systemctl daemon-reload
sudo systemctl restart kubelet
```
The automatic detection of cgroup driver for other container runtimes
like CRI-O and containerd is work in progress.
@@ -547,7 +547,7 @@ Your main source of help for troubleshooting your Kubernetes cluster should star
1. After launching `start.ps1`, flanneld is stuck in "Waiting for the Network to be created"
There are numerous reports of this [issue which are being investigated](https://github.com/coreos/flannel/issues/1066); most likely it is a timing issue for when the management IP of the flannel network is set. A workaround is to simply relaunch start.ps1 or relaunch it manually as follows:
There are numerous reports of this [issue](https://github.com/coreos/flannel/issues/1066); most likely it is a timing issue for when the management IP of the flannel network is set. A workaround is to relaunch start.ps1 or relaunch it manually as follows:
```powershell
PS C:> [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows_Worker_Hostname>")
@@ -23,7 +23,7 @@ Windows applications constitute a large portion of the services and applications
## Before you begin
* Create a Kubernetes cluster that includes a [master and a worker node running Windows Server](/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes)
* It is important to note that creating and deploying services and workloads on Kubernetes behaves in much the same way for Linux and Windows containers. [Kubectl commands](/docs/reference/kubectl/overview/) to interface with the cluster are identical. The example in the section below is provided simply to jumpstart your experience with Windows containers.
* It is important to note that creating and deploying services and workloads on Kubernetes behaves in much the same way for Linux and Windows containers. [Kubectl commands](/docs/reference/kubectl/overview/) to interface with the cluster are identical. The example in the section below is provided to jumpstart your experience with Windows containers.
## Getting Started: Deploying a Windows container
@@ -280,7 +280,7 @@ at `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-l
#### Manually constructing apiserver proxy URLs
As mentioned above, you use the `kubectl cluster-info` command to retrieve the service's proxy URL. To create proxy URLs that include service endpoints, suffixes, and parameters, you simply append to the service's proxy URL:
As mentioned above, you use the `kubectl cluster-info` command to retrieve the service's proxy URL. To create proxy URLs that include service endpoints, suffixes, and parameters, you append to the service's proxy URL:
`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`service_name[:port_name]`*`/proxy`
If you haven't specified a name for your port, you don't have to specify *port_name* in the URL.
@@ -215,7 +215,7 @@ for i in ret.items:
#### Java client
* To install the [Java Client](https://github.com/kubernetes-client/java), simply execute :
To install the [Java Client](https://github.com/kubernetes-client/java), run:
```shell
# Clone java library
@@ -83,7 +83,7 @@ See [Access Clusters Using the Kubernetes API](/docs/tasks/administer-cluster/ac
#### Manually constructing apiserver proxy URLs
As mentioned above, you use the `kubectl cluster-info` command to retrieve the service's proxy URL. To create proxy URLs that include service endpoints, suffixes, and parameters, you simply append to the service's proxy URL:
As mentioned above, you use the `kubectl cluster-info` command to retrieve the service's proxy URL. To create proxy URLs that include service endpoints, suffixes, and parameters, you append to the service's proxy URL:
`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`[https:]service_name[:port_name]`*`/proxy`
If you haven't specified a name for your port, you don't have to specify *port_name* in the URL.
@@ -32,7 +32,7 @@ for example, it might provision storage that is too expensive. If this is the ca
you can either change the default StorageClass or disable it completely to avoid
dynamic provisioning of storage.
Simply deleting the default StorageClass may not work, as it may be re-created
Deleting the default StorageClass may not work, as it may be re-created
automatically by the addon manager running in your cluster. Please consult the docs for your installation
for details about addon manager and how to disable individual addons.
@@ -201,6 +201,9 @@ allow.textmode=true
how.nice.to.look=fairlyNice
```
When `kubectl` creates a ConfigMap from inputs that are not ASCII or UTF-8, the tool puts these into the `binaryData` field of the ConfigMap, and not in `data`. Both text and binary data sources can be combined in one ConfigMap.
If you want to view the `binaryData` keys (and their values) in a ConfigMap, you can run `kubectl get configmap -o jsonpath='{.binaryData}' <name>`.
Use the option `--from-env-file` to create a ConfigMap from an env-file, for example:
```shell
@@ -687,4 +690,3 @@ data:
* Follow a real world example of [Configuring Redis using a ConfigMap](/docs/tutorials/configuration/configure-redis-using-configmap/).
@@ -23,16 +23,10 @@ authenticated by the apiserver as a particular User Account (currently this is
usually `admin`, unless your cluster administrator has customized your cluster). Processes in containers inside pods can also contact the apiserver.
When they do, they are authenticated as a particular Service Account (for example, `default`).
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
## Use the Default Service Account to access the API server.
@@ -129,7 +123,7 @@ then you will see that a token has automatically been created and is referenced
You may use authorization plugins to [set permissions on service accounts](/docs/reference/access-authn-authz/rbac/#service-account-permissions).
To use a non-default service account, simply set the `spec.serviceAccountName`
To use a non-default service account, set the `spec.serviceAccountName`
field of a pod to the name of the service account you wish to use.
The service account has to exist at the time the pod is created, or it will be rejected.
@@ -12,16 +12,10 @@ What's Kompose? It's a conversion tool for all things compose (namely Docker Com
More information can be found on the Kompose website at [http://kompose.io](http://kompose.io).
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
## Install Kompose
@@ -35,13 +29,13 @@ Kompose is released via GitHub on a three-week cycle, you can see all current re
```sh
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.21.0/kompose-linux-amd64 -o kompose
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-linux-amd64 -o kompose
# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.21.0/kompose-darwin-amd64 -o kompose
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-darwin-amd64 -o kompose
# Windows
curl -L https://github.com/kubernetes/kompose/releases/download/v1.21.0/kompose-windows-amd64.exe -o kompose.exe
curl -L https://github.com/kubernetes/kompose/releases/download/v1.22.0/kompose-windows-amd64.exe -o kompose.exe
chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose
@@ -49,7 +43,6 @@ sudo mv ./kompose /usr/local/bin/kompose
Alternatively, you can download the [tarball](https://github.com/kubernetes/kompose/releases).
{{% /tab %}}
{{% tab name="Build from source" %}}
@@ -87,8 +80,8 @@ On macOS you can install latest release via [Homebrew](https://brew.sh):
```bash
brew install kompose
```
{{% /tab %}}
{{< /tabs >}}
@@ -97,111 +90,117 @@ brew install kompose
In just a few steps, we'll take you from Docker Compose to Kubernetes. All
you need is an existing `docker-compose.yml` file.
1. Go to the directory containing your `docker-compose.yml` file. If you don't
have one, test using this one.
1. Go to the directory containing your `docker-compose.yml` file. If you don't have one, test using this one.
```yaml
version: "2"
```yaml
version: "2"
services:
services:
redis-master:
image: k8s.gcr.io/redis:e2e
ports:
- "6379"
redis-master:
image: k8s.gcr.io/redis:e2e
ports:
- "6379"
redis-slave:
image: gcr.io/google_samples/gb-redisslave:v3
ports:
- "6379"
environment:
- GET_HOSTS_FROM=dns
redis-slave:
image: gcr.io/google_samples/gb-redisslave:v3
ports:
- "6379"
environment:
- GET_HOSTS_FROM=dns
frontend:
image: gcr.io/google-samples/gb-frontend:v4
ports:
- "80:80"
environment:
- GET_HOSTS_FROM=dns
labels:
kompose.service.type: LoadBalancer
```
frontend:
image: gcr.io/google-samples/gb-frontend:v4
ports:
- "80:80"
environment:
- GET_HOSTS_FROM=dns
labels:
kompose.service.type: LoadBalancer
```
2. Run the `kompose up` command to deploy to Kubernetes directly, or skip to
the next step instead to generate a file to use with `kubectl`.
2. To convert the `docker-compose.yml` file to files that you can use with
`kubectl`, run `kompose convert` and then `kubectl apply -f <output file>`.
```bash
$ kompose up
We are going to create Kubernetes Deployments, Services and PersistentVolumeClaims for your Dockerized application.
If you need different kind of resources, use the 'kompose convert' and 'kubectl apply -f' commands instead.
```bash
kompose convert
```
INFO Successfully created Service: redis
INFO Successfully created Service: web
INFO Successfully created Deployment: redis
INFO Successfully created Deployment: web
The output is similar to:
Your application has been deployed to Kubernetes. You can run 'kubectl get deployment,svc,pods,pvc' for details.
```
```none
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
```
3. To convert the `docker-compose.yml` file to files that you can use with
`kubectl`, run `kompose convert` and then `kubectl apply -f <output file>`.
```bash
kubectl apply -f frontend-service.yaml,redis-master-service.yaml,redis-slave-service.yaml,frontend-deployment.yaml,
```
```bash
$ kompose convert
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
```
The output is similar to:
```bash
$ kubectl apply -f frontend-service.yaml,redis-master-service.yaml,redis-slave-service.yaml,frontend-deployment.yaml,redis-master-deployment.yaml,redis-slave-deployment.yaml
service/frontend created
service/redis-master created
service/redis-slave created
deployment.apps/frontend created
deployment.apps/redis-master created
deployment.apps/redis-slave created
```
```none
redis-master-deployment.yaml,redis-slave-deployment.yaml
service/frontend created
service/redis-master created
service/redis-slave created
deployment.apps/frontend created
deployment.apps/redis-master created
deployment.apps/redis-slave created
```
Your deployments are running in Kubernetes.
Your deployments are running in Kubernetes.
4. Access your application.
3. Access your application.
If you're already using `minikube` for your development process:
If you're already using `minikube` for your development process:
```bash
$ minikube service frontend
```
```bash
minikube service frontend
```
Otherwise, let's look up what IP your service is using!
Otherwise, let's look up what IP your service is using!
```sh
$ kubectl describe svc frontend
Name: frontend
Namespace: default
Labels: service=frontend
Selector: service=frontend
Type: LoadBalancer
IP: 10.0.0.183
LoadBalancer Ingress: 192.0.2.89
Port: 80 80/TCP
NodePort: 80 31144/TCP
Endpoints: 172.17.0.4:80
Session Affinity: None
No events.
```sh
kubectl describe svc frontend
```
```
If you're using a cloud provider, your IP will be listed next to `LoadBalancer Ingress`.
```sh
$ curl http://192.0.2.89
```
```none
Name: frontend
Namespace: default
Labels: service=frontend
Selector: service=frontend
Type: LoadBalancer
IP: 10.0.0.183
LoadBalancer Ingress: 192.0.2.89
Port: 80 80/TCP
NodePort: 80 31144/TCP
Endpoints: 172.17.0.4:80
Session Affinity: None
No events.
```
If you're using a cloud provider, your IP will be listed next to `LoadBalancer Ingress`.
```sh
curl http://192.0.2.89
```
<!-- discussion -->
@@ -221,15 +220,17 @@ you need is an existing `docker-compose.yml` file.
Kompose has support for two providers: OpenShift and Kubernetes.
You can choose a targeted provider using global option `--provider`. If no provider is specified, Kubernetes is set by default.
## `kompose convert`
Kompose supports conversion of V1, V2, and V3 Docker Compose files into Kubernetes and OpenShift objects.
### Kubernetes
### Kubernetes `kompose convert` example
```sh
$ kompose --file docker-voting.yml convert
```shell
kompose --file docker-voting.yml convert
```
```none
WARN Unsupported key networks - ignoring
WARN Unsupported key build - ignoring
INFO Kubernetes file "worker-svc.yaml" created
@@ -242,16 +243,24 @@ INFO Kubernetes file "result-deployment.yaml" created
INFO Kubernetes file "vote-deployment.yaml" created
INFO Kubernetes file "worker-deployment.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
```
$ ls
```shell
ls
```
```none
db-deployment.yaml docker-compose.yml docker-gitlab.yml redis-deployment.yaml result-deployment.yaml vote-deployment.yaml worker-deployment.yaml
db-svc.yaml docker-voting.yml redis-svc.yaml result-svc.yaml vote-svc.yaml worker-svc.yaml
```
You can also provide multiple docker-compose files at the same time:
```sh
$ kompose -f docker-compose.yml -f docker-guestbook.yml convert
```shell
kompose -f docker-compose.yml -f docker-guestbook.yml convert
```
```none
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "mlbparks-service.yaml" created
INFO Kubernetes file "mongodb-service.yaml" created
@@ -263,8 +272,13 @@ INFO Kubernetes file "mongodb-deployment.yaml" created
INFO Kubernetes file "mongodb-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
```
$ ls
```shell
ls
```
```none
mlbparks-deployment.yaml mongodb-service.yaml redis-slave-service.jsonmlbparks-service.yaml
frontend-deployment.yaml mongodb-claim0-persistentvolumeclaim.yaml redis-master-service.yaml
frontend-service.yaml mongodb-deployment.yaml redis-slave-deployment.yaml
@@ -273,10 +287,13 @@ redis-master-deployment.yaml
When multiple docker-compose files are provided the configuration is merged. Any configuration that is common will be over ridden by subsequent file.
### OpenShift
### OpenShift `kompose convert` example
```sh
$ kompose --provider openshift --file docker-voting.yml convert
kompose --provider openshift --file docker-voting.yml convert
```
```none
WARN [worker] Service cannot be created because of missing port.
INFO OpenShift file "vote-service.yaml" created
INFO OpenShift file "db-service.yaml" created
@@ -297,7 +314,10 @@ INFO OpenShift file "result-imagestream.yaml" created
It also supports creating buildconfig for build directive in a service. By default, it uses the remote repo for the current git branch as the source repo, and the current branch as the source branch for the build. You can specify a different source repo and branch using ``--build-repo`` and ``--build-branch`` options respectively.
```sh
$ kompose --provider openshift --file buildconfig/docker-compose.yml convert
kompose --provider openshift --file buildconfig/docker-compose.yml convert
```
```none
WARN [foo] Service cannot be created because of missing port.
INFO OpenShift Buildconfig using git@github.com:rtnpro/kompose.git::master as source.
INFO OpenShift file "foo-deploymentconfig.yaml" created
@@ -313,23 +333,31 @@ If you are manually pushing the OpenShift artifacts using ``oc create -f``, you
Kompose supports a straightforward way to deploy your "composed" application to Kubernetes or OpenShift via `kompose up`.
### Kubernetes `kompose up` example
### Kubernetes
```sh
$ kompose --file ./examples/docker-guestbook.yml up
```shell
kompose --file ./examples/docker-guestbook.yml up
```
```none
We are going to create Kubernetes deployments and services for your Dockerized application.
If you need different kind of resources, use the 'kompose convert' and 'kubectl apply -f' commands instead.
INFO Successfully created service: redis-master
INFO Successfully created service: redis-slave
INFO Successfully created service: frontend
INFO Successfully created service: redis-master
INFO Successfully created service: redis-slave
INFO Successfully created service: frontend
INFO Successfully created deployment: redis-master
INFO Successfully created deployment: redis-slave
INFO Successfully created deployment: frontend
INFO Successfully created deployment: frontend
Your application has been deployed to Kubernetes. You can run 'kubectl get deployment,svc,pods' for details.
```
$ kubectl get deployment,svc,pods
```shell
kubectl get deployment,svc,pods
```
```none
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.extensions/frontend 1 1 1 1 4m
deployment.extensions/redis-master 1 1 1 1 4m
@@ -347,14 +375,19 @@ pod/redis-master-1432129712-63jn8 1/1 Running 0 4m
pod/redis-slave-2504961300-nve7b 1/1 Running 0 4m
```
**Note**:
{{< note >}}
- You must have a running Kubernetes cluster with a pre-configured kubectl context.
- Only deployments and services are generated and deployed to Kubernetes. If you need different kind of resources, use the `kompose convert` and `kubectl apply -f` commands instead.
{{< /note >}}
### OpenShift
```sh
$ kompose --file ./examples/docker-guestbook.yml --provider openshift up
### OpenShift `kompose up` example
```shell
kompose --file ./examples/docker-guestbook.yml --provider openshift up
```
```none
We are going to create OpenShift DeploymentConfigs and Services for your Dockerized application.
If you need different kind of resources, use the 'kompose convert' and 'oc create -f' commands instead.
@@ -369,8 +402,13 @@ INFO Successfully created deployment: redis-master
INFO Successfully created ImageStream: redis-master
Your application has been deployed to OpenShift. You can run 'oc get dc,svc,is' for details.
```
$ oc get dc,svc,is
```shell
oc get dc,svc,is
```
```none
NAME REVISION DESIRED CURRENT TRIGGERED BY
dc/frontend 0 1 0 config,image(frontend:v4)
dc/redis-master 0 1 0 config,image(redis-master:e2e)
@@ -385,16 +423,16 @@ is/redis-master 172.30.12.200:5000/fff/redis-master
is/redis-slave 172.30.12.200:5000/fff/redis-slave v1
```
**Note**:
- You must have a running OpenShift cluster with a pre-configured `oc` context (`oc login`)
{{< note >}}
You must have a running OpenShift cluster with a pre-configured `oc` context (`oc login`).
{{< /note >}}
## `kompose down`
Once you have deployed "composed" application to Kubernetes, `$ kompose down` will help you to take the application out by deleting its deployments and services. If you need to remove other resources, use the 'kubectl' command.
Once you have deployed "composed" application to Kubernetes, `kompose down` will help you to take the application out by deleting its deployments and services. If you need to remove other resources, use the 'kubectl' command.
```sh
$ kompose --file docker-guestbook.yml down
```shell
kompose --file docker-guestbook.yml down
INFO Successfully deleted service: redis-master
INFO Successfully deleted deployment: redis-master
INFO Successfully deleted service: redis-slave
@@ -403,16 +441,16 @@ INFO Successfully deleted service: frontend
INFO Successfully deleted deployment: frontend
```
**Note**:
- You must have a running Kubernetes cluster with a pre-configured kubectl context.
{{< note >}}
You must have a running Kubernetes cluster with a pre-configured `kubectl` context.
{{< /note >}}
## Build and Push Docker Images
Kompose supports both building and pushing Docker images. When using the `build` key within your Docker Compose file, your image will:
- Automatically be built with Docker using the `image` key specified within your file
- Be pushed to the correct Docker repository using local credentials (located at `.docker/config`)
- Automatically be built with Docker using the `image` key specified within your file
- Be pushed to the correct Docker repository using local credentials (located at `.docker/config`)
Using an [example Docker Compose file](https://raw.githubusercontent.com/kubernetes/kompose/master/examples/buildconfig/docker-compose.yml):
@@ -428,7 +466,7 @@ services:
Using `kompose up` with a `build` key:
```none
$ kompose up
kompose up
INFO Build key detected. Attempting to build and push image 'docker.io/foo/bar'
INFO Building image 'docker.io/foo/bar' from directory 'build'
INFO Image 'docker.io/foo/bar' from directory 'build' built successfully
@@ -448,10 +486,10 @@ In order to disable the functionality, or choose to use BuildConfig generation (
```sh
# Disable building/pushing Docker images
$ kompose up --build none
kompose up --build none
# Generate Build Config artifacts for OpenShift
$ kompose up --provider openshift --build build-config
kompose up --provider openshift --build build-config
```
## Alternative Conversions
@@ -459,45 +497,54 @@ $ kompose up --provider openshift --build build-config
The default `kompose` transformation will generate Kubernetes [Deployments](/docs/concepts/workloads/controllers/deployment/) and [Services](/docs/concepts/services-networking/service/), in yaml format. You have alternative option to generate json with `-j`. Also, you can alternatively generate [Replication Controllers](/docs/concepts/workloads/controllers/replicationcontroller/) objects, [Daemon Sets](/docs/concepts/workloads/controllers/daemonset/), or [Helm](https://github.com/helm/helm) charts.
```sh
$ kompose convert -j
kompose convert -j
INFO Kubernetes file "redis-svc.json" created
INFO Kubernetes file "web-svc.json" created
INFO Kubernetes file "redis-deployment.json" created
INFO Kubernetes file "web-deployment.json" created
```
The `*-deployment.json` files contain the Deployment objects.
```sh
$ kompose convert --replication-controller
kompose convert --replication-controller
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-replicationcontroller.yaml" created
INFO Kubernetes file "web-replicationcontroller.yaml" created
```
The `*-replicationcontroller.yaml` files contain the Replication Controller objects. If you want to specify replicas (default is 1), use `--replicas` flag: `$ kompose convert --replication-controller --replicas 3`
The `*-replicationcontroller.yaml` files contain the Replication Controller objects. If you want to specify replicas (default is 1), use `--replicas` flag: `kompose convert --replication-controller --replicas 3`
```sh
$ kompose convert --daemon-set
```shell
kompose convert --daemon-set
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-daemonset.yaml" created
INFO Kubernetes file "web-daemonset.yaml" created
```
The `*-daemonset.yaml` files contain the Daemon Set objects
The `*-daemonset.yaml` files contain the DaemonSet objects
If you want to generate a Chart to be used with [Helm](https://github.com/kubernetes/helm) simply do:
If you want to generate a Chart to be used with [Helm](https://github.com/kubernetes/helm) run:
```sh
$ kompose convert -c
```shell
kompose convert -c
```
```none
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-deployment.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
chart created in "./docker-compose/"
```
$ tree docker-compose/
```shell
tree docker-compose/
```
```none
docker-compose
├── Chart.yaml
├── README.md
@@ -578,7 +625,7 @@ If you want to create normal pods without controllers you can use `restart` cons
| `no` | Pod | `Never` |
{{< note >}}
The controller object could be `deployment` or `replicationcontroller`, etc.
The controller object could be `deployment` or `replicationcontroller`.
{{< /note >}}
For example, the `pival` service will become pod down here. This container calculated value of `pi`.
@@ -593,7 +640,7 @@ services:
restart: "on-failure"
```
### Warning about Deployment Config's
### Warning about Deployment Configurations
If the Docker Compose file has a volume specified for a service, the Deployment (Kubernetes) or DeploymentConfig (OpenShift) strategy is changed to "Recreate" instead of "RollingUpdate" (default). This is done to avoid multiple instances of a service from accessing a volume at the same time.
@@ -606,5 +653,3 @@ Please note that changing service name might break some `docker-compose` files.
Kompose supports Docker Compose versions: 1, 2 and 3. We have limited support on versions 2.1 and 3.2 due to their experimental nature.
A full list on compatibility between all three versions is listed in our [conversion document](https://github.com/kubernetes/kompose/blob/master/docs/conversion.md) including a list of all incompatible Docker Compose keys.
@@ -18,10 +18,10 @@ you to figure out what's going wrong.
## Running commands in a Pod
For many steps here you will want to see what a Pod running in the cluster
sees. The simplest way to do this is to run an interactive alpine Pod:
sees. The simplest way to do this is to run an interactive busybox Pod:
```none
kubectl run -it --rm --restart=Never alpine --image=alpine sh
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox sh
```
{{< note >}}
@@ -111,7 +111,7 @@ kubectl get pods -l app=hostnames \
10.244.0.7
```
The example container used for this walk-through simply serves its own hostname
The example container used for this walk-through serves its own hostname
via HTTP on port 9376, but if you are debugging your own app, you'll want to
use whatever port number your Pods are listening on.
@@ -421,7 +421,7 @@ Earlier you saw that the Pods were running. You can re-check that:
kubectl get pods -l app=hostnames
```
```none
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 1h
hostnames-632524106-ly40y 1/1 Running 0 1h
hostnames-632524106-tlaok 1/1 Running 0 1h
@@ -12,20 +12,15 @@ content_type: task
This guide demonstrates how to install and write extensions for [kubectl](/docs/reference/kubectl/kubectl/). By thinking of core `kubectl` commands as essential building blocks for interacting with a Kubernetes cluster, a cluster administrator can think
of plugins as a means of utilizing these building blocks to create more complex behavior. Plugins extend `kubectl` with new sub-commands, allowing for new and custom features not included in the main distribution of `kubectl`.
## {{% heading "prerequisites" %}}
You need to have a working `kubectl` binary installed.
<!-- steps -->
## Installing kubectl plugins
A plugin is nothing more than a standalone executable file, whose name begins with `kubectl-`. To install a plugin, simply move its executable file to anywhere on your `PATH`.
A plugin is a standalone executable file, whose name begins with `kubectl-`. To install a plugin, move its executable file to anywhere on your `PATH`.
You can also discover and install kubectl plugins available in the open source
using [Krew](https://krew.dev/). Krew is a plugin manager maintained by
@@ -60,9 +55,9 @@ You can write a plugin in any programming language or script that allows you to
There is no plugin installation or pre-loading required. Plugin executables receive
the inherited environment from the `kubectl` binary.
A plugin determines which command path it wishes to implement based on its name. For
example, a plugin wanting to provide a new command `kubectl foo`, would simply be named
`kubectl-foo`, and live somewhere in your `PATH`.
A plugin determines which command path it wishes to implement based on its name.
For example, a plugin named `kubectl-foo` provides a command `kubectl foo`. You must
install the plugin executable somewhere in your `PATH`.
### Example plugin
@@ -88,32 +83,34 @@ echo "I am a plugin named kubectl-foo"
### Using a plugin
To use the above plugin, simply make it executable:
To use a plugin, make the plugin executable:
```
```shell
sudo chmod +x ./kubectl-foo
```
and place it anywhere in your `PATH`:
```
```shell
sudo mv ./kubectl-foo /usr/local/bin
```
You may now invoke your plugin as a `kubectl` command:
```
```shell
kubectl foo
```
```
I am a plugin named kubectl-foo
```
All args and flags are passed as-is to the executable:
```
```shell
kubectl foo version
```
```
1.0.0
```
@@ -124,6 +121,7 @@ All environment variables are also passed as-is to the executable:
export KUBECONFIG=~/.kube/config
kubectl foo config
```
```
/home/<user>/.kube/config
```
@@ -131,6 +129,7 @@ kubectl foo config
```shell
KUBECONFIG=/etc/kube/config kubectl foo config
```
```
/etc/kube/config
```
@@ -376,16 +375,11 @@ set up a build environment (if it needs compiling), and deploy the plugin.
If you also make compiled packages available, or use Krew, that will make
installs easier.
## {{% heading "whatsnext" %}}
* Check the Sample CLI Plugin repository for a
[detailed example](https://github.com/kubernetes/sample-cli-plugin) of a
plugin written in Go.
In case of any questions, feel free to reach out to the
[SIG CLI team](https://github.com/kubernetes/community/tree/master/sig-cli).
* Read about [Krew](https://krew.dev/), a package manager for kubectl plugins.
@@ -12,7 +12,7 @@ based on a common template. You can use this approach to process batches of work
parallel.
For this example there are only three items: _apple_, _banana_, and _cherry_.
The sample Jobs process each item simply by printing a string then pausing.
The sample Jobs process each item by printing a string then pausing.
See [using Jobs in real workloads](#using-jobs-in-real-workloads) to learn about how
this pattern fits more realistic use cases.
@@ -66,7 +66,7 @@ Use caution when deleting a PVC, as it may lead to data loss.
### Complete deletion of a StatefulSet
To simply delete everything in a StatefulSet, including the associated pods, you can run a series of commands similar to the following:
To delete everything in a StatefulSet, including the associated pods, you can run a series of commands similar to the following:
```shell
grace=$(kubectl get pods <stateful-set-pod> --template '{{.spec.terminationGracePeriodSeconds}}')
@@ -383,7 +383,12 @@ behavior:
periodSeconds: 60
```
When the number of pods is more than 40 the second policy will be used for scaling down.
`periodSeconds` indicates the length of time in the past for which the policy must hold true.
The first policy _(Pods)_ allows at most 4 replicas to be scaled down in one minute. The second policy
_(Percent)_ allows at most 10% of the current replicas to be scaled down in one minute.
Since by default the policy which allows the highest amount of change is selected, the second policy will
only be used when the number of pod replicas is more than 40. With 40 or less replicas, the first policy will be applied.
For instance if there are 80 replicas and the target has to be scaled down to 10 replicas
then during the first step 8 replicas will be reduced. In the next iteration when the number
of replicas is 72, 10% of the pods is 7.2 but the number is rounded up to 8. On each loop of
@@ -391,10 +396,6 @@ the autoscaler controller the number of pods to be change is re-calculated based
of current replicas. When the number of replicas falls below 40 the first policy _(Pods)_ is applied
and 4 replicas will be reduced at a time.
`periodSeconds` indicates the length of time in the past for which the policy must hold true.
The first policy allows at most 4 replicas to be scaled down in one minute. The second policy
allows at most 10% of the current replicas to be scaled down in one minute.
The policy selection can be changed by specifying the `selectPolicy` field for a scaling
direction. By setting the value to `Min` which would select the policy which allows the
smallest change in the replica count. Setting the value to `Disabled` completely disables
@@ -441,7 +442,7 @@ behavior:
periodSeconds: 15
selectPolicy: Max
```
For scaling down the stabilization window is _300_ seconds(or the value of the
For scaling down the stabilization window is _300_ seconds (or the value of the
`--horizontal-pod-autoscaler-downscale-stabilization` flag if provided). There is only a single policy
for scaling down which allows a 100% of the currently running replicas to be removed which
means the scaling target can be scaled down to the minimum allowed replicas.
@@ -171,10 +171,10 @@ properties.
The script in the `init-mysql` container also applies either `primary.cnf` or
`replica.cnf` from the ConfigMap by copying the contents into `conf.d`.
Because the example topology consists of a single primary MySQL server and any number of
replicas, the script simply assigns ordinal `0` to be the primary server, and everyone
replicas, the script assigns ordinal `0` to be the primary server, and everyone
else to be replicas.
Combined with the StatefulSet controller's
[deployment order guarantee](/docs/concepts/workloads/controllers/statefulset/#deployment-and-scaling-guarantees/),
[deployment order guarantee](/docs/concepts/workloads/controllers/statefulset/#deployment-and-scaling-guarantees),
this ensures the primary MySQL server is Ready before creating replicas, so they can begin
replicating.
@@ -65,6 +65,8 @@ for a secure solution.
kubectl describe deployment mysql
The output is similar to this:
Name: mysql
Namespace: default
CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700
@@ -105,6 +107,8 @@ for a secure solution.
kubectl get pods -l app=mysql
The output is similar to this:
NAME READY STATUS RESTARTS AGE
mysql-63082529-2z3ki 1/1 Running 0 3m
@@ -112,6 +116,8 @@ for a secure solution.
kubectl describe pvc mysql-pv-claim
The output is similar to this:
Name: mysql-pv-claim
Namespace: default
StorageClass:
@@ -51,7 +51,6 @@ a Deployment that runs the nginx:1.14.2 Docker image:
The output is similar to this:
user@computer:~/website$ kubectl describe deployment nginx-deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700
@@ -51,12 +51,12 @@ Configurations with a single API server will experience unavailability while the
If any pods are started before new CA is used by API servers, they will get this update and trust both old and new CAs.
```shell
base64_encoded_ca="$(base64 <path to file containing both old and new CAs>)"
base64_encoded_ca="$(base64 -w0 <path to file containing both old and new CAs>)"
for namespace in $(kubectl get ns --no-headers | awk '{print $1}'); do
for token in $(kubectl get secrets --namespace "$namespace" --field-selector type=kubernetes.io/service-account-token -o name); do
kubectl get $token --namespace "$namespace" -o yaml | \
/bin/sed "s/\(ca.crt:\).*/\1 ${base64_encoded_ca}" | \
/bin/sed "s/\(ca.crt:\).*/\1 ${base64_encoded_ca}/" | \
kubectl apply -f -
done
done
@@ -132,10 +132,10 @@ Configurations with a single API server will experience unavailability while the
1. If your cluster is using bootstrap tokens to join nodes, update the ConfigMap `cluster-info` in the `kube-public` namespace with new CA.
```shell
base64_encoded_ca="$(base64 /etc/kubernetes/pki/ca.crt)"
base64_encoded_ca="$(base64 -w0 /etc/kubernetes/pki/ca.crt)"
kubectl get cm/cluster-info --namespace kube-public -o yaml | \
/bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}" | \
/bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}/" | \
kubectl apply -f -
```
+1 -1
View File
@@ -33,7 +33,7 @@ Before walking through each tutorial, you may want to bookmark the
* [Exposing an External IP Address to Access an Application in a Cluster](/docs/tutorials/stateless-application/expose-external-ip-address/)
* [Example: Deploying PHP Guestbook application with Redis](/docs/tutorials/stateless-application/guestbook/)
* [Example: Deploying PHP Guestbook application with MongoDB](/docs/tutorials/stateless-application/guestbook/)
## Stateful Applications
@@ -168,8 +168,7 @@ k8s-apparmor-example-deny-write (enforce)
*This example assumes you have already set up a cluster with AppArmor support.*
First, we need to load the profile we want to use onto our nodes. The profile we'll use simply
denies all file writes:
First, we need to load the profile we want to use onto our nodes. This profile denies all file writes:
```shell
#include <tunables/global>
@@ -63,13 +63,7 @@ weight: 10
<h3>Services and Labels</h3>
</div>
</div>
<div class="row">
<div class="col-md-8">
<p><img src="/docs/tutorials/kubernetes-basics/public/images/module_04_services.svg" width="150%" height="150%"></p>
</div>
</div>
<div class="row">
<div class="col-md-8">
<p>A Service routes traffic across a set of Pods. Services are the abstraction that allow pods to die and replicate in Kubernetes without impacting your application. Discovery and routing among dependent Pods (such as the frontend and backend components in an application) is handled by Kubernetes Services.</p>
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 79 KiB

@@ -934,10 +934,10 @@ web-2 0/1 Terminating 0 3m
When the `web` StatefulSet was recreated, it first relaunched `web-0`.
Since `web-1` was already Running and Ready, when `web-0` transitioned to
Running and Ready, it simply adopted this Pod. Since you recreated the StatefulSet
with `replicas` equal to 2, once `web-0` had been recreated, and once
`web-1` had been determined to already be Running and Ready, `web-2` was
terminated.
Running and Ready, it adopted this Pod. Since you recreated the StatefulSet
with `replicas` equal to 2, once `web-0` had been recreated, and once
`web-1` had been determined to already be Running and Ready, `web-2` was
terminated.
Let's take another look at the contents of the `index.html` file served by the
Pods' webservers:
@@ -945,6 +945,7 @@ Pods' webservers:
```shell
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
```
```
web-0
web-1
@@ -970,15 +971,18 @@ In another terminal, delete the StatefulSet again. This time, omit the
```shell
kubectl delete statefulset web
```
```
statefulset.apps "web" deleted
```
Examine the output of the `kubectl get` command running in the first terminal,
and wait for all of the Pods to transition to Terminating.
```shell
kubectl get pods -w -l app=nginx
```
```
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 11m
@@ -1006,10 +1010,10 @@ the cascade does not delete the headless Service associated with the StatefulSet
You must delete the `nginx` Service manually.
{{< /note >}}
```shell
kubectl delete service nginx
```
```
service "nginx" deleted
```
@@ -1019,6 +1023,7 @@ Recreate the StatefulSet and headless Service one more time:
```shell
kubectl apply -f web.yaml
```
```
service/nginx created
statefulset.apps/web created
@@ -1030,6 +1035,7 @@ the contents of their `index.html` files:
```shell
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
```
```
web-0
web-1
@@ -1044,13 +1050,17 @@ Finally, delete the `nginx` Service...
```shell
kubectl delete service nginx
```
```
service "nginx" deleted
```
...and the `web` StatefulSet:
```shell
kubectl delete statefulset web
```
```
statefulset "web" deleted
```
@@ -1,460 +0,0 @@
---
title: "Example: Add logging and metrics to the PHP / Redis Guestbook example"
reviewers:
- sftim
content_type: tutorial
weight: 21
card:
name: tutorials
weight: 31
title: "Example: Add logging and metrics to the PHP / Redis Guestbook example"
---
<!-- overview -->
This tutorial builds upon the [PHP Guestbook with Redis](/docs/tutorials/stateless-application/guestbook) tutorial. Lightweight log, metric, and network data open source shippers, or *Beats*, from Elastic are deployed in the same Kubernetes cluster as the guestbook. The Beats collect, parse, and index the data into Elasticsearch so that you can view and analyze the resulting operational information in Kibana. This example consists of the following components:
* A running instance of the [PHP Guestbook with Redis tutorial](/docs/tutorials/stateless-application/guestbook)
* Elasticsearch and Kibana
* Filebeat
* Metricbeat
* Packetbeat
## {{% heading "objectives" %}}
* Start up the PHP Guestbook with Redis.
* Install kube-state-metrics.
* Create a Kubernetes Secret.
* Deploy the Beats.
* View dashboards of your logs and metrics.
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
{{< version-check >}}
Additionally you need:
* A running deployment of the [PHP Guestbook with Redis](/docs/tutorials/stateless-application/guestbook) tutorial.
* A running Elasticsearch and Kibana deployment. You can use [Elasticsearch Service in Elastic Cloud](https://cloud.elastic.co),
run the [downloaded files](https://www.elastic.co/guide/en/elastic-stack-get-started/current/get-started-elastic-stack.html)
on your workstation or servers, or the [Elastic Helm Charts](https://github.com/elastic/helm-charts).
<!-- lessoncontent -->
## Start up the PHP Guestbook with Redis
This tutorial builds on the [PHP Guestbook with Redis](/docs/tutorials/stateless-application/guestbook) tutorial. If you have the guestbook application running, then you can monitor that. If you do not have it running then follow the instructions to deploy the guestbook and do not perform the **Cleanup** steps. Come back to this page when you have the guestbook running.
## Add a Cluster role binding
Create a [cluster level role binding](/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) so that you can deploy kube-state-metrics and the Beats at the cluster level (in kube-system).
```shell
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin --user=<your email associated with the k8s provider account>
```
## Install kube-state-metrics
Kubernetes [*kube-state-metrics*](https://github.com/kubernetes/kube-state-metrics) is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. Metricbeat reports these metrics. Add kube-state-metrics to the Kubernetes cluster that the guestbook is running in.
```shell
git clone https://github.com/kubernetes/kube-state-metrics.git kube-state-metrics
kubectl apply -f kube-state-metrics/examples/standard
```
### Check to see if kube-state-metrics is running
```shell
kubectl get pods --namespace=kube-system -l app.kubernetes.io/name=kube-state-metrics
```
Output:
```
NAME READY STATUS RESTARTS AGE
kube-state-metrics-89d656bf8-vdthm 1/1 Running 0 21s
```
## Clone the Elastic examples GitHub repo
```shell
git clone https://github.com/elastic/examples.git
```
The rest of the commands will reference files in the `examples/beats-k8s-send-anywhere` directory, so change dir there:
```shell
cd examples/beats-k8s-send-anywhere
```
## Create a Kubernetes Secret
A Kubernetes {{< glossary_tooltip text="Secret" term_id="secret" >}} is an object that contains a small amount of sensitive data such as a password, a token, or a key. Such information might otherwise be put in a Pod specification or in an image; putting it in a Secret object allows for more control over how it is used, and reduces the risk of accidental exposure.
{{< note >}}
There are two sets of steps here, one for *self managed* Elasticsearch and Kibana (running on your servers or using the Elastic Helm Charts), and a second separate set for the *managed service* Elasticsearch Service in Elastic Cloud. Only create the secret for the type of Elasticsearch and Kibana system that you will use for this tutorial.
{{< /note >}}
{{< tabs name="tab_with_md" >}}
{{% tab name="Self Managed" %}}
### Self managed
Switch to the **Managed service** tab if you are connecting to Elasticsearch Service in Elastic Cloud.
### Set the credentials
There are four files to edit to create a k8s secret when you are connecting to self managed Elasticsearch and Kibana (self managed is effectively anything other than the managed Elasticsearch Service in Elastic Cloud). The files are:
1. `ELASTICSEARCH_HOSTS`
1. `ELASTICSEARCH_PASSWORD`
1. `ELASTICSEARCH_USERNAME`
1. `KIBANA_HOST`
Set these with the information for your Elasticsearch cluster and your Kibana host. Here are some examples (also see [*this configuration*](https://stackoverflow.com/questions/59892896/how-to-connect-from-minikube-to-elasticsearch-installed-on-host-local-developme/59892897#59892897))
#### `ELASTICSEARCH_HOSTS`
1. A nodeGroup from the Elastic Elasticsearch Helm Chart:
```
["http://elasticsearch-master.default.svc.cluster.local:9200"]
```
1. A single Elasticsearch node running on a Mac where your Beats are running in Docker for Mac:
```
["http://host.docker.internal:9200"]
```
1. Two Elasticsearch nodes running in VMs or on physical hardware:
```
["http://host1.example.com:9200", "http://host2.example.com:9200"]
```
Edit `ELASTICSEARCH_HOSTS`:
```shell
vi ELASTICSEARCH_HOSTS
```
#### `ELASTICSEARCH_PASSWORD`
Just the password; no whitespace, quotes, `<` or `>`:
```
<yoursecretpassword>
```
Edit `ELASTICSEARCH_PASSWORD`:
```shell
vi ELASTICSEARCH_PASSWORD
```
#### `ELASTICSEARCH_USERNAME`
Just the username; no whitespace, quotes, `<` or `>`:
```
<your ingest username for Elasticsearch>
```
Edit `ELASTICSEARCH_USERNAME`:
```shell
vi ELASTICSEARCH_USERNAME
```
#### `KIBANA_HOST`
1. The Kibana instance from the Elastic Kibana Helm Chart. The subdomain `default` refers to the default namespace. If you have deployed the Helm Chart using a different namespace, then your subdomain will be different:
```
"kibana-kibana.default.svc.cluster.local:5601"
```
1. A Kibana instance running on a Mac where your Beats are running in Docker for Mac:
```
"host.docker.internal:5601"
```
1. Two Elasticsearch nodes running in VMs or on physical hardware:
```
"host1.example.com:5601"
```
Edit `KIBANA_HOST`:
```shell
vi KIBANA_HOST
```
### Create a Kubernetes Secret
This command creates a Secret in the Kubernetes system level namespace (`kube-system`) based on the files you just edited:
```shell
kubectl create secret generic dynamic-logging \
--from-file=./ELASTICSEARCH_HOSTS \
--from-file=./ELASTICSEARCH_PASSWORD \
--from-file=./ELASTICSEARCH_USERNAME \
--from-file=./KIBANA_HOST \
--namespace=kube-system
```
{{% /tab %}}
{{% tab name="Managed service" %}}
## Managed service
This tab is for Elasticsearch Service in Elastic Cloud only, if you have already created a secret for a self managed Elasticsearch and Kibana deployment, then continue with [Deploy the Beats](#deploy-the-beats).
### Set the credentials
There are two files to edit to create a Kubernetes Secret when you are connecting to the managed Elasticsearch Service in Elastic Cloud. The files are:
1. `ELASTIC_CLOUD_AUTH`
1. `ELASTIC_CLOUD_ID`
Set these with the information provided to you from the Elasticsearch Service console when you created the deployment. Here are some examples:
#### `ELASTIC_CLOUD_ID`
```
devk8s:ABC123def456ghi789jkl123mno456pqr789stu123vwx456yza789bcd012efg345hijj678klm901nop345zEwOTJjMTc5YWQ0YzQ5OThlN2U5MjAwYTg4NTIzZQ==
```
#### `ELASTIC_CLOUD_AUTH`
Just the username, a colon (`:`), and the password, no whitespace or quotes:
```
elastic:VFxJJf9Tjwer90wnfTghsn8w
```
### Edit the required files:
```shell
vi ELASTIC_CLOUD_ID
vi ELASTIC_CLOUD_AUTH
```
### Create a Kubernetes Secret
This command creates a Secret in the Kubernetes system level namespace (`kube-system`) based on the files you just edited:
```shell
kubectl create secret generic dynamic-logging \
--from-file=./ELASTIC_CLOUD_ID \
--from-file=./ELASTIC_CLOUD_AUTH \
--namespace=kube-system
```
{{% /tab %}}
{{< /tabs >}}
## Deploy the Beats
Manifest files are provided for each Beat. These manifest files use the secret created earlier to configure the Beats to connect to your Elasticsearch and Kibana servers.
### About Filebeat
Filebeat will collect logs from the Kubernetes nodes and the containers running in each pod running on those nodes. Filebeat is deployed as a {{< glossary_tooltip text="DaemonSet" term_id="daemonset" >}}. Filebeat can autodiscover applications running in your Kubernetes cluster. At startup Filebeat scans existing containers and launches the proper configurations for them, then it will watch for new start/stop events.
Here is the autodiscover configuration that enables Filebeat to locate and parse Redis logs from the Redis containers deployed with the guestbook application. This configuration is in the file `filebeat-kubernetes.yaml`:
```yaml
- condition.contains:
kubernetes.labels.app: redis
config:
- module: redis
log:
input:
type: docker
containers.ids:
- ${data.kubernetes.container.id}
slowlog:
enabled: true
var.hosts: ["${data.host}:${data.port}"]
```
This configures Filebeat to apply the Filebeat module `redis` when a container is detected with a label `app` containing the string `redis`. The redis module has the ability to collect the `log` stream from the container by using the docker input type (reading the file on the Kubernetes node associated with the STDOUT stream from this Redis container). Additionally, the module has the ability to collect Redis `slowlog` entries by connecting to the proper pod host and port, which is provided in the container metadata.
### Deploy Filebeat:
```shell
kubectl create -f filebeat-kubernetes.yaml
```
#### Verify
```shell
kubectl get pods -n kube-system -l k8s-app=filebeat-dynamic
```
### About Metricbeat
Metricbeat autodiscover is configured in the same way as Filebeat. Here is the Metricbeat autodiscover configuration for the Redis containers. This configuration is in the file `metricbeat-kubernetes.yaml`:
```yaml
- condition.equals:
kubernetes.labels.tier: backend
config:
- module: redis
metricsets: ["info", "keyspace"]
period: 10s
# Redis hosts
hosts: ["${data.host}:${data.port}"]
```
This configures Metricbeat to apply the Metricbeat module `redis` when a container is detected with a label `tier` equal to the string `backend`. The `redis` module has the ability to collect the `info` and `keyspace` metrics from the container by connecting to the proper pod host and port, which is provided in the container metadata.
### Deploy Metricbeat
```shell
kubectl create -f metricbeat-kubernetes.yaml
```
#### Verify
```shell
kubectl get pods -n kube-system -l k8s-app=metricbeat
```
### About Packetbeat
Packetbeat configuration is different than Filebeat and Metricbeat. Rather than specify patterns to match against container labels the configuration is based on the protocols and port numbers involved. Shown below is a subset of the port numbers.
{{< note >}}
If you are running a service on a non-standard port add that port number to the appropriate type in `filebeat.yaml` and delete/create the Packetbeat DaemonSet.
{{< /note >}}
```yaml
packetbeat.interfaces.device: any
packetbeat.protocols:
- type: dns
ports: [53]
include_authorities: true
include_additionals: true
- type: http
ports: [80, 8000, 8080, 9200]
- type: mysql
ports: [3306]
- type: redis
ports: [6379]
packetbeat.flows:
timeout: 30s
period: 10s
```
#### Deploy Packetbeat
```shell
kubectl create -f packetbeat-kubernetes.yaml
```
#### Verify
```shell
kubectl get pods -n kube-system -l k8s-app=packetbeat-dynamic
```
## View in Kibana
Open Kibana in your browser and then open the **Dashboard** application. In the search bar type Kubernetes and click on the Metricbeat dashboard for Kubernetes. This dashboard reports on the state of your Nodes, deployments, etc.
Search for Packetbeat on the Dashboard page, and view the Packetbeat overview.
Similarly, view dashboards for Apache and Redis. You will see dashboards for logs and metrics for each. The Apache Metricbeat dashboard will be blank. Look at the Apache Filebeat dashboard and scroll to the bottom to view the Apache error logs. This will tell you why there are no metrics available for Apache.
To enable Metricbeat to retrieve the Apache metrics, enable server-status by adding a ConfigMap including a mod-status configuration file and re-deploy the guestbook.
## Scale your Deployments and see new pods being monitored
List the existing Deployments:
```shell
kubectl get deployments
```
The output:
```
NAME READY UP-TO-DATE AVAILABLE AGE
frontend 3/3 3 3 3h27m
redis-master 1/1 1 1 3h27m
redis-slave 2/2 2 2 3h27m
```
Scale the frontend down to two pods:
```shell
kubectl scale --replicas=2 deployment/frontend
```
The output:
```
deployment.extensions/frontend scaled
```
Scale the frontend back up to three pods:
```shell
kubectl scale --replicas=3 deployment/frontend
```
## View the changes in Kibana
See the screenshot, add the indicated filters and then add the columns to the view. You can see the ScalingReplicaSet entry that is marked, following from there to the top of the list of events shows the image being pulled, the volumes mounted, the pod starting, etc.
![Kibana Discover](https://raw.githubusercontent.com/elastic/examples/master/beats-k8s-send-anywhere/scaling-up.png)
## {{% heading "cleanup" %}}
Deleting the Deployments and Services also deletes any running Pods. Use labels to delete multiple resources with one command.
1. Run the following commands to delete all Pods, Deployments, and Services.
```shell
kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment -l app=guestbook
kubectl delete service -l app=guestbook
kubectl delete -f filebeat-kubernetes.yaml
kubectl delete -f metricbeat-kubernetes.yaml
kubectl delete -f packetbeat-kubernetes.yaml
kubectl delete secret dynamic-logging -n kube-system
```
1. Query the list of Pods to verify that no Pods are running:
```shell
kubectl get pods
```
The response should be this:
```
No resources found.
```
## {{% heading "whatsnext" %}}
* Learn about [tools for monitoring resources](/docs/tasks/debug-application-cluster/resource-usage-monitoring/)
* Read more about [logging architecture](/docs/concepts/cluster-administration/logging/)
* Read more about [application introspection and debugging](/docs/tasks/debug-application-cluster/)
* Read more about [troubleshoot applications](/docs/tasks/debug-application-cluster/resource-usage-monitoring/)
@@ -1,5 +1,5 @@
---
title: "Example: Deploying PHP Guestbook application with Redis"
title: "Example: Deploying PHP Guestbook application with MongoDB"
reviewers:
- ahmetb
content_type: tutorial
@@ -7,22 +7,19 @@ weight: 20
card:
name: tutorials
weight: 30
title: "Stateless Example: PHP Guestbook with Redis"
title: "Stateless Example: PHP Guestbook with MongoDB"
min-kubernetes-server-version: v1.14
---
<!-- overview -->
This tutorial shows you how to build and deploy a simple, multi-tier web application using Kubernetes and [Docker](https://www.docker.com/). This example consists of the following components:
This tutorial shows you how to build and deploy a simple _(not production ready)_, multi-tier web application using Kubernetes and [Docker](https://www.docker.com/). This example consists of the following components:
* A single-instance [Redis](https://redis.io/) master to store guestbook entries
* Multiple [replicated Redis](https://redis.io/topics/replication) instances to serve reads
* A single-instance [MongoDB](https://www.mongodb.com/) to store guestbook entries
* Multiple web frontend instances
## {{% heading "objectives" %}}
* Start up a Redis master.
* Start up Redis slaves.
* Start up a Mongo database.
* Start up the guestbook frontend.
* Expose and view the Frontend Service.
* Clean up.
@@ -39,24 +36,28 @@ This tutorial shows you how to build and deploy a simple, multi-tier web applica
<!-- lessoncontent -->
## Start up the Redis Master
## Start up the Mongo Database
The guestbook application uses Redis to store its data. It writes its data to a Redis master instance and reads data from multiple Redis slave instances.
The guestbook application uses MongoDB to store its data.
### Creating the Redis Master Deployment
### Creating the Mongo Deployment
The manifest file, included below, specifies a Deployment controller that runs a single replica Redis master Pod.
The manifest file, included below, specifies a Deployment controller that runs a single replica MongoDB Pod.
{{< codenew file="application/guestbook/redis-master-deployment.yaml" >}}
{{< codenew file="application/guestbook/mongo-deployment.yaml" >}}
1. Launch a terminal window in the directory you downloaded the manifest files.
1. Apply the Redis Master Deployment from the `redis-master-deployment.yaml` file:
1. Apply the MongoDB Deployment from the `mongo-deployment.yaml` file:
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-deployment.yaml
```
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-deployment.yaml
-->
1. Query the list of Pods to verify that the Redis Master Pod is running:
1. Query the list of Pods to verify that the MongoDB Pod is running:
```shell
kubectl get pods
@@ -66,32 +67,33 @@ The manifest file, included below, specifies a Deployment controller that runs a
```shell
NAME READY STATUS RESTARTS AGE
redis-master-1068406935-3lswp 1/1 Running 0 28s
mongo-5cfd459dd4-lrcjb 1/1 Running 0 28s
```
1. Run the following command to view the logs from the Redis Master Pod:
1. Run the following command to view the logs from the MongoDB Deployment:
```shell
kubectl logs -f POD-NAME
kubectl logs -f deployment/mongo
```
{{< note >}}
Replace POD-NAME with the name of your Pod.
{{< /note >}}
### Creating the MongoDB Service
### Creating the Redis Master Service
The guestbook application needs to communicate to the MongoDB to write its data. You need to apply a [Service](/docs/concepts/services-networking/service/) to proxy the traffic to the MongoDB Pod. A Service defines a policy to access the Pods.
The guestbook application needs to communicate to the Redis master to write its data. You need to apply a [Service](/docs/concepts/services-networking/service/) to proxy the traffic to the Redis master Pod. A Service defines a policy to access the Pods.
{{< codenew file="application/guestbook/mongo-service.yaml" >}}
{{< codenew file="application/guestbook/redis-master-service.yaml" >}}
1. Apply the Redis Master Service from the following `redis-master-service.yaml` file:
1. Apply the MongoDB Service from the following `mongo-service.yaml` file:
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-service.yaml
```
1. Query the list of Services to verify that the Redis Master Service is running:
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-service.yaml
-->
1. Query the list of Services to verify that the MongoDB Service is running:
```shell
kubectl get service
@@ -102,77 +104,17 @@ The guestbook application needs to communicate to the Redis master to write its
```shell
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
redis-master ClusterIP 10.0.0.151 <none> 6379/TCP 8s
mongo ClusterIP 10.0.0.151 <none> 6379/TCP 8s
```
{{< note >}}
This manifest file creates a Service named `redis-master` with a set of labels that match the labels previously defined, so the Service routes network traffic to the Redis master Pod.
This manifest file creates a Service named `mongo` with a set of labels that match the labels previously defined, so the Service routes network traffic to the MongoDB Pod.
{{< /note >}}
## Start up the Redis Slaves
Although the Redis master is a single pod, you can make it highly available to meet traffic demands by adding replica Redis slaves.
### Creating the Redis Slave Deployment
Deployments scale based off of the configurations set in the manifest file. In this case, the Deployment object specifies two replicas.
If there are not any replicas running, this Deployment would start the two replicas on your container cluster. Conversely, if there are more than two replicas running, it would scale down until two replicas are running.
{{< codenew file="application/guestbook/redis-slave-deployment.yaml" >}}
1. Apply the Redis Slave Deployment from the `redis-slave-deployment.yaml` file:
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-slave-deployment.yaml
```
1. Query the list of Pods to verify that the Redis Slave Pods are running:
```shell
kubectl get pods
```
The response should be similar to this:
```shell
NAME READY STATUS RESTARTS AGE
redis-master-1068406935-3lswp 1/1 Running 0 1m
redis-slave-2005841000-fpvqc 0/1 ContainerCreating 0 6s
redis-slave-2005841000-phfv9 0/1 ContainerCreating 0 6s
```
### Creating the Redis Slave Service
The guestbook application needs to communicate to Redis slaves to read data. To make the Redis slaves discoverable, you need to set up a Service. A Service provides transparent load balancing to a set of Pods.
{{< codenew file="application/guestbook/redis-slave-service.yaml" >}}
1. Apply the Redis Slave Service from the following `redis-slave-service.yaml` file:
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-slave-service.yaml
```
1. Query the list of Services to verify that the Redis slave service is running:
```shell
kubectl get services
```
The response should be similar to this:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 2m
redis-master ClusterIP 10.0.0.151 <none> 6379/TCP 1m
redis-slave ClusterIP 10.0.0.223 <none> 6379/TCP 6s
```
## Set up and Expose the Guestbook Frontend
The guestbook application has a web frontend serving the HTTP requests written in PHP. It is configured to connect to the `redis-master` Service for write requests and the `redis-slave` service for Read requests.
The guestbook application has a web frontend serving the HTTP requests written in PHP. It is configured to connect to the `mongo` Service to store Guestbook entries.
### Creating the Guestbook Frontend Deployment
@@ -184,6 +126,11 @@ The guestbook application has a web frontend serving the HTTP requests written i
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
```
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
-->
1. Query the list of Pods to verify that the three frontend replicas are running:
```shell
@@ -201,12 +148,12 @@ The guestbook application has a web frontend serving the HTTP requests written i
### Creating the Frontend Service
The `redis-slave` and `redis-master` Services you applied are only accessible within the container cluster because the default type for a Service is [ClusterIP](/docs/concepts/services-networking/service/#publishing-services---service-types). `ClusterIP` provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster.
The `mongo` Services you applied is only accessible within the Kubernetes cluster because the default type for a Service is [ClusterIP](/docs/concepts/services-networking/service/#publishing-services---service-types). `ClusterIP` provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster.
If you want guests to be able to access your guestbook, you must configure the frontend Service to be externally visible, so a client can request the Service from outside the container cluster. Minikube can only expose Services through `NodePort`.
If you want guests to be able to access your guestbook, you must configure the frontend Service to be externally visible, so a client can request the Service from outside the Kubernetes cluster. However a Kubernetes user you can use `kubectl port-forward` to access the service even though it uses a `ClusterIP`.
{{< note >}}
Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, support external load balancers. If your cloud provider supports load balancers and you want to use it, simply delete or comment out `type: NodePort`, and uncomment `type: LoadBalancer`.
Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, support external load balancers. If your cloud provider supports load balancers and you want to use it, uncomment `type: LoadBalancer`.
{{< /note >}}
{{< codenew file="application/guestbook/frontend-service.yaml" >}}
@@ -217,6 +164,11 @@ Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, su
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
```
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
-->
1. Query the list of Services to verify that the frontend Service is running:
```shell
@@ -227,29 +179,27 @@ Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, su
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend NodePort 10.0.0.112 <none> 80:31323/TCP 6s
frontend ClusterIP 10.0.0.112 <none> 80/TCP 6s
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 4m
redis-master ClusterIP 10.0.0.151 <none> 6379/TCP 2m
redis-slave ClusterIP 10.0.0.223 <none> 6379/TCP 1m
mongo ClusterIP 10.0.0.151 <none> 6379/TCP 2m
```
### Viewing the Frontend Service via `NodePort`
### Viewing the Frontend Service via `kubectl port-forward`
If you deployed this application to Minikube or a local cluster, you need to find the IP address to view your Guestbook.
1. Run the following command to get the IP address for the frontend Service.
1. Run the following command to forward port `8080` on your local machine to port `80` on the service.
```shell
minikube service frontend --url
kubectl port-forward svc/frontend 8080:80
```
The response should be similar to this:
```
http://192.168.99.100:31323
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```
1. Copy the IP address, and load the page in your browser to view your guestbook.
1. load the page [http://localhost:8080](http://localhost:8080) in your browser to view your guestbook.
### Viewing the Frontend Service via `LoadBalancer`
@@ -295,9 +245,7 @@ You can scale up or down as needed because your servers are defined as a Service
frontend-3823415956-k22zn 1/1 Running 0 54m
frontend-3823415956-w9gbt 1/1 Running 0 54m
frontend-3823415956-x2pld 1/1 Running 0 5s
redis-master-1068406935-3lswp 1/1 Running 0 56m
redis-slave-2005841000-fpvqc 1/1 Running 0 55m
redis-slave-2005841000-phfv9 1/1 Running 0 55m
mongo-1068406935-3lswp 1/1 Running 0 56m
```
1. Run the following command to scale down the number of frontend Pods:
@@ -318,9 +266,7 @@ You can scale up or down as needed because your servers are defined as a Service
NAME READY STATUS RESTARTS AGE
frontend-3823415956-k22zn 1/1 Running 0 1h
frontend-3823415956-w9gbt 1/1 Running 0 1h
redis-master-1068406935-3lswp 1/1 Running 0 1h
redis-slave-2005841000-fpvqc 1/1 Running 0 1h
redis-slave-2005841000-phfv9 1/1 Running 0 1h
mongo-1068406935-3lswp 1/1 Running 0 1h
```
@@ -332,20 +278,18 @@ Deleting the Deployments and Services also deletes any running Pods. Use labels
1. Run the following commands to delete all Pods, Deployments, and Services.
```shell
kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment -l app=guestbook
kubectl delete service -l app=guestbook
kubectl delete deployment -l app.kubernetes.io/name=mongo
kubectl delete service -l app.kubernetes.io/name=mongo
kubectl delete deployment -l app.kubernetes.io/name=guestbook
kubectl delete service -l app.kubernetes.io/name=guestbook
```
The responses should be:
```
deployment.apps "redis-master" deleted
deployment.apps "redis-slave" deleted
service "redis-master" deleted
service "redis-slave" deleted
deployment.apps "frontend" deleted
deployment.apps "mongo" deleted
service "mongo" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
@@ -365,7 +309,6 @@ Deleting the Deployments and Services also deletes any running Pods. Use labels
## {{% heading "whatsnext" %}}
* Add [ELK logging and monitoring](/docs/tutorials/stateless-application/guestbook-logs-metrics-with-elk/) to your Guestbook application
* Complete the [Kubernetes Basics](/docs/tutorials/kubernetes-basics/) Interactive Tutorials
* Use Kubernetes to create a blog using [Persistent Volumes for MySQL and Wordpress](/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog)
* Read more about [connecting applications](/docs/concepts/services-networking/connect-applications-service/)