Rolling Updates and Rollbacks
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: nginx
spec:
template:
metadata:
name: myap-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx:1.7.1
replicas: 3
selector:
matchLabels:
type: front-endkubectl create -f deployment-definition.yml
kubectl get deployments
위와 같이 nginx:1.7.1 을 호스팅하는 Deployment Object 가 있다고 해보자.
kubectl apply -f deployment-definiton.yml
kubectl set image deployment/myapp-deployment nginx=nginx:1.9.1
만약 버전을 1.9.1 로 업그레이드하고 싶을 경우 yaml 파일을 수정한 뒤 apply 하거나 set 명령어를 통해 전체 Container 의 버전을 업그레이드 할 수 있다.
K8s 는 기본적으로 Container 를 하나씩 업그레이드하는 Rolling Update 를 배포전략으로 사용하고, 전체 Container 를 내리고 다시 띄우는 Recreate 전략도 사용할 수 있다.
kubectl get replicasets
K8s 에서 Container 버전을 업그레이드할 때 Deployment Object 내부적으로 새로운 ReplicaSet 을 생성하여 새로운 버전의 Container 들을 하나씩 배포하기 때문에 위 명령어를 쳐보면 2개의 ReplicaSet 이 존재하는 것을 확인할 수 있다.
kubectl rollout status deployment/myapp-deployment
kubectl rollout history deployment/myapp-deployment
kubectl rollout undo deployment/myapp-deployment
Configure Applications
Configuring Command and Arguments on applications
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper-pod
spec:
containers:
- name: ubuntu-sleeper
image: ubuntu-sleeper
command: ["sleep2.0"]
args: ["10"]Docker Container 를 실행할 때 Command 와 Argument 를 전달하듯이 위처럼 Pod definition file 에 Command 와 Argument 를 지정해줄 수 있다.
kubectl run webapp-green --image=kodekloud/webapp-color -- --color=green
명령어로 Argument 를 전달하고 싶은 경우 위와 같이 전달할 수 있다.
Configuring Environment Variables
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
env:
- name: APP_COLOR
value: pinkDocker 에서 docker run -e APP_COLOR=pink simple-webapp-color 으로 Container 에 환경변수를 전달하듯이 위처럼 Pod definition file 에 환경변수를 지정해줄 수 있다.
ConfigMap
관리해야 할 환경변수가 많이질 경우 ConfigMap 을 통해 환경변수를 관리할 수 있다.
kubectl create configmap \
app-config --from-literal=APP_COLOR=blue \
--from-literal=APP_MOD=prod
위 명령어를 통해 직접 ConfigMap 을 생성하거나,
kubectl create configmap \
app-config --from-file=app_config.properties
위 명령어를 통해 파일을 바탕으로 ConfigMap 을 생성할 수 있고,
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_COLOR: blue
APP_MODE: prod또는 yaml 파일 형태로 정의한 후 생성하여 사용할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-configConfigMap 을 생성한 뒤엔 envFrom 필드를 통해 Pod 에 환경변수를 주입해줄 수 있다.
env:
- name: APP_COLOR
valueFrom:
configMapKeyRef:
name: app-config
key: APP_COLOR
이외에도 ConfigMap 에서 하나의 환경변수만 주입하거나,
volumes:
- name: app-config-volume
configMap:
name: app-config
파일 형태로 주입 역시 가능하다.
Configuring Secrets
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
DB_Host: bX1zcWw=
DB_User: cm9vdA==
DB_Password: cGFzd3JkapiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secretSecret 을 다룰 땐 ConfigMap 과 비슷하게 Secret Object 를 사용하여 Pod 에 주입해줄 수 있다.
kubectl create secret generic app-secret \
--from-literal=DB_Host=mysql \
--from-literal=DB_User=root \
--from-literal=DB_Password=paswrd
마찬가지로 Imperative 하게 생성도 가능하다.
ConfigMap 과 Secret 을 볼륨으로 마운트하는 이유
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "prod"
APP_VER: "1.0"
---
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: app-container
image: busybox
command:
- sleep
- 3600
volumeMounts:
- name: config-volume
mountPath: "/etc/config"
volumes:
- name: config-volume
configMap:
name: app-config
ConfigMap 과 Secret 을 볼륨으로 마운트하면 해당 데이터가 Pod 의 특정 디렉터리에 파일 형태로 저장된다. 이는 k8s 내부적으로 tmpfs(메모리 기반 파일시스템)을 사용하여 데이터를 동적으로 마운팅하는 방식이다. 환경변수의 경우 프로세스 환경변수에 직접 사용된다. 파일로 환경변수를 관리하면 여러 이점이 존재한다.
보안 강화
kubectl exec -it pod-name -- env | grep SECRET_
환경변수를 사용할 경우 Pod 내부에서 값을 쉽게 확인할 수 있다.
cat /proc/$(pgrep -f app)/environ
또 프로세스 내부에 환경변수가 남아있어 쉽게 확인할 수 있다.
Secret 을 볼륨으로 마운트하면 단순 파일로 제공되기 때문에 접근 권한을 저정하여 보안을 강화할 수 있다.
실시간 변경 반영
k8s 는 synlink 방식을 사용하여 파일을 자동으로 교체하기 때문에 값이 변경되어도 컨테이너를 재시작하지 않고도 적용된다.
일관된 관리
여러 Pod 에서 동일한 ConfigMap 또는 Secret 을 공유할 수 있다. 애플리케이션을 중앙 집중식으로 관리할 수 있어 운영이 편리해진다.
용량 제한
환경변수 방식은 시스템에 따라 길이 제한이 있으나 볼륨은 제한이 없다. TLS 인증서, SSH 키 등 길이가 긴 값들을 환경변수로 사용할 수 없을 때 유용하다.
Multi-Container Pods
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
labels:
name: simple-webapp
spec:
containers:
- name: simple-webapp
image: simple-webapp
ports:
- ContainerPort: 8080
- name: log-agent
image: log-agentPod 는 보통 1개의 Container 를 포함하지만 여러개의 Container 를 포함할 수 있도록 설계되었다. 이는 Log Agent 와 같은 Helper Container 를 함께 생명주기에 포함하여 관리하기 위함이다. 위처럼 2개의 Container 를 포함하여 Pod 를 배포할 수 있다.
Multi-Container Pods Design Patterns
다수의 Container 를 포함한 Pod 를 배포할 때 따르는 디자인 패턴이다. 위 Log Agent 는 Sidecar Pattern 의 예시다.
- Sidecar Pattern
- Adapter Pattern
- Ambassador Pattern
InitContainers
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']Pod 를 배포할 때 일회성 작업이 필요한 경우 initContainers 를 통해 구성할 수 있다. Pod 의 메인 Container 는 initContainers 작업이 완료될 때 까지 기다리며, 실패할 경우 계속 Pod 를 새로 만든다.
Self-Healing Applications
K8s 는 ReplicaSet 과 Replicate Controller 를 통해 Pod 의 작동을 보장한다.
Horizontal Pod Autoscaler (HPA)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx
resources:
requests:
cpu: "250m"
limits:
cpu: "500m"트래픽이 많아져 CPU 사용량이 limit 에 가까워지기 전에 오토스케일링을 통해 부하를 분산할 수 있다.
kubectl autoscale deployment my-app --cpu-percent=50 --min=1 --max=10
kubectl get hpa
kubectl delete hpa my-app
위 명령어로 HPA 를 직접 생성할 수도 있고,
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50위와 같이 파일을 통해 생성할 수도 있다.
Vertical Pod Autoscaling (VPA)
kubectl apply -f https://github.com/kubernetes/autoscaler/releases/latest/download/vertical-pod-autoscaler.yaml
VPA 는 Pod 의 하드웨어 리소스를 오토스케일링하는 Object 로 K8s 에 기본적으로 제공되지 않기 때문에 직접 배포해야 한다.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "my-app"
minAllowed:
cpu: "250m"
maxAllowed:
cpu: "2"
controlledResources: ["cpu"]기본적으로 제공되지 않는 Object 이다보니 Imperative 하게 배포할 수 없기에 위와 같이 파일형식으로 생성해줘야한다.