nginx(tls 인증서)+webapp을 포함한 도커를 kubernetes에서 사용하려면 

k8s 443(ingress)-> 443(service) -> 443 (docker)로 적용되야 하는데.. 이는 처음부터 잘 작동되지 않는다. k8s ingress와 service에 tls인증서가 없고 docker 단에서 처리되야 하기에... 이슈가 있다.


만약 이를 동작하게 하려면 ssl paththough라는 기술을 사용해야 한다.



kubernetes (쿠버네티스) ssl passthrough 관련 정보


https://medium.com/ibm-cloud/how-to-enable-ssl-passthrough-in-ibm-cloud-private-d33e5d442d96


https://github.com/kubernetes/ingress-nginx/issues/803


https://www.thomas-zuehlke.de/2019/02/setup-kubernetes-ingress-with-ssl-passthrough/




Posted by 김용환 '김용환'

댓글을 달아 주세요


helm 차트 삭제 (helm delete) 삭제하는 예시



$ helm ls --all --short $(kubectl config current-context) | xargs -L1 helm delete

삭제


$ helm ls --all $(kubectl config current-context)

NAME                  REVISION UPDATED                  STATUS  CHART                   APP VERSION NAMESPACE

google-production-context 25       Wed Sep 11 20:31:07 2019 DELETED prometheus 10.19.0      monitoring



$ helm del --purge  $(kubectl config current-context)

release "google-production-context" deleted


--purge를 해야 깔끔히 정리한다 .




helm 차트 추가하기(with 사설 저장소 추가)



$ helm repo add google-community http://charts.google.io

$ helm repo update


$ helm install --name $(kubectl config current-context) google-community/k8s-prometheus




Posted by 김용환 '김용환'

댓글을 달아 주세요



kubernetes의 Service.spec.type의 기본값은 ClusterIP이다. 

clusterip는 iptables 기반이다.  k8s 서비스를 클러스터 내부 IP에 노출하고 클러스터 내에서만 서비스에 도달할 수 있게 한다. 


(참고 : kubernetes)





이외 3가지가 더 있다. 

Ingress를 사용하지 않으면 Nodeport를 사용한다. 

하지만 개인적으로 Ingress를 두는 것이 운영하는 데 훨씬 도움이 되는 것 같다. 


LoadBalancer는 LBaaS로 사용자가 로드 밸런서를 추가할 수 있는 형태이다.


아마존의 경우는 아래와 같이 사용할 수 있다. 

https://aws.amazon.com/ko/blogs/opensource/network-load-balancer-nginx-ingress-controller-eks/




https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md




실제 사용 예를 살펴본다. 아래 ingress-nginx에 잘 나와 있다. 

https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md


type이 LoadBalancer 타입일 경우에는 어떻게 설정되어 있는지 확인할 수 있다. 


aws L4 LB를 사용하려면 다음과 같이 사용한다. 

https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/service-l4.yaml

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  annotations:
    # Enable PROXY protocol
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
    # Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
    # NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
    # increased to '3600' to avoid any potential issues.
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: https

---



l7인 경우는 다음과 같이 설정한다. 

https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/aws/service-l7.yaml


kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  annotations:
    # replace with the correct value of the generated certificate in the AWS console
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-west-2:XXXXXXXX:certificate/XXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX"
    # the backend instances are HTTP
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
    # Map port 443
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
    # Ensure the ELB idle timeout is less than nginx keep-alive timeout. By default,
    # NGINX keep-alive is set to 75s. If using WebSockets, the value will need to be
    # increased to '3600' to avoid any potential issues.
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: http

---






마지막으로 EnternalName은 CoreDNS에서 지원하는 CNAME 값이다. 







지금까지 설명한 내용은 다음 문서에 있다. 

https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types


  • ClusterIP: Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable from within the cluster. This is the default ServiceType.
  • NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You’ll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
  • LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.
  • ExternalName: Maps the Service to the contents of the externalName field (e.g. foo.bar.example.com), by returning a CNAME record

    with its value. No proxying of any kind is set up.



Posted by 김용환 '김용환'

댓글을 달아 주세요



(이미지만 참고) Refernece : https://www.youtube.com/watch?v=TFAASAfO_gg





외부 또는 중요한 내부 서버와 통신할 때 ACL을 뚫어서 통신할 때가 있다.


현재 kubernetes 클러스터의 서버(node)만 보고 ACL을 뚫으면 나중에 새로운 서버가 추가되고 새로운 장비에 실행된 pod에서는 막힌 부분 때문에 에러가 발생할 것이다.



특정 장비(node)에만 pod를 배포하면 이슈가 없을 것이다.



이에 대한 2가지 방법이 있다.


1. pod 적용


이 방식은 공식 문서에 있는 방식이다. 



https://kubernetes.io/docs/concepts/configuration/assign-pod-node/






2. deployment 적용




$ kubectl label nodes google-k8s-worker001 server=google-config

$ kubectl label nodes google-k8s-worker002 server=google-config



$ kubectl get nodes -l server=google-config
NAME               STATUS   ROLES   AGE   VERSION
google-k8s-worker001   Ready    node    14d   v1.11.5

google-k8s-worker002   Ready    node    14d   v1.11.5
 


apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: google-config
namespace: production
spec:
selector:
matchLabels:
app: google-config
replicas: 2
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 3
template:
metadata:
labels:
app: google-config
spec:
nodeSelector:
server: google-config

containers:
- name: google-config
image: dockerhub-url
imagePullPolicy: Always


테스트 방법은 다음과 같다. 

google-config를 1번 2번 장비에서만 실행되게 했다.


$ kubectl delete pod $(kubectl get pods | grep config | awk '{print $1}') 


