From 9d018343c018057bc77553029707884e38357c99 Mon Sep 17 00:00:00 2001 From: abregman Date: Sat, 15 Oct 2022 22:34:50 +0300 Subject: [PATCH] Update CKA Added additional questions to CKA and fixed some styling issues with pulumi Python code. --- README.md | 2 +- .../aws/exercises/new_vpc/pulumi/__main__.py | 2 +- .../s3/new_bucket/pulumi/__main__.py | 33 ++- .../aws/exercises/subnets/pulumi/__main__.py | 35 ++- topics/kubernetes/CKA.md | 247 +++++++++++++++++- topics/kubernetes/README.md | 205 +++++++++++++-- 6 files changed, 466 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index af73e0c..8f7935a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ :information_source:  This repo contains questions and exercises on various technical topics, sometimes related to DevOps and SRE -:bar_chart:  There are currently **2477** exercises and questions +:bar_chart:  There are currently **2354** exercises and questions :books:  To learn more about DevOps and SRE, check the resources in [devops-resources](https://github.com/bregman-arie/devops-resources) repository diff --git a/topics/aws/exercises/new_vpc/pulumi/__main__.py b/topics/aws/exercises/new_vpc/pulumi/__main__.py index ef35bd4..24f79d6 100644 --- a/topics/aws/exercises/new_vpc/pulumi/__main__.py +++ b/topics/aws/exercises/new_vpc/pulumi/__main__.py @@ -7,4 +7,4 @@ pulumi.export("vpc_id", vpc.vpc_id) pulumi.export("publicSubnetIds", vpc.public_subnet_ids) pulumi.export("privateSubnetIds", vpc.private_subnet_ids) -# Run 'pulumi up' to create it \ No newline at end of file +# Run 'pulumi up' to create it diff --git a/topics/aws/exercises/s3/new_bucket/pulumi/__main__.py b/topics/aws/exercises/s3/new_bucket/pulumi/__main__.py index c400074..c263128 100644 --- a/topics/aws/exercises/s3/new_bucket/pulumi/__main__.py +++ b/topics/aws/exercises/s3/new_bucket/pulumi/__main__.py @@ -1,28 +1,25 @@ -import pulumi import pulumi_aws as aws # Private Bucket private_bucket = aws.s3.Bucket("my-first-private-bucket", - acl="private", - tags={ - "Environment": "Exercise", - "Name": "My First Private Bucket"}, - region="eu-west-2" - ) + acl="private", + tags={ + "Environment": "Exercise", + "Name": "My First Private Bucket"}, + region="eu-west-2" + ) # Bucket Object - aws.s3.BucketObject("bucketObject", - key="some_object_key", - bucket=private_bucket.id, - content="object content") + key="some_object_key", + bucket=private_bucket.id, + content="object content") # Public Bucket aws.s3.Bucket("my-first-public-bucket", - acl="private", - tags={ - "Environment": "Exercise", - "Name": "My First Public Bucket"}, - region="eu-west-1", - versioning=aws.s3.BucketVersioningArgs(enabled=True) - ) \ No newline at end of file + acl="private", + tags={ + "Environment": "Exercise", + "Name": "My First Public Bucket"}, + region="eu-west-1", + versioning=aws.s3.BucketVersioningArgs(enabled=True)) diff --git a/topics/aws/exercises/subnets/pulumi/__main__.py b/topics/aws/exercises/subnets/pulumi/__main__.py index 058e8b0..11fc6dd 100644 --- a/topics/aws/exercises/subnets/pulumi/__main__.py +++ b/topics/aws/exercises/subnets/pulumi/__main__.py @@ -1,27 +1,26 @@ -import pulumi import pulumi_aws as aws -availableZones = pulumi_aws.get_availability_zones(state="available") +availableZones = aws.get_availability_zones(state="available") aws.ec2.Subnet("NewSubnet1", - vpc_id=aws_vpc["main"]["id"], - cidr_block="10.0.0.0/24", - availability_zone=availableZones.names[0], - tags={"Name": "NewSubnet1"} - ) + vpc_id=aws.vpc["main"]["id"], + cidr_block="10.0.0.0/24", + availability_zone=availableZones.names[0], + tags={"Name": "NewSubnet1"} + ) aws.ec2.Subnet("NewSubnet2", - vpc_id=aws_vpc["main"]["id"], - cidr_block="10.0.1.0/24", - availability_zone=availableZones.names[1] - tags={"Name": "NewSubnet2"} - ) + vpc_id=aws.vpc["main"]["id"], + cidr_block="10.0.1.0/24", + availability_zone=availableZones.names[1], + tags={"Name": "NewSubnet2"} + ) aws.ec2.Subnet("NewSubnet3", - vpc_id=aws_vpc["main"]["id"], - cidr_block="10.0.2.0/24", - availability_zone=availableZones.names[2] - tags={"Name": "NewSubnet3"} - ) + vpc_id=aws.vpc["main"]["id"], + cidr_block="10.0.2.0/24", + availability_zone=availableZones.names[2], + tags={"Name": "NewSubnet3"} + ) -# Run "pulumi up" \ No newline at end of file +# Run "pulumi up" diff --git a/topics/kubernetes/CKA.md b/topics/kubernetes/CKA.md index 1c7eeb8..935fe57 100644 --- a/topics/kubernetes/CKA.md +++ b/topics/kubernetes/CKA.md @@ -7,6 +7,10 @@ - [Namespaces](#namespaces) - [Nodes](#nodes) - [Services](#services) + - [ReplicaSets](#replicasets) + - [Troubleshooting ReplicaSets](#troubleshooting-replicasets) + - [Deployments](#deployments) + - [Troubleshooting Deployments](#troubleshooting-deployments) ## Setup @@ -28,7 +32,9 @@ alias kg=kubectl get ## Pods
-Run a command to view all the pods in current namespace
+Run a command to view all the pods in the current namespace
+ +`kubectl get pods` Note: create an alias (`alias k=kubectl`) and get used to `k get po`
@@ -49,12 +55,16 @@ Note: create an alias (`alias k=kubectl`) and get used to `k get po` In what namespace the etcd pod is running? list the pods in that namespace
`k get po -n kube-system` + +Let's say you didn't know in what namespace it is. You could then run `k get po -A | grep etc` to find the Pod and see in what namespace it resides.
List pods from all namespaces
-`k get po --all-namespaces` +`k get po -A` + +The long version would be `kubectl get pods --all-namespaces`.
@@ -76,6 +86,8 @@ EOL k create -f pod.yaml ``` + +If you ask yourself how would I remember writing all of that? no worries, you can simply run `kubectl run some_pod --image=redis -o yaml --dry-run=client > pod.yaml`. If you ask yourself "how am I supposed to remember this long command" time to change attitude ;)
@@ -118,6 +130,12 @@ You can also run `k describe po POD_NAME` `k get po --show-labels`
+
+Delete a Pod called "nm"
+ +`k delete po nm` +
+ ### Troubleshooting Pods
@@ -137,12 +155,13 @@ Some ways to debug: 1. This should provide an accurate output of 2. For specific container, you can add `-c CONTAINER_NAME` 3. If you still have no idea why it failed, try `kubectl get events` +4.
What the error ImagePullBackOff means?
-Most likely you didn't write correctly the name of the image you try to pull and run +Most likely you didn't write correctly the name of the image you try to pull and run. Or perhaps it doesn't exists in the registry. You can confirm with `kubectl describe po POD_NAME`
@@ -153,6 +172,14 @@ You can confirm with `kubectl describe po POD_NAME` `k get po POD_NAME -o wide` +
+Run the following command: kubectl run ohno --image=sheris. Did it work? why not? fix it without removing the Pod and using any image you want
+ +Because there is no such image `sheris`. At least for now :) + +To fix it, run `kubectl edit ohno` and modify the following line `- image: sheris` to `- image: redis` or any other image you prefer. +
+ ## Namespaces
@@ -187,4 +214,216 @@ Note: create an alias (`alias k=kubectl`) and get used to `k get no`
Create an internal service called "sevi" to expose the app 'web' on port 1991
-
\ No newline at end of file +
+ +## ReplicaSets + +
+How to check how many replicasets defined in the current namespace?
+ +`k get rs` +
+ +
+You have a replica set defined to run 3 Pods. You removed one of these 3 pods. What will happen next? how many Pods will there be?
+ +There will still be 3 Pods running theoretically because the goal of the replica set is to ensure that. so if you delete one or more Pods, it will run additional Pods so there are always 3 Pods. +
+ +
+How to check which container image was used as part of replica set called "repli"?
+ +`k describe rs repli | grep -i image` +
+ +
+How to check how many Pods are ready as part of a replica set called "repli"?
+ +`k describe rs repli | grep -i "Pods Status"` +
+ +
+How to delete a replica set called "rori"?
+ +`k delete rs rori` +
+ +
+How to modify a replica set called "rori" to use a different image?
+ +`k edis rs rori` +
+ +
+Scale up a replica set called "rori" to run 5 Pods instead of 2
+ +`k scale rs rori --replicas=5` +
+ +
+Scale down a replica set called "rori" to run 1 Pod instead of 5
+ +`k scale rs rori --replicas=1` +
+ +### Troubleshooting ReplicaSets + +
+Fix the following ReplicaSet definition + +```yaml +apiVersion: apps/v1 +kind: ReplicaCet +metadata: + name: redis + labels: + app: redis + tier: cache +spec: + selector: + matchLabels: + tier: cache + template: + metadata: + labels: + tier: cachy + spec: + containers: + - name: redis + image: redis +``` +
+ +kind should be ReplicaSet and not ReplicaCet :) + +
+ +
+Fix the following ReplicaSet definition + +```yaml +apiVersion: apps/v1 +kind: ReplicaSet +metadata: + name: redis + labels: + app: redis + tier: cache +spec: + selector: + matchLabels: + tier: cache + template: + metadata: + labels: + tier: cachy + spec: + containers: + - name: redis + image: redis +``` +
+ +The selector doesn't match the label (cache vs cachy). To solve it, fix cachy so it's cache instead. + +
+ +## Deployments + +
+How to list all the deployments in the current namespace?
+ +`k get deploy` + +
+ +
+How to check which image a certain Deployment is using?
+ +`k describe deploy | grep image` + +
+ +
+Create a file definition/manifest of a deployment called "dep", with 3 replicas that uses the image 'redis'
+ +`k create deploy dep -o yaml --image=redis --dry-run=client --replicas 3 > deployment.yaml ` + +
+ +
+Remove the deployment `depdep`
+ +`k delete deploy depdep` + +
+ +### Troubleshooting Deployments + +
+Fix the following deployment manifest + +```yaml +apiVersion: apps/v1 +kind: Deploy +metadata: + creationTimestamp: null + labels: + app: dep + name: dep +spec: + replicas: 3 + selector: + matchLabels: + app: dep + strategy: {} + template: + metadata: + creationTimestamp: null + labels: + app: dep + spec: + containers: + - image: redis + name: redis + resources: {} +status: {} +``` +
+ +Change `kind: Deploy` to `kind: Deployment` +
+ +
+Fix the following deployment manifest + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + creationTimestamp: null + labels: + app: dep + name: dep +spec: + replicas: 3 + selector: + matchLabels: + app: depdep + strategy: {} + template: + metadata: + creationTimestamp: null + labels: + app: dep + spec: + containers: + - image: redis + name: redis + resources: {} +status: {} +``` +
+ +The selector doesn't match the label (dep vs depdep). To solve it, fix depdep so it's dep instead. +
diff --git a/topics/kubernetes/README.md b/topics/kubernetes/README.md index 72befea..87a1ec4 100644 --- a/topics/kubernetes/README.md +++ b/topics/kubernetes/README.md @@ -531,7 +531,7 @@ A Deployment is a declarative statement for the desired state for Pods and Repli
-How to create a deployment?
+How to create a deployment with the image "nginx:alpine"?
`kubectl create deployment my_first_deployment --image=nginx:alpine` @@ -554,7 +554,7 @@ EOF
How to verify a deployment was created?
-`kubectl get deployments` +`kubectl get deployments` or `kubectl get deploy` This command lists all the Deployment objects created and exist in the cluster. It doesn't mean the deployments are readt and running. This can be checked with the "READY" and "AVAILABLE" columns.
@@ -562,7 +562,7 @@ This command lists all the Deployment objects created and exist in the cluster.
How to edit a deployment?
-kubectl edit deployment some-deployment +`kubectl edit deployment `
@@ -576,7 +576,8 @@ Also, when looking at the replicaset, you'll see the old replica doesn't have an
How to delete a deployment?
-One way is by specifying the deployment name: `kubectl delete deployment [deployment_name]`
+One way is by specifying the deployment name: `kubectl delete deployment [deployment_name]` + Another way is using the deployment configuration file: `kubectl delete -f deployment.yaml`
@@ -607,12 +608,94 @@ Using a Service. Can you use a Deployment for stateful applications?
+
+Create a file definition/manifest of a deployment called "dep", with 3 replicas that uses the image 'redis'
+ +`k create deploy dep -o yaml --image=redis --dry-run=client --replicas 3 > deployment.yaml ` + +
+ +
+Delete the deployment `depdep`
+ +`k delete deploy depdep` + +
+ +
+Fix the following deployment manifest + +```yaml +apiVersion: apps/v1 +kind: Deploy +metadata: + creationTimestamp: null + labels: + app: dep + name: dep +spec: + replicas: 3 + selector: + matchLabels: + app: dep + strategy: {} + template: + metadata: + creationTimestamp: null + labels: + app: dep + spec: + containers: + - image: redis + name: redis + resources: {} +status: {} +``` +
+ +Change `kind: Deploy` to `kind: Deployment` +
+ +
+Fix the following deployment manifest + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + creationTimestamp: null + labels: + app: dep + name: dep +spec: + replicas: 3 + selector: + matchLabels: + app: depdep + strategy: {} + template: + metadata: + creationTimestamp: null + labels: + app: dep + spec: + containers: + - image: redis + name: redis + resources: {} +status: {} +``` +
+ +The selector doesn't match the label (dep vs depdep). To solve it, fix depdep so it's dep instead. +
+ ### Services
What is a Service in Kubernetes?
-"An abstract way to expose an application running on a set of Pods as a network service." - read more [here](https://kubernetes.io/docs/concepts/services-networking/service)
+"An abstract way to expose an application running on a set of Pods as a network service." - read more [here](https://kubernetes.io/docs/concepts/services-networking/service) In simpler words, it allows you to add an internal or external connectivity to a certain application running in a container.
@@ -665,12 +748,14 @@ The truth is they aren't connected. Service points to Pod(s) directly, without c 1. Making sure that targetPort of the Service is matching the containerPort of the Pod 2. Making sure that selector matches at least one of the Pod's labels +
What is the default service type in Kubernetes and what is it used for?
The default is ClusterIP and it's used for exposing a port internally. It's useful when you want to enable internal communication between Pods and prevent any external access. +
@@ -679,6 +764,7 @@ The default is ClusterIP and it's used for exposing a port internally. It's usef `kubctl describe service ` It's more common to use `kubectl describe svc ...` +
@@ -1037,7 +1123,7 @@ False. It will terminate one of the Pods to reach the desired state of 2 replica
How to list ReplicaSets in the current namespace?
-kubectl get rs +`kubectl get rs`
@@ -1064,13 +1150,6 @@ web 2 2 0 2m23s The replicaset `web` has 2 replicas. It seems that the containers inside the Pod(s) are not yet running since the value of READY is 0. It might be normal since it takes time for some containers to start running and it might be due to an error. Running `kubectl describe po POD_NAME` or `kubectl logs POD_NAME` can give us more information.
-
-You run kubectl get rs and while DESIRED is set to 2, you see that READY is set to 0. What are some possible reasons for it to be 0?
- - * Images are still being pulled - * There is an error and the containers can't reach the state "Running" -
-
True or False? Pods specified by the selector field of ReplicaSet must be created by the ReplicaSet itself
@@ -1104,7 +1183,7 @@ True (and not only the Pods but anything else it created).
-True or False? Removing the label from a Pod that is used by ReplicaSet to match Pods, will cause the ReplicaSet to create a new Pod
+True or False? Removing the label from a Pod that is tracked by a ReplicaSet, will cause the ReplicaSet to create a new Pod
True. When the label, used by a ReplicaSet in the selector field, removed from a Pod, that Pod no longer controlled by the ReplicaSet and the ReplicaSet will create a new Pod to compensate for the one it "lost".
@@ -1132,11 +1211,105 @@ Few notes:
-What's the diffence between a ReplicaSet and DaemonSet?
+What's the difference between a ReplicaSet and DaemonSet?
A ReplicaSet's purpose is to maintain a stable set of replica Pods running at any given time. A DaemonSet ensures that all Nodes run a copy of a Pod. -
+ + +
+Fix the following ReplicaSet definition + +```yaml +apiVersion: apps/v1 +kind: ReplicaCet +metadata: + name: redis + labels: + app: redis + tier: cache +spec: + selector: + matchLabels: + tier: cache + template: + metadata: + labels: + tier: cachy + spec: + containers: + - name: redis + image: redis +``` +
+ +kind should be ReplicaSet and not ReplicaCet :) +
+ +
+Fix the following ReplicaSet definition + +```yaml +apiVersion: apps/v1 +kind: ReplicaSet +metadata: + name: redis + labels: + app: redis + tier: cache +spec: + selector: + matchLabels: + tier: cache + template: + metadata: + labels: + tier: cachy + spec: + containers: + - name: redis + image: redis +``` +
+ +The selector doesn't match the label (cache vs cachy). To solve it, fix cachy so it's cache instead. +
+ +
+How to check which container image was used as part of replica set called "repli"?
+ +`k describe rs repli | grep -i image` +
+ +
+How to check how many Pods are ready as part of a replica set called "repli"?
+ +`k describe rs repli | grep -i "Pods Status"` +
+ +
+How to delete a replica set called "rori"?
+ +`k delete rs rori` +
+ +
+How to modify a replica set called "rori" to use a different image?
+ +`k edis rs rori` +
+ +
+Scale up a replica set called "rori" to run 5 Pods instead of 2
+ +`k scale rs rori --replicas=5` +
+ +
+Scale down a replica set called "rori" to run 1 Pod instead of 5
+ +`k scale rs rori --replicas=1` +
### StatefulSet