이 문서에서는 베어메탈용 GKE에 대한 사용자, 하이브리드 또는 독립형 클러스터에서 Kubernetes 인그레스 객체를 만드는 방법을 보여줍니다. 인그레스는 각각 포드 집합과 연결된 서비스 하나 이상과 연결됩니다.
시작하기 전에
클러스터에서 관리자 워크스테이션으로 SSH 연결을 가져옵니다.
배포 만들기
배포의 매니페스트는 다음과 같습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
selector:
matchLabels:
greeting: hello
replicas: 3
template:
metadata:
labels:
greeting: hello
spec:
containers:
- name: hello-world
image: "gcr.io/google-samples/hello-app:2.0"
env:
- name: "PORT"
value: "50000"
- name: hello-kubernetes
image: "gcr.io/google-samples/node-hello:1.0"
env:
- name: "PORT"
value: "8080"
이 실습을 진행하면서 배포 매니페스트에 대해 알아야 할 중요한 사항은 다음과 같습니다.
배포에 속한 각 pod에는
greeting: hello
라벨이 있습니다.각 pod에는 2개의 컨테이너가 있습니다.
env
필드는hello-app
컨테이너가 TCP 포트 50000에서 리슨하고node-hello
컨테이너가 TCP 포트 8080에서 리슨하는 것을 지정합니다.hello-app
의 경우 소스 코드를 보면PORT
환경 변수의 효과를 확인할 수 있습니다.
hello-deployment.yaml
파일에 매니페스트를 복사하고 배포를 만듭니다.
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
CLUSTER_KUBECONFIG
를 클러스터의 kubeconfig 파일 이름으로 바꿉니다.
서비스에 배포 노출
클라이언트가 배포 pod로 요청을 보내는 안정적인 방법을 제공하려면 서비스를 만듭니다.
다음은 클러스터 내부 클라이언트에 배포를 노출하는 서비스의 매니페스트입니다.
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
type: ClusterIP
selector:
greeting: hello
ports:
- name: world-port
protocol: TCP
port: 60000
targetPort: 50000
- name: kubernetes-port
protocol: TCP
port: 60001
targetPort: 8080
매니페스트를 hello-service.yaml
파일에 복사하고 서비스를 만듭니다.
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml
CLUSTER_KUBECONFIG
를 클러스터의 kubeconfig 파일 이름으로 바꿉니다.
서비스를 확인합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml
서비스에 제공된 clusterIP
의 값이 출력에 표시됩니다.
예를 들면 다음과 같습니다.
apiVersion: v1
kind: Service
metadata:
annotations:
...
spec:
clusterIP: 10.96.14.249
clusterIPs:
- 10.96.14.249
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
selector:
greeting: hello
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
위 출력에서 ports
필드는 이름이 각각 world-port
및 kubernetes-port
인 ServicePort
객체의 배열입니다. 서비스 필드에 대한 자세한 내용은 Kubernetes 문서의 ServiceSpec을 참조하세요.
클라이언트에서 서비스를 호출할 수 있는 방법은 다음과 같습니다.
world-port
사용: 클러스터 노드 중 하나에서 실행되는 클라이언트가port
의clusterIP
에 요청을 전송합니다. 이 예시에서는 10.96.14.249:60000입니다. 요청은targetPort
의 구성원 포드로 전달됩니다. 이 예시에서는POD_IP_ADDRESS:50000
입니다.kubernetes-port
사용: 클러스터 노드 중 하나에서 실행되는 클라이언트가port
의clusterIP
에 요청을 전송합니다. 이 예시에서는 10.96.14.249:60001입니다. 요청은targetPort
의 구성원 포드로 전달됩니다. 이 예시에서는POD_IP_ADDRESS:8080
입니다.
인그레스 구성요소
인그레스와 관련된 몇 가지 클러스터 구성요소는 다음과 같습니다.
istio-ingress
배포. 인그레스 프록시입니다. 인그레스 프록시는 인그레스 객체에 지정된 규칙에 따라 트래픽을 내부 서비스로 전달합니다.istio-ingress
서비스. 이 서비스는istio-ingress
배포를 노출합니다.istiod
배포. 인그레스 컨트롤러입니다. 인그레스 컨트롤러는 인그레스 객체 생성을 감시하고 그에 따라 인그레스 프록시를 구성합니다.
이러한 모든 Istio 클러스터 내 구성요소는 gke-system
네임스페이스에 설치됩니다. 이 네임스페이스는 전체 Istio/Anthos Service Mesh 설치와 충돌하지 않습니다.
인그레스 만들기
인그레스의 매니페스트는 다음과 같습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
my-ingress.yaml
이라는 파일에 매니페스트를 복사하고 인그레스를 만듭니다.
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml
사용자 클러스터를 만들 때 클러스터 구성 파일에서 loadbalancer.ingressVIP
값을 지정합니다. 이 IP 주소는 클러스터 부하 분산기에서 구성됩니다. 인그레스를 만들면 외부 IP 주소와 동일한 이 VIP가 인그레스에 지정됩니다.
클라이언트가 사용자 클러스터 인그레스 VIP로 요청을 전송하면 요청이 부하 분산기로 라우팅됩니다. 부하 분산기는 istio-ingress
서비스를 사용하여 사용자 클러스터에서 실행되는 인그레스 프록시로 요청을 전달합니다. 인그레스 프록시는 요청 URL의 경로에 따라 요청을 다른 백엔드로 전달하도록 구성됩니다.
/greet-the-world
경로
인그레스 매니페스트에서 /greet-the-world
경로가 serviceName: hello-service
및 servicePort: 60000
과 연결되어 있음을 나타내는 규칙을 확인할 수 있습니다. 60000은 hello-service
서비스의 world-port
섹션에 있는 port
값입니다.
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
인그레스 서비스는 요청을 clusterIP
:50000으로 전달합니다. 그런 다음 요청은 hello-service
서비스의 구성원 포드 중 하나로 이동합니다. 해당 포드의 포트 50000에서 리슨하는 컨테이너에 Hello World!
메시지가 표시됩니다.
/greet-kubernetes
경로
인그레스 매니페스트에서 /greet-kubernetes
경로가 serviceName: hello-service
및 servicePort: 60001
과 연결되어 있음을 나타내는 규칙을 확인할 수 있습니다. 60001은 hello-service
서비스의 kubernetes-port
섹션에 있는 port
값입니다
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
인그레스 서비스는 요청을 clusterIP
: 8080으로 전달합니다. 그런 다음 요청은 hello-service
서비스의 구성원 포드 중 하나로 이동합니다. 해당 포드의 포트 8080에서 리슨하는 컨테이너에 Hello Kubernetes!
메시지가 표시됩니다.
인그레스 테스트
/greet-the-world
경로를 사용하여 인그레스를 테스트합니다.
curl CLUSTER_INGRESS_VIP/greet-the-world
CLUSTER_INGRESS_VIP
를 인그레스의 외부 IP 주소로 바꿉니다.
출력에 Hello, world!
메시지가 표시됩니다.
Hello, world!
Version: 2.0.0
Hostname: ...
/greet-kubernetes
경로를 사용하여 인그레스를 테스트합니다.
curl CLUSTER_INGRESS_VIP/greet-kubernetes
출력에 Hello, Kubernetes!
메시지가 표시됩니다.
Hello Kubernetes!
번들 인그레스 사용 중지
베어메탈용 GKE와 함께 번들로 제공되는 인그레스는 인그레스 기능만 지원합니다. Istio 또는 Anthos Service Mesh와 통합할 수 있습니다. 이러한 제품은 상호 TLS(mTLS), 서비스 간 인증 관리 기능, 워크로드 관측 가능성과 같이 모든 기능을 갖춘 서비스 메시의 추가 이점을 제공합니다. Istio 또는 Anthos Service Mesh와 통합하는 경우 번들 인그레스 기능을 사용 중지하는 것이 좋습니다.
클러스터 구성 파일의 spec.clusterNetwork.bundledIngress
필드를 사용하여 번들 인그레스를 사용 설정하거나 중지할 수 있습니다.
이 필드는 버전 1.13.0 이상 클러스터에서만 사용할 수 있습니다. bundledIngress
필드의 기본값은 true
이며 생성된 클러스터 구성 파일에 없습니다. 이 필드는 변경 가능하며 버전 1.13.0 이상의 클러스터를 만들거나 업데이트할 때 변경할 수 있습니다. 클러스터를 버전 1.13.0 이상으로 업그레이드하는 경우 이 필드를 지정할 수도 있습니다.
다음 샘플 클러스터 구성 파일은 번들 인그레스 기능을 사용 중지하도록 클러스터를 구성하는 방법을 보여줍니다.
apiVersion: v1
kind: Namespace
metadata:
name: cluster-hybrid-basic
---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
name: hybrid-basic
namespace: cluster-hybrid-basic
spec:
type: hybrid
profile: default
anthosBareMetalVersion: 1.13.0
gkeConnect:
projectID: project-fleet
controlPlane:
nodePoolSpec:
nodes:
- address: 10.200.0.2
clusterNetwork:
bundledIngress: false
pods:
cidrBlocks:
- 192.168.0.0/16
services:
cidrBlocks:
- 10.96.0.0/20
...
인그레스에 HTTPS 설정
클라이언트의 HTTPS 요청을 수락하려면 인그레스 프록시에 인증서가 있어야 인그레스 프록시가 클라이언트에게 ID를 증명할 수 있습니다. 또한 이 프록시에 비공개 키가 있어야 HTTPS 핸드셰이크를 완료할 수 있습니다.
다음 예시에서 이러한 항목이 사용됩니다.
인그레스 프록시: HTTPS 핸드셰이크에 참여한 후
hello-service
서비스의 구성원 포드에 패킷을 전달합니다.hello-service
서비스의 도메인: 예시 조직의 altostrat.com
다음 단계를 따르세요.
루트 인증서와 비공개 키를 만듭니다. 이 예시에서는 루트 CA 예시 조직에서
root.ca.example.com
의 루트 인증 기관을 사용합니다.openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \ '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \ -out root-ca.crt
인증서 서명 요청을 만듭니다.
openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \ "/CN=altostrat.com/O=Example Org"
인그레스 프록시에 대해 제공 인증서를 만듭니다.
openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \ -in server.csr -out server.crt
이제 다음 인증서 및 키가 생성되었습니다.
root-ca.crt
: 루트 CA의 인증서root-ca.key
: 루트 CA의 비공개 키server.crt
: 인그레스 프록시에 대한 제공 인증서server.key
: 인그레스 프록시의 비공개 키
제공 인증서 및 키가 포함된 Kubernetes 보안 비밀을 만듭니다.
kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \ --namespace gke-system
결과 보안 비밀은 이름이
example-server-creds
로 지정됩니다.
배포 및 서비스 만들기
이 가이드의 HTTP 부분에서 배포와 서비스를 만든 경우 이를 그대로 둡니다. 만들지 않았으면 지금 HTTP에 설명된 단계를 수행하여 만듭니다.
인그레스 만들기
이전에 HTTP 부분에서 인그레스를 만들었으면 인그레스를 삭제한 후 계속 진행합니다.
인그레스를 삭제합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
이전에 만든 서비스의 트래픽을 처리하려면 tls
섹션이 있는 새 인그레스를 만듭니다. 이렇게 하면 클라이언트와 인그레스 프록시 간에 HTTPS가 사용 설정됩니다.
인그레스의 매니페스트는 다음과 같습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-2
spec:
tls:
- hosts:
- altostrat.com
secretName: example-server-creds
rules:
- host: altostrat.com
http:
paths:
- path: /greet-the-world
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60000
- path: /greet-kubernetes
pathType: Exact
backend:
service:
name: hello-service
port:
number: 60001
my-ingress-2.yaml
이라는 파일에 매니페스트를 저장하고 인그레스를 만듭니다.
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
다음을 테스트하여 확인합니다.
/greet-the-world
경로를 테스트합니다.curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP\ https://altostrat.com/greet-the-world \ --cacert root-ca.crt
출력:
Hello, world! Version: 2.0.0 Hostname: hello-deployment-5ff7f68854-wqzp7
/greet-kubernetes
경로를 테스트합니다.curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \ https://altostrat.com/greet-kubernetes --cacert root-ca.crt
출력:
Hello Kubernetes!
LoadBalancer 서비스 만들기
LoadBalancer
유형은 NodePort
유형의 확장입니다. 따라서 LoadBalancer
유형의 서비스에 클러스터 IP 주소 및 하나 이상의 nodePort
값이 포함됩니다.
기본적으로 Kubernetes는 LoadBalancer 서비스에 노드 포트를 할당합니다. 이러한 할당은 클러스터에 할당된 2,768개의 사용 가능한 노드 포트를 빠르게 소진할 수 있습니다. 노드 포트를 저장하려면 LoadBalancer 서비스 사양에서 allocateLoadBalancerNodePorts
필드를 false
로 설정하여 부하 분산기 노드 포트 할당을 사용 중지합니다. 이렇게 설정하면 Kubernetes가 LoadBalancer 서비스에 노드 포트를 할당할 수 없습니다. 자세한 내용은 Kubernetes 문서의 부하 분산기 NodePort 할당 중지를 참조하세요.
다음은 노드 포트를 사용하지 않는 서비스를 만드는 매니페스트입니다.
apiVersion: v1
kind: Service
metadata:
name: service-does-not-use-nodeports
spec:
selector:
app: my-app
type: LoadBalancer
ports:
- port: 8000
# Set allocateLoadBalancerNodePorts to false
allocateLoadBalancerNodePorts: false
삭제
인그레스를 삭제합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
INGRESS_NAME
을 my-ingress
또는 my-ingress-2
와 같은 인그레스 이름으로 바꿉니다.
서비스를 삭제합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
배포를 삭제합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
LoadBalancer 서비스를 삭제합니다.
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports