mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-07-15 19:09:43 +00:00
Update for Kubernetes 1.18 kubectl run
In Kubernetes 1.18, `kubectl run` no longer creates a Deployment, and cannot create Jobs or CronJobs anymore. It only creates Pods. Since we were using `kubectl run` to create our first Deployment, I've changed the materials to explain that change, and explain how the behavior differs between 1.17- and 1.18+, since I expect that people will deal with a mix of both scenarios for a while (at least a year).
This commit is contained in:
@@ -10,14 +10,47 @@
|
||||
|
||||
- In that container in the pod, we are going to run a simple `ping` command
|
||||
|
||||
- Then we are going to start additional copies of the pod
|
||||
--
|
||||
|
||||
- Sounds simple enough, right?
|
||||
|
||||
--
|
||||
|
||||
- Except ... that the `kubectl run` command changed in Kubernetes 1.18!
|
||||
|
||||
- We'll explain what has changed, and why
|
||||
|
||||
---
|
||||
|
||||
## Choose your own adventure
|
||||
|
||||
- First, let's check which version of Kubernetes we're running
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check our API server version:
|
||||
```bash
|
||||
kubectl version
|
||||
```
|
||||
|
||||
- Look at the **Server Version** in the second part of the output
|
||||
|
||||
]
|
||||
|
||||
- In the following slides, we will talk about 1.17- or 1.18+
|
||||
|
||||
(to indicate "up to Kubernetes 1.17" and "from Kubernetes 1.18")
|
||||
|
||||
---
|
||||
|
||||
## Starting a simple pod with `kubectl run`
|
||||
|
||||
- `kubectl run` is convenient to start a single pod
|
||||
|
||||
- We need to specify at least a *name* and the image we want to use
|
||||
|
||||
- Optionally, we can specify the command to run in the pod
|
||||
|
||||
.exercise[
|
||||
|
||||
- Let's ping the address of `localhost`, the loopback interface:
|
||||
@@ -25,90 +58,289 @@
|
||||
kubectl run pingpong --image alpine ping 127.0.0.1
|
||||
```
|
||||
|
||||
<!-- ```hide kubectl wait deploy/pingpong --for condition=available``` -->
|
||||
<!-- ```hide kubectl wait pod --selector=run=pingpong --for condition=ready``` -->
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
---
|
||||
|
||||
(Starting with Kubernetes 1.12, we get a message telling us that
|
||||
`kubectl run` is deprecated. Let's ignore it for now.)
|
||||
## What do we see?
|
||||
|
||||
- In Kubernetes 1.18+, the output tells us that a Pod is created:
|
||||
```
|
||||
pod/pingpong created
|
||||
```
|
||||
|
||||
- In Kubernetes 1.17-, the output is much more verbose:
|
||||
```
|
||||
kubectl run --generator=deployment/apps.v1 is DEPRECATED
|
||||
and will be removed in a future version. Use kubectl run
|
||||
--generator=run-pod/v1 or kubectl create instead.
|
||||
deployment.apps/pingpong created
|
||||
```
|
||||
|
||||
- There is a deprecation warning ...
|
||||
|
||||
- ... And a Deployment was created instead of a Pod
|
||||
|
||||
🤔 What does that mean?
|
||||
|
||||
---
|
||||
|
||||
## Behind the scenes of `kubectl run`
|
||||
## Show me all you got!
|
||||
|
||||
- Let's look at the resources that were created by `kubectl run`
|
||||
- What resources were created by `kubectl run`?
|
||||
|
||||
.exercise[
|
||||
|
||||
- List most resource types:
|
||||
- Let's ask Kubernetes to show us *all* the resources:
|
||||
```bash
|
||||
kubectl get all
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Note: `kubectl get all` is a lie. It doesn't show everything.
|
||||
|
||||
(But it shows a lot of "usual suspects", i.e. commonly used resources.)
|
||||
|
||||
---
|
||||
|
||||
## The situation with Kubernetes 1.18+
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/pingpong 1/1 Running 0 9s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h30m
|
||||
```
|
||||
|
||||
We wanted a pod, we got a pod, named `pingpong`. Great!
|
||||
|
||||
(We can ignore `service/kubernetes`, it was already there before.)
|
||||
|
||||
---
|
||||
|
||||
## The situation with Kubernetes 1.17-
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/pingpong-6ccbc77f68-kmgfn 1/1 Running 0 11s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h45
|
||||
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/pingpong 1/1 1 1 11s
|
||||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/pingpong-6ccbc77f68 1 1 1 11s
|
||||
```
|
||||
|
||||
Our pod is not named `pingpong`, but `pingpong-xxxxxxxxxxx-yyyyy`.
|
||||
|
||||
We have a Deployment named `pingpong`, and an extra Replica Set, too. What's going on?
|
||||
|
||||
---
|
||||
|
||||
## From Deployment to Pod
|
||||
|
||||
We have the following resources:
|
||||
|
||||
- `deployment.apps/pingpong`
|
||||
|
||||
This is the Deployment that we just created.
|
||||
|
||||
- `replicaset.apps/pingpong-xxxxxxxxxx`
|
||||
|
||||
This is a Replica Set created by this Deployment.
|
||||
|
||||
- `pod/pingpong-xxxxxxxxxx-yyyyy`
|
||||
|
||||
This is a *pod* created by the Replica Set.
|
||||
|
||||
Let's explain what these things are.
|
||||
|
||||
---
|
||||
|
||||
## Pod
|
||||
|
||||
- Can have one or multiple containers
|
||||
|
||||
- Runs on a single node
|
||||
|
||||
(Pod cannot "straddle" multiple nodes)
|
||||
|
||||
- Pods cannot be moved
|
||||
|
||||
(e.g. in case of node outage)
|
||||
|
||||
- Pods cannot be scaled
|
||||
|
||||
(except by manually creating more Pods)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## Pod details
|
||||
|
||||
- A Pod is not a process; it's an environment for containers
|
||||
|
||||
- it cannot be "restarted"
|
||||
|
||||
- it cannot "crash"
|
||||
|
||||
- The containers in a Pod can crash
|
||||
|
||||
- They may or may not get restarted
|
||||
|
||||
(depending on Pod's restart policy)
|
||||
|
||||
- If all containers exit successfully, the Pod ends in "Succeeded" phase
|
||||
|
||||
- If some containers fail and don't get restarted, the Pod ends in "Failed" phase
|
||||
|
||||
---
|
||||
|
||||
## Replica Set
|
||||
|
||||
- Set of identical (replicated) Pods
|
||||
|
||||
- Defined by a pod template + number of desired replicas
|
||||
|
||||
- If there are not enough Pods, the Replica Set creates more
|
||||
|
||||
(e.g. in case of node outage; or simply when scaling up)
|
||||
|
||||
- If there are too many Pods, the Replica Set deletes some
|
||||
|
||||
(e.g. if a node was disconnected and comes back; or when scaling down)
|
||||
|
||||
- We can scale up/down a Replica Set
|
||||
|
||||
- we update the manifest of the Replica Set
|
||||
|
||||
- as a consequence, the Replica Set controller creates/deletes Pods
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
- Replica Sets control *identical* Pods
|
||||
|
||||
- Deployments are used to roll out different Pods
|
||||
|
||||
(different image, command, environment variables, ...)
|
||||
|
||||
- When we update a Deployment with a new Pod definition:
|
||||
|
||||
- a new Replica Set is created with the new Pod definition
|
||||
|
||||
- that new Replica Set is progressively scaled up
|
||||
|
||||
- meanwhile, the old Replica Set(s) is(are) scaled down
|
||||
|
||||
- This is a *rolling update*, minimizing application downtime
|
||||
|
||||
- When we scale up/down a Deployment, it scales up/down its Replica Set
|
||||
|
||||
---
|
||||
|
||||
## `kubectl run` through the ages
|
||||
|
||||
- When we want to run an app on Kubernetes, we *generally* want a Deployment
|
||||
|
||||
- Up to Kubernetes 1.17, `kubectl run` created a Deployment
|
||||
|
||||
- it could also create other things, by using special flags
|
||||
|
||||
- this was powerful, but potentially confusing
|
||||
|
||||
- creating a single Pod was done with `kubectl run --restart=Never`
|
||||
|
||||
- other resources could also be created with `kubectl create ...`
|
||||
|
||||
- From Kubernetes 1.18, `kubectl run` creates a Pod
|
||||
|
||||
- other kinds of resources can still be created with `kubectl create`
|
||||
|
||||
---
|
||||
|
||||
## Creating a Deployment the proper way
|
||||
|
||||
- Let's destroy that `pingpong` app that we created
|
||||
|
||||
- Then we will use `kubectl create deployment` to re-create it
|
||||
|
||||
.exercise[
|
||||
|
||||
- On Kubernetes 1.18+, delete the Pod named `pingpong`:
|
||||
```bash
|
||||
kubectl delete pod pingpong
|
||||
```
|
||||
|
||||
- On Kubernetes 1.17-, delete the Deployment named `pingpong`:
|
||||
```bash
|
||||
kubectl delete deployment pingpong
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Running `ping` in a Deployment
|
||||
|
||||
<!-- ##VERSION## -->
|
||||
|
||||
- When using `kubectl create deployment`, we cannot indicate the command to execute
|
||||
|
||||
(at least, not in Kubernetes 1.18)
|
||||
|
||||
- We can:
|
||||
|
||||
- write a custom YAML manifest for our Deployment
|
||||
|
||||
--
|
||||
|
||||
We should see the following things:
|
||||
- `deployment.apps/pingpong` (the *deployment* that we just created)
|
||||
- `replicaset.apps/pingpong-xxxxxxxxxx` (a *replica set* created by the deployment)
|
||||
- `pod/pingpong-xxxxxxxxxx-yyyyy` (a *pod* created by the replica set)
|
||||
- (yeah right ... too soon!)
|
||||
|
||||
Note: as of 1.10.1, resource types are displayed in more detail.
|
||||
--
|
||||
|
||||
- use an image that has the command to execute baked in
|
||||
|
||||
- (much easier!)
|
||||
|
||||
--
|
||||
|
||||
- We will use the image `jpetazzo/ping`
|
||||
|
||||
(it has a default command of `ping 127.0.0.1`)
|
||||
|
||||
---
|
||||
|
||||
## What are these different things?
|
||||
## Creating a Deployment running `ping`
|
||||
|
||||
- A *deployment* is a high-level construct
|
||||
- Let's create a Deployment named `pingpong`
|
||||
|
||||
- allows scaling, rolling updates, rollbacks
|
||||
- It will use the image `jpetazzo/ping`
|
||||
|
||||
- multiple deployments can be used together to implement a
|
||||
[canary deployment](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
|
||||
.exercise[
|
||||
|
||||
- delegates pods management to *replica sets*
|
||||
- Create the Deployment:
|
||||
```bash
|
||||
kubectl create deployment pingpong --image=jpetazzo/ping
|
||||
```
|
||||
|
||||
- A *replica set* is a low-level construct
|
||||
- Check the resources that were created:
|
||||
```bash
|
||||
kubectl get all
|
||||
```
|
||||
|
||||
- makes sure that a given number of identical pods are running
|
||||
<!-- ```hide kubectl wait pod --selector=run=pingpong --for condition=ready ``` -->
|
||||
|
||||
- allows scaling
|
||||
|
||||
- rarely used directly
|
||||
|
||||
- A *replication controller* is the (deprecated) predecessor of a replica set
|
||||
|
||||
---
|
||||
|
||||
## Our `pingpong` deployment
|
||||
|
||||
- `kubectl run` created a *deployment*, `deployment.apps/pingpong`
|
||||
|
||||
```
|
||||
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/pingpong 1 1 1 1 10m
|
||||
```
|
||||
|
||||
- That deployment created a *replica set*, `replicaset.apps/pingpong-xxxxxxxxxx`
|
||||
|
||||
```
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/pingpong-7c8bbcd9bc 1 1 1 10m
|
||||
```
|
||||
|
||||
- That replica set created a *pod*, `pod/pingpong-xxxxxxxxxx-yyyyy`
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/pingpong-7c8bbcd9bc-6c9qz 1/1 Running 0 10m
|
||||
```
|
||||
|
||||
- We'll see later how these folks play together for:
|
||||
|
||||
- scaling, high availability, rolling updates
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
@@ -294,132 +526,6 @@ Let's leave `kubectl logs` running while we keep exploring.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## What if we wanted something different?
|
||||
|
||||
- What if we wanted to start a "one-shot" container that *doesn't* get restarted?
|
||||
|
||||
- We could use `kubectl run --restart=OnFailure` or `kubectl run --restart=Never`
|
||||
|
||||
- These commands would create *jobs* or *pods* instead of *deployments*
|
||||
|
||||
- Under the hood, `kubectl run` invokes "generators" to create resource descriptions
|
||||
|
||||
- We could also write these resource descriptions ourselves (typically in YAML),
|
||||
<br/>and create them on the cluster with `kubectl apply -f` (discussed later)
|
||||
|
||||
- With `kubectl run --schedule=...`, we can also create *cronjobs*
|
||||
|
||||
---
|
||||
|
||||
## Scheduling periodic background work
|
||||
|
||||
- A Cron Job is a job that will be executed at specific intervals
|
||||
|
||||
(the name comes from the traditional cronjobs executed by the UNIX crond)
|
||||
|
||||
- It requires a *schedule*, represented as five space-separated fields:
|
||||
|
||||
- minute [0,59]
|
||||
- hour [0,23]
|
||||
- day of the month [1,31]
|
||||
- month of the year [1,12]
|
||||
- day of the week ([0,6] with 0=Sunday)
|
||||
|
||||
- `*` means "all valid values"; `/N` means "every N"
|
||||
|
||||
- Example: `*/3 * * * *` means "every three minutes"
|
||||
|
||||
---
|
||||
|
||||
## Creating a Cron Job
|
||||
|
||||
- Let's create a simple job to be executed every three minutes
|
||||
|
||||
- Cron Jobs need to terminate, otherwise they'd run forever
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create the Cron Job:
|
||||
```bash
|
||||
kubectl run every3mins --schedule="*/3 * * * *" --restart=OnFailure \
|
||||
--image=alpine sleep 10
|
||||
```
|
||||
|
||||
- Check the resource that was created:
|
||||
```bash
|
||||
kubectl get cronjobs
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Cron Jobs in action
|
||||
|
||||
- At the specified schedule, the Cron Job will create a Job
|
||||
|
||||
- The Job will create a Pod
|
||||
|
||||
- The Job will make sure that the Pod completes
|
||||
|
||||
(re-creating another one if it fails, for instance if its node fails)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the Jobs that are created:
|
||||
```bash
|
||||
kubectl get jobs
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
(It will take a few minutes before the first job is scheduled.)
|
||||
|
||||
---
|
||||
|
||||
|
||||
## What about that deprecation warning?
|
||||
|
||||
- As we can see from the previous slide, `kubectl run` can do many things
|
||||
|
||||
- The exact type of resource created is not obvious
|
||||
|
||||
- To make things more explicit, it is better to use `kubectl create`:
|
||||
|
||||
- `kubectl create deployment` to create a deployment
|
||||
|
||||
- `kubectl create job` to create a job
|
||||
|
||||
- `kubectl create cronjob` to run a job periodically
|
||||
<br/>(since Kubernetes 1.14)
|
||||
|
||||
- Eventually, `kubectl run` will be used only to start one-shot pods
|
||||
|
||||
(see https://github.com/kubernetes/kubernetes/pull/68132)
|
||||
|
||||
---
|
||||
|
||||
## Various ways of creating resources
|
||||
|
||||
- `kubectl run`
|
||||
|
||||
- easy way to get started
|
||||
- versatile
|
||||
|
||||
- `kubectl create <resource>`
|
||||
|
||||
- explicit, but lacks some features
|
||||
- can't create a CronJob before Kubernetes 1.14
|
||||
- can't pass command-line arguments to deployments
|
||||
|
||||
- `kubectl create -f foo.yaml` or `kubectl apply -f foo.yaml`
|
||||
|
||||
- all features are available
|
||||
- requires writing YAML
|
||||
|
||||
---
|
||||
|
||||
## Viewing logs of multiple pods
|
||||
|
||||
- When we specify a deployment name, only one single pod's logs are shown
|
||||
@@ -428,13 +534,15 @@ Let's leave `kubectl logs` running while we keep exploring.
|
||||
|
||||
- A selector is a logic expression using *labels*
|
||||
|
||||
- Conveniently, when you `kubectl run somename`, the associated objects have a `run=somename` label
|
||||
- If we check the pods created by the deployment, they all have the label `app=pingpong`
|
||||
|
||||
(this is just a default label that gets added when using `kubectl create deployment`)
|
||||
|
||||
.exercise[
|
||||
|
||||
- View the last line of log from all pods with the `run=pingpong` label:
|
||||
- View the last line of log from all pods with the `app=pingpong` label:
|
||||
```bash
|
||||
kubectl logs -l run=pingpong --tail 1
|
||||
kubectl logs -l app=pingpong --tail 1
|
||||
```
|
||||
|
||||
]
|
||||
@@ -449,7 +557,7 @@ Let's leave `kubectl logs` running while we keep exploring.
|
||||
|
||||
- Combine `-l` and `-f` flags:
|
||||
```bash
|
||||
kubectl logs -l run=pingpong --tail 1 -f
|
||||
kubectl logs -l app=pingpong --tail 1 -f
|
||||
```
|
||||
|
||||
<!--
|
||||
@@ -480,7 +588,7 @@ class: extra-details
|
||||
|
||||
- Stream the logs:
|
||||
```bash
|
||||
kubectl logs -l run=pingpong --tail 1 -f
|
||||
kubectl logs -l app=pingpong --tail 1 -f
|
||||
```
|
||||
|
||||
<!-- ```wait error:``` -->
|
||||
@@ -586,3 +694,195 @@ class: extra-details
|
||||
- This is a quick way to check connectivity
|
||||
|
||||
(if we can reach 1.1, we probably have internet access)
|
||||
|
||||
---
|
||||
|
||||
## Creating other kinds of resources
|
||||
|
||||
- Deployments are great for stateless web apps
|
||||
|
||||
(as well as workers that keep running forever)
|
||||
|
||||
- Jobs are great for "long" background work
|
||||
|
||||
("long" being at least minutes our hours)
|
||||
|
||||
- CronJobs are great to schedule Jobs at regular intervals
|
||||
|
||||
(just like the classic UNIX `cron` daemon with its `crontab` files)
|
||||
|
||||
- Pods are great for one-off execution that we don't care about
|
||||
|
||||
(because they don't get automatically restarted if something goes wrong)
|
||||
|
||||
---
|
||||
|
||||
## Creating a Job
|
||||
|
||||
- A Job will create a Pod
|
||||
|
||||
- If the Pod fails, the Job will create another one
|
||||
|
||||
- The Job will keep trying until:
|
||||
|
||||
- either a Pod succeeds,
|
||||
|
||||
- or we hit the *backoff limit* of the Job (default=6)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a Job that has a 50% chance of success:
|
||||
```bash
|
||||
kubectl create job flipcoin --image=alpine -- sh -c 'exit $(($RANDOM%2))'
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Our Job in action
|
||||
|
||||
- Our Job will create a Pod named `flipcoin-xxxxx`
|
||||
|
||||
- If the Pod succeeds, the Job stops
|
||||
|
||||
- If the Pod fails, the Job creates another Pod
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the status of the Pod(s) created by the Job:
|
||||
```bash
|
||||
kubectl get pods --selector=job-name=flipcoin
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## More advanced jobs
|
||||
|
||||
- We can specify a number of "completions" (default=1)
|
||||
|
||||
- This indicates how many times the Job must be executed
|
||||
|
||||
- We can specify the "parallelism" (default=1)
|
||||
|
||||
- This indicates how many Pods should be running in parallel
|
||||
|
||||
- These options cannot be specified with `kubectl create job`
|
||||
|
||||
(we have to write our own YAML manifest to use them)
|
||||
|
||||
---
|
||||
|
||||
## Scheduling periodic background work
|
||||
|
||||
- A Cron Job is a Job that will be executed at specific intervals
|
||||
|
||||
(the name comes from the traditional cronjobs executed by the UNIX crond)
|
||||
|
||||
- It requires a *schedule*, represented as five space-separated fields:
|
||||
|
||||
- minute [0,59]
|
||||
- hour [0,23]
|
||||
- day of the month [1,31]
|
||||
- month of the year [1,12]
|
||||
- day of the week ([0,6] with 0=Sunday)
|
||||
|
||||
- `*` means "all valid values"; `/N` means "every N"
|
||||
|
||||
- Example: `*/3 * * * *` means "every three minutes"
|
||||
|
||||
---
|
||||
|
||||
## Creating a Cron Job
|
||||
|
||||
- Let's create a simple job to be executed every three minutes
|
||||
|
||||
- Careful: make sure that the job terminates!
|
||||
|
||||
(The Cron Job will not hold if a previous job is still running)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create the Cron Job:
|
||||
```bash
|
||||
kubectl create cronjob every3mins --schedule="*/3 * * * *" \
|
||||
--image=alpine -- sleep 10
|
||||
```
|
||||
|
||||
- Check the resource that was created:
|
||||
```bash
|
||||
kubectl get cronjobs
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Cron Jobs in action
|
||||
|
||||
- At the specified schedule, the Cron Job will create a Job
|
||||
|
||||
- The Job will create a Pod
|
||||
|
||||
- The Job will make sure that the Pod completes
|
||||
|
||||
(re-creating another one if it fails, for instance if its node fails)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the Jobs that are created:
|
||||
```bash
|
||||
kubectl get jobs
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
(It will take a few minutes before the first job is scheduled.)
|
||||
|
||||
---
|
||||
|
||||
class: extra-details
|
||||
|
||||
## What about `kubectl run` before v1.18?
|
||||
|
||||
- Creating a Deployment:
|
||||
|
||||
`kubectl run`
|
||||
|
||||
- Creating a Pod:
|
||||
|
||||
`kubectl run --restart=Never`
|
||||
|
||||
- Creating a Job:
|
||||
|
||||
`kubectl run --restart=OnFailure`
|
||||
|
||||
- Creating a Cron Job:
|
||||
|
||||
`kubectl run --restart=OnFailure --schedule=...`
|
||||
|
||||
*Avoid using these forms, as they are deprecated since Kubernetes 1.18!*
|
||||
|
||||
---
|
||||
|
||||
## Beyond `kubectl create`
|
||||
|
||||
- As hinted earlier, `kubectl create` doesn't always expose all options
|
||||
|
||||
- can't express parallelism or completions of Jobs
|
||||
|
||||
- can't express Pods with multiple containers
|
||||
|
||||
- can't express healthchecks, resource limits
|
||||
|
||||
- etc.
|
||||
|
||||
- `kubectl create` and `kubectl run` are *helpers* that generate YAML manifests
|
||||
|
||||
- If we write these manifests ourselves, we can use all features and options
|
||||
|
||||
- We'll see later how to do that!
|
||||
|
||||
Reference in New Issue
Block a user