쿠버네티스에서 어플리케이션을 배포하는 방법은 크게 다음과 같은 방법을 따르면 된다.
쿠버네티스는 기본적으로 컨테이너 런타임에 이미지의 경로를 전달하고, 컨테이너 런타임에서 이미지를 바탕으로 팟을 생성해 서비스를 하는 방식으로 운영이 된다.
쿠버네티스 클러스터에서 어플리케이션을 정상적으로 실행 시키기 위해서는 정상적으로 실행이 되는 도커 이미지가 필요하다.
도커 이미지를 생성하는 방법은 언어마다 다르나 버택스 어플리케이션의 경우는 아래와 같이 Dockerfile을 생성하여 docker build -t <이미지 이름> -f Dockerfile .로 생성할 수 있다.
# Extend vert.x image
FROM openjdk:11
ENV VERTICLE_FILE evCloud_tcp_server-1.0.0-SNAPSHOT-fat.jar
# Set the location of the verticles
ENV VERTICLE_HOME /usr/verticles
EXPOSE 2237
EXPOSE 2238
# Copy your verticle to the container
COPY build/libs/$VERTICLE_FILE $VERTICLE_HOME/
# Launch the verticle
WORKDIR $VERTICLE_HOME
ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $VERTICLE_FILE"]
아마존에서 제공해주는 Dockerhub으로 보면 간단하게 이해할 수 있으며, 생성한 도커 이미지를 푸시하고 풀 받을 수 있는 레포지토리다.
AWS console에서 Elastic Container Registry로 이동 후 '리포지토리 생성' 후 푸시 명령어에 맞게 도커 이미지의 태그를 변경 후 푸시를 하면 된다.
이미지를 ECR에 올려두었다면, 쿠버네티스 클러스터 내에서 정상적으로 실행을 시키려면 해당 이미지를 내려 받아야한다.
Pod을 직접 생성하여 해당 이미지를 받게 할 수 있지만, 서비스 도중 pod이 죽는 경우가 많이 발생한다.
그렇기 때문에 pod을 직접 생성하는 방법은 권장되는 방법은 아니다.
다음은 deployment, service와 ingress yaml 파일의 예시다.
적용은 kubectl apply -f <yaml파일 이름>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coupon-dev
namespace: tardis
spec:
replicas: 1
selector:
matchLabels:
app: coupon-dev
template:
metadata:
labels:
app: coupon-dev
spec:
containers:
- name: coupon-dev
image: ECR 주소
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: config-coupon-dev
---
apiVersion: v1
kind: Service
metadata:
namespace: tardis
name: coupon-dev
spec:
type: ClusterIP
ports:
- name: http
port: 8080
selector:
app: coupon-dev
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: coupon-dev-fanout
namespace: tardis
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: external-nginx
rules:
- host: aws-dev.evcoupon.co.kr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: coupon-dev
port:
number: 8080
부수적으로 pod에서 쓸 수 있는 config를 같은 방식으로 configmap과 secret으로 생성하여 주입할 수 있는데, 이 역시 어플리케이션 별로 조금씩 상이한 부분이 있기 때문에 이는 각 언어와 프레임워크 별로 조금씩 상이한 부분이 있기 때문에 관련 문서들을 찾아보는 편이 빠를 것 같다.
잉그래스를 사용해 외부 http 트래픽을 원하는 pod에 전달해주는 것은 가능하나, https 트래픽을 전달하기 위해서는 tls 인증이 필요하다.
쿠버네티스 클러스터에 tls를 적용하기 위해서는 인증서를 관리하는 패키지인 cert-manager, 그리고 무료로 발급 가능하고 자동적으로 갱신되는 인증서인 letsencrypt인증서가 필요하다.
설치는 cert-manager을 관리하는 jetstack의 깃헙에서 받을 수 있다.
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.0.1/cert-manager.yaml
인증서를 발급 받는 유저를 생성하는 과정으로 아래 yaml파일을 참고하면 될 것 같다.
apiVersion: cert-manager.io/v1
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: adamlee@tardistechnology.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: external-nginx
해당 cluster issuer 정보를 갖고 certificate을 발급 받을 수 있는데, 아래 yaml과 같이 생성을 할 수 있다.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: home.tardistechnology.com
namespace: tardis
spec:
secretName: home.tardistechnology.com-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: home.tardistechnology.com
dnsNames:
- home.tardistechnology.com
발급을 받은 certificate을 ingress에 적용시킬 수 있는데, ingress의 spec 밑에 다음과 같은 정보를 추가해주고 적용을 하면 정상적으로 적용이 되는 것을 확인할 수 있다.
tls:
- hosts:
- home.tardistechnology.com
secretName: home.tardistechnology.com-tls
또한 annotation 부분에 다음과 같은 정보 역시 추가해 주면 정상적으로 발급받은 인증서가 적용이 되어 https 방식의 통신을 정상적으로 할 수 있는 것을 확인할 수 있다.
nginx.ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: external-nginx
cert-manager.io/cluster-issuer: letsencrypt-prod