1. Take a backup of the etcd cluster and save it to /opt/etcd-backup.db
etcd 클러스터를 backup 후 /opt/etcd-backup.db 해당 경로의 해당 파일명으로 저장
Docs keyword : etcd backup
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#backing-up-an-etcd-cluster
# help
ETCDCTL_API=3 etcdctl -h
# spanshot 생성 예시(옵션 사용)
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>
# endpoint 확인
cat /etc/kubernetes/manifests/etcd.yaml | grep listen
# 인증서 확인
cat /etc/kubernetes/manifests/etcd.yaml | grep file
# spanshot 스크립트 완성
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 /opt/etcd-backup.db
2. Create a Pod called redis-storage with image: redis:alpine with a Volume of type emptyDir that lasts for the life of the Pod
redis-storage 라는 이름의 파드 생성 redis:alpine 이라는 이미지 ,emptyDir 볼륨 사용
- Pod named 'redis-storage' created
- Pod 'redis-storage' uses Volume type of emptyDir
- Pod 'redis-storage' uses volumeMount with mountPath = /data/redis
Docs keyword : emptyDir
https://kubernetes.io/docs/concepts/storage/volumes/#emptydir
# redis-storage.yaml 생성(--dry-run=client 을 통해 화면 출력, 해당 내용 yaml 파일 생성)
k run redis-storage --image=redis:alpine --dry-run=client -o yaml > redis-storage.yaml
# redis-storage.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: redis-storage
name: redis-storage
spec:
containers:
- image: redis:alpine
name: redis-storage
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# emptyDir 설정 샘플
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
# redis-storage.yaml - 실제 사용할 pod 에 emptyDir 관련 설정 추가 및 mountPath 변경(/data/redis)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: redis-storage
name: redis-storage
spec:
containers:
- image: redis:alpine
name: redis-storage
volumeMounts:
- mountPath: /data/redis
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 500Mi
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# yaml 로 자원 생성
k create -f redis-storage.yaml
3. Create a new pod called super-user-pod with image busybox:1.28. Allow the pod to be able to set system_time
The container should sleep for 4800 seconds.
busybox:1.28 이미지를 사용해서 super-user-pod 라는 pod 를 생성하고 pod 가 system_time 을 설정할 수 있도록 허용
컨테이너 sleep 설정 4800 초
- Pod: super-user-pod
- Container Image: busybox:1.28
- Is SYS_TIME capability set for the container?
Docs keyword : Set capabilities for a Container
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container
# super-user-pod.yaml 생성
k run super-user-pod --image=busybox:1.28 --dry-run=client -o yaml > super-user-pod.yaml
# securityContext 설정 샘플
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
# super-user-pod.yaml securityContext 적용
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: super-user-pod
name: super-user-pod
spec:
containers:
- image: busybox:1.28
securityContext:
capabilities:
add: ["SYS_TIME"]
name: super-user-pod
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# super-user-pod.yaml sleep 적용
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: super-user-pod
name: super-user-pod
spec:
containers:
- image: busybox:1.28
securityContext:
capabilities:
add: ["SYS_TIME"]
command: ["sleep","4800"]
name: super-user-pod
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# yaml 실행 (설정된 값으로 Pod 생성)
k create -f super-user-pod.yaml
4. A pod definition file is created at /root/CKA/use-pv.yaml. Make use of this manifest file and mount the persistent volume called pv-1. Ensure the pod is running and the PV is bound.
/root/CKA/use-pv.yaml 해당 파일을 사용해서 pod 를 생성하고 pv-1 이라는 pvc 를 연결 후 확인
mountPath: /data
persistentVolumeClaim Name: my-pvc
- persistentVolume Claim configured correctly
- pod using the correct mountPath
- pod using the persistent volume claim?
Docs keyword : pv, pvc
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims
# pv 확인 시 pv-1 존재 확인 가능
k get pv
# pv-1 상세 정보
Name: pv-1
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass:
Status: Available
Claim:
Reclaim Policy: Retain
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 10Mi
Node Affinity: <none>
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /opt/data
HostPathType:
Events: <none>
# pvc 설정 샘플
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
# pvc.yaml 생성 (storage 값을 pv 와 동일하게 설정)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 10Mi
# pvc 생성
k create -f pvc.yaml
# pvc 생성 확인
k get pvc
# use-pv.yaml 문제에서 제공되는 샘플 yaml (pvc 연결 필요)
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: use-pv
name: use-pv
spec:
containers:
- image: nginx
name: use-pv
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# docs pv -> Claims As Volumes 샘플 코드
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
# use-pv.yaml pvc 연결
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: use-pv
name: use-pv
spec:
containers:
- image: nginx
name: use-pv
volumeMounts:
- mountPath: "/data" # moutPath 지정
name: mypd
volumes:
- name: mypd
persistentVolumeClaim: # pvc 추가
claimName: my-pvc # 생성한 pvc 설정
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# pod 생성
k create -f use-pv.yaml
# pod 확인
k get pods
# pod 상세 확인
k describe pod use-pv
5. Create a new deployment called nginx-deploy, with image nginx:1.16 and 1 replica. Next upgrade the deployment to version 1.17 using rolling update.
nginx:1.16 이미지 사용 deployment 를 replica 1개로 지정 후 생성 rolling update 사용 deployment 버전 1.17 로 변경
- Deployment : nginx-deploy. Image: nginx:1.16
- Image: nginx:1.16
- Task: Upgrade the version of the deployment to 1:17
- Task: Record the changes for the image upgrade
Docs keyword : deploy upgrade
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment
# deployment 생성
k create deployment nginx-deploy --image=nginx:1.16 --replicas=1
# update > Updating a Deployment 참고
kubectl set image deployment/nginx-deploy nginx=nginx:1.17
# 버전 변경 확인
k describe deploy nginx-deploy | grep -i image
6. Create a new user called john. Grant him access to the cluster. John should have permission to create, list, get, update and delete pods in the development namespace . The private key exists in the location: /root/CKA/john.key and csr at /root/CKA/john.csr
유저 john 생성, 생성한 유저는 클러스터에 접근이 가능해야함, development namespace 에서 create, list, get, update, delete pod 를 할 수 있는 권한이 있어야한다
Important Note: As of kubernetes 1.19, the CertificateSigningRequest object expects a signerName.
Please refer the documentation to see an example. The documentation tab is available at the top right of terminal.
- CSR: john-developer Status:Approved
- Role Name: developer, namespace: development, Resource: Pods
- Access: User 'john' has appropriate permissions
Docs keyword : Create a CertificateSigningRequest
https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#certificate-signing-requests
1. CSR (CertificateSigningRequest) 생성
# 1.csr 생성시 spec.request 에 들어갈 값 조회
cat john.csr | base64 | tr -d "\n"
# 1-1. cat에 대한 결과 (spec.request 에 들어감)
# LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZEQ0NBVHdDQVFBd0R6RU5NQXNHQTFVRUF3d0VhbTlvYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRApnZ0VQQURDQ0FRb0NnZ0VCQUpzb21RdHI4eERsUVZNaHFWbkxFVTZrdU5CQ1VKYk42V3ZoODhRVjZrSTI1SlFzCmNPT0VCcEZiYVV5OFJUb3dhY1A1cmJPUUpHZmV1RHQ3M0laUFdTOTJlYUhkQkEyTWI0YjVpL2tWKy8vbzRlczMKOW1pM2s5Q3I1NG1NYWF6OUN5NGo4d2NDVW5yZHF3MkVheU9zb2N1R1hqM0lXUDhtTjBLWnhyN09qTi81YkY4dwp4RkxXcTlDK3crRkRoZzM2bis3WWFVWFdUZ0VkcFpsWStkcmRrZVBUNXQrUmNFZDNBNmc0TWp1ZVhOMjZJVVl3CkdxTU9oRUM1NUxGVmpkYTZ6MlY0QkM0aFJ4NnN4d1h0K25kRlpGNjNCbnRFaFVGSmZwN1lYd1Z6cWxtc3FUU1cKVHlzNVc2amozSDFjNEJyMDNqTWorMnBidDNYS1VzLzg0Um1IaFNzQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQgpDd1VBQTRJQkFRQkowQzE4cFNBODNiamtwZEM4dEtyTTlLWTRsRWErTTN1THNGeTZVbkQxTGNzOXM2ckJxMXZDCkJ5QmZxczhRb3hYVUZqQjcxdVBPY1E1K21Xcjk0R2RkWUtlT3pqdUxrLy9jWGlYUVBFa2U3T3g1c3lkdlYvaGoKcmg0RnVRaUU2NXI5czM1enZySW1xb2lSUjkxMDlDYXRkV3ZiUnRYbUc1aEVGYkwyVyticHJOMzVkUWFjd3VYMQpIWlBvMkQyOThkYmYwODFQNE9xVGROZFB2UGtaWXRxdWtrcmlFb0lub0pBRWpvOWRRaStaK1Zja3ZmbnVOdDFYCnNNdm0vL3FmMEt3cWhHejhueHJ4Q3EwSmVKMThDZnVnVVovTXlwWnVmdEhnVldYckxHaFV6YVdKTFNHbHduMWwKUFF5ZllHeXZkZFpyTHg1dVZvUjZ4czlYeG51dFBJZEEKLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
# Create a CertificateSigningRequest yaml 생성 샘플
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: myuser
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400 # one day
usages:
- client auth
# 1-2. john-csr.yaml 생성 (CertificateSigningRequest 생성 샘플에서 필요한 부분만 변경)
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: john-developer
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZEQ0NBVHdDQVFBd0R6RU5NQXNHQTFVRUF3d0VhbTlvYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRApnZ0VQQURDQ0FRb0NnZ0VCQUpzb21RdHI4eERsUVZNaHFWbkxFVTZrdU5CQ1VKYk42V3ZoODhRVjZrSTI1SlFzCmNPT0VCcEZiYVV5OFJUb3dhY1A1cmJPUUpHZmV1RHQ3M0laUFdTOTJlYUhkQkEyTWI0YjVpL2tWKy8vbzRlczMKOW1pM2s5Q3I1NG1NYWF6OUN5NGo4d2NDVW5yZHF3MkVheU9zb2N1R1hqM0lXUDhtTjBLWnhyN09qTi81YkY4dwp4RkxXcTlDK3crRkRoZzM2bis3WWFVWFdUZ0VkcFpsWStkcmRrZVBUNXQrUmNFZDNBNmc0TWp1ZVhOMjZJVVl3CkdxTU9oRUM1NUxGVmpkYTZ6MlY0QkM0aFJ4NnN4d1h0K25kRlpGNjNCbnRFaFVGSmZwN1lYd1Z6cWxtc3FUU1cKVHlzNVc2amozSDFjNEJyMDNqTWorMnBidDNYS1VzLzg0Um1IaFNzQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQgpDd1VBQTRJQkFRQkowQzE4cFNBODNiamtwZEM4dEtyTTlLWTRsRWErTTN1THNGeTZVbkQxTGNzOXM2ckJxMXZDCkJ5QmZxczhRb3hYVUZqQjcxdVBPY1E1K21Xcjk0R2RkWUtlT3pqdUxrLy9jWGlYUVBFa2U3T3g1c3lkdlYvaGoKcmg0RnVRaUU2NXI5czM1enZySW1xb2lSUjkxMDlDYXRkV3ZiUnRYbUc1aEVGYkwyVyticHJOMzVkUWFjd3VYMQpIWlBvMkQyOThkYmYwODFQNE9xVGROZFB2UGtaWXRxdWtrcmlFb0lub0pBRWpvOWRRaStaK1Zja3ZmbnVOdDFYCnNNdm0vL3FmMEt3cWhHejhueHJ4Q3EwSmVKMThDZnVnVVovTXlwWnVmdEhnVldYckxHaFV6YVdKTFNHbHduMWwKUFF5ZllHeXZkZFpyTHg1dVZvUjZ4czlYeG51dFBJZEEKLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400 # one day
usages:
- client auth
# 1-3. yaml 실행 (설정한 값으로 csr 생성)
k create -f john-csr.yaml
# 1-4. csr 생성 확인 시 CONDITION 이 pending 으로 확인됨 (승인 필요)
k get csr
# 1-5. pending 확인을 위해 승인
k certificate approve john-developer
# 1-6. csr 재 확인 CONDITION 이 Approve 로 변경된걸 확인 가능
k get csr
2. Role 생성 및 RoleBinding
# 1. role 생성 (create, get, list, update, delete 에 대한 권한 부여 및 네임스페이스=development 지정)
# k create role --help 참고
k create role developer --verb=create,get,list,update,delete --resource=pods -n development
# 2. role 생성 확인
k describe role -n development developer
# 3. Access 권한 확인 (현재는 rolebinding 을 하지 않았기 때문에 두 명령어 모두 no 출력)
# k auth can-i get --help
k auth can-i create pods -n development --as john
k auth can-i get pods -n development --as john
# 4. rolebinding 생성
# k create rolebinding --help
kubectl create rolebinding john-developer --role=developer --user=john -n development
# 5. rolebinding 생성 확인 (john 과 role 이 묶인걸 확인 가능)
k describe rolebinding -n development
# 6. Access 권한 확인 (이제 yes 로 나오면 끝)
k auth can-i create pods -n development --as john
k auth can-i get pods -n development --as john
7. 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 /root/CKA/nginx.svc and /root/CKA/nginx.pod
nginx 라는 이미지를 사용해서 nginx-resolver pod 를 생성하고, nginx-resolver-service 를 통해서 내부적으로 노출 후 클러스터 내부에서 테스트
테스트시 busybox:1.28 이미지를 사용하고 해당 경로에 결과를 기록 /root/CKA/nginx.svc, /root/CKA/nginx.pod
- Pod: nginx-resolver created
- Service DNS Resolution recorded correctly
- Pod DNS resolution recorded correctly
Docs keyword : DNS
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
# 1. pod 생성
k run nginx-resolver --image=nginx
# 1-1. pod 확인
k get pods
# 2. expose 서비스 연결
k expose pod nginx-resolver --name nginx-resolver-service --port=80
# 2-1. 서비스 확인
k get svc
# 3. 통신 확인을 위한 pod 생성
k run busybox --image=busybox:1.28 -- sleep 3600
# 4. svc nslookup 결과 저장
k exec busybox -- nslookup nginx-resolver-service > /root/CKA/nginx.svc
# 4-1. nginx-resolver pod nslookup 을 위한 ip 체크
k get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 4m13s 10.244.192.2 node01 <none> <none>
nginx-resolver 1/1 Running 0 33m 10.244.192.1 node01 <none> <none>
# 4-2. pod nslookup 결과 저장 (nslookup 이후 문법 Pods - A/AAAA records 참고)
k exec busybox -- nslookup 10-244-192-1.default.pod.cluster.local > /root/CKA/nginx.pod
# 5. 결과 확인
cat /root/CKA/nginx.svc
cat /root/CKA/nginx.pod
8. Create a static pod on node01 called nginx-critical with image nginx and make sure that it is recreated/restarted automatically in case of a failure.
Use /etc/kubernetes/manifests as the Static Pod path for example.
node01 에서 nginx 이미지로 nginx-critical static pod 를 생성하고 오류가 발생하면 자동으로 재생성/실행 되는지 확인
- static pod configured under /etc/kubernetes/manifests ?
- Pod nginx-critical-node01 is up and running
Docs keyword : create static pod
https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/#static-pod-creation
# 1. restart 를 위한 pod yaml 생성 (controleplane 에서 생성 후 복사)
kubectl run nginx-critical --image=nginx --restart=Always --dry-run=client -o yaml
# 2. node01 이동
ssh node01
# 3. static pod 생성 경로 이동
cd /etc/kubernetes/manifests/
# 4. nginx-ciritical static pod 생성을 위해 yaml 작성
vi nginx-critical
# 4-1. dry-run 으로 생성한 yaml 내용 붙여넣고 저장
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx-critical
name: nginx-critical
spec:
containers:
- image: nginx
name: nginx-critical
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# 5. pod 생성 확인 (node01 에서 controleplan 으로 복귀 후 확인)
k get pods