시크릿은 비밀번호, OAuth 토큰, SSH 키와 같은 민감한 정보들을 저장하는 용도로 사용한다. 이러한 정보들은 컨테이너 안에 저장하지 않고 별도로 보관했다가 실제 파드를 실행할 때의 템플릿으로 컨테이너에 제공한다.

 

시크릿은 내장 시크릿과 사용자 정의 시크릿이 있다. 내장 시크릿은 쿠버네트 클러스터 안에서 쿠버네티스 API에 접근할 때 사용한다.

클러스터 안에서 사용하는 ServiceAccount라는 계정을 생성하면 자동으로 관련 시크릿을 만든다. 이 시크릿으로 ServiceAccount가 사용 권한을 갖는 API에 접근할 수 있다. 사용자 정의 시크릿은 사용자가 만든 시크릿이다. 

 

시크릿은 kubectl create secret 명령으로 만들 수 있고 다른 자원처럼 템플릿으로 만들 수 있다.


시크릿 생성

echo -n 명령으로 사용자 이름과 비밀번호를 설정하는 파일을 생성한다.

 

이후 kubectl create secret generic 시크릿이름 명령으로 user-pass-secret이라는 시크릿을 만든다.

 

$ kubectl get secret 시크릿이름 -o yaml #생성한 시크릿 확인 가능

 

 

.data 필드의 하위 필드로 .password.txt / .username.txt 라는 파일이 있는 것을 확인할 수 있다. 필드 값은 지정한 문구 그대로가 아닌 base64 문자 인코딩 방식이다. 시크릿이 생성될 때 자동으로 필드 값을 base64로 인코딩한 것이다.

 

다음 명령어로 필드 값들을 디코딩 할 수 있다.

디코딩하여 원래 값을 확인할 수 있다.


템플릿으로 시크릿 만들기

템플릿으로 시크릿을 만드는 예시

.type 필드 값으로 Opaque인 것을 확인할 수 있다.

 

시크릿 타입 설명
Opaque 기본 값. 키-값 형식으로 임의의 데이터를 설정할 수 있다.
kubernetes.io/service-account-token 쿠버네티스 인증 토큰을 저장
kubernetes.io/dockercfg 도커 저장소 환경 설정 정보를 저장
kubernetes.io/dockerconfigjson 도커 저장소 인증 정보를 저장
kubernetes.io/basic-auth 기본 인증을 위한 자격 증명 저장
kubernetes.io/ssh-auth SSH 접속을 위한 자격 증명 저장
kubernetes.io/tls TLS 인증서 저장
bootstrap.kubernetes.io/token 부트스트랩 토큰 데이터 정보를 저장

 


시크릿 사용

시크릿은 파드의 환경 변수나 볼륨을 이용한 파일 형식으로 사용할 수 있다.

시크릿을 파드의 환경 변수로 설정해 사용하는 예시

.spec.template.spec.containers[ ].env[ ] 필드를 확인했을 때

 

첫 번째 .name 필드 값으로는 SECRET_USERNAME이라는 환경 변수 이름을 설정했고 하위의 .valueFrom 필드에 .secretKeyRef .name과 .key라는 하위 필드를 설정해 시크릿의 이름(user-pass-yaml)과 키 값(username)을 참조한다.

두 번째 .name 필드 값으로는 SECRET_PASSWORD라는 환경 변수 이름을 설정해 .secretKeyRef.name과 .key라는 하위 필드를 설정해 시크릿의 이름과 키 값을 참조한다.

 

이후 kubectl apply -f deployment-secret01.yaml 명령을 실행해 클러스터에 적용한다.

그리고 웹 브라우저에서 localhost:30900/env 에 접속 해준다.

 

파드에서 불러온 시크릿 설정(SECRET_USERNAME=username & SECRET_PASSWORD=password)을 확인할 수 있다.


프라이빗 컨테이너 이미지를 가져올 때 시크릿 사용

보통 컨테이너에서 이미지를 pull 할 때는 대부분 공개된 이미지를 사용한다. 프라이빗 컨테이너 이미지를 사용하려면 인증 정보가 필요하다. 로컬 서버라면 프라이빗 컨테이너 이미지 사용 권한(인증 정보)를 저장한 후 사용할 수 있지만 쿠버네티스 클러스터에서는 보안상의 위험이 있으므로 그렇게 설정하지 않는다. 인증 정보를 시크릿에 설정해 저장한 후 사용한다.

 

쿠버네티스에는 kubectl create secret의 하위 명령으로 도커 컨테이너 이미지 저장소용 시크릿을 만드는 docker-registry가 있다.

 

위와 같이 시크릿을 생성해준 뒤 어떻게 사용하는지 확인해준다.

 

기존과는 다르게 .data 필드 아래 .dockerconfigjson라는 필드와 앞에서 설정한 도커 인증 정보 값이 설정돼있다.

*.type 필드 값은 kubernetes.io/dockerconfigjson(도커 저장소 인증 정보를 저장)이다.

 

프라이빗 컨테이너 이미지 인증 정보를 시크릿에 저장

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

컨피그맵은 컨테이너에 필요한 환경 설정을 컨테이너와 분리해 제공하는 기능이다.
클라우드 네이티브 아키텍처에서 컨테이너는 변하지 않는 자원이어야 한다. 개발 할 때 사용하는 컨테이너와 상용 서비스에서 사용하는 컨테이너가 같아야 한다는 의미이다. 그래야만 개발과 서비스 환경 차이에서 오는 잠재적 문제를 없앨 수 있기 때문이다.

 

하지만 개발용과 상용 서비스에서는 서로 다른 설정이 필요할 때가 많다. 사용하는 데이터베이스가 다를 수 있고, 개발을 할 때는 디버그 모드로 출력하지만, 서비스용에서는 시스템 정보를 나타내는 모드로 로그를 출력해야 하는 등의 차이가 있다.

 

위와같이 다른 설정으로 컨테이너를 실행해야 할 때 사용하는 것이 컨피그맵이다.

 

컨피그맵을 컨테이너와 분리하면 컨테이너 하나를 개발용, 상용 서비스를 운영하기 전 보안이나 성능 장애 등의 검증하는 스테이지용, 사용 서비스용으로 사용할 수 있다.


컨피그맵 사용

컨피그맵 설정 예시

.data의 하위 필드로 실제 사용하려는 환경 설정 값을 입력해준다. 

$ kubectl apply -f configmap-dev.yaml #쿠버네티스 클러스터 안에 적용한다.

 

 

위와 같이 Data 항목의 출력 결과가 템플릿 설정과 일치하면 정상적으로 적용된 것이다.


컨피그맵 설정 일부만 불러와 사용

컨피그맵의 일부 설정만 불러오는 디플로이먼트와 NodePort 타입 서비스가 포함된 템플릿 예시

 

.spec.template.spec.containers[ ].env[ ].valueFrom 필드는 각 값을 어디에서 가져올 것인지를 결정하고, 하위의 configMapKeyRef 필드는 어떤 컨피그맵의 어떤 키를 가져올 것인지 지정한다. 위에서는 .name 필드 값으로 config-dev를 설정해 앞서 만들어 둔 config-dev 컨피그맵을 선택했다.

 

.spec.template.spec.containers[ ].env[ ].valueFrom.configMapKeyRef.key 필드 값으로 .DEBUG_INFO 필드를 설정해 .data.DEBUG_INFO 필드를 불러왔다.

 

위 템플릿을 적용해준 뒤 http://localhost30800/env로 접속한 후 아래 그림을 확인하면 .DEBUG_LEVEL 필드 값에 .DEBUG_INFO 필드 값인 debug가 설정된 것을 확인할 수 있다.


컨피그맵 설정 전체를 불러와 사용

컨피그맵 설정 전체를 불러오는 예시

 

.spec.template.spec.containers[ ].envFrom[ ] 필드에서는 환경 변수를 어디에서 가져올 것인지를 설정한다.

 

.spec.template.spec.containers[ ].envFrom[ ].configMapRef.name 필드에 위에서 적용한 컨피그맵인 config-dev를 연결했다.    .configMapRef 필드는 어떤 컨피그맵을 참조해 환경 변수들을 불러올 것인지 설정한다. 하위의 .name 필드 값으로 불러올 컨피그맵의 이름을 설정한다.

 