삭제된 pod가 계속 1번 2번 장비에서 실행되는지 확인한다.




Posted by 김용환 '김용환'

댓글을 달아 주세요



도커 파일에서 env를 사용할 때 항상 env를 사용할 수 없다.

RUN, CMD, ENTRYPOINT에만 사용할 수 있다.


나 같은 경우는 k8s를 사용하고 런타임에 PHASE를 사용할 것이라 ENTRYPOINT에 추가했다.


ENV PHASE production
...
ENTRYPOINT /usr/src/app/docker-entrypoint.sh "$PHASE"


실제 docker-entrypoint.sh 를 다음과 같이 구성했다.


#!/bin/sh

ln -sf /etc/nginx/$1.nginx-vhost.conf /etc/nginx/nginx-vhost.conf

service nginx start

phantomjs --ssl-protocol=any rasterize.js



빌드는 다음과 같이 해서 테스트할 수 있다.


docker build -t voucher-renderer .

docker run -p 80:80 -e PHASE="sandbox" -it voucher-renderer


Posted by 김용환 '김용환'

댓글을 달아 주세요



 kubernetes 에서 tls 정보를  namespace별로 저장한다.




#!/usr/bin/env bash

root="$(cd "$( dirname "${BASH_SOURCE[0]}")/.." && pwd )"
source $root/.env
cd $root

kubectl config use-context google-production-context

declare -a phases=("sandbox" "beta" "production")
for phase in "${phases[@]}"
do
echo "$phase"
## google.com secret 생성하기
kubectl create secret tls google-com --key $root/cert/google.com.key --cert $root/cert/google.com.crt -n $phase

## kakao.com secret 확인하기
kubectl describe secret google-com -n $phase
done

## 인증서 확인하기
kubectl get cm -n ingress-nginx ingress-nginx -o yaml


인증서를 tls 정보로 변경할 때 유의할 점은 namespace 별로만 인증서를 인식한다.


즉 production namespace에서 default에 저장된 tls 인증서를 찾지 못한다. 

Posted by 김용환 '김용환'

댓글을 달아 주세요



(쿠버네티스를 처음 공부하고 테스트하는 사람에게 도움이 된다)


간단하게 kubernetes 앱을 실행할 때는 apply를 사용하는 것이 가장 쉽다. 


kubectl apply -f kubernetes.yml



반대로 자원/실행 종료는 다음과 같다.


kubectl delete -f kubernetes.yml


기억이 나지 않을 때는 아래와 같이 delete를 직접 해도 된다.


kubectl delete deployment {deployment_name} 



kubectl delete 를 진행할 때 주의해야 하는 부분이 있다. 





만약 namespace를 정하면 부분이 yaml에 있는데 kubectl delete를 실행하면 namespace의 모든 deployment도 삭제되니. 주의해야 한다.


Posted by 김용환 '김용환'

댓글을 달아 주세요



ingress nginx 에 인증서 추가하는 방법이다. 

1. context 변경하기
kubectl config use-context google-production-context

2. kakao.com secret 생성하기
kubectl create secret tls google-com --key google.com.key --cert google.com.crt

3. kakao.com secret 확인하기
kubectl describe secret google-com

4. 인증서 확인하기
kubectl get cm -n ingress-nginx ingress-nginx -o yaml



kubernetes 설정 파일에 추가하기

spec:
tls:
- hosts:
- server_name aa.google.com
secretName: google-io


Posted by 김용환 '김용환'

댓글을 달아 주세요


kubernetes에서는 네임 스페이스를 줘서 상태 정보를 확인한다. 



$ kubectl get pods  -n capture

NAME                             READY   STATUS    RESTARTS   AGE

phantom-server-f597bbbb6-24pww   1/1     Running   0          1d

phantom-server-f597bbbb6-2vljz   1/1     Running   0          1d

phantom-server-f597bbbb6-z7fk5   1/1     Running   0          1d




특정 노드에 대한 로그를 확인할 때도 네임 스페이스를 지정해야 한다.


$ kubectl logs -f phantom-server-f597bbbb6-24pww -n capture

(로그)




따라서 3개의 pods를 모두 보려면 pod 별로 호출해야 한다.



하지만, 

https://github.com/wercker/stern를 사용하면 예쁘게 많은 pods 로그를 쉽게 볼 수 있다. 

맥이라면 brew install stern으로 설치한다.



$ stern phantom-server-f597bbbb6-z7fk5 --namespace capture

(예쁘게 로그)




3개의 포드에 대한 로그를 보려면 다음 커맨드를 실행한다.


$ stern phantom-server --namespace capture





또한 동일한 방식으로 ingress 로그도 출력할 수 있다.



$ kubectl logs ingress-nginx-controller-lh75d  -n ingress-nginx

->


$ stern ingress-nginx-controller  -n ingress-nginx




Posted by 김용환 '김용환'

댓글을 달아 주세요


default namespace 앱을 새로운 namespace로 옮길 때 이슈가 발생할 수 있다.


k8s는 기본적으로 기존 정보를 모른다. 

default namespace에 올린 service,ingress,pods는 그대로 둔채..

새로운 namespace에 service, ingress,pods는 뜬다.


이때 ingress는 같은 포트를 사용하기 때문에 에러가 당연히 발생한다.

디폴트의 ingress는 종료시키고, 새로운 namespace의 ingress는 떠있게 한다.

그리고 default service, pods도 일일이 종료 시킨다. 


다음과 같이 나오면 정상이다. 



$ kubectl get ingress

x


$ kubectl get ingress -n <새로운 namespace>

새로운 ingress


Posted by 김용환 '김용환'

댓글을 달아 주세요