컨테이너 이미지는 애플리케이션과 모든 소프트웨어 의존성을 캡슐화하는 바이너리 데이터를 나타낸다. 컨테이너 이미지는 독립적으로 실행할 수 있고 런타임 환경에 대해 잘 정의된 가정을 만드는 실행 가능한 소프트웨어 번들이다.
일반적으로 파드에서 참조하기 전에 애플리케이션의 컨테이너 이미지를 생성해서 레지스트리로 푸시한다.
도커 레지스트리
A Docker registry is a storage and distribution system for named Docker images. The same image might have multiple different versions, identified by their tags.
도커 퍼플릿 레지스트리
By default, the Docker engine interacts with DockerHub
디플로이먼트,스테이트풀셋, 파드 또는 파드 템플릿은 포함하는 다른 오브젝트를 처음 만들 때 특별히 명시하지 않은 경우 기본적으로 해당 파드에 있는 모든 컨테이너의 풀(pull) 정책은IfNotPresent로 설정된다.
이미지 Pull Policy
pull policy
설명
IfNotPresent
the image is pulled only if it is not already present locally.
Always
every time the kubelet launches a container, the kubelet queries the container image registry to resolve the name to an imagedigest. If the kubelet has a container image with that exact digest cached locally, the kubelet uses its cached image; otherwise, the kubelet pulls the image with the resolved digest, and uses that image to launch the container.
Never
the kubelet does not try fetching the image. If the image is somehow already present locally, the kubelet attempts to start the container; otherwise, startup fails.
만약 항상 이미지 풀을 강제하고 싶다면, 다음 중 하나를 수행하면 된다.
컨테이너의imagePullPolicy를Always로 설정.
imagePullPolicy를 생략하고:latest를 사용할 이미지의 태그로 사용, 쿠버네티스는 정책을Always로 설정한다.
컨테이너의 imagePullPolicy 값은 오브젝트가 처음 created 일 때 항상 설정되고 나중에 이미지 태그가 변경되더라도 업데이트되지 않는다. 예를 들어, 태그가 :latest가 아닌 이미지로 디플로이먼트를 생성하고, 나중에 해당 디플로이먼트의 이미지를 :latest 태그로 업데이트하면 imagePullPolicy 필드가 Always 로 변경되지 않는다. 오브젝트를 처음 생성 한 후 모든 오브젝트의 풀 정책을 수동으로 변경해야 한다.
Kubernetes 관리 서비스를 제공하는 대형 클라우드 업체 중 AWS EKS를 통한 k8s 클러스터 생성 과정을 살펴보자.
첫째, 클러스터 생성
AWS CLI 혹은 eksctl 등으로 EKS 클러스터를 할 수 있는데 eksctl를 이용한 방법을 살펴보자. 그 이유는 eksctl은 클러스터 구성에 필요한 설정을 일반적인 수준에서 알아서 관리해준다. 좀 더 자세한 클러스터 튜닝을 하고 싶다면 AWS CLI를 이용하여 클러스터를 생성하는 것을 추천한다.
Prerequisites
- kubectl : A command line tool for working with Kubernetes clusters.
- eksctl : A command line tool for working with EKS clusters that automates many individual tasks.
- coredns : 쿠버네티스 클러스터의 DNS 역할을 수행할 수 있는, 유연하고 확장 가능한 DNS 서버이다. 서비스디스커버리에 활용됨.
- kube-proxy : worker node 사이의 container들의 커뮤니케이션 수단 제공
- cni : Container Network Interface
- kubelet : master node와 컨테이너 상태 등에 대해서 커뮤니케이션 및 container를 제어하는 역할
셋째, kubectl을 이용하여 EKS 클러스터를 관리한다.
넷째, 원하는 워크로드를 생성한 EKS 클러스터에 배포한다.
자동으로 생성된 VPC 네트워크 구성에 대해서 살펴보도록 하자.
VPC(Amazon Virtual Private Cloud)
1. 인터넷게이트웨이(IGW)
- 응답을 받을때 private ip로 주소변환(NAT)
- enables inbound and outbound access to the internet
- 기타
2. 보안그룹
- SSH 접근 보안 설정
- control plane과 워커 노드그룹 사이 보안 설정
- 클러스터 노드 사이 보안 설정
- CNI 보안 설정
- 기타
3. Subnet
Private subnet
기본적으로 외부와 차단되어 있고, 다른 서브넷과의 연결만 가능
- 라우팅 테이블
- 네트워크 ACL
- Amazon EC2
Public subnet
- NAT 게이트웨이 : 인터넷에서 들어오는 트래픽을 차단. private subnet의 인터넷 요청에 대한 결과를 전달.
NAT(Network Address Translation) : IP 패킷 헤더의 IP 주소를 변경하는 기능을 뜻함. DNAT, SNAT
- 라우팅 테이블
- 네트워크 ACL
- Amazon EC2
4. 로드밸런서
5. 기타
이렇게 eksctl를 이용하여 AWS EKS 클러스터 생성과정을 살펴보았다.
이외에 Calico를 이용하여 Networkpolicy를 적용하는 등의 설정을 통해 클러스터 보안을 향상시킬 수 있다. 참고로 클러스터 밖에서 접속하는 트래픽에 대해서는 방화벽 설정을 할 수 없다. 그 이유는 외부에서 클러스터 내부로 들어오는 Source 주소가 변경되기 때문이다.
데이터 처리 전문가가 되고 싶은"어피치"는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자열에서 같은 값이 연속해서 나타나는 것을 그 문자의 개수와 반복되는 값으로 표현하여 더 짧은 문자열로 줄여서 표현하는 알고리즘을 공부하고 있습니다. 간단한 예로 "aabbaccc"의 경우 "2a2ba3c"(문자가 반복되지 않아 한번만 나타난 경우 1은 생략함)와 같이 표현할 수 있는데, 이러한 방식은 반복되는 문자가 적은 경우 압축률이 낮다는 단점이 있습니다. 예를 들면, "abcabcdede"와 같은 문자열은 전혀 압축되지 않습니다. "어피치"는 이러한 단점을 해결하기 위해 문자열을 1개 이상의 단위로 잘라서 압축하여 더 짧은 문자열로 표현할 수 있는지 방법을 찾아보려고 합니다.
예를 들어, "ababcdcdababcdcd"의 경우 문자를 1개 단위로 자르면 전혀 압축되지 않지만, 2개 단위로 잘라서 압축한다면 "2ab2cd2ab2cd"로 표현할 수 있습니다. 다른 방법으로 8개 단위로 잘라서 압축한다면 "2ababcdcd"로 표현할 수 있으며, 이때가 가장 짧게 압축하여 표현할 수 있는 방법입니다.
다른 예로, "abcabcdede"와 같은 경우, 문자를 2개 단위로 잘라서 압축하면 "abcabc2de"가 되지만, 3개 단위로 자른다면 "2abcdede"가 되어 3개 단위가 가장 짧은 압축 방법이 됩니다. 이때 3개 단위로 자르고 마지막에 남는 문자열은 그대로 붙여주면 됩니다.
압축할 문자열 s가 매개변수로 주어질 때, 위에 설명한 방법으로 1개 이상 단위로 문자열을 잘라 압축하여 표현한 문자열 중 가장 짧은 것의 길이를 return 하도록 solution 함수를 완성해주세요.
제한사항
s의 길이는 1 이상 1,000 이하입니다.
s는 알파벳 소문자로만 이루어져 있습니다.
입출력 예
s
result
"aabbaccc"
7
"ababcdcdababcdcd"
9
"abcabcdede"
8
"abcabcabcabcdededededede"
14
"xababcdcdababcdcd"
17
입출력 예에 대한 설명
입출력 예 #1
문자열을 1개 단위로 잘라 압축했을 때 가장 짧습니다.
입출력 예 #2
문자열을 8개 단위로 잘라 압축했을 때 가장 짧습니다.
입출력 예 #3
문자열을 3개 단위로 잘라 압축했을 때 가장 짧습니다.
입출력 예 #4
문자열을 2개 단위로 자르면 "abcabcabcabc6de" 가 됩니다. 문자열을 3개 단위로 자르면 "4abcdededededede" 가 됩니다. 문자열을 4개 단위로 자르면 "abcabcabcabc3dede" 가 됩니다. 문자열을 6개 단위로 자를 경우 "2abcabc2dedede"가 되며, 이때의 길이가 14로 가장 짧습니다.
입출력 예 #5
문자열은 제일 앞부터 정해진 길이만큼 잘라야 합니다. 따라서 주어진 문자열을 x / ababcdcd / ababcdcd 로 자르는 것은 불가능 합니다. 이 경우 어떻게 문자열을 잘라도 압축되지 않으므로 가장 짧은 길이는 17이 됩니다.
노드의 OS Upgrade를 위해서는 노드를 정지해야한다. 이때 도커 컨테이너의 라이브 마이그레이션에 해당하는 기능이 존재하지 않아 메인터넌스 등으로 노드를 정지하는 경우 파드를 정지해야 한다. 따라서 SIGTERM, SIGKILL 신호에 동작하는 애플리케이션을 만들고 terminationGracePeriodSeconds를 적절하게 설정해야한다.
즉, 각 파드에 정지 처리가 실행될 때 안전하게 정지하도록 preStop 설정 / gracefulPeriod 설정 / 애플리케이션 측에서 SIGTERM 신호 핸들링 등과 같은 적절한 준비를 해두어야 한다.
쿠버네티스 노드는 SchedulingEnabled(Default)와 SchedulingDisabled 중 하나의 상태를 가진다. 노드가 SchedulingDisabled 상태로 변경되도 이미 노드에서 실행되는 파드에는 영향을 주지 않는다.
노드의 OS Upgrade 절차는 아래와 같다.
참고) 테스트를 위해 kube-controller-manager의 --pod-eviction-timeout을 사용할 수 있다.
첫째, 파드축출(관련 포드들을 gracefully stop 시키고, 다른 노드에 띄운다.)
kube-apiserver, controller-manager, kube-scheduler, kubelet, kube-proxy, kubectl는 같은 버전의 패키지에 포함된다.
kubeadm으로 쿠버네티스 클러스터를 구성했다는 가정하에 master/controlplane components의 버전을 업그레이드 하는 과정을 살펴보겠다.
Automatic upgrade by providers(AWS EKS, ...)
# 어떤 버전으로 업그레이드 가능한지 볼수 있음
kubectl upgrade plan
# Upgrade
kubectl upgrade apply
Upgrade in a hard way(kubeadm)
Master 노드
첫째, master 노드의 파드를 축출한다.
kubectl drain master --ignore-daemonsets
둘째, kubeadm tool을 업그레이드 한다.
# Kubeadm installation
apt install kubeadm=1.xx.0-00 -y
# Check kubeadm version
kubeadm version
셋째, master components를 업그레이드 한다.
# Upgrade
kubeadm upgrade apply v1.xx.0
# Check if it is Upgraded
# not yet upgraded because kubelet is not upgraded
kubectl version --short
kubectl get nodes
넷째, kubelet을 업그레이드 한다.
# upgrade the kubelet on the master node
apt install kubelet=1.xx.0-00
# Recheck if it is Upgraded
kubectl get nodes
다섯째, master node를 스케줄링 대상으로 복귀시킨다.
# Mark the master/controlplane node as "Schedulable"
kubectl uncordon controlplane
Work 노드
첫째, work 노드의 파드를 축출한다.
# Drain the worker node of the workloads and mark it UnSchedulable
kubectl drain node-1 --ignore-daemonsets
둘째, kubeadm tool을 업그레이드 한다.
# Kubeadm installation
apt install kubeadm=1.xx.0-00 -y
# Check kubeadm version
kubeadm version
셋째, worker 노드를 업그레이드 한다.
kubeadm upgrade node
넷째, local kubelet configuration을 업그레이드 한다.
# upgrade the kubelet on the worker node
apt install kubelet=1.xx.0-00
# Recheck if it is Upgraded
kubectl get nodes
다섯째, worker 노드를 스케줄링 대상으로 복귀시킨다.
# Mark the worker node as "Schedulable"
kubectl uncordon worker_node
ETCD
ETCD is adistributedreliable key-value store that is Simple, Secure & Fast.
HA topology
- stacked etcd architecture : each control plane node creates a local etcd member
- external etcd architecture : etcd members run on separate hosts
--cert-file=/etc/kubernetes/pki/etc/server.crt(ETCD server certificate)
--peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt(ETCD CA certificate)
ETCD read & write
READ : you can easily read data from any node
Write : only one of the instances is responsible for processing the writes. the two nodes elect a leader among them. Of the total instances one node becomes the leader and the other node becomes the followers. If the writes came into the leader node, then the leader processes the write. The leader makes sure that the other nodes are sent a copy of the data. A write in only considered complete, if the leader gets consent from other members in the cluster.
ETCD Leader Election(RAFT protocol)
Quorum = N/2 + 1 : If it can be written on the majority of the nodes in the cluster, a write will be successful.
Fault Tolerance : HA 구성을 위해서는 1 노드가 죽더라도 Quorum 2를 유지할 수 있게적어도 3개 노드는 필요함(recommended).
Even or Odd : with even number of nodes there is possibility of the cluster faliling during a network segmentation. So need to choose the odd number.
If any API servers are running in your cluster, you should not attempt to restore instances of etcd. Instead, follow these steps to restore etcd:
stop all API server instances
restore state in all etcd instances
restart all API server instances
We also recommend restarting any components (e.g.kube-scheduler,kube-controller-manager,kubelet) to ensure that they don't rely on some stale data. Note that in practice, the restore takes a bit of time. During the restoration, critical components will lose leader lock and restart themselves.
ETCD 디버깅
docker ps -a | grep etcd
docker logs xxx(위 명령어로 docker container id를 얻는다)
If the etcd pod is not getting Ready 1/1, then restart it by kubectl delete pod -n kube-system etcd-controlplane and wait 1 minute.
퀴즈
1. How many nodes can host workloads in this cluster?
>> Inspect the applications and taints set on the nodes.
>> taint 걸려있지 않는 노드의 수
2. How many applications are hosted on the cluster?
>> Count the number of deployments
3. You are tasked to upgrade the cluster. you can't provision new VMs and User's accessing the applications must not be impacted. What strategy would you use to upgrade the cluster?
>> Upgrade one node at a time while moving the workloads to the other