1.1. 쿠버네티스에서 서비스 디스커버리를 제공하는 방법 #
다음 방법 등이 있다.
- ClusterIP
- ExternalName
- NodePort
- LoadBalancer
- Ingress
쿠버네티스에서 서비스 디스커버리 기능을 얻을 수 있는 방법은 모두 무엇이 있습니까?
쿠버네티스에서 서비스 디스커버리를 제공하는 방법은 크게 두 가지입니다.
1. Kubernetes 내장 DNS 서버 사용
- Kubernetes는 내장 DNS 서버를 제공합니다.
- 이를 이용하면 서비스 이름으로 서비스 IP를 찾을 수 있습니다.
- 예를 들어,
my-service
라는 이름으로 서비스를 생성하면,my-service.default.svc.cluster.local
라는 DNS 이름으로 해당 서비스의 IP 주소를 찾을 수 있습니다.
- 이 DNS 이름은 쿠버네티스 클러스터 내부에서만 사용할 수 있습니다.
- Kubernetes는 Service와 Endpoint라는 개념을 제공합니다.
- Service는 특정 Pod 집합에 대한 로드 밸런싱 기능을 제공하고, Endpoint는 해당 Service가 로드 밸런싱할 대상 Pod의 IP 주소와 포트 번호를 관리합니다.
- 이를 이용하여 서비스 디스커버리 기능을 구현할 수 있습니다.
- 예를 들어,
my-service
라는 이름으로 서비스를 생성하면,my-service
라는 이름의 Endpoint가 자동으로 생성되며, 이 Endpoint를 이용하여 로드 밸런싱할 Pod의 IP 주소와 포트 번호를 알 수 있습니다.
- 이 방법은 DNS를 이용하는 것보다 직접적으로 Endpoint를 이용하므로 더 빠른 속도로 서비스 디스커버리 기능을 제공할 수 있습니다.
Kubernetes Service의 다음 유형들은 무엇입니까? 1. ClusterIP, 2. ExternalName, 3. NodePort, 4. LoadBalancer, 5. Ingress
Kubernetes(K8S)에서 Service는 일종의 가상 IP 주소를 제공하는 자원으로서, Pod 집합에 대한 로드 밸런싱과 Service 디스커버리 기능을 제공합니다. Service는 다양한 유형이 있으며, 각각의 유형에 대해서 설명해드리겠습니다.
1. ClusterIP
- ClusterIP는 Kubernetes 클러스터 내에서만 접근 가능한 가상 IP 주소를 제공합니다.
- 이 유형의 Service는 Pod 집합에 대한 로드 밸런싱과 Service 디스커버리 기능을 제공합니다.
- 기본적으로 ClusterIP 유형의 Service는 TCP와 UDP 프로토콜을 지원하며, 포트는 사용자가 지정할 수 있습니다.
- ExternalName은 Kubernetes 클러스터 외부에 있는 서비스에 대한 DNS 레코드를 생성합니다.
- 이 유형의 Service는 로드 밸런싱 기능을 제공하지 않으며, 단순히 외부 서비스의 DNS 이름을 내부 DNS 레코드에 등록하는 역할을 합니다.
- NodePort는 각각의 노드의 IP 주소와 지정된 포트를 사용하여 Service를 외부에 노출시킵니다.
- 이 유형의 Service는 Kubernetes 클러스터 외부에서 접근 가능하며, 로드 밸런싱 기능도 제공합니다.
- 기본적으로 NodePort 유형의 Service는 TCP와 UDP 프로토콜을 지원하며, 포트는 사용자가 지정할 수 있습니다.
- LoadBalancer는 클라우드 공급자의 로드 밸런서를 사용하여 Service를 외부에 노출시킵니다.
- 이 유형의 Service는 NodePort와 마찬가지로 Kubernetes 클러스터 외부에서 접근 가능하며, 로드 밸런싱 기능을 제공합니다.
- 클라우드 공급자마다 지원하는 로드 밸런서 유형이 다르므로, 각각의 공급자에서 제공하는 로드 밸런서 유형을 확인해야 합니다.
- Ingress는 클러스터 외부에서 HTTP(S) 트래픽을 처리하는 Layer 7 로드 밸런서를 제공합니다.
- 이 유형의 Service는 HTTP(S) 프로토콜을 지원하며, HTTP(S) 요청의 경로나 호스트 이름을 기반으로 트래픽을 분배합니다.
- Ingress 자체는 로드 밸런서 기능만을 제공하며, 백엔드 Pod를 지정하는 역할은 Ingress Controller가 담당합니다.
1.2. 인그레스 Ingress #
인그레스(Ingress)는 서비스 앞쪽에 위치하며 스마트 라우터 및 클러스터 엔트리 포인트 역할을 하는 별도의 쿠버네티스 자원이다. 인그레스는 외부에서 접근 가능한 URL, 로드 밸런싱, SSL 종료, 이름 기반 가상 호스팅 등을 통해 서비스에 대한 HTTP 기반 접근을 제공한다.
예)
예)
apiVersion: extentions/v1beta1 kind: Ingress ... spec: backend: serviceName: ... servicePort: 8080
인그레스는 쿠버네티스에서 가장 강력하고 동시에 가장 복잡한 서비스 디스커버리 메커니즘이다.
K8S의 Ingress에 대해 더 자세히 알려주십시오.
Kubernetes(K8S)에서 Ingress는 클러스터 외부에서 HTTP(S) 트래픽을 처리하는 Layer 7 로드 밸런서를 제공하는 리소스입니다. Ingress는 다음과 같은 특징을 가집니다.
1. Ingress는 HTTP(S) 프로토콜만을 지원합니다.
- TCP, UDP 등 다른 프로토콜을 사용하는 서비스에 대해서는 Service 자원을 이용해야 합니다.
- 레이블 셀렉터를 이용하면 서비스 디스커버리 기능을 수행할 수 있으며, 적절한 포트와 프로토콜을 선택하여 백엔드 서비스에 연결합니다.
- 실제 트래픽을 처리하기 위해서는 Ingress Controller가 필요합니다.
- Ingress Controller는 Ingress 자원을 모니터링하고, Ingress 규칙에 따라 트래픽을 백엔드 서비스로 분배합니다.
- 각각의 규칙은 호스트 이름, 경로, 백엔드 서비스 등을 지정합니다.
- Ingress 규칙을 적용하기 위해서는 kubectl apply 명령을 사용합니다.
- HTTPS를 사용하는 경우에는 TLS 인증서를 Ingress 자원에 연결할 수 있습니다.
- Ingress 자원에는 Basic Authentication, OAuth2 등의 인증 기능을 추가할 수 있습니다.
- 클라우드 공급자의 로드 밸런서를 사용할 수 있으며, Nginx, Traefik, Istio 등의 오픈 소스 로드 밸런서를 사용할 수도 있습니다.
- Ingress 규칙을 사용하여 경로 기반 라우팅을 수행하면, 다중 레이어의 서비스 아키텍처를 간편하게 구성할 수 있습니다.
K8S Ingress로 서비스 디스커버리를 설정하는 예제 YAML 코드를 하나 보여주십시오.
다음은 Ingress 리소스를 이용하여 특정 호스트 이름과 경로를 갖는 HTTP 요청을 서비스로 전달하는 예제 YAML 코드입니다.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: example.com http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: name: http - path: /app2 pathType: Prefix backend: service: name: app2-service port: name: http
이 예제에서는
example.com
호스트 이름을 갖는 Ingress를 정의하고 있습니다. 이 Ingress는 /app1
과 /app2
경로를 갖는 HTTP 요청을 각각 app1-service
와 app2-service
라는 이름의 서비스로 전달합니다.또한,
pathType
필드를 이용하여 경로 타입을 지정할 수 있습니다. 이 예제에서는 Prefix
를 사용하여 경로가 /app1
또는 /app2
로 시작하는 모든 요청을 처리합니다.이 예제를 적용하기 위해서는,
kubectl apply
명령어를 사용하여 YAML 파일을 클러스터에 적용하면 됩니다.2.1. EnvVar #
설정을 외부화 하는 가장 쉬운 방법은 도커의 ENV 지시자나 도커파일에서 직접 정의할 수 있는 환경 변수에 설정 값을 배치하는 것이다. 쿠버네티스는 디플로이먼트 또는 레플리카세트 같은 컨트롤러의 파드 명세에서 직접 설정할 수 있다.
... spec: containers: ... env: - name: ... value: ...
EnvVar는 소규모의 변수와 간단한 설정에만 적합하다. 또, 어디에 변수가 정의되어 있는지 찾기 어렵다는 단점도 있다. 쿠버네티스는 단순 환경 변수보다 훨씬 유연한 전용 설정 자원인 컨피그맵(ConfigMap), 시크릿(Secret) 객체를 제공한다.
2.2.1. 컨피그맵에 설정된 환경 변수 세트 #
... spec: containers: - env: - name: ... valueFrom: configMapKeyRef: name: ... key: ...
... spec: containers: envFrom: - configMapKeyRef: name: ...
2.2.2. 컨피그맵을 볼륨으로 마운트 #
... spec: containers: ... volumes: - name: config-volume configMap: name: ...
2.3.1. 시크릿은 얼마나 안전한가? #
시크릿은 데이터를 Base64로 인코딩해 가지고 있다가 환경 변수나 마운트된 볼륨으로 파드에 전달하기 전에 디코딩된다. 간혹 시크릿을 보안 기능으로 착각하기도 하지만 Base64는 암호화 기법이 사용된 인코딩이 아니며 보안 측면에서 평문과 동일하다. 그렇다면 왜 시크릿이 컨피그맵보다 안전하다고 할까? 시크릿은 보안을 유지하기 위한 구현 세부사항이 많다. 끊임없이 개선이 이루어지는 중이지만 현재 시점에서는 크게,
1. 시크릿은 자신에게 접근한 파드가 실행 중인 노드에만 배포된다.
2. 노드에서 시크릿은 tmpfs 메모리에 저장되며, 실제 스토리지에는 기록되지 않고 파드가 제거될 때 함께 제거된다.
3. 시크릿은 etcd에 암호화된 형태로 저장된다.
2. 노드에서 시크릿은 tmpfs 메모리에 저장되며, 실제 스토리지에는 기록되지 않고 파드가 제거될 때 함께 제거된다.
3. 시크릿은 etcd에 암호화된 형태로 저장된다.
그러나 이런 주요 구현과 상관없이 루트 사용자로 시크릿에 접근하거나, 파드를 생성해서 시크릿에 마운트하는 등 다양한 방법으로 시크릿을 읽을 수 있다. 따라서 민감한 정보는 애플리케이션 레벨에서 별도의 암호화가 필요하다.
쿠버네티스 Secret 자원은 얼마나 안전합니까? 그리고 ConfigMap보다 어떤 점에서 안전하다고 볼 수 있습니까?
쿠버네티스 Secret 자원은 상대적으로 안전한 자원입니다. Secret 자원은 Kubernetes에서 제공하는 암호화된 방식으로 저장되며, 기본적으로 메모리 내에만 저장되며, 노드나 Pod에 대한 로깅과 같은 기능으로 보호됩니다. 또한, Secret 자원을 사용하는 컨테이너가 실행되는 노드에서만 액세스 가능하며, 컨테이너 내에서 암호화된 형태로만 사용되기 때문에 데이터가 보호됩니다.
ConfigMap과 비교하여 Secret 자원은 보안적인 측면에서 더 안전하다고 볼 수 있습니다. ConfigMap은 기본적으로 암호화되지 않은 평문으로 저장되며, ConfigMap에 저장된 데이터는 컨테이너 내에서 별도의 암호화 처리를 수행하지 않으면 노출될 수 있습니다. 따라서 ConfigMap에 저장된 민감한 정보를 사용하는 경우, 해당 정보를 보호하기 위해 별도의 보안 처리가 필요합니다.
그러나 Secret 자원도 완전히 안전한 것은 아닙니다. Secret 자원을 사용하는 컨테이너나 Pod가 해킹되면, Secret 자원에 저장된 민감한 정보가 노출될 수 있습니다. 따라서 Secret 자원을 사용할 때는 보안적인 측면을 고려하여 사용해야 합니다.
쿠버네티스 Secret은 Base64로 인코딩해 가지고 있을 뿐 암호화된 방법이 아니지 않습니까? 그렇다면 보안 측면에서 평문과 똑같은 것이 아닙니까?
맞습니다. 쿠버네티스 Secret은 기본적으로 Base64 인코딩된 형태로 저장되어 있습니다. 따라서 Secret에 저장된 데이터는 실제로 암호화되어 저장되는 것이 아니라, Base64로 인코딩된 평문 형태로 저장되는 것입니다.
그러나 이는 단순히 인코딩된 형태일 뿐, Base64로 인코딩된 데이터는 평문으로 보이지만 인코딩된 형태이기 때문에 인코딩을 해제하지 않는 이상 데이터를 읽을 수 없습니다. 따라서 Secret을 사용하는 컨테이너나 Pod가 해킹되더라도, Base64로 인코딩된 데이터를 해독하지 못한다면 노출될 가능성이 낮아지게 됩니다.
하지만 이는 보안을 위한 완벽한 방법이 아닙니다. 따라서 민감한 데이터를 저장하는 경우, Secret 자원을 사용하기 전에 암호화를 수행하고, 사용 시에도 별도의 보안 처리를 추가하는 것이 좋습니다. 이를 통해 보안성을 더욱 강화할 수 있습니다.
3.1. 수평 스케일링과 수직 스케일링의 차이 #
애플리케이션을 스케일링하는 것에는 2가지 주요 접근 방법이 있다.
1. 수평 스케일링
쿠버네티스에서 수평으로 스케일하는 것은 파드 레플리카를 더 많이 만드는 것이다.
쿠버네티스에서 수평으로 스케일하는 것은 파드 레플리카를 더 많이 만드는 것이다.
2. 수직 스케일링
수직으로 스케일하는 것은 파드가 관리하는 컨테이너를 실행하는 데 더 많은 자원을 제공하는 것이다.
수직으로 스케일하는 것은 파드가 관리하는 컨테이너를 실행하는 데 더 많은 자원을 제공하는 것이다.
※ 설명으로는 간단해 보이지만, 다른 서비스와 클러스터 자체에 영향을 미치지 않도록 오토스케일링을 위한 애플리케이션 설정을 생성하려면 상당한 시행착오를 거쳐야 한다.
3.2. 수동 수평 스케일링 #
이름에서 알 수 있듯이 쿠버네티스 운영자를 기반으로 최적의 설정을 점진적으로 튜닝한다. 오토스케일링이 없는 경우나 느리게 변화하는 로드를 처리하는 애플리케이션의 경우 사용할 수 있다. 자주 변경되고 적응이 필요한 동적 워크로드 패턴에는 적합하지 않다.
3.3. 수평 파드 오토스케일링 #
고정되어 있지 않으면서도 로드를 충분히 처리할 수 있는 용량을 보장하는 애플리케이션 용량을 정의할 수 있다. 가장 간단한 방법은
HorizonPodAutoscaler
(HPA)를 사용해 파드의 수를 수평으로 스케일하는 것이다.apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler ... spec: minReplicas: 1 maxReplicas: 5 scaleTargetRef: apiVersion: extentions/v1beta1 kind: Deployment ...
3.4. 수직 파드 오토스케일링 #
수평 스케일링은 스테이트리스 서비스에 지장을 덜 주기 때문에 수직 스케일링보다 선호되지만, 수직 스케일링은 실제 로드 기반으로 서비스의 실제 자원 요구를 튜닝할 때 유용하다.
파드의 모든 컨테이너는 CPU와 메모리 requests를 지정할 수 있으며 특정한 양의 자원을 보장한다. 즉 자원이 보장되지 않으면 파드가 스케줄되지 않는다. 메모리 요청을 너무 낮게 잡으면 노드가 더욱 꽉 채워지기 때문에 메모리 압박으로 메모리 부족 오류로 워크로드 축출이 일어날 수 있다. CPU limits를 너무 낮게 잡으면 CPU 고갈이나 성능이 저하된 워크로드가 발생할 수 있다. 반면에 너무 많은 자원을 requets하면 불필요한 용량이 할당되어 자원이 낭비된다. 클러스터의 사용률과 수평 스케일링의 효율성을 위해 가능한 정확하게 자원을 요청하는 것이 중요하며
VerticalPodAutoscaler
(VPA)가 이를 해결하는데 도움이 되며 실제 사용 피드백을 기반으로 자원을 조정 및 할당하는 과정을 자동화한다.apiVersion: poc.autoscaling.k8s.io/v1alpha1 kind: VerticalPodAutoscaler ... spec: selector: matchLables: app: ... updatePolicy: updateMode: "Off"
※ VPA와 HPA를 함께 사용하는 것은 오토스케일러가 아직까지는 서로를 인식하지 않아 원치 않은 동작이 발생될 수 있다. VPA는 아직 베타버전이며 향후 활발히 사용되면 변경될 가능성도 있다.
그러나 여전히 VPA는 자원 소비 효율성을 크게 향상 시킬 가능성이 있는 기능이다.
그러나 여전히 VPA는 자원 소비 효율성을 크게 향상 시킬 가능성이 있는 기능이다.
3.5. 클러스터 오토스케일링 #
새로운 노드를 스케일링한다. 쿠버네티스가 클라우드 컴퓨팅 인프라스트럭처상에서 실행 중일 때만 수행될 수 있다. 모든 주요 클라우드 제공업체는 쿠버네티스 오토스케일러(CA)를 제공한다. HPA와 VPA의 스케일링 기술은 클러스터 용량 한도 내에서만 탄력성을 제공한다. CA는 쿠버네티스 애드온으로 구동되고 요청된 CPU나 메모리를 충족시키는 용량을 갖춘 노드가 없다면 새로운 노드를 프로비전 한다. 최소 노드 수와 최대 노드 수가 설정되어야 한다.
4.2. Pod 안에서 네임스페이스 확인 방법 #
dat, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err != nil { panic(err) } fmt.Print(string(dat))
4.3. 배포 컨테이너 이미지 버전이 같을 때 강제로 업데이트 #
* 예를 들어 Deployment를 업데이트할 때 컨테이너 이미지 버전이 같더라도 강제로 업데이트 하고 싶으면 Deployment에서 사용하는 환경 변수를 변경하면, 쿠버네티스는 변경 사항이 있으므로 Deployment를 업데이트하게 된다. 가장 간단한 방법.
FORCE_RESTART 환경 변수에 현재 시간을 넣는다(이전 값에서 변경만 되면 어떤 값이든 괜찮다.).
kubectl set env deployment/<DEPLOYMENT_NAME> FORCE_RESTART="$(date)"
또는 Rolling Resart 지정된 자원을 완전히 재시작하는 명령어
kubectl rollout restart deployment <DEPLOYMENT_NAME>
4.4. Kubernetes YAML 자원 추가 삭제 #
`kubectl delete` 명령어를 사용하여 특정 자원을 삭제할 수 있습니다. 예를 들어, `Service` 자원을 삭제하려면 다음 명령어를 사용할 수 있습니다:
{{{#!bash
kubectl delete service
}}}
여기서 ``은 삭제하려는 `Service` 자원의 이름입니다. 이 명령어를 실행하면 해당 `Service` 자원이 삭제됩니다.
만약, YAML 파일을 사용하여 `Service` 자원을 생성했다면, 해당 YAML 파일을 편집하여 `Service` 자원을 삭제하거나, 다음 명령어를 사용하여 YAML 파일에서 `Service` 자원을 삭제하고 적용할 수 있습니다:
{{{#!bash
kubectl delete -f
}}}
여기서 ``은 삭제하려는 `Service` 자원이 포함된 YAML 파일의 경로입니다. 이 명령어를 실행하면 해당 YAML 파일에서 `Service` 자원이 삭제되고, 변경 사항이 Kubernetes 클러스터에 적용됩니다.
kubectl delete namespace 로 네임스페이스를 지우면 네임스페이스 안에 있던 모든 자원들이 지워집니까?
네,
kubectl delete namespace <namespace-name>
명령어를 사용하여 네임스페이스를 삭제하면 해당 네임스페이스 안에 있는 모든 자원들이 함께 삭제됩니다.기본적으로, 네임스페이스를 삭제하면 해당 네임스페이스 내부에 있는 모든 Kubernetes 자원(예: Pod, Deployment, Service 등)이 자동으로 삭제됩니다. 그러나 만약에 네임스페이스 안에 다른 네임스페이스가 있거나, 다른 네임스페이스를 참조하는 Kubernetes 자원이 있다면, 이러한 자원들은 삭제되지 않을 수 있습니다.
따라서,
kubectl delete namespace
명령어를 사용하기 전에, 해당 네임스페이스에 어떤 자원들이 있는지 확인하고, 필요한 경우 해당 자원들을 먼저 삭제해 주는 것이 좋습니다.delete namespace를 했는데도 Namespace 내의 리소스가 유지되는 경우는 무슨 이유가 있습니까?
kubectl delete namespace
명령어를 사용하여 Namespace를 삭제하면 해당 Namespace 내의 모든 리소스가 삭제되어야 합니다. 하지만 때로는 모든 리소스가 삭제되지 않는 경우가 있습니다.이러한 경우에는 일반적으로 다음과 같은 이유가 있습니다.
- Finalizers가 있는 리소스
Namespace 내에 있는 일부 리소스에는 Finalizers라는 삭제 프로세스가 있습니다. Namespace을 삭제하려면 이러한 리소스의 Finalizers를 제거해야합니다. 이를 위해서는kubectl edit
명령어를 사용하여 리소스의 YAML 파일을 편집하고, Finalizers를 수동으로 삭제해야합니다.
- 삭제 중인 리소스
일부 리소스가 삭제 중이라면, Namespace 삭제 명령이 완료될 때까지 삭제되지 않을 수 있습니다. 이 경우 명령이 완료되기를 기다리거나, 리소스 삭제를 완료한 후에 다시 시도해야합니다.
- 오류가 있는 리소스
일부 리소스가 삭제 중에 오류가 발생하면 Namespace 내의 모든 리소스가 삭제되지 않을 수 있습니다. 이 경우 오류를 해결한 후에 다시 시도해야합니다.
kubectl delete namespace
명령어를 사용하여 Namespace을 삭제하기 전에 해당 Namespace 내의 리소스를 확인하고, 문제가 발생하면 해당 문제를 해결해야합니다.4.5. Well-Known Labels을 임의로 지워도 되나? #
K8S의 Well-Known Labels들(예를 들어 node.kubernetes.io/instance-type과 같은)은 언제 생성됩니까? 함부로 지우면 안되겠지요?
Kubernetes에서 Well-Known Labels은 Kubernetes 자체와 관련된 정보를 제공하는 레이블입니다. 이러한 레이블은 시스템 구성 요소와 관련된 정보를 포함하고 있으므로 Kubernetes에서 자동으로 생성됩니다.
예를 들어,
node.kubernetes.io/instance-type
레이블은 노드 인스턴스 유형과 관련된 정보를 포함하고 있습니다. 이 레이블은 AWS, GCE, Azure 등의 클라우드 제공업체에서 자동으로 생성되며, 노드 유형과 연결된 정보를 포함합니다.일반적으로 이러한 Well-Known Labels은 시스템에서 자동으로 생성되므로, 삭제하면 Kubernetes의 일부 기능이 영향을 받을 수 있습니다. 예를 들어,
kubernetes.io/hostname
레이블은 각 노드의 호스트 이름을 포함하고 있으며, 이 레이블이 없으면 Kubernetes에서 노드를 식별할 수 없습니다.따라서 Well-Known Labels을 함부로 지우면 안됩니다. 이러한 레이블은 Kubernetes 시스템 구성의 일부이며, 시스템 구성 요소와 상호 작용하는 데 필요합니다. 필요한 경우 이러한 레이블을 수정할 수는 있지만, 삭제하면 안됩니다.