# 기출 문제 및 Tips



# [1] ETCD Backup & Restore

## ❓ETCD Backup &amp; Restore

- 작업 시스템: k8s-master
    
    First, create a snapshot of the existing etcd instance running at `https://127.0.0.1:2379`, saving the snapshot to `/data/etcd-snapshot.db`.
    
    Next, restore an existing, previous snapshot located at `/data/etcd-snapshot-previous.db`.
    
    The following TLS certificates/key are supplied for connecting to the server with etcdctl.
    
    CA certificate: `/etc/kubernetes/pki/etcd/ca.crt`
    
    Client certificate: `/etc/kubernetes/pki/etcd/server.crt`
    
    Client key: `/etc/kubernetes/pki/etcd/server.key`

##### **설명:**

etcd는 key:value 형태로 데이터를 저장하며 etcd도 하나의 pod형태로 구성되어 있다.

etcd에 저장되는 데이터들은 모두 /var/lib/etcd 디렉토리에 저장된다.

이 디렉토리를 하나의 파일로 저장하는 것을 백업한다고 표현하며 쿠버네티스 상에서는 etcd를 스냅샷 떴다고 표현한다.

etcd 백업 후 restore 할 때에는 현재 구동중인 /var/lib/etcd 디렉토리에 overwrite하면 안되고 임의의 다른 디렉토리에 restore해야한다.

임의의 다른 디렉토리에 restore한 후 etcd pod에게 /var/lib/etcd 디렉토리가 아닌 restore한 다른 디렉토리를 바라보게 함으로써 restore한다.

- 과정 
    - etcd 스냅샷 생성
    - 생성한 스냅샷으로 /var/lib/etcd 디렉토리가 아닌 임의의 디렉토리에 restore
    - config파일을 수정해 etcd pod가 restore한 임의의 디렉토리를 바라보게 한다.

### Reference

docs에서 etcd backup 검색

[Operating etcd clusters for Kubernetes](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/)

### 실습

```docker
# 현재 위치중인 cluster 확인
[user@console ~]$ kubectl config current-context
k8s

# 현재 위치중인 k8s 클러스터에 위치한 k8s-master 노드로 이동
[user@console ~]$ ssh k8s-master

# user계정으로는 etcd 백업을 하지 못하므로 root계정으로 전환해서 사용하여야 함

```

```docker
# etcd 명령어를 사용하기 전에 etcd가 설치되어 있는지 확인
[user@k8s-master ~]$ etcdctl version
etcdctl version: 3.5.2
API version: 3.5

# kubernetes docs에 나와있는 etcd backup 예제
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \\
--cacert=<trusted-ca-file> \\
--cert=<cert-file> \\
--key=<key-file> \\
snapshot save <backup-file-location>

# 위의 예제를 사용해 명령어 실행
# 이 명령어를 실행할때는 sudo를 해줘야한다
[user@k8s-master ~]$ sudo ETCDCTL_API=3 etcdctl \\
--endpoints=https://127.0.0.1:2379 \\
--cacert=/etc/kubernetes/pki/etcd/ca.crt \\
--cert=/etc/kubernetes/pki/etcd/server.crt \\
--key=/etc/kubernetes/pki/etcd/server.key \\
snapshot save /data/etcd-snapshot.db

# 스냅샷이 생성됬는지 확인
[user@k8s-master ~]$ sudo ls -l /data/etcd-snapshot.db

# 문제에 나와있는 /data/etcd-snapshot-previous.db 파일이 있는지 확인
[user@k8s-master ~]$ sudo ls -l /data/etcd-snapshot-previous.db

# kubernetes docs에 나와있는 etcd restore 예제
ETCDCTL_API=3 etcdctl \\
--data-dir <data-dir-location> \\
snapshot restore snapshotdb

# 임의의 디렉토리에 이전 etcd 스냅샷을 이용해 복구
[user@k8s-master ~]$ sudo ETCDCTL_API=3 etcdctl \\
--data-dir /var/lib/etcd-new \\
snapshot restore /data/etcd-snapshot-previous.db


```

```docker
[user@k8s-master ~]$ cd /etc/kubernetes/manifest

[user@k8s-master manifest]$ ls
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml

# hostPath 부분을 변경
[user@k8s-master manifest]$ sudo vi etcd.yaml
- hostPath:
		path: /var/lib/etcd-new

:wq

static pod이기 때문에 재시작 없이 수정사항이 반영된다.

#반영됬는지 확인
[user@k8s-master manifest]$ sudo docker ps -a | grep etcd
-> Up상태가 2개인거 확인

```

## 기출문제 (21번)

