초보개발자의 Kubernetes 사용해보기 #3(feat. GCP)

이현빈·2020년 6월 28일
1

HTTPS 적용해보기

참고한 곳

SSL 프로토콜은 간단하게 웹서버와 브라우저 사이의 보안을 위해 만들어졌다. HTTP에 SSL 적용을 한 것이 https 통신이라고 생각하면 편하다. 이러한 암호화 통신을 하기 위해선 SSL 인증서가 필요하다.

SSL 인증서를 생성하고 공인된 기관에 인증을 받는 데에는 letsencrypt를 이용하는 등 여러가지 방법이 있다. GKE를 사용하여 프로젝트를 진행하면 managedcertificate 오브젝트를 사용하여 SSL 인증을 쉽게 받을 수 있다. 관련하여서는 이곳을 참고하면 될 것이다. 하지만 내가 작성한 애플리케이션에서는 websocket 통신시 gke의 인그레스와 managedcertificate 오브젝트를 사용하면 소켓이 자꾸 여러개 생성되는 문제가 생겼다. 따라서 nginx-ingress-controller와 letsencrypt를 사용하여 https를 적용하는 방법에 대해서 알아보도록 하겠다.

1. 선행 요구사항

  • 기본적인 쿠버네티스의 오브젝트들에 대한 이해
  • 쿠버네티스 클러스터와 kubectl 준비
  • 도메인 네임 필수!!

2. 샘플 앱 배포하기

http와 https를 비교하기 위해 두 개의 Deployment와 Service를 정의한다.

# echo1.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo1
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo1
spec:
  selector:
    matchLabels:
      app: echo1
  replicas: 2
  template:
    metadata:
      labels:
        app: echo1
    spec:
      containers:
      - name: echo1
        image: hashicorp/http-echo
        args:
        - "-text=echo1"
        ports:
        - containerPort: 5678
# echo2.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo2
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo2
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo2
spec:
  selector:
    matchLabels:
      app: echo2
  replicas: 1
  template:
    metadata:
      labels:
        app: echo2
    spec:
      containers:
      - name: echo2
        image: hashicorp/http-echo
        args:
        - "-text=echo2"
        ports:
        - containerPort: 5678

다음 명령어를 사용하여 정의한 오브젝트들을 생성한다.

kubectl apply -f echo1.yaml
kubectl apply -f echo2.yaml

생성한 오브젝트들을 확인해본다.

kubectl get svc, deploy

3. Ingress Nginx 준비하기

다음 명령어를 사용해 인그레스 컨트롤러를 생성한다. 설치가 안될 경우 파일이 깃허브에서 삭제되었거나 변경되었을 수도 있으니 이곳을 참고하여 다시 설치하도록 한다.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml

Service 오브젝트를 수정하고 싶으면 wget을 사용하거나 직접 해당 링크에서 파일을 다운받은 후 원하는 곳에서 수정하면 된다. 참고한 레퍼런스에서는 Service 오브젝트에서 externalTrafficPolicy을 Local이 아닌 Cluster라고 바꾸라고 하였지만 무조건 해야할 필요는 없고 해당 옵션을 알아본 후 자신의 상황에 맞춰서 바꾸길 추천한다.

다음은 Ingress 오브젝트를 정의할 차례이다.

# echo_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"    
spec:
  rules:
  - host: yourdomain
    http:
      paths:
      - path: /echo1
      	backend:
          serviceName: echo1
          servicePort: 80
  - host: yourdomain
    http:
      paths:
      - path: /echo2
      	backend:
          serviceName: echo2
          servicePort: 80

오브젝트를 생성하고 확인해본다.

kubectl apply -f echo_ingress.yaml
kubetcl get ing

Ingress 오브젝트가 정상적으로 생성되었다면, 할당받은 external-ip를 도메인과 포트포워딩 작업을 통해 맞춰주도록 하자.

4. Cert-manager

다음 단계는 cert-manager를 설치하는 것이다. SSL 인증서를 발급받기 위해 반드시 필요하다.

kubectl create namespace cert-manager
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml

kubectl get pods --namespace cert-manager 명령어로 확인 가능하다.

ClusterIssuer

두 개의 Issuer 오브젝트를 만들것이다. 하나는 정상적으로 작동하기 위해 테스트해보는 Test Issuer이고 하나는 실제 배포에 사용되는 Production Issuer이다. Issuer 오브젝트가 현재 무엇인지는 정확히 알지 못하지만 SSL 인증을 받는데 필요한 오브젝트라고만 기억해두자.

자신의 이메일 주소를 사용하여 Issuer 오브젝트를 정의해본다.

# staging_issuer.yaml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: me@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class:  nginx
# prod_issuer.yaml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: me@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class:  nginx

정의한 오브젝트들을 생성한다.

kubectl apply -f staging_issuer.yaml
kubectl apply -f prod_issuer.yaml

위에서 생성한 Ingress 오브젝트를 수정해야한다.

# echo_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # 변경된 항목. 적용할 ClusterIssuer의 이름을 넣어준다.
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
spec:
  # SSL 인증을 위해 추가된 항목
  tls:
  - hosts:
    - yourdomain
    secretName: letsencrypt-staging
  rules:
  - host: yourdomain
    http:
      paths:
      - path: /echo1
      	backend:
          serviceName: echo1
          servicePort: 80
  - host: yourdomain
    http:
      paths:
      - path: /echo2
      	backend:
          serviceName: echo2
          servicePort: 80

수정한 오브젝트를 적용한다.

kubectl apply -f echo_ingress.yaml

인증서가 발행될 때까지 몇 분의 시간이 소요된다. 다음 명령어를 사용해 인증서가 발행되었는지 확인한다.

kubectl describe certificate letsencrypt-staging

'Certificate issued successfully' 문구를 보면 정상적으로 수행된 것이다. 브라우저에서 https로 접속하여 인증서를 눌러 확인해보면 가짜 인증서가 발행된 것을 볼 수 있다.

이제 issuer를 staging에서 prod로 바꾸면 정상적으로 인증서가 적용된 것을 확인할 수 있다.

profile
익숙해질때까지 한걸음씩

0개의 댓글