CKA #4 Logging & Monitoring, #5 Application LifeCycle Management

· Infra, Kubernetes, CKA

Certified Kubernetes Administrator (CKA) with Practice Tests 강의를 듣고 몰랐던 내용, 알고 있어도 중요하다고 생각하는 내용 등을 추가적인 공부와 함께 간략히 정리한 글입니다.

Index

Introduction

이번 4장은 강의 자체도 짧아서 별 내용이 없고, 5장은 Configuration 관련 내용이 많이 나오는데, 어려운건 없지만 똑같은 동작이라도 여러 가지 방법으로 설정할 수 있기 때문에, 관련해서 yaml이나 명령을 작성하는 방법들을 위주로 필기해놓았다.

#4 Logging & Monitoring

Monitoring Cluster Components

Logging

docker logging

docker logs -f ecf 

k8s logging

kubectl logs -f <pod-name>

만약, 파드 안에 컨테이너가 여러개라면? 컨테이너 이름을 함께 명시해주어야 한다.

kubectl logs -f <pod-name> <container-name>

#5 Application LifeCycle Management

Rolling Updates and Rollback

Deployment rollout Status

Deployment StrategyType은 deployment 리소스를 describe해보면 알 수 있다.

kubectl rollout status deployment/myapp-deployment
kubectl rollout history deployment/myapp-deployment

Deployment를 imperative하게 하는 방법

현업에서 쓰면 귀싸대기 챱챱 맞을 것 같은 명령어… yaml 파일로 관리하는게 대부분의 상황에서 옳다고 생각한다.

kubectl set image deployment/myapp-deployment nginx-container=nginx:1.9.1
kubectl set image deployment/<deployment-name> <containers.name>=<image>

Deployment Rollback

kubectl rollout undo deployment/myapp-deployment

Configure Applications - Commands, Arguments, Environment Variables

Dockerfile에서의 ENTRYPOINT, CMD 처리

FROM Ubuntu
CMD sleep 5

도커 파일을 실행만 해도 CMD가 실행된다.

FROM Ubuntu
ENTRYPOINT ["sleep"]
docker run ubuntu-sleep 10

ENTRYPOINT의 sleep과 커맨드 10이 합쳐져 sleep 10의 효과가 된다.

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["5"]
docker run ubuntu-sleeper 10

커맨드에 10을 적어준다면 CMD가 override되고, 안적는다면 default 5로 실행된다.

ENTRYPOINT를 수정해주고 싶다면 --entrypoint 옵션으로 처리할 수 있다.

docker run --entrypoint sleep2.0 ubuntu-sleeper 10

Dockerfile과 yaml 대응

ENTRYPOINT, CMD와 command, args의 차이 이미지 출처: Certified Kubernetes Administrator (CKA) with Practice Tests(Udemy)

환경변수 설정

...
spec:
	containers:
	- name: simple-webapp-color
	  image: simple-webapp-color
	  ports:
	  - containerPort: 8080
	  env:
	  - name: APP_COLOR
		  value: pint # Plain Value Key
		- name: APP_COLOR
		  valueFrom:
			  configMapKeyRef: # ConfigMap
	  - name: APP_COLOR
	    valueFrom:
		    secretKeyRef: # Secrets

Configure Applications - ConfigMaps

APP_COLOR: blue
APP_MODE: prod
# Imperative
kubectl create configmap <config-name> --from-literal=<key>=<value>
kubectl create configmap app-config \
 --from-literal=APP_COLOR=blue \
 --from-literal=APP_MODE=prod
kubectl create configmap <config-name> --from-file=<path-to-file>
kubectl create configmap app-config --from-file=app_config.properties

ConfigMap yaml

apiVersion: v1
kind: ConfigMap
metadata:
	name: app-config
data:
	APP_COLOR: blue
	APP_MODE: prod

ConfigMap in Pods

# ENV
envFrom:
- configMapRef:
		name: app-config
		
# SINGLE ENV
env:
- name: APP_COLOR
  valueFrom:
	  configMapKeyRef:
			name: app-config
			key: APP_COLOR

# VOLUME
volumes:
- name: app-config-volume
  configMap:
	  name: app-config
spec:
  containers:
  - env:
    - name: APP_COLOR
      valueFrom:
        configMapKeyRef:
          name: webapp-config-map
          key: APP_COLOR

Configure Applications - Secrets

민감한 정보를 저장하는데, ConfigMap과는 다르게 인코딩되어 저장된다.

DB_Host: mysql
DB_User: root
DB_Password: passwrd`
kubectl create secret generic <secret-name> --from-literal=key=value
kubectl create secret generic app-secret --from-literal=DB_Host=mysql

kubectl create secret generic <secret-name> --from-file=<path-to-file>
kubectl create secret generic app-secret --from-file=app_secret.properties

Configure Applications - Encrypting Secret Data at Rest

https://happycloud-lee.tistory.com/243

강의 영상과 함께 위 링크를 참고하였습니다.

시크릿 암호화 작업 시작하기 - EncryptionConfiguration 파일 작성하기

시크릿도 etcd에 저장되는 리소스이다. 그런데 평문으로 저장된다… (base64로 인코딩되긴 하지만 base64는 암호화라고 할 수 없기 때문) 그래서 쿠버네티스는 etcd에 저장되는 시크릿을 암호화할 수 있는 방법을 제공한다.

---
# /etc/kubernetes/pki/secrets.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
      - configmaps
      - pandas.awesome.bears.example # a custom resource API
    providers:
      # This configuration does not provide data confidentiality. The first
      # configured provider is specifying the "identity" mechanism, which
      # stores resources as plain text.
      - identity: {} # plain text, in other words NO encryption
      - aesgcm:
          keys:
            - name: key1
              secret: c2VjcmV0IGlzIHNlY3VyZQ==
            - name: key2
              secret: dGhpcyBpcyBwYXNzd29yZA==
      - aescbc:
          keys:
            - name: key1
              secret: c2VjcmV0IGlzIHNlY3VyZQ==
            - name: key2
              secret: dGhpcyBpcyBwYXNzd29yZA==
      - secretbox:
          keys:
            - name: key1
              secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
  - resources:
      - events
    providers:
      - identity: {} # do not encrypt Events even though *.* is specified below
  - resources:
      - '*.apps' # wildcard match requires Kubernetes 1.27 or later
    providers:
      - aescbc:
          keys:
          - name: key2
            secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
  - resources:
      - '*.*' # wildcard match requires Kubernetes 1.27 or later
    providers:
      - aescbc:
          keys:
          - name: key3
            secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
- secretbox:
  keys:
  - name: key1
    secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=

이 부분이 포인트인데, secretbox를 가장 권장하고 있고, keys.name은 반드시 key1이여야 한다.

key1의 secret 값은 32byte 랜덤 암호다.

head -c 32 /dev/urandom | base64

API Server 설정 파일에 추가하기

spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=169.56.70.197
    - --encryption-provider-config=/etc/kubernetes/pki/secrets.yaml
    - --allow-privileged=true
    ...

MultiContainer Pods

로그 에이전트 같은 경우, 로깅 에이전트 코드 자체를 서버 코드 안에 합치는 것은 좋지 않다. 따라서 분리를 하되, 옆에 붙어서 동작할 수 있어야 하는데, 파드는 이러한 기능을 지원한다.

파드 내에서는 서로를 로컬호스트로 호출할 수 있다. 볼륨 쉐어도 필요하지 않다.

MultiContainer Pods Design Pattern

Init Containers