First, create a snapshot of the existing etcd instance running at [https://127.0.0.1:2379](https://127.0.0.1:2379), saving the snapshot to /srv/data/etcd-snapshot.db.

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/Ef0image.png)](http://138.2.116.150/uploads/images/gallery/2023-05/Ef0image.png)

Next, restore an existing, previous snapshot located at /var/lib/backup/etcd-snapshot-previo us.db

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/eTsimage.png)](http://138.2.116.150/uploads/images/gallery/2023-05/eTsimage.png)

- 답안
    
    ```jsx
    ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \\
    --cacert=/opt/KUIN00601/ca.crt \\
    --cert=/opt/KUIN00601/etcd-client.crt \\
    --key=/opt/KUIN00601/etcd-client.key \\
    snapshot save /srv/data/etcd-snapshot.db
    
    ```
    
    ```jsx
    ETCDCTL_API=3 etcdctl --data-dir /var/lib/etcd-new \\
    snapshot restore /var/lib/backup/etcd-snapshot-previous.db
    
    ```
    
    ```jsx
    cd /etc/kubernetes/manifests
    
    ```
    
    ```jsx
    vi etcd.yaml
    
    hostPath: 부분을 /var/lib/etcd-new로 수정
    
    :wq
    
    ```
    
    ```jsx
    # 확인
    docker ps -a | grep etcd
    
    2개가 Up 상태여야 함
    
    ```

## 💡Tip!!

1. 스냅샷 생성
    
    
    1. 인증서 파일 있으면 해당 명령어 사용해서 생성
2. 스냅샷 복구
    
    
    1. 이전 스냅샷이 있는지 확인 후 복구
    2. 복구할 때 /var/lib/etcd가 아닌 다른 디렉토리에 복구
3. 다른 디렉토리를 바라보게 config파일 수정
    
    
    1. /etc/kubernetes/manifests/etcd.yaml파일에서 hostPath부분 수정
4. 확인
    
    
    1. docker ps -a | grep etcd했을 때 2개가 Up상태이면 끝
    
    검색 : backup → Snapshot using etcdctl options

# [2] Pod 생성하기

## ❓Pod 생성하기

- 클러스터: k8s
- Create a new namespace and create a pod in the namespace. 
    - namespace name: ecommerce
    - Pod Name: eshop-main
    - image: nginx:1.17
    - env: DB=mysql

### 실습

```docker
# 클러스터 변경
[user@console ~]$ kubectl config use-context k8s

# namespace 생성
[user@console ~]$ kubectl create namespace ecommerce

# 생성된 namespace 확인
[user@console ~]$ kubectl get namespaces

# pod 생성
# 엔터를 누르기 전에 --dry-run=client 옵션으로 해당 명령어가 문제없는 명령어인지 확인
[user@console ~]$ kubectl run eshop-main --image=nginx:1.17 --env=DB=mysql --namespace=ecommerce --dry-run=client

# 정상동작 확인 후 --dry-client 옵션 지운 후 명령어 실행
[user@console ~]$ kubectl run eshop-main --image=nginx:1.17 --env=DB=mysql --namespace=ecommerce

# Pod 생성됬는지 확인
[user@console ~]$ kubectl get pods --namespace ecommerce


```

## 기출문제 (2번)

Create 2 nginx image pods in which one of them is labelled with env=prod and another one labelled with env=dev and verify the same

- 답안
    
    ```jsx
    kubectl run nginx-prod --image=nginx --labels=env=prod
    
    ```
    
    ```jsx
    kubectl run nginx-dev --image=nginx --labels=env=dev
    
    ```
    
    ```jsx
    # 확인
    kubectl get pods
    
    kubectl get pod nginx-prod -o yaml
    --> labels부분 확인
    
    kubectl get pod nginx-dev -o yaml
    --> labels부분 확인
    
    ```

## 기출문제 (3번)

Create an nginx pod and list the pod with different levels of verbosity

- 답안
    
    ```jsx
    kubectl run nginx --image=nginx
    
    ```
    
    ```jsx
    kubectl get pod nginx --v=7
    
    ```
    
    ```jsx
    kubectl get pod nginx --v=8
    
    ```
    
    ```jsx
    kubectl get pod nginx --v=9
    
    ```
    
    
    - 참고 (verbosity)
    
    [https://kubernetes.io/ko/docs/reference/kubectl/cheatsheet/](https://kubernetes.io/ko/docs/reference/kubectl/cheatsheet/)

## 기출문제 (4번)

Create a pod with environment variables as var1=value1.Check the environment variable in pod

- 답안
    
    ```jsx
    kubectl run test-pod --image=nginx --env=var1=value1
    
    ```
    
    ```jsx
    # 확인
    kubectl get pods
    
    kubectl describe pod test-pod
    --> env 부분 확인
    
    ```

## 기출문제 (6번)

List "nginx-dev" and "nginx-prod" pod and delete those pods

- 답안
    
    ```jsx
    # 모든 네임스페이스에 있는 pod 확인
    kubectl get pods -A
    
    nginx-dev, nginx-prod pod 있는 것 확인
    
    ```
    
    ```jsx
    kubectl delete pod nginx-dev
    
    ```
    
    ```jsx
    kubectl delete pod nginx-prod
    
    ```

## 기출문제 (8번)

Create a pod as follows:

- Name: non-persistent-redis
- container Image: redis
- Volume with name: cache-control
- Mount path: /data/redis

The pod should launch in the staging namespace and the volume must not be persistent.

- 답안
    
    ```jsx
    kubectl create namespace staging 
    
    ```
    
    ```jsx
    # YAML 파일 생성
    vi volume.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: non-persistent-redis
      name: non-persistent-redis
      namespace: staging
    spec:
      containers:
      - image: redis
        name: redis
        resources: {}
        volumeMounts:
        - mountPath: /data/redis
          name: cache-control
      volumes:
      - name: cache-control
        emptyDir: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f volume.yaml
    
    ```

## 기출문제 (9번)

Create a pod with i traffic on port 80

- 답안
    
    ```jsx
    kubectl run nginx --image=nginx --port=80
    
    ```

## 기출문제 (11번)

Create a file: /opt/KUCC00302/kucc00302.txt that lists all pods that implement service baz in namespace development. The format of the file should be one pod name per line.

- 답안
    
    ```jsx
    # baz 라는 이름의 service가 있는지 확인
    kubectl get svc baz -n development
    
    ```
    
    ```jsx
    kubectl describe svc baz -n development
    --> 확인해보면 라벨이 name=foo인 것들에 대해 서비스로 묶고 있다.
    
    ```
    
    ```jsx
    kubectl get pods -l name=foo -n development
    
    ```
    
    ```jsx
    kubectl get pods -l name=foo -n development -o NAME > /opt/KUCC00302/kucc00302.txt
    
    ```

## 기출문제 (12번)

Create a pod named kucc8 with a single app container for each of the following images running inside (there may be between 1 and 4 images specified): nginx + redis + memcached.

- 답안
    
    ```jsx
    kubectl run kucc8 --image=nginx --dry-run=client -o yaml
    --> yaml 파일 복사
    
    ```
    
    ```jsx
    vi kucc.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: kucc8
      name: kucc8
    spec:
      containers:
      - image: nginx
        name: nginx
      - image: redis
        name: redis
      - image: memcached
        name: memcached
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f kucc.yaml
    
    ```
    
    ```jsx
    # 확인
    kubectl get pods
    
    kubectl describe pod kucc8
    --> 컨테이너 3개 생성된 것 확인
    
    ```

## 기출문제 (18번)

Check the image version in pod name nginx without the describe command

- 답안
    
    ```jsx
    kubectl get pod nginx -o jsonpath='{.spec.container[].image}{"\\n"}'
    
    ```

## 기출문제 (19번)

Print pod name and start time to "/opt/pod-status" file

- 답안
    
    ```jsx
    # json 파일로 확인 후 start time이 어디에 속해있는지 확인
    kubectl get pods -o json
    
    ```
    
    ```jsx
    kubectl get pods -o jsonpath='{range.items[*]}{.metadata.name}{"\\t"}{.status.startTime}{"\\n"}{end}’ > /opt/pod-status
    
    ```

## 기출문제 (23번)

Get IP address of the pod "nginx-dev”

- 답안
    
    ```jsx
    kubectl get pod nginx-dev -o jsonpath='{.status.podIP}{"\\n"}'
    
    ```

## 기출문제 (24번)

List all the pods sorted by name

- 답안
    
    ```jsx
    kubectl get pods --sort-by=.metadata.name
    
    ```

## 기출문제 (26번)

List the nginx pod with custom columns POD\_NAME and POD\_STATUS

- 답안
    
    ```jsx
    kubectl get pod -o=custom-columns="POD_NAME:.metadata.name, POD_STATUS:.status.containerStatuses[].state"
    
    ```
    
    
    - 참고
    
    [https://kubernetes.io/docs/reference/kubectl/cheatsheet/](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)

## 기출문제 (27번)

List all the pods sorted by created timestamp

- 답안
    
    ```jsx
    kubectl get pods --sort-by=.metadata.creationTimestamp
    
    ```

## 기출문제 (29번)

Get list of all pods in all namespaces and write it to file "/opt/pods-list.yaml”

- 답안
    
    ```jsx
    kubectl get pods -A > /opt/pods-list.yaml
    
    ```

## 기출문제 (34번)

Get list of all the pods showing name and namespace with a jsonpath expression.

- 답안
    
    ```jsx
    kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\\t"}{.metadata.namespace}{"\\n"}{end}'
    
    ```

## 기출문제 (38번)

Create a busybox pod and add "sleep 3600" command

- 답안
    
    ```jsx
    kubectl run busybox --image=busybox -- /bin/sh -c "sleep 3600"
    
    ```

## 기출문제 (42번)

Create a nginx pod with label env=test in engineering namespace

- 답안
    
    ```jsx
    kubectl create namespace engineering
    
    ```
    
    ```jsx
    kubectl run nginx --image=nginx --labels=env=test -n engineering
    
    ```

## 기출문제 (44번)

Check the Image version of nginx-dev pod using jsonpath

- 답안
    
    ```jsx
    kubectl get pod nginx-dev -o json
    
    ```
    
    ```jsx
    kubectl get pod nginx-dev -o jsonpath='{.spec.containers[].image}{"\\n"}'
    
    ```

## 기출문제 (57번)

List all the pods showing name and namespace with a json path expression

- 답안
    
    ```jsx
    kubectl get pods -A -o=jsonpath='{range .items[*]}{.metadata.name}{"\\t"}{.metadata.namespace}{"\\n"}{end}'
    
    ```

## 기출문제 (59번)

Create a pod as follows: Name: mongo Using Image: mongo In a new Kubernetes namespace named: my-website

- 답안
    
    ```jsx
    kubectl create namespace my-website
    
    ```
    
    ```jsx
    kubectl run mongo --image=mongo --namespace=my-website
    
    ```

## 기출문제 (66번)

Create a pod that echo "hello world" and then exists.

Have the pod deleted automatically when it's completed

- 답안
    
    ```jsx
    # rm옵션은 pod를 생성하고 실행한 후 해당 pod를 삭제하는 옵션
    # it옵션은 쉘로 접속하여 컨테이너 상태를 파악하는 옵션
    kubectl run busybox --image=busybox -it --rm --restart=Never -- /bin/sh -c 'echo hello world'
    
    ```

## 기출문제 (68번)

Schedule a Pod as follows:

- Name: kucc1
- App Containers: 2
- Container Name/Images: o nginx o consul
- 답안

# [3] Static Pod 생성하기

일반적으로 kubectl 명령어를 실행하면 그 명령어가 API 서버에 전달되어 명령어 실행이 이루어 지는데 Static Pod의 경우에는 API 서버에 명령어가 전달되지 않는다.

바로 각 워커노드에 있는 kubelet에 전달한다.

## ❓Static Pod 생성하기

- Configure kubelet hosting to start a pod on the node
- TASK: 
    - node: hk8s-w1
    - pod Name: web
    - image: nginx

### 실습

```docker
# image가 nginx이고 이름이 web인 pod를 테스트로 실행하고 그 yaml파일 출력
[user@console ~]$ kubectl run web --image=nginx --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
	creationTimestamp: null
	labels:
		run: web
	name: web
spec: 
	containers:
	- image: nginx
		name: web
		resources: {}
	dnsPolicy: ClusterFirst
	restartPolicy: Always
Status: {}

# hk8s-w1 노드 접속
[user@console ~]$ ssh hk8s-w1

# root권한으로 전환
[user@hk8s-w1 ~]$ sudo -i

# kubelet의 config 파일 확인
# 기본 Pod 경로가 /etc/kubernetes/manifests 디렉토리로 지정되어있는거 확인
[root@hk8s-w1 ~]# cat /var/lib/kubelet/config.yaml
staticPodPath: /etc/kubernetes/manifests

[root@hk8s-w1 ~]# cd /etc/kubernetes/manifests

[root@hk8s-w1 manifests]# ls

# 아까 복사해놓은 yaml 템플릿을 약간 수정한 다음 저장
[root@hk8s-w1 manifests]# vi web-pod.yaml
apiVersion: v1
kind: Pod
metadata:
	name: web
spec: 
	containers:
	- image: nginx
		name: web

:wq

# 파일을 생성하자마자 node에 있는 kubelet이 pod를 동작시킨다.
# 이 파일을 삭제하면 pod도 같이 삭제된다.

[root@hk8s-w1 manifests]# exit

[user@hk8s-w1 manifests]$ exit

[user@console ~]$ kubectl get pods
web-hk8s-w1 라는 이름의 pod가 구동중인 것 확인

```

## 기출문제 (60번)

Configure the kubelet systemd- managed service, on the node labelled with name=wk8s -node-1, to launch a pod containing a single container of Image httpd named webtool automatically. Any spec files required should be placed in the /etc/kubernetes/manifests directory on the node

- 답안  
    ```jsx
    ssh wk8s-node-1
    
    ```
    
    ```jsx
    cat /var/lib/kubelet/config.yaml
    --> 여기서 staticPodPath가 /etc/kubernetes/manifests로 되어있는지 확인
    
    ```
    
    ```jsx
    cd /etc/kubernetes/manifests
    
    ```
    
    ```jsx
    kubectl run webtool --image=httpd --dry-run=client -o yamlvi webtool-pod.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        name: wk8s-node-1
      name: webtool
    spec:
      containers:
      - image: httpd
        name: webtool
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    :wq
    
    ```

# [4] Multi-Container Pod 생성하기

## ❓Multi-Container Pod 생성하기

- Create pod 
    - 작업 클러스터: hk8s
    - Create a pod named lab004 with 3 containers running: nginx, redis, memcached

### 실습

```docker
# 이미지가 nginx이고 이름이 lab004인 pod를 --dry-run 옵션으로 생성하고 해당 yaml파일을 multi.yaml이라는 이름의 파일로 출력
[user@console ~]$ kubectl run lab004 --image=nginx --dry-run=client -o yaml > multi.yaml

[user@console ~]$ ls
multi.yaml

[user@console ~]$ vi multi.yaml
apiVersion: v1
kind: Pod
metadata: 
	name: lab004
spec:
	containers:
	- image: nginx
		name: nginx
	- image: redis
		name: redis
	- image: memcached
		name: memcached

:wq

# multi.yaml 파일가지고 실행
[user@console ~]$ kubectl apply -f multi.yaml 

[user@console ~]$ kubectl get pods
lab004  0/3  ContainerCreating

# lab004 pod안에 어떤 컨테이너가 동작중인지 확인
[user@console ~]$ kubectl describe pod lab004


```

# [5] Side-car Container Pod 실행하기

하나의 Pod안에 nginx 어플리케이션 컨테이너가 동작하고 있다.

이 컨테이너는 varlog라는 이름을 가지는 볼륨을 마운트해서 사용하고 있으며 이 볼륨에 access.log, error.log를 기록하고 읽는다. (read, write)

동일한 Pod안데 log 분석 어플리케이션 컨테이너가 하나 더 생성된다.

이 컨테이너는 varlog 볼륨을 마운트해서 사용하고 있으며 이 볼륨에 있는 access.log, error.log를 읽고 분석한다. (read only)

이 때, 이 log분석 컨테이너를 side-car 컨테이너라고 하며 nginx 컨테이너를 main 컨테이너라고 하고 이 구조를 side-car container 구조라고 한다.

## ❓Side-car Container Pod

- An existing Pod needs to be integrated into the Kubernetes muilt-in logging architecture (e.g. kubectl logs).
    
    Adding a streaming sidecar container is a good and common way to accomplish this requirement.
- TASK
    
    
    - Add a sidecar container named `sidecar`, using the `busybox` image to the existing pod `eshop-cart-app`.
    - The new sidecar container has to run the following command: */bin/sh -c “tail -n+1 -F /var/log/cart-app.log”*
    - Use a volume, mounted at `/var/log`, to make the log file `cart-app.log` available to the sidecar container.
    - Don’t modify the cart-app.

### Reference

docs에서 sidecar container 검색

[Logging Architecture](https://kubernetes.io/docs/concepts/cluster-administration/logging/)

### 실습

```docker
# eshop-cart-app pod 확인
[user@console ~]$ kubectl get pod eshop-cart-app

# 현재 running 중인 eshop-cart-app이라는 pod의 yaml 템플릿을 얻어낸 후 eshop.yaml 파일이라는 이름으로 저장
[user@console ~]$ kubectl get pod eshop-cart-app -o yaml > eshop.yaml

[user@console ~]$ ls
eshop.yaml

# docs에 나오는 ex에 나오는 템플릿 이용
# 문제에 맞춰 수정한다 -> 여기서 아래 컨테이너만 존재하는게 아니라 기존 탬플릿에
# 존재하는 컨테이너 아래에 추가하는 것임.
# 즉, 기존 파드에서 빼낸 yaml파일에서
# kind, metadata, spec 순으로 있는데
# spec안에 containers와 같은 라인에 사이드카를 적어주는 것임

spec:
	containers:
	- command:
#여기서부터 원래있던 파드 정보가 있을거고 
#volumeMouts, mountPath, name이 있을건데
#거기 바로아래에 (- command:)와 같은 라인 유지
	- name: sidecar
	  image: busybox
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/cart-app.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log

:wq

# 기존에 있는 pod 삭제
[user@console ~]$ kubectl delete pod eshop-cart.app

# eshop.yaml 파일을 이용해서 pod 생성
[user@console ~]$ kubectl apply -f eshop.yaml

# 생성된 pod 확인
[user@console ~]$ kubectl get pods

# 명령어를 실행했을 때 log가 확인되면 된다.
# sidecar 라는 이름의 컨테이너의 로그를 확인하겠다는 의미
[user@console ~]$ kubectl logs eshop-cart-app -c sidecar

```

## 💡TIP!!

Pod YAML파일에 2개의 컨테이너에 대한 정보가 들어가야 한다.

하나는 main container에 대한 내용 (로그 기록)

나머지 하나는 side-car container에 대한 내용 (로그 확인)

## 기출문제 (62번)

An existing Pod needs to be integrated into the Kubernetes built-in logging architecture (e. g. kubectl logs).

Adding a streaming sidecar container is a good and common way to accomplish this requirement. Task: Add a sidecar container named sidecar, using the busybox Image, to the existing Pod bigcorp-app. The new sidecar container has to run the following command: */bin/sh -c tail -n+1 -f /var/log/big-corp-app.log* Use a Volume, mounted at /var/log, to make the log file big-corp-app.log available to the sidecar container.

Context: k8s

Don’t modify the specification of the existing container other than adding the required volume mount.

- 답안
    
    ```jsx
    kubectl config use-context k8s
    
    ```
    
    ```jsx
    # bigcorp-app이라는 pod가 있는지 확인
    kubectl get pods
    
    ```
    
    ```jsx
    kubectl get pod bigcorp-app -o yaml > bigcorp.yaml
    
    ```
    
    ```jsx
    vi bigcorp.yaml
    
    ...
    spec:
    	containers:
    		...
    	- name: sidecar
    	  image: busybox
        args: [/bin/sh, -c, 'tail -n+1 -f /var/log/big-corp-app.log']
        volumeMounts:
        - name: varlog
          mountPath: /var/log
    ...
    
    해당 부분 추가하고 :wq
    
    ```
    
    ```jsx
    kubectl delete pod bigcorp-app
    
    ```
    
    ```jsx
    # 수정한 yaml파일로 pod 생성
    kubectl apply -f bigcorp.yaml
    
    ```
    
    ```jsx
    # bigcorp-app pod안에 있는 sidecar 컨테이너의 로그 내용 확인
    kubectl logs bigcorp-app -c sidecar
    
    ```

# [6] Deployment & Pod Scale

# 1. Pod Scale out

## ❓Pod Scale Out

- Expand the number of running pods in “eshop-order” to 5. 
    - 작업 클러스터: k8s
    - namespace: devops
    - deployment: eshop-order

### Reference

docs에서 reference 검색 → scale

[Kubectl Reference Docs](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands)

### 실습

```docker
# 작업 클러스터 이동
[user@console ~]$ kubectl config use-context k8s

# devops라는 namespace가 있는지 확인
[user@console ~]$ kubectl get namespaces devops

# namespace가 devops인 곳에서 deployment가 있는지 확인
# 확인했을 때 2개의 pod가 돌아가고 있는거 확인
[user@console ~]$ kubectl get deployments.app -n devops
NAME           READY
eshop-order    2/2

# Deployment의 ReplicaSet을 5로 늘려준다
[user@console ~]$ kubectl scale deployment eshop-order -n devops --replicas=5

# 확인했을 때 5개의 pod가 돌아가고 있는거 확인
[user@console ~]$ kubectl get deployments.app -n devops
NAME           READY
eshop-order    5/5

```

# 2. deployment 생성하고 scaling하기

## ❓deployment 생성하고 scaling하기

- create a deployment as follows: 
    - 작업 클러스터: k8s
    - TASK: 
        - name: webserver
        - 2 replicas
        - label: app\_env\_stage=dev
        - container name: webserver
        - container image: nginx:1.14
    - Scale Out deployment 
        - Scale the deployment webserver to 3 pods

### 실습

```docker
# 조건에 맞게 deployment 생성
# webserver.yaml 파일로 YAML 파일 생성
[user@console ~]$ kubectl create deployment webserver --image=nginx:1.14 --replicas=2 --dry-run=client -o yaml > webserver.yaml

# webserver.yaml 파일 수정
[user@console ~]$ vi webserver.yaml

matchLabels:
	app: webserver
되어있는 부분을 아래처럼 수정하기
matchLabels:
	app_env_stage: dev
로 수정하기

밑에 metadata에 해당하는 labels 부분도 수정하기

container부분에 name webserver로 수정하기

:wq

# 수정한 yaml파일 실행
[user@console ~]$ kubectl apply -f webserver.yaml

# 확인
[user@console ~]$ kubectl get deployments -o wide

# 3개로 Scale Out
[user@console ~]$ kubectl scale deployments webserver --replicas=3

# 확인 (label 정보까지 포함해서)
[user@console ~]$ kubectl get pods --show-labels

```

## 기출문제 (10번)

Task: Scale the deployment webserver to 3 pods.

- 답안
    
    ```jsx
    kubectl get deployments
    --> webserver라는 deployment가 있는지 확인
    
    ```
    
    ```jsx
    kubectl scale deployment webserver --replicas=3
    
    ```

## 기출문제 (14번)

Task: Scale the deployment presentation to 6 pods.

- 답안
    
    ```jsx
    # presentation이라는 deployment가 있는지 확인
    kubectl get deployments presentation
    
    ```
    
    ```jsx
    kubectl scale deployment presentation --replicas=6
    
    ```

## 기출문제 (65번)

Create a deployment spec file that will: Launch 7 replicas of the nginx Image with the label app\_runtime\_stage=dev deployment name: kual00201.

Save a copy of this spec file to /opt/KUAL00201/spec\_deployment.yaml (or /opt/KUAL00201/spec\_deployment.json). When you are done, clean up (delete) any new Kubernetes API object that you produced during this task.

- 답안  
    ```jsx
    kubectl create deploy kual00201 --image=nginx --dry-run=client -o yaml > /opt/KUAL00201/spec_deployment.yaml
    
    ```
    
    ```jsx
    vi /opt/KUAL00201/spec_deployment.yaml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      creationTimestamp: null
      labels:
        app_runtime_stage: dev
      name: kual00201
    spec:
      replicas: 7
      selector:
        matchLabels:
          app_runtime_stage: dev
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
          labels:
            app_runtime_stage: dev
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
    status: {}
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f /opt/KUAL00201/spec_deployment.yaml 
    
    ```
    
    ```jsx
    # 만들어졌는지 확인
    kubectl get deploy kual00201
    
    ```
    
    ```jsx
    # 만든 것 삭제하기
    rm -rf /opt/KUAL00201/spec_deployment.yaml 
    
    kubectl delete deploy kual00201
    
    ```

# [7] Rolling Update & Rollback

## ❓Rolling Update

- Create a deployment as follows: 
    - 작업 클러스터: k8s
    - TASK: 
        - name: nginx-app
        - Using container nginx with version 1.11.10-alpine
        - The deployment should contain 3 replicas
- Next, deploy the application with new version 1.11.13-alpine, by performing a rolling update
- Finally, rollback that update to the previous version 1.11.10-alpine

### Reference

docs에서 Deployment검색 Updating a Deployment 부분 확인

[Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)

### 실습

```docker
# 클러스터 전환
[user@console ~]$ kubectl config use-context k8s

# 조건에 맞춰 deployment 생성
# dry-run 옵션 사용
[user@console ~]$ kubectl create deployment nginx-app --image=nginx:1.11.10-alpine --replicas=3

# 만들어진 deployment 확인
[user@console ~]$ kubectl get deployment nginx-app
NAME          READY
nginx-app     3/3

# nginx-app로 시작하는 pod확인
[user@console ~]$ kubectl get pods |grep nginx-app

# POD안에 있는 container 버전 확인
[user@console ~]$ kubectl describe pod {pod 이름}
container 이미지 버전 nginx:1.11.10-alpine 인거 확인

# docs 참고해서 update
# 여기서 nginx는 container이름
# --record 옵션을 쓰면 히스토리 파악 가능
[user@console ~]$ kubectl set image deployment nginx-app nginx=nginx:1.11.13-alpine --record

# update가 되고있는지 과정 확인
[user@console ~]$ kubectl rollout status deployment/nginx-app

# update가 됬는지 확인
[user@console ~]$ kubectl get pods |grep nginx-app

# 위의 결과에서 나온 하나의 pod 확인
# 버전 업데이트 된 것 확인하기
[user@console ~]$ kubectl describe pod {pod이름}

# rollback 하기 
# 바로 전 단계로 롤백된다
[user@console ~]$ kubectl rollout undo deployment/nginx-app

# rollback 된 것 확인
[user@console ~]$ kubectl get pods | grep nginx-app

[user@console ~]$ kubectl describe pod {pod이름}

```

### Update가 되는 과정

update를 실행하면 기존에 있는 Replicaset에서 새로운 Replicaset이 생성되고 그 새로 생성된 곳에 업데이트 된 버전의 pod가 생성된다.

업데이트 된 버전의 pod가 하나씩 생겨날때마다 기존 버전의 pod가 하나씩 삭제된다.

업데이트가 모두 완료된 후에 get pods명령어를 확인해보면 다른 해쉬값을 가지는 replicaset이 생성된 것을 확인할 수 있다.

# [8] NodeSelector

# NodeSelector란?

특정 Application Pod를 특정 Node에 실행시켜달라는 것

## ❓Schedule a pod

- 작업 클러스터: k8s
- Schedule a pod as follows: 
    - Name: eshop-store
    - Image: nginx
    - Node selector: disktype=ssd

### Reference

docs에서 nodeselector 검색

[Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/)

### 실습

```docker
# 클러스터 전환
[user@console ~]$ kubectl config use-context k8s

# node 정보 확인 (label 정보랑 같이)
[user@console ~]$ kubectl get nodes --show-labels
NAME          STATUS
k8s-master    READY
k8s-worker1   READY
k8s-worker2   READY

# node 정보 확인 (disktype label 정보랑 같이)
[user@console ~]$ kubectl get nodes -L disktype
NAME          STATUS   DISKTYPE
k8s-master    READY
k8s-worker1   READY    ssd
k8s-worker2   READY    std

# pod 생성하기
[user@console ~]$ kubectl run eshop-store --image=nginx --dry-run=client -o yaml

# yaml 템플릿으로 yaml 파일 생성
[user@console ~]$ kubectl run eshop-store --image=nginx --dry-run=client -o yaml > eshop-store.yaml

[user@console ~]$ vi eshop-store.yaml

spec:
	nodeSelector:
		disktype: ssd
추가하기

:wq

# 수정한 yaml파일로 pod 생성
[user@console ~]$ kubectl apply -f eshop-store.yaml

# 확인
[user@console ~]$ kubectl get pods -o wide eshop-store
NODE 부분 확인하면 k8s-worker1에 생성된 것 확인

```

## 기출문제 (36번)

Schedule a pod as follows: Name: nginx-kusc00101 Image: nginx Node selector: disk=ssd

- 답안  
    ```jsx
    # 각 노드들이 disk 라벨값을 뭘로 가지는지 확인해서 어느 노드에 할당될지 미리 파악하기
    kubectl get nodes -L disk
    
    ```
    
    ```jsx
    kubectl run nginx-kusc00101 --image=nginx --dry-run=client -o yaml > kusc.yaml
    
    ```
    
    ```jsx
    # nodeSelector부분 container와 동일한 급으로 추가
    vi kusc.yaml
    
    ...
    spec:
    	container:
    		...
    	nodeSelector:
    		disk: ssd
    ...
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f kusc.yaml
    
    ```
    
    ```jsx
    # 확인하기
    kubectl get pods
    
    kubectl describe pod nginx-kusc00101
    
    ```

# [9] Node 관리

# Node 관련된 명령어 정리

```docker
# 현재 시스템의 노드 정보 확인하기
kubectl get nodes 

# 더 자세한 정보 확인
kubectl get nodes -o wide

# 해당 node에 대한 자세한 정보 확인
kubectl describe node {node 이름}

# pod에 대한 자세한 정보 확인
kubectl get pods -o wide

# 특정 node에는 배치되지 않도록 하기 (스케줄링 중지)
kubectl cordon k8s-worker1

# 배치되지 않도록 해줬던 설정을 해제하기 (스케줄링 시작)
kubectl uncordon k8s-worker1

# 해당 node에 동작되고 있는 모든 pod들이 삭제됨
kubectl drain k8s-worker2
daemonset으로 실행되고 있는 pod들은 삭제 안됨 -> --ignore-daemonsets 옵션을 넣어주면 해당 에러를 무시하고 모든 pod들을 삭제한다
해당 옵션 사용하면 스케줄링도 자동으로 중지된다.

# k8s-worker2를 다시 스케줄링 가능하게 하기
kubectl uncordon k8s-worker2
이렇게 해도 원래 worker1에서 동작중이던 pod들이 옮겨지지는 않는다.

이 이후에 scale out 명령을 수행하면 k8s-worker2에도 스케줄링 된다.

```

## ❓Management Node

- Set the node named k8s-worker1 as unavailable and reschedule all the pods running on it.
- 작업 클러스터: k8s

### Reference

docs에서 reference 검색 후 cordon 찾기

[Kubectl Reference Docs](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#cordon)

### 실습

```docker
# 클러스터 전환
[user@console ~]$ kubectl config use-context k8s

# daemonset에 의해 구동중인 pod 정보들도 확인
# k8s-worker1에서 구동중인 모든 pod정보 확인
[user@console ~]$ kubectl get pods -o wide -A | grep worker1

# k8s-worker1에 있는 모든 pod들 삭제
# 해당 node에서 사용하고 있는 스토리지도 삭제 (--delete-emptydir-data)
[user@console ~]$ kubectl drain k8s-worker1 --ignore-daemonsets --force --delete-emptydir-data

이렇게 drain하면 이제 더이상 k8s-worker1에는 스케줄링 되지 않는다.
그리고 k8s-worker1에 있던 pod들은 k8s-worker2 node에 재배치된다. (reschedule)

# node 정보 확인
[user@console ~]$ kubectl get pods -o wide

# k8s-worker1에서는 더이상 스케줄링 안받는다는 상태 확인
[user@console ~]$ kubectl get nodes
```

# [10] Node 정보 수집

## ❓Check Ready Nodes

- Check to see how many nodes are ready (not including nodes tainted NoSchedule) and write the number to /var/CKA2022/RN0001 
    - not including nodes tainted NoSchedule —&gt; tainted에 NoSchedule 적혀있는건 제외

### 실습

```docker
# ready 단어와 일치하는 것만 결과 출력
[user@console ~]$ kubectl get nodes | grep -i -w ready
hk8s-m    Ready
hk8s-w1   Ready

[user@console ~]$ kubectl describe node hk8s-m | grep -i NoSchedule

[user@console ~]$ kubectl describe node hk8s-w1 | grep -i NoSchedule

```

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/SFLimage.png)](http://138.2.116.150/uploads/images/gallery/2023-05/SFLimage.png)

hk8s-m 노드에는 NoSchedule 정보가 포함되어 있음

```docker
# 결과값 파일에 저장
[user@console ~]$ echo "1" > /var/CKA2022/RN0001

[user@console ~]$ cat /var/CKA2022/RN0001
1

```

## ❓Count the number of nodes that are ready to run normal workloads

- Determine how many nodes in the cluster are ready to run normal workloads (i.e workloads that do not have any special tolerations)
- Output this number to the file /var/CKA2022/NODE-Count

### 실습

```docker
# ready 상태인 노드 출력
[user@console ~]$ kubectl get nodes | grep -i -w ready

[user@console ~]$ kubectl get nodes | grep -i -w ready | wc -l
2

[user@console ~]$ kubectl get nodes | grep -i -w ready | wc -l > /var/CKA2022/NODE-Count

[user@console ~]$ cat /var/CKA2022/NODE-Count
2
```

# [11] Deployment & Expose the Service

## ❓Deploy and Service

- Reconfigure the existing deployment `front-end` and add a port specification named `http` exposing port `80/tcp` of the existing container nginx.
- Create a new service named `front-end-svc` exposing the container port http.
- Configure the new service to also expose the individual Pods via a `NodePort` on the nodes on which they are scheduled. 
    - 작업 클러스터: k8s

### Reference

docs에서 nodeport검색

[Service](https://kubernetes.io/docs/concepts/services-networking/service/)

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ kubectl get deployment front-end

[user@console ~]$ kubectl get deployment front-end -o yaml > front-end.yaml

[user@console ~]$ vi front-end.yaml

기존 파일에 밑의 내용 추가

spec:
  containers:
  - image: nginx
		name: http
#여기까지가 기존내용, 아래 내용 전부 넣기
    ports:
      - containerPort: 80
        name: http

---
apiVersion: v1
kind: Service
metadata:
  name: front-end-svc
spec:
	type: NodePort
  selector:
    run: nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: http

:wq

# 충돌되지 않도록 삭제 후 생성
[user@console ~]$ kubectl delete deployment front-end

[user@console ~]$ kubectl apply -f front-end.yaml

```

## 기출문제 (31번)

Create a deployment as follows: Name: nginx-random Exposed via a service nginx-random Ensure that the service &amp; pod are accessible via their respective DNS records.

The container(s) within any pod(s) running as a part of this deployment should use the nginx Image.

Next, use the utility nslookup to look up the DNS records of the service &amp; pod and write the output to /opt/KUNW00601/service.dns and /opt/KUNW00601/pod.dns respectively.

- 답안
    
    ```jsx
    kubectl create deploy nginx-random --image=nginx --dry-run=client -o yaml
    ```

## 기출문제 (63번)

Create and configure the service front-end-service so it's accessible through NodePort and routes to the existing pod named front-end.

- 답안  
    ```jsx
    kubectl expose pod front-end --port=80 --protocol=TCP --target-port=80 --name=front-end-service --type=NodePort
    ```

# [12] Pod Log 추출

## ❓Record the extracted log lines

- Monitor the logs of pod custom-app and: Extract log lines corresponding to error file not found. write them to /var/CKA2022/podlog 
    - 작업 클러스터: hk8s

### Reference

docs에서 reference 검색 &gt; logs 검색

[Kubectl Reference Docs](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#logs)

### 실습

```docker
[user@console ~]$ kubectl config use-context hk8s

[user@console ~]$ kubectl get pods custom-app

[user@console ~]$ kubectl logs custom-app | grep 'file not found'

[user@console ~]$ kubectl logs custom-app | grep 'file not found' > /var/CKA2022/podlog

# 잘 들어갔는지 확인
[user@console ~]$ cat /var/CKA2022/podlog

```

## 기출문제 (1번)

List pod logs named "frontend" and search for the pattern "started" and write it to a file "/opt/error-logs"

- 답안
    
    ```jsx
    kubectl get pod frontend
    
    ```
    
    ```jsx
    kubectl logs frontend | grep -i "started" > /opt/error-logs
    
    ```
    
    ```jsx
    # 확인
    cat /opt/error-logs
    
    ```

## 기출문제 (7번)

Monitor the logs of pod foo and: Extract log lines corresponding to error unable-to-access-website Write them to /opt/KULM00201/foo

- 답안
    
    ```jsx
    kubectl get pods
    --> foo라는 이름의 pod있는지 확인
    
    ```
    
    ```jsx
    kubectl logs foo | grep unable-to-access-website
    
    ```
    
    ```jsx
    kubectl logs foo | grep unable-to-access-website > /opt/KULM00201/foo
    
    ```

## 기출문제 (17번)

Task Monitor the logs of pod bar and:

- Extract log lines corresponding to error file-not-found
- Write them to /opt/KUTR00101/bar
- 답안  
    ```jsx
    kubectl logs bar | grep file-not-found
    
    ```
    
    ```jsx
    kubectl logs bar | grep file-not-found > /opt/KUTR00101/bar
    
    ```

# [13] CPU 사용량이 높은 Pod 검색

## ❓Find a Pod that consumes a lot of CPU

- From the pod label name=overloaded-cpu, find pods running high CPU workloads and write the name of the pod consuming most CPU to the file /var/CKA2022/cpu\_load\_pod.txt 
    - 작업 클러스터: hk8s

### Reference

docs에서 reference 검색 → top 검색

[Kubectl Reference Docs](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#top)

### 실습

```docker
[user@console ~]$ kubectl config use-context hk8s

[user@console ~]$ kubectl top pods -l name=overloaded-cpu

# cpu사용량이 높은 순대로 정렬
[user@console ~]$ kubectl top pods -l name=overloaded-cpu --sort-by=cpu

```

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/825153b6-dea6-423e-8589-bc67c988086d/Untitled.png)

```docker
[user@console ~]$ echo "campus-01" > /var/CKA2022/cpu_load_pod.txt

[user@console ~]$ cat /var/CKA2022/cpu_load_pod.txt

```

## 기출문제 (20번)

Task From the pod label name=cpu-utilizer, find pods running high CPU workloads and write the name of the pod consuming most CPU to the file /opt/KUTR00401/KUTR00401.txt (which already exists).

- 답안  
    ```jsx
    kubectl top pod -l name=cpu-utilizer --sort-by=cpu
    --> CPU 사용량 제일 높은 pod의 이름 확인
    
    ```
    
    ```jsx
    echo '{pod이름}' > /opt/KUTR00401/KUTR00401.txt
    
    ```

# [14] init 컨테이너를 포함한 Pod 운영

# init 컨테이너에 대해 알아보기

docs에서 init container 검색

[초기화 컨테이너](https://kubernetes.io/ko/docs/concepts/workloads/pods/init-containers/)

## init 컨테이너란

초기화 컨테이너는 파드의 앱 컨테이너들이 실행되기 전에 실행되는 특수한 컨테이너이다.

이 init 컨테이너가 정상적으로 실행되야 main 컨테이너가 실행되고 실패할 경우 성공할때까지 재실행된다.

비슷한 경우로는 AWS의 user data같은거

## Tip!

이 유형에 대한 문제는 CKA보다는 CKAD에서 더 자주 나오는 유형의 문제이다

## ❓Additional init container

- Add an init container to web-pod(which has been defined in spec file /data/cka/webpod.yaml)
- The init container should create an empty file named /workdir/data.txt
- If /workdir/data.txt is not detected, the Pod should exit.
- Once the spec file has been updated with the init container definition, the Pod should be created.

### 실습

```docker
[user@console ~]$ vi /data/cka/webpod.yaml

apiVersion: v1
kind: Pod
metadata:
	name: web-pod
spec:
	containers:
	- image: busybox:1.28
		name: main
		command: ['sh', '-c', 'if [ !-f /workdir/data.txt ];then exit 1;else sleep 300;fi']
		volumeMounts:
		- name: workdir
			mountPath: "/workdir"
#여기까지 기존내용, 여기서부터
	initContainers:
	- name: init
		image: busybox:1.28
		command: ['sh', '-c', "touch /workdir/data.txt"]
		volumeMounts:
		- name: workdir
			mountPath: "/workdir"
#여기위까지 내용을 추가
	volumes:
	- name: workdir
		emptyDir: {}

:wq

[user@console ~]$ kubectl apply -f /data/cka/webpod.yaml

[user@console ~]$ kubectl get pods 
web-pod라는 이름의 pod가 실행됬는지 확인하기

```

## 기출문제 (40번)

Perform the following tasks: Add an init container to hungry-bear (which has been defined in spec file /opt/KUCC00108/pod-spec-KUC C00108.yaml )

The init container should create an empty file named /workdir/calm.txt If /workdir/calm.txt is not detected, the pod should exit.

Once the spec file has been updated with the init container definition, the pod should be created

- 답안  
    ```jsx
    vi /opt/KUCC00108/pod-spec-KUC C00108.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: hungry-bear
    spec:
      volumes:
      - name: workdir
        emptyDir: {}
      containers:
      - image: alpine
        name: checker
        command: ["/bin/sh", "-c", "if [ -f /workdir/calm.txt ]; then sleep 100000; else exit 1; fi"]
        volumeMounts:
        - name: workdir
          mountPath: /workdir
      initContainers:
      - name: init-myservice
        image: alpine
        command: ["/bin/sh", "-c", "touch /workdir/calm.txt"]
        volumeMounts:
        - name: workdir
          mountPath: /workdir
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f /opt/KUCC00108/pod-spec-KUC C00108.yaml
    
    ```

# [15] NodePort 서비스 생성

# NodePort란?

클러스터 외부의 사용자가 클러스터 내에 위치한 서비스에 접근하도록 할 수 있게 하는 서비스타입

## ❓NodePort Service

- Create the service as type NodePort with port 32767 for the nginx pod with the pod selector app:webui
- 작업 클러스터: k8s

### Reference

docs에서 nodeport 검색 → Type Nodeport 부분

[Service](https://kubernetes.io/docs/concepts/services-networking/service/)

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ kubectl get pod --selector app=webui

[user@console ~]$ vi myservice.yaml

docs에 나와있는 example 가공

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app:webui
  ports:
    - port: 80
      targetPort: 80
      nodePort: 32767

:wq

[user@console ~]$ cat myservice.yaml

[user@console ~]$ kubectl apply -f myservice.yaml

[user@console ~]$ kubectl get services my-service

[user@console ~]$ kubectl get nodes
ready상태인 노드 아무거나 본 다음

# 결과 출력 확인
[user@console ~]$ curl {node이름}:32767

```

## 기출문제 (63번)

Create and configure the service front-end-service so it's accessible through NodePort and routes to the existing pod named front-end.

- 답안
    
    ```jsx
    kubectl expose pod front-end --name=front-end-service --port=80 --target-port=80 --type=NodePort
    
    ```

# [16] ConfigMap 운영

# ConfigMap이란? 

ConfigMap은 애플리케이션 설정 데이터를 관리하는 데 사용된다. 애플리케이션 구성, 환경 변수, 설정 파일 등과 같은 설정 정보를 저장하고 관리하는 데 사용 된다. ConfigMap은 YAML 파일로 정의되며, Pod, Deployment, StatefulSet 등의 다른 K8s 리소스에서 사용될 수 있다.

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/7Ywimage.png)](http://138.2.116.150/uploads/images/gallery/2023-05/7Ywimage.png)

### 실습

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/VVYimage.png)](http://138.2.116.150/uploads/images/gallery/2023-05/VVYimage.png)

# [17] Secret 운영

## ❓Secret을 생성 후 Pod에 전달

- Create a kubernetes secret and expose using a file in the pod.
- 작업 클러스터: k8s

1. Create a kubernetes secret as follows:
    
    
    1. Name: super-secret
    2. DATA:
        
        password=secretpass
2. Create a Pod named `pod-secrets-via-file`, using the `redis` image, which mounts a secret named `super-secret` at `/secrets`
3. Create a second Pod named `pod-secrets-via-env` using the `redis` image which exports password as PASSWORD

### Reference

docs에서 secret검색 → Use Cases 부분

[Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ kubectl get secrets

[user@console ~]$ kubectl describe super-secrets

[user@console ~]$ kubectl get secret super-secrets
```

# [18] Ingress 구성

# Ingress란?

인그레스는 클러스터 외부에서 클러스터 내부 서비스로 HTTP와 HTTPS 경로를 노출한다.

트래픽 라우팅은 인그레스 리소스에 정의된 규칙에 의해 컨트롤된다.

### Reference

docs에서 ingress 검색

[인그레스(Ingress)](https://kubernetes.io/ko/docs/concepts/services-networking/ingress/)

## ❓Ingress 구성

- Application Service 운영 
    - 작업 클러스터: k8s
    - `ingress-nginx` namespace에 nginx 이미지를 `app=nginx` 레이블을 가지고 실행하는 `nginx` pod를 구성하시오
    - 앞서 생성한 nginx pod를 서비스하는 nginx service를 생성하세요
    - 현재 `appjs-service` Service는 이미 동작 중입니다. 별도 구성이 필요 없습니다.
- Ingress 구성 
    - `app-ingress.yaml` 파일을 생성하여 다음 조건의 ingress 서비스를 구성하세요 
        - ingress name: `app-ingress`
        - NODE\_PORT:30080/ 접속했을 때 nginx 서비스로 연결
        - NODE\_PORT:30080/app 접속했을 때 appjs-service 서비스로 연결
        - ingress 구성에 다음 annotations을 포함시키시오
            
            annotations:
            
            [kubernetes.io/ingress.class:](http://kubernetes.io/ingress.class:) nginx

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s 

# ingress-nginx 네임스페이스에 있는 파드 가져옴
[user@console ~]$ kubectl get pods -n ingress-nginx

# 조건에 충족하는 파드를 run 명령으로 ingress-nginx 네임스페이스에 생성
[user@console ~]$ kubectl run nginx --namespace=ingress-nginx --image=nginx --labels=app=nginx

[user@console ~]$ kubectl get pods -n ingress-nginx

# 서비스를 생성하기 위해 방금 생성한 파드를 expose함
[user@console ~]$ kubectl expose -n ingress-nginx pod nginx --port 80 --target-port 80

[user@console ~]$ kubectl get svc -n ingress-nginx

[user@console ~]$ kubectl describe svc -n ingress-nginx nginx

---------- docs에서 ingress 검색 -> The Ingress resource 검색해서 다 긁어옴 ----------

# yaml파일 vi로 만들어서 긁어온 내용 복붙하고 수
[user@console ~]$ vi app-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
	namespace: ingress-nginx
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
		kubernetes.io/ingress.class: nginx
spec:
  ingressClassName: nginx-example
  rules:
  - http:
      paths:
			- path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
# 여기 위 number 포트는 위에서kubectl get svc -n ingress-nginx했을 때 
# nginx, appjs-service가 어떤 포트 사용하고 있는지 확인하고 넣어준다.
      - path: /app
        pathType: Prefix
        backend:
          service:
            name: appjs-service
            port:
              number: 80
			
:wq

# namespace가 ingress-nginx인 곳에서 돌아가고 있는 서비스 목록 확인
[user@console ~]$ kubectl get svc -n ingress-nginx
appjs-service서비스는 80포트 사용
nginx 서비스는 80포트 사용

[user@console ~]$ kubectl apply -f app-ingress.yaml

[user@console ~]$ kubectl get ingress -n ingress-nginx

[user@console ~]$ kubectl describe ingress -n ingress-nginx

[user@console ~]$ kubectl get nodes

[user@console ~]$ curl k8s-worker1:30080

[user@console ~]$ curl k8s-worker1:30080/app

```

## 기출문제 (30번)

Task Create a new nginx Ingress resource as follows:

- Name: ping
- Namespace: ing-internal
- Exposing service hi on path /hi using service port 5678
- hi서비스는 있다고 가정
- 답안  
    ```jsx
    vi ping.yaml
    
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      namespace: ing-internal
      name: ping
    spec:
      rules:
      - http:
          paths:
          - path: /hi
            pathType: Prefix
            backend:
              service:
                name: hi
                port:
                  number: 5678
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f ping.yaml
    
    ```

# [19] Persistent Volume 생성

# Persistent Volume이란

클러스터 내의 지속적인 데이터 저장을 위한 추상화된 스토리지를 제공한다. 클러스터 외부 스토리지 리소스를 클러스터 내부에서 사용할 수 있게 하며, 데이터의 지속성과 데이터 볼륨에 대한 독립성을 보장 한다. 그 외 클러스터 관리자에 의해 생성되고 관리되며, Pod 및 다른 K8s 리소스에서 사용할 수 있다. 이를 통해 애플리케이션에서 데이터를 영속적으로 저장하고 공유할 수 있다.

### Reference

docs에서 persistent volume 검색

[퍼시스턴트 볼륨](https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/)

## ❓Create Persistent Volume

- Create a Persistent Volume with name `app-config` of capacity `1Gi` and access mode `ReadWriteMany`
- StorageClass: az-c
- The type of Volume is `hostPath` and its location is `/srv/app-config`
- 작업 클러스터: k8s

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ vi app-config-pv.yaml

#docs에서 persistent volume 검색 --> Persistent Volumes 부분 긁어옴

apiVersion: v1
kind: PersistentVolume
metadata:
  name: app-config
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  storageClassName: az-c
	hostPath:
		path: /srv/app-config

:wq

[user@console ~]$ kubectl apply -f app-config-pv.yaml

[user@console ~]$ kubectl get pv

```

# [20] Persistent Volume Claim을 사용하는 Pod 운영

# ❓Application with Persistent Volume Claim

- Create a new PersistentVolumeClaim 
    - Name: `app-volume`
    - Storage Class: `app-hostpath-sc`
    - Capacity: `10Mi`
- Create a new pod which mounts the PersistentVolumeClaim as a volume 
    - Name: `web-server-pod`
    - Image: `nginx`
    - Mount Path: `/usr/share/nginx/html`
- Configure the new pod to have `ReadWriteMany` access on the volume.
- 작업 클러스터: k8s

### Reference

docs에서 persistent volume 검색 후 → PersistentVolumeClaim부분

[Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)

docs에서 persistent volume 검색 후 → claims as volumes

[Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ vi app-volume-pvc.yaml

#docs에서 Persistent volume 검색 후 PersistentVolumeClaims 부분 긁어옴

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-volume
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Mi
  storageClassName: app-hostpath-sc

:wq

[user@console ~]$ kubectl apply -f app-volume-pvc.yaml

[user@console ~]$ kubectl get pvc 

[user@console ~]$ vi web-server-pod.yaml

#docs에서 persistent volume 검색 -> Claims as volumes 부분 긁어옴

apiVersion: v1
kind: Pod
metadata:
  name: web-server-pod
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
      - mountPath: "/usr/share/nginx/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: app-volume
  
:wq

[user@console ~]$ kubectl apply -f web-server-pod.yaml

[user@console ~]$ kubectl get pods

[user@console ~]$ kubectl describe pod web-server-pod

```

## 기출문제 (61번)

kubectl config use-context k8s Create a new PersistentVolumeClaim:

Name: pv-volume

Class: app-hostpath-sc

Capacity: 10Mi Create a new Pod which mounts the PersistentVolumeClaim as a volume: Name: web-server-pod Image: nginx Mount path: /usr/share/nginx/html Configure the new Pod to have ReadWriteMany access on the volume. Finally, using kubectl edit or kubectl patch expand the PersistentVolumeClaim to a capacity of 70Mi and record that change.

- 답안
    
    ```jsx
    
    
    ```

## 기출문제 (13번)

List all persistent volumes sorted by capacity, saving the full kubectl output to /opt/KUCC00102/volume\_list.

Use kubectl 's own functionality for sorting the output, and do not manipulate it any further

- 답안
    
    ```jsx
    kubectl get pv --sort-by=.spec.capacity.storage > /opt/KUCC00102/volume_list
    
    ```

## 기출문제 (16번)

Create a persistent volume with name app-data, of capacity 2Gi and access mode ReadWriteMany.

The type of volume is hostPath and its location is /srv/app-data.

- 답안
    
    ```jsx
    vi pv.yaml
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: app-data
    spec:
      capacity:
        storage: 2Gi
      volumeMode: Filesystem
      accessModes:
        - ReadWriteMany
      persistentVolumeReclaimPolicy: Recycle
      storageClassName: slow
      hostPath:
        path: /srv/app-data
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f pv.yaml
    
    ```

## 기출문제 (55번)

Task Create a persistent volume with name app-data , of capacity 1Gi and access mode ReadOnlyMany. The type of volume is hostPath and its location is /srv/app-data .

- 답안
    
    ```jsx
    vi pv.yaml
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: app-data
    spec:
      capacity:
        storage: 1Gi
      volumeMode: Filesystem
      accessModes:
        - ReadOnlyMany
      persistentVolumeReclaimPolicy: Recycle
      storageClassName: slow
      hostPath:
        path: /srv/app-data
    
    :wq
    
    ```
    
    ```jsx
    kubectl apply -f pv.yaml
    
    ```

# [21] Check Resource Information

## ❓Check Resource Information

- List all PVs sorted by name saving the full `kubectl` output to `/var/CKA2022/my_volumes`
- Use `kubectl` ’s own functionally for sorting the output, and do not manipulate it any further.
- 작업 클러스터: k8s

### 실습

```docker
[user@console ~]$ kubectl config use-contest k8s

[user@console ~]$ kubectl get svc 

```

[![image.png](http://138.2.116.150/uploads/images/gallery/2023-05/scaled-1680-/jyuimage.png)](http://138.2.116.150/uploads/images/gallery/2023-05/jyuimage.png)

```docker
# 이건 yaml 파일 형태로 출력하는 것
[user@console ~]$ kubectl get svc kubernetes -o yaml

# 이건 json 파일 형태로 출력하는 것
[user@console ~]$ kubectl get svc kubernetes -o json

json 형태로 된 포맷을 보면 .metadata.name 이런식으로 보이는데 이 뜻이 metadata 밑에 있는 name 이런 뜻

# 문제에서 name으로 sort하라고 했으니깐
[user@console ~]$ kubectl get pv --sort-by=.metadata.name

[user@console ~]$ kubectl get pv --sort-by=.metadata.name > /var/CKA2022/my_volumes

# 확인
[user@console ~]$ cat /var/CKA2022/my_volumes

```

# [22] Kubernetes Upgrade

## ❓Cluster Upgrade - only Master

- upgrade system: k8s-master
- Given an existing Kubernetes cluster running version `1.22.4`, upgrade all of the Kubernetes control plane and node components on the master node only to version `1.23.3`
- Be sure to `drain` the `master` node before upgrading it and `uncordon` it after the upgrade.

### Reference

docs에서 upgrade kubeadm 검색

[Upgrading kubeadm clusters](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)

### 실습

```docker
[user@console ~]$ kubectl config use-context k8s

[user@console ~]$ ssh k8s-master

[user@k8s-master ~]$ sudo -i

# 시험환경은 ubuntu 환경이니까 헷갈려 하지 않기
# Ubuntu
[root@k8s-master ~]# apt-update
[root@k8s-master ~]# apt-cache madison kubeadm

# Ubuntu
[root@k8s-master ~]# apt-mark unhold kubeadm && \\
 apt-get update && apt-get install -y kubeadm=1.23.3-00 && \\
 apt-mark hold kubeadm

# v1.23.3 버전으로 업그레이드 할 수 있는 master component 목록 확인
[root@k8s-master ~]# kubeadm upgrade plan v1.23.3
[root@k8s-master ~]# sudo kubeadm upgrade apply v1.23.3

# 현재 우리는 문제에서 요구한대로 k8s-master로 ssh를 통해 들어와서 작업중인데
# 이 마스터노드를 master노드를 drain 하는 작업을 해야하기 때문에
# exit로 console로 나와서 작업해줘야 한다.
[root@k8s-master ~]# exit
[user@k8s-master ~]$ exit
[user@console ~]$ kubectl drain k8s-master --ignore-daemonsets

# 이제 다시 마스터 노드로 들어간다
[user@console ~]$ ssh k8s-master

# Ubuntu
[user@k8s-master ~]$ sudo apt-mark unhold kubelet kubectl && \\
apt-get update && \\
apt-get install -y kubelet=1.23.3-00 kubectl=1.23.3-00 && \\
apt-mark hold kubelet kubectl

[user@k8s-master ~]$ sudo -i 
[root@k8s-master ~]# systemctl daemon-reload
[root@k8s-master ~]# systemctl restart kubelet

# 이제 다 끝나서 다시 콘솔로 나온 후에 언코던을 해준다
[root@k8s-master ~]# exit
[user@k8s-master ~]$ exit
[user@console ~]$ kubectl uncordon k8s-master
[user@console ~]$ kubectl get nodes

```

## 기출문제

upgrade system : k8s-worker1, k8s-worker2 k8s 클러스터의 모든 worker를 1.23.3 으로 업그레이드 하시오.

- 답안
    
    ```jsx
    # Ubuntu 환경
    kubectl config use-context k8s
    
    ```
    
    ```jsx
    ssh k8s-worker1
    
    sudo -i
    
    ```
    
    ```jsx
    apt-mark unhold kubeadm && \\
    apt-get update && apt-get install -y kubeadm=1.23.3-00 && \\
    apt-mark hold kubeadm
    
    ```
    
    ```jsx
    sudo kubeadm upgrade node
    
    ```
    
    ```jsx
    # console 창으로 이동
    exit
    
    ```
    
    ```jsx
    kubectl drain k8s-worker1 --ignore-daemonsets
    
    ```
    
    ```jsx
    ssh k8s-worker1
    
    ```
    
    ```jsx
    apt-mark unhold kubelet kubectl && \\
    apt-get update && apt-get install -y kubelet=1.23.3-00 kubectl=1.23.3-00 && \\
    apt-mark hold kubelet kubectl
    
    ```
    
    ```jsx
    sudo systemctl daemon-reload
    
    sudo systemctl restart kubelet
    
    ```
    
    ```jsx
    # console 창으로 이동
    exit
    
    ```
    
    ```jsx
    kubectl uncordon k8s-worker1
    --> k8s-worker2도 동일하게 진행
    
    ```
    
    ```jsx
    kubectl get nodes
    --> 노드 버전 확인
    
    ```

## 기출문제 (25번)

Given an existing Kubernetes cluster running version 1.20.0, upgrade all of the Kubernetes control plane and node components on the master node only to version 1.20.1. Be sure to drain the master node before upgrading it and uncordon it after the upgrade.

You are also expected to upgrade kubelet and kubectl on the master node.

- 답안  
    ```jsx
    kubectl get nodes
    --> node 이름 확인
    
    ```
    
    ```jsx
    ssh {Node 이름}
    
    sudo -i 
    
    ```
    
    ```jsx
    # Ubuntu 버전
    apt update
    
    ```
    
    ```jsx
    apt-cache madison kubeadm
    
    ```
    
    ```jsx
    apt-mark unhold kubeadm && \\
     apt-get update && apt-get install -y kubeadm=1.20.1-00 && \\
     apt-mark hold kubeadm
    
    ```
    
    ```jsx
    kubeadm version
    
    ```
    
    ```jsx
    kubeadm upgrade plan
    
    ```
    
    ```jsx
    sudo kubeadm upgrade apply v1.20.1
    
    ```
    
    ```jsx
    # console 창으로 이동
    exit
    
    ```
    
    ```jsx
    kubectl drain <node-to-drain> --ignore-daemonsets
    
    ```
    
    ```jsx
    ssh {Node 이름}
    
    ```
    
    ```jsx
    apt-mark unhold kubelet kubectl && \\
    apt-get update && apt-get install -y kubelet=1.20.1-00 kubectl=1.20.1-00 && \\
    apt-mark hold kubelet kubectl
    
    ```
    
    ```jsx
    sudo systemctl daemon-reload
    
    sudo systemctl restart kubelet
    
    ```
    
    ```jsx
    # console 창으로 이동
    exit
    
    ```
    
    ```jsx
    kubectl uncordon <node-to-drain>
    
    ```
    
    ```jsx
    # 버전 확인
    kubectl get nodes
    -> 업그레이드 한 Node 버전 확인
    
    ```

# [23] Kubernetes Troubleshooting (1)

## ❓Not Ready 상태의 노드 활성화

- A Kubernetes worker node, named hk8s-w2 is in state NotReady.
- Investigate why this is the case, and perform any appropriate steps to bring the node to a `Ready` state, ensuring that any changes are made permanent.

## 확인해야 할 것

- docker가 실행중인지?
- kubelet이 실행중인지?
- kube-proxy가 실행중인지?
- CNI가 실행중인지? (컨테이너와 컨테이너 사이에 통신이 가능한지)

—&gt; 이 모든 것이 실행중이여야 컨테이너가 Ready상태가 된다.

### 실습

```docker
[user@console ~]$ kubectl get nodes
hk8s-w2가 Not Ready상태임

[user@console ~]$ ssh hk8s-w2

[user@hk8s-w2 ~]$ sudo -i

# docker가 running중인지 확인
[root@hk8s-w2 ~]# systemctl status docker
active상태임

# kubelet이 running중인지 확인
[root@hk8s-w2 ~]# systemctl status kubelet
inactive상태 뿐만 아니라 disable 상태

# kubelet 실행 (--now 옵션은 지금 당장 시작하고 다음 시작때에도 시작)
[root@hk8s-w2 ~]# systemctl enable --now kubelet

[root@hk8s-w2 ~]# systemctl status kubelet
active 상태 확인

# kube-proxy가 running중인지 확인
[root@hk8s-w2 ~]# exit

[user@hk8s-w2 ~]$ exit

# kube-proxy와 CNI는 console에서 확인
[user@console ~]$ kubectl get pods -n kube-system -o wide
calico라고 나와있는 것이 CNI이다.
kube-proxy도 running중
CNI 종류로는 calico, flannel 등이 있다.

```

## 기출문제 (5번)

Given a partially-functioning Kubernetes cluster, identify symptoms of failure on the cluster. Determine the node, the failing service, and take actions to bring up the failed service and restore the health of the cluster. Ensure that any changes are made permanently.

- 답안
    
    ```jsx
    # 확인해야 할 것 4개
    # 1. docker가 실행중인지
    --> ssh로 노드 접속한 다음 systemctl status docker로 확인
    --> active상태가 아니면 systemctl start docker, systemctl enable docker
    
    # 2. kubelet이 실행중인지
    --> ssh로 노드 접속한 다음 systemctl status kubelet
    --> active상태가 아니라면 systemctl start kubelet, systemctl enable kubelet
    
    # 3. kube-proxy가 실행중인지
    # 4. CNI가 실행중인지
    --> console에서 실행
    --> kubectl get pods -n kube-system -o wide
    
    ```

## 기출문제 (32번)

A Kubernetes worker node, named wk8s-node-0 is in state NotReady. Investigate why this is the case, and perform any appropriate steps to bring the node to a Ready state, ensuring that any changes are made permanent.

- 답안
    
    ```jsx
    # 확인해야 할 것 4개
    # 1. docker가 실행중인지
    --> ssh로 노드 접속한 다음 systemctl status docker로 확인
    --> active상태가 아니면 systemctl start docker, systemctl enable docker
    
    # 2. kubelet이 실행중인지
    --> ssh로 노드 접속한 다음 systemctl status kubelet
    --> active상태가 아니라면 systemctl start kubelet, systemctl enable kubelet
    
    # 3. kube-proxy가 실행중인지
    # 4. CNI가 실행중인지
    --> console에서 실행
    --> kubectl get pods -n kube-system -o wide
    
    ```

# [24] Kubernetes Troubleshooting (2)

## ❓Not Ready 상태의 노드 활성화

- A Kubernetes worker node, named hk8s-w2 is in state NotReady.
- Investigate why this is the case, and perform any appropriate steps to bring the node to a `Ready` state, ensuring that any changes are made permanent.

### 실습

```docker
[user@console ~]$ kubectl config use-context hk8s

[user@console ~]$ kubectl get nodes
hk8s-w2가 Not Ready상태임

[user@console ~]$ ssh hk8s-w2

[user@hk8s-w2 ~]$ sudo -i

# docker가 running중인지 확인
[root@hk8s-w2 ~]# systemctl status docker
inactive상태뿐만 아니라 disable 상태

[root@hk8s-w2 ~]# systemctl enable --now docker

[root@hk8s-w2 ~]# systemctl status docker
active상태, enable 상태

```

# [25] User Role Binding

## ❓Configuring User API Authentication

- TASK: 
    - Create the kubeconfig named `ckauser`
        - username: `ckauser`
        - `ckauser` cluster must be operated with the privileges of the `ckauser` account
        - certificate location: /data/cka/ckauser.crt, /data/cka/ckauser.key
        - context-name: `ckauser`
    - Create a role named `pod-role` that can `create, delete, watch, list, get` pods.
    - Create the following rolebinding: 
        - name: `pod-rolebinding`
        - role: `pod-role`
        - user: `ckauser`
- 작업 클러스터: k8s

### Reference

[Certificate Signing Requests](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/)

[Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)

### 실습

```docker
[user@console ~]$ ssh k8s-master

# pod-role이라는 이름의 role 생성
[user@k8s-master ~]$ kubectl create role pod-role --verb=create,delete,watch,list,get --resource=pods
[user@k8s-master ~]$ kubectl get role pod-role
[user@k8s-master ~]$ kubectl describe role pod-role

# role-binding 생성
[user@k8s-master ~]$ kubectl create rolebinding pod-rolebinding --role=pod-role --user=ckauser
[user@k8s-master ~]$ kubectl get rolebinding pod-rolebinding
[user@k8s-master ~]$ kubectl describe rolebinding pod-rolebinding

# context안에 user를 넣어줘야함
[user@k8s-master ~]$ kubectl config set-credentials ckauser --client-key=/data/cka/ckauser.key --client-certificate=/data/cka/ckauser.crt --embed-certs=true

# ckauser가 인증서 기반으로 생성된것 확인 가능
[user@k8s-master ~]$ kubectl config view
[user@k8s-master ~]$ kubectl config set-context ckauser --cluster=kubernetes --user=ckauser

# 테스트 해보기
[user@k8s-master ~]$ kubectl config use-context ckauser
[user@k8s-master ~]$ kubectl get pods

[user@k8s-master ~]$ kubectl get service
--> service에 대한 권한이 없기 때문에 불가능

# 원래 클러스터로 복귀
[user@k8s-master ~]$ kubectl config use-context kubernetes-admin@kubernetes

```

# [26] User Cluster Role Binding

## ❓Configuring User API Authentication

- Create a new ClusterRole named `app-clusterrole`, which only allows to get, watch, list the following resource types: Deployment, Service
- Bind the new ClusterRole `app-clusterrole` to the new user `ckcuser`
- User ckauser and ckauser clusters are ready configured.
- To check the results, run the following command: 
    - kubectl config use-context ckauser
- 작업 클러스터: k8s

## Role vs Cluster Role

일반적인 role은 namespace단위로 적용되는 거지만 cluster role은 namespace상관없이 특정 cluster 단위로 적용 된다. (role &lt; cluster role)

## Reference

docs에서 cluster role 검색 → 페이지에서 오른쪽에 Command-line utilities에서 kubectl create clusterrole

[Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#kubectl-create-clusterrole)

### 실습

```docker
# Cluster Role 생성
[user@k8s-master ~]$ kubectl create clusterrole app-clusterrole --verb=get,list,watch --resource=deployment,service
[user@k8s-master ~]$ kubectl get clusterrole app-clusterrole
[user@k8s-master ~]$ kubectl describe clusterrole app-clusterrole

# Cluster RoleBinding 설정
[user@k8s-master ~]$ kubectl create clusterrolebinding app-clusterrolebinding --clusterrole=app-clusterrole --user=ckauser
[user@k8s-master ~]$ kubectl get clusterrolebinding app-clusterrolebinding
[user@k8s-master ~]$ kubectl describe clusterrolebinding app-clusterrolebinding

# 확인해보기
[user@k8s-master ~]$ kubectl config use-context ckauser

[user@k8s-master ~]$ kubectl get deployment
--> 권한 있음

[user@k8s-master ~]$ kubectl get services
--> 권한 있음

[user@k8s-master ~]$ kubectl get secret
--> 권한 없음

```

## 기출문제 (37번)

Context You have been asked to create a new ClusterRole for a deployment pipeline and bind it to a specific ServiceAccount scoped to a specific namespace. Task Create a new ClusterRole named deployment-clusterrole, which only allows to create the following resource types:

- Deployment
- StatefulSet
- DaemonSet Create a new ServiceAccount named cicd-token in the existing namespace app-team1. Bind the new ClusterRole deployment-clusterrole lo the new ServiceAccount cicd-token , limited to the namespace app-team1.
- 답안
    
    ```jsx
    kubectl create clusterrole deployment-clusterrole --resource=deployment,statefulset,daemonset --verb=create
    
    ```
    
    ```jsx
    kubectl create serviceaccount cicd-token -n app-team1
    
    ```
    
    ```jsx
    kubectl create rolebinding deployment-rolebinding --clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token -n app-team1
    
    ```

# [27] ServiceAccount Role Binding

## ❓Service Account, Role and Role Binding

- Create the ServiceAccount named `pod-access` in a new namespace called `apps`
- Create a Role with the name `pod-role` and the RoleBinding named `pod-rolebinding`
- Map the ServiceAccount from the previous step to the API resources `Pods` with the operations `watch, list, get`
- 작업 클러스터: k8s

### Reference

[Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#kubectl-create-role)

[Kubectl Reference Docs](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands)

### 실습

```docker
# apps 이라는 namespace가 있는지 확인
[user@console ~]$ kubectl get namespace apps

# 없으면 namespace 생성
[user@console ~]$ kubectl create namespace apps

# service account 생성 및 확인
[user@console ~]$ kubectl create serviceaccount pod-access -n apps
[user@console ~]$ kubectl get serviceaccount -n apps

# apps namespace에 role 생성 및 확인
[user@console ~]$ kubectl create role pod-role --verb=watch,list,get --resource=pods -n apps
[user@console ~]$ kubectl get role -n apps
[user@console ~]$ kubectl describe role -n apps pod-role

# role binding 생성 및 확인
[user@console ~]$ kubectl create rolebinding pod-rolebinding --role=pod-role --serviceaccount=apps:pod-access --namespace=apps
[user@console ~]$ kubectl get rolebinding -n apps
[user@console ~]$ kubectl describe rolebinding -n apps pod-rolebinding

```

# [28] ServiceAccount Cluster Role Binding

## ❓ClusterRole &amp; ClusterRoleBinding 구성

- Create a new ClusterRole named `deployment-clusterrole`, which only allows to create the following resource types: Deployment, StatefulSet, DaemonSet
- Create a new ServiceAccount named `cicd-token` in the existing namespace `apps`
- Bind the new ClusterRole `deployment-clusterrole` to the new ServiceAccount `cicd-token`, limited to the namespace `apps`

### 실습

```docker
# service account 생성 및 확인
[user@console ~]$ kubectl create serviceaccount cicd-token -n apps
[user@console ~]$ kubectl get sa -n apps

# cluster role 생성
[user@console ~]$ kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployment,statefulset,daemonset

# role binding 생성
[user@console ~]$ kubectl create clusterrolebinding deploy-clusterrolebinding --clusterrole=deployment-clusterrole --serviceaccount=apps:cicd-token

# 확인
[user@console ~]$ kubectl get rolebinding deploy-clusterrolebinding
[user@console ~]$ kubectl describe rolebinding deploy-clusterrolebinding 

```

## 기출문제

Cluster : k8s Context You have been asked to create a new ClusterRole for a deployment pipeline and bind it to a specific ServiceAccount scoped to a specific namespace. Task:

- Create a new ClusterRole named deployment-clusterrole , which only allows to create the following resource types: Deployment StatefulSet DaemonSet
- Create a new ServiceAccount named cicd-token in the existing namespace app-team1 .
- Bind the new ClusterRole deployment-clusterrole to the new ServiceAccount cicd-token , limited to the namespace app-team1
- 답안
    
    ```jsx
    kubectl create clusterrole deployment-clusterrole --resource=deployment,statefulset,daemonset --verb=create
    
    ```
    
    ```jsx
    kubectl create serviceaccount cicd-token -n app-team1
    
    ```
    
    ```jsx
    kubectl create clusterrolebinding deployment-clusterrolebinding --clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token
    
    ```

# [29] Kube-DNS

# Kube-DNS란?

Kube-DNS는 도메인 이름을 IP 주소로 해석하는 역할을 한다. 이를 통해 K8s 클러스터 내부의 다른 리소스(서비스, Pod 등)를 도메인 이름을 통해 찾을 수 있다. Kube-DNS는 각 노드에 배포되며, 클러스터 내의 모든 Pod에서 사용할 수 있는 DNS 서버 역할을 수행 한.

## 나오는 문제 유형

- CoreDNS의 동작원리를 알고 있는가?
- 컨테이너 내부에 접속해서 서비스 또는 pod에 대한 DNS 질의를 해봐라

## ❓Service and DNS Lookup 구성

- Create a `nginx` pod called `nginx-resolver` using image `nginx`, expose it internally with a service called `nginx-resolver-service`.
- Test that you are able to look up the service and pod names from within the cluster.
- Use the image: `busybox:1.28` for dns lookup. 
    - Record results in /tmp/nginx.svc and /tmp/nginx.pod
    - Pod: **nginx-resolver** created
    - **Service DNS Resolution** recorded correctly
    - **Pod DNS resolution** recorded correctly

### Reference

docs에서 DNS 검색

[DNS for Services and Pods](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/)

### DNS 질의하는 법

1. Service에 대해 질의하는 법

nslookup `{service 이름}`. `{service namespace}`.svc.cluster.local

nslookup `{Cluster IP}`

2. Pod에 대해 질의하는 법

`{Pod IP}`. `{Pod namespace}`.pod.cluster.local

### 실습

```jsx
kubectl run nginx-resolver --image=nginx 

kubectl expose pod nginx --name=nginx-resolver-service --port=80 --target-port=80

# 확인
kubectl get pod nginx-resolver -o wide
--> IP정보 확인하기

kubectl get service nginx-resolver-service

kubectl run test --image=busybox:1.28 --rm -it --restart=Never -- /bin/sh 

cat /etc/resolv.conf
--> DNS 서버 IP 확인

nslookup nginx-resolver-service.default.svc.cluster.local
nslookup {Cluster IP}
--> 두 개의 결과가 같은지 확인

nslookup {Pod IP}.default.pod.cluster.local
--> DNS 서버 IP맞는지 확인

exit

vi /tmp/nginx.svc
--> service lookup 결과 안에 결과 넣어주기

vi /tmp/nginx.pod
--> pod lookup 결과 안에 결과 넣어주기

```

## 기출문제 (31번)

Create a deployment as follows: Name: nginx-random Exposed via a service nginx-random Ensure that the service &amp; pod are accessible via their respective DNS records.

The container(s) within any pod(s) running as a part of this deployment should use the nginx Image.

Next, use the utility nslookup to look up the DNS records of the service &amp; pod and write the output to /opt/KUNW00601/service.dns and /opt/KUNW00601/pod.dns respectively.

- 답안
    
    ```jsx
    kubectl create deploy nginx-random --image=nginx
    
    ```
    
    ```jsx
    kubectl expose deploy nginx-random --name=nginx-random --port=80 --target-port=80
    
    ```
    
    ```jsx
    kubectl run test --image=busybox:1.28 --rm -it --restart=Never -- /bin/sh
    
    ```
    
    ```jsx
    cat /etc/resolv.conf
    
    nslookup nginx-random.default.svc.cluster.local
    --> 결과 복사
    
    nslookup 10.244.1.24.default.pod.cluster.local
    --> 결과 복사
    
    # pod에서 나오기
    exit
    
    ```
    
    각각 결과 복사한거 파일에 넣기

# [30] Network Policy

쉽게 말하면 Pod에 대한 방화벽을 설정해주는 것이다.

## ❓Network Policy with Namespaces

- Create a new Network Policy named allowed-port-from-namespace in the existing namespace devops.
- Ensure that the new Network Policy allows pods in namespace migops to connect to port 80 of pods in namespace devops

### 실습

```docker
# docs에서 NetworkPolicy검색하고 The NetworkPolicy resource 부분  
vi allow-port-from-namespace.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allowed-port-from-namespace
  namespace: devops
spec:
  podSelector:
    matchLabels:
      app: web
# namespace devops에 있던 pod가 가지는 라벨
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              team: migops
# migops라는 namespace가 가지는 라벨
      ports:
        - protocol: TCP
          port: 80

:wq

kubectl apply -f allow-port-from-namespace.yaml
kubectl get networkpolicies -n devops allow-port-from-namespace

```

## 기출문제 (46번)

Task Create a new NetworkPolicy named allow-port-from-namespace in the existing namespace echo. Ensure that the new NetworkPolicy allows Pods in namespace my-app to connect to port 9000 of Pods in namespace echo. Further ensure that the new NetworkPolicy:

- does not allow access to Pods, which don't listen on port 9000
- does not allow access from Pods, which are not in namespace my-app
- 답안  
    //답안을 찾아야된다.