컨피그맵 전체 설정 적용 확인


컨피그맵 볼륨에 불러와 사용

컨피그맵 설정을 컨테애너의 환경 변수로 설정하는 것이 아닌 다른 방식으로 사용할 수 있다. 

컨테이너의 볼륨 형식으로 컨피그맵 설정하는 예시

config-volume이라는 볼륨을 만들어 config-dev 컨피그맵의 .data 하위 필드 4개를 컨테이너의 /etc/config 디렉터리에 필드 이름 형태의 파일로 저장한다. (예를 들어 data.DB_URL 필드 값으로 localhost가 설정되었다면 파일 이름은 DB_URL이고 파일 . 안내용은 localhost인 파일을 생성한다는 것이다.)

config-volume 볼륨을 사용하는 컨피그맵 config-dev를 설정했다.

컨피그맵에 해당하는 파드 이름을 확인해준다.

컨테이너 안 /etc/config 디렉터리에 진짜 파일이 만들어졌는지 확인한다.

 

실제로 config-dev 컨피그맵 .data 하위 필드 4개 이름이 파일로 있다.

 

컨피그맵 설정이 파일로 컨테이너에 저장되어 있기 때문에 볼륨에 해당하는 쿼리가 있는 위 URL로 접속하였을 때 볼륨에 해당하는 쿼리를 입력한 컨테이너에 접속이 가능하다. 또한 컨테이너 안 /etc/config/DB_USER 라는 파일 내용을 확인할 수 있다.

 

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

서비스는 여러 개 파드에 접근할 수 있는 IP 하나를 제공한다. 본질적으로 로드밸런서 역할을 하고 다양한 기능을 제공한다.

파드는 컨트롤러가 관리하기 때문에 한 곳에 고정돼서 실행되지 않고, 클러스터 안을 옮겨 다닌다. 이 과정에서 노드를 옮기면서 실행되기도 하고 클러스터 안 파드의 IP가 변경되기도 한다. 이렇게 동적으로 변하는 파드들에 고정적으로 접근할 때 사용하는 방법이 쿠버네티스의 서비스이다. 

서비스를 사용하면 파드가 클러스터 안 어디에 있든 고정 주소를 이용해 접근할 수 있다. 클러스터 외부에서 클러스터 안 파드에 접근할 수도 있다. 인그레스로도 접근할 수 있는데 서비스는 주로 L4 영역에서 통신할 때 사용하고 인그레스는 L7 영역에서 통신할 때 사용한다는 차이점이 있다. 


서비스 타입 

ClusterIP: 기본 서비스 타입이며 쿠버네티스 클러스터 안에서만 사용할 수 있다. 클러스터 안 노드나 파드에서는 클러스터 IP를 사용해 서비스에 연결된 파드에 접근하다. (클러스터 외부에서는 사용할 수 없다)

 

NodePort: 서비스 하나에 모든 노드의 지정된 포트를 할당한다. ex) node1:8080, node2:8080처럼 노드에 상관없이 서비스에 지정된 포트 번호만 사용하면 파드에 접근할 수 있다. 노드의 포트를 사용하므로 클러스터 안 뿐만 아니라 클러스터 외부에서도 접근할 수 있다. (클러스터 외부에서 클러스터 안 파드로 접근할 때 사용할 수 있는 가장 간단한 방법이다.)

 

LoadBalancer: AWS같은 퍼블릭 클라우드 서비스, 오픈스택 같은 프라이빗 클라우드, 쿠버네티스를 지원하는 로드밸런서 장비에서 사용한다. 클라우드에서 제공하는 로드밸런서와 파드를 연결한 후 해당 로드밸런서의 IP를 이용해 클러스터 외부에서 파드에 접근할 수 있도록 해준다. (kubectl get service 명령으로 서비스 상태를 확인하면 EXTERNAL-IP 항목에 로드밸런서 IP를 표시한다. 이 IP를 사용해 클러스터 외부에서 파드에 접근한다.)

 

ExternalName: 서비스를 .spec.externalName 필드에 설정한 값과 연결한다. 클러스터 안에서 외부에 접근할 때 주로 사용한다. 이 서비스로 클러스터 외부에 접근하면 설정해둔 CNAME 값을 이용해 클러스터 외부에 접근할 수 있다. (클러스터 외부에 접근할 때 사용하는 값이므로 설정할 때 셀렉터(.spec.selector 필드) 가 필요 없다.) 


서비스 사용

서비스 기본 설정 예시

  1.  .spec.type 필드에서 서비스 타입을 설정할 수 있다. (따로 설정하지 않으면 기본 타입은 ClusterIP이다.)
  2.  .spec.clusterIP 필드에서 클러스터 IP를 직접 설정할 수 있다. (설정하지 않을 시 자동으로 IP값이 할당된다.)
  3.  .spec.selector 필드에는 서비스와 연결할  파드에 설정한 .labels 필드 값을 설정한다.
  4.  .spec.ports[ ] 필드는 배열 형태이다. 서비스에서 한꺼번에 포트 여러 개를 외부에 제공할 때는 .spec.ports[ ] 하위에 필드 값을 설정하면 된다. 

위와같이 디플로이먼트로 생성하는 서비스에 연결할 파드를 실행해준다. nginx 컨테이너를 실행하는 nginx-for-service라는 이름의 파드이다. (포트 번호는 80, 서비스에서 사용할 레이블은 파드 이름인 nginx-for-service로 자동 설정된다.)


1. ClusterIP 타입 서비스 사용

clusterIP 타입의 서비스를 만드는 설정

 

Cluster IP 타입 서비스의 구조

 

 

TYPE 항목이 ClusterIP고 CLUSTER-IP 항목에 10.101.112.209로 클러스터 IP가 생성되었다. EXTERNAL-IP 항목은 외부 IP가 없고 포트에는 80번 포트가 연결되었다.

 

$ kubectl describe service 서비스이름

 

위 명령어로 좀 더 자세한 정보를 확인할 수 있다.

 

현재 실행 중인 파드들의 IP 확인

 

앞서 실행했던 nginx-for-svc 디플로이먼트의 파드가 2개 실행중이고, IP가 각각 10.1.0.103, 10.1.0.104이고 위 clusterip-service의 Endpoints 항목과 값이 같다.

 

이제 위 클러스터 서비스의 클러스터 IP인 "10.101.112.209"로 파드에 접근할 수 있는지 확인해본다(클러스터 IP는 쿠버네티스 클러스터 안에서만 사용 가능하다). 쿠버네티스 클러스터 안에 파드를 하나 실행하고 해당 파드 안에서 앞서 만든 클러스터 IP로 접속해본다.

 

파드 안 컨테이너의 배시 셸에 접속한 뒤 curl 파드IP 명령을 실행하면 nginx 접속 페이지의 HTML 마크업을 출력한다.

위 결과를 보았을 때, ClusterIP 타입 서비스가 잘 설정되었고 정상 작동 중임을 알 수 있다.


2. NodePort 타입 서비스 사용

NodePort 타입 서비스 예시

 

NodePort 타입이고 CLUSTER-IP 항목이 10.96.237.69로 설정돼있다. PORT(S) 항목의 80:30080/TCP는 노드의 30080 포트가 ClusterIP 타입 서비스의 80 포트와 연결되어 있다는 뜻이다.

 

localhost:30080으로 접속했을 때 위와같이 기본 화면이 나오면 서비스가 정상 작동하는 것이다. 


3. LoadBalancer 타입 서비스 사용

LoadBalancer 타입 서비스 설정

LoadBalancer TYPE/ CLUSTER-IP/ EXTERNAL-IP : localhost/ PORT(S) 항목도 30267 포트로 설정된 것을 확인할 수 있다.

 

도커 데스크톱에서 실습을 할 때는 외부 로드밸런서가 없어 EXTERNAL-IP 항목이 localhost로 나타난다. 외부 로드밸런서와 연계되어 쿠버네티스 클러스터가 설정된 상태라면 localhost가 아닌 실제 외부에서 접근 가능한 IP가 나타난다.


4. ExternalName 타입 서비스 사용

ExternalName 타입 서비스 설정 예시

 

연결하려는 외부 도메인으로 google.com을 설정해주었다.

$ dig 도메인이름 #위 명령을 실행하면 도메인의 DNS 레코드가 CNAME 타입의 google.com으로 설정되었는지 볼 수 있다.

 

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

디플로이먼트(Deployment)

디플로이먼트(Deployment)는 쿠버네티스에서 stateless 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러이다. 

디플로이먼트는 레플리카세트를 관리하면서 앱 배포를 더 세밀하게 관리한다. 이름 그대로 배포 기능을 세분화한 것이다.

단순히 실행시켜야 할 파드 개수를 유지하는 것 뿐만 아니라 앱을 배포할 때 롤링 업데이트를 하거나, 앱 배포 도중 잠시 멈췄다가 다시 배포할 수 있다. 또한 앱 배포 후 이전 버전으로 롤백할 수도 있다.


1. 디플로이먼트 사용

디플로이먼트에 사용하는 템플릿

 

kubectl apply -f deployment-nginx.yaml

 

위 명령으로 클러스터에 적용한 뒤 디플로이먼트가 제대로 실행됐는지 확인한다.

실행 결과를 보았을 때, nginx-deployment가 생성되었고, 이 디플로이먼트가 관리하는 레플리카세트 또한 생성되었다. 마지막으로 레플리카 세트를 관리하는 파드들이 생성되었다.


2. 컨테이너 이미지 설정 정보 업데이트

 

kubectl set 명령으로 직접 컨테이너 이미지를 지정해준 뒤, 다시 상태 확인을 해준다.

컨테이너 이미지를 업데이트 하면서 nginx-deployment 디플로이먼트가 새로운 레플리카세트(7bb7b9c7f6)가 생성되었고 기존 파드는 새롭게 생성된 레플리카가 관리하는 형식의 파드들(7bb7b9c7f6)로 변경되었다. 

디플로이먼트의 설정을 변경할 때마다 이렇게 새로운 레플리카세트가 생성되고 그에 맞게 파드가 변경되는다는 점을 반드시 기억해야 한다.

3. 디플로이먼트 롤백하기

컨테이너 이미지를 변경한 내역은 kubectl rollout history deploy 디플로이먼트이름 명령으로 확인할 수 있다.

리비전이 보이고 현재 리비전은 3이다. 

위와같은 명령어로 특정 리비전의 상세 내용을 확인할 수 있다.

 

이 상태에서 kubectl rollout undo deploy nginx-deployment 명령어를 입력해주면 컨테이너 이미지를 되돌리면서 레플리카세트와 관리하는 파드들의 형식들 또한 되돌려진다.

 

위와같이 특정 리비전으로 실행중인 파드를 되돌리려면 위 명령어를 입력해준다.


4. 파드 개수 조정

실행 중인 디플로이먼트의 파드 개수를 조정하려면 kubectl scale 명령을 사용한다. (--replicas 옵션에 파드 개수를 입력해 조절한다)

총 3개의 파드들을 확인

파드 수를 5개가 되도록 조정한 후 파드 수를 확인했을 때 새로운 파드 2개가 더 생성된 것을 확인할 수 있다.


5. 디플로이먼트 배포 정지, 배포 재개, 재시작

kubectl rollout 명령을 사용해 진행 중인 배포를 잠시 멈췄다가 다시 시작할 수 있다.

위 명령어로 업데이틀 정지한다.

 

위 명령으로 컨테이너 이미지와 CHANGE-CASUE 항목에 나타내는 메시지를 변경해준다.

 

업데이트를 정지시켰으므로 디플로이먼트 작업이 진행되지 않는다.

kubectl rollout resume deploy/디플로이먼트이름 명령을 실행하면 미뤄졌던 배포가 진행된다.

위와 같이 배포 진행 상태를 확인할 수 있다. 

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

'DevOps > KUBERNETES' 카테고리의 다른 글

[8] 컨피그맵(configmap)  (0) 2024.05.02
[7] 서비스(Services)  (0) 2024.04.29
[6-1] 컨트롤러(Controller)- 레플리케이션 컨트롤러, 레플리카세트  (1) 2024.04.25
[5] 파드(Pod) -2  (1) 2024.04.23
[4] 파드(Pod)  (0) 2024.04.22

컨트롤러란?

컨트롤러는 파드들을 관리하는 역할을 한다. 다양한 목적에 맞게 사용할 수 있는 컨트롤러가 있다는 것은 쿠버네티스의 장점 중 하나이다.

 

웹 서비스와 같이 오랜 시간 동안 계속 실행되어야 하는 파드들을 관리할 때는 레플리케이션 컨트롤러, 레플리카세트, 디플로이먼트 등을 사용한다.

클러스터의 전체 노드에 같은 파드를 실행할 때는 데몬세트를 사용한다. 그리고 stateless 앱을 실행하는 데 사용하는 컨테이너를 statefull앱을 실행할 때 사용하도록 만드는 스테이트풀 세트도 있다. 마지막으로 1회성 작업을 할 때 사용하는 잡, 주기적인 배치 작업을 실행할 때 사용하는 크론잡도 있다.


1. 레플리케이션 컨트롤러

레플리케이션 컨트롤러는 쿠버네티스 프로젝트의 초기부터 존재한 가장 기본적인 컨트롤러이다. 지정한 숫자만큼의 파드가 항상 클러스터 안에서 실행되도록 관리한다. 예를 들어, 파드 2개를 명시해 둔 레플리케이션 컨트롤러가 있을 때 장애나 다른 이유로 파드 개수가 2개보다 적을 시 다시 새로운 파드를 실행해 파드 개수를 2개로 맞춘다. 만약 파드가 2개보다 많아졌을 때는 그 숫자를 줄여 2개만큼만 실행되도록 조정한다.

 

컨트롤러를 사용하지 않고 파드를 직접 실행하면 파드에 이상이 생겨 종료되었을 때 재시작하기가 어렵다. 레플리케이션 컨트롤러를 이용해 실행한 파드라면 클러스터 안 다른 노드에 다시 파드를 실행시킬 수 있다.

 

레플리케이션 컨트롤러는 쿠버네티스 초창기부터 존재했지만 최근에는 비슷한 역할을 하는 레플리카세트를 사용하는 추세이다.


2. 레플리카세트

레플리카세트는 레플리케이션 컨트롤로의 발전형이다. 레플리케이션 컨트롤러와 같은 동작을 하지만 집합 기반의 셀렉터를 지원하는 차이점이 있다. 레플리케이션 컨트롤러는 실렉터가 등호 기반이므로 레이블을 선택할 때 같은지(=) 다른지(!=)만 확인한다. 하지만 집합 기반의 셀렉터는 in, notin, exists 같은 연산자를 지원한다.

 

또한 레플리케이션 컨트롤러는 kubectl에서 rolling-update 옵션을 사용할 수 있지만 레플리카세트는 사용할 수가 없으므로, rolling-update 옵션이 필요할 때는 디플로이먼트를 사용해야 한다.


2.1. 레플리카세트 사용

레플리카세트 설정 예시

  • 자세한 명세는 .spec 필드에 설정한다. .spec.template 필드에는 레플리카세트가 어떤 파드를 실행할지에 관한 정보를 설정한다.
  • .spec.template.spec.containers[ ] 필드는 하위에 .name, .imgae, .ports[ ], .containerPort 필드를 이용해 컨테이너의 구체적인 명세를 설정한다. 위 예시에서는 nignx를 컨테이너 이미지, 해당 컨테이너에 접속할 포트 번호는 80번으로 설정했다.
  • .spec.replicas는 파드를 몇 개 유지할지 개수를 설정하는 필드이다. (기본 값은 1이다.)
  • .spec.selector는 어떤 레이블(.labels)의 파드를 선택해서 관리할지를 설정한다. 레이블을 기준으로 파드를 관리하므로 실행 중인 파드를 중단하거나 재시작하지 않고 레플리케이션 컨트롤러가 관리하는 파드를 변경할 수 있다. 그렇기때문에 처음 레플리케이션 컨트롤러를 생성할 때 .spec.template.metadata.labelsd의 하위 필드 설정과 .spec.selector.matchLabels의 하위 필드 설정이 같아야 한다. 만약 다를시 kube-apiserver에서 유효하지 않은 요청이라고 판단해 파드 변경을 거부한다.

.spec.replicas를 3으로 설정했으므로 3개의 파드가 실행된 것을 확인할 수 있다.

임의로 파드 1개를 삭제한 뒤 다시 pod를 확인했을 때 파드 개수를 3개로 유지하기 위해 파드 1개가 추가로 실행되는 것을 확인할 수 있다.

 

파드 개수를 조절하려면 replicaset-nginx.yaml 안 .spec.replicas 필드 값을 원하는 숫자로 수정한 뒤 다시 kubectl apply -f replicaset-nginx.yaml 명령을 실행한다.


2.2. 레플리카세트와 파드의 연관 관계

파드는 레이블 기준으로 관리하기 때문에 레플리카세트와 파드는 느슨하게 결합되어 있다. 즉, 레플리카세트와 파드를 한꺼번에 삭제할 때는 kubectl delete replicaset 컨테이너이름 --cascade=false 명령으로 레플리카세트를 삭제한다.

레플리카세트 삭제
레플리카세트와 파드 상태 확인
레플리카세트 재생성 후 상태 확인

이때 레플리카의 상태도 확인을 할 수가 있다.

레플리카 상태 항목:

  • DESIRED: 레플리카세트 설정에 지정한 파드 개수
  • CURRENT: 레플리카세트를 이용해 현재 클러스터에서 동작하는 실제 파드 개수

새로 만든 레플리카세트가 정상적으로 동작하는지 확인.

새롭게 nginx-replicaset-j7gdf라는 파드를 생성한 것을 확인할 수 있다.


실행 중인 파드의 .metadata.labels.app 필드를 수정했을 때 발생하는 상황

우선 실행 중인 파드 목록을 확인한다.

kubectl edit pod 수정하려는 파드이름 명령을 실행한다.

위와같이 .metadata.labels.app 필드에서 nginx-replicaset >> nginx-other이라고 변경한다.

 

kubectl get pods 명령을 실행했을 때, 위와 같이 파드가 추가되어 4개가 실행되는 것을 확인할 수 있다.

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

1. 초기화 컨테이너

초기화 컨테이너는 앱 컨테이너가 실행되기 전 파드를 초기화한다.

보안상 이유로 앱 컨테이너 이미지와 같이 두면 안 되는 앱의 소스 코드를 별도로 관리할 때 유용하다.

  • 초기화 컨테이너는 여러 개를 구성할 수 있다. 여러 개 있다면 파드 템플릿에 명시한 순서대로 초기화 컨테이너가 실행된다.
  • 초기화 컨테이너는 실행이 실패하면 성공할 때까지 재시작한다. 이러한 특성을 이용하면 쿠버네티스의 "선언적"이라는 특징에서 벗어날 수 있다. 즉, 필요한 명령들을 순서대로 실행하는 데 사용하는 것이다.
  • 초기화 컨테이너는 모두 실행된 후 앱 컨테이너 실행이 시작된다.

이러한 특징을 이용하여 파드를 실행할 때 앱 컨테이너가 외부의 특정 조건을 만족할 때까지 기다렸다가 실행하도록 할 수 있다.

예를 들어, 초기화 컨테이너가 외부의 특정 조건을 만족할 때까지 대기하고 있다가 조건이 충족된 후 앱 컨테이너를 실행하는 것이다.

 

초기화 컨테이너는 앱 컨테이너와 비슷하게 동작하지만 몇 가지 다른 점이 있다. 특히 프로브를 지원하지 않는다. 왜냐하면 파드가 모두 준비되기 전에 실행한 후 종료되는 컨테이너이기 때문이다.

 

<초기화 컨테이너를 설정한 파드 설정 예시>

 

  1. 첫 번째 초기화 컨테이너의 .spec.initContainers[ ].name 필드 값으로는 init-myservice라는 이름으로 설정했다.                          .image 필드 값으로는 위와 같은 이미지를 설정해주었고 .command 필드 값으로 해당 컨테이너를 실행할 때 2초를 대기한 후 helloworld01이라는 메시지를 출력하게 설정하였다.
  2. 두 번째 초기화 컨테이너의 .spec.initContainers[ ].name 필드 값으로는 init-mydb라는 이름으로 설정하였고, .command 필드 값으로는 해당 컨테이너를 실행할 때 2초 대기한 뒤 helloworld02라는 메시지를 출력하게 설정했다.
  3. .spec.containers[ ]의 하위 필드는 실제로 생성할 파드를 설정했다. .command 필드 값으로는 해당 컨테이너를 실행할 때 "The app is running!" 메시지를 출력하고 3600초 대기하도록 설정하였다.

즉, 위 코드는 kubernetes-simple-pod라는 파드를 생성하기 전 초기화 컨테이너로 init-service와 init-mydb를 실행한다.


2. 파드 인프라 컨테이너

쿠버네티스에는 모든 파드에서 항상 실행되는 pause라는 컨테이너가 있다. 이 pause를 "파드 인프라 컨테이너(Pod Infrastructure Container)"라고 한다.

파드 인프라 컨테이너 구조

pause는 파드 안 기본 네트워크로 설정되며, 프로세스 식별자가 1(PID 1)로 설정되므로 다른 컨테이너의 부모 컨테이너 역할을 한다.

파드 안 다른 컨테이너는 pause 컨테이너가 제공하는 네트워크를 공유해 사용한다. 그래서 파드 안 다른 컨테이너가 재시작됐을 때는 파드의 IP를 유지하지만, pause 컨테이너가 재시작되면 파드 안 모든 컨테이너도 재시작된다.

 

kublet에는 명령 옵션으로 --pod-infra-container-image 가 있다.

*pause가 아닌 다른 컨테이너를 파드 인프라 컨테이너로 지정할 때 사용한다.


3. 스태틱 파드

kube-apiserver를 통하지 않고 kubelet이 직접 실행하는 파드들이 있는데 이를 스태틱 파드라고 한다.

kubelet 설정의 --pod-manifest-path라는 옵션에 지정한 디렉터리에 스태틱 파드로 실행하려는 파드들을 넣어두면 kubelet이 그걸 감지해 파드로 실행한다.

 

스태틱 파드는 kubelet이 직접 관리하며 이상이 생길 시 재시작을 한다, 또한 kubelet이 실행 중인 노드에서만 실행되고 다른 노드에서는 실행되지 않는다. kube-apiserver로 파드를 조회할 수 있지만 스태틱 파드에 어떤 명령을 실행할 수는 없다.

보통 스태틱 파드는 kube-apiserver 또는 etcd와 같은 시스템 파드를 실행하는 용도로 많이 사용된다.

 

쿠버네티스에서 파드를 실행하기 위해서는 kube-apiserver가 필요한데 kube-apiserver 자체를 처음 실행하는 별도의 수단으로 스태틱 파드를 사용하는 것이다.

 

*도커 데스크톱 안 kube-apiserver의 위치 > /etc/kubernetes/manifests


4. 파드에 CPU와 메모리 자원 할당

마이크로서비스 아키텍처 기반으로 여러 개 작은 프로세스를 실행하면 노드 하나에 여러 개 파드를 실행하는 일이 자주 있다.

이때 자원 사용량이 많은 파드가 노드 하나에 모여 있다면 파드들의 성능이 나빠지고 전체 클러스터의 자원 사용 효율도 낮아진다.

예를 들어, 어떤 노드에는 파드가 없어서 CPU나 메모리 같은 자원이 남고, 어떤 노드에는 파드들이 많아 파드에서 사용해야 하는 CPU나 메모리가 부족한 현상이 발생할 수도 있다.

 

이러한 현상을 막기 위해 쿠버네티스는 파드를 설정할 때 파드 안 각 컨테이너가 CPU나 메모리를 얼마나 사용할 수 있을지 조건을 지정한다.

 

파드에는 CPU와 메모리를 대상으로 자원 사용량을 설정할 수 있도록 .limits와 .requests 필드를 설정했다.

자원 사용량을 설정하는 예시 yaml

  • .spec.containers[ ].resources.requests 필드는 최소 자원 요구량을 나타낸다. 파드가 실행될 때 최소한 설정된 만큼의 자원 여유가 있는 노드가 있어야 파드를 그곳에 스케줄링해 실행한다. .spec.containers[ ].resources.requests에서 요구하는 여유 자원이 있는 노드가 없다면 파드는 Pending 상태로 실행되지 않고 클러스터 안에 자원 여유가 생길 때까지 대기한다.
  • .spec.containers[ ].resources.limits 필드는 자원을 최대로 얼마까지 사용할 수 있는지 제한하는 설정이다. 웹 서비스를 제공하는 컨테이너가 있다고 할 때, 급격하게 트래픽이 늘어나면 자원 사용량 또한 늘어난다. 이때 이 설정이 없다면 해당 컨테이너가 노드의 모든 자원을 사용할 수 있고 그러면 같은 노드에 실행된 다른 컨테이너가 모두 영향을 받아 최악의 상황에는 클러스터 안 모든 서비스에 영향을 끼칠 수도 있다.

쿠버네티스가 파드를 스케줄링 할 때는 노드의 현재 사용량을 보는 것이 아닌 .spec.containers[ ].resources.requests와 .spec.containers[ ].resources.limits만을 확인한다.


5. 파드에 환경 변수 설정

컨테이너를 사용할 때 장점 중 하나는 개발 환경에서 만든 컨테이너의 환경 변수만 변경해 실제 환경에서 실행하더라도 개발 환경에서 동작하던 그대로 동작한다는 점이다.

파드 환경 변수 설정 예시 yaml

 

.spec.containers[ ]의 하위 필드를 살펴보면 .spec.containers[ ].env[ ]라는 하위 필드를 확인할 수 있다.

이 필드에는 각각 다음과 같은 뜻이 있다.

  • name:  사용할 환경 변수의 이름을 설정한다.
  • value: 문자열이나 숫자 형식의 값을 설정한다.
  • valueFrom: 값을 직접 할당하는 것이 아닌 어딘가 다른 곳에서 참조하는 값을 설정한다.
  • fieldRef: 파드의 현재 설정 내용을 값으로 설정한다는 선언이다.
  • fieldPath: .fieldRef에서 어디서 값을 가져올 것인지를 지정한다. 즉, 값을 참조하려는 항목의 위치를 지정한다.
  • resourceFiledRef: 컨테이너에 CPU, 메모리 사용량을 얼마나 할당했는지에 관한 정보를 가져온다.
  • containerName: 환경 변수 설정을 가져올 컨테이너 이름을 설정한다.
  • resource: 어떤 자원의 정보를 가져올지 설정한다.

6. 파드 환경 설정 내용 적용

파드는 환경 설정 내용을 템플릿 하나에 모두 작성한 후 적용해야 한다.

$ kubectl apply -f 0000.yaml

 

환경 변수 설정을 확인하기 위해서 아래 명령어를 입력 후 컨테이너 안으로 접속해 준다.

이후 env 명령어를 실행해 환경 변수를 확인한다.

KUBERNETES_ 라는 접두어를 사용하는 환경 변수들은 쿠버네티스 안에서 현재 사용 중인 자원 관련 정보가 있다.


7. 파드 구성 패턴

파드로 여러 개의 컨테이너를 묶어서 구성하고 실행할 때 몇 가지 패턴을 적용할 수 있다.


7.1. 사이드카 패턴

사이드카 패턴은 원래 사용하려던 기본 컨테이너의 기능을 확장하거나 강화하는 용도의 컨테이너를 추가하는 것이다. 기본 컨테이너는 원래 목적의 기능에만 충실하도록 구성하고, 나머지 공통 부가 기능들은 사이드카 컨테이너를 추가하여 사용한다.

사이드카 패턴 구조

 

일반적인 웹 서버라면 웹 서버 컨테이너는 웹 서버 역할만 하고 로그는 파일(파일 시스템안에)로 남긴다. 사이드카 역할인 로그 수집 컨테이너는 파일 시스템에 쌓이는 로그를 수집해서 외부의 로그 수집 시스템으로 보내는 역할을 한다.

 

이와 같이 구성을 하면 웹 서버 컨테이너를 다른 역할을 하는 컨테이너로 변경했을 때도 로그 수집 컨테이너는 그대로 사용할 수 있다.

즉, 공통 역할을 하는 컨테이너의 재사용성을 높일 수 있다.


7.2. 앰배서더 패턴

앰배서더 패턴은 파드 안에서 프록시 역할을 하는 컨테이너를 추가하는 패턴이다. 파드 안에서 외부 서버에 접근할 때 내부 프록시에 접근하도록 설정하고 쉽게 외부와의 연결은 프록시에서 알아서 처리한다.

 

앰배서더 패턴 구조

 

웹 서버 컨테이너는 캐시에 localhost로만 접근하고 실제 외부 캐시 중 어디로 접근할지는 프록시 컨테이너가 처리한다.


7.3. 어댑터 패턴

어댑터 패턴은 파드 외부로 노출되는 정보를 표준화하는 어댑터 컨테이너를 사용한다는  의미이다.

주로 어댑터 컨테이너 파드의 모니터링 지표를 표준화한 형식으로 노출시키고, 외부의 모니터링 시스템에서 해당 데이터를 주기적으로 가져가서 모니터링하는데 이용한다.

어댑터 패턴의 구조

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

1. 파드란 무엇인가?

쿠버네티스는 실제로 파드라는 단위로 컨테이너를 묶어서 관리하므로 보통 컨테이너가 하나가 아닌 여러 개 컨테이너로 구성된다.

파드로 컨테이너 여러 개를 한꺼번에 관리할 때는 컨테이너마다 역할을 부여할 수 있다. 파드 하나에 속한 컨테이너들은 모두 노드 하나 안에서 실행된다. 컨테이너들이 같은 목적으로 자원을 공유하는 것은 파드의 역할중 하나이기때문에 가능한 현상이다.

파드 안 여러 개 컨테이너에 역할을 부여하는 그림

 

파드 안에 컨테이가 3개 있고 각각 웹 서버, 로그 수집기, 볼륨 컨테이너라는 역할을 부여했다. 또한 파드 하나 안에 있는 컨테이너들은 하나의 IP를 공유한다.

즉, 외부에서 파드에 접근할 때, 192.168.10.10이라는 IP로 접근하며 파드 안 컨테이너와 통신할 때는 컨테이너마다 다르게 설정한 포트를 사용한다.

 

컨테이너 하나에 앞 그림의 세 가지 역할을 모두 부여할 수도 있다. 하지만 실제로 컨테이너 하나 안에 2개의 프로세스를 실행하는 것은 간단하지 않다. 시스템 신호나 종료 코드 처리도 프로세스마다 설정해줘야 하기 때문에 컨테이너 관리 효율이 떨어진다.


2. 파드 사용

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-simple-pod
  labels:
    app: kubernetes-simple-pod
spec:
  containers:
  - name: kubernetes-simple-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080

<기본적인 파드의 템플릿 설정 예시>

 

  • .metadata.name 필드는 파드 이름을 설정한다.
  • .metadata.labels.app 필드는 오브젝트를 식별하는 레이블을 설정한다. 위 예시에서는 해당 파드가 앱 컨테이너이고 kubernetes-simple-pod라고 식별한다고 설정했다.
  • .spec.containers[ ].name 필드는 컨테이너의 이름을 설정한다. 위 예시에서는 kubernetes-simple-pod로 설정하였다. name 앞에 설정한 '-'은 .spec.containers의 하위 필드를 배열 형태로 묶겠다는 뜻이다. (그렇기때문에 .spec.contaienrs[ ] 라고 표기)
  • .spec.containers[ ].imgae 필드는 컨테이너에서 사용할 이미지를 결정한다.
  • .spec.container[ ].ports[ ].containerPort 필드는 해당 컨테이너에 접속할 포트 번호를 설정한다.

파드 실행

정상적으로 파드가 실행됐음을 확인


3. 파드 생명 주기

파드는 생성부터 삭제까지의 과정에 생명 주기가 있다.

  • Pending: 쿠버네티스 시스템에서 파드를 생성 중임을 의미한다. 이 상태는 컨테이너 이미지를 다운로드한 뒤 전체 컨테이너를 실행하는 과정이므로 파드 안의 전체 컨테이너가 실행될 때까지 시간이 걸린다.
  • Running: 파드 안 모든 컨테이너가 실행 중인 상태를 의미한다. 1개 이상의 컨테이너가 실행 중이거나 시작 또는 재시작 상태일 수 있다.
  • Succeeded: 파드 안 모든 컨테이너가 정상 실행 종료된 상태로 재시작되지 않는다.
  • Failed: 파드 안 모든 컨테이너 중 정상적으로 실행 종료되지 않은 컨테이너가 있는 상태이다. 컨테이너 종료 코드가 0이 아니면 비정상 종료이거나 시스템이 직접 컨테이너를 종료한 것이다.
  • Unknwon: 파드의 상태를 확인할 수 없는 상태이다. 보통 파드가 있는 노드와 통신할 수 없을 때이다.

현재 파드 생명 주기는 kubectl describe pods 파드이름 명령을 실행한 후 Status 항목에서 확인할 수 있다.

 

Status 항목에서 현재 파드가 Running 상태인 것을 확인할 수 있다.

 

Conditions 항목은 파드의 현재 상태 정보를 나타내며 Type과 Status로 구분되어 있다.

  • Initialized: 모든 초기화 컨테이너가 성공적으로 시작 완료되었다는 의미이다.
  • Ready: 파드는 요청들을 실행할 수 있고 연결된 모든 서비스의 로드밸런싱 풀에 추가되어야 한다는 의미이다.
  • ContainersReady: 파드가 하나의 노드로 스케줄을 완료했다는 의미이다.
  • Unschedulable: 스케줄러가 자원의 부족이나 다른 제약 등으로 지금 당장 파드를 스케줄 할 수 없다는 의미이다.

Status는 Type의 상태를 나타내는 True(상태 활성화), False(상태 비활성화), Unknown(상태 알 수 없음)값을 출력한다.


4. kubelet으로 컨테이너 진단

Probe는 컨테이너에서 kubelet에 의해 주기적으로 수행되는 진단이다. 컨테이너가 실행된 후에는 kubelet이 컨테이너를 주기적으로 진단하는데 이때 필요한 Probe는 다음 세 가지가 있다.

  • livenessProbe: 컨테이너가 실행됐는지 확인한다. 이 진단이 실패하면 kubelet은 컨테이너를 종료시키고, 재시작 정책에 따라 컨테이너를 재시작한다. 컨테이너에 livenessProbe를 어떻게 할지 명시되지 않았다면 기본 상태 값은 Success이다.
  • readinessProbe: 컨테이너가 실행된 후 실제로 서비스 요청에 응답할 수 있는지 진단한다. 이 진단이 실패하면 엔드포인트 컨트롤러는 해당 파드에 연결된 모든 서비스를 대상으로 엔드포인트 정보를 제거한다. 첫 번째 readinessProbe를 하기 전까지의 기본 상태 값은 Failure이고 readinessProbe를 지원하지 않는 컨테이너라면 기본 상태 값은 Success이다.
  • startupProbe: 컨테이너 안 애플리케이션이 시작되었는지를 나타낸다. 스타트업 프로브는 진단이 성공할 때까지 다른 나머지 프로브는 활성화되지 않으며, 진단이 실패할 시 kubelet이 컨테이너를 종료시키고, 컨테이너를 재시작 정책에 따라 처리한다. 컨테이너 스타트업 프로브가 없으면 기본 상태 값은 Success이다.

앞 세 가지 프로브가 있는 것은 쿠버네티스의 장점중 하나이다. readinessProbe를 지원하는 컨테이너라면 컨테이너가 실행된 다음 바로 서비스에 투입되어서 트래픽을 받지 않는다. 실제 트래픽을 받을 준비가 되었음을 확인한 후 트래픽을 받을 수 있다.

자바 애플리케이션처럼 프로세스가 시작된 후 앱이 초기화될 때까지 시간이 걸리는 상황에 유용하다. 또한 앱을 실행할 때 대용량 데이터를 불러와야 하거나, 컨테이너 실행은 시작됐지만 앱의 환경 설정 실수로 앱이 실행되지 않는 상황 등에 대비할 수 있다.


컨테이너 진단은 컨테이너가 구현한 핸들러를 kubelet이 호출해서 실행한다.

 

핸들러는 세 가지가 있다.

  • ExecAction: 컨테이너 안에 지정된 명령을 실행하고 종료 코드가 0일 때 Success라고 진단한다.
  • TCPSocketAction: 컨테이너 안에 지정된 IP와 포트로 TCP 상태를 확인하고 포트가 열려있으면 Success라고 진단한다.
  • HTTPGetAction: 컨테이너 안에 지정된 IP, 포트, 경로로 HTTP GET 요청을 보낸다. 응답 상태 코드가 200에서 400 사이면 Success라고 진단한다.

진단 결과 3개

  • Success: 컨테이너가 진단에 성공
  • Failure: 컨테이너가 진단에 실패
  • Unknown: 진단 자체가 실패해서 컨테이너 상태를 알 수 없음

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

쿠버네티스는 크게 오브젝트와 오브젝트를 관리하는 컨트롤러로 나눈다. 사용자는 템플릿 등으로 쿠버네티스에 자원의 "바라는 상태"를 정의하고 컨트롤러는 바라는 상태와 현재 상태가 일치하도록 오브젝트들을 생성/삭제한다.

  • 오브젝트에는 파드, 서비스, 볼륨, 네임스페이스 등이 있다.
  • 컨트롤러에는 레플리카세트, 디플로이먼트,스테이트풀세트, 데몬세트, 잡 등이 있다.

네임스페이스

네임스페이스는 쿠버네티스 클러스터 하나를 여러 개 논리적인 단위로 나눠서 사용하는 것이다. 네임스페이스 덕분에 쿠버네티스 클러스터 하나를 여러 개 팀이나 사용자가 함께 공유할 수 있다. 클러스터 안에서 용도에 따라 실행해야 하는 앱을 구분할 때도 네임스페이스를 사용한다. 네임스페이스별로 별도의 쿼터를 설정해서 특정 네임스페이스의 사용량을 제한할 수도 있다.

$ kubectl get namespaces   
#쿠버네티스를 처음 설치하면 기본으로 몇 개의 네임스페이스가 생성됨.
#위 명령어로 현재 생성되어 있는 네임스페이스 확인가능

 

default, kube-system, kube-public, kube-node-lease 등은 쿠버네티스가 기본으로 생성하는 네임스페이스이다.

 

  • default: 기본 네임스페이스이다. 쿠버네티스에서 명령을 실행할 때 별도의 네임스페이스를 지정하지 않는다면 항상 default 네임스페이스에 명령을 적용하게 된다.
  • kube-system: 쿠버네티스 시스템에서 관리하는 네임스페이스이다. 쿠버네티스 관리용 파드나 설정이 있다.
  • kube-public: 클러스터 안 모든 사용자가 읽을 수 있는 네임스페이스이다. 클러스터를 사용하는 모두가 볼 수 있기때문에 보통 클러스터 사용량 같은 정보를 이 네임스페이스에서 관리한다.
  • kube-node-lease: 각 노드의 임대 오브젝트들(lease object)을 관리하는 네임스페이스이다.

kubectl로 네임스페이스를 지정해서 사용할 때는 "--namespace=kube-system"처럼 네임스페이스를 명시해야 한다.

그런데 default 이외의 네임스페이스를 사용할 때 매번 옵션을 변경하기 번거롭기 때문에 기본 네임스페이스를 변경해 사용하면된다.


1. 기본 네임스페이스를 변경하기 위해서는 context 정보를 확인해야 한다.

$ kubectl config current-context

 

 

현재 context는 docker-desktop인 것을 확인할 수 있다.


2. 다음으로 context 정보를 확인한다.

$ kubectl config get-contexts 컨텍스트 이름

 

 

NAMESPACE 부분이 비어있다는 것은 기본 네임스페이스가 default라는 뜻이다.


3. 기본 네임스페이스 변경

 

기본 네임스페이스를 kube-system으로 변경해준다.

 

다시 확인을 해보았을 때, NAMESPACE 부분이 kube-system으로 변경된 것을 확인할 수 있다.


4. 기본 네임스페이스 확인

# macOS 및 리눅스
$ kubectl config view | grep namespace

 

기본 네임스페이스가 kube-system이라는 것을 확인할 수 있다.


각 파드의 기본 네임스페이스를 어떻게 설정했는지 한 번에 확인하고 싶다면 아래 명령어를 입력해주면 된다.

$ kubectl get pods --all-namespaces

기본 네임스페이스를 다시 default로 바꿀 때는 "kubectl config set-context 컨텍스트이름 --namespace=default" 명령을 실행해주면 된다.


kubens

네임스페이스를 변경할 때 매번 긴 명령어를 입력하기 번거롭기 때문에 네임스페이스 변경을 돕는 도구인 kubens를 사용할 수 있다.

배시 스크립트 기반이므로 다음 명령으로 스크립트를 다운로드 한 뒤 실행 권한을 설정하여 사용할 수 있다.

$ brew install kubectx

$ kubens

 

 

위 명령어로 현재 클러스터에서 선택할 수 있는 네임스페이스 목록을 확인할 수 있습니다.

 

현재 context의 기본 네임스페이스를 변경할 때는 kubens kube-system 명령을 실행한다. 간단한 명령어로 현재 context의 네임스페이스를 변경할 수 있다.


쿠버네티스 클러스터의 오브젝트나 컨트롤러가 어떤 상태여야 하는지를 적용할 때는 YAML 형식의 템플릿을 사용한다.

 

템플릿의 내용을 표현하는 YAML은 JSON과 비교했을 때 간결하며, 주석을 지원해 가독성이 좋다.

그러나 들여쓰기에 따라 구조가 바뀌기때문에 들여쓰기를 신경써줘야 한다.

 

YAML은 "Scalars(strings/numbers)", "Sequence(arrays/lists)", "Mapping(hashes/dictionaries)" 라는 세 가지 기초 요소로 표현한다. 주석은 '#' 으로 시작하며, 여러 줄 주석은 지원하지 않는다.

'---'은 성격이 다른 YAML 형식의 문서 여러 개가 있을 때 구분자로 사용하고, YAML의 시작을 알리는 용도로 사용한다.

 

Scalars(strings/numbers) Sequence(arrays/lists) Mapping(hashes/dictionaries)
Name: Kim
Birth: 1999
ProgrammingSkills:
   -java
   -python
   -c
Data:
   Height: 170
   Weight: 75

 

 

각 항목은 필드라고 하고 필드 각각은 다음 같은 설정을 한다.

  • apiVersion: 사용하려는 쿠버네티스 API 버전을 명시한다. 쿠버네티스는 버전 변경이 빠른 편이므로 여러 가지 API 버전이 있다. 그래서 API 버전을 정확하게 지정하는 것이 중요하다. kubectl api-version 명령으로 현재 클러스터에서 사용 가능한 API 버전을 확인할 수 있다.
  • kind: 어떤 종류의 오브젝트 혹은 컨트롤러에 작업인지 명시한다. Pod라고 설정하면 파드에 관한 템플릿을 의미한다. 종류로는 Pod, Deployment, Ingress 등의 다양한 오브젝트나 컨트롤러를 설정할 수 있다.
  • .apiVersion과 .kind 필드 다음에는 .kind에서 지정한 오브젝트나 컨트롤러에 필요한 옵션을 설정한다. 보통 .metadata 와 .spec을 설정한다.
    • metadata: 메타데이터를 설정한다. 해당 오브젝트의 이름이나 레이블등을 설정한다.
    • spec: 파드가 어떤 컨테이너를 가지고 실행하며, 실행할 때 어떻게 동작하는지 명시한다.
  • .metadata 와 .spec은 각각 다양한 하위 필드가 있는데 kubectl explain 명령어를 통해 어떤 필드와 어떤 역할을 하는지 볼 수 있다.

 

여기서 .metadata 데이터 타입이 Object라면 kubectl explain pods.metadata 라는 명령어를 통해 하위 필드가 무엇이지 확인할 수 있다.

 

위와같은 방식으로 하위 필드 각각이 무슨 역할을 하는지 알 수 있다.

 

하위 필드를 포함해 특정 필드를 커맨드 라인에서 지정할 때는 보통 필드 이름을 '.' 으로 연결해 표현한다.

 

필드 설명 없이 특정 필드와 그 아래에 속한 모든 하위 필드를 한꺼번에 보고싶다면 kubectl explain pods --recursive 명령을 실행한다. 위 명령어를 입력하면 아래에 속한 모든 필드가 데이터 타입과 함께 트리 형식으로 출력된다.

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

'DevOps > KUBERNETES' 카테고리의 다른 글

[6-1] 컨트롤러(Controller)- 레플리케이션 컨트롤러, 레플리카세트  (1) 2024.04.25
[5] 파드(Pod) -2  (1) 2024.04.23
[4] 파드(Pod)  (0) 2024.04.22
[2] Kubernetes Architecture  (0) 2024.04.17
[1] kubectl 사용법  (0) 2024.04.17

쿠버네티스 클러스터 구조

쿠버네티스 클러스터는 크게 두 종류의 서버로 구성된다. 클러스터를 관리하는 Control Plane(Master)와 실제 컨테이너를 실행시키는 Node이다. 마스터에는 etcd, kube-api-server, kube scheduler, kube-controller-manager 등의 컴포넌트가 실행된다. 컴포넌트 각각 다른 마스터나 노드 서버에서 별개로 실행되어도 실제 쿠버네티스 클러스터를 운영하는 데 이상은 없다. 하지만 마스터가 서버 1대라면 프로세스 한 묶음을 해당 서버에서 같이 실행하는 것이 일반적인 구성이다.

노드에는 kubelet, kube-proxy, docker 등의 컴포넌트가 실행된다. 실제 사용하는 컨테이너 대부분은 노드에서 실행된다.

 

각 컴포넌트의 중심에는 kube-api-server가 있습니다. 쿠버네티스의 모든 통신은 kube-api-server를 중심으로 이루어진다.

kube-api-server를 거쳐 다른 컴포넌트가 서로 필요한 정보를 주고 받는다. 특히 etcd에는  kube-api-server만 접근이 가능하다.


쿠버네티스 주요 컴포넌트

쿠버네티스의 컴포넌트는 세 가지로 구분된다. 클러스터를 관리하는 데 필수인 마스터용 컴포넌트, 노드용 컴포넌트, 필수는 아니지만 추가로 사용할 수 있는 애드온용 컴포넌트이다.


1. 마스터용 컴포넌트

마스터용 컴포넌트는 실제 클러스터 전체를 관리한다. etcd, kube-apiserver, kube-scheduler, kube-controller-manager, cloud-controller-manager 등이 마스터용 컴포넌트이다.

 

  • etcd: 코어 OS에서 개발한 고가용성을 제공하는 키-값 저장소이다. 쿠버네티스에서 필요한 모든 데이터를 저장하는 데이터베이스 역할을 한다. *etcd는 서버 하나당 프로세스 1개만 사용할 수 있고, 보통 etcd 자체를 클러스터링한 후 여러 개 마스터 서버에 분산해서 실행해 데이터의 안정성을 보장하도록 구성한다. 안정적으로 쿠버네티스를 운영하기 위해서는 주기적으로 etcd에 있는 데이터를 백업하는 것이 좋다.
  • kube-apiserver: 쿠버네티스 클러스터의 API를 사용할 수 있도록 하는 컴포넌트이다. 클러스터로 온 요청이 유효한지 검증한다. 쿠버네티스는 마이크로서비스 아키텍처이므로 서로 분리된 컴포넌트 여러 개로 구성되어 있다. 쿠버네티스에 보내는 모든 요청은 kube-apiserver를 이용해서 다른 컴포넌트로 전달된다. * kube-apiserver는 수평적으로 확장할 수 있도록 설계되어 서버 여러 대에 여러 개 kube-apiserver를 실행해 사용할 수 있다.
  • kube-scheduler: 현재 클러스터 안에서 자원 할당이 가능한 노드 중 알맞은 노드를 선택해 새롭게 만든 파드를 실행한다. 파드는 처음 실행할 때 여러 가지 조건을 설정하며, kube-scheduler가 조건에 맞는 노드를 찾는다. *조건으로는 하드웨어 요구사항, 함께 있어야 하는 파드들을 같은 노드에 실행하는 어피니티(affinity)와 파드를 다양한 노드를 분산해서 실행하는 안티 어피니티 만족 여부, 특정 데이터가 있는 노드 할당 등이 있다.
  • kube-controller-manager: 쿠버네티스는 파드들을 관리하는 컨트롤러가 있다. 컨트롤러 각각은 논리적으로 개별 프로세스지만 복잡도를 줄이려고 모든 컨트롤러를 바이너리 파일 하나로 컴파일해 단일 프로세스로 실행한다. kube-controller-manager는 컨트롤러 각각을 실행하는 컴포넌트이다. 
  • cloud-controller-manager: 쿠버네티스의 컨트롤러들은 클라우드 서비스와 연결해 관리하는 컴포넌트이다. 관련 컴포넌트의 소스 코드는 각 클라우드 서비스에서 직접 관리한다. 보통 네 가지 컨트롤러 컴포넌트를 관리한다.
    • 노드 컨트롤러: 클라우드 서비스 안에서 노드를 관리하는 데 사용
    • 라우트 컨트롤러: 각 클라우드 서비스 안의 네트워크 라우팅을 관리하는 데 사용
    • 서비스 컨트롤러: 각 클라우드 서비스에서 제공하는 로드밸런서를 생성, 갱신, 삭제하는 데 사용
    • 볼륨 컨트롤러: 클라우드 서비스에서 생성한 볼륨을 노드에 연결하거나 마운트하는 등에 사용

2. 노드용 컴포넌트

노드용 컴포넌트는 쿠버네티스 실행 환경을 관리한다. 대표적으로 각 노드의 파드 실행을 관리하는 것이 있다. 컴포넌트에는 kubelet, kube-proxy, 컨테이너 런타임 등이 있다.
  • kubelet: 클러스터 안 모든 노드에서 실행되는 에이전트이다. 파드 컨테이너들의 실행을 직접 관리하고 kublet은 파드스펙(PodSpecs)이라는 조건이 담긴 설정을 전달 받아서 컨테이너를 실행하고 컨테이너가 정상적으로 실행되는지 헬스 체크를 진행한다. 단, 노드 안에 있는 컨테이너라도 쿠버네티스가 만들지 않은 컨테이너는 관리하지 않는다.
  • kube-proxy: 쿠버네티스는 클러스터 안에 별도의 가상 네트워크를 설정하고 관리한다. kube-proxy는 이런 가상 네트워크의 동작을 관리하는 컴포넌트로 호스트의 네트워크 규칙을 관리하거나 연결을 전달할 수도 있다.
  • 컨테이너 런타임: 컨테이너 런타임은 실제로 컨테이너를 실행시킨다. 가장 많이 알려진 런타임으로는 도커가 있고 containerd, runc 같은 런타임도 지원을 한다.

3. 애드온 (Addons)

애드온은 클러스터 안에서 필요한 기능을 실행하는 파드이다. 네임 스페이스는 kube-system이며 애드온으로 사용하는 파드들은 디플로이먼트, 리플리케이션 컨트롤러 등으로 관리한다.
  • 네트워킹 애드온: 쿠버네티스는 클러스터 안에 가상 네트워크를 구성해 사용할 때 kube-proxy외에 네트워킹 애드온(네트워크 플러그인)을 사용한다. AWS와 같은 클라우드 서비스에서 제공하는 쿠버네티스를 사용한다면 별도의 네트워킹 애드온을 제공한다. 하지만 쿠버네티스를 직접 서버에 구성한다면 네트워킹 관련 애드온을 설치해야 한다.
  • DNS 애드온: 클러스터 안에서 동작하는 DNS 서버이다. 쿠버네티스 서비스에 DNS 레코드를 제공하고 쿠버네티스 안에 실행된 컨테이너들은 자동으로 DNS 서버에 등록된다.
  • 대시보드 애드온: 쿠버네티스는 kubectl이라는 CLI를 많이 사용한다. 하지만 웹 UI로 쿠버네티스를 사용할 필요도 있기때문에 이때 쿠버네티스에서 제공하는 대시보드 애드온을 사용할 수 있다.
  • 컨테이너 자원 모니터링: 클러스터 안에서 실행 중인 컨테이너의 상태를 모니터링하는 애드온이다. CPU 및 메모리 사용량 같은 데이터들을 시계열 형식으로 저장해서 볼 수 있다.
  • 클러스터 로깅: 클러스터 안 개별 컨테이너의 로그와 쿠버네티스 구성 요소의 로그들을 중앙화한 로그 수집 시스템에서 모아서 보는 애드온이다.

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

kubernetes cluster를 관리하는 대부분의 동작은 kubectl이라는 CLI로 실행이 가능하다.

 

kubectl에서 지원하는 명령

  • 쿠버네티스 자원들 생성, 업데이트, 삭제 (create, update, delete)
  • debug, monitoring, trouble shooting (log, exec, cp, top, attach, ...)
  • 클러스터 관리 (cordon, top, drain, taint, ...)

이외에도 다양한 사용법이 있고 https://kubernetes.io/docs/reference/kubectl/cheatsheet/ 에서 확인 할수 있다.

 

*docker desktop을 사용하면 이미 kubectl이 설치되어 있으므로 별도의 설치 과정이 필요없다.


kubectl 기본 사용법

kubectl [command] [TYPE] [NAME] [flags]
  • command: 자원에 실행하려는 동작 (create, get, delete 등 사용 가능)
  • TYPE: 자원 타입 (pod, service, ingress 등 사용 가능)
  • NAME: 자원 이름
  • FLAG: 부가적으로 설정할 옵션 입력

간단한 에코 서버 동작

1. echoserver라는 이름의 파드 생성


2. 쿠버네티스의 파드들에 접근 해야할 때 필요한 echoserver라는 이름의 서비스 생성


3. 파드 생성 확인

$ kubectl get pods

 

  • NAME: 파드 이름 표시
  • READY: 숫자/숫자 형태로 파드의 준비 상태를 표시. (0/1 : 현재 파드는 생성되었으나 사용할 준비가 안됐음을 의미. 1/1: 파드가 생성되었고 사용할 준비가 끝났음을 의미)
  • STATUS: 파드의 현재 상태를 의미 (Running: 파드가 실행되었다는 의미)
  • RESTARTS: 해당 파드가 몇 번 재시작 했는지를 표시
  • AGE: 파드가 생성된 후 얼마나 시간이 지났는지 표시

4. 서비스 생성 확인

$ kubectl get service

 

  • NAME: 서비스 이름 표시
  • TYPE: 서비스 타입을 의미
  • CLUSTER-IP: 현재 클러스터 안에서 사용되는 IP
  • EXTERNAL-IP: 클러스터 외부에서 접속할 때 사용하는 IP
  • PORT(S): 해당 서비스에 접속하는 포트를 표시
  • AGE: 자원을 생성한 후 얼마나 시간이 지났는지 표시

5. 서버 실행

5-1. 에코 서버에서 접근할 수 있도록 로컬 컴퓨터로 포트포워딩

5-2. 에코 서버 실행

5-3. 에코서버 테스트


6. 에코 서버 실행 중 로그 수집

$ kubectl logs -f 파드이름

 

시간, HTTP 버전, 웹 브라우저와 운영체제 버전 등의 정보 확인 가능


7. 파드 및 서비스 삭제

$ kubectl delete pod 파드이름
$ kubectl delete service 서비스이름

 

7-1. 삭제 확인

 

 

<출처>
정원천 외 3명, 쿠버네티스 입문 90가지 예제로 배우는 컨테이너 관리 자동화 표준

 

+ Recent